generated from Jaysyn/ModuleTemplate
2025/08/23 Update
Added PEPS AI. Updated for PRC8 updates.
This commit is contained in:
@@ -9,6 +9,6 @@ Repository for the development of the PRC8 version of Lord of Terror, by Tolitz
|
||||
|
||||
2.) [Lord of Terror](https://neverwintervault.org/project/nwn1/module/lord-terror-diablo-campaign)
|
||||
|
||||
3.) [PRC8](https://gitea.raptio.us/Jaysyn/PRC8/src/branch/main/Release)
|
||||
3.) [PRC8](https://gitea.raptio.us/Jaysyn/PRC8/releases)
|
||||
|
||||
4.) [CEP3](https://neverwintervault.org/project/nwnee/hakpak/combined/cep-3-community-expansion-pack)
|
||||
1980
src/_removed/nw_i0_generic.nss
Normal file
1980
src/_removed/nw_i0_generic.nss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/_removed/nw_s0_heal.ncs
Normal file
BIN
src/_removed/nw_s0_heal.ncs
Normal file
Binary file not shown.
74
src/_removed/nw_s0_heal.nss
Normal file
74
src/_removed/nw_s0_heal.nss
Normal file
@@ -0,0 +1,74 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Heal
|
||||
//:: [NW_S0_Heal.nss]
|
||||
//:: Copyright (c) 2000 Bioware Corp.
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Heals the target to full unless they are undead.
|
||||
//:: If undead they reduced to 1d4 HP.
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Created By: Preston Watamaniuk
|
||||
//:: Created On: Jan 12, 2001
|
||||
//:: Modified 69MEH69 JUL2003
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Update Pass By: Preston W, On: Aug 1, 2001
|
||||
#include "69_i0_henchman"
|
||||
#include "NW_I0_SPELLS"
|
||||
void main()
|
||||
{
|
||||
//Declare major variables
|
||||
object oTarget = GetSpellTargetObject();
|
||||
effect eKill, eHeal;
|
||||
int nDamage, nHeal, nModify, nMetaMagic, nTouch;
|
||||
effect eSun = EffectVisualEffect(VFX_IMP_SUNSTRIKE);
|
||||
effect eHealVis = EffectVisualEffect(VFX_IMP_HEALING_X);
|
||||
string sTag = GetTag(oTarget);
|
||||
object oArea = GetArea(oTarget);
|
||||
//Check to see if the target is an undead
|
||||
if (GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
|
||||
{
|
||||
if(!GetIsReactionTypeFriendly(oTarget))
|
||||
{
|
||||
//Fire cast spell at event for the specified target
|
||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_HEAL));
|
||||
//Make a touch attack
|
||||
if (TouchAttackMelee(oTarget))
|
||||
{
|
||||
//Make SR check
|
||||
if (!MyResistSpell(OBJECT_SELF, oTarget))
|
||||
{
|
||||
//Roll damage
|
||||
nModify = d4();
|
||||
nMetaMagic = GetMetaMagicFeat();
|
||||
//Make metamagic check
|
||||
if (nMetaMagic == METAMAGIC_MAXIMIZE)
|
||||
{
|
||||
nModify = 1;
|
||||
}
|
||||
//Figure out the amount of damage to inflict
|
||||
nDamage = GetCurrentHitPoints(oTarget) - nModify;
|
||||
//Set damage
|
||||
eKill = EffectDamage(nDamage, DAMAGE_TYPE_POSITIVE);
|
||||
//Apply damage effect and VFX impact
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eKill, oTarget);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eSun, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Fire cast spell at event for the specified target
|
||||
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, SPELL_HEAL, FALSE));
|
||||
//Figure out how much to heal
|
||||
nHeal = GetMaxHitPoints(oTarget);
|
||||
//Set the heal effect
|
||||
eHeal = EffectHeal(nHeal);
|
||||
//Apply the heal effect and the VFX impact
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHealVis, oTarget);
|
||||
ApplyEffectToObject(DURATION_TYPE_INSTANT, eHeal, oTarget);
|
||||
if(GetIsHenchmanDying(oTarget))
|
||||
{
|
||||
SetLocalInt(oArea, "nCHP" +sTag, 21);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,77 +47,78 @@ const string MES_CONTINGENCIES_YES2 = "The contingencies must expire to allo
|
||||
*/
|
||||
|
||||
//Primogenitors SpellID constants
|
||||
const int SPELL_EPIC_A_STONE = 0;//4007;
|
||||
const int SPELL_EPIC_ACHHEEL = 1;//4000;
|
||||
const int SPELL_EPIC_AL_MART = 2;//4002;
|
||||
const int SPELL_EPIC_ALLHOPE = 3;//4001;
|
||||
const int SPELL_EPIC_ANARCHY = 4;//4003;
|
||||
const int SPELL_EPIC_ANBLAST = 5;//4004;
|
||||
const int SPELL_EPIC_ANBLIZZ = 6;//4005;
|
||||
const int SPELL_EPIC_ARMY_UN = 7;//4006;
|
||||
const int SPELL_EPIC_BATTLEB = 999;//4008;
|
||||
const int SPELL_EPIC_CELCOUN = 8;//4009;
|
||||
const int SPELL_EPIC_CHAMP_V = 9;//4010;
|
||||
const int SPELL_EPIC_CON_RES =10;//4011;
|
||||
const int SPELL_EPIC_CON_REU =11;//4012;
|
||||
const int SPELL_EPIC_DEADEYE =12;//4013;
|
||||
const int SPELL_EPIC_DIREWIN =13;//4015;
|
||||
const int SPELL_EPIC_DREAMSC =14;//4017;
|
||||
const int SPELL_EPIC_DRG_KNI =15;//4016;
|
||||
const int SPELL_EPIC_DTHMARK =1000;//4014;
|
||||
const int SPELL_EPIC_DULBLAD =16;//4018;
|
||||
const int SPELL_EPIC_DWEO_TH =17;//4019;
|
||||
const int SPELL_EPIC_ENSLAVE =18;//4020;
|
||||
const int SPELL_EPIC_EP_M_AR =19;//4021;
|
||||
const int SPELL_EPIC_EP_RPLS =20;//4022;
|
||||
const int SPELL_EPIC_EP_SP_R =21;//4023;
|
||||
const int SPELL_EPIC_EP_WARD =22;//4024;
|
||||
const int SPELL_EPIC_ET_FREE =23;//4025;
|
||||
const int SPELL_EPIC_FIEND_W =24;//4026;
|
||||
const int SPELL_EPIC_FLEETNS =25;//4027;
|
||||
const int SPELL_EPIC_GEMCAGE =26;//4028;
|
||||
const int SPELL_EPIC_GODSMIT =27;//4029;
|
||||
const int SPELL_EPIC_GR_RUIN =28;//4030;
|
||||
const int SPELL_EPIC_GR_SP_RE=29;//4031;
|
||||
const int SPELL_EPIC_GR_TIME =30;//4032;
|
||||
const int SPELL_EPIC_HELBALL =31;//4034;
|
||||
const int SPELL_EPIC_HELSEND =1001;//4033;
|
||||
const int SPELL_EPIC_HERCALL =32;//4035;
|
||||
const int SPELL_EPIC_HERCEMP =33;//4036;
|
||||
const int SPELL_EPIC_IMPENET =34;//4037;
|
||||
const int SPELL_EPIC_LEECH_F =35;//4038;
|
||||
const int SPELL_EPIC_LEG_ART =1002;//4039;
|
||||
const int SPELL_EPIC_LIFE_FT =1003;//4040;
|
||||
const int SPELL_EPIC_MAGMA_B =36;//4041;
|
||||
const int SPELL_EPIC_MASSPEN =37;//4042;
|
||||
const int SPELL_EPIC_MORI = 38;//4043;
|
||||
const int SPELL_EPIC_MUMDUST =39;//4044;
|
||||
const int SPELL_EPIC_NAILSKY =40;//4045;
|
||||
const int SPELL_EPIC_NIGHTSU =1004;//4046;
|
||||
const int SPELL_EPIC_ORDER_R =41;//4047;
|
||||
const int SPELL_EPIC_PATHS_B =42;//4048;
|
||||
const int SPELL_EPIC_PEERPEN =43;//4049;
|
||||
const int SPELL_EPIC_PESTIL = 44;//4050;
|
||||
const int SPELL_EPIC_PIOUS_P =45;//4051;
|
||||
const int SPELL_EPIC_PLANCEL =46;//4052;
|
||||
const int SPELL_EPIC_PSION_S =47;//4053;
|
||||
const int SPELL_EPIC_RAINFIR =48;//4054;
|
||||
const int SPELL_EPIC_RISEN_R =1005;//4055;
|
||||
const int SPELL_EPIC_RUINN = 49;//4056; //NON_STANDARD
|
||||
const int SPELL_EPIC_SINGSUN =50;//4057;
|
||||
const int SPELL_EPIC_SP_WORM =51;//4058;
|
||||
const int SPELL_EPIC_STORM_M =52;//4059;
|
||||
const int SPELL_EPIC_SUMABER =53;//4060;
|
||||
const int SPELL_EPIC_SUP_DIS =54;//4061;
|
||||
const int SPELL_EPIC_SYMRUST =1006;//4062;
|
||||
const int SPELL_EPIC_THEWITH =55;//4063;
|
||||
const int SPELL_EPIC_TOLO_KW =56;//4064;
|
||||
const int SPELL_EPIC_TRANVIT =57;//4065;
|
||||
const int SPELL_EPIC_TWINF = 58;//4066;
|
||||
const int SPELL_EPIC_UNHOLYD =59;//4067;
|
||||
const int SPELL_EPIC_UNIMPIN =60;//4068;
|
||||
const int SPELL_EPIC_UNSEENW =61;//4069;
|
||||
const int SPELL_EPIC_WHIP_SH =62;//4070;
|
||||
const int SPELL_EPIC_A_STONE = 0;//4007;
|
||||
const int SPELL_EPIC_ACHHEEL = 1;//4000;
|
||||
const int SPELL_EPIC_AL_MART = 2;//4002;
|
||||
const int SPELL_EPIC_ALLHOPE = 3;//4001;
|
||||
const int SPELL_EPIC_ANARCHY = 4;//4003;
|
||||
const int SPELL_EPIC_ANBLAST = 5;//4004;
|
||||
const int SPELL_EPIC_ANBLIZZ = 6;//4005;
|
||||
const int SPELL_EPIC_ARMY_UN = 7;//4006;
|
||||
const int SPELL_EPIC_BATTLEB = 999;//4008;
|
||||
const int SPELL_EPIC_CELCOUN = 8;//4009;
|
||||
const int SPELL_EPIC_CHAMP_V = 9;//4010;
|
||||
const int SPELL_EPIC_CON_RES = 10;//4011;
|
||||
const int SPELL_EPIC_CON_REU = 11;//4012;
|
||||
const int SPELL_EPIC_DEADEYE = 12;//4013;
|
||||
const int SPELL_EPIC_DIREWIN = 13;//4015;
|
||||
const int SPELL_EPIC_DREAMSC = 14;//4017;
|
||||
const int SPELL_EPIC_DRG_KNI = 15;//4016;
|
||||
const int SPELL_EPIC_DTHMARK = 1000;//4014;
|
||||
const int SPELL_EPIC_DULBLAD = 16;//4018;
|
||||
const int SPELL_EPIC_DWEO_TH = 17;//4019;
|
||||
const int SPELL_EPIC_ENSLAVE = 18;//4020;
|
||||
const int SPELL_EPIC_EP_M_AR = 19;//4021;
|
||||
const int SPELL_EPIC_EP_RPLS = 20;//4022;
|
||||
const int SPELL_EPIC_EP_SP_R = 21;//4023;
|
||||
const int SPELL_EPIC_EP_WARD = 22;//4024;
|
||||
const int SPELL_EPIC_ET_FREE = 23;//4025;
|
||||
const int SPELL_EPIC_FIEND_W = 24;//4026;
|
||||
const int SPELL_EPIC_FLEETNS = 25;//4027;
|
||||
const int SPELL_EPIC_GEMCAGE = 26;//4028;
|
||||
const int SPELL_EPIC_GODSMIT = 27;//4029;
|
||||
const int SPELL_EPIC_GR_RUIN = 28;//4030;
|
||||
const int SPELL_EPIC_GR_SP_RE = 29;//4031;
|
||||
const int SPELL_EPIC_GR_TIME = 30;//4032;
|
||||
const int SPELL_EPIC_HELBALL = 31;//4034;
|
||||
const int SPELL_EPIC_HELSEND = 1001;//4033;
|
||||
const int SPELL_EPIC_HERCALL = 32;//4035;
|
||||
const int SPELL_EPIC_HERCEMP = 33;//4036;
|
||||
const int SPELL_EPIC_IMPENET = 34;//4037;
|
||||
const int SPELL_EPIC_LEECH_F = 35;//4038;
|
||||
const int SPELL_EPIC_LEG_ART = 1002;//4039;
|
||||
const int SPELL_EPIC_LIFE_FT = 1003;//4040;
|
||||
const int SPELL_EPIC_MAGMA_B = 36;//4041;
|
||||
const int SPELL_EPIC_MASSPEN = 37;//4042;
|
||||
const int SPELL_EPIC_MORI = 38;//4043;
|
||||
const int SPELL_EPIC_MUMDUST = 39;//4044;
|
||||
const int SPELL_EPIC_NAILSKY = 40;//4045;
|
||||
const int SPELL_EPIC_NIGHTSU = 1004;//4046;
|
||||
const int SPELL_EPIC_ORDER_R = 41;//4047;
|
||||
const int SPELL_EPIC_PATHS_B = 42;//4048;
|
||||
const int SPELL_EPIC_PEERPEN = 43;//4049;
|
||||
const int SPELL_EPIC_PESTIL = 44;//4050;
|
||||
const int SPELL_EPIC_PIOUS_P = 45;//4051;
|
||||
const int SPELL_EPIC_PLANCEL = 46;//4052;
|
||||
const int SPELL_EPIC_PSION_S = 47;//4053;
|
||||
const int SPELL_EPIC_RAINFIR = 48;//4054;
|
||||
//const int SPELL_EPIC_RISEN_R =1005;//4055;
|
||||
const int SPELL_EPIC_RISEN_R = 49;//4055;
|
||||
const int SPELL_EPIC_RUINN = 50;//4056; //NON_STANDARD
|
||||
const int SPELL_EPIC_SINGSUN = 51;//4057;
|
||||
const int SPELL_EPIC_SP_WORM = 52;//4058;
|
||||
const int SPELL_EPIC_STORM_M = 53;//4059;
|
||||
const int SPELL_EPIC_SUMABER = 54;//4060;
|
||||
const int SPELL_EPIC_SUP_DIS = 55;//4061;
|
||||
const int SPELL_EPIC_SYMRUST = 1006;//4062;
|
||||
const int SPELL_EPIC_THEWITH = 56;//4063;
|
||||
const int SPELL_EPIC_TOLO_KW = 57;//4064;
|
||||
const int SPELL_EPIC_TRANVIT = 58;//4065;
|
||||
const int SPELL_EPIC_TWINF = 59;//4066;
|
||||
const int SPELL_EPIC_UNHOLYD = 60;//4067;
|
||||
const int SPELL_EPIC_UNIMPIN = 61;//4068;
|
||||
const int SPELL_EPIC_UNSEENW = 62;//4069;
|
||||
const int SPELL_EPIC_WHIP_SH = 63;//4070;
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -246,7 +246,7 @@ int GetSpellFromAbrev(string sAbrev)
|
||||
sAbrev = GetStringLowerCase(sAbrev);
|
||||
if(GetStringLeft(sAbrev, 8) == "epic_sp_")
|
||||
sAbrev = GetStringRight(sAbrev, GetStringLength(sAbrev)-8);
|
||||
if(DEBUG) DoDebug("sAbrew to check vs: " + sAbrev);
|
||||
if(DEBUG) DoDebug("sAbrev to check vs: " + sAbrev);
|
||||
int i = 0;
|
||||
string sLabel = GetStringLowerCase(Get2DACache("epicspells", "LABEL", i));
|
||||
while(sLabel != "")
|
||||
|
||||
481
src/include/inc_infusion.nss
Normal file
481
src/include/inc_infusion.nss
Normal file
@@ -0,0 +1,481 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//::///////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Script: inc_infusion
|
||||
Author: Jaysyn
|
||||
Created: 2025-08-11 17:01:26
|
||||
|
||||
Description:
|
||||
Contains most functions related to the Create
|
||||
Infusion feat.
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_spells"
|
||||
|
||||
int GetMaxDivineSpellLevel(object oCaster, int nClass);
|
||||
int GetCastSpellCasterLevelFromItem(object oItem, int nSpellID);
|
||||
int GetIsClassSpell(object oCaster, int nSpellID, int nClass);
|
||||
int GetHasSpellOnClassList(object oCaster, int nSpellID);
|
||||
void InfusionSecondSave(object oUser, int nDC);
|
||||
|
||||
/**
|
||||
* @brief Finds the class index for which the given spell is available to the specified caster.
|
||||
*
|
||||
* This function iterates through all possible classes and returns the first class
|
||||
* index for which the specified spell is on the caster's spell list.
|
||||
*
|
||||
* @param oCaster The creature object to check.
|
||||
* @param nSpellID The spell ID to find the class for.
|
||||
*
|
||||
* @return The class index that has the spell on its class spell list for the caster,
|
||||
* or -1 if no matching class is found.
|
||||
*/
|
||||
int FindSpellCastingClass(object oCaster, int nSpellID)
|
||||
{
|
||||
int i = 0;
|
||||
int nClassFound = -1;
|
||||
int nClass;
|
||||
|
||||
// Only loop through caster's classes
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
nClass = GetClassByPosition(i, oCaster);
|
||||
if (nClass == CLASS_TYPE_INVALID) continue;
|
||||
|
||||
if (GetIsClassSpell(oCaster, nSpellID, nClass))
|
||||
{
|
||||
nClassFound = nClass;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return nClassFound;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Performs validation checks to determine if the caster can use a spell infusion from the specified item.
|
||||
*
|
||||
* This function verifies that the item is a valid infused herb, checks the caster's relevant class and ability scores,
|
||||
* confirms the caster is a divine spellcaster with the necessary caster level, and ensures the spell is on the caster's class spell list.
|
||||
*
|
||||
* @param oCaster The creature attempting to use the infusion.
|
||||
* @param oItem The infused herb item containing the spell.
|
||||
* @param nSpellID The spell ID of the infusion spell being cast.
|
||||
*
|
||||
* @return TRUE if all infusion use checks pass and the caster can use the infusion; FALSE otherwise.
|
||||
*/
|
||||
int DoInfusionUseChecks(object oCaster, object oItem, int nSpellID)
|
||||
{
|
||||
int bPnPHerbs = GetPRCSwitch(PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
|
||||
if(GetBaseItemType(oItem) != BASE_ITEM_INFUSED_HERB)
|
||||
{
|
||||
FloatingTextStringOnCreature("Not casting from an Infused Herb", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int nItemSpellLvl = GetCastSpellCasterLevelFromItem(oItem, nSpellID);
|
||||
if (bPnPHerbs && nItemSpellLvl == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("Item has no spellcaster level.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// **CRITICAL: Find the correct class that actually has the spell on its list**
|
||||
int nClassCaster = FindSpellCastingClass(oCaster, nSpellID);
|
||||
|
||||
if(DEBUG) DoDebug("nClassCaster is: " + IntToString(nClassCaster) + ".");
|
||||
|
||||
// Check for valid class
|
||||
if (nClassCaster == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("No valid class found for this spell.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if(GetMaxDivineSpellLevel(oCaster, nClassCaster) < 1 )
|
||||
{
|
||||
FloatingTextStringOnCreature("You must be a divine spellcaster to activate an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have spell on class list - (This will also double-check via the class)
|
||||
if (!GetHasSpellOnClassList(oCaster, nSpellID))
|
||||
{
|
||||
FloatingTextStringOnCreature("You must have a spell on one of your class spell lists to cast it from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must meet ability requirement: Ability score >= 10 + spell level
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClassCaster);
|
||||
int nClassAbility = GetAbilityScoreForClass(nClassCaster, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassCaster is "+IntToString(nClassCaster)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: Class nSpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassAbility is "+IntToString(nClassAbility)+".");
|
||||
|
||||
if (nClassAbility < 10 + nSpellLevel)
|
||||
{
|
||||
FloatingTextStringOnCreature("You must meet ability score requirement to cast spell from infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have a divine caster level at least equal to infusion's caster level
|
||||
int nDivineLvl = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nDivineLvl is "+IntToString(nDivineLvl)+".");
|
||||
|
||||
if (nDivineLvl < nItemSpellLvl)
|
||||
{
|
||||
FloatingTextStringOnCreature("Your divine caster level is too low to cast this spell from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* int DoInfusionUseChecks(object oCaster, object oItem, int nSpellID)
|
||||
{
|
||||
int bPnPHerbs = GetPRCSwitch(PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
|
||||
if(GetBaseItemType(oItem) != BASE_ITEM_INFUSED_HERB)
|
||||
{
|
||||
FloatingTextStringOnCreature("Not casting from an Infused Herb", oCaster);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
int nItemSpellLvl = GetCastSpellCasterLevelFromItem(oItem, nSpellID);
|
||||
if (bPnPHerbs && nItemSpellLvl == -1)
|
||||
{
|
||||
FloatingTextStringOnCreature("Item has no spellcaster level.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Find relevant class for the spell
|
||||
int nClassCaster = FindSpellCastingClass(oCaster, nSpellID);
|
||||
|
||||
if(DEBUG) DoDebug("nClassCaster is: "+IntToString(nClassCaster)+".");
|
||||
|
||||
if(GetMaxDivineSpellLevel(oCaster, nClassCaster) < 1 )
|
||||
{
|
||||
FloatingTextStringOnCreature("You must be a divine spellcaster to activate an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have spell on class list
|
||||
if (!GetHasSpellOnClassList(oCaster, nSpellID))
|
||||
{
|
||||
FloatingTextStringOnCreature("You must have a spell on one of your class spell lists to cast it from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must meet ability requirement: Ability score >= 10 + spell level
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClassCaster);
|
||||
int nClassAbility = GetAbilityScoreForClass(nClassCaster, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassCaster is "+IntToString(nClassCaster)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: Class nSpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nClassAbility is "+IntToString(nClassAbility)+".");
|
||||
|
||||
if (nClassAbility < 10 + nSpellLevel)
|
||||
{
|
||||
FloatingTextStringOnCreature("You must meet ability score requirement to cast spell from infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Must have a divine caster level at least equal to infusion's caster level
|
||||
int nDivineLvl = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster);
|
||||
|
||||
if(DEBUG) DoDebug("inc_infusion >> DoInfusionUseChecks: nDivineLvl is "+IntToString(nDivineLvl)+".");
|
||||
|
||||
if (nDivineLvl < nItemSpellLvl)
|
||||
{
|
||||
FloatingTextStringOnCreature("Your divine caster level is too low to cast this spell from an infusion.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
*/
|
||||
/**
|
||||
* @brief Retrieves the maximum divine spell level known by the caster for a given class.
|
||||
*
|
||||
* This function checks the caster's local integers named "PRC_DivSpell1" through "PRC_DivSpell9"
|
||||
* in descending order to determine the highest divine spell level available.
|
||||
* It returns the highest spell level for which the corresponding local int is false (zero).
|
||||
*
|
||||
* @param oCaster The creature whose divine spell levels are being checked.
|
||||
* @param nClass The class index for which to check the divine spell level (currently unused).
|
||||
*
|
||||
* @return The highest divine spell level known by the caster (1 to 9).
|
||||
*/
|
||||
int GetMaxDivineSpellLevel(object oCaster, int nClass)
|
||||
{
|
||||
int i = 9;
|
||||
for (i; i > 0; i--)
|
||||
{
|
||||
if(!GetLocalInt(oCaster, "PRC_DivSpell"+IntToString(i)))
|
||||
return i;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the spell school of an herb based on its resref by looking it up in the craft_infusion.2da file.
|
||||
*
|
||||
* This function searches the "craft_infusion" 2DA for a row matching the herb's resref.
|
||||
* If found, it returns the corresponding spell school as an integer constant.
|
||||
* If not found or the SpellSchool column is missing/invalid, it returns -1.
|
||||
*
|
||||
* @param oHerb The herb object to check.
|
||||
*
|
||||
* @return The spell school constant corresponding to the herb's infusion spell school,
|
||||
* or -1 if the herb is invalid, not found, or the data is missing.
|
||||
*/
|
||||
int GetHerbsSpellSchool(object oHerb)
|
||||
{
|
||||
if (!GetIsObjectValid(oHerb)) return -1;
|
||||
|
||||
string sResref = GetResRef(oHerb);
|
||||
int nRow = 0;
|
||||
string sRowResref;
|
||||
|
||||
while (nRow < 200)
|
||||
{
|
||||
sRowResref = Get2DACache("craft_infusion", "Resref", nRow);
|
||||
if (sRowResref == "") break;
|
||||
if (sRowResref == sResref)
|
||||
{
|
||||
string sHerbSpellSchool = Get2DAString("craft_infusion", "SpellSchool", nRow);
|
||||
|
||||
if (sHerbSpellSchool == "A") return SPELL_SCHOOL_ABJURATION;
|
||||
else if (sHerbSpellSchool == "C") return SPELL_SCHOOL_CONJURATION;
|
||||
else if (sHerbSpellSchool == "D") return SPELL_SCHOOL_DIVINATION;
|
||||
else if (sHerbSpellSchool == "E") return SPELL_SCHOOL_ENCHANTMENT;
|
||||
else if (sHerbSpellSchool == "V") return SPELL_SCHOOL_EVOCATION;
|
||||
else if (sHerbSpellSchool == "I") return SPELL_SCHOOL_ILLUSION;
|
||||
else if (sHerbSpellSchool == "N") return SPELL_SCHOOL_NECROMANCY;
|
||||
else if (sHerbSpellSchool == "T") return SPELL_SCHOOL_TRANSMUTATION;
|
||||
else return SPELL_SCHOOL_GENERAL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
nRow++;
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the infusion spell level of an herb by matching its resref in the craft_infusion.2da file.
|
||||
*
|
||||
* This function searches the "craft_infusion" 2DA for a row matching the herb's resref.
|
||||
* If found, it returns the spell level from the SpellLevel column as an integer.
|
||||
* If not found or the column is missing, it returns -1.
|
||||
*
|
||||
* @param oHerb The herb object whose infusion spell level is to be retrieved.
|
||||
*
|
||||
* @return The spell level as an integer if found, or -1 if the herb is invalid, not found, or the column is missing.
|
||||
*/
|
||||
int GetHerbsInfusionSpellLevel(object oHerb)
|
||||
{
|
||||
if (!GetIsObjectValid(oHerb)) return -1;
|
||||
|
||||
string sResref = GetResRef(oHerb);
|
||||
int nRow = 0;
|
||||
string sRowResref;
|
||||
|
||||
// Brute-force loop <20> adjust limit if your 2DA has more than 500 rows
|
||||
while (nRow < 200)
|
||||
{
|
||||
sRowResref = Get2DACache("craft_infusion", "Resref", nRow);
|
||||
if (sRowResref == "") break; // End of valid rows
|
||||
if (sRowResref == sResref)
|
||||
{
|
||||
string sSpellLevelStr = Get2DAString("craft_infusion", "SpellLevel", nRow);
|
||||
return StringToInt(sSpellLevelStr);
|
||||
}
|
||||
nRow++;
|
||||
}
|
||||
return -1; // Not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the caster level of a specific cast-spell item property from an item.
|
||||
*
|
||||
* This function iterates through the item properties of the given item, searching for an
|
||||
* ITEM_PROPERTY_CAST_SPELL_CASTER_LEVEL property that matches the specified spell ID.
|
||||
* If found, it returns the caster level value stored in the item property.
|
||||
*
|
||||
* @param oItem The item object to check.
|
||||
* @param nSpellID The spell ID to match against the item property.
|
||||
*
|
||||
* @return The caster level associated with the matching cast-spell item property,
|
||||
* or -1 if no matching property is found.
|
||||
*/
|
||||
int GetCastSpellCasterLevelFromItem(object oItem, int nSpellID)
|
||||
{
|
||||
int nFoundCL = -1;
|
||||
|
||||
itemproperty ip = GetFirstItemProperty(oItem);
|
||||
while (GetIsItemPropertyValid(ip))
|
||||
{
|
||||
int nType = GetItemPropertyType(ip);
|
||||
|
||||
// First preference: PRC's CASTER_LEVEL itemprop
|
||||
if (nType == ITEM_PROPERTY_CAST_SPELL_CASTER_LEVEL)
|
||||
{
|
||||
int nSubType = GetItemPropertySubType(ip);
|
||||
string sSpellIDStr = Get2DAString("iprp_spells", "SpellIndex", nSubType);
|
||||
int nSubSpellID = StringToInt(sSpellIDStr);
|
||||
|
||||
if (nSubSpellID == nSpellID)
|
||||
{
|
||||
return GetItemPropertyCostTableValue(ip); // Found exact CL
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: vanilla CAST_SPELL property
|
||||
if (nType == ITEM_PROPERTY_CAST_SPELL && nFoundCL == -1)
|
||||
{
|
||||
int nSubType = GetItemPropertySubType(ip);
|
||||
string sSpellIDStr = Get2DAString("iprp_spells", "SpellIndex", nSubType);
|
||||
int nSubSpellID = StringToInt(sSpellIDStr);
|
||||
|
||||
if (nSubSpellID == nSpellID)
|
||||
{
|
||||
// Vanilla uses CostTableValue for *number of uses*, not CL,
|
||||
// so we<77>ll assume default caster level = spell level * 2 - 1
|
||||
int nSpellLevel = StringToInt(Get2DAString("spells", "Innate", nSubSpellID));
|
||||
nFoundCL = nSpellLevel * 2 - 1; // default NWN caster level rule
|
||||
}
|
||||
}
|
||||
|
||||
ip = GetNextItemProperty(oItem);
|
||||
}
|
||||
|
||||
return nFoundCL; // -1 if not found
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Checks if a given spell ID is present on the specified class's spell list for the caster.
|
||||
*
|
||||
* This function determines the spell level of the spell for the given class using PRCGetSpellLevelForClass.
|
||||
* If the spell level is -1, the spell is not on the class's spell list.
|
||||
* Otherwise, the spell is considered to be on the class spell list.
|
||||
*
|
||||
* @param oCaster The creature object casting or querying the spell.
|
||||
* @param nSpellID The spell ID to check.
|
||||
* @param nClass The class index to check the spell list against.
|
||||
*
|
||||
* @return TRUE if the spell is on the class's spell list; FALSE otherwise.
|
||||
*/
|
||||
int GetIsClassSpell(object oCaster, int nSpellID, int nClass)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: nSpellID is: "+IntToString(nSpellID)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: nClass is: "+IntToString(nClass)+".");
|
||||
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nClass);
|
||||
if (nSpellLevel == -1)
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: SpellLevel is "+IntToString(nSpellLevel)+".");
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetIsClassSpell: Spell "+IntToString(nSpellID)+" is not in spelllist of "+IntToString(nClass)+".");
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks if the caster has the specified spell on any of their class spell lists.
|
||||
*
|
||||
* This function iterates through all classes the caster has (up to position 8),
|
||||
* and returns TRUE if the spell is found on any class's spell list.
|
||||
*
|
||||
* @param oCaster The creature object to check.
|
||||
* @param nSpellID The spell ID to search for.
|
||||
*
|
||||
* @return TRUE if the spell is present on at least one of the caster's class spell lists;
|
||||
* FALSE otherwise.
|
||||
*/
|
||||
int GetHasSpellOnClassList(object oCaster, int nSpellID)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i <= 8; i++)
|
||||
{
|
||||
int nClass = GetClassByPosition(i, oCaster);
|
||||
if (nClass == CLASS_TYPE_INVALID) continue;
|
||||
|
||||
if (GetIsClassSpell(oCaster, nSpellID, nClass))
|
||||
{
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetHasSpellOnClassList: Class spell found.");
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
if(DEBUG) DoDebug("inc_infusion >> GetHasSpellOnClassList: Class spell not found.");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Applies a poison nausea effect to the user when infusion use fails.
|
||||
*
|
||||
* This function performs an immediate Fortitude saving throw against poison DC based on infusion caster level.
|
||||
* If the user fails and is not immune to poison, an infusion nausea effect is applied, replacing any existing one.
|
||||
* A second saving throw is scheduled after 1 minute to attempt to remove the effect.
|
||||
*
|
||||
* @param oUser The creature who used the infusion and may be poisoned.
|
||||
* @param nInfusionCL The caster level of the infusion used, affecting the DC of the saving throw.
|
||||
*/
|
||||
void ApplyInfusionPoison(object oUser, int nInfusionCL)
|
||||
{
|
||||
int nDC = 10 + (nInfusionCL / 2);
|
||||
int bImmune = GetIsImmune(oUser, IMMUNITY_TYPE_POISON);
|
||||
|
||||
// First save immediately
|
||||
if (!bImmune && !PRCMySavingThrow(SAVING_THROW_FORT, oUser, nDC, SAVING_THROW_TYPE_POISON))
|
||||
{
|
||||
// Remove existing infusion poison nausea effect before applying new
|
||||
effect eOld = GetFirstEffect(oUser);
|
||||
while (GetIsEffectValid(eOld))
|
||||
{
|
||||
if (GetEffectTag(eOld) == "INFUSION_POISON_TAG")
|
||||
{
|
||||
RemoveEffect(oUser, eOld);
|
||||
break; // Assuming only one effect with this tag
|
||||
}
|
||||
eOld = GetNextEffect(oUser);
|
||||
}
|
||||
|
||||
effect eNausea = EffectNausea(oUser, 60.0f);
|
||||
|
||||
TagEffect(eNausea, "INFUSION_POISON_TAG");
|
||||
FloatingTextStringOnCreature("The infusion has made you nauseous.", oUser);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, eNausea, oUser, RoundsToSeconds(10));
|
||||
}
|
||||
|
||||
// Second save 1 minute later
|
||||
if (!bImmune)
|
||||
{
|
||||
DelayCommand(60.0, InfusionSecondSave(oUser, nDC));
|
||||
}
|
||||
}
|
||||
|
||||
void InfusionSecondSave(object oUser, int nDC)
|
||||
{
|
||||
if (!PRCMySavingThrow(SAVING_THROW_FORT, oUser, nDC, SAVING_THROW_TYPE_POISON))
|
||||
{
|
||||
FloatingTextStringOnCreature("The infusion has made you nauseous.", oUser);
|
||||
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectNausea(oUser, 60.0f), oUser, RoundsToSeconds(10));
|
||||
}
|
||||
}
|
||||
|
||||
//:: void main (){}
|
||||
@@ -242,25 +242,27 @@ void SetupLookupStage(object oMod, int n)
|
||||
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_DREAD_NECROMANCER, "cls_spell_dnecro"); break;
|
||||
case 18: SetLkupStage(n, oMod, CLASS_TYPE_DUSKBLADE, "cls_spell_duskbl"); break;
|
||||
case 19: SetLkupStage(n, oMod, CLASS_TYPE_FAVOURED_SOUL, "cls_spell_favsol"); break;
|
||||
case 20: SetLkupStage(n, oMod, CLASS_TYPE_HARPER, "cls_spell_harper"); break;
|
||||
case 21: SetLkupStage(n, oMod, CLASS_TYPE_HEXBLADE, "cls_spell_hexbl"); break;
|
||||
case 22: SetLkupStage(n, oMod, CLASS_TYPE_JUSTICEWW, "cls_spell_justww"); break;
|
||||
case 23: SetLkupStage(n, oMod, CLASS_TYPE_SORCERER, "cls_spell_sorc"); break;
|
||||
case 24: SetLkupStage(n, oMod, CLASS_TYPE_SUBLIME_CHORD, "cls_spell_schord"); break;
|
||||
case 25: SetLkupStage(n, oMod, CLASS_TYPE_SUEL_ARCHANAMACH, "cls_spell_suel"); break;
|
||||
case 26: SetLkupStage(n, oMod, CLASS_TYPE_VIGILANT, "cls_spell_vigil"); break;
|
||||
case 27: SetLkupStage(n, oMod, CLASS_TYPE_WARMAGE, "cls_spell_wrmage"); break;
|
||||
case 28: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_WEAVE, "cls_spell_kngtwv"); break;
|
||||
case 29: SetLkupStage(n, oMod, CLASS_TYPE_PSYCHIC_ROGUE, "cls_psipw_psyrog"); break;
|
||||
case 30: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWCASTER, "cls_myst_shdcst"); break;
|
||||
case 31: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWSMITH, "cls_myst_shdsmt"); break;
|
||||
case 32: SetLkupStage(n, oMod, CLASS_TYPE_CELEBRANT_SHARESS, "cls_spell_sharss"); break;
|
||||
case 14: SetLkupStage(n, oMod, CLASS_TYPE_BARD, "cls_spell_bard"); break;
|
||||
case 15: SetLkupStage(n, oMod, CLASS_TYPE_BEGUILER, "cls_spell_beguil"); break;
|
||||
case 16: SetLkupStage(n, oMod, CLASS_TYPE_DREAD_NECROMANCER, "cls_spell_dnecro"); break;
|
||||
case 17: SetLkupStage(n, oMod, CLASS_TYPE_DUSKBLADE, "cls_spell_duskbl"); break;
|
||||
case 18: SetLkupStage(n, oMod, CLASS_TYPE_FAVOURED_SOUL, "cls_spell_favsol"); break;
|
||||
case 19: SetLkupStage(n, oMod, CLASS_TYPE_HARPER, "cls_spell_harper"); break;
|
||||
case 20: SetLkupStage(n, oMod, CLASS_TYPE_HEXBLADE, "cls_spell_hexbl"); break;
|
||||
case 21: SetLkupStage(n, oMod, CLASS_TYPE_JUSTICEWW, "cls_spell_justww"); break;
|
||||
case 22: SetLkupStage(n, oMod, CLASS_TYPE_SORCERER, "cls_spell_sorc"); break;
|
||||
case 23: SetLkupStage(n, oMod, CLASS_TYPE_SUBLIME_CHORD, "cls_spell_schord"); break;
|
||||
case 24: SetLkupStage(n, oMod, CLASS_TYPE_SUEL_ARCHANAMACH, "cls_spell_suel"); break;
|
||||
case 25: SetLkupStage(n, oMod, CLASS_TYPE_VIGILANT, "cls_spell_vigil"); break;
|
||||
case 26: SetLkupStage(n, oMod, CLASS_TYPE_WARMAGE, "cls_spell_wrmage"); break;
|
||||
case 27: SetLkupStage(n, oMod, CLASS_TYPE_KNIGHT_WEAVE, "cls_spell_kngtwv"); break;
|
||||
case 28: SetLkupStage(n, oMod, CLASS_TYPE_PSYCHIC_ROGUE, "cls_psipw_psyrog"); break;
|
||||
case 29: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWCASTER, "cls_myst_shdcst"); break;
|
||||
case 30: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWSMITH, "cls_myst_shdsmt"); break;
|
||||
case 31: SetLkupStage(n, oMod, CLASS_TYPE_CELEBRANT_SHARESS, "cls_spell_sharss"); break;
|
||||
|
||||
//:: These were all moved to the Bioware spellbooks -Jaysyn
|
||||
//case 14: SetLkupStage(n, oMod, CLASS_TYPE_ASSASSIN, "cls_spell_asasin"); break;
|
||||
//case 46: SetLkupStage(n, oMod, CLASS_TYPE_CULTIST_SHATTERED_PEAK, "cls_spell_cultst"); break;
|
||||
//case 40: SetLkupStage(n, oMod, CLASS_TYPE_NENTYAR_HUNTER, "cls_spell_hunter"); break;
|
||||
//case 28: SetLkupStage(n, oMod, CLASS_TYPE_SHADOWLORD, "cls_spell_tfshad"); break;
|
||||
@@ -528,7 +530,7 @@ int SpellToSpellbookID(int nSpell)
|
||||
int nOutSpellID = GetLocalInt(oWP, /*"PRC_GetRowFromSpellID_" + */IntToString(nSpell));
|
||||
if(nOutSpellID == 0)
|
||||
nOutSpellID = -1;
|
||||
//if(DEBUG) DoDebug("SpellToSpellbookID(" + IntToString(nSpell) + ", " + sFile + ") = " + IntToString(nOutSpellID));
|
||||
if(DEBUG) DoDebug("inc_lookup >> SpellToSpellbookID: (nSpell: " + IntToString(nSpell) + ") = nOutSpellID: " + IntToString(nOutSpellID));
|
||||
return nOutSpellID;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ Make cls_spcr_*.2da
|
||||
Make blank cls_spell_*.2da
|
||||
Add cls_spgn_*.2da to classes.2da
|
||||
Add class entry in prc_classes.2da
|
||||
Add the spellbook feat (#1999) to cls_feat_*.2da at the appropriate level
|
||||
Add the spellbook feat (#1999) to cls_feat_*.2da at the appropriate level (not needed for NWN:EE)
|
||||
Add class to PRCGetSpellSaveDC() in prc_add_spell_dc
|
||||
Add class to GetSpellbookTypeForClass() below
|
||||
Add class to GetAbilityScoreForClass() below
|
||||
@@ -119,6 +119,7 @@ int GetSpellbookTypeForClass(int nClass)
|
||||
switch(nClass)
|
||||
{
|
||||
case CLASS_TYPE_ARCHIVIST:
|
||||
case CLASS_TYPE_ASSASSIN:
|
||||
case CLASS_TYPE_BLACKGUARD:
|
||||
case CLASS_TYPE_BLIGHTER:
|
||||
case CLASS_TYPE_CLERIC:
|
||||
@@ -141,7 +142,6 @@ int GetSpellbookTypeForClass(int nClass)
|
||||
case CLASS_TYPE_VIGILANT:
|
||||
case CLASS_TYPE_WIZARD:
|
||||
return SPELLBOOK_TYPE_PREPARED;
|
||||
case CLASS_TYPE_ASSASSIN:
|
||||
case CLASS_TYPE_BARD:
|
||||
case CLASS_TYPE_BEGUILER:
|
||||
case CLASS_TYPE_CELEBRANT_SHARESS:
|
||||
@@ -559,7 +559,7 @@ int bKnowsAllClassSpells(int nClass)
|
||||
{
|
||||
//case CLASS_TYPE_WIZARD:
|
||||
case CLASS_TYPE_ARCHIVIST:
|
||||
case CLASS_TYPE_ASSASSIN:
|
||||
//case CLASS_TYPE_ASSASSIN:
|
||||
case CLASS_TYPE_BARD:
|
||||
case CLASS_TYPE_CELEBRANT_SHARESS:
|
||||
case CLASS_TYPE_CULTIST_SHATTERED_PEAK:
|
||||
@@ -580,7 +580,79 @@ int bKnowsAllClassSpells(int nClass)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC)
|
||||
{
|
||||
// If the character doesn't have any spell slots available on for this level, it can't know any spells of that level either
|
||||
if(!GetSlotCount(nLevel, nSpellLevel, GetAbilityScoreForClass(nClass, oPC), nClass))
|
||||
{
|
||||
if(DEBUG) DoDebug("GetSpellKnownMaxCount: No slots available for " + IntToString(nClass) + " level " + IntToString(nLevel) + " circle " + IntToString(nSpellLevel));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nKnown;
|
||||
string sFile = Get2DACache("classes", "SpellKnownTable", nClass);
|
||||
string sKnown = Get2DACache(sFile, "SpellLevel" + IntToString(nSpellLevel), nLevel - 1);
|
||||
|
||||
if(DEBUG)
|
||||
{
|
||||
DoDebug("GetSpellKnownMaxCount Details:");
|
||||
DoDebug("- Class: " + IntToString(nClass));
|
||||
DoDebug("- Passed Level: " + IntToString(nLevel));
|
||||
DoDebug("- Base Class Level: " + IntToString(GetLevelByClass(nClass, oPC)));
|
||||
DoDebug("- Effective Level: " + IntToString(GetSpellslotLevel(nClass, oPC)));
|
||||
DoDebug("- Spell Level: " + IntToString(nSpellLevel));
|
||||
DoDebug("- SpellKnownTable: " + sFile);
|
||||
DoDebug("- MaxKnown from 2DA: " + sKnown);
|
||||
}
|
||||
|
||||
if(sKnown == "")
|
||||
{
|
||||
nKnown = -1;
|
||||
if(DEBUG) DoDebug("GetSpellKnownMaxCount: Problem getting known numbers");
|
||||
}
|
||||
else
|
||||
nKnown = StringToInt(sKnown);
|
||||
|
||||
if(nKnown == -1)
|
||||
return 0;
|
||||
|
||||
// COMPLETELY REWROTE THIS SECTION
|
||||
// Bard and Sorcerer logic for prestige class advancement
|
||||
if(nClass == CLASS_TYPE_SORCERER || nClass == CLASS_TYPE_BARD)
|
||||
{
|
||||
int baseClassLevel = GetLevelByClass(nClass, oPC);
|
||||
int effectiveLevel = GetSpellslotLevel(nClass, oPC);
|
||||
|
||||
// Debug the values we're checking
|
||||
if(DEBUG)
|
||||
{
|
||||
DoDebug("Spont caster check - Base level: " + IntToString(baseClassLevel) +
|
||||
", Effective level: " + IntToString(effectiveLevel));
|
||||
}
|
||||
|
||||
// If they have prestige class advancement OR special feats, they should get spells
|
||||
if(effectiveLevel > baseClassLevel ||
|
||||
GetHasFeat(FEAT_DRACONIC_GRACE, oPC) ||
|
||||
GetHasFeat(FEAT_DRACONIC_BREATH, oPC))
|
||||
{
|
||||
// Allow them to get spells - do nothing here, return nKnown at the end
|
||||
if(DEBUG) DoDebug("Spontaneous caster eligible for new spells");
|
||||
}
|
||||
else
|
||||
{
|
||||
// No advancement, no special feats - no new spells
|
||||
if(DEBUG) DoDebug("Spontaneous caster NOT eligible for new spells");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("Final spell known count: " + IntToString(nKnown));
|
||||
return nKnown;
|
||||
}
|
||||
|
||||
|
||||
/* int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC)
|
||||
{
|
||||
// If the character doesn't have any spell slots available on for this level, it can't know any spells of that level either
|
||||
// @todo Check rules. There might be cases where this doesn't hold
|
||||
@@ -588,22 +660,9 @@ int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC)
|
||||
return 0;
|
||||
int nKnown;
|
||||
string sFile;
|
||||
// Bioware casters use their classes.2da-specified tables
|
||||
/*if( nClass == CLASS_TYPE_WIZARD
|
||||
|| nClass == CLASS_TYPE_SORCERER
|
||||
|| nClass == CLASS_TYPE_BARD
|
||||
|| nClass == CLASS_TYPE_CLERIC
|
||||
|| nClass == CLASS_TYPE_DRUID
|
||||
|| nClass == CLASS_TYPE_PALADIN
|
||||
|| nClass == CLASS_TYPE_RANGER)
|
||||
{*/
|
||||
sFile = Get2DACache("classes", "SpellKnownTable", nClass);
|
||||
/*}
|
||||
else
|
||||
{
|
||||
sFile = Get2DACache("classes", "FeatsTable", nClass);
|
||||
sFile = "cls_spkn" + GetStringRight(sFile, GetStringLength(sFile) - 8); // Hardcoded the cls_ part. It's not as if any class uses some other prefix - Ornedan, 20061231
|
||||
}*/
|
||||
|
||||
sFile = Get2DACache("classes", "SpellKnownTable", nClass);
|
||||
|
||||
|
||||
string sKnown = Get2DACache(sFile, "SpellLevel" + IntToString(nSpellLevel), nLevel - 1);
|
||||
if(DEBUG) DoDebug("GetSpellKnownMaxCount(" + IntToString(nLevel) + ", " + IntToString(nSpellLevel) + ", " + IntToString(nClass) + ", " + GetName(oPC) + ") = " + sKnown);
|
||||
@@ -626,6 +685,7 @@ int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC)
|
||||
}
|
||||
return nKnown;
|
||||
}
|
||||
*/
|
||||
|
||||
int GetSpellKnownCurrentCount(object oPC, int nSpellLevel, int nClass)
|
||||
{
|
||||
@@ -693,6 +753,44 @@ int GetSpellKnownCurrentCount(object oPC, int nSpellLevel, int nClass)
|
||||
}
|
||||
|
||||
int GetSpellUnknownCurrentCount(object oPC, int nSpellLevel, int nClass)
|
||||
{
|
||||
// Get the lookup token created by MakeSpellbookLevelLoop()
|
||||
string sTag = "SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nSpellLevel);
|
||||
object oCache = GetObjectByTag(sTag);
|
||||
if(!GetIsObjectValid(oCache))
|
||||
{
|
||||
if(DEBUG) DoDebug("GetSpellUnknownCurrentCount: " + sTag + " is not valid");
|
||||
|
||||
// Add code to create the missing lookup object
|
||||
if(DEBUG) DoDebug("Attempting to create missing spell lookup token");
|
||||
ExecuteScript("prc_create_spellb", oPC);
|
||||
|
||||
// Try again after creating it
|
||||
oCache = GetObjectByTag(sTag);
|
||||
if(!GetIsObjectValid(oCache))
|
||||
{
|
||||
if(DEBUG) DoDebug("Still couldn't create spell lookup token");
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DEBUG) DoDebug("Successfully created spell lookup token");
|
||||
}
|
||||
}
|
||||
|
||||
// Read the total number of spells on the given level and determine how many are already known
|
||||
int nTotal = array_get_size(oCache, "Lkup");
|
||||
int nKnown = GetSpellKnownCurrentCount(oPC, nSpellLevel, nClass);
|
||||
int nUnknown = nTotal - nKnown;
|
||||
|
||||
if(DEBUG) DoDebug("GetSpellUnknownCurrentCount(" + GetName(oPC) + ", " + IntToString(nSpellLevel) + ", " + IntToString(nClass) + ") = " + IntToString(nUnknown));
|
||||
if(DEBUG) DoDebug(" Total spells in lookup: " + IntToString(nTotal) + ", Known spells: " + IntToString(nKnown));
|
||||
|
||||
return nUnknown;
|
||||
}
|
||||
|
||||
|
||||
/* int GetSpellUnknownCurrentCount(object oPC, int nSpellLevel, int nClass)
|
||||
{
|
||||
// Get the lookup token created by MakeSpellbookLevelLoop()
|
||||
string sTag = "SpellLvl_" + IntToString(nClass) + "_Level_" + IntToString(nSpellLevel);
|
||||
@@ -709,7 +807,7 @@ int GetSpellUnknownCurrentCount(object oPC, int nSpellLevel, int nClass)
|
||||
|
||||
if(DEBUG) DoDebug("GetSpellUnknownCurrentCount(" + GetName(oPC) + ", " + IntToString(nSpellLevel) + ", " + IntToString(nClass) + ") = " + IntToString(nUnknown));
|
||||
return nUnknown;
|
||||
}
|
||||
} */
|
||||
|
||||
void AddSpellUse(object oPC, int nSpellbookID, int nClass, string sFile, string sArrayName, int nSpellbookType, object oSkin, int nFeatID, int nIPFeatID, string sIDX = "")
|
||||
{
|
||||
@@ -850,7 +948,7 @@ void SetupSpells(object oPC, int nClass)
|
||||
int nAbility = GetAbilityScoreForClass(nClass, oPC);
|
||||
int nSpellbookType = GetSpellbookTypeForClass(nClass);
|
||||
|
||||
if(DEBUG) DoDebug("SetupSpells\n"
|
||||
if(DEBUG) DoDebug("SetupSpells()\n"
|
||||
+ "nClass = " + IntToString(nClass) + "\n"
|
||||
+ "nSpellslotLevel = " + IntToString(nLevel) + "\n"
|
||||
+ "nAbility = " + IntToString(nAbility) + "\n"
|
||||
@@ -1178,7 +1276,7 @@ void CastSpontaneousSpell(int nClass, int bInstantSpell = FALSE)
|
||||
else if(GetLocalInt(OBJECT_SELF, "PRC_metamagic_state") == 1)
|
||||
SetLocalInt(OBJECT_SELF, "MetamagicFeatAdjust", 0);
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("CastSpontaneousSpell(): nSpellLevel is: "+IntToString(nSpellLevel)+".");
|
||||
CheckSpontSlots(nClass, nSpellID, nSpellLevel);
|
||||
if(GetLocalInt(OBJECT_SELF, "NSB_Cast"))
|
||||
ActionDoCommand(CheckSpontSlots(nClass, nSpellID, nSpellLevel, TRUE));
|
||||
@@ -1331,6 +1429,8 @@ void NewSpellbookSpell(int nClass, int nSpellbookType, int nMetamagic = METAMAGI
|
||||
string sFile = GetFileForClass(nClass);
|
||||
int nSpellLevel = StringToInt(Get2DACache(sFile, "Level", nSpellbookID));
|
||||
|
||||
if (DEBUG) DoDebug("inc_newspellbook >> NewSpellbookSpell(): nSpellbookType is: "+IntToString(nSpellbookType)+".");
|
||||
|
||||
// Make sure the caster has uses of this spell remaining
|
||||
// 2009-9-20: Add metamagic feat abilities. -N-S
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
||||
@@ -1371,13 +1471,14 @@ void NewSpellbookSpell(int nClass, int nSpellbookType, int nMetamagic = METAMAGI
|
||||
else if(nSpellLevel > 9)//now test the spell level
|
||||
{
|
||||
nMetamagic = METAMAGIC_NONE;
|
||||
ActionDoCommand(SendMessageToPC(oPC, "Modified spell level is to high! Casting spell without metamagic"));
|
||||
ActionDoCommand(SendMessageToPC(oPC, "Modified spell level is too high! Casting spell without metamagic"));
|
||||
nSpellLevel = nSpellSlotLevel;
|
||||
}
|
||||
else if(GetLocalInt(oPC, "PRC_metamagic_state") == 1)
|
||||
SetLocalInt(oPC, "MetamagicFeatAdjust", 0);
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("inc_newspellbook >> NewSpellbookSpell(): nSpellLevel is: "+IntToString(nSpellLevel)+".");
|
||||
CheckSpontSlots(nClass, nSpellID, nSpellLevel);
|
||||
if(GetLocalInt(oPC, "NSB_Cast"))
|
||||
ActionDoCommand(CheckSpontSlots(nClass, nSpellID, nSpellLevel, TRUE));
|
||||
@@ -1460,7 +1561,7 @@ void CheckPrepSlots(int nClass, int nSpellID, int nSpellbookID, int bIsAction =
|
||||
{
|
||||
DeleteLocalInt(OBJECT_SELF, "NSB_Cast");
|
||||
int nCount = persistant_array_get_int(OBJECT_SELF, "NewSpellbookMem_" + IntToString(nClass), nSpellbookID);
|
||||
if(DEBUG) DoDebug("NewSpellbookSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(nSpellbookID) + "] = " + IntToString(nCount));
|
||||
if(DEBUG) DoDebug("NewSpellbookSpell >> CheckPrepSlots: NewSpellbookMem_" + IntToString(nClass) + "[SpellbookID: " + IntToString(nSpellbookID) + "] = " + IntToString(nCount));
|
||||
if(nCount < 1)
|
||||
{
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", nSpellID)));
|
||||
@@ -1486,7 +1587,7 @@ void CheckSpontSlots(int nClass, int nSpellID, int nSpellSlotLevel, int bIsActio
|
||||
{
|
||||
DeleteLocalInt(OBJECT_SELF, "NSB_Cast");
|
||||
int nCount = persistant_array_get_int(OBJECT_SELF, "NewSpellbookMem_" + IntToString(nClass), nSpellSlotLevel);
|
||||
if(DEBUG) DoDebug("NewSpellbookSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(nSpellSlotLevel) + "] = " + IntToString(nCount));
|
||||
if(DEBUG) DoDebug("NewSpellbookSpell >> CheckSpontSlots: NewSpellbookMem_" + IntToString(nClass) + "[SpellSlotLevel: " + IntToString(nSpellSlotLevel) + "] = " + IntToString(nCount));
|
||||
if(nCount < 1)
|
||||
{
|
||||
// "You have no castings of spells of level " + IntToString(nSpellLevel) + " remaining"
|
||||
|
||||
@@ -720,7 +720,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_polymorph", 155);
|
||||
SetPRCSwitch("PRC_FILE_END_portraits", 1300);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_craft_alchem", 37);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_craft_gen_it", 204);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_craft_gen_it", 253);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_craft_poison", 62);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_domains", 59);
|
||||
SetPRCSwitch("PRC_FILE_END_prc_familiar", 10);
|
||||
@@ -767,7 +767,7 @@ void SetDefaultFileEnds()
|
||||
SetPRCSwitch("PRC_FILE_END_soundset", 453);
|
||||
SetPRCSwitch("PRC_FILE_END_soundsettype", 4);
|
||||
SetPRCSwitch("PRC_FILE_END_soundtypes", 1);
|
||||
SetPRCSwitch("PRC_FILE_END_spells", 19348);
|
||||
SetPRCSwitch("PRC_FILE_END_spells", 19400);
|
||||
//SetPRCSwitch("PRC_FILE_END_spellschools", 9);
|
||||
SetPRCSwitch("PRC_FILE_END_statescripts", 35);
|
||||
SetPRCSwitch("PRC_FILE_END_stringtokens", 92);
|
||||
@@ -876,6 +876,8 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_HARM);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_NEUTRALIZE_POISON);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIOWARE_REMOVE_DISEASE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BIO_UNLEARN);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_UNLEARN_SPELL_MAXNR);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_BIOWARE_DURATION);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_LOCAL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_TIMESTOP_NO_HOSTILE);
|
||||
@@ -1067,14 +1069,16 @@ void CreateSwitchNameArray()
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_ROD_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_STAFF_CASTER_LEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_BASE_ITEMS);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), X2_CI_BREWPOTION_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), X2_CI_BREWPOTION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), X2_CI_SCRIBESCROLL_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), X2_CI_CRAFTWAND_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), X2_CI_CRAFTWAND_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_BREWPOTION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_SCRIBESCROLL_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_MAXLEVEL);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CRAFTWAND_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_X2_CREATEINFUSION_COSTMODIFIER);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_ARBITRARY);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_COST_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFTING_TIME_SCALE);
|
||||
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_CASTER_LEVEL);
|
||||
|
||||
//spells
|
||||
|
||||
|
||||
@@ -1182,7 +1182,7 @@ int GetMaxEssentiaCapacityFeat(object oMeldshaper)
|
||||
// Don't allow more than they have
|
||||
if (nMax > GetTotalUsableEssentia(oMeldshaper)) nMax = GetTotalUsableEssentia(oMeldshaper);
|
||||
|
||||
//if (DEBUG) DoDebug("GetMaxEssentiaCapacityFeat: nHD "+IntToString(nHD)+" nMax "+IntToString(nMax));
|
||||
if(DEBUG) DoDebug("GetMaxEssentiaCapacityFeat: nHD "+IntToString(nHD)+" nMax "+IntToString(nMax));
|
||||
return nMax;
|
||||
}
|
||||
|
||||
|
||||
623
src/include/nw_inc_gff.nss
Normal file
623
src/include/nw_inc_gff.nss
Normal file
@@ -0,0 +1,623 @@
|
||||
// This is a helper library for advanced use: It allows constructing arbitrary gff data.
|
||||
// You can then spawn your object via JsonToObject().
|
||||
//
|
||||
// The data format is the same as https://github.com/niv/neverwinter.nim@1.4.3+.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// json j = GffCreateObject(OBJECT_TYPE_ITEM);
|
||||
// j = GffAddInt(j, "BaseItem", BASE_ITEM_BELT);
|
||||
// j = GffAddInt(j, "ModelPart1", 12);
|
||||
// j = GffAddLocString(j, "LocalizedName", "hi!");
|
||||
// object belt = JsonToObject(j, GetLocation(OBJECT_SELF));
|
||||
|
||||
|
||||
const string GFF_FIELD_TYPE_STRUCT = "struct";
|
||||
const string GFF_FIELD_TYPE_LIST = "list";
|
||||
const string GFF_FIELD_TYPE_BYTE = "byte";
|
||||
const string GFF_FIELD_TYPE_CHAR = "char";
|
||||
const string GFF_FIELD_TYPE_WORD = "word";
|
||||
const string GFF_FIELD_TYPE_SHORT = "short";
|
||||
const string GFF_FIELD_TYPE_DWORD = "dword";
|
||||
const string GFF_FIELD_TYPE_INT = "int";
|
||||
const string GFF_FIELD_TYPE_DWORD64 = "dword64";
|
||||
const string GFF_FIELD_TYPE_INT64 = "int64";
|
||||
const string GFF_FIELD_TYPE_FLOAT = "float";
|
||||
const string GFF_FIELD_TYPE_DOUBLE = "double";
|
||||
const string GFF_FIELD_TYPE_RESREF = "resref";
|
||||
const string GFF_FIELD_TYPE_STRING = "cexostring";
|
||||
const string GFF_FIELD_TYPE_LOC_STRING = "cexolocstring";
|
||||
|
||||
|
||||
// Create a empty object of the given type. You need to manually fill in all
|
||||
// GFF data with GffAddXXX. This will require understanding of the GFF file format
|
||||
// and what data fields each object type requires.
|
||||
json GffCreateObject(int nObjectType);
|
||||
// Create a combined area format(CAF) object. You need to manually create the ARE and GIT objects with their required data fields.
|
||||
json GffCreateArea(json jARE, json jGIT);
|
||||
|
||||
// Returns the OBJECT_TYPE_* of jGff.
|
||||
// Note: Will return 0 for invalid object types, including areas.
|
||||
int GffGetObjectType(json jGff);
|
||||
// Returns TRUE if jGff is a combined area format(CAF) object.
|
||||
int GffGetIsArea(json jGff);
|
||||
|
||||
// Returns TRUE if a field named sLabel of sType exists in jGff.
|
||||
// * sLabel: Can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// * sType: An optional GFF_FIELD_TYPE_*, leave empty to check if sLabel exists regardless of type.
|
||||
int GffGetFieldExists(json jGff, string sLabel, string sType = "");
|
||||
|
||||
|
||||
// Add a new field, will overwrite any existing fields with the same label even if the type is different.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to add the tag of an area to an empty combined area format(CAF) object you can do the following:
|
||||
// json jArea = GffCreateArea(JsonObject(), JsonObject());
|
||||
// jArea = GffAddString(jArea, "ARE/value/Tag", "AREA_TAG");
|
||||
|
||||
json GffAddStruct(json jGff, string sLabel, json jStruct, int nType = -1);
|
||||
json GffAddList(json jGff, string sLabel, json jList);
|
||||
json GffAddByte(json jGff, string sLabel, int v);
|
||||
json GffAddChar(json jGff, string sLabel, int v);
|
||||
json GffAddWord(json jGff, string sLabel, int v);
|
||||
json GffAddShort(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddDword(json jGff, string sLabel, int v);
|
||||
json GffAddInt(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddDword64(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffAddInt64(json jGff, string sLabel, int v);
|
||||
json GffAddFloat(json jGff, string sLabel, float v);
|
||||
// Note: Only data of type float will fit, because that's all that NWScript supports.
|
||||
json GffAddDouble(json jGff, string sLabel, float v);
|
||||
json GffAddResRef(json jGff, string sLabel, string v);
|
||||
json GffAddString(json jGff, string sLabel, string v);
|
||||
json GffAddLocString(json jGff, string sLabel, string v, int nStrRef = -1);
|
||||
|
||||
|
||||
// Replace a field, the type must match and the field must exist.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to replace the name of an area in a combined area format(CAF) object you can do the following:
|
||||
// json jArea = ObjectToStruct(GetFirstArea());
|
||||
// jArea = GffReplaceLocString(jArea, "ARE/value/Name", "New Area Name");
|
||||
|
||||
json GffReplaceStruct(json jGff, string sLabel, json jStruct);
|
||||
json GffReplaceList(json jGff, string sLabel, json jList);
|
||||
json GffReplaceByte(json jGff, string sLabel, int v);
|
||||
json GffReplaceChar(json jGff, string sLabel, int v);
|
||||
json GffReplaceWord(json jGff, string sLabel, int v);
|
||||
json GffReplaceShort(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDword(json jGff, string sLabel, int v);
|
||||
json GffReplaceInt(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDword64(json jGff, string sLabel, int v);
|
||||
// Note: Only data of type int32 will fit, because that's all that NWScript supports.
|
||||
json GffReplaceInt64(json jGff, string sLabel, int v);
|
||||
json GffReplaceFloat(json jGff, string sLabel, float v);
|
||||
// Note: Only data of type float will fit, because that's all that NWScript supports.
|
||||
json GffReplaceDouble(json jGff, string sLabel, float v);
|
||||
json GffReplaceResRef(json jGff, string sLabel, string v);
|
||||
json GffReplaceString(json jGff, string sLabel, string v);
|
||||
json GffReplaceLocString(json jGff, string sLabel, string v, int nStrRef = -1);
|
||||
|
||||
|
||||
// Remove a field, the type must match and the field must exist.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to remove all placeables from an area in a combined area format(CAF) object you can do the following:
|
||||
// json jArea = ObjectToStruct(GetFirstArea());
|
||||
// jArea = GffRemoveList(jArea, "GIT/value/Placeable List");
|
||||
|
||||
json GffRemoveStruct(json jGff, string sLabel);
|
||||
json GffRemoveList(json jGff, string sLabel);
|
||||
json GffRemoveByte(json jGff, string sLabel);
|
||||
json GffRemoveChar(json jGff, string sLabel);
|
||||
json GffRemoveWord(json jGff, string sLabel);
|
||||
json GffRemoveShort(json jGff, string sLabel);
|
||||
json GffRemoveDword(json jGff, string sLabel);
|
||||
json GffRemoveInt(json jGff, string sLabel);
|
||||
json GffRemoveDword64(json jGff, string sLabel);
|
||||
json GffRemoveInt64(json jGff, string sLabel);
|
||||
json GffRemoveFloat(json jGff, string sLabel);
|
||||
json GffRemoveDouble(json jGff, string sLabel);
|
||||
json GffRemoveResRef(json jGff, string sLabel);
|
||||
json GffRemoveString(json jGff, string sLabel);
|
||||
json GffRemoveLocString(json jGff, string sLabel);
|
||||
|
||||
|
||||
// Get a field's value as json object.
|
||||
// Returns a json null value on error with GetJsonError() filled in.
|
||||
//
|
||||
// Note: Json types do not implicitly convert between types, this means you cannot convert a JsonInt to a string with JsonGetString(), etc.
|
||||
// You may need to check the type with JsonGetType() and then do the appropriate cast yourself.
|
||||
// For GffGet*() functions the json type returned is noted in the function description.
|
||||
//
|
||||
// Example:
|
||||
// INCORRECT: string s = JsonGetString(GffGetInt());
|
||||
// CORRECT: string s = IntToString(JsonGetInt(GffGetInt()));
|
||||
//
|
||||
// sLabel can be a json pointer(path) without the starting /, see the documentation of JsonPointer() for details.
|
||||
// For example, to get the resref of an area in a combined area format(CAF) object you can do the following:
|
||||
// json jResRef = GffGetResRef(ObjectToStruct(GetFirstArea()), "ARE/value/ResRef");
|
||||
// if (jResRef != JsonNull())
|
||||
// {
|
||||
// string sResRef = JsonGetString(jResRef);
|
||||
// }
|
||||
// else
|
||||
// WriteTimestampedLogEntry("Failed to get area ResRef: " + JsonGetError(jResRef));
|
||||
|
||||
// Returns the struct as JsonObject() on success.
|
||||
json GffGetStruct(json jGff, string sLabel);
|
||||
// Returns a JsonArray() with all the list elements on success.
|
||||
json GffGetList(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetByte(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetChar(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetWord(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetShort(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetDword(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetInt(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetDword64(json jGff, string sLabel);
|
||||
// Returns a JsonInt() on success.
|
||||
json GffGetInt64(json jGff, string sLabel);
|
||||
// Returns a JsonFloat() on success.
|
||||
json GffGetFloat(json jGff, string sLabel);
|
||||
// Returns a JsonFloat() on success.
|
||||
json GffGetDouble(json jGff, string sLabel);
|
||||
// Returns a JsonString() on success.
|
||||
json GffGetResRef(json jGff, string sLabel);
|
||||
// Returns a JsonString() on success.
|
||||
json GffGetString(json jGff, string sLabel);
|
||||
// Returns a JsonObject() on success.
|
||||
// Key "0" will have a JsonString() with the string, if set.
|
||||
// Key "id" will have a JsonInt() with the strref, if set.
|
||||
json GffGetLocString(json jGff, string sLabel);
|
||||
|
||||
|
||||
// *** Internal Helper Functions
|
||||
json AddPatchOperation(json jPatchArray, string sOp, string sPath, json jValue)
|
||||
{
|
||||
json jOperation = JsonObject();
|
||||
jOperation = JsonObjectSet(jOperation, "op", JsonString(sOp));
|
||||
jOperation = JsonObjectSet(jOperation, "path", JsonString(sPath));
|
||||
jOperation = JsonObjectSet(jOperation, "value", jValue);
|
||||
return JsonArrayInsert(jPatchArray, jOperation);
|
||||
}
|
||||
|
||||
json GffAddField(json jGff, string sLabel, string sType, json jValue, int nType = -1)
|
||||
{
|
||||
json jField = JsonObject();
|
||||
jField = JsonObjectSet(jField, "type", JsonString(sType));
|
||||
jField = JsonObjectSet(jField, "value", jValue);
|
||||
if (sType == GFF_FIELD_TYPE_STRUCT && nType != -1)
|
||||
jField = JsonObjectSet(jField, "__struct_id", JsonInt(nType));
|
||||
|
||||
return JsonPatch(jGff, AddPatchOperation(JsonArray(), "add", "/" + sLabel, jField));
|
||||
}
|
||||
|
||||
json GffReplaceField(json jGff, string sLabel, string sType, json jValue)
|
||||
{
|
||||
json jPatch = JsonArray();
|
||||
jPatch = AddPatchOperation(jPatch, "test", "/" + sLabel + "/type", JsonString(sType));
|
||||
jPatch = AddPatchOperation(jPatch, "replace", "/" + sLabel + "/value", jValue);
|
||||
return JsonPatch(jGff, jPatch);
|
||||
}
|
||||
|
||||
json GffRemoveField(json jGff, string sLabel, string sType)
|
||||
{
|
||||
json jPatch = JsonArray();
|
||||
jPatch = AddPatchOperation(jPatch, "test", "/" + sLabel + "/type", JsonString(sType));
|
||||
jPatch = AddPatchOperation(jPatch, "remove", "/" + sLabel, JsonNull());
|
||||
return JsonPatch(jGff, jPatch);
|
||||
}
|
||||
|
||||
json GffGetFieldType(json jGff, string sLabel)
|
||||
{
|
||||
return JsonPointer(jGff, "/" + sLabel + "/type");
|
||||
}
|
||||
|
||||
json GffGetFieldValue(json jGff, string sLabel)
|
||||
{
|
||||
return JsonPointer(jGff, "/" + sLabel + "/value");
|
||||
}
|
||||
|
||||
json GffGetField(json jGff, string sLabel, string sType)
|
||||
{
|
||||
json jType = GffGetFieldType(jGff, sLabel);
|
||||
if (jType == JsonNull())
|
||||
return jType;
|
||||
else if (jType != JsonString(sType))
|
||||
return JsonNull("field type does not match");
|
||||
else
|
||||
return GffGetFieldValue(jGff, sLabel);
|
||||
}
|
||||
|
||||
json GffLocString(string v, int nStrRef = -1)
|
||||
{
|
||||
json jLocString = JsonObject();
|
||||
if (v != "")
|
||||
jLocString = JsonObjectSet(jLocString, "0", JsonString(v)); // english/any
|
||||
if (nStrRef != -1)
|
||||
jLocString = JsonObjectSet(jLocString, "id", JsonInt(nStrRef));
|
||||
|
||||
return jLocString;
|
||||
}
|
||||
//***
|
||||
|
||||
json GffCreateObject(int nObjectType)
|
||||
{
|
||||
string ot;
|
||||
if (nObjectType == OBJECT_TYPE_CREATURE) ot = "UTC ";
|
||||
else if (nObjectType == OBJECT_TYPE_ITEM) ot = "UTI ";
|
||||
else if (nObjectType == OBJECT_TYPE_TRIGGER) ot = "UTT ";
|
||||
else if (nObjectType == OBJECT_TYPE_DOOR) ot = "UTD ";
|
||||
else if (nObjectType == OBJECT_TYPE_WAYPOINT) ot = "UTW ";
|
||||
else if (nObjectType == OBJECT_TYPE_PLACEABLE) ot = "UTP ";
|
||||
else if (nObjectType == OBJECT_TYPE_STORE) ot = "UTM ";
|
||||
else if (nObjectType == OBJECT_TYPE_ENCOUNTER) ot = "UTE ";
|
||||
|
||||
if (ot == "") return JsonNull("invalid object type");
|
||||
|
||||
json ret = JsonObject();
|
||||
ret = JsonObjectSet(ret, "__data_type", JsonString(ot));
|
||||
return ret;
|
||||
}
|
||||
|
||||
json GffCreateArea(json jARE, json jGIT)
|
||||
{
|
||||
json jCAF = JsonObject();
|
||||
jCAF = JsonObjectSet(jCAF, "__data_type", JsonString("CAF "));
|
||||
jCAF = GffAddStruct(jCAF, "ARE", jARE, 0);
|
||||
jCAF = GffAddStruct(jCAF, "GIT", jGIT, 1);
|
||||
return jCAF;
|
||||
}
|
||||
|
||||
|
||||
int GffGetObjectType(json jGff)
|
||||
{
|
||||
json jDataType = JsonObjectGet(jGff, "__data_type");
|
||||
if (jDataType == JsonNull())
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
string sObjectType = JsonGetString(jDataType);
|
||||
|
||||
if (sObjectType == "UTC ") return OBJECT_TYPE_CREATURE;
|
||||
else if (sObjectType == "UTI ") return OBJECT_TYPE_ITEM;
|
||||
else if (sObjectType == "UTT ") return OBJECT_TYPE_TRIGGER;
|
||||
else if (sObjectType == "UTD ") return OBJECT_TYPE_DOOR;
|
||||
else if (sObjectType == "UTW ") return OBJECT_TYPE_WAYPOINT;
|
||||
else if (sObjectType == "UTP ") return OBJECT_TYPE_PLACEABLE;
|
||||
else if (sObjectType == "UTM ") return OBJECT_TYPE_STORE;
|
||||
else if (sObjectType == "UTE ") return OBJECT_TYPE_ENCOUNTER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GffGetIsArea(json jGff)
|
||||
{
|
||||
return JsonObjectGet(jGff, "__data_type") == JsonString("CAF ");
|
||||
}
|
||||
|
||||
int GffGetFieldExists(json jGff, string sLabel, string sType = "")
|
||||
{
|
||||
json jFieldType = GffGetFieldType(jGff, sLabel);
|
||||
return sType == "" ? jFieldType != JsonNull() : jFieldType == JsonString(sType);
|
||||
}
|
||||
|
||||
|
||||
json GffAddStruct(json jGff, string sLabel, json jStruct, int nType = -1)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT, jStruct, nType);
|
||||
}
|
||||
|
||||
json GffAddList(json jGff, string sLabel, json jList)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_LIST, jList);
|
||||
}
|
||||
|
||||
json GffAddByte(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_BYTE, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddChar(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_CHAR, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddWord(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_WORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddShort(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_SHORT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddDword(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DWORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddInt(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_INT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddDword64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddInt64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_INT64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffAddFloat(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffAddDouble(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffAddResRef(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_RESREF, JsonString(v));
|
||||
}
|
||||
|
||||
json GffAddString(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_STRING, JsonString(v));
|
||||
}
|
||||
|
||||
json GffAddLocString(json jGff, string sLabel, string v, int nStrRef = -1)
|
||||
{
|
||||
return GffAddField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING, GffLocString(v, nStrRef));
|
||||
}
|
||||
|
||||
|
||||
json GffReplaceStruct(json jGff, string sLabel, json jStruct)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT, jStruct);
|
||||
}
|
||||
|
||||
json GffReplaceList(json jGff, string sLabel, json jList)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_LIST, jList);
|
||||
}
|
||||
|
||||
json GffReplaceByte(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_BYTE, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceChar(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_CHAR, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceWord(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_WORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceShort(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_SHORT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceDword(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DWORD, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceInt(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_INT, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceDword64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceInt64(json jGff, string sLabel, int v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_INT64, JsonInt(v));
|
||||
}
|
||||
|
||||
json GffReplaceFloat(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffReplaceDouble(json jGff, string sLabel, float v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE, JsonFloat(v));
|
||||
}
|
||||
|
||||
json GffReplaceResRef(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_RESREF, JsonString(v));
|
||||
}
|
||||
|
||||
json GffReplaceString(json jGff, string sLabel, string v)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_STRING, JsonString(v));
|
||||
}
|
||||
|
||||
json GffReplaceLocString(json jGff, string sLabel, string v, int nStrRef = -1)
|
||||
{
|
||||
return GffReplaceField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING, GffLocString(v, nStrRef));
|
||||
}
|
||||
|
||||
|
||||
json GffRemoveStruct(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT);
|
||||
}
|
||||
|
||||
json GffRemoveList(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_LIST);
|
||||
}
|
||||
|
||||
json GffRemoveByte(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_BYTE);
|
||||
}
|
||||
|
||||
json GffRemoveChar(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_CHAR);
|
||||
}
|
||||
|
||||
json GffRemoveWord(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_WORD);
|
||||
}
|
||||
|
||||
json GffRemoveShort(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_SHORT);
|
||||
}
|
||||
|
||||
json GffRemoveDword(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DWORD);
|
||||
}
|
||||
|
||||
json GffRemoveInt(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_INT);
|
||||
}
|
||||
|
||||
json GffRemoveDword64(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64);
|
||||
}
|
||||
|
||||
json GffRemoveInt64(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_INT64);
|
||||
}
|
||||
|
||||
json GffRemoveFloat(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
json GffRemoveDouble(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
json GffRemoveResRef(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_RESREF);
|
||||
}
|
||||
|
||||
json GffRemoveString(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_STRING);
|
||||
}
|
||||
|
||||
json GffRemoveLocString(json jGff, string sLabel)
|
||||
{
|
||||
return GffRemoveField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING);
|
||||
}
|
||||
|
||||
|
||||
json GffGetStruct(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_STRUCT);
|
||||
}
|
||||
|
||||
json GffGetList(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_LIST);
|
||||
}
|
||||
|
||||
json GffGetByte(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_BYTE);
|
||||
}
|
||||
|
||||
json GffGetChar(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_CHAR);
|
||||
}
|
||||
|
||||
json GffGetWord(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_WORD);
|
||||
}
|
||||
|
||||
json GffGetShort(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_SHORT);
|
||||
}
|
||||
|
||||
json GffGetDword(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DWORD);
|
||||
}
|
||||
|
||||
json GffGetInt(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_INT);
|
||||
}
|
||||
|
||||
json GffGetDword64(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DWORD64);
|
||||
}
|
||||
|
||||
json GffGetInt64(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_INT64);
|
||||
}
|
||||
|
||||
json GffGetFloat(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
json GffGetDouble(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_DOUBLE);
|
||||
}
|
||||
|
||||
json GffGetResRef(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_RESREF);
|
||||
}
|
||||
|
||||
json GffGetString(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_STRING);
|
||||
}
|
||||
|
||||
json GffGetLocString(json jGff, string sLabel)
|
||||
{
|
||||
return GffGetField(jGff, sLabel, GFF_FIELD_TYPE_LOC_STRING);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -513,6 +513,8 @@ int PRCGetSpellSaveDC(int nSpellID = -1, int nSchool = -1, object oCaster = OBJE
|
||||
|
||||
if(nClass == CLASS_TYPE_BARD)
|
||||
nDC += StringToInt(Get2DACache("Spells", "Bard", nSpellID));
|
||||
else if(nClass == CLASS_TYPE_ASSASSIN)
|
||||
nDC += StringToInt(Get2DACache("Spells", "Assassin", nSpellID));
|
||||
else if(nClass == CLASS_TYPE_CLERIC || nClass == CLASS_TYPE_UR_PRIEST || nClass == CLASS_TYPE_OCULAR)
|
||||
nDC += StringToInt(Get2DACache("Spells", "Cleric", nSpellID));
|
||||
else if(nClass == CLASS_TYPE_DRUID)
|
||||
|
||||
@@ -143,7 +143,7 @@ const int CLASS_TYPE_MASTER_HARPER = 176;
|
||||
const int CLASS_TYPE_FRE_BERSERKER = 177;
|
||||
const int CLASS_TYPE_TEMPEST = 178;
|
||||
const int CLASS_TYPE_FOE_HUNTER = 179;
|
||||
//:: Free = 180
|
||||
const int CLASS_TYPE_VERDANT_LORD = 180;
|
||||
const int CLASS_TYPE_ORC_WARLORD = 181;
|
||||
const int CLASS_TYPE_THRALL_OF_GRAZZT_A = 182;
|
||||
const int CLASS_TYPE_NECROCARNATE = 183;
|
||||
@@ -162,7 +162,7 @@ const int CLASS_TYPE_MASTER_OF_NINE = 195;
|
||||
const int CLASS_TYPE_ETERNAL_BLADE = 196;
|
||||
const int CLASS_TYPE_SHADOW_SUN_NINJA = 197;
|
||||
const int CLASS_TYPE_WITCHBORN_BINDER = 198;
|
||||
const int CLASS_TYPE_BAELNORN = 199;
|
||||
const int CLASS_TYPE_LION_OF_TALISID = 199;
|
||||
const int CLASS_TYPE_DISCIPLE_OF_MEPH = 200;
|
||||
const int CLASS_TYPE_SOUL_EATER = 201;
|
||||
const int CLASS_TYPE_HENSHIN_MYSTIC = 202;
|
||||
@@ -236,6 +236,7 @@ const int CLASS_TYPE_WITCH = -1;
|
||||
const int CLASS_TYPE_TEMPLAR = -1;
|
||||
const int CLASS_TYPE_MYSTIC = -1;
|
||||
const int CLASS_TYPE_NOBLE = -1;
|
||||
const int CLASS_TYPE_BAELNORN = -2;
|
||||
|
||||
|
||||
//void main (){}
|
||||
@@ -75,6 +75,13 @@ void DeathlessFrenzyCheck(object oTarget);
|
||||
// * PRC Version of a Bioware function to disable include loops
|
||||
void PRCRemoveSpellEffects(int nSpell_ID, object oCaster, object oTarget);
|
||||
|
||||
/**
|
||||
* Target is immune to gaze attacks
|
||||
*
|
||||
* @return the Dazzle effect
|
||||
*/
|
||||
effect EffectGazeImmune();
|
||||
|
||||
/**
|
||||
* Dazzles the target: -1 Attack, Search, Spot, and VFX
|
||||
*
|
||||
@@ -583,7 +590,8 @@ effect PRCEffectHeal(int nHP, object oTarget)
|
||||
return EffectHeal(nHP);
|
||||
}
|
||||
|
||||
effect EffectAbilityBasedSkillIncrease(int iAbility, int iIncrease = 1){
|
||||
effect EffectAbilityBasedSkillIncrease(int iAbility, int iIncrease = 1)
|
||||
{
|
||||
effect eReturn;
|
||||
switch(iAbility)
|
||||
{
|
||||
@@ -639,7 +647,8 @@ effect EffectAbilityBasedSkillIncrease(int iAbility, int iIncrease = 1){
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
effect EffectAbilityBasedSkillDecrease(int iAbility, int iDecrease = 1){
|
||||
effect EffectAbilityBasedSkillDecrease(int iAbility, int iDecrease = 1)
|
||||
{
|
||||
effect eReturn;
|
||||
switch(iAbility)
|
||||
{
|
||||
@@ -695,7 +704,8 @@ effect EffectAbilityBasedSkillDecrease(int iAbility, int iDecrease = 1){
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
effect EffectDamageImmunityAll(){
|
||||
effect EffectDamageImmunityAll()
|
||||
{
|
||||
effect eReturn = EffectDamageImmunityIncrease(DAMAGE_TYPE_ACID, 100);
|
||||
eReturn = EffectLinkEffects(eReturn, EffectDamageImmunityIncrease(DAMAGE_TYPE_BLUDGEONING, 100));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectDamageImmunityIncrease(DAMAGE_TYPE_COLD, 100));
|
||||
@@ -712,7 +722,8 @@ effect EffectDamageImmunityAll(){
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
effect EffectImmunityMiscAll(){
|
||||
effect EffectImmunityMiscAll()
|
||||
{
|
||||
effect eReturn = EffectImmunity(IMMUNITY_TYPE_ABILITY_DECREASE);
|
||||
eReturn = EffectLinkEffects(eReturn, EffectImmunity(IMMUNITY_TYPE_BLINDNESS));
|
||||
eReturn = EffectLinkEffects(eReturn, EffectImmunity(IMMUNITY_TYPE_DEAFNESS));
|
||||
@@ -732,6 +743,31 @@ effect EffectImmunityMiscAll(){
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
//:: Immunity to all gaze attacks
|
||||
effect EffectGazeImmune()
|
||||
{
|
||||
effect eBlank;
|
||||
|
||||
effect eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CHARM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CONFUSION);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DAZE);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DEATH);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_CHAOS);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_EVIL);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_GOOD);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DESTROY_LAW);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DOMINATE);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_DOOM);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_FEAR);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_PARALYSIS);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_PETRIFY);
|
||||
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_STUNNED);
|
||||
|
||||
eReturn = TagEffect(eReturn, "PRCGazeImmune");
|
||||
|
||||
return eReturn;
|
||||
}
|
||||
|
||||
int GetIsShaken(object oTarget)
|
||||
{
|
||||
effect eEffect = GetFirstEffect(oTarget);
|
||||
@@ -748,3 +784,6 @@ int GetIsShaken(object oTarget)
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//:: Test void
|
||||
//:: void main() {}
|
||||
@@ -152,6 +152,9 @@ const int FEAT_EPIC_DIAMOND_DRAGON = 25115;
|
||||
const int FEAT_EPIC_CRUSADER = 25116;
|
||||
const int FEAT_EPIC_SWORDSAGE = 25117;
|
||||
const int FEAT_EPIC_WARBLADE = 25118;
|
||||
const int FEAT_EPIC_LION_OF_TALISID = 25600;
|
||||
const int FEAT_EPIC_VERDANT_LORD = 25618;
|
||||
|
||||
|
||||
//:: Vile Martial Strike Expansion
|
||||
const int FEAT_VILE_MARTIAL_EAGLE_CLAW = 24800;
|
||||
@@ -195,6 +198,28 @@ const int FEAT_CHARMING_THE_ARROW = 25998;
|
||||
//:: Skill Based Feats
|
||||
const int FEAT_JUMP = 2884;
|
||||
|
||||
//:: Lion of Talisid
|
||||
const int FEAT_LOT_LIONS_COURAGE = 25614;
|
||||
const int FEAT_LOT_LIONS_POUNCE = 25615;
|
||||
const int FEAT_LOT_LIONS_SWIFTNESS = 25616;
|
||||
const int FEAT_LOT_LEONALS_ROAR = 25617;
|
||||
|
||||
//::: Verdant Lord
|
||||
const int FEAT_VL_EXPERT_INFUSION = 25634;
|
||||
const int FEAT_VL_SUN_SUSTENANCE = 25635;
|
||||
const int FEAT_VL_SPONTANEITY = 25636;
|
||||
const int FEAT_VL_PLANT_FACILITY = 25637;
|
||||
const int FEAT_VL_WILD_SHAPE_TREANT = 25638;
|
||||
const int FEAT_VL_ANIMATE_TREE = 25639;
|
||||
const int FEAT_VL_GAEAS_EMBRACE = 25640;
|
||||
|
||||
//:: Masters of the Wild feats
|
||||
const int FEAT_CREATE_INFUSION = 25960;
|
||||
const int FEAT_MAGICAL_ARTISAN_CREATE_INFUSION = 25961;
|
||||
const int FEAT_PLANT_DEFIANCE = 25992;
|
||||
const int FEAT_PLANT_CONTROL = 25993;
|
||||
|
||||
|
||||
//:: Racial Feats
|
||||
const int FEAT_WEMIC_JUMP_8 = 4518;
|
||||
const int FEAT_URDINNIR_STONESKIN = 4644;
|
||||
@@ -782,6 +807,9 @@ const int FEAT_SUEL_IGNORE_SPELL_FAILURE = 2398;
|
||||
const int FEAT_SUEL_EXTENDED_SPELL = 2399;
|
||||
const int FEAT_SUEL_DISPELLING_STRIKE = 2400;
|
||||
|
||||
//:: Druid
|
||||
const int FEAT_SPONT_SUMMON = 2372;
|
||||
|
||||
//Passive Feats
|
||||
const int FEAT_ETERNAL_FREEDOM = 4298;
|
||||
const int FEAT_INTUITIVE_ATTACK = 3166;
|
||||
@@ -1538,18 +1566,19 @@ const int FEAT_SELVETARMS_BLESSING = 2447;
|
||||
const int FEAT_RANGER_DUAL = 374;
|
||||
const int FEAT_CAMOUFLAGE = 4486;
|
||||
|
||||
//Exalted Feat
|
||||
const int FEAT_SAC_VOW = 3388;
|
||||
const int FEAT_VOW_OBED = 3389;
|
||||
const int FEAT_EXALTED_TURNING = 3168;
|
||||
const int FEAT_HAND_HEALER = 3167;
|
||||
const int FEAT_NIMBUSLIGHT = 3165;
|
||||
const int FEAT_HOLYRADIANCE = 3164;
|
||||
const int FEAT_STIGMATA = 3163;
|
||||
const int FEAT_SERVHEAVEN = 3355;
|
||||
const int FEAT_RANGED_SMITE = 3356;
|
||||
const int FEAT_VOW_PURITY = 5360;
|
||||
const int FEAT_VOWOFPOVERTY = 26001;
|
||||
//:: Exalted Feats
|
||||
const int FEAT_SAC_VOW = 3388;
|
||||
const int FEAT_VOW_OBED = 3389;
|
||||
const int FEAT_EXALTED_TURNING = 3168;
|
||||
const int FEAT_HAND_HEALER = 3167;
|
||||
const int FEAT_NIMBUSLIGHT = 3165;
|
||||
const int FEAT_HOLYRADIANCE = 3164;
|
||||
const int FEAT_STIGMATA = 3163;
|
||||
const int FEAT_SERVHEAVEN = 3355;
|
||||
const int FEAT_RANGED_SMITE = 3356;
|
||||
const int FEAT_VOW_PURITY = 5360;
|
||||
const int FEAT_VOWOFPOVERTY = 26002;
|
||||
const int FEAT_FAV_COMPANIONS = 25994;
|
||||
|
||||
//Vile Feat
|
||||
const int FEAT_LICHLOVED = 3395;
|
||||
@@ -1868,12 +1897,12 @@ const int FEAT_SANCTIFY_MARTIAL_SICKLE = 3169;
|
||||
const int FEAT_SANCTIFY_MARTIAL_MINDBLADE = 3623;
|
||||
const int FEAT_SANCTIFY_MARTIAL_WHIP = 3596;
|
||||
const int FEAT_SANCTIFY_MARTIAL_TRIDENT = 3597;
|
||||
const int FEAT_SANCTIFYKISTRIKE = 26002;
|
||||
const int FEAT_HOLYKISTRIKE = 26003;
|
||||
const int FEAT_FISTOFHEAVENS = 26004;
|
||||
const int FEAT_VOWABSTINENCE = 26005;
|
||||
const int FEAT_VOWCHASTITY = 26006;
|
||||
const int FEAT_GIFTOFFAITH = 26007;
|
||||
const int FEAT_SANCTIFYKISTRIKE = 26003;
|
||||
const int FEAT_HOLYKISTRIKE = 26004;
|
||||
const int FEAT_FISTOFHEAVENS = 26005;
|
||||
const int FEAT_VOWABSTINENCE = 26006;
|
||||
const int FEAT_VOWCHASTITY = 26007;
|
||||
const int FEAT_GIFTOFFAITH = 26008;
|
||||
|
||||
//heartwarder
|
||||
const int FEAT_CHARISMA_INC1 = 3230;
|
||||
@@ -3189,6 +3218,8 @@ const int FEAT_ETHEREAL = 4167;
|
||||
const int FEAT_TEMPLATE_ARCHLICH_MARKER = 22700;
|
||||
const int FEAT_TEMPLATE_ARCHLICH_TURN_UNDEAD = 22701;
|
||||
|
||||
const int FEAT_TEMPLATE_BAELNORN_MARKER = 22708;
|
||||
|
||||
const int FEAT_TEMPLATE_CELESTIAL_SMITE_EVIL = 22601;
|
||||
const int FEAT_TEMPLATE_CELESTIAL_MARKER = 22602;
|
||||
const int FEAT_TEMPLATE_FIENDISH_SMITE_GOOD = 22603;
|
||||
@@ -3933,6 +3964,8 @@ const int FEAT_OPPORTUNISTIC_PIETY_HEAL = 5358;
|
||||
const int FEAT_OPPORTUNISTIC_PIETY_TURN = 5359;
|
||||
|
||||
// Combat Maneuver Feats
|
||||
const int FEAT_CM_CHARGE = 2823;
|
||||
const int FEAT_CM_GRAPPLE = 3414;
|
||||
const int FEAT_CURLING_WAVE_STRIKE = 2809;
|
||||
const int FEAT_SIDESTEP_CHARGE = 3505;
|
||||
const int FEAT_POWERFUL_CHARGE = 3506;
|
||||
@@ -6203,6 +6236,38 @@ const int FEAT_SHINING_BLADE_SPELLCASTING_VASSAL = 19587;
|
||||
const int FEAT_SWIFT_WING_SPELLCASTING_VASSAL = 19588;
|
||||
const int FEAT_WARPRIEST_SPELLCASTING_VASSAL = 19589;
|
||||
|
||||
//:: Lion of Talisid marker feats
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_ARCHIVIST = 25601;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_CLERIC = 25602;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_DRUID = 25603;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_FAVOURED_SOUL = 25604;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_HEALER = 25605;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_JOWAW = 25606;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_KOTMC = 25607;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_NENTYAR_HUNTER = 25608;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_RANGER = 25609;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_OASHAMAN = 25610;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_SOHEI = 25611;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_SOL = 25612;
|
||||
const int FEAT_LION_OF_TALISID_SPELLCASTING_SPSHAMAN = 25613;
|
||||
|
||||
//:: Verdant Lord marker feats
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_ARCHIVIST = 25619;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_CLERIC = 25620;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_DRUID = 25621;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_FAVOURED_SOUL = 25622;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_HEALER = 25623;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_JOWAW = 25624;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_KOTC = 25625;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_KOTMC = 25626;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_NENTYAR_HUNTER = 25627;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_PALADIN = 25628;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_RANGER = 25629;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_OASHAMAN = 25630;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_SOHEI = 25631;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_SOL = 25632;
|
||||
const int FEAT_VERDANT_LORD_SPELLCASTING_SPSHAMAN = 25633;
|
||||
|
||||
//:: No spellcasting or invoking marker feats
|
||||
const int FEAT_ASMODEUS_SPELLCASTING_NONE = 19590;
|
||||
const int FEAT_TIAMAT_SPELLCASTING_NONE = 19591;
|
||||
|
||||
@@ -575,8 +575,8 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
|
||||
iReturnLevel = GetLevelByClass(CLASS_TYPE_SHAPECHANGER);
|
||||
|
||||
}
|
||||
// Casting as a bard but don't have any levels in the class
|
||||
if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
// Casting as a bard but don't have any levels in the class //:: Double-dipping?
|
||||
/* if(iCastingClass == CLASS_TYPE_BARD && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
{
|
||||
int nRace = GetRacialType(oCaster);
|
||||
|
||||
@@ -584,7 +584,7 @@ int PRCGetCasterLevel(object oCaster = OBJECT_SELF)
|
||||
//otherwise use RHD instead of bard levels
|
||||
if(nRace == RACIAL_TYPE_GLOURA)
|
||||
iReturnLevel = GetLevelByClass(CLASS_TYPE_FEY);
|
||||
}
|
||||
} */
|
||||
|
||||
//Spell Rage ability
|
||||
if(GetHasSpellEffect(SPELL_SPELL_RAGE, oCaster)
|
||||
@@ -960,8 +960,10 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
}
|
||||
//:: End Bard Arcane PrC casting calculations
|
||||
|
||||
if(nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
if(nCastingClass == CLASS_TYPE_BARD || nCastingClass == CLASS_TYPE_BARD && nRace == RACIAL_TYPE_GLOURA && !GetLevelByClass(CLASS_TYPE_BARD, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey RHD caster (not bard)");
|
||||
|
||||
if(GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_FEY, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_ABJURANT_CHAMPION, oCaster);
|
||||
|
||||
@@ -1065,7 +1067,10 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_VIRTUOSO_SPELLCASTING_FEY, oCaster))
|
||||
{
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_VIRTUOSO, oCaster);
|
||||
if(DEBUG) DoDebug("prc_inc_castlvl >> Found Fey + Virtuoso PrC. Arcane caster level is "+IntToString(nArcane)+".");
|
||||
}
|
||||
|
||||
if(GetHasFeat(FEAT_WWOC_SPELLCASTING_FEY, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_WAR_WIZARD_OF_CORMYR, oCaster);
|
||||
@@ -1143,8 +1148,8 @@ int GetArcanePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_DIABOLIST_SPELLCASTING_ASSASSIN, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_DIABOLIST, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_DHEART_SPELLCASTING_ASSASSIN, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_DRAGONHEART_MAGE, oCaster);
|
||||
//if(GetHasFeat(FEAT_DHEART_SPELLCASTING_ASSASSIN, oCaster))
|
||||
//nArcane += GetLevelByClass(CLASS_TYPE_DRAGONHEART_MAGE, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_EKNIGHT_SPELLCASTING_ASSASSIN, oCaster))
|
||||
nArcane += GetLevelByClass(CLASS_TYPE_ELDRITCH_KNIGHT, oCaster);
|
||||
@@ -3817,6 +3822,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_ARCHIVIST, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster); */
|
||||
|
||||
@@ -4145,6 +4153,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_CLERIC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
@@ -4255,6 +4266,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_DRUID, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_DRUID, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
// if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_DRUID, oCaster))
|
||||
// nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
@@ -4367,8 +4381,11 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
// if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
// nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_MORNINGLORD_SPELLCASTING_FAVOURED_SOUL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MORNINGLORD, oCaster);
|
||||
@@ -4474,6 +4491,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_HEALER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster); */
|
||||
|
||||
@@ -4581,6 +4601,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_JUSTICEWW, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_JOWAW, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
// if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_JUSTICEWW, oCaster))
|
||||
// nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
@@ -4791,6 +4814,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_KOTMC, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster); */
|
||||
|
||||
@@ -4898,6 +4924,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_NENTYAR_HUNTER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster); */
|
||||
|
||||
@@ -5209,6 +5238,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_MORNINGLORD_SPELLCASTING_RANGER, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MORNINGLORD, oCaster);
|
||||
|
||||
@@ -5313,6 +5345,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_SHAMAN, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_OASHAMAN, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
@@ -5524,6 +5559,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_SOHEI, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_SOHEI, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
// if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_SOHEI, oCaster))
|
||||
// nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster);
|
||||
|
||||
@@ -5631,6 +5669,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
|
||||
if(GetHasFeat(FEAT_HOSPITALER_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_HOSPITALER, oCaster);
|
||||
|
||||
if(GetHasFeat(FEAT_LION_OF_TALISID_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_LION_OF_TALISID, oCaster);
|
||||
|
||||
/* if(GetHasFeat(FEAT_MASTER_OF_SHROUDS_SPELLCASTING_SOL, oCaster))
|
||||
nDivine += GetLevelByClass(CLASS_TYPE_MASTER_OF_SHROUDS, oCaster); */
|
||||
|
||||
|
||||
@@ -402,6 +402,7 @@ int Vile_Feat(int iTypeWeap)
|
||||
case BASE_ITEM_LONGSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_LONGSWORD);
|
||||
case BASE_ITEM_MORNINGSTAR: return GetHasFeat(FEAT_VILE_MARTIAL_MORNINGSTAR);
|
||||
case BASE_ITEM_QUARTERSTAFF: return GetHasFeat(FEAT_VILE_MARTIAL_QUARTERSTAFF);
|
||||
case BASE_ITEM_MAGICSTAFF: return GetHasFeat(FEAT_VILE_MARTIAL_QUARTERSTAFF);
|
||||
case BASE_ITEM_RAPIER: return GetHasFeat(FEAT_VILE_MARTIAL_RAPIER);
|
||||
case BASE_ITEM_SCIMITAR: return GetHasFeat(FEAT_VILE_MARTIAL_SCIMITAR);
|
||||
case BASE_ITEM_SCYTHE: return GetHasFeat(FEAT_VILE_MARTIAL_SCYTHE);
|
||||
@@ -482,6 +483,7 @@ int GetSanctifedMartialFeat(int iTypeWeap)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_SANCTIFY_MARTIAL_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_SANCTIFY_MARTIAL_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_SANCTIFY_MARTIAL_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_SANCTIFY_MARTIAL_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_SANCTIFY_MARTIAL_SCYTHE;
|
||||
@@ -555,6 +557,7 @@ int Sanctify_Feat(int iTypeWeap)
|
||||
case BASE_ITEM_LONGSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_LONGSWORD);
|
||||
case BASE_ITEM_MORNINGSTAR: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_MORNINGSTAR);
|
||||
case BASE_ITEM_QUARTERSTAFF: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF);
|
||||
case BASE_ITEM_MAGICSTAFF: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF);
|
||||
case BASE_ITEM_RAPIER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_RAPIER);
|
||||
case BASE_ITEM_SCIMITAR: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SCIMITAR);
|
||||
case BASE_ITEM_SCYTHE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_SCYTHE);
|
||||
|
||||
@@ -1082,6 +1082,7 @@ int GetIsTwoHandedMeleeWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_HEAVYFLAIL: return TRUE;
|
||||
case BASE_ITEM_SCYTHE: return TRUE;
|
||||
case BASE_ITEM_QUARTERSTAFF: return TRUE;
|
||||
case BASE_ITEM_MAGICSTAFF: return TRUE;
|
||||
case BASE_ITEM_ELVEN_COURTBLADE: return TRUE;
|
||||
case BASE_ITEM_MAUL: return TRUE;
|
||||
case BASE_ITEM_FALCHION: return TRUE;
|
||||
@@ -1130,6 +1131,7 @@ int GetIsSimpleWeaponType(int iWeaponType)
|
||||
{
|
||||
case BASE_ITEM_MORNINGSTAR: return 1;
|
||||
case BASE_ITEM_QUARTERSTAFF: return 1;
|
||||
case BASE_ITEM_MAGICSTAFF: return 1;
|
||||
case BASE_ITEM_SHORTSPEAR: return 1;
|
||||
case BASE_ITEM_HEAVYCROSSBOW: return 1;
|
||||
case BASE_ITEM_INVALID: return 1;
|
||||
@@ -1204,6 +1206,7 @@ int GetIsDoubleSidedWeaponType(int iWeaponType)
|
||||
return ( iWeaponType == BASE_ITEM_DIREMACE
|
||||
|| iWeaponType == BASE_ITEM_DOUBLEAXE
|
||||
|| iWeaponType == BASE_ITEM_TWOBLADEDSWORD
|
||||
|| iWeaponType == BASE_ITEM_DOUBLE_SCIMITAR
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1562,6 +1565,19 @@ struct WeaponFeat GetAllFeatsOfWeaponType(int iWeaponType)
|
||||
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_QUARTERSTAFF;
|
||||
break;
|
||||
}
|
||||
case BASE_ITEM_MAGICSTAFF: {
|
||||
sFeat.Focus = FEAT_WEAPON_FOCUS_STAFF;
|
||||
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_STAFF;
|
||||
sFeat.EpicFocus = FEAT_EPIC_WEAPON_FOCUS_QUARTERSTAFF;
|
||||
sFeat.EpicSpecialization = FEAT_EPIC_WEAPON_SPECIALIZATION_QUARTERSTAFF;
|
||||
sFeat.ImprovedCritical = FEAT_IMPROVED_CRITICAL_STAFF;
|
||||
sFeat.OverwhelmingCritical = FEAT_EPIC_OVERWHELMING_CRITICAL_QUARTERSTAFF;
|
||||
sFeat.DevastatingCritical = FEAT_EPIC_DEVASTATING_CRITICAL_QUARTERSTAFF;
|
||||
sFeat.WeaponOfChoice = FEAT_WEAPON_OF_CHOICE_QUARTERSTAFF;
|
||||
sFeat.SanctifyMartialStrike = FEAT_SANCTIFY_MARTIAL_QUARTERSTAFF;
|
||||
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_QUARTERSTAFF;
|
||||
break;
|
||||
}
|
||||
case BASE_ITEM_RAPIER: {
|
||||
sFeat.Focus = FEAT_WEAPON_FOCUS_RAPIER;
|
||||
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_RAPIER;
|
||||
|
||||
@@ -1140,6 +1140,9 @@ void DoCharge(object oPC, object oTarget, int nDoAttack = TRUE, int nGenerateAoO
|
||||
nPounce = TRUE;
|
||||
if (GetHasSpellEffect(VESTIGE_CHUPOCLOPS, oPC) && GetLocalInt(oPC, "ExploitVestige") != VESTIGE_CHUPOCLOPS_POUNCE)
|
||||
nPounce = TRUE;
|
||||
//:: Lion of Talisid
|
||||
if(GetHasFeat(FEAT_LOT_LIONS_POUNCE, oPC))
|
||||
nPounce = TRUE;
|
||||
|
||||
// Checks for a White Raven Stance
|
||||
// If it exists, +1 damage/initiator level
|
||||
@@ -2313,6 +2316,9 @@ void DoShieldCharge(object oPC, object oTarget, int nSlam = FALSE)
|
||||
nPounce = TRUE;
|
||||
if(GetRacialType(oPC) == RACIAL_TYPE_MARRUSAULT)
|
||||
nPounce = TRUE;
|
||||
//:: Lion of Talisid
|
||||
if(GetHasFeat(FEAT_LOT_LIONS_POUNCE, oPC))
|
||||
nPounce = TRUE;
|
||||
|
||||
// Checks for a White Raven Stance
|
||||
// If it exists, +1 damage/initiator level
|
||||
|
||||
@@ -462,7 +462,7 @@ int PRCGetSpellLevelForClass(int nSpell, int nClass)
|
||||
return nSpellLevel;
|
||||
}
|
||||
|
||||
// returns the spelllevel of nSpell as it can be cast by oCreature
|
||||
// returns the spell circle level of nSpell as it can be cast by oCreature
|
||||
int PRCGetSpellLevel(object oCreature, int nSpell)
|
||||
{
|
||||
/*if (!PRCGetHasSpell(nSpell, oCreature))
|
||||
@@ -605,7 +605,7 @@ int PRCGetHasSpell(int nRealSpellID, object oCreature = OBJECT_SELF)
|
||||
if(nSpellbookType == SPELLBOOK_TYPE_PREPARED)
|
||||
{
|
||||
nCount = persistant_array_get_int(oCreature, "NewSpellbookMem_" + IntToString(nClass), j);
|
||||
if(DEBUG) DoDebug("PRCGetHasSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(j) + "] = " + IntToString(nCount));
|
||||
if(DEBUG) DoDebug("prc_inc_core >> PRCGetHasSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(j) + "] = " + IntToString(nCount));
|
||||
if(nCount > 0)
|
||||
{
|
||||
nUses += nCount;
|
||||
@@ -615,7 +615,7 @@ int PRCGetHasSpell(int nRealSpellID, object oCreature = OBJECT_SELF)
|
||||
{
|
||||
nSpellLevel = StringToInt(Get2DACache(sFile, "Level", j));
|
||||
nCount = persistant_array_get_int(oCreature, "NewSpellbookMem_" + IntToString(nClass), nSpellLevel);
|
||||
if(DEBUG) DoDebug("PRCGetHasSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(j) + "] = " + IntToString(nCount));
|
||||
if(DEBUG) DoDebug("prc_inc_core >> PRCGetHasSpell: NewSpellbookMem_" + IntToString(nClass) + "[" + IntToString(j) + "] = " + IntToString(nCount));
|
||||
if(nCount > 0)
|
||||
{
|
||||
nUses += nCount;
|
||||
|
||||
@@ -248,6 +248,7 @@ int GetFocusFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_WEAPON_FOCUS_LONG_SWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_FOCUS_MORNING_STAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_WEAPON_FOCUS_STAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_WEAPON_FOCUS_STAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_WEAPON_FOCUS_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_FOCUS_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_WEAPON_FOCUS_SCYTHE;
|
||||
@@ -318,6 +319,7 @@ int GetSpecializationFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_WEAPON_SPECIALIZATION_LONG_SWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_SPECIALIZATION_MORNING_STAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_WEAPON_SPECIALIZATION_STAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_WEAPON_SPECIALIZATION_STAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_WEAPON_SPECIALIZATION_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_SPECIALIZATION_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_WEAPON_SPECIALIZATION_SCYTHE;
|
||||
@@ -388,6 +390,7 @@ int GetEpicFocusFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_EPIC_WEAPON_FOCUS_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_EPIC_WEAPON_FOCUS_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_EPIC_WEAPON_FOCUS_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_EPIC_WEAPON_FOCUS_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_EPIC_WEAPON_FOCUS_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_EPIC_WEAPON_FOCUS_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_EPIC_WEAPON_FOCUS_SCYTHE;
|
||||
@@ -458,7 +461,8 @@ int GetEpicSpecializationFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_EPIC_WEAPON_SPECIALIZATION_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_EPIC_WEAPON_SPECIALIZATION_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_EPIC_WEAPON_SPECIALIZATION_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_EPIC_WEAPON_SPECIALIZATION_RAPIER;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_EPIC_WEAPON_SPECIALIZATION_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_EPIC_WEAPON_SPECIALIZATION_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_EPIC_WEAPON_SPECIALIZATION_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_EPIC_WEAPON_SPECIALIZATION_SCYTHE;
|
||||
case BASE_ITEM_SHORTBOW: return FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTBOW;
|
||||
@@ -528,6 +532,7 @@ int GetImprovedCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_IMPROVED_CRITICAL_LONG_SWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_IMPROVED_CRITICAL_MORNING_STAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_IMPROVED_CRITICAL_STAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_IMPROVED_CRITICAL_STAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_IMPROVED_CRITICAL_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_IMPROVED_CRITICAL_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_IMPROVED_CRITICAL_SCYTHE;
|
||||
@@ -598,6 +603,7 @@ int GetOverwhelmingCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_EPIC_OVERWHELMING_CRITICAL_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_EPIC_OVERWHELMING_CRITICAL_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_EPIC_OVERWHELMING_CRITICAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_EPIC_OVERWHELMING_CRITICAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_EPIC_OVERWHELMING_CRITICAL_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_EPIC_OVERWHELMING_CRITICAL_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_EPIC_OVERWHELMING_CRITICAL_SCYTHE;
|
||||
@@ -668,6 +674,7 @@ int GetDevastatingCriticalFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_EPIC_DEVASTATING_CRITICAL_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_EPIC_DEVASTATING_CRITICAL_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_EPIC_DEVASTATING_CRITICAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_EPIC_DEVASTATING_CRITICAL_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_EPIC_DEVASTATING_CRITICAL_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_EPIC_DEVASTATING_CRITICAL_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_EPIC_DEVASTATING_CRITICAL_SCYTHE;
|
||||
@@ -729,6 +736,7 @@ int GetWeaponOfChoiceFeatOfWeaponType(int iWeaponType)
|
||||
case BASE_ITEM_LONGSWORD: return FEAT_WEAPON_OF_CHOICE_LONGSWORD;
|
||||
case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_OF_CHOICE_MORNINGSTAR;
|
||||
case BASE_ITEM_QUARTERSTAFF: return FEAT_WEAPON_OF_CHOICE_QUARTERSTAFF;
|
||||
case BASE_ITEM_MAGICSTAFF: return FEAT_WEAPON_OF_CHOICE_QUARTERSTAFF;
|
||||
case BASE_ITEM_RAPIER: return FEAT_WEAPON_OF_CHOICE_RAPIER;
|
||||
case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_OF_CHOICE_SCIMITAR;
|
||||
case BASE_ITEM_SCYTHE: return FEAT_WEAPON_OF_CHOICE_SCYTHE;
|
||||
@@ -787,6 +795,7 @@ int GetWeaponSize(object oWeapon)
|
||||
case BASE_ITEM_GREATAXE:
|
||||
case BASE_ITEM_HEAVYFLAIL:
|
||||
case BASE_ITEM_QUARTERSTAFF:
|
||||
//case BASE_ITEM_MAGICSTAFF:
|
||||
case BASE_ITEM_SCYTHE:
|
||||
case BASE_ITEM_SHORTSPEAR:
|
||||
case BASE_ITEM_ELVEN_COURTBLADE:
|
||||
@@ -823,6 +832,7 @@ int PRCLargeWeaponCheck(int iBaseType, int nSize)
|
||||
case BASE_ITEM_GREATAXE:
|
||||
case BASE_ITEM_HEAVYFLAIL:
|
||||
case BASE_ITEM_QUARTERSTAFF:
|
||||
//case BASE_ITEM_MAGICSTAFF:
|
||||
case BASE_ITEM_SCYTHE:
|
||||
case BASE_ITEM_SHORTSPEAR:
|
||||
case BASE_ITEM_ELVEN_COURTBLADE:
|
||||
|
||||
@@ -108,8 +108,8 @@ void SetupCharacterData(object oPC)
|
||||
case CLASS_TYPE_ALIENIST: sScript = "prc_alienist"; break;
|
||||
case CLASS_TYPE_ARCANE_DUELIST: sScript = "prc_arcduel"; break;
|
||||
case CLASS_TYPE_ARCHIVIST: sScript = "prc_archivist"; iData |= 0x01; break;
|
||||
case CLASS_TYPE_ASSASSIN: iData |= 0x03; break;
|
||||
case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; break;
|
||||
case CLASS_TYPE_ASSASSIN: break;
|
||||
//case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; break;
|
||||
case CLASS_TYPE_BARD: iData |= 0x07; break;
|
||||
case CLASS_TYPE_BATTLESMITH: sScript = "prc_battlesmith"; break;
|
||||
case CLASS_TYPE_BEGUILER: iData |= 0x03; break;
|
||||
@@ -121,7 +121,7 @@ void SetupCharacterData(object oPC)
|
||||
case CLASS_TYPE_BLIGHTLORD: sScript = "prc_blightlord"; break;
|
||||
case CLASS_TYPE_BLOODCLAW_MASTER: sScript = "tob_bloodclaw"; break;
|
||||
case CLASS_TYPE_BONDED_SUMMONNER: sScript = "prc_bondedsumm"; break;
|
||||
case CLASS_TYPE_CELEBRANT_SHARESS: iData |= 0x03; break;
|
||||
case CLASS_TYPE_CELEBRANT_SHARESS: iData |= 0x07; break;
|
||||
case CLASS_TYPE_CHILD_OF_NIGHT: sScript = "shd_childnight"; break;
|
||||
case CLASS_TYPE_COC: sScript = "prc_coc"; break;
|
||||
case CLASS_TYPE_COMBAT_MEDIC: sScript = "prc_cbtmed"; break;
|
||||
@@ -180,6 +180,7 @@ void SetupCharacterData(object oPC)
|
||||
case CLASS_TYPE_LASHER: sScript = "prc_lasher"; break;
|
||||
case CLASS_TYPE_LEGENDARY_DREADNOUGHT: sScript = "prc_legendread"; break;
|
||||
case CLASS_TYPE_LICH: sScript = "pnp_lich_level"; break;
|
||||
case CLASS_TYPE_LION_OF_TALISID: sScript = "prc_lot"; break;
|
||||
case CLASS_TYPE_MAGEKILLER: sScript = "prc_magekill"; break;
|
||||
case CLASS_TYPE_MASTER_HARPER: sScript = "prc_masterh"; break;
|
||||
case CLASS_TYPE_MASTER_OF_NINE: sScript = "tob_masterofnine"; break;
|
||||
@@ -245,6 +246,7 @@ void SetupCharacterData(object oPC)
|
||||
case CLASS_TYPE_TOTEM_RAGER: sScript = "moi_totemrager"; break;
|
||||
case CLASS_TYPE_TRUENAMER: sScript = "true_truenamer"; iData |= 0x01; break;
|
||||
case CLASS_TYPE_VASSAL: sScript = "prc_vassal"; break;
|
||||
case CLASS_TYPE_VERDANT_LORD: sScript = "prc_verdantlord"; break;
|
||||
case CLASS_TYPE_VIGILANT: sScript = "prc_vigilant"; break;
|
||||
case CLASS_TYPE_WARBLADE: sScript = "tob_warblade"; iData |= 0x01; break;
|
||||
case CLASS_TYPE_WARCHIEF: sScript = "prc_warchief"; break;
|
||||
@@ -2264,6 +2266,8 @@ void FeatSpecialUsePerDay(object oPC)
|
||||
FeatUsePerDay(oPC, FEAT_FM_FOREST_DOMINION, ABILITY_CHARISMA, 3);
|
||||
FeatUsePerDay(oPC, FEAT_SOD_DEATH_TOUCH, -1, (GetLevelByClass(CLASS_TYPE_SLAYER_OF_DOMIEL, oPC)+4)/4);
|
||||
FeatUsePerDay(oPC, FEAT_SUEL_DISPELLING_STRIKE, -1, (GetLevelByClass(CLASS_TYPE_SUEL_ARCHANAMACH, oPC) + 2) / 4);
|
||||
FeatUsePerDay(oPC, FEAT_PLANT_CONTROL, ABILITY_CHARISMA, 3);
|
||||
FeatUsePerDay(oPC, FEAT_PLANT_DEFIANCE, ABILITY_CHARISMA, 3);
|
||||
FeatDiabolist(oPC);
|
||||
FeatAlaghar(oPC);
|
||||
ShadowShieldUses(oPC);
|
||||
|
||||
750
src/include/prc_inc_json.nss
Normal file
750
src/include/prc_inc_json.nss
Normal file
@@ -0,0 +1,750 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//:://////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Library for json related functions.
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Script: prc_inc_json.nss
|
||||
//:: Author: Jaysyn
|
||||
//:: Created: 2025-08-14 12:52:32
|
||||
//:://////////////////////////////////////////////
|
||||
#include "nw_inc_gff"
|
||||
#include "inc_debug"
|
||||
|
||||
|
||||
//::---------------------------------------------|
|
||||
//:: Helper functions |
|
||||
//::---------------------------------------------|
|
||||
|
||||
//:: Function to calculate the maximum possible hitpoints for oCreature
|
||||
int GetMaxPossibleHP(object oCreature)
|
||||
{
|
||||
int nMaxHP = 0; // Stores the total maximum hitpoints
|
||||
int i = 1; // Initialize position for class index
|
||||
int nConb = GetAbilityModifier(ABILITY_CONSTITUTION, oCreature);
|
||||
|
||||
// Loop through each class position the creature may have, checking each class in turn
|
||||
while (TRUE)
|
||||
{
|
||||
// Get the class ID at position i
|
||||
int nClassID = GetClassByPosition(i, oCreature);
|
||||
|
||||
// If class is invalid (no more classes to check), break out of loop
|
||||
if (nClassID == CLASS_TYPE_INVALID)
|
||||
break;
|
||||
|
||||
// Get the number of levels in this class
|
||||
int nClassLevels = GetLevelByClass(nClassID, oCreature);
|
||||
|
||||
// Get the row index of the class in classes.2da by using class ID as the row index
|
||||
int nHitDie = StringToInt(Get2DAString("classes", "HitDie", nClassID));
|
||||
|
||||
// Add maximum HP for this class (Hit Die * number of levels in this class)
|
||||
nMaxHP += nClassLevels * nHitDie;
|
||||
|
||||
// Move to the next class position
|
||||
i++;
|
||||
}
|
||||
|
||||
nMaxHP += nConb * GetHitDice(oCreature);
|
||||
|
||||
return nMaxHP;
|
||||
}
|
||||
|
||||
// Returns how many feats a creature should gain when its HD increases
|
||||
int CalculateFeatsFromHD(int nOriginalHD, int nNewHD)
|
||||
{
|
||||
// HD increase
|
||||
int nHDIncrease = nNewHD - nOriginalHD;
|
||||
|
||||
if (nHDIncrease <= 0)
|
||||
return 0; // No new feats if HD did not increase
|
||||
|
||||
// D&D 3E: 1 feat per 3 HD
|
||||
int nBonusFeats = nHDIncrease / 3;
|
||||
|
||||
return nBonusFeats;
|
||||
}
|
||||
|
||||
// Returns how many stat boosts a creature needs based on its HD
|
||||
int GetStatBoostsFromHD(int nCreatureHD, int nModiferCap)
|
||||
{
|
||||
// Make sure we don't get negative boosts
|
||||
int nBoosts = (40 - nCreatureHD) / 4;
|
||||
if (nBoosts < 0)
|
||||
{
|
||||
nBoosts = 0;
|
||||
}
|
||||
return nBoosts;
|
||||
}
|
||||
|
||||
// Struct to hold size modifiers
|
||||
struct SizeModifiers
|
||||
{
|
||||
int strMod;
|
||||
int dexMod;
|
||||
int conMod;
|
||||
int naturalAC;
|
||||
int attackBonus;
|
||||
int dexSkillMod;
|
||||
};
|
||||
|
||||
//::---------------------------------------------|
|
||||
//:: JSON functions |
|
||||
//::---------------------------------------------|
|
||||
|
||||
//:: Returns the integer value of a VarTable entry named sVarName, or 0 if not found.
|
||||
int json_GetLocalIntFromVarTable(json jCreature, string sVarName)
|
||||
{
|
||||
json jVarTable = GffGetList(jCreature, "VarTable");
|
||||
if (jVarTable == JsonNull())
|
||||
return 0;
|
||||
|
||||
int nCount = JsonGetLength(jVarTable);
|
||||
int i;
|
||||
for (i = 0; i < nCount; i++)
|
||||
{
|
||||
json jEntry = JsonArrayGet(jVarTable, i);
|
||||
if (jEntry == JsonNull()) continue;
|
||||
|
||||
// Get the Name field using GFF functions
|
||||
json jName = GffGetString(jEntry, "Name");
|
||||
if (jName == JsonNull()) continue;
|
||||
string sName = JsonGetString(jName);
|
||||
|
||||
if (sName == sVarName)
|
||||
{
|
||||
// Get the Type field to verify it's an integer
|
||||
json jType = GffGetDword(jEntry, "Type");
|
||||
if (jType != JsonNull())
|
||||
{
|
||||
int nType = JsonGetInt(jType);
|
||||
if (nType == 1) // Type 1 = integer
|
||||
{
|
||||
// Get the Value field using GFF functions
|
||||
json jValue = GffGetInt(jEntry, "Value");
|
||||
if (jValue == JsonNull()) return 0;
|
||||
return JsonGetInt(jValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//:: Returns the total Hit Dice from a JSON creature GFF.
|
||||
int json_GetCreatureHD(json jGff)
|
||||
{
|
||||
int nHD = 0;
|
||||
|
||||
json jClasses = GffGetList(jGff, "ClassList");
|
||||
if (jClasses == JsonNull())
|
||||
return 0;
|
||||
|
||||
int nCount = JsonGetLength(jClasses);
|
||||
int i;
|
||||
for (i = 0; i < nCount; i = i + 1)
|
||||
{
|
||||
json jClass = JsonArrayGet(jClasses, i);
|
||||
if (jClass == JsonNull())
|
||||
continue;
|
||||
|
||||
json jLevel = GffGetShort(jClass, "ClassLevel"); // Use GffGetShort, not GffGetField
|
||||
if (jLevel != JsonNull())
|
||||
{
|
||||
int nLevel = JsonGetInt(jLevel);
|
||||
nHD += nLevel;
|
||||
}
|
||||
}
|
||||
|
||||
if (nHD <= 0) nHD = 1;
|
||||
return nHD;
|
||||
}
|
||||
|
||||
//:: Reads ABILITY_TO_INCREASE from creature's VarTable and applies stat boosts based on increased HD
|
||||
json json_ApplyAbilityBoostFromHD(json jCreature, int nOriginalHD, int nModifierCap)
|
||||
{
|
||||
if (jCreature == JsonNull())
|
||||
return jCreature;
|
||||
|
||||
// Get the ability to increase from VarTable
|
||||
int nAbilityToIncrease = json_GetLocalIntFromVarTable(jCreature, "ABILITY_TO_INCREASE");
|
||||
if (nAbilityToIncrease < 0 || nAbilityToIncrease > 5)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Invalid ABILITY_TO_INCREASE value: " + IntToString(nAbilityToIncrease));
|
||||
return jCreature; // Invalid ability index
|
||||
}
|
||||
|
||||
// Calculate total current HD from ClassList
|
||||
json jClassList = GffGetList(jCreature, "ClassList");
|
||||
if (jClassList == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Failed to get ClassList");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
int nCurrentTotalHD = 0;
|
||||
int nClassCount = JsonGetLength(jClassList);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nClassCount; i++)
|
||||
{
|
||||
json jClass = JsonArrayGet(jClassList, i);
|
||||
if (jClass != JsonNull())
|
||||
{
|
||||
json jClassLevel = GffGetShort(jClass, "ClassLevel");
|
||||
if (jClassLevel != JsonNull())
|
||||
{
|
||||
nCurrentTotalHD += JsonGetInt(jClassLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nCurrentTotalHD <= 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: No valid Hit Dice found");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Calculate stat boosts based on crossing level thresholds
|
||||
// Characters get stat boosts at levels 4, 8, 12, 16, 20, etc.
|
||||
int nOriginalBoosts = nOriginalHD / 4; // How many boosts they already had
|
||||
int nCurrentBoosts = nCurrentTotalHD / 4; // How many they should have now
|
||||
int nBoosts = nCurrentBoosts - nOriginalBoosts; // Additional boosts to apply
|
||||
|
||||
if (nBoosts <= 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: No boosts needed (Original boosts: " + IntToString(nOriginalBoosts) + ", Current boosts: " + IntToString(nCurrentBoosts) + ")");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Applying " + IntToString(nBoosts) + " boosts to ability " + IntToString(nAbilityToIncrease) + " for HD increase from " + IntToString(nOriginalHD) + " to " + IntToString(nCurrentTotalHD));
|
||||
|
||||
// Determine which ability to boost and apply the increases
|
||||
string sAbilityField;
|
||||
switch (nAbilityToIncrease)
|
||||
{
|
||||
case 0: sAbilityField = "Str"; break;
|
||||
case 1: sAbilityField = "Dex"; break;
|
||||
case 2: sAbilityField = "Con"; break;
|
||||
case 3: sAbilityField = "Int"; break;
|
||||
case 4: sAbilityField = "Wis"; break;
|
||||
case 5: sAbilityField = "Cha"; break;
|
||||
default:
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Unknown ability index: " + IntToString(nAbilityToIncrease));
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Get current ability score
|
||||
json jCurrentAbility = GffGetByte(jCreature, sAbilityField);
|
||||
if (jCurrentAbility == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Failed to get " + sAbilityField + " score");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
int nCurrentScore = JsonGetInt(jCurrentAbility);
|
||||
int nNewScore = nCurrentScore + nBoosts;
|
||||
|
||||
// Clamp to valid byte range
|
||||
if (nNewScore < 1) nNewScore = 1;
|
||||
if (nNewScore > 255) nNewScore = 255;
|
||||
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Increasing " + sAbilityField + " from " + IntToString(nCurrentScore) + " to " + IntToString(nNewScore));
|
||||
|
||||
// Apply the ability score increase
|
||||
jCreature = GffReplaceByte(jCreature, sAbilityField, nNewScore);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Failed to update " + sAbilityField);
|
||||
return JsonNull();
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_ApplyAbilityBoostFromHD: Successfully applied ability boosts");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Adjust a skill by its ID (more efficient than name lookup)
|
||||
json json_AdjustCreatureSkillByID(json jCreature, int nSkillID, int nMod)
|
||||
{
|
||||
// Get the SkillList
|
||||
json jSkillList = GffGetList(jCreature, "SkillList");
|
||||
if (jSkillList == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSkillByID: Failed to get SkillList");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Check if we have enough skills in the list
|
||||
int nSkillCount = JsonGetLength(jSkillList);
|
||||
if (nSkillID >= nSkillCount)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSkillByID: Skill ID " + IntToString(nSkillID) + " exceeds skill list length " + IntToString(nSkillCount));
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Get the skill struct at the correct index
|
||||
json jSkill = JsonArrayGet(jSkillList, nSkillID);
|
||||
if (jSkill == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSkillByID: Failed to get skill at index " + IntToString(nSkillID));
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Get current rank
|
||||
json jRank = GffGetByte(jSkill, "Rank");
|
||||
if (jRank == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSkillByID: Failed to get Rank for skill ID " + IntToString(nSkillID));
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
int nCurrentRank = JsonGetInt(jRank);
|
||||
int nNewRank = nCurrentRank + nMod;
|
||||
|
||||
// Clamp to valid range
|
||||
if (nNewRank < 0) nNewRank = 0;
|
||||
if (nNewRank > 255) nNewRank = 255;
|
||||
|
||||
// Update the rank in the skill struct
|
||||
jSkill = GffReplaceByte(jSkill, "Rank", nNewRank);
|
||||
if (jSkill == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSkillByID: Failed to replace Rank for skill ID " + IntToString(nSkillID));
|
||||
return JsonNull();
|
||||
}
|
||||
|
||||
// Replace the skill in the array
|
||||
jSkillList = JsonArraySet(jSkillList, nSkillID, jSkill);
|
||||
|
||||
// Replace the SkillList in the creature
|
||||
jCreature = GffReplaceList(jCreature, "SkillList", jSkillList);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Reads FutureFeat1..FutureFeatN from the template's VarTable and appends them to FeatList if missing.
|
||||
json json_AddFeatsFromCreatureVars(json jCreature, int nOriginalHD)
|
||||
{
|
||||
if (jCreature == JsonNull())
|
||||
return jCreature;
|
||||
|
||||
// Calculate current total HD
|
||||
int nCurrentHD = json_GetCreatureHD(jCreature);
|
||||
int nAddedHD = nCurrentHD - nOriginalHD;
|
||||
|
||||
if (nAddedHD <= 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: No additional HD to process (Current: " + IntToString(nCurrentHD) + ", Original: " + IntToString(nOriginalHD) + ")");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Calculate how many feats the creature should get based on added HD
|
||||
// Characters get a feat at levels 1, 3, 6, 9, 12, 15, 18, etc.
|
||||
// For added levels, we need to check what feat levels they cross
|
||||
int nOriginalFeats = (nOriginalHD + 2) / 3; // Feats from original HD
|
||||
int nCurrentFeats = (nCurrentHD + 2) / 3; // Feats from current HD
|
||||
int nNumFeats = nCurrentFeats - nOriginalFeats; // Additional feats earned
|
||||
|
||||
if (nNumFeats <= 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: No additional feats earned from " + IntToString(nAddedHD) + " added HD");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Processing " + IntToString(nNumFeats) + " feats for " + IntToString(nAddedHD) + " added HD (Original: " + IntToString(nOriginalHD) + ", Current: " + IntToString(nCurrentHD) + ")");
|
||||
|
||||
// Get or create FeatList
|
||||
json jFeatArray = GffGetList(jCreature, "FeatList");
|
||||
if (jFeatArray == JsonNull())
|
||||
jFeatArray = JsonArray();
|
||||
|
||||
int nOriginalFeatCount = JsonGetLength(jFeatArray);
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Original feat count: " + IntToString(nOriginalFeatCount));
|
||||
|
||||
int nAdded = 0;
|
||||
int i = 1;
|
||||
int nMaxIterations = 100; // Safety valve
|
||||
int nIterations = 0;
|
||||
|
||||
while (nAdded < nNumFeats && nIterations < nMaxIterations)
|
||||
{
|
||||
nIterations++;
|
||||
string sVarName = "FutureFeat" + IntToString(i);
|
||||
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Checking " + sVarName);
|
||||
|
||||
int nFeat = json_GetLocalIntFromVarTable(jCreature, sVarName);
|
||||
|
||||
if (nFeat <= 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: " + sVarName + " not found or invalid");
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Found " + sVarName + " = " + IntToString(nFeat));
|
||||
|
||||
// Check if feat already exists
|
||||
int bHasFeat = FALSE;
|
||||
int nFeatCount = JsonGetLength(jFeatArray);
|
||||
int j;
|
||||
|
||||
for (j = 0; j < nFeatCount; j++)
|
||||
{
|
||||
json jFeatStruct = JsonArrayGet(jFeatArray, j);
|
||||
if (jFeatStruct != JsonNull())
|
||||
{
|
||||
json jFeatValue = GffGetWord(jFeatStruct, "Feat");
|
||||
if (jFeatValue != JsonNull() && JsonGetInt(jFeatValue) == nFeat)
|
||||
{
|
||||
bHasFeat = TRUE;
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Feat " + IntToString(nFeat) + " already exists");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Insert if missing
|
||||
if (!bHasFeat)
|
||||
{
|
||||
json jNewFeat = JsonObject();
|
||||
jNewFeat = JsonObjectSet(jNewFeat, "__struct_id", JsonInt(1));
|
||||
jNewFeat = GffAddWord(jNewFeat, "Feat", nFeat);
|
||||
|
||||
if (jNewFeat == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Failed to create feat struct for feat " + IntToString(nFeat));
|
||||
break;
|
||||
}
|
||||
|
||||
jFeatArray = JsonArrayInsert(jFeatArray, jNewFeat);
|
||||
nAdded++;
|
||||
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Added feat " + IntToString(nFeat) + " (" + IntToString(nAdded) + "/" + IntToString(nNumFeats) + ")");
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
// Safety break if we've checked too many variables
|
||||
if (i > 100)
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Safety break - checked too many FutureFeat variables");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Completed. Added " + IntToString(nAdded) + " feats in " + IntToString(nIterations) + " iterations");
|
||||
|
||||
// Save back the modified FeatList only if we added something
|
||||
if (nAdded > 0)
|
||||
{
|
||||
jCreature = GffReplaceList(jCreature, "FeatList", jFeatArray);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("json_AddFeatsFromCreatureVars: Failed to replace FeatList");
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Get the size of a JSON array
|
||||
int json_GetArraySize(json jArray)
|
||||
{
|
||||
int iSize = 0;
|
||||
while (JsonArrayGet(jArray, iSize) != JsonNull())
|
||||
{
|
||||
iSize++;
|
||||
}
|
||||
return iSize;
|
||||
}
|
||||
|
||||
//:: Directly modifies oCreature's Base Natural AC if iNewAC is higher.
|
||||
//::
|
||||
json json_UpdateBaseAC(json jCreature, int iNewAC)
|
||||
{
|
||||
//json jBaseAC = GffGetByte(jCreature, "Creature/value/NaturalAC/value");
|
||||
json jBaseAC = GffGetByte(jCreature, "NaturalAC");
|
||||
|
||||
if (jBaseAC == JsonNull())
|
||||
{
|
||||
return JsonNull();
|
||||
}
|
||||
else if (JsonGetInt(jBaseAC) > iNewAC)
|
||||
{
|
||||
return jCreature;
|
||||
}
|
||||
else
|
||||
{
|
||||
jCreature = GffReplaceByte(jCreature, "NaturalAC", iNewAC);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
}
|
||||
|
||||
//:: Directly modifies jCreature's Challenge Rating.
|
||||
//:: This is useful for most XP calculations.
|
||||
json json_UpdateCR(json jCreature, int nBaseCR, int nCRMod)
|
||||
{
|
||||
int nNewCR;
|
||||
|
||||
//:: Add CRMod to current CR
|
||||
nNewCR = nBaseCR + nCRMod;
|
||||
|
||||
//:: Modify Challenge Rating
|
||||
jCreature = GffReplaceFloat(jCreature, "ChallengeRating", IntToFloat(nNewCR));
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Directly modifies ability scores in a creature's JSON GFF.
|
||||
//::
|
||||
json json_UpdateTemplateStats(json jCreature, int iModStr = 0, int iModDex = 0, int iModCon = 0,
|
||||
int iModInt = 0, int iModWis = 0, int iModCha = 0)
|
||||
{
|
||||
int iCurrent;
|
||||
|
||||
// STR
|
||||
if (!GffGetFieldExists(jCreature, "Str", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Str", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Str"));
|
||||
jCreature = GffReplaceByte(jCreature, "Str", iCurrent + iModStr);
|
||||
|
||||
// DEX
|
||||
if (!GffGetFieldExists(jCreature, "Dex", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Dex", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Dex"));
|
||||
jCreature = GffReplaceByte(jCreature, "Dex", iCurrent + iModDex);
|
||||
|
||||
// CON
|
||||
if (!GffGetFieldExists(jCreature, "Con", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Con", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Con"));
|
||||
jCreature = GffReplaceByte(jCreature, "Con", iCurrent + iModCon);
|
||||
|
||||
// INT
|
||||
if (!GffGetFieldExists(jCreature, "Int", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Int", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Int"));
|
||||
jCreature = GffReplaceByte(jCreature, "Int", iCurrent + iModInt);
|
||||
|
||||
// WIS
|
||||
if (!GffGetFieldExists(jCreature, "Wis", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Wis", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Wis"));
|
||||
jCreature = GffReplaceByte(jCreature, "Wis", iCurrent + iModWis);
|
||||
|
||||
// CHA
|
||||
if (!GffGetFieldExists(jCreature, "Cha", GFF_FIELD_TYPE_BYTE))
|
||||
jCreature = GffAddByte(jCreature, "Cha", 10);
|
||||
iCurrent = JsonGetInt(GffGetByte(jCreature, "Cha"));
|
||||
jCreature = GffReplaceByte(jCreature, "Cha", iCurrent + iModCha);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Directly modifies oCreature's ability scores.
|
||||
//::
|
||||
json json_UpdateCreatureStats(json jCreature, object oBaseCreature, int iModStr = 0, int iModDex = 0, int iModCon = 0, int iModInt = 0, int iModWis = 0, int iModCha = 0)
|
||||
{
|
||||
//:: Retrieve and modify ability scores
|
||||
int iCurrentStr = GetAbilityScore(oBaseCreature, ABILITY_STRENGTH);
|
||||
int iCurrentDex = GetAbilityScore(oBaseCreature, ABILITY_DEXTERITY);
|
||||
int iCurrentCon = GetAbilityScore(oBaseCreature, ABILITY_CONSTITUTION);
|
||||
int iCurrentInt = GetAbilityScore(oBaseCreature, ABILITY_INTELLIGENCE);
|
||||
int iCurrentWis = GetAbilityScore(oBaseCreature, ABILITY_WISDOM);
|
||||
int iCurrentCha = GetAbilityScore(oBaseCreature, ABILITY_CHARISMA);
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "Str", iCurrentStr + iModStr);
|
||||
jCreature = GffReplaceByte(jCreature, "Dex", iCurrentDex + iModDex);
|
||||
jCreature = GffReplaceByte(jCreature, "Con", iCurrentCon + iModCon);
|
||||
jCreature = GffReplaceByte(jCreature, "Int", iCurrentInt + iModInt);
|
||||
jCreature = GffReplaceByte(jCreature, "Wis", iCurrentWis + iModWis);
|
||||
jCreature = GffReplaceByte(jCreature, "Cha", iCurrentCha + iModCha);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Increases a creature's Hit Dice in its JSON GFF data by nAmount
|
||||
json json_AddHitDice(json jCreature, int nAmount)
|
||||
{
|
||||
if (jCreature == JsonNull() || nAmount <= 0)
|
||||
return jCreature;
|
||||
|
||||
// Get the ClassList
|
||||
json jClasses = GffGetList(jCreature, "ClassList");
|
||||
if (jClasses == JsonNull() || JsonGetLength(jClasses) == 0)
|
||||
return jCreature;
|
||||
|
||||
// Grab the first class entry
|
||||
json jFirstClass = JsonArrayGet(jClasses, 0);
|
||||
|
||||
// Only touch ClassLevel; do NOT modify Class type
|
||||
json jCurrentLevel = GffGetShort(jFirstClass, "ClassLevel");
|
||||
int nCurrentLevel = JsonGetInt(jCurrentLevel);
|
||||
int nNewLevel = nCurrentLevel + nAmount;
|
||||
|
||||
// Replace ClassLevel only
|
||||
jFirstClass = GffReplaceShort(jFirstClass, "ClassLevel", nNewLevel);
|
||||
|
||||
// Put modified class back into the array
|
||||
jClasses = JsonArraySet(jClasses, 0, jFirstClass);
|
||||
|
||||
// Replace ClassList in the creature JSON
|
||||
jCreature = GffReplaceList(jCreature, "ClassList", jClasses);
|
||||
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
//:: Adjusts a creature's size by nSizeChange (-4 to +4) and updates ability scores accordingly.
|
||||
json json_AdjustCreatureSize(json jCreature, int nSizeDelta)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Entering function. nSizeDelta=" + IntToString(nSizeDelta));
|
||||
|
||||
if (jCreature == JsonNull() || nSizeDelta == 0)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Exiting: jCreature is null or nSizeDelta is 0");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
// Get Appearance_Type using GFF functions
|
||||
json jAppearanceType = GffGetWord(jCreature, "Appearance_Type");
|
||||
if (jAppearanceType == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed to get Appearance_Type");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
int nAppearance = JsonGetInt(jAppearanceType);
|
||||
int nCurrentSize = StringToInt(Get2DAString("appearances", "Size", nAppearance));
|
||||
|
||||
// Default to Medium (4) if invalid
|
||||
if (nCurrentSize < 0 || nCurrentSize > 8) nCurrentSize = 4;
|
||||
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Appearance_Type =" + IntToString(nAppearance) + ", Size =" + IntToString(nCurrentSize));
|
||||
|
||||
int nSteps = nSizeDelta;
|
||||
|
||||
// Calculate modifiers based on size change
|
||||
int strMod = nSteps * 4;
|
||||
int dexMod = nSteps * -1;
|
||||
int conMod = nSteps * 2;
|
||||
int naturalAC = nSteps * 1;
|
||||
int dexSkillMod = nSteps * -2;
|
||||
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Applying stat modifiers: STR=" + IntToString(strMod) +
|
||||
" DEX=" + IntToString(dexMod) +
|
||||
" CON=" + IntToString(conMod));
|
||||
|
||||
// Update ability scores using GFF functions with error checking
|
||||
json jStr = GffGetByte(jCreature, "Str");
|
||||
if (jStr != JsonNull())
|
||||
{
|
||||
int nNewStr = JsonGetInt(jStr) + strMod;
|
||||
if (nNewStr < 1) nNewStr = 1;
|
||||
if (nNewStr > 255) nNewStr = 255;
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "Str", nNewStr);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed to update Str");
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
json jDex = GffGetByte(jCreature, "Dex");
|
||||
if (jDex != JsonNull())
|
||||
{
|
||||
int nNewDex = JsonGetInt(jDex) + dexMod;
|
||||
if (nNewDex < 1) nNewDex = 1;
|
||||
if (nNewDex > 255) nNewDex = 255;
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "Dex", nNewDex);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed to update Dex");
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
json jCon = GffGetByte(jCreature, "Con");
|
||||
if (jCon != JsonNull())
|
||||
{
|
||||
int nNewCon = JsonGetInt(jCon) + conMod;
|
||||
if (nNewCon < 1) nNewCon = 1;
|
||||
if (nNewCon > 255) nNewCon = 255;
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "Con", nNewCon);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed to update Con");
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
// Update Natural AC
|
||||
json jNaturalAC = GffGetByte(jCreature, "NaturalAC");
|
||||
if (jNaturalAC != JsonNull())
|
||||
{
|
||||
int nCurrentNA = JsonGetInt(jNaturalAC);
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Current NaturalAC: " + IntToString(nCurrentNA));
|
||||
|
||||
int nNewNA = nCurrentNA + naturalAC;
|
||||
if (nNewNA < 0) nNewNA = 0;
|
||||
if (nNewNA > 255) nNewNA = 255;
|
||||
|
||||
jCreature = GffReplaceByte(jCreature, "NaturalAC", nNewNA);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed to update NaturalAC");
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust all Dexterity-based skills by finding them in skills.2da
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Adjusting DEX-based skills");
|
||||
|
||||
int nSkillID = 0;
|
||||
while (TRUE)
|
||||
{
|
||||
string sKeyAbility = Get2DAString("skills", "KeyAbility", nSkillID);
|
||||
|
||||
// Break when we've reached the end of skills
|
||||
if (sKeyAbility == "")
|
||||
break;
|
||||
|
||||
// If this skill uses Dexterity, adjust it
|
||||
if (sKeyAbility == "DEX")
|
||||
{
|
||||
string sSkillLabel = Get2DAString("skills", "Label", nSkillID);
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Adjusting DEX skill: " + sSkillLabel + " (ID: " + IntToString(nSkillID) + ")");
|
||||
|
||||
jCreature = json_AdjustCreatureSkillByID(jCreature, nSkillID, dexSkillMod);
|
||||
if (jCreature == JsonNull())
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_json >> json_AdjustCreatureSize: Failed adjusting skill ID " + IntToString(nSkillID));
|
||||
return JsonNull();
|
||||
}
|
||||
}
|
||||
|
||||
nSkillID++;
|
||||
}
|
||||
|
||||
if(DEBUG) DoDebug("json_AdjustCreatureSize completed successfully");
|
||||
return jCreature;
|
||||
}
|
||||
|
||||
|
||||
//:: Test void
|
||||
//:: void main (){}
|
||||
@@ -16,26 +16,28 @@ const int MATERIAL_TYPE_UNKNOWN = 0;
|
||||
const int MATERIAL_TYPE_BONE = 1;
|
||||
const int MATERIAL_TYPE_CERAMIC = 2;
|
||||
const int MATERIAL_TYPE_CRYSTAL = 3;
|
||||
const int MATERIAL_TYPE_FABRIC = 4;
|
||||
const int MATERIAL_TYPE_FIBER = 4;
|
||||
const int MATERIAL_TYPE_LEATHER = 5;
|
||||
const int MATERIAL_TYPE_METAL = 6;
|
||||
const int MATERIAL_TYPE_PAPER = 7;
|
||||
const int MATERIAL_TYPE_ROPE = 8;
|
||||
const int MATERIAL_TYPE_STONE = 9;
|
||||
const int MATERIAL_TYPE_WOOD = 10;
|
||||
const int MATERIAL_TYPE_BOTANICAL = 11;
|
||||
|
||||
const string MATERIAL_TYPE_NAME_INVALID = "";
|
||||
const string MATERIAL_TYPE_NAME_UNKNOWN = "Unknown";
|
||||
const string MATERIAL_TYPE_NAME_BONE = "Bone";
|
||||
const string MATERIAL_TYPE_NAME_CERAMIC = "Ceramic";
|
||||
const string MATERIAL_TYPE_NAME_CRYSTAL = "Crystal";
|
||||
const string MATERIAL_TYPE_NAME_FABRIC = "Fabric";
|
||||
const string MATERIAL_TYPE_NAME_FIBER = "Fiber";
|
||||
const string MATERIAL_TYPE_NAME_LEATHER = "Leather";
|
||||
const string MATERIAL_TYPE_NAME_METAL = "Metal";
|
||||
const string MATERIAL_TYPE_NAME_PAPER = "Paper";
|
||||
const string MATERIAL_TYPE_NAME_ROPE = "Rope";
|
||||
const string MATERIAL_TYPE_NAME_STONE = "Stone";
|
||||
const string MATERIAL_TYPE_NAME_WOOD = "Wood";
|
||||
const string MATERIAL_TYPE_NAME_BOTANICAL = "Bontanical";
|
||||
|
||||
//:: Material Itemproperty Constants
|
||||
//::////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -163,7 +165,8 @@ const int IP_MATERIAL_OBSIDIAN = 140;
|
||||
const int IP_MATERIAL_BAMBOO = 141;
|
||||
const int IP_MATERIAL_POTTERY = 142;
|
||||
const int IP_MATERIAL_GLASSTEEL = 143;
|
||||
const int IP_NUM_MATERIALS = 143;
|
||||
const int IP_MATERIAL_HERB = 144;
|
||||
const int IP_NUM_MATERIALS = 144;
|
||||
|
||||
const string IP_MATERIAL_NAME_INVALID = "";
|
||||
const string IP_MATERIAL_NAME_UNKNOWN = "Unknown";
|
||||
@@ -288,6 +291,7 @@ const string IP_MATERIAL_NAME_OBSIDIAN = "Obsidian";
|
||||
const string IP_MATERIAL_NAME_BAMBOO = "Bamboo";
|
||||
const string IP_MATERIAL_NAME_POTTERY = "Pottery";
|
||||
const string IP_MATERIAL_NAME_GLASSTEEL = "Glassteel";
|
||||
const string IP_MATERIAL_NAME_HERB = "Herbs";
|
||||
|
||||
//::///////////////////////////////////////////////////////////////
|
||||
// GetMaterialName( int iMaterialType, int bLowerCase = FALSE)
|
||||
@@ -428,6 +432,7 @@ string GetMaterialName( int iMaterialType, int bLowerCase = FALSE)
|
||||
case IP_MATERIAL_BAMBOO: sName = IP_MATERIAL_NAME_BAMBOO; break;
|
||||
case IP_MATERIAL_POTTERY: sName = IP_MATERIAL_NAME_POTTERY; break;
|
||||
case IP_MATERIAL_GLASSTEEL: sName = IP_MATERIAL_NAME_GLASSTEEL; break;
|
||||
case IP_MATERIAL_HERB: sName = IP_MATERIAL_NAME_HERB; break;
|
||||
|
||||
default: return "";
|
||||
}
|
||||
@@ -573,6 +578,7 @@ int GetIPMaterial( string sMaterialName)
|
||||
else if( sMaterialName == GetStringUpperCase(IP_MATERIAL_NAME_BAMBOO)) return IP_MATERIAL_BAMBOO;
|
||||
else if( sMaterialName == GetStringUpperCase(IP_MATERIAL_NAME_POTTERY)) return IP_MATERIAL_POTTERY;
|
||||
else if( sMaterialName == GetStringUpperCase(IP_MATERIAL_NAME_GLASSTEEL)) return IP_MATERIAL_GLASSTEEL;
|
||||
else if( sMaterialName == GetStringUpperCase(IP_MATERIAL_NAME_HERB)) return IP_MATERIAL_HERB;
|
||||
|
||||
return IP_MATERIAL_INVALID;
|
||||
}
|
||||
@@ -806,6 +812,9 @@ int GetMaterialType(int nMaterial)
|
||||
|| nMaterial == IP_MATERIAL_DRAKE_IVORY )
|
||||
return MATERIAL_TYPE_BONE;
|
||||
|
||||
else if ( nMaterial == IP_MATERIAL_HERB )
|
||||
return MATERIAL_TYPE_BOTANICAL;
|
||||
|
||||
else if ( nMaterial == IP_MATERIAL_ELUKIAN_CLAY
|
||||
|| nMaterial == IP_MATERIAL_POTTERY )
|
||||
return MATERIAL_TYPE_CERAMIC;
|
||||
@@ -814,7 +823,7 @@ int GetMaterialType(int nMaterial)
|
||||
|| nMaterial == IP_MATERIAL_COTTON
|
||||
|| nMaterial == IP_MATERIAL_SILK
|
||||
|| nMaterial == IP_MATERIAL_WOOL )
|
||||
return MATERIAL_TYPE_FABRIC;
|
||||
return MATERIAL_TYPE_FIBER;
|
||||
|
||||
else if ( nMaterial == IP_MATERIAL_GEM
|
||||
|| nMaterial == IP_MATERIAL_GEM_ALEXANDRITE
|
||||
|
||||
@@ -115,11 +115,11 @@ int PerformJump(object oPC, location lLoc, int bDoKnockDown = TRUE)
|
||||
iBonus = 4;
|
||||
}
|
||||
}
|
||||
/*if (GetHasSpellEffect(MOVE_TC_LEAPING_DRAGON, oPC))
|
||||
if (GetHasSpellEffect(MOVE_TC_LEAPING_DRAGON, oPC))
|
||||
{
|
||||
bIsRunningJump = TRUE;
|
||||
iBonus = 10;
|
||||
} */
|
||||
//iBonus = 10; //:: This is granted in the stance.
|
||||
}
|
||||
// PnP rules are height * 6 for run and height * 2 for jump.
|
||||
// I can't get height so that is assumed to be 6.
|
||||
// Changed maxed jump distance because the NwN distance is rather short
|
||||
@@ -375,6 +375,12 @@ int PRCIsFlying(object oCreature)
|
||||
if(GetRacialType(oCreature) == RACIAL_TYPE_GLOURA)
|
||||
bFlying = TRUE;
|
||||
|
||||
if(GetRacialType(oCreature) == RACIAL_TYPE_AVARIEL)
|
||||
bFlying = TRUE;
|
||||
|
||||
if(GetRacialType(oCreature) == RACIAL_TYPE_FEYRI)
|
||||
bFlying = TRUE;
|
||||
|
||||
if(GetRacialType(oCreature) == RACIAL_TYPE_SPIRETOPDRAGON)
|
||||
bFlying = TRUE;
|
||||
|
||||
|
||||
@@ -20,6 +20,11 @@
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//:: Calculates total Shield AC bonuses from all sources
|
||||
int GetTotalShieldACBonus(object oCreature);
|
||||
|
||||
//:: Handles psuedo-Foritifcation
|
||||
void DoFortification(object oPC = OBJECT_SELF, int nFortification = 25);
|
||||
|
||||
@@ -376,23 +381,53 @@ const int TYPE_DIVINE = -2;
|
||||
/* Function definitions */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
// Returns TRUE if nSpellID is a subradial spell, FALSE otherwise
|
||||
int GetIsSubradialSpell(int nSpellID)
|
||||
{
|
||||
string sMaster = Get2DACache("spells", "Master", nSpellID);
|
||||
|
||||
// If the Master column is numeric, this spell is a subradial of that master
|
||||
if (sMaster != "" && sMaster != "****")
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Returns the masterspell SpellID for a subradial spell.
|
||||
int GetMasterSpellFromSubradial(int nSpellID)
|
||||
{
|
||||
string sMaster = Get2DAString("spells", "Master", nSpellID);
|
||||
|
||||
if (sMaster != "****")
|
||||
{
|
||||
return StringToInt(sMaster);
|
||||
}
|
||||
|
||||
return -1; // No master
|
||||
}
|
||||
|
||||
|
||||
|
||||
int GetPrCAdjustedClassLevel(int nClass, object oCaster = OBJECT_SELF)
|
||||
{
|
||||
int iTemp;
|
||||
// is it arcane, divine or neither?
|
||||
if(GetIsArcaneClass(nClass, oCaster) && nClass != CLASS_TYPE_SUBLIME_CHORD)
|
||||
{
|
||||
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
|
||||
if (GetPrimaryArcaneClass(oCaster) == nClass) // adjust for any PrCs
|
||||
iTemp = GetArcanePRCLevels(oCaster, nClass);
|
||||
}
|
||||
else if(GetIsDivineClass(nClass, oCaster))
|
||||
{
|
||||
if (GetPrimaryDivineClass(oCaster) == nClass) // adjust for any PrCs
|
||||
if (GetPrimaryDivineClass(oCaster) == nClass) // adjust for any PrCs
|
||||
iTemp = GetDivinePRCLevels(oCaster, nClass);
|
||||
}
|
||||
else // a non-caster class or a PrC
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
// add the caster class levels
|
||||
return iTemp += GetLevelByClass(nClass, oCaster);
|
||||
@@ -412,7 +447,9 @@ int GetPrCAdjustedCasterLevelByType(int nClassType, object oCaster = OBJECT_SELF
|
||||
{
|
||||
int nClassLvl;
|
||||
int nClass1, nClass2, nClass3, nClass4, nClass5, nClass6, nClass7, nClass8;
|
||||
int nClass1Lvl, nClass2Lvl, nClass3Lvl, nClass4Lvl, nClass5Lvl, nClass6Lvl, nClass7Lvl, nClass8Lvl;
|
||||
int nClass1Lvl = 0, nClass2Lvl = 0, nClass3Lvl = 0, nClass4Lvl = 0,
|
||||
nClass5Lvl = 0, nClass6Lvl = 0, nClass7Lvl = 0, nClass8Lvl = 0;
|
||||
|
||||
|
||||
nClass1 = GetClassByPosition(1, oCaster);
|
||||
nClass2 = GetClassByPosition(2, oCaster);
|
||||
@@ -2223,6 +2260,78 @@ int GetControlledCelestialTotalHD(object oPC = OBJECT_SELF)
|
||||
return nTotalHD;
|
||||
}
|
||||
|
||||
//:: Calculates total Shield AC bonuses from all sources
|
||||
int GetTotalShieldACBonus(object oCreature)
|
||||
{
|
||||
int nShieldBonus = 0;
|
||||
object oItem;
|
||||
|
||||
// Check left hand for shield
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
||||
if (GetIsObjectValid(oItem))
|
||||
{
|
||||
int nBaseItem = GetBaseItemType(oItem);
|
||||
if (nBaseItem == BASE_ITEM_SMALLSHIELD ||
|
||||
nBaseItem == BASE_ITEM_LARGESHIELD ||
|
||||
nBaseItem == BASE_ITEM_TOWERSHIELD)
|
||||
{
|
||||
nShieldBonus += GetItemACValue(oItem);
|
||||
if(DEBUG) DoDebug("prc_inc_spells >> GetTotalShieldACBonus: Found Shield AC, bonus = " + IntToString(nShieldBonus)+".");
|
||||
}
|
||||
}
|
||||
|
||||
// Check creature weapon slots for shield AC bonus
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCreature);
|
||||
if (GetIsObjectValid(oItem))
|
||||
nShieldBonus += GetItemACValue(oItem);
|
||||
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oCreature);
|
||||
if (GetIsObjectValid(oItem))
|
||||
nShieldBonus += GetItemACValue(oItem);
|
||||
|
||||
oItem = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCreature);
|
||||
if (GetIsObjectValid(oItem))
|
||||
nShieldBonus += GetItemACValue(oItem);
|
||||
|
||||
// Add shield AC bonuses from magical effects
|
||||
effect eEffect = GetFirstEffect(oCreature);
|
||||
while (GetIsEffectValid(eEffect))
|
||||
{
|
||||
int nACType = GetEffectInteger(eEffect, 0);
|
||||
int nACAmount = GetEffectInteger(eEffect, 1);
|
||||
|
||||
if(GetEffectType(eEffect) == EFFECT_TYPE_AC_INCREASE && nACType == AC_SHIELD_ENCHANTMENT_BONUS)
|
||||
{
|
||||
if(DEBUG) DoDebug("prc_inc_spells >> GetTotalShieldACBonus: Found Shield AC effect, bonus = " + IntToString(nACAmount)+".");
|
||||
nShieldBonus += nACAmount;
|
||||
}
|
||||
|
||||
eEffect = GetNextEffect(oCreature);
|
||||
}
|
||||
return nShieldBonus;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Add shield AC bonuses from magical effects
|
||||
/* effect eEffect = GetFirstEffect(oCreature);
|
||||
while (GetIsEffectValid(eEffect))
|
||||
{
|
||||
if (GetEffectType(eEffect) == EFFECT_TYPE_AC_INCREASE &&
|
||||
GetEffectInteger(eEffect, 1) == AC_SHIELD_ENCHANTMENT_BONUS)
|
||||
{
|
||||
int nMod = GetEffectInteger(eEffect, 0);
|
||||
int nType = GetEffectInteger(eEffect, 1);
|
||||
nShieldBonus += GetEffectInteger(eEffect, 0);
|
||||
string s = "Found AC effect: bonus = " + IntToString(nMod) + ", type = " + IntToString(nType);
|
||||
SendMessageToPC(GetFirstPC(), s);
|
||||
}
|
||||
eEffect = GetNextEffect(oCreature);
|
||||
}
|
||||
|
||||
return nShieldBonus;
|
||||
}*/
|
||||
//
|
||||
//:: Handles psuedo-Foritifcation
|
||||
void DoFortification(object oPC = OBJECT_SELF, int nFortification = 25)
|
||||
{
|
||||
@@ -2275,7 +2384,7 @@ void DoFortification(object oPC = OBJECT_SELF, int nFortification = 25)
|
||||
IPSafeAddItemProperty(oHide, ItemPropertyImmunityMisc(IP_CONST_IMMUNITYMISC_BACKSTAB));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// wrapper for DecrementRemainingSpellUses, works for newspellbook 'fake' spells too
|
||||
// should also find and decrement metamagics for newspellbooks
|
||||
|
||||
@@ -70,6 +70,8 @@
|
||||
43 PRC_CRAFTING_BASE_ITEMS int 1
|
||||
44 PRC_XP_USE_SIMPLE_LA int 1
|
||||
45 PRC_XP_USE_SIMPLE_RACIAL_HD int 1
|
||||
46 PRC_CREATE_INFUSION_CASTER_LEVEL int 1
|
||||
47 PRC_CREATE_INFUSION_OPTIONAL_HERBS int 0
|
||||
*/
|
||||
|
||||
/* This variable MUST be updated with every new version of the PRC!!! */
|
||||
@@ -1952,6 +1954,18 @@ const string PRC_CRAFT_ROD_CASTER_LEVEL = "PRC_CRAFT_ROD_CASTER_LEVE
|
||||
*/
|
||||
const string PRC_CRAFT_STAFF_CASTER_LEVEL = "PRC_CRAFT_STAFF_CASTER_LEVEL";
|
||||
|
||||
/*
|
||||
* As above, except it applies to herbal infusions
|
||||
*/
|
||||
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
|
||||
|
||||
/*
|
||||
* Builder's Option: Enables the optional PnP herbs for creating infusions.
|
||||
* Each herb is keyed to a spell circle level & spell school as shown on pg. 33
|
||||
* of the Master's of the Wild sourcebook.
|
||||
*/
|
||||
const string PRC_CREATE_INFUSION_OPTIONAL_HERBS = "PRC_CREATE_INFUSION_OPTIONAL_HERBS";
|
||||
|
||||
/*
|
||||
* Characters with a crafting feat always have the appropriate base item in their inventory
|
||||
*/
|
||||
@@ -1961,45 +1975,52 @@ const string PRC_CRAFTING_BASE_ITEMS = "PRC_CRAFTING_BASE_ITEMS";
|
||||
* Max level of spells brewed into potions
|
||||
* defaults to 3
|
||||
*/
|
||||
const string X2_CI_BREWPOTION_MAXLEVEL = "X2_CI_BREWPOTION_MAXLEVEL";
|
||||
//const string X2_CI_BREWPOTION_MAXLEVEL = "X2_CI_BREWPOTION_MAXLEVEL";
|
||||
const string PRC_X2_BREWPOTION_MAXLEVEL = "PRC_X2_BREWPOTION_MAXLEVEL";
|
||||
|
||||
/*
|
||||
* cost modifier of spells brewed into poitions
|
||||
* defaults to 50
|
||||
*/
|
||||
const string X2_CI_BREWPOTION_COSTMODIFIER = "X2_CI_BREWPOTION_COSTMODIFIER";
|
||||
const string PRC_X2_BREWPOTION_COSTMODIFIER = "PRC_X2_BREWPOTION_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells scribed into scrolls
|
||||
* defaults to 25
|
||||
*/
|
||||
const string X2_CI_SCRIBESCROLL_COSTMODIFIER = "X2_CI_SCRIBESCROLL_COSTMODIFIER";
|
||||
const string PRC_X2_SCRIBESCROLL_COSTMODIFIER = "PRC_X2_SCRIBESCROLL_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells infused into herbs
|
||||
* defaults to 25
|
||||
*/
|
||||
const string PRC_X2_CREATEINFUSION_COSTMODIFIER = "PRC_X2_CREATEINFUSION_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* Max level of spells crafted into wands
|
||||
* defaults to 4
|
||||
*/
|
||||
const string X2_CI_CRAFTWAND_MAXLEVEL = "X2_CI_CRAFTWAND_MAXLEVEL";
|
||||
const string PRC_X2_CRAFTWAND_MAXLEVEL = "PRC_X2_CRAFTWAND_MAXLEVEL";
|
||||
|
||||
/*
|
||||
* cost modifier of spells crafted into wands
|
||||
* defaults to 750
|
||||
*/
|
||||
const string X2_CI_CRAFTWAND_COSTMODIFIER = "X2_CI_CRAFTWAND_COSTMODIFIER";
|
||||
const string PRC_X2_CRAFTWAND_COSTMODIFIER = "PRC_X2_CRAFTWAND_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells crafted into rods
|
||||
* note that adding a second spell costs 75% and 3 or more costs 50%
|
||||
* defaults to 750
|
||||
*/
|
||||
const string X2_CI_CRAFTROD_COSTMODIFIER = "X2_CI_CRAFTROD_COSTMODIFIER";
|
||||
const string PRC_X2_CRAFTROD_COSTMODIFIER = "PRC_X2_CRAFTROD_COSTMODIFIER";
|
||||
|
||||
/*
|
||||
* cost modifier of spells crafted into staffs
|
||||
* note that adding a second spell costs 75% and 3 or more costs 50%
|
||||
* defaults to 750
|
||||
*/
|
||||
const string X2_CI_CRAFTSTAFF_COSTMODIFIER = "X2_CI_CRAFTSTAFF_COSTMODIFIER";
|
||||
const string PRC_X2_CRAFTSTAFF_COSTMODIFIER = "PRC_X2_CRAFTSTAFF_COSTMODIFIER";
|
||||
|
||||
/**
|
||||
* Allows the use of arbitrary itemproperties and uses NWN item costs
|
||||
|
||||
@@ -14,17 +14,6 @@
|
||||
/* Function prototypes */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//gets the number of class levels that count for turning
|
||||
int GetTurningClassLevel(object oCaster = OBJECT_SELF, int nTurnType = SPELL_TURN_UNDEAD);
|
||||
|
||||
@@ -191,6 +180,20 @@ int GetIsTurnOrRebuke(object oTarget, int nTurnType, int nTargetRace)
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_PLANT_DEFIANCE:
|
||||
{
|
||||
if(nTargetRace == RACIAL_TYPE_PLANT)
|
||||
nReturn = ACTION_TURN;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_PLANT_CONTROL:
|
||||
{
|
||||
if(nTargetRace == RACIAL_TYPE_PLANT)
|
||||
nReturn = ACTION_REBUKE;
|
||||
|
||||
break;
|
||||
}
|
||||
case SPELL_TURN_PLANT:
|
||||
{
|
||||
// Plant domain rebukes or commands plants
|
||||
@@ -384,6 +387,13 @@ int GetTurningClassLevel(object oCaster = OBJECT_SELF, int nTurnType = SPELL_TUR
|
||||
if (nTurnType == SPELL_OPPORTUNISTIC_PIETY_TURN)
|
||||
return GetLevelByClass(CLASS_TYPE_FACTOTUM, oCaster);
|
||||
|
||||
if (nTurnType == SPELL_PLANT_DEFIANCE || nTurnType == SPELL_PLANT_CONTROL)
|
||||
{
|
||||
int nDivineLvl = GetPrCAdjustedCasterLevelByType(TYPE_DIVINE, oCaster);
|
||||
|
||||
return nDivineLvl;
|
||||
}
|
||||
|
||||
//Baelnorn & Archlich adds all class levels.
|
||||
if(GetLevelByClass(CLASS_TYPE_BAELNORN, oCaster) || GetHasFeat(FEAT_TEMPLATE_ARCHLICH_MARKER, oCaster)) //:: Archlich
|
||||
nLevel = GetHitDice(oCaster);
|
||||
|
||||
@@ -40,13 +40,31 @@ int IsProficient(object oPC, int nBaseItem)
|
||||
|
||||
case BASE_ITEM_CLUB:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_CLUB, oPC);
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_CLUB, oPC);
|
||||
|
||||
case BASE_ITEM_HEAVYCROSSBOW:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW, oPC);
|
||||
|
||||
case BASE_ITEM_LIGHTCROSSBOW:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW, oPC);
|
||||
|
||||
case BASE_ITEM_DAGGER:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DAGGER, oPC);
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DAGGER, oPC);
|
||||
|
||||
case BASE_ITEM_LONGSWORD:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_MARTIAL, oPC)
|
||||
@@ -152,7 +170,14 @@ int IsProficient(object oPC, int nBaseItem)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_ROGUE, oPC);
|
||||
|
||||
case BASE_ITEM_QUARTERSTAFF:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF, oPC)
|
||||
||GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC);
|
||||
|
||||
case BASE_ITEM_MAGICSTAFF:
|
||||
return GetHasFeat(FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF, oPC)
|
||||
||GetHasFeat(FEAT_WEAPON_PROFICIENCY_SIMPLE, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_DRUID, oPC)
|
||||
|| GetHasFeat(FEAT_WEAPON_PROFICIENCY_WIZARD, oPC);
|
||||
|
||||
@@ -295,167 +320,185 @@ int GetWeaponProfFeatByType(int nBaseType)
|
||||
{
|
||||
switch(nBaseType)
|
||||
{
|
||||
case BASE_ITEM_SHORTSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
|
||||
case BASE_ITEM_CLUB:
|
||||
return FEAT_WEAPON_PROFICIENCY_CLUB;
|
||||
|
||||
case BASE_ITEM_LONGSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_LONGSWORD;
|
||||
case BASE_ITEM_QUARTERSTAFF:
|
||||
return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
|
||||
|
||||
case BASE_ITEM_BATTLEAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
|
||||
case BASE_ITEM_MAGICSTAFF:
|
||||
return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
|
||||
|
||||
case BASE_ITEM_BASTARDSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
|
||||
case BASE_ITEM_DAGGER:
|
||||
return FEAT_WEAPON_PROFICIENCY_DAGGER;
|
||||
|
||||
case BASE_ITEM_LIGHTFLAIL:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
|
||||
case BASE_ITEM_HEAVYCROSSBOW:
|
||||
return FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW;
|
||||
|
||||
case BASE_ITEM_WARHAMMER:
|
||||
return FEAT_WEAPON_PROFICIENCY_WARHAMMER;
|
||||
case BASE_ITEM_LIGHTCROSSBOW:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW;
|
||||
|
||||
case BASE_ITEM_LONGBOW:
|
||||
return FEAT_WEAPON_PROFICIENCY_LONGBOW;
|
||||
case BASE_ITEM_SHORTSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
|
||||
|
||||
case BASE_ITEM_LIGHTMACE:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
|
||||
case BASE_ITEM_LONGSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_LONGSWORD;
|
||||
|
||||
case BASE_ITEM_HALBERD:
|
||||
return FEAT_WEAPON_PROFICIENCY_HALBERD;
|
||||
case BASE_ITEM_BATTLEAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
|
||||
|
||||
case BASE_ITEM_SHORTBOW:
|
||||
case BASE_ITEM_BASTARDSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
|
||||
|
||||
case BASE_ITEM_LIGHTFLAIL:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
|
||||
|
||||
case BASE_ITEM_WARHAMMER:
|
||||
return FEAT_WEAPON_PROFICIENCY_WARHAMMER;
|
||||
|
||||
case BASE_ITEM_LONGBOW:
|
||||
return FEAT_WEAPON_PROFICIENCY_LONGBOW;
|
||||
|
||||
case BASE_ITEM_LIGHTMACE:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
|
||||
|
||||
case BASE_ITEM_HALBERD:
|
||||
return FEAT_WEAPON_PROFICIENCY_HALBERD;
|
||||
|
||||
case BASE_ITEM_SHORTBOW:
|
||||
return FEAT_WEAPON_PROFICIENCY_SHORTBOW;
|
||||
|
||||
case BASE_ITEM_TWOBLADEDSWORD:
|
||||
case BASE_ITEM_TWOBLADEDSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD;
|
||||
|
||||
case BASE_ITEM_GREATSWORD:
|
||||
case BASE_ITEM_GREATSWORD:
|
||||
return FEAT_WEAPON_PROFICIENCY_GREATSWORD;
|
||||
|
||||
case BASE_ITEM_GREATAXE:
|
||||
case BASE_ITEM_GREATAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_GREATAXE;
|
||||
|
||||
case BASE_ITEM_DART:
|
||||
case BASE_ITEM_DART:
|
||||
return FEAT_WEAPON_PROFICIENCY_DART;
|
||||
|
||||
case BASE_ITEM_DIREMACE:
|
||||
case BASE_ITEM_DIREMACE:
|
||||
return FEAT_WEAPON_PROFICIENCY_DIRE_MACE;
|
||||
|
||||
case BASE_ITEM_DOUBLEAXE:
|
||||
case BASE_ITEM_DOUBLEAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE;
|
||||
|
||||
case BASE_ITEM_HEAVYFLAIL:
|
||||
case BASE_ITEM_HEAVYFLAIL:
|
||||
return FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL;
|
||||
|
||||
case BASE_ITEM_LIGHTHAMMER:
|
||||
case BASE_ITEM_LIGHTHAMMER:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER;
|
||||
|
||||
case BASE_ITEM_HANDAXE:
|
||||
case BASE_ITEM_HANDAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_HANDAXE;
|
||||
|
||||
case BASE_ITEM_KAMA:
|
||||
case BASE_ITEM_KAMA:
|
||||
return FEAT_WEAPON_PROFICIENCY_KAMA;
|
||||
|
||||
case BASE_ITEM_KATANA:
|
||||
case BASE_ITEM_KATANA:
|
||||
return FEAT_WEAPON_PROFICIENCY_KATANA;
|
||||
|
||||
case BASE_ITEM_KUKRI:
|
||||
case BASE_ITEM_KUKRI:
|
||||
return FEAT_WEAPON_PROFICIENCY_KUKRI;
|
||||
|
||||
case BASE_ITEM_MORNINGSTAR:
|
||||
case BASE_ITEM_MORNINGSTAR:
|
||||
return FEAT_WEAPON_PROFICIENCY_MORNINGSTAR;
|
||||
|
||||
case BASE_ITEM_RAPIER:
|
||||
case BASE_ITEM_RAPIER:
|
||||
return FEAT_WEAPON_PROFICIENCY_RAPIER;
|
||||
|
||||
case BASE_ITEM_SCIMITAR:
|
||||
case BASE_ITEM_SCIMITAR:
|
||||
return FEAT_WEAPON_PROFICIENCY_SCIMITAR;
|
||||
|
||||
case BASE_ITEM_SCYTHE:
|
||||
case BASE_ITEM_SCYTHE:
|
||||
return FEAT_WEAPON_PROFICIENCY_SCYTHE;
|
||||
|
||||
case BASE_ITEM_SHORTSPEAR:
|
||||
case BASE_ITEM_SHORTSPEAR:
|
||||
return FEAT_WEAPON_PROFICIENCY_SHORTSPEAR;
|
||||
|
||||
case BASE_ITEM_SHURIKEN:
|
||||
case BASE_ITEM_SHURIKEN:
|
||||
return FEAT_WEAPON_PROFICIENCY_SHURIKEN;
|
||||
|
||||
case BASE_ITEM_SICKLE:
|
||||
case BASE_ITEM_SICKLE:
|
||||
return FEAT_WEAPON_PROFICIENCY_SICKLE;
|
||||
|
||||
case BASE_ITEM_SLING:
|
||||
case BASE_ITEM_SLING:
|
||||
return FEAT_WEAPON_PROFICIENCY_SLING;
|
||||
|
||||
case BASE_ITEM_THROWINGAXE:
|
||||
case BASE_ITEM_THROWINGAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_THROWING_AXE;
|
||||
|
||||
case BASE_ITEM_CSLASHWEAPON:
|
||||
case BASE_ITEM_CSLASHWEAPON:
|
||||
return FEAT_WEAPON_PROFICIENCY_CREATURE;
|
||||
|
||||
case BASE_ITEM_CPIERCWEAPON:
|
||||
case BASE_ITEM_CPIERCWEAPON:
|
||||
return FEAT_WEAPON_PROFICIENCY_CREATURE;
|
||||
|
||||
case BASE_ITEM_CBLUDGWEAPON:
|
||||
case BASE_ITEM_CBLUDGWEAPON:
|
||||
return FEAT_WEAPON_PROFICIENCY_CREATURE;
|
||||
|
||||
case BASE_ITEM_CSLSHPRCWEAP:
|
||||
case BASE_ITEM_CSLSHPRCWEAP:
|
||||
return FEAT_WEAPON_PROFICIENCY_CREATURE;
|
||||
|
||||
case BASE_ITEM_TRIDENT:
|
||||
case BASE_ITEM_TRIDENT:
|
||||
return FEAT_WEAPON_PROFICIENCY_TRIDENT;
|
||||
|
||||
case BASE_ITEM_DWARVENWARAXE:
|
||||
case BASE_ITEM_DWARVENWARAXE:
|
||||
return FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE;
|
||||
|
||||
case BASE_ITEM_WHIP:
|
||||
case BASE_ITEM_WHIP:
|
||||
return FEAT_WEAPON_PROFICIENCY_WHIP;
|
||||
|
||||
case BASE_ITEM_ELVEN_LIGHTBLADE:
|
||||
case BASE_ITEM_ELVEN_LIGHTBLADE:
|
||||
return FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE;
|
||||
|
||||
case BASE_ITEM_ELVEN_THINBLADE:
|
||||
case BASE_ITEM_ELVEN_THINBLADE:
|
||||
return FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE;
|
||||
|
||||
case BASE_ITEM_ELVEN_COURTBLADE:
|
||||
case BASE_ITEM_ELVEN_COURTBLADE:
|
||||
return FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE;
|
||||
|
||||
case BASE_ITEM_HEAVY_PICK:
|
||||
case BASE_ITEM_HEAVY_PICK:
|
||||
return FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
|
||||
|
||||
case BASE_ITEM_LIGHT_PICK:
|
||||
case BASE_ITEM_LIGHT_PICK:
|
||||
return FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
|
||||
|
||||
case BASE_ITEM_SAI:
|
||||
case BASE_ITEM_SAI:
|
||||
return FEAT_WEAPON_PROFICIENCY_SAI;
|
||||
|
||||
case BASE_ITEM_NUNCHAKU:
|
||||
case BASE_ITEM_NUNCHAKU:
|
||||
return FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
|
||||
|
||||
case BASE_ITEM_FALCHION:
|
||||
case BASE_ITEM_FALCHION:
|
||||
return FEAT_WEAPON_PROFICIENCY_FALCHION;
|
||||
|
||||
case BASE_ITEM_SAP:
|
||||
case BASE_ITEM_SAP:
|
||||
return FEAT_WEAPON_PROFICIENCY_SAP;
|
||||
|
||||
case BASE_ITEM_KATAR:
|
||||
case BASE_ITEM_KATAR:
|
||||
return FEAT_WEAPON_PROFICIENCY_KATAR;
|
||||
|
||||
case BASE_ITEM_HEAVY_MACE:
|
||||
case BASE_ITEM_HEAVY_MACE:
|
||||
return FEAT_WEAPON_PROFICIENCY_HEAVY_MACE;
|
||||
|
||||
case BASE_ITEM_MAUL:
|
||||
case BASE_ITEM_MAUL:
|
||||
return FEAT_WEAPON_PROFICIENCY_MAUL;
|
||||
|
||||
case BASE_ITEM_DOUBLE_SCIMITAR:
|
||||
case BASE_ITEM_DOUBLE_SCIMITAR:
|
||||
return FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR;
|
||||
|
||||
case BASE_ITEM_GOAD:
|
||||
case BASE_ITEM_GOAD:
|
||||
return FEAT_WEAPON_PROFICIENCY_GOAD;
|
||||
|
||||
case BASE_ITEM_EAGLE_CLAW:
|
||||
case BASE_ITEM_EAGLE_CLAW:
|
||||
return FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW;
|
||||
|
||||
default:
|
||||
return FEAT_WEAPON_PROFICIENCY_SIMPLE;
|
||||
default:
|
||||
return FEAT_WEAPON_PROFICIENCY_SIMPLE;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -1206,11 +1206,12 @@ const int IP_CONST_FEAT_REGENERATION_5 = 24820;
|
||||
const int IP_CONST_FEAT_SCENT = 24821;
|
||||
const int IP_CONST_FEAT_GIANT_RACIAL_TYPE = 24822;
|
||||
|
||||
const int IP_CONST_FEAT_TEMPLATE_ARCHLICH_MARKER = 16401; //:: Archlich
|
||||
const int IP_CONST_FEAT_TEMPLATE_TURN_UNDEAD = 16402;
|
||||
const int IP_CONST_FEAT_TEMPLATE_PROJECTION = 24823;
|
||||
const int IP_CONST_FEAT_TEMPLATE_END_PROJECTION = 24824;
|
||||
const int IP_CONST_FEAT_TEMPLATE_ANIMATE_DEAD = 24825;
|
||||
const int IP_CONST_FEAT_TEMPLATE_ARCHLICH_MARKER = 16401; //:: Archlich
|
||||
const int IP_CONST_FEAT_TEMPLATE_TURN_UNDEAD = 16402;
|
||||
const int IP_CONST_FEAT_TEMPLATE_BAELNORN_MARKER = 16409; //:: Baelnorn
|
||||
const int IP_CONST_FEAT_TEMPLATE_PROJECTION = 24823;
|
||||
const int IP_CONST_FEAT_TEMPLATE_END_PROJECTION = 24824;
|
||||
const int IP_CONST_FEAT_TEMPLATE_ANIMATE_DEAD = 24825;
|
||||
const int IP_CONST_FEAT_TEMPLATE_SAINT_SLA_BLESS = 16403; //:: Saint
|
||||
//const int IP_CONST_FEAT_TEMPLATE_SAINT_SLA_GUIDANCE = 16404;
|
||||
const int IP_CONST_FEAT_TEMPLATE_SAINT_SLA_RESISTANCE = 16405;
|
||||
|
||||
@@ -29,6 +29,10 @@ const int BASE_ITEM_CRAFTED_STAFF = 201;
|
||||
const int BASE_ITEM_ELVEN_LIGHTBLADE = 202;
|
||||
const int BASE_ITEM_ELVEN_THINBLADE = 203;
|
||||
const int BASE_ITEM_ELVEN_COURTBLADE = 204;
|
||||
const int BASE_ITEM_CRAFT_SCEPTER = 249;
|
||||
const int BASE_ITEM_MAGIC_SCEPTER = 250;
|
||||
const int BASE_ITEM_MUNDANE_HERB = 252;
|
||||
const int BASE_ITEM_INFUSED_HERB = 253;
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Player Health Const
|
||||
|
||||
530
src/include/prc_nui_com_inc.nss
Normal file
530
src/include/prc_nui_com_inc.nss
Normal file
@@ -0,0 +1,530 @@
|
||||
#include "prc_nui_consts"
|
||||
#include "inc_newspellbook"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "nw_inc_nui"
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
// Gets the current spell level the class can achieve at the current
|
||||
// caster level (ranging from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
// nLevel:int the caster level
|
||||
//
|
||||
// Returns:
|
||||
// int the circle the class can achieve currently
|
||||
//
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||
|
||||
//
|
||||
// GetMaxSpellLevel
|
||||
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest circle that can be achieved
|
||||
//
|
||||
int GetMaxSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetMinSpellLevel
|
||||
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the lowest circle that can be achieved
|
||||
//
|
||||
int GetMinSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetHighestLevelPossibleInClass
|
||||
// Given a class Id this will determine what the max level of a class can be
|
||||
// achieved
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest possible level the class can achieve
|
||||
//
|
||||
int GetHighestLevelPossibleInClass(int nClass);
|
||||
|
||||
//
|
||||
// GetClassSpellbookFile
|
||||
// Gets the class 2da spellbook/ability for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the classID
|
||||
//
|
||||
// Returns:
|
||||
// string the 2da file name for the spell/abilities of the ClassID
|
||||
//
|
||||
string GetClassSpellbookFile(int nClass);
|
||||
|
||||
//
|
||||
// GetBinderSpellToFeatDictionary
|
||||
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||
// to their feat. This is constructed based off the binder's known location of
|
||||
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||
// this it will be saved to the player locally as a cached result since we do
|
||||
// not need to call this again.
|
||||
//
|
||||
// Argument:
|
||||
// oPlayer:object the player
|
||||
//
|
||||
// Returns:
|
||||
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||
// and the FeatID of a vestige ability
|
||||
//
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// GetSpellLevelIcon
|
||||
// Takes the spell circle int and gets the icon appropriate for it (i.e. 0 turns
|
||||
// into "ir_cantrips"
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level icon
|
||||
//
|
||||
string GetSpellLevelIcon(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellLevelToolTip
|
||||
// Gets the spell level tool tip text based on the int spell level provided (i.e.
|
||||
// 0 turns into "Cantrips")
|
||||
//
|
||||
// Arguments:
|
||||
// spellLevel:int the spell level we want the tooltip for
|
||||
//
|
||||
// Returns:
|
||||
// string the spell level toop tip
|
||||
//
|
||||
string GetSpellLevelToolTip(int spellLevel);
|
||||
|
||||
//
|
||||
// GetSpellIcon
|
||||
// Gets the spell icon based off the spellId, or featId supplied
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the class Id
|
||||
// featId:int the featId we can use the icon for
|
||||
// spellId:int the spell Id we want the icon for
|
||||
//
|
||||
// Returns:
|
||||
// json:String the string of the icon we want.
|
||||
//
|
||||
json GetSpellIcon(int spellId, int featId=0, int nClass=0);
|
||||
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0);
|
||||
|
||||
//
|
||||
// GreyOutButton
|
||||
// Takes NUI Button along with it's width and height and greys it out it with a drawn
|
||||
// colored rectangle to represent it's not been selected or not valid.
|
||||
//
|
||||
// Arguments:
|
||||
// jButton:json the NUI Button
|
||||
// w:float the width of the button
|
||||
// h:float the height of the button
|
||||
//
|
||||
// Returns:
|
||||
// json the NUI button greyed out
|
||||
//
|
||||
json GreyOutButton(json jButton, float w, float h);
|
||||
|
||||
//
|
||||
// CreateGreyOutRectangle
|
||||
// Creates a grey out rectangle for buttons
|
||||
//
|
||||
// Arguments:
|
||||
// w:float the width of the button
|
||||
// h:float the height of the button
|
||||
//
|
||||
// Returns:
|
||||
// json the transparant black rectangle
|
||||
//
|
||||
json CreateGreyOutRectangle(float w, float h);
|
||||
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
|
||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
int currentLevel = nLevel;
|
||||
|
||||
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||
if(nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
||||
// Binders don't really have a concept of spell level
|
||||
if (nClass == CLASS_TYPE_BINDER
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||
return 1;
|
||||
|
||||
//Shadowsmith has no concept of spell levels
|
||||
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
return 2;
|
||||
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
return 4;
|
||||
|
||||
// Spont casters have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
|
||||
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||
|
||||
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||
|
||||
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||
|
||||
// in case we somehow go over bounds just don't :)
|
||||
if (currentLevel >= totalLevel)
|
||||
currentLevel = totalLevel - 1;
|
||||
|
||||
//Psionics have MaxPowerLevel as their column name
|
||||
string columnName = "MaxPowerLevel";
|
||||
|
||||
//Invokers have MaxInvocationLevel
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
columnName = "MaxInvocationLevel";
|
||||
|
||||
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
columnName = "EvolvingMind";
|
||||
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
columnName = "VestigeLvl";
|
||||
spellLevel2da = "cls_bind_binder";
|
||||
}
|
||||
|
||||
// ToB doesn't have a concept of this, but we don't care.
|
||||
|
||||
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMinSpellLevel(int nClass)
|
||||
{
|
||||
// again sponts have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_BINDER)
|
||||
return 1;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMaxSpellLevel(int nClass)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSION)
|
||||
return 9;
|
||||
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
return 5;
|
||||
if (nClass == CLASS_TYPE_PSYWAR)
|
||||
return 6;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
|
||||
int GetHighestLevelPossibleInClass(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
|
||||
//sponts have their spells in the classes.2da
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
sFile = GetAMSKnownFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "cls_bind_binder";
|
||||
}
|
||||
}
|
||||
|
||||
return Get2DARowCount(sFile);
|
||||
}
|
||||
|
||||
string GetClassSpellbookFile(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
// Spontaneous casters use a specific file name structure
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = GetFileForClass(nClass);
|
||||
}
|
||||
// everyone else uses this structure
|
||||
else
|
||||
{
|
||||
sFile = GetAMSDefinitionFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "vestiges";
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
string GetSpellLevelIcon(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "ir_cantrips";
|
||||
case 1: return "ir_level1";
|
||||
case 2: return "ir_level2";
|
||||
case 3: return "ir_level3";
|
||||
case 4: return "ir_level4";
|
||||
case 5: return "ir_level5";
|
||||
case 6: return "ir_level6";
|
||||
case 7: return "ir_level789";
|
||||
case 8: return "ir_level789";
|
||||
case 9: return "ir_level789";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
string GetSpellLevelToolTip(int spellLevel)
|
||||
{
|
||||
switch (spellLevel)
|
||||
{
|
||||
case 0: return "Cantrips";
|
||||
case 1: return "Level 1";
|
||||
case 2: return "Level 2";
|
||||
case 3: return "Level 3";
|
||||
case 4: return "Level 4";
|
||||
case 5: return "Level 5";
|
||||
case 6: return "Level 6";
|
||||
case 7: return "Level 7";
|
||||
case 8: return "Level 8";
|
||||
case 9: return "Level 9";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
json GetSpellIcon(int spellId,int featId=0,int nClass=0)
|
||||
{
|
||||
// Binder's spells don't have the FeatID on the spells.2da, so we have to use
|
||||
// the mapping we constructed to get it.
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
json binderDict = GetBinderSpellToFeatDictionary();
|
||||
int nFeatID = JsonGetInt(JsonObjectGet(binderDict, IntToString(spellId)));
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
}
|
||||
|
||||
if (featId)
|
||||
return JsonString(Get2DACache("feat", "Icon", featId));
|
||||
|
||||
int masterSpellID = StringToInt(Get2DACache("spells", "Master", spellId));
|
||||
|
||||
// if this is a sub radial spell, then we use spell's icon instead
|
||||
if (masterSpellID)
|
||||
return JsonString(Get2DACache("spells", "IconResRef", spellId));
|
||||
|
||||
// the FeatID holds the accurate spell icon, not the SpellID
|
||||
int nFeatID = StringToInt(Get2DACache("spells", "FeatID", spellId));
|
||||
|
||||
return JsonString(Get2DACache("feat", "Icon", nFeatID));
|
||||
}
|
||||
|
||||
string GetSpellName(int spellId, int realSpellID=0, int featId=0, int nClass=0)
|
||||
{
|
||||
if ((nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER) && spellId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
if (nClass == CLASS_TYPE_TRUENAMER && featId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||
if (realSpellID)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", realSpellID)));
|
||||
if (spellId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
if (featId)
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("feat", "FEAT", featId)));
|
||||
|
||||
return GetStringByStrRef(StringToInt(Get2DACache("spells", "Name", spellId)));
|
||||
}
|
||||
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
// a dictionary of <SpellID, FeatID>
|
||||
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||
// if this hasn't been created, create it now.
|
||||
if (binderDict == JsonNull())
|
||||
binderDict = JsonObject();
|
||||
else
|
||||
return binderDict;
|
||||
|
||||
// the starting row for binder spells
|
||||
int spellIndex = 19070;
|
||||
// the starting row for binder feats
|
||||
int featIndex = 9030;
|
||||
//the end of the binder spells/feats
|
||||
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||
{
|
||||
// get the SpellID tied to the feat
|
||||
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||
// if the spellID matches the current index, then this is the spell
|
||||
// attached to the feat
|
||||
if (spellID == spellIndex)
|
||||
{
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||
|
||||
// move to next spell/feat
|
||||
featIndex++;
|
||||
spellIndex++;
|
||||
}
|
||||
// else we have reached a subdial spell
|
||||
else
|
||||
{
|
||||
// loop through until we reach back at spellID
|
||||
while (spellIndex < spellID)
|
||||
{
|
||||
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||
|
||||
// add the sub radial to the dict, tied to the master's FeatID
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||
|
||||
spellIndex++;
|
||||
}
|
||||
|
||||
|
||||
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||
// if it happens then move on
|
||||
if (spellIndex > spellID)
|
||||
featIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the result
|
||||
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||
return binderDict;
|
||||
}
|
||||
|
||||
json GreyOutButton(json jButton, float w, float h)
|
||||
{
|
||||
json retValue = jButton;
|
||||
|
||||
json jBorders = JsonArray();
|
||||
jBorders = JsonArrayInsert(jBorders, CreateGreyOutRectangle(w, h));
|
||||
|
||||
return NuiDrawList(jButton, JsonBool(FALSE), jBorders);
|
||||
}
|
||||
|
||||
json CreateGreyOutRectangle(float w, float h)
|
||||
{
|
||||
// set the points of the button shape
|
||||
json jPoints = JsonArray();
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(h));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(w));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
jPoints = JsonArrayInsert(jPoints, JsonFloat(0.0));
|
||||
|
||||
return NuiDrawListPolyLine(JsonBool(TRUE), NuiColor(0, 0, 0, 127), JsonBool(TRUE), JsonFloat(2.0), jPoints);
|
||||
}
|
||||
|
||||
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0)
|
||||
{
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR, featID);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR, spellId);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR, realSpellId);
|
||||
SetLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR, nClass);
|
||||
ExecuteScript("prc_nui_dsc_view", oPlayer);
|
||||
}
|
||||
|
||||
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_FEATID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_SPELLID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR);
|
||||
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
|
||||
}
|
||||
|
||||
@@ -111,3 +111,48 @@ const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
|
||||
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
|
||||
// Right Button Enabled Bind for Power Attack NUI
|
||||
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// //
|
||||
// NUI Level Up //
|
||||
// //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const string NUI_LEVEL_UP_WINDOW_ID = "prcLevelUpNui";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID = "NuiLevelUpCircleButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_BUTTON_BASEID = "NuiLevelUpSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID = "NuiLevelUpChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_DONE_BUTTON = "NuiLevelUpDoneButton";
|
||||
const string NUI_LEVEL_UP_RESET_BUTTON = "NuiLevelUpResetButton";
|
||||
|
||||
const string NUI_LEVEL_UP_SELECTED_CLASS_VAR = "NUILevelUpSelectedClass";
|
||||
const string NUI_LEVEL_UP_SELECTED_CIRCLE_VAR = "NUILevelUpSelectedCircle";
|
||||
const string NUI_LEVEL_UP_KNOWN_SPELLS_VAR = "NUILevelUpKnownSpells";
|
||||
const string NUI_LEVEL_UP_CHOSEN_SPELLS_VAR = "NUILevelUpChosenSpells";
|
||||
const string NUI_LEVEL_UP_EXPANDED_KNOW_LIST_VAR = "NUILevelUpExpKnowList";
|
||||
const string NUI_LEVEL_UP_POWER_LIST_VAR = "NUILevelUpPowerList";
|
||||
const string NUI_LEVEL_UP_DISCIPLINE_INFO_VAR = "GetDisciplineInfoObjectCache_";
|
||||
const string NUI_LEVEL_UP_SPELLID_LIST_VAR = "NUILevelUpSpellIDList_";
|
||||
const string NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR = "NUIRemainingChoicesCache";
|
||||
const string NUI_LEVEL_UP_RELEARN_LIST_VAR = "NUILevelUpRelearnList";
|
||||
const string NUI_LEVEL_UP_ARCHIVIST_NEW_SPELLS_LIST_VAR = "NUILevelUpArchivistNewSpellsList";
|
||||
|
||||
const string NUI_LEVEL_UP_EXPANDED_CHOICES_VAR = "NUIExpandedChoices";
|
||||
const string NUI_LEVEL_UP_EPIC_EXPANDED_CHOICES_VAR = "NUIEpicExpandedChoices";
|
||||
|
||||
const int NUI_LEVEL_UP_MANEUVER_PREREQ_LIMIT = 6;
|
||||
|
||||
const string NUI_LEVEL_UP_MANEUVER_TOTAL = "ManeuverTotal";
|
||||
const string NUI_LEVEL_UP_STANCE_TOTAL = "StanceTotal";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELLBOOK_OBJECT_CACHE_VAR = "GetSpellListObjectCache_";
|
||||
const string NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR = "GetInvokerKnownListObjectCache_";
|
||||
|
||||
const string NUI_SPELL_DESCRIPTION_FEATID_VAR = "NUISpellDescriptionFeatID";
|
||||
const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
|
||||
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
|
||||
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
|
||||
|
||||
|
||||
3339
src/include/prc_nui_lv_inc.nss
Normal file
3339
src/include/prc_nui_lv_inc.nss
Normal file
File diff suppressed because it is too large
Load Diff
@@ -10,10 +10,8 @@
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 24.05.2005
|
||||
//:://////////////////////////////////////////////
|
||||
#include "inc_newspellbook"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "prc_nui_consts"
|
||||
|
||||
#include "prc_nui_com_inc"
|
||||
|
||||
//
|
||||
// GetSpellListForCircle
|
||||
@@ -43,69 +41,6 @@ json GetSpellListForCircle(object oPlayer, int nClass, int circle);
|
||||
//
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer);
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
// Gets the current spell level the class can achieve at the current
|
||||
// caster level (ranging from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
// nLevel:int the caster level
|
||||
//
|
||||
// Returns:
|
||||
// int the circle the class can achieve currently
|
||||
//
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||
|
||||
//
|
||||
// GetMaxSpellLevel
|
||||
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest circle that can be achieved
|
||||
//
|
||||
int GetMaxSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetMinSpellLevel
|
||||
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the lowest circle that can be achieved
|
||||
//
|
||||
int GetMinSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetHighestLevelPossibleInClass
|
||||
// Given a class Id this will determine what the max level of a class can be
|
||||
// achieved
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest possible level the class can achieve
|
||||
//
|
||||
int GetHighestLevelPossibleInClass(int nClass);
|
||||
|
||||
//
|
||||
// GetClassSpellbookFile
|
||||
// Gets the class 2da spellbook/ability for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the classID
|
||||
//
|
||||
// Returns:
|
||||
// string the 2da file name for the spell/abilities of the ClassID
|
||||
//
|
||||
string GetClassSpellbookFile(int nClass);
|
||||
|
||||
//
|
||||
// IsSpellKnown
|
||||
// Returns whether the player with the given class, spell file, and spellbook id
|
||||
@@ -234,23 +169,6 @@ json GetMetaMysteryFeatList();
|
||||
//
|
||||
int GetTrueClassIfRHD(object oPlayer, int nClass);
|
||||
|
||||
//
|
||||
// GetBinderSpellToFeatDictionary
|
||||
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||
// to their feat. This is constructed based off the binder's known location of
|
||||
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||
// this it will be saved to the player locally as a cached result since we do
|
||||
// not need to call this again.
|
||||
//
|
||||
// Argument:
|
||||
// oPlayer:object the player
|
||||
//
|
||||
// Returns:
|
||||
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||
// and the FeatID of a vestige ability
|
||||
//
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// ShouldAddSpell
|
||||
// Given a spellId and a class, determines if the spell should be added to the
|
||||
@@ -318,6 +236,18 @@ json GetInvokerEssenceSpellList(int nClass, object oPlayer=OBJECT_SELF);
|
||||
//
|
||||
int JsonArrayContainsInt(json list, int item);
|
||||
|
||||
//
|
||||
// IsSpellbookNUIOpen
|
||||
// Checks to see if the Spellbook NUI is open on a given player.
|
||||
//
|
||||
// Arguments:
|
||||
// oPC:object the player
|
||||
//
|
||||
// Returns:
|
||||
// int:Boolean TRUE if window is open, FALSE otherwise
|
||||
//
|
||||
int IsSpellbookNUIOpen(object oPC);
|
||||
|
||||
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@@ -397,86 +327,6 @@ int ShouldAddSpell(int nClass, int spellId, object oPlayer=OBJECT_SELF)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
// a dictionary of <SpellID, FeatID>
|
||||
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||
// if this hasn't been created, create it now.
|
||||
if (binderDict == JsonNull())
|
||||
binderDict = JsonObject();
|
||||
else
|
||||
return binderDict;
|
||||
|
||||
// the starting row for binder spells
|
||||
int spellIndex = 19070;
|
||||
// the starting row for binder feats
|
||||
int featIndex = 9030;
|
||||
//the end of the binder spells/feats
|
||||
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||
{
|
||||
// get the SpellID tied to the feat
|
||||
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||
// if the spellID matches the current index, then this is the spell
|
||||
// attached to the feat
|
||||
if (spellID == spellIndex)
|
||||
{
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||
|
||||
// move to next spell/feat
|
||||
featIndex++;
|
||||
spellIndex++;
|
||||
}
|
||||
// else we have reached a subdial spell
|
||||
else
|
||||
{
|
||||
// loop through until we reach back at spellID
|
||||
while (spellIndex < spellID)
|
||||
{
|
||||
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||
|
||||
// add the sub radial to the dict, tied to the master's FeatID
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||
|
||||
spellIndex++;
|
||||
}
|
||||
|
||||
|
||||
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||
// if it happens then move on
|
||||
if (spellIndex > spellID)
|
||||
featIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the result
|
||||
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||
return binderDict;
|
||||
}
|
||||
|
||||
string GetClassSpellbookFile(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
// Spontaneous casters use a specific file name structure
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = GetFileForClass(nClass);
|
||||
}
|
||||
// everyone else uses this structure
|
||||
else
|
||||
{
|
||||
sFile = GetAMSDefinitionFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "vestiges";
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@@ -526,167 +376,6 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
int currentLevel = nLevel;
|
||||
|
||||
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||
if(nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
||||
// Binders don't really have a concept of spell level
|
||||
if (nClass == CLASS_TYPE_BINDER
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||
return 1;
|
||||
|
||||
//Shadowsmith has no concept of spell levels
|
||||
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
return 2;
|
||||
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
return 4;
|
||||
|
||||
// Spont casters have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
|
||||
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||
|
||||
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||
|
||||
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||
|
||||
// in case we somehow go over bounds just don't :)
|
||||
if (currentLevel >= totalLevel)
|
||||
currentLevel = totalLevel - 1;
|
||||
|
||||
//Psionics have MaxPowerLevel as their column name
|
||||
string columnName = "MaxPowerLevel";
|
||||
|
||||
//Invokers have MaxInvocationLevel
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
columnName = "MaxInvocationLevel";
|
||||
|
||||
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
columnName = "EvolvingMind";
|
||||
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
columnName = "VestigeLvl";
|
||||
spellLevel2da = "cls_bind_binder";
|
||||
}
|
||||
|
||||
// ToB doesn't have a concept of this, but we don't care.
|
||||
|
||||
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMinSpellLevel(int nClass)
|
||||
{
|
||||
// again sponts have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_BINDER)
|
||||
return 1;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMaxSpellLevel(int nClass)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSION)
|
||||
return 9;
|
||||
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
return 5;
|
||||
if (nClass == CLASS_TYPE_PSYWAR)
|
||||
return 6;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
|
||||
int GetHighestLevelPossibleInClass(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
|
||||
//sponts have their spells in the classes.2da
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
sFile = GetAMSKnownFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "cls_bind_binder";
|
||||
}
|
||||
}
|
||||
|
||||
return Get2DARowCount(sFile);
|
||||
}
|
||||
|
||||
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||
{
|
||||
// This controls who can use the Spellbook NUI, if for some reason you don't
|
||||
@@ -698,8 +387,7 @@ int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||
return TRUE;
|
||||
|
||||
// Arcane Spont
|
||||
if (nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
if (nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
|| nClass == CLASS_TYPE_DUSKBLADE
|
||||
@@ -817,8 +505,7 @@ int CanClassUseMetamagicFeats(int nClass)
|
||||
// I don't want to spend the time looping through each class's
|
||||
// feat 2da so this is the list of all classes that are allowed to use the
|
||||
// Spellbook NUI and can use Metamagic
|
||||
return (nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BARD
|
||||
return (nClass == CLASS_TYPE_BARD
|
||||
|| nClass == CLASS_TYPE_SORCERER
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
@@ -838,7 +525,6 @@ int CanClassUseSuddenMetamagicFeats(int nClass)
|
||||
// Spellbook NUI and can use Sudden Metamagic
|
||||
return (nClass == CLASS_TYPE_SHADOWLORD
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST
|
||||
|| nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BARD
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
@@ -1146,3 +832,14 @@ int JsonArrayContainsInt(json list, int item)
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int IsSpellbookNUIOpen(object oPC)
|
||||
{
|
||||
int nPreviousToken = NuiFindWindow(oPC, PRC_SPELLBOOK_NUI_WINDOW_ID);
|
||||
if (nPreviousToken != 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: PRC Spellbook Description NUI
|
||||
//:: prc_nui_scd_inc
|
||||
//:: prc_nui_sbd_inc
|
||||
//:://////////////////////////////////////////////
|
||||
/*
|
||||
This is the view for the Spell Description NUI
|
||||
@@ -22,6 +22,9 @@ const int SPELL_BCM_RENDING_CLAWS = 17997;
|
||||
//:: Complete Warrior
|
||||
const int SPELL_RANGED_DISARM = 3493;
|
||||
|
||||
//:: Tome of Battle
|
||||
const int SPELL_TOB_SNAP_KICK = 3794;
|
||||
|
||||
//marshal
|
||||
const int SPELL_MINAUR_DEMFORT = 3500;
|
||||
const int SPELL_MINAUR_FORCEWILL = 3501;
|
||||
@@ -1289,6 +1292,69 @@ const int SPELL_SUMMON_CREATURE_IX_WATER = 3200;
|
||||
//:: Player's Handbook Spells
|
||||
const int SPELL_SPIRITUAL_WEAPON = 17249;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1 = 17000;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1_DIREBADGER = 17001;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1_DIRERAT = 17002;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1_DOG = 17003;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1_HAWK = 17004;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_1_TINY_VIPER = 17005;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2 = 17010;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2_DIREBOAR = 17011;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2_COOSHEE = 17012;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2_WOLF = 17013;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2_SMALL_VIPER = 17014;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_2_BLACKBEAR = 17015;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3 = 17020;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3_BROWNBEAR = 17021;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3_DIREWOLK = 17022;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3_LARGE_VIPER = 17023;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3_LEOPARD = 17024;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_3_SATYR = 17025;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4 = 17030;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4_LION = 17031;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4_POLAR_BEAR = 17032;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4_DIRE_SPIDER = 17033;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4_HUGE_VIPER = 17034;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_4_WEREBOAR = 17035;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5 = 17040;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5_MED_AIR = 17041;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5_MED_EARTH = 17042;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5_MED_FIRE = 17043;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5_MED_WATER = 17044;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_5_DIRE_BEAR = 17045;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6 = 17050;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6_LG_AIR = 17051;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6_LG_EARTH = 17052;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6_LG_FIRE = 17053;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6_LG_WATER = 17054;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_6_DIRETIGER = 17055;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7 = 17060;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7_BULETTE = 17061;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7_INVSTALKER = 17062;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7_PIXIE = 17063;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7_GORGON = 17064;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_7_MANTICORE = 17065;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8 = 17070;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8_GR_AIR = 17071;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8_GR_EARTH = 17072;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8_GR_FIRE = 17073;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8_GR_WATER = 17074;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_8_NYMPH = 17075;
|
||||
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9 = 17080;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9_ELD_AIR = 17081;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9_ELD_EARTH = 17082;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9_ELD_FIRE = 17083;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9_ELD_WATER = 17084;
|
||||
const int SPELL_SUMMON_NATURES_ALLY_9_ARANEA = 17085;
|
||||
|
||||
//:: Player's Handbook II Spells
|
||||
const int SPELL_CHASING_PERFECTION = 2479;
|
||||
|
||||
@@ -1297,6 +1363,14 @@ const int SPELL_SPIRIT_WORM = 17248;
|
||||
const int SPELL_FORCE_MISSILES = 2480;
|
||||
|
||||
//:: Masters of the Wild Spells
|
||||
const int SPELL_FORESTFOLD = 17090;
|
||||
const int SPELL_CREEPING_COLD = 17091;
|
||||
const int SPELL_GREATER_CREEPING_COLD = 17092;
|
||||
const int SPELL_CONTROL_PLANTS = 17237;
|
||||
const int SPELL_ADRENALINE_SURGE = 17238;
|
||||
const int SPELL_INVULNERABILITY_TO_ELEMENTS = 17239;
|
||||
const int SPELL_REGEN_RING = 17241;
|
||||
const int SPELL_REGEN_CIRCLE = 17242;
|
||||
const int SPELL_REGEN_LIGHT_WOUNDS = 17243;
|
||||
const int SPELL_REGEN_MODERATE_WOUNDS = 17244;
|
||||
const int SPELL_REGEN_SERIOUS_WOUNDS = 17245;
|
||||
@@ -1304,6 +1378,20 @@ const int SPELL_REGEN_CRITICAL_WOUNDS = 17246;
|
||||
const int SPELL_SPEED_WIND = 17247;
|
||||
const int SPELL_TORTISE_SHELL = 17250;
|
||||
|
||||
//:: Book of Exalted Deeds Spells
|
||||
const int SPELL_LEONALS_ROAR = 17240;
|
||||
|
||||
//:: Master of the Wild Feats
|
||||
const int SPELL_VL_WILD_SHAPE_TREANT = 17989;
|
||||
const int SPELL_VL_ANIMATE_TREE = 17990;
|
||||
const int SPELL_PLANT_DEFIANCE = 17991;
|
||||
const int SPELL_PLANT_CONTROL = 17992;
|
||||
|
||||
//:: Book of Exalted Deeds Feats
|
||||
const int SPELL_FOT_LEONALS_ROAR = 17993;
|
||||
const int SPELL_FOT_LIONS_SWIFTNESS = 17994;
|
||||
const int SPELL_FAVORED_OF_THE_COMPANIONS = 17995;
|
||||
|
||||
//x
|
||||
const int SPELL_TENSERS_FLOATING_DISK = 3849;
|
||||
const int SPELL_WOLFSKIN = 3850;
|
||||
|
||||
@@ -299,6 +299,7 @@ int SpellfireDrainItem(object oPC, object oItem, int bCharged = TRUE, int bSingl
|
||||
{
|
||||
|
||||
if((nBase == BASE_ITEM_POTIONS) ||
|
||||
(nBase == BASE_ITEM_INFUSED_HERB) ||
|
||||
(nBase == BASE_ITEM_SCROLL) ||
|
||||
(nBase == BASE_ITEM_SPELLSCROLL) ||
|
||||
(nBase == BASE_ITEM_BLANK_POTION) ||
|
||||
@@ -382,6 +383,7 @@ void SpellfireDrain(object oPC, object oTarget, int bCharged = TRUE, int bExempt
|
||||
if(GetPRCSwitch(PRC_SPELLFIRE_DISALLOW_DRAIN_SCROLL_POTION) &&
|
||||
((nBase == BASE_ITEM_POTIONS) ||
|
||||
(nBase == BASE_ITEM_SCROLL) ||
|
||||
(nBase == BASE_ITEM_INFUSED_HERB) ||
|
||||
(nBase == BASE_ITEM_BLANK_POTION) ||
|
||||
(nBase == BASE_ITEM_BLANK_SCROLL)
|
||||
)
|
||||
@@ -525,3 +527,4 @@ void SpellfireCrown(object oPC)
|
||||
}
|
||||
}
|
||||
|
||||
//:: void main() {}
|
||||
@@ -18,6 +18,7 @@ const int TEMPLATE_CURST = 26;
|
||||
const int TEMPLATE_GRAVETOUCHED_GHOUL = 29;
|
||||
const int TEMPLATE_CRYPTSPAWN = 30;
|
||||
const int TEMPLATE_ARCHLICH = 99;
|
||||
const int TEMPLATE_BAELNORN = 100;
|
||||
const int TEMPLATE_LICH = 101;
|
||||
const int TEMPLATE_DEMILICH = 102;
|
||||
const int TEMPLATE_NECROPOLITAN = 105;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
//:: Created On: 2003-05-09
|
||||
//:: Last Updated On: 2003-10-14
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_x2_itemprop"
|
||||
|
||||
struct craft_struct
|
||||
{
|
||||
@@ -44,22 +44,24 @@ const string X2_CI_CRAFTSKILL_CONV ="x2_p_craftskills";
|
||||
/* moved to be code switches
|
||||
|
||||
const int X2_CI_BREWPOTION_MAXLEVEL = 3; // Max Level for potions
|
||||
const int X2_CI_BREWPOTION_COSTMODIFIER = 50; // gp Brew Potion XPCost Modifier
|
||||
const int PRC_X2_BREWPOTION_COSTMODIFIER = 50; // gp Brew Potion XPCost Modifier
|
||||
|
||||
// Scribe Scroll related constants
|
||||
const int X2_CI_SCRIBESCROLL_COSTMODIFIER = 25; // Scribescroll Cost Modifier
|
||||
const int PRC_X2_SCRIBESCROLL_COSTMODIFIER = 25; // Scribescroll Cost Modifier
|
||||
|
||||
// Craft Wand related constants
|
||||
const int X2_CI_CRAFTWAND_MAXLEVEL = 4;
|
||||
const int X2_CI_CRAFTWAND_COSTMODIFIER = 750;
|
||||
const int PRC_X2_CRAFTWAND_MAXLEVEL = 4;
|
||||
const int PRC_X2_CRAFTWAND_COSTMODIFIER = 750;
|
||||
*/
|
||||
const int X2_CI_BREWPOTION_FEAT_ID = 944; // Brew Potion feat simulation
|
||||
const int X2_CI_SCRIBESCROLL_FEAT_ID = 945;
|
||||
const int X2_CI_CRAFTWAND_FEAT_ID = 946;
|
||||
const int X2_CI_CRAFTROD_FEAT_ID = 2927;
|
||||
const int X2_CI_CRAFTROD_EPIC_FEAT_ID = 3490;
|
||||
const int X2_CI_CRAFTSTAFF_FEAT_ID = 2928;
|
||||
const int X2_CI_CRAFTSTAFF_EPIC_FEAT_ID = 3491;
|
||||
const int X2_CI_BREWPOTION_FEAT_ID = 944; // Brew Potion feat simulation
|
||||
const int X2_CI_SCRIBESCROLL_FEAT_ID = 945;
|
||||
const int X2_CI_CRAFTWAND_FEAT_ID = 946;
|
||||
const int X2_CI_CRAFTROD_FEAT_ID = 2927;
|
||||
const int X2_CI_CRAFTROD_EPIC_FEAT_ID = 3490;
|
||||
const int X2_CI_CRAFTSTAFF_FEAT_ID = 2928;
|
||||
const int X2_CI_CRAFTSTAFF_EPIC_FEAT_ID = 3491;
|
||||
const int X2_CI_CREATEINFUSION_FEAT_ID = 25960;
|
||||
|
||||
const string X2_CI_BREWPOTION_NEWITEM_RESREF = "x2_it_pcpotion"; // ResRef for new potion item
|
||||
const string X2_CI_SCRIBESCROLL_NEWITEM_RESREF = "x2_it_pcscroll"; // ResRef for new scroll item
|
||||
const string X2_CI_CRAFTWAND_NEWITEM_RESREF = "x2_it_pcwand";
|
||||
@@ -185,6 +187,17 @@ int CheckAlternativeCrafting(object oPC, int nSpell, struct craft_cost_struct co
|
||||
// Returns the maximum of caster level used and other effective levels from emulating spells
|
||||
int GetAlternativeCasterLevel(object oPC, int nLevel);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Create and Return an herbal infusion with an item property
|
||||
// matching nSpellID.
|
||||
// -----------------------------------------------------------------------------
|
||||
object CICreateInfusion(object oCreator, int nSpellID);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player successfully performed Create Infusion
|
||||
// -----------------------------------------------------------------------------
|
||||
int CICraftCheckCreateInfusion(object oSpellTarget, object oCaster, int nID = 0);
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Include section */
|
||||
//////////////////////////////////////////////////
|
||||
@@ -194,6 +207,7 @@ int GetAlternativeCasterLevel(object oPC, int nLevel);
|
||||
#include "prc_inc_newip"
|
||||
#include "prc_inc_spells"
|
||||
#include "prc_add_spell_dc"
|
||||
#include "inc_infusion"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function definitions */
|
||||
@@ -261,7 +275,8 @@ int CIGetIsCraftFeatBaseItem(object oItem)
|
||||
nBt == BASE_ITEM_BLANK_SCROLL ||
|
||||
nBt == BASE_ITEM_BLANK_WAND ||
|
||||
nBt == BASE_ITEM_CRAFTED_ROD ||
|
||||
nBt == BASE_ITEM_CRAFTED_STAFF)
|
||||
nBt == BASE_ITEM_CRAFTED_STAFF ||
|
||||
nBt == BASE_ITEM_MUNDANE_HERB)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
@@ -453,11 +468,158 @@ object CICraftCraftWand(object oCreator, int nSpellID )
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Georg, 2003-06-12
|
||||
// Create and Return a magic wand with an item property
|
||||
// matching nSpellID. Charges are set to d20 + casterlevel
|
||||
// capped at 50 max
|
||||
// Create and Return a magic scroll with an item property
|
||||
// matching nSpellID.
|
||||
// -----------------------------------------------------------------------------
|
||||
object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: Enter (nSpellID=" + IntToString(nSpellID) + ")");
|
||||
|
||||
// Keep original and compute one-step master (if subradial)
|
||||
int nSpellOriginal = nSpellID;
|
||||
int nSpellMaster = nSpellOriginal;
|
||||
if (GetIsSubradialSpell(nSpellOriginal))
|
||||
{
|
||||
nSpellMaster = GetMasterSpellFromSubradial(nSpellOriginal);
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: subradial detected original=" + IntToString(nSpellOriginal) + " master=" + IntToString(nSpellMaster));
|
||||
}
|
||||
|
||||
// Prefer iprp mapping for the original, fallback to master
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellOriginal);
|
||||
int nSpellUsedForIP = nSpellOriginal;
|
||||
if (nPropID < 0)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: no iprp for original " + IntToString(nSpellOriginal) + ", trying master " + IntToString(nSpellMaster));
|
||||
nPropID = IPGetIPConstCastSpellFromSpellID(nSpellMaster);
|
||||
nSpellUsedForIP = nSpellMaster;
|
||||
}
|
||||
|
||||
// If neither original nor master has an iprp row, we can still try templates,
|
||||
// but most templates expect a matching iprp. Bail out now if nothing found.
|
||||
if (nPropID < 0)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: no iprp_spells entry for original/master -> aborting");
|
||||
FloatingTextStringOnCreature("This spell cannot be scribed (no item property mapping).", oCreator, FALSE);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: using spell " + IntToString(nSpellUsedForIP) + " (iprp row " + IntToString(nPropID) + ") for item property");
|
||||
|
||||
// Material component check (based on resolved iprp row)
|
||||
string sMat = GetMaterialComponentTag(nPropID);
|
||||
if (sMat != "")
|
||||
{
|
||||
object oMat = GetItemPossessedBy(oCreator, sMat);
|
||||
if (oMat == OBJECT_INVALID)
|
||||
{
|
||||
FloatingTextStrRefOnCreature(83374, oCreator); // Missing material component
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyObject(oMat);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve class and scroll template
|
||||
int nClass = PRCGetLastSpellCastClass();
|
||||
string sClass = "";
|
||||
switch (nClass)
|
||||
{
|
||||
case CLASS_TYPE_WIZARD:
|
||||
case CLASS_TYPE_SORCERER: sClass = "Wiz_Sorc"; break;
|
||||
case CLASS_TYPE_CLERIC:
|
||||
case CLASS_TYPE_UR_PRIEST: sClass = "Cleric"; break;
|
||||
case CLASS_TYPE_PALADIN: sClass = "Paladin"; break;
|
||||
case CLASS_TYPE_DRUID:
|
||||
case CLASS_TYPE_BLIGHTER: sClass = "Druid"; break;
|
||||
case CLASS_TYPE_RANGER: sClass = "Ranger"; break;
|
||||
case CLASS_TYPE_BARD: sClass = "Bard"; break;
|
||||
case CLASS_TYPE_ASSASSIN: sClass = "Assassin"; break;
|
||||
}
|
||||
|
||||
object oTarget = OBJECT_INVALID;
|
||||
string sResRef = "";
|
||||
|
||||
// Try to find a class-specific scroll template.
|
||||
if (sClass != "")
|
||||
{
|
||||
// Try original first (so if you made a subradial-specific template it will be used)
|
||||
sResRef = Get2DACache(X2_CI_2DA_SCROLLS, sClass, nSpellOriginal);
|
||||
if (sResRef == "")
|
||||
{
|
||||
// fallback to the spell that matched an iprp row (master or original)
|
||||
sResRef = Get2DACache(X2_CI_2DA_SCROLLS, sClass, nSpellUsedForIP);
|
||||
}
|
||||
if (sResRef != "")
|
||||
{
|
||||
oTarget = CreateItemOnObject(sResRef, oCreator);
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: created template " + sResRef + " for class " + sClass);
|
||||
// Ensure template uses the correct cast-spell property: replace the template's cast-spell IP with ours
|
||||
if (oTarget != OBJECT_INVALID)
|
||||
{
|
||||
itemproperty ipIter = GetFirstItemProperty(oTarget);
|
||||
while (GetIsItemPropertyValid(ipIter))
|
||||
{
|
||||
if (GetItemPropertyType(ipIter) == ITEM_PROPERTY_CAST_SPELL)
|
||||
{
|
||||
RemoveItemProperty(oTarget, ipIter);
|
||||
break;
|
||||
}
|
||||
ipIter = GetNextItemProperty(oTarget);
|
||||
}
|
||||
itemproperty ipSpell = ItemPropertyCastSpell(nPropID, IP_CONST_CASTSPELL_NUMUSES_SINGLE_USE);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipSpell, oTarget);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If no template or sClass was empty, create generic scroll and add itemprop.
|
||||
if (oTarget == OBJECT_INVALID)
|
||||
{
|
||||
sResRef = "craft_scroll";
|
||||
oTarget = CreateItemOnObject(sResRef, oCreator);
|
||||
if (oTarget == OBJECT_INVALID)
|
||||
{
|
||||
WriteTimestampedLogEntry("CICraftScribeScroll: failed to create craft_scroll template.");
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
// Remove existing default IP and add correct one
|
||||
itemproperty ipFirst = GetFirstItemProperty(oTarget);
|
||||
if (GetIsItemPropertyValid(ipFirst))
|
||||
RemoveItemProperty(oTarget, ipFirst);
|
||||
|
||||
itemproperty ipSpell = ItemPropertyCastSpell(nPropID, IP_CONST_CASTSPELL_NUMUSES_SINGLE_USE);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipSpell, oTarget);
|
||||
}
|
||||
|
||||
// Add PRC metadata (use the same spell that matched the iprp row so metadata and IP line up)
|
||||
if (GetPRCSwitch(PRC_SCRIBE_SCROLL_CASTER_LEVEL))
|
||||
{
|
||||
int nCasterLevel = GetAlternativeCasterLevel(oCreator, PRCGetCasterLevel(oCreator));
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpellUsedForIP, nCasterLevel);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipLevel, oTarget);
|
||||
|
||||
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpellUsedForIP, PRCGetMetaMagicFeat());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipMeta, oTarget);
|
||||
|
||||
int nDC = PRCGetSpellSaveDC(nSpellUsedForIP, GetSpellSchool(nSpellUsedForIP), OBJECT_SELF);
|
||||
itemproperty ipDC = ItemPropertyCastSpellDC(nSpellUsedForIP, nDC);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipDC, oTarget);
|
||||
}
|
||||
|
||||
if (oTarget == OBJECT_INVALID)
|
||||
{
|
||||
WriteTimestampedLogEntry("prc_x2_craft::CICraftScribeScroll failed - Resref: " + sResRef + " Class: " + sClass + "(" + IntToString(nClass) + ") " + " SpellID " + IntToString(nSpellID));
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("CICraftScribeScroll: Success - created scroll " + sResRef + " for spell " + IntToString(nSpellUsedForIP));
|
||||
return oTarget;
|
||||
}
|
||||
|
||||
|
||||
/* object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
{
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellID);
|
||||
object oTarget;
|
||||
@@ -491,6 +653,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
break;
|
||||
case CLASS_TYPE_CLERIC:
|
||||
case CLASS_TYPE_UR_PRIEST:
|
||||
case CLASS_TYPE_OCULAR:
|
||||
sClass = "Cleric";
|
||||
break;
|
||||
case CLASS_TYPE_PALADIN:
|
||||
@@ -506,6 +669,9 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
case CLASS_TYPE_BARD:
|
||||
sClass = "Bard";
|
||||
break;
|
||||
case CLASS_TYPE_ASSASSIN:
|
||||
sClass = "Assassin";
|
||||
break;
|
||||
}
|
||||
string sResRef;
|
||||
if (sClass != "")
|
||||
@@ -542,7 +708,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
|
||||
}
|
||||
return oTarget;
|
||||
}
|
||||
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player used the last spell to brew a potion
|
||||
// -----------------------------------------------------------------------------
|
||||
@@ -593,7 +759,7 @@ These dont work as IPs since they are hardcoded */
|
||||
// -------------------------------------------------------------------------
|
||||
// check if spell is below maxlevel for brew potions
|
||||
// -------------------------------------------------------------------------
|
||||
int nPotionMaxLevel = GetPRCSwitch(X2_CI_BREWPOTION_MAXLEVEL);
|
||||
int nPotionMaxLevel = GetPRCSwitch(PRC_X2_BREWPOTION_MAXLEVEL);
|
||||
if(nPotionMaxLevel == 0)
|
||||
nPotionMaxLevel = 3;
|
||||
|
||||
@@ -624,7 +790,7 @@ These dont work as IPs since they are hardcoded */
|
||||
// -------------------------------------------------------------------------
|
||||
// XP/GP Cost Calculation
|
||||
// -------------------------------------------------------------------------
|
||||
int nCostModifier = GetPRCSwitch(X2_CI_BREWPOTION_COSTMODIFIER);
|
||||
int nCostModifier = GetPRCSwitch(PRC_X2_BREWPOTION_COSTMODIFIER);
|
||||
if(nCostModifier == 0)
|
||||
nCostModifier = 50;
|
||||
int nCost = CIGetCraftGPCost(nLevel, nCostModifier, PRC_BREW_POTION_CASTER_LEVEL);
|
||||
@@ -728,7 +894,7 @@ int CICraftCheckScribeScroll(object oSpellTarget, object oCaster, int nID = 0)
|
||||
// XP/GP Cost Calculation
|
||||
// -------------------------------------------------------------------------
|
||||
int nLevel = CIGetSpellInnateLevel(nID,TRUE);
|
||||
int nCostModifier = GetPRCSwitch(X2_CI_SCRIBESCROLL_COSTMODIFIER);
|
||||
int nCostModifier = GetPRCSwitch(PRC_X2_SCRIBESCROLL_COSTMODIFIER);
|
||||
if(nCostModifier == 0)
|
||||
nCostModifier = 25;
|
||||
int nCost = CIGetCraftGPCost(nLevel, nCostModifier, PRC_SCRIBE_SCROLL_CASTER_LEVEL);
|
||||
@@ -884,7 +1050,7 @@ These dont work as IPs since they are hardcoded */
|
||||
// -------------------------------------------------------------------------
|
||||
// check if spell is below maxlevel for craft want
|
||||
// -------------------------------------------------------------------------
|
||||
int nMaxLevel = GetPRCSwitch(X2_CI_CRAFTWAND_MAXLEVEL);
|
||||
int nMaxLevel = GetPRCSwitch(PRC_X2_CRAFTWAND_MAXLEVEL);
|
||||
if(nMaxLevel == 0)
|
||||
nMaxLevel = 4;
|
||||
if (nLevel > nMaxLevel)
|
||||
@@ -896,7 +1062,7 @@ These dont work as IPs since they are hardcoded */
|
||||
// -------------------------------------------------------------------------
|
||||
// XP/GP Cost Calculation
|
||||
// -------------------------------------------------------------------------
|
||||
int nCostMod = GetPRCSwitch(X2_CI_CRAFTWAND_COSTMODIFIER);
|
||||
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTWAND_COSTMODIFIER);
|
||||
if(nCostMod == 0)
|
||||
nCostMod = 750;
|
||||
int nCost = CIGetCraftGPCost(nLevel, nCostMod, PRC_CRAFT_WAND_CASTER_LEVEL);
|
||||
@@ -1027,7 +1193,7 @@ int CICraftCheckCraftStaff(object oSpellTarget, object oCaster, int nSpellID = 0
|
||||
These dont work as IPs since they are hardcoded */
|
||||
}
|
||||
}
|
||||
int nCostMod = GetPRCSwitch(X2_CI_CRAFTSTAFF_COSTMODIFIER);
|
||||
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTSTAFF_COSTMODIFIER);
|
||||
if(!nCostMod) nCostMod = 750;
|
||||
int nLvlRow = IPGetIPConstCastSpellFromSpellID(nSpellID);
|
||||
int nCLevel = StringToInt(Get2DACache("iprp_spells","CasterLvl",nLvlRow));
|
||||
@@ -1175,7 +1341,7 @@ int CICraftCheckCraftRod(object oSpellTarget, object oCaster, int nSpellID = 0)
|
||||
These dont work as IPs since they are hardcoded */
|
||||
}
|
||||
}
|
||||
int nCostMod = GetPRCSwitch(X2_CI_CRAFTROD_COSTMODIFIER);
|
||||
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTROD_COSTMODIFIER);
|
||||
if(!nCostMod) nCostMod = 750;
|
||||
int nLvlRow = IPGetIPConstCastSpellFromSpellID(nSpellID);
|
||||
int nCLevel = StringToInt(Get2DACache("iprp_spells","CasterLvl",nLvlRow));
|
||||
@@ -1544,7 +1710,7 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
|
||||
// No point scribing Gems from items, and its not allowed.
|
||||
if (oItem != OBJECT_INVALID)
|
||||
{
|
||||
FloatingTextStringOnCreature("You cannot scribe a Gem from an item.", oCaster, FALSE);
|
||||
FloatingTextStringOnCreature("You cannot attune a Gem from an item.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
// oTarget here should be the gem. If it's not, fail.
|
||||
@@ -1952,6 +2118,12 @@ int CIGetSpellWasUsedForItemCreation(object oSpellTarget)
|
||||
nRet = CICraftCheckCraftStaff(oSpellTarget,oCaster);
|
||||
break;
|
||||
|
||||
case BASE_ITEM_MUNDANE_HERB :
|
||||
// -------------------------------------------------
|
||||
// Create Infusion
|
||||
// -------------------------------------------------
|
||||
nRet = CICraftCheckCreateInfusion(oSpellTarget,oCaster);
|
||||
break;
|
||||
// you could add more crafting basetypes here....
|
||||
}
|
||||
|
||||
@@ -2740,6 +2912,11 @@ int GetMagicalArtisanFeat(int nCraftingFeat)
|
||||
nReturn = FEAT_MAGICAL_ARTISAN_CRAFT_SKULL_TALISMAN;
|
||||
break;
|
||||
}
|
||||
case FEAT_CREATE_INFUSION:
|
||||
{
|
||||
nReturn = FEAT_MAGICAL_ARTISAN_CREATE_INFUSION;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if(DEBUG) DoDebug("GetMagicalArtisanFeat: invalid crafting feat");
|
||||
@@ -2941,6 +3118,306 @@ int GetAlternativeCasterLevel(object oPC, int nLevel)
|
||||
return nLevel;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Returns TRUE if the player successfully performed Create Infusion
|
||||
// -----------------------------------------------------------------------------
|
||||
int CICraftCheckCreateInfusion(object oSpellTarget, object oCaster, int nID = 0)
|
||||
{
|
||||
if (nID == 0) nID = PRCGetSpellId();
|
||||
|
||||
int bIsSubradial = GetIsSubradialSpell(nID);
|
||||
|
||||
if(bIsSubradial)
|
||||
{
|
||||
nID = GetMasterSpellFromSubradial(nID);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check if the caster has the Create Infusion feat
|
||||
// -------------------------------------------------------------------------
|
||||
if (!GetHasFeat(FEAT_CREATE_INFUSION, oCaster))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(40487, oCaster); // Missing feat
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Divine spellcasters only
|
||||
// -------------------------------------------------------------------------
|
||||
int nClass = PRCGetLastSpellCastClass();
|
||||
if (!GetIsDivineClass(nClass))
|
||||
{
|
||||
FloatingTextStringOnCreature("Only divine casters can create infusions.", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check if spell is restricted for Create Infusion
|
||||
// -------------------------------------------------------------------------
|
||||
if (CIGetIsSpellRestrictedFromCraftFeat(nID, X2_CI_CREATEINFUSION_FEAT_ID))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(83451, oCaster); // Spell not allowed
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Optional PnP Herb check
|
||||
// -------------------------------------------------------------------------
|
||||
int bPnPHerbs = GetPRCSwitch(PRC_CREATE_INFUSION_OPTIONAL_HERBS);
|
||||
if(bPnPHerbs)
|
||||
{
|
||||
int nSpellschool = GetSpellSchool(nID);
|
||||
int nHerbSchool = GetHerbsSpellSchool(oSpellTarget);
|
||||
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nID, nClass);
|
||||
int nHerbLevel = GetHerbsInfusionSpellLevel(oSpellTarget);
|
||||
|
||||
if(nSpellschool != nHerbSchool)
|
||||
{
|
||||
// Herb is for wrong spellschool
|
||||
FloatingTextStringOnCreature("This herb isn't appropriate for this spell school", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if(nSpellLevel > nHerbLevel)
|
||||
{
|
||||
// Herb spell circle level too low
|
||||
FloatingTextStringOnCreature("This herb isn't appropriate for this spell level", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// XP/GP Cost Calculation
|
||||
// -------------------------------------------------------------------------
|
||||
int nLevel = CIGetSpellInnateLevel(nID, TRUE);
|
||||
int nCostModifier = GetPRCSwitch(PRC_X2_CREATEINFUSION_COSTMODIFIER);
|
||||
if (nCostModifier == 0)
|
||||
nCostModifier = 25;
|
||||
|
||||
int nCost = CIGetCraftGPCost(nLevel, nCostModifier, PRC_CREATE_INFUSION_CASTER_LEVEL);
|
||||
struct craft_cost_struct costs = GetModifiedCostsFromBase(nCost, oCaster, FEAT_CREATE_INFUSION, FALSE);
|
||||
|
||||
// Adjust level for metamagic
|
||||
if (GetPRCSwitch(PRC_CREATE_INFUSION_CASTER_LEVEL))
|
||||
{
|
||||
int nMetaMagic = PRCGetMetaMagicFeat();
|
||||
switch(nMetaMagic)
|
||||
{
|
||||
case METAMAGIC_EMPOWER: nLevel += 2; break;
|
||||
case METAMAGIC_EXTEND: nLevel += 1; break;
|
||||
case METAMAGIC_MAXIMIZE: nLevel += 3; break;
|
||||
// Unsupported metamagic IPs not added
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check Gold
|
||||
// -------------------------------------------------------------------------
|
||||
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(3786, oCaster); // Not enough gold
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check XP
|
||||
// -------------------------------------------------------------------------
|
||||
if (!GetHasXPToSpend(oCaster, costs.nXPCost))
|
||||
{
|
||||
FloatingTextStrRefOnCreature(3785, oCaster); // Not enough XP
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Check alternative spell emulation requirements
|
||||
// -------------------------------------------------------------------------
|
||||
if (!CheckAlternativeCrafting(oCaster, nID, costs))
|
||||
{
|
||||
FloatingTextStringOnCreature("*Crafting failed!*", oCaster, FALSE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Create the infused herb item
|
||||
// -------------------------------------------------------------------------
|
||||
object oInfusion = CICreateInfusion(oCaster, nID);
|
||||
|
||||
if (GetIsObjectValid(oInfusion))
|
||||
{
|
||||
// Get the spell's display name from spells.2da via TLK
|
||||
int nNameStrRef = StringToInt(Get2DAString("spells", "Name", nID));
|
||||
string sSpellName = GetStringByStrRef(nNameStrRef);
|
||||
|
||||
// Rename the item
|
||||
string sNewName = "Infusion of " + sSpellName;
|
||||
SetName(oInfusion, sNewName);
|
||||
|
||||
// Post-creation actions
|
||||
SetIdentified(oInfusion, TRUE);
|
||||
ActionPlayAnimation(ANIMATION_FIREFORGET_READ, 1.0);
|
||||
SpendXP(oCaster, costs.nXPCost);
|
||||
SpendGP(oCaster, costs.nGoldCost);
|
||||
DestroyObject(oSpellTarget);
|
||||
FloatingTextStrRefOnCreature(8502, oCaster); // Item creation successful
|
||||
|
||||
if (!costs.nTimeCost) costs.nTimeCost = 1;
|
||||
AdvanceTimeForPlayer(oCaster, RoundsToSeconds(costs.nTimeCost));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingTextStringOnCreature("Infusion creation failed", oCaster); // Item creation failed
|
||||
FloatingTextStrRefOnCreature(76417, oCaster); // Item creation failed
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* // -------------------------------------------------------------------------
|
||||
// Create the infused herb item
|
||||
// -------------------------------------------------------------------------
|
||||
object oInfusion = CICreateInfusion(oCaster, nID);
|
||||
|
||||
if (GetIsObjectValid(oInfusion))
|
||||
{
|
||||
SetIdentified(oInfusion, TRUE);
|
||||
ActionPlayAnimation(ANIMATION_FIREFORGET_READ, 1.0);
|
||||
SpendXP(oCaster, costs.nXPCost);
|
||||
SpendGP(oCaster, costs.nGoldCost);
|
||||
DestroyObject(oSpellTarget);
|
||||
FloatingTextStrRefOnCreature(8502, oCaster); // Item creation successful
|
||||
|
||||
if (!costs.nTimeCost) costs.nTimeCost = 1;
|
||||
AdvanceTimeForPlayer(oCaster, RoundsToSeconds(costs.nTimeCost));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
FloatingTextStringOnCreature("Infusion creation failed", oCaster); // Item creation failed
|
||||
FloatingTextStrRefOnCreature(76417, oCaster); // Item creation failed
|
||||
return TRUE;
|
||||
} */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Create and return an herbal infusion with an item property matching nSpellID
|
||||
// -----------------------------------------------------------------------------
|
||||
object CICreateInfusion(object oCreator, int nSpellID)
|
||||
{
|
||||
if (DEBUG) DoDebug("prc_x2_craft >> CICreateInfusion: Entering function");
|
||||
|
||||
// Keep the original spell id the engine gave us (may be a subradial)
|
||||
int nSpellOriginal = nSpellID;
|
||||
if (DEBUG) DoDebug("prc_x2_craft >> CICreateInfusion: nSpellOriginal is "+IntToString(nSpellOriginal)+".");
|
||||
|
||||
// Compute the master if this is a subradial. Keep original intact.
|
||||
int nSpellMaster = nSpellOriginal;
|
||||
if (GetIsSubradialSpell(nSpellOriginal))
|
||||
{
|
||||
nSpellMaster = GetMasterSpellFromSubradial(nSpellOriginal);
|
||||
if (DEBUG) DoDebug("CICreateInfusion: detected subradial " + IntToString(nSpellOriginal) + " master -> " + IntToString(nSpellMaster));
|
||||
}
|
||||
if (DEBUG) DoDebug("prc_x2_craft >> CICreateInfusion: nSpellMaster is "+IntToString(nSpellMaster)+".");
|
||||
|
||||
// Try to find an iprp_spells row for the original subradial first (preferred).
|
||||
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellOriginal);
|
||||
int nSpellUsedForIP = nSpellOriginal;
|
||||
|
||||
// If not found for original, fall back to the master/base spell.
|
||||
if (nPropID < 0)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICreateInfusion: no iprp row for original " + IntToString(nSpellOriginal) + ", trying master " + IntToString(nSpellMaster));
|
||||
nPropID = IPGetIPConstCastSpellFromSpellID(nSpellMaster);
|
||||
nSpellUsedForIP = nSpellMaster;
|
||||
}
|
||||
|
||||
// If still invalid, bail out with a helpful message
|
||||
if (nPropID < 0)
|
||||
{
|
||||
if (DEBUG) DoDebug("CICreateInfusion: No iprp_spells entry for either original " + IntToString(nSpellOriginal) + " or master " + IntToString(nSpellMaster));
|
||||
FloatingTextStringOnCreature("This spell cannot be infused (no item property mapping).", oCreator, FALSE);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
if (DEBUG) DoDebug("CICreateInfusion: using spell " + IntToString(nSpellUsedForIP) + " (iprp row " + IntToString(nPropID) + ") for item property");
|
||||
|
||||
// Optional: check for material component (use the resolved iprp row)
|
||||
string sMat = GetMaterialComponentTag(nPropID);
|
||||
if (sMat != "")
|
||||
{
|
||||
object oMat = GetItemPossessedBy(oCreator, sMat);
|
||||
if (oMat == OBJECT_INVALID)
|
||||
{
|
||||
FloatingTextStrRefOnCreature(83374, oCreator); // Missing material component
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyObject(oMat);
|
||||
}
|
||||
}
|
||||
|
||||
// Only allow divine spellcasters
|
||||
int nClass = PRCGetLastSpellCastClass();
|
||||
if (!GetIsDivineClass(nClass))
|
||||
{
|
||||
FloatingTextStringOnCreature("Only divine casters can use Create Infusion.", oCreator, FALSE);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
// Create base infusion item (herb)
|
||||
string sResRef = "prc_infusion_000";
|
||||
object oTarget = CreateItemOnObject(sResRef, oCreator);
|
||||
if (oTarget == OBJECT_INVALID)
|
||||
{
|
||||
WriteTimestampedLogEntry("Create Infusion failed: couldn't create item with resref " + sResRef);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
// Confirm that the item is a herb
|
||||
int nBaseItem = GetBaseItemType(oTarget);
|
||||
if (nBaseItem != BASE_ITEM_INFUSED_HERB)
|
||||
{
|
||||
FloatingTextStringOnCreature("Only herbs may be infused.", oCreator, FALSE);
|
||||
DestroyObject(oTarget);
|
||||
return OBJECT_INVALID;
|
||||
}
|
||||
|
||||
// Remove all non-material item properties from the herb
|
||||
itemproperty ipRemove = GetFirstItemProperty(oTarget);
|
||||
while (GetIsItemPropertyValid(ipRemove))
|
||||
{
|
||||
itemproperty ipNext = GetNextItemProperty(oTarget);
|
||||
if (GetItemPropertyType(ipRemove) != ITEM_PROPERTY_MATERIAL)
|
||||
RemoveItemProperty(oTarget, ipRemove);
|
||||
ipRemove = ipNext;
|
||||
}
|
||||
|
||||
// Add the cast-spell itemproperty using the iprp row we resolved
|
||||
itemproperty ipSpell = ItemPropertyCastSpell(nPropID, IP_CONST_CASTSPELL_NUMUSES_SINGLE_USE);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipSpell, oTarget);
|
||||
|
||||
// Optional PRC casting metadata: use the SAME spell id that matched the iprp row
|
||||
// so caster level/DC/meta line up with the actual cast property on the item.
|
||||
if (GetPRCSwitch(PRC_CREATE_INFUSION_CASTER_LEVEL))
|
||||
{
|
||||
int nCasterLevel = GetAlternativeCasterLevel(oCreator, PRCGetCasterLevel(oCreator));
|
||||
// nSpellUsedForIP is either original (if that had an iprp row) or the master (fallback)
|
||||
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpellUsedForIP, nCasterLevel);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipLevel, oTarget);
|
||||
|
||||
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpellUsedForIP, PRCGetMetaMagicFeat());
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipMeta, oTarget);
|
||||
|
||||
int nDC = PRCGetSpellSaveDC(nSpellUsedForIP, GetSpellSchool(nSpellUsedForIP), OBJECT_SELF);
|
||||
itemproperty ipDC = ItemPropertyCastSpellDC(nSpellUsedForIP, nDC);
|
||||
AddItemProperty(DURATION_TYPE_PERMANENT, ipDC, oTarget);
|
||||
}
|
||||
|
||||
return oTarget;
|
||||
}
|
||||
|
||||
|
||||
// Test main
|
||||
//void main(){}
|
||||
// void main(){}
|
||||
|
||||
@@ -768,7 +768,6 @@ int IPGetIsBludgeoningWeapon(object oItem)
|
||||
// ----------------------------------------------------------------------------
|
||||
// Return the IP_CONST_CASTSPELL_* ID matching to the SPELL_* constant given
|
||||
// in nSPELL_ID.
|
||||
// This uses Get2DAstring, so it is slow. Avoid using in loops!
|
||||
// returns -1 if there is no matching property for a spell
|
||||
// ----------------------------------------------------------------------------
|
||||
int IPGetIPConstCastSpellFromSpellID(int nSpellID)
|
||||
@@ -1883,7 +1882,7 @@ int IPDamageConstant(int nDamBon)
|
||||
case 49: nIPBonus = IP_CONST_DAMAGEBONUS_49; break;
|
||||
case 50: nIPBonus = IP_CONST_DAMAGEBONUS_50; break;
|
||||
}
|
||||
if (nDamBon > 20) nIPBonus = IP_CONST_DAMAGEBONUS_50;
|
||||
if (nDamBon > 50) nIPBonus = IP_CONST_DAMAGEBONUS_50;
|
||||
|
||||
return nIPBonus;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ const string _MYSTERY_LIST_MISC_ARRAY = "_MysteriesKnownMiscArray";
|
||||
const string _MYSTERY_LIST_LEVEL_ARRAY = "_MysteriesKnownLevelArray_";
|
||||
const string _MYSTERY_LIST_GENERAL_ARRAY = "_MysteriesKnownGeneralArray";
|
||||
|
||||
#include "shd_inc_shdfunc"
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
/* Function prototypes */
|
||||
|
||||
@@ -236,12 +236,12 @@ int GetShadowcasterLevel(object oShadow = OBJECT_SELF, int nSpecificClass = CLAS
|
||||
// For when you want to assign the caster level.
|
||||
if(nLevel)
|
||||
{
|
||||
if(DEBUG) SendMessageToPC(oShadow, "GetShadowcasterLevel(): Forced-level shadowcasting at level " + IntToString(nLevel));
|
||||
if(DEBUG) DoDebug("GetShadowcasterLevel(): Forced-level shadowcasting at level " + IntToString(nLevel));
|
||||
//DelayCommand(1.0, DeleteLocalInt(oShadow, PRC_CASTERLEVEL_OVERRIDE));
|
||||
return nLevel + nAdjust;
|
||||
}
|
||||
|
||||
if (DEBUG) FloatingTextStringOnCreature("GetShadowcasterLevel: "+GetName(oShadow)+" is a "+IntToString(nSpecificClass), oShadow);
|
||||
if (DEBUG) DoDebug("GetShadowcasterLevel: "+GetName(oShadow)+" is a "+IntToString(nSpecificClass), oShadow);
|
||||
// The function user needs to know the character's Shadowcaster level in a specific class
|
||||
// instead of whatever the character last shadowcast a mystery as
|
||||
if(nSpecificClass != CLASS_TYPE_INVALID)
|
||||
@@ -288,7 +288,7 @@ int GetShadowcasterLevel(object oShadow = OBJECT_SELF, int nSpecificClass = CLAS
|
||||
nLevel -= 4;
|
||||
}
|
||||
|
||||
if(DEBUG) FloatingTextStringOnCreature("Shadowcaster Level: " + IntToString(nLevel), oShadow, FALSE);
|
||||
if(DEBUG) DoDebug("Shadowcaster Level: " + IntToString(nLevel));
|
||||
|
||||
return nLevel + nAdjust;
|
||||
}
|
||||
|
||||
@@ -1154,6 +1154,7 @@ int GetIsDisciplineWeapon(object oWeapon, int nDiscipline)
|
||||
// Invalid is empty handed / Unarmed strike
|
||||
if(nType == BASE_ITEM_INVALID
|
||||
|| nType == BASE_ITEM_QUARTERSTAFF
|
||||
|| nType == BASE_ITEM_MAGICSTAFF
|
||||
|| nType == BASE_ITEM_SHORTSWORD
|
||||
|| nType == BASE_ITEM_NUNCHAKU)
|
||||
return TRUE;
|
||||
|
||||
@@ -144,8 +144,103 @@ int PRCGetUserSpecificSpellScriptFinished();
|
||||
#include "pnp_shft_main"
|
||||
#include "inc_dynconv"
|
||||
#include "inc_npc"
|
||||
#include "inc_infusion"
|
||||
#include "prc_add_spell_dc"
|
||||
|
||||
|
||||
int Spontaneity(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel)
|
||||
{
|
||||
if(GetLocalInt(oCaster, "PRC_SpontRegen"))
|
||||
{
|
||||
DeleteLocalInt(oCaster, "PRC_SpontRegen");
|
||||
|
||||
int nMetamagic = GetMetaMagicFeat();//we need bioware metamagic here
|
||||
nSpellLevel = PRCGetSpellLevelForClass(nSpellID, nCastingClass);
|
||||
nSpellLevel += GetMetaMagicSpellLevelAdjustment(nMetamagic);
|
||||
|
||||
int nRegenSpell;
|
||||
|
||||
if(nCastingClass == CLASS_TYPE_DRUID)
|
||||
{
|
||||
switch(nSpellLevel)
|
||||
{
|
||||
case 0: return TRUE;
|
||||
case 1: nRegenSpell = SPELL_REGEN_LIGHT_WOUNDS; break;
|
||||
case 2: nRegenSpell = SPELL_REGEN_MODERATE_WOUNDS; break;
|
||||
case 3: nRegenSpell = SPELL_REGEN_RING; break;
|
||||
case 4: nRegenSpell = SPELL_REGEN_SERIOUS_WOUNDS; break;
|
||||
case 5: nRegenSpell = SPELL_REGEN_CRITICAL_WOUNDS; break;
|
||||
case 6: nRegenSpell = SPELL_REGEN_CIRCLE; break;
|
||||
case 7: nRegenSpell = SPELL_REGEN_CIRCLE; break;
|
||||
case 8: nRegenSpell = SPELL_REGEN_CIRCLE; break;
|
||||
case 9: nRegenSpell = SPELL_REGENERATE; break;
|
||||
}
|
||||
ActionCastSpell(nRegenSpell, 0, 0, 0, METAMAGIC_NONE, CLASS_TYPE_DRUID);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(nSpellLevel)
|
||||
{
|
||||
case 0: return TRUE;
|
||||
case 1: nRegenSpell = SPELL_REGEN_LIGHT_WOUNDS; break;
|
||||
case 2: nRegenSpell = SPELL_REGEN_LIGHT_WOUNDS; break;
|
||||
case 3: nRegenSpell = SPELL_REGEN_MODERATE_WOUNDS; break;
|
||||
case 4: nRegenSpell = SPELL_REGEN_MODERATE_WOUNDS; break;
|
||||
case 5: nRegenSpell = SPELL_REGEN_SERIOUS_WOUNDS; break;
|
||||
case 6: nRegenSpell = SPELL_REGEN_CRITICAL_WOUNDS; break;
|
||||
case 7: nRegenSpell = SPELL_REGENERATE; break;
|
||||
case 8: nRegenSpell = SPELL_REGENERATE; break;
|
||||
case 9: nRegenSpell = SPELL_REGENERATE; break;
|
||||
}
|
||||
|
||||
ActionCastSpell(nRegenSpell, 0, 0, 0, METAMAGIC_NONE, nCastingClass);
|
||||
}
|
||||
//Don't cast original spell
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int DruidSpontSummon(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel)
|
||||
{
|
||||
if(nCastingClass != CLASS_TYPE_DRUID)
|
||||
return TRUE;
|
||||
|
||||
if(GetLocalInt(oCaster, "PRC_SpontSummon"))
|
||||
{
|
||||
DeleteLocalInt(oCaster, "PRC_SpontSummon");
|
||||
int nMetamagic = GetMetaMagicFeat();//we need bioware metamagic here
|
||||
int nSpellLevel = PRCGetSpellLevelForClass(nSpellID, CLASS_TYPE_DRUID);
|
||||
nSpellLevel += GetMetaMagicSpellLevelAdjustment(nMetamagic);
|
||||
int nSummonSpell;
|
||||
switch(nSpellLevel)
|
||||
{
|
||||
case 0: return TRUE;
|
||||
case 1: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_1; break;
|
||||
case 2: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_2; break;
|
||||
case 3: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_3; break;
|
||||
case 4: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_4; break;
|
||||
case 5: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_5; break;
|
||||
case 6: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_6; break;
|
||||
case 7: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_7; break;
|
||||
case 8: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_8; break;
|
||||
case 9: nSummonSpell = SPELL_SUMMON_NATURES_ALLY_9; break;
|
||||
}
|
||||
|
||||
//:: All SNA spells are subradial spells
|
||||
SetLocalInt(oCaster, "DomainOrigSpell", nSummonSpell);
|
||||
SetLocalInt(oCaster, "DomainCastLevel", nSpellLevel);
|
||||
SetLocalInt(oCaster, "DomainCastClass", CLASS_TYPE_DRUID);
|
||||
StartDynamicConversation("prc_domain_conv", oCaster, DYNCONV_EXIT_NOT_ALLOWED, FALSE, TRUE, oCaster);
|
||||
|
||||
//Don't cast original spell
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* int DruidSpontSummon(object oCaster, int nCastingClass, int nSpellID, int nSpellLevel)
|
||||
{
|
||||
if(nCastingClass != CLASS_TYPE_DRUID)
|
||||
return TRUE;
|
||||
@@ -191,6 +286,8 @@ int DruidSpontSummon(object oCaster, int nCastingClass, int nSpellID, int nSpell
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
int ArcaneSpellFailure(object oCaster, int nCastingClass, int nSpellLevel, int nMetamagic, string sComponents)
|
||||
{
|
||||
if(!GetIsArcaneClass(nCastingClass))
|
||||
@@ -904,7 +1001,8 @@ int ShifterCasting(object oCaster, object oSpellCastItem, int nSpellLevel, int n
|
||||
{
|
||||
// Potion drinking is not restricted
|
||||
if(GetBaseItemType(oSpellCastItem) == BASE_ITEM_ENCHANTED_POTION
|
||||
|| GetBaseItemType(oSpellCastItem) == BASE_ITEM_POTIONS)
|
||||
|| GetBaseItemType(oSpellCastItem) == BASE_ITEM_POTIONS
|
||||
|| GetBaseItemType(oSpellCastItem) == BASE_ITEM_INFUSED_HERB)
|
||||
return TRUE;
|
||||
|
||||
//OnHit properties on equipped items not restricted
|
||||
@@ -1441,8 +1539,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
if (GetHasFeat(FEAT_WILDMAGE_SPELLCASTING_BARD)) return TRUE;
|
||||
if (GetHasFeat(FEAT_WWOC_SPELLCASTING_BARD)) return TRUE;
|
||||
}
|
||||
else if (bBeguiler)
|
||||
if (bBeguiler)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Beguiler", oPC);
|
||||
if (GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_BEGUILER)) return TRUE;
|
||||
@@ -1492,8 +1591,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
|
||||
|
||||
}
|
||||
else if (bDuskblade)
|
||||
if (bDuskblade)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Dusblade", oPC);
|
||||
if (GetHasFeat(FEAT_ABCHAMP_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_DUSKBLADE)) return TRUE;
|
||||
@@ -1540,8 +1640,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
|
||||
|
||||
}
|
||||
else if (bSorcerer)
|
||||
if (bSorcerer)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Sorcerer", oPC);
|
||||
if (GetHasFeat(FEAT_ABERRATION_SPELLCASTING_DRIDER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_MONSTROUS_SPELLCASTING_ARKAMOI)) return TRUE;
|
||||
if (GetHasFeat(FEAT_MONSTROUS_SPELLCASTING_MARRUTACT)) return TRUE;
|
||||
@@ -1599,8 +1700,9 @@ int CheckSecondaryPrC(object oPC = OBJECT_SELF)
|
||||
if (GetHasFeat(FEAT_WILDMAGE_SPELLCASTING_SORCERER)) return TRUE;
|
||||
if (GetHasFeat(FEAT_WWOC_SPELLCASTING_SORCERER)) return TRUE;
|
||||
}
|
||||
else if (bWarmage)
|
||||
if (bWarmage)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: CheckSecondaryPrC >>> Entering Warmage", oPC);
|
||||
if (GetHasFeat(FEAT_AOTS_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ALCHEM_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
if (GetHasFeat(FEAT_ANIMA_SPELLCASTING_WARMAGE)) return TRUE;
|
||||
@@ -1662,14 +1764,71 @@ int BardSorcPrCCheck(object oCaster, int nCastingClass, object oSpellCastItem)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//check its a sorc spell
|
||||
//check its a sorcerer spell
|
||||
if(nCastingClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if (CheckSecondaryPrC(oCaster) == TRUE)
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> nCastingClass is Sorcerer.", oCaster);
|
||||
//no need to check further if new spellbooks are disabled
|
||||
if(GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sorcerer w/RHD found.", oCaster);
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> PRC_SORC_DISALLOW_NEWSPELLBOOK.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//check they have sorcerer levels
|
||||
if(!GetLevelByClass(CLASS_TYPE_SORCERER, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Not a sorcerer.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//check if they are casting via new spellbook
|
||||
if(GetLocalInt(oCaster, "NSB_Class") != CLASS_TYPE_SORCERER && GetLevelByClass(CLASS_TYPE_ULTIMATE_MAGUS, oCaster))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> UltMagus using new spellbook.", oCaster);
|
||||
return FALSE;
|
||||
}
|
||||
//check if they are casting via new spellbook
|
||||
if(GetLocalInt(oCaster, "NSB_Class") == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Using new spellbook.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
if(GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oCaster) > 0 && CheckSecondaryPrC(oCaster) == TRUE)
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sublime Chord w/RHD found.", oCaster);
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
if (CheckSecondaryPrC(oCaster) == TRUE)
|
||||
{
|
||||
if (DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> Sorcerer w/RHD found.", oCaster);
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
//check they have arcane PrC or Draconic Arcane Grace/Breath
|
||||
if(!(GetArcanePRCLevels(oCaster, nCastingClass) - GetLevelByClass(CLASS_TYPE_SUBLIME_CHORD, oCaster))
|
||||
&& !(GetHasFeat(FEAT_DRACONIC_GRACE, oCaster) || GetHasFeat(FEAT_DRACONIC_BREATH, oCaster)))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> First Sublime Chord check.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//check they have sorcerer in first arcane slot
|
||||
//if(GetPrimaryArcaneClass() != CLASS_TYPE_SORCERER)
|
||||
if(GetPrCAdjustedCasterLevelByType(TYPE_ARCANE, oCaster, TRUE) != GetPrCAdjustedCasterLevelByType(CLASS_TYPE_SORCERER, oCaster, TRUE))
|
||||
{
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook: BardSorcPrCCheck >>> GetPrCAdjustedCasterLevelByType.", oCaster);
|
||||
return TRUE;
|
||||
}
|
||||
//at this point, they must be using the bioware spellbook
|
||||
//from a class that adds to bard
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* //check its a sorc spell
|
||||
if(nCastingClass == CLASS_TYPE_SORCERER)
|
||||
{
|
||||
//no need to check further if new spellbooks are disabled
|
||||
if(GetPRCSwitch(PRC_SORC_DISALLOW_NEWSPELLBOOK))
|
||||
return TRUE;
|
||||
@@ -1708,7 +1867,7 @@ int BardSorcPrCCheck(object oCaster, int nCastingClass, object oSpellCastItem)
|
||||
//from a class that adds to sorc
|
||||
FloatingTextStringOnCreature("You must use the new spellbook on the class radial.", oCaster, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
} */
|
||||
|
||||
//check its a bard spell
|
||||
if(nCastingClass == CLASS_TYPE_BARD)
|
||||
@@ -3188,6 +3347,28 @@ int X2PreSpellCastCode2()
|
||||
X2BreakConcentrationSpells();
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Herbal Infusion Use check
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue && (GetBaseItemType(oSpellCastItem) == BASE_ITEM_INFUSED_HERB))
|
||||
{
|
||||
int bIsSubradial = GetIsSubradialSpell(nSpellID);
|
||||
|
||||
if(bIsSubradial)
|
||||
{
|
||||
nSpellID = GetMasterSpellFromSubradial(nSpellID);
|
||||
}
|
||||
int nItemCL = GetCastSpellCasterLevelFromItem(oSpellCastItem, nSpellID);
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Item Spellcaster Level: "+IntToString(nItemCL)+".");
|
||||
|
||||
if(DEBUG) DoDebug("x2_inc_spellhook >> X2PreSpellCastCode2: Herbal Infusion Found");
|
||||
if(!DoInfusionUseChecks(oCaster, oSpellCastItem, nSpellID))
|
||||
{
|
||||
ApplyInfusionPoison(oCaster, nItemCL);
|
||||
nContinue = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// No casting while using expertise
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
@@ -3338,6 +3519,12 @@ int X2PreSpellCastCode2()
|
||||
if (nContinue)
|
||||
nContinue = SpellAlignmentRestrictions(oCaster, nSpellID, nCastingClass);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Verdant Lord Spontaneous Regernate
|
||||
//---------------------------------------------------------------------------
|
||||
if(nContinue)
|
||||
Spontaneity(oCaster, nCastingClass, nSpellID, nSpellLevel);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Druid spontaneous summoning
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
27180
src/module/dlg/oc_ai_henchmen.dlg.json
Normal file
27180
src/module/dlg/oc_ai_henchmen.dlg.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -788,7 +788,7 @@
|
||||
"Mod_Description": {
|
||||
"type": "cexolocstring",
|
||||
"value": {
|
||||
"0": "The Lord of Terror - The Diablo Campaign [PRC8-CEP3]\n\nThis is a remake of the original Diablo game published by Blizzard Entertainment, along with its expansion, Hellfire, published by Sierra Online. This reimagining of the Diablo saga features all the original quests, plus additional story-related side quests that will further enhance the engrossing story of the Diablo saga.\n\nThis module was created by Tolitz Rosel. \n\nRequires PRC 8, CEP 1 & CEP 3 (for visuals)\n\nFor game hints and walkthrough, visit http://nwn.tolitz.com/lordofterror/"
|
||||
"0": "The Lord of Terror - The Diablo Campaign [PRC8-CEP3]\n\nNOW WITH PEPS AI!\n\nThis is a remake of the original Diablo game published by Blizzard Entertainment, along with its expansion, Hellfire, published by Sierra Online. This reimagining of the Diablo saga features all the original quests, plus additional story-related side quests that will further enhance the engrossing story of the Diablo saga.\n\nThis module was created by Tolitz Rosel. \n\nRequires PRC 8, CEP 1 & CEP 3 (for visuals)\n\nFor game hints and walkthrough, visit http://nwn.tolitz.com/lordofterror/"
|
||||
}
|
||||
},
|
||||
"Mod_DuskHour": {
|
||||
@@ -830,6 +830,13 @@
|
||||
"Mod_HakList": {
|
||||
"type": "list",
|
||||
"value": [
|
||||
{
|
||||
"__struct_id": 8,
|
||||
"Mod_Hak": {
|
||||
"type": "cexostring",
|
||||
"value": "peps_prc8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"__struct_id": 8,
|
||||
"Mod_Hak": {
|
||||
@@ -1077,7 +1084,7 @@
|
||||
},
|
||||
"Mod_OnClientEntr": {
|
||||
"type": "resref",
|
||||
"value": "prc_onenter"
|
||||
"value": "hif_onenter"
|
||||
},
|
||||
"Mod_OnClientLeav": {
|
||||
"type": "resref",
|
||||
|
||||
@@ -19955,7 +19955,7 @@
|
||||
"__struct_id": 0,
|
||||
"CR": {
|
||||
"type": "float",
|
||||
"value": 0.5
|
||||
"value": 0.3333
|
||||
},
|
||||
"FACTION": {
|
||||
"type": "cexostring",
|
||||
|
||||
172
src/module/nss/0c_assoc_actions.nss
Normal file
172
src/module/nss/0c_assoc_actions.nss
Normal file
@@ -0,0 +1,172 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_assoc_actions
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Conversation script that sets modes or allows oAssociate to do actions from a
|
||||
conversation.
|
||||
Param "sAction"
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
object oPC = GetPCSpeaker();
|
||||
object oAssociate = OBJECT_SELF;
|
||||
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
|
||||
object oArea = GetArea(oAssociate);
|
||||
string sAction = GetScriptParam("sAction");
|
||||
// Scout ahead is done int 0e_ch_1_hb (heartbeat script).
|
||||
if(sAction == "Scout")
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
ai_HaveCreatureSpeak(oAssociate, 4, ":29:35:46:");
|
||||
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, TRUE);
|
||||
ai_ScoutAhead(oAssociate);
|
||||
}
|
||||
else if(sAction == "BasicTactics")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "");
|
||||
ai_SetAssociateAIScript(oAssociate, FALSE);
|
||||
}
|
||||
else if(sAction == "AmbushTactics")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ambusher");
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ambusher");
|
||||
}
|
||||
else if(sAction == "DefensiveTactics")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_defensive");
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_defensive");
|
||||
}
|
||||
else if(sAction == "RangedTactics")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_ranged");
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_ranged");
|
||||
}
|
||||
else if(sAction == "Taunt")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_taunter");
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_taunter");
|
||||
}
|
||||
else if(sAction == "CounterSpell")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_cntrspell");
|
||||
SetLocalString(oAssociate, AI_DEFAULT_SCRIPT, "ai_a_cntrspell");
|
||||
}
|
||||
else if(sAction == "PeaceTactics")
|
||||
{
|
||||
SetLocalString(oAssociate, AI_COMBAT_SCRIPT, "ai_a_peaceful");
|
||||
}
|
||||
else if(sAction == "AttackTactics")
|
||||
{
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK))
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, FALSE);
|
||||
}
|
||||
else ai_SetAIMode(oAssociate, AI_MODE_CHECK_ATTACK, TRUE);
|
||||
}
|
||||
else if(sAction == "FollowCloser") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
|
||||
else if(sAction == "FollowFarther") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
|
||||
else if(sAction == "Pickup") ai_Loot(oPC, oAssociate, sAssociateType);
|
||||
else if(sAction == "HealSelf") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 1);
|
||||
else if(sAction == "HealAllies") ai_Heal_OnOff(oPC, oAssociate, sAssociateType, 2);
|
||||
else if(sAction == "HealOutMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sAction == "HealOutPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_OUT_OF_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sAction == "HealInMinus") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sAction == "HealInPlus") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
|
||||
else if(sAction == "Traps") ai_Traps(oPC, oAssociate, sAssociateType);
|
||||
else if(sAction == "Locks") ai_Locks(oPC, oAssociate, sAssociateType, 1);
|
||||
else if(sAction == "Bash") ai_Locks(oPC, oAssociate, sAssociateType, 2);
|
||||
else if(sAction == "Search") ai_Search(oPC, oAssociate, sAssociateType);
|
||||
else if(sAction == "Stealth") ai_Stealth(oPC, oAssociate, sAssociateType);
|
||||
else if(sAction == "NoMagic") ai_UseMagic(oPC, oAssociate, sAssociateType);
|
||||
else if(sAction == "DefensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, TRUE, FALSE, sAssociateType);
|
||||
else if(sAction == "OffensiveCasting") ai_UseOffensiveMagic(oPC, oAssociate, FALSE, TRUE, sAssociateType);
|
||||
else if(sAction == "MagicMinus") ai_MagicIncrement(oPC, oAssociate, -1, sAssociateType);
|
||||
else if(sAction == "MagicPlus") ai_MagicIncrement(oPC, oAssociate, 1, sAssociateType);
|
||||
else if(sAction == "Speaking")
|
||||
{
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK))
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, FALSE);
|
||||
}
|
||||
else ai_SetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK, TRUE);
|
||||
}
|
||||
else if(sAction == "Ranged")
|
||||
{
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED))
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, FALSE);
|
||||
}
|
||||
else ai_SetAIMode(oAssociate, AI_MODE_STOP_RANGED, TRUE);
|
||||
}
|
||||
else if(sAction == "AtkAssociates")
|
||||
{
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES))
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, FALSE);
|
||||
}
|
||||
else ai_SetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES, TRUE);
|
||||
}
|
||||
else if(sAction == "BuffFirst")
|
||||
{
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER))
|
||||
{
|
||||
ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, FALSE);
|
||||
}
|
||||
else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER, TRUE);
|
||||
}
|
||||
else if(sAction == "RestBuffing")
|
||||
{
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST))
|
||||
{
|
||||
ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, FALSE);
|
||||
}
|
||||
else ai_SetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST, TRUE);
|
||||
}
|
||||
else if(sAction == "Dispel")
|
||||
{
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL))
|
||||
{
|
||||
ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, FALSE);
|
||||
}
|
||||
else ai_SetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL, TRUE);
|
||||
}
|
||||
else if(sAction == "MagicItems")
|
||||
{
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS))
|
||||
{
|
||||
ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, FALSE);
|
||||
}
|
||||
else ai_SetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS, TRUE);
|
||||
}
|
||||
else if(sAction == "Identify")
|
||||
{
|
||||
ai_IdentifyAllVsKnowledge(oAssociate, oPC, oPC);
|
||||
return;
|
||||
}
|
||||
else if(sAction == "GiveUnIdentifiedItems")
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
object oItem = GetFirstItemInInventory(oAssociate);
|
||||
while(oItem != OBJECT_INVALID)
|
||||
{
|
||||
if(!GetIdentified(oItem)) ActionGiveItem(oItem, oPC);
|
||||
oItem = GetNextItemInInventory(oAssociate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(sAction == "GiveMagicItems")
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
itemproperty ipItemProp;
|
||||
object oItem = GetFirstItemInInventory(oAssociate);
|
||||
while(oItem != OBJECT_INVALID)
|
||||
{
|
||||
ipItemProp = GetFirstItemProperty(oItem);
|
||||
if(GetIsItemPropertyValid(ipItemProp)) ActionGiveItem(oItem, oPC);
|
||||
oItem = GetNextItemInInventory(oAssociate);
|
||||
}
|
||||
return;
|
||||
}
|
||||
aiSaveAssociateModesToDb(oPC, oAssociate);
|
||||
}
|
||||
18
src/module/nss/0c_cast_polymorp.nss
Normal file
18
src/module/nss/0c_cast_polymorp.nss
Normal file
@@ -0,0 +1,18 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0c_cast_polymorp
|
||||
Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Conversation script to have a henchman cast a polymorph spell.
|
||||
int nSpell is the spell to cast.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_items"
|
||||
void main()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
int nSpell = StringToInt (GetScriptParam ("nSpell"));
|
||||
// Save the original form so we can check when we turn back (Add 1 so we don't save a 0!).
|
||||
SetLocalInt (oHenchman, AI_NORMAL_FORM, GetAppearanceType (oHenchman) + 1);
|
||||
SetLocalString (oHenchman, AI_COMBAT_SCRIPT, "ai_a_polymorphed");
|
||||
ActionCastSpellAtObject (nSpell, oHenchman, 255, TRUE);
|
||||
}
|
||||
|
||||
15
src/module/nss/0c_fire_henchmen.nss
Normal file
15
src/module/nss/0c_fire_henchmen.nss
Normal file
@@ -0,0 +1,15 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_fire_henchmen
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Action taken script to fire/remove henchman for higher.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
ai_ClearCreatureActions();
|
||||
ai_FireHenchman (GetPCSpeaker(), oHenchman);
|
||||
PlayVoiceChat (VOICE_CHAT_GOODBYE, oHenchman);
|
||||
}
|
||||
|
||||
22
src/module/nss/0c_get_convo.nss
Normal file
22
src/module/nss/0c_get_convo.nss
Normal file
@@ -0,0 +1,22 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_get_convo
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Action taken script that leaves the current conversation and starts a new
|
||||
conversation with oCreature using the linked conversation instead of the
|
||||
ai_Henchman conversation.
|
||||
|
||||
Allows use of ai_conversation for henchman in other modules.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void BeginOriginalHenchmanConversation(string sDialog, object oPC)
|
||||
{
|
||||
BeginConversation(sDialog, oPC);
|
||||
}
|
||||
void main()
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
// Need to check special dialogs for HOTU henchman.
|
||||
string sDialog = GetDialogFileToUse(GetLastSpeaker());
|
||||
DelayCommand(0.0, BeginOriginalHenchmanConversation(sDialog, GetPCSpeaker()));
|
||||
}
|
||||
25
src/module/nss/0c_get_henchman.nss
Normal file
25
src/module/nss/0c_get_henchman.nss
Normal file
@@ -0,0 +1,25 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_get_henchman
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Action taken script that adds oCreature to oPC's party as a henchman
|
||||
while giving a random message.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
object oPC = GetPCSpeaker();
|
||||
AddHenchman(oPC, oCreature);
|
||||
int nVoice;
|
||||
switch(d4())
|
||||
{
|
||||
case 1: nVoice = VOICE_CHAT_CANDO; break;
|
||||
case 2: nVoice = VOICE_CHAT_CHEER; break;
|
||||
case 3: nVoice = VOICE_CHAT_GOODIDEA; break;
|
||||
case 4: nVoice = VOICE_CHAT_LAUGH; break;
|
||||
}
|
||||
PlayVoiceChat(nVoice, oCreature);
|
||||
}
|
||||
|
||||
|
||||
12
src/module/nss/0c_h_cast_spell.nss
Normal file
12
src/module/nss/0c_h_cast_spell.nss
Normal file
@@ -0,0 +1,12 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_cast_spell
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Action taken script that sets the specified spell to be cast.
|
||||
Param
|
||||
nSpell - the spell to cast.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
void main()
|
||||
{
|
||||
SetLocalInt (OBJECT_SELF, "0_SPELL_TO_CAST", StringToInt (GetScriptParam ("nSpell")));
|
||||
}
|
||||
81
src/module/nss/0c_henchmenspell.nss
Normal file
81
src/module/nss/0c_henchmenspell.nss
Normal file
@@ -0,0 +1,81 @@
|
||||
/*///////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_henchmenspell
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Action script to cast a specific spell for a henchman.
|
||||
|
||||
Script Param
|
||||
nTarget (INT) : 0 = ALL, 1 PC, 2 Caster, 3-6 = oPC's Henchman, 7 = PC's Familiar
|
||||
8 = PC's Animal Companion, 9 = PC's Summon.
|
||||
nBuffType = 1 all 2 short 3 long, 4 healing, 5 lay on hands.
|
||||
If nBuffType is 0 then it will cast a specific spell from
|
||||
Variable "0_SPELL_TO_CAST". Use script: 0c_h_spell_cast spell to set the spell.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCaster);
|
||||
void main()
|
||||
{
|
||||
object oTarget, oPC = GetPCSpeaker();
|
||||
object oCreature = OBJECT_SELF;
|
||||
float fDelay;
|
||||
int nTarget = StringToInt(GetScriptParam("nTarget"));
|
||||
int nBuffType = StringToInt(GetScriptParam("nBuffType"));
|
||||
// Cast a group of buff spells based on nBuffType and nTarget or a single spell.
|
||||
if(nBuffType < 4)
|
||||
{
|
||||
// Cast a specific spell.
|
||||
if(nBuffType == 0)
|
||||
{
|
||||
int nSpell = GetLocalInt(oCreature, "0_SPELL_TO_CAST");
|
||||
// These are buff spells so Acid fog (index 0) is not a valid spell.
|
||||
if(nSpell > 0)
|
||||
{
|
||||
ai_ClearCreatureActions();
|
||||
object oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
|
||||
if(oTarget != OBJECT_INVALID && ai_CheckAndCastSpell(oCreature, nSpell, 0, 0.0f, oTarget, oPC))
|
||||
{
|
||||
DeleteLocalInt(oCreature, "0_SPELL_TO_CAST");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature);
|
||||
string sSpellName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
|
||||
ai_SendMessages("I cannot cast " + sSpellName + ".", AI_COLOR_RED, oPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Cast a creatures buff spells on nTarget.
|
||||
else ai_CastBuffs(oCreature, nBuffType, nTarget, oPC);
|
||||
}
|
||||
// Cast Healing spells.
|
||||
else if(nBuffType == 4)
|
||||
{
|
||||
ai_SetupAllyTargets(oCreature, oPC);
|
||||
oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
|
||||
ai_TryHealing(oCreature, oTarget);
|
||||
}
|
||||
// Use lay on hands.
|
||||
else if(nBuffType == 5)
|
||||
{
|
||||
ai_SetupAllyTargets(oCreature, oPC);
|
||||
oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
|
||||
ai_UseLayOnHands(oTarget, oPC, 0.0f, oCreature);
|
||||
}
|
||||
else if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CUSS, oCreature);
|
||||
}
|
||||
float ai_UseLayOnHands(object oTarget, object oPC, float fDelay, object oCreature)
|
||||
{
|
||||
int nHpLost = GetMaxHitPoints(oTarget) - GetCurrentHitPoints(oTarget);
|
||||
if(!nHpLost)
|
||||
{
|
||||
if(!ai_GetAIMode(oCreature, AI_MODE_DO_NOT_SPEAK)) PlayVoiceChat(VOICE_CHAT_CANTDO, oCreature);
|
||||
ai_SendMessages(GetName(oTarget) + " does not need healed.", AI_COLOR_RED, oPC);
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_SendMessages(GetName(oCreature) + " is laying hands on " + GetName(oTarget), AI_COLOR_GREEN, oPC);
|
||||
ActionUseFeat(FEAT_LAY_ON_HANDS, oTarget);
|
||||
fDelay += 6.0f;
|
||||
}
|
||||
return fDelay;
|
||||
}
|
||||
16
src/module/nss/0c_if_a_magic_m.nss
Normal file
16
src/module/nss/0c_if_a_magic_m.nss
Normal file
@@ -0,0 +1,16 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_a_magic_m
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if the henchmen has a specific
|
||||
associate magic mode.
|
||||
Param:
|
||||
nMode - The mode to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
int nMode = StringToInt(GetScriptParam("nMode"));
|
||||
return ai_GetMagicMode (oHenchman, nMode);
|
||||
}
|
||||
132
src/module/nss/0c_if_ass_convo.nss
Normal file
132
src/module/nss/0c_if_ass_convo.nss
Normal file
@@ -0,0 +1,132 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_ass_convo
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that has the henchman tell the player what options
|
||||
have been selected.
|
||||
|
||||
sOption will decide what the henchman says.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oPC = GetPCSpeaker();
|
||||
object oAssociate = OBJECT_SELF;
|
||||
string sParam = GetScriptParam("sOption");
|
||||
if(sParam == "BaseMode")
|
||||
{
|
||||
string sBaseMode = "I'm ready to attack.";
|
||||
string sVolume = " While shouting when I see things.";
|
||||
// Lets get which base mode the henchman is in.
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_STAND_GROUND)) sBaseMode = "I'm holding here.";
|
||||
else if(ai_GetAIMode(oAssociate, AI_MODE_DEFEND_MASTER)) sBaseMode = "I'm defending you.";
|
||||
else if(ai_GetAIMode(oAssociate, AI_MODE_FOLLOW)) sBaseMode = "I'm following you.";
|
||||
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful") sBaseMode = "I will not fight the enemy!";
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_DO_NOT_SPEAK)) sVolume = " While not speaking unless spoken to.";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN, sBaseMode + sVolume);
|
||||
}
|
||||
else if(sParam == "CombatTactics")
|
||||
{
|
||||
string sRangedUse = "", sCombatTactic = "I'm using my best judgement in combat ";
|
||||
string sAtkAssociates = "";
|
||||
string sTargets = "against all enemies and ";
|
||||
// Lets get which base mode the henchman is in.
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_CHECK_ATTACK)) sTargets = "against enemies I can handle and ";
|
||||
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_ambusher") sCombatTactic = "I'm using ambush tactics ";
|
||||
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_defensive") sCombatTactic = "I'm using defensive tactics ";
|
||||
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_taunter") sCombatTactic = "I'm ready to taunt ";
|
||||
else if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell") sCombatTactic = "I'm ready to counter spell ";
|
||||
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_peaceful")
|
||||
{
|
||||
sCombatTactic = "I will not fight the enemy!";
|
||||
sTargets = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_STOP_RANGED)) sRangedUse = "will not use a ranged weapon.";
|
||||
else sRangedUse = "will use a ranged weapon.";
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_IGNORE_ASSOCIATES)) sAtkAssociates = " I will also ignore familiars, companions, and summons.";
|
||||
else sAtkAssociates = " I will also attack familiars, companions, and summons.";
|
||||
}
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 1, sCombatTactic + sTargets + sRangedUse + sAtkAssociates);
|
||||
}
|
||||
else if(sParam == "Plans")
|
||||
{
|
||||
float fFollowRange = GetLocalFloat(oAssociate, AI_FOLLOW_RANGE);
|
||||
string sFollowRange = FloatToString(fFollowRange, 0, 0);
|
||||
string sDistance = "I'm following from " + sFollowRange + " meters away while";
|
||||
string sStealth, sSearch, sPickup;
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_PICKUP_ITEMS)) sPickup = " picking up items";
|
||||
else sPickup = " not picking up any items";
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_STEALTH)) sStealth = " in stealth";
|
||||
else sStealth = "";
|
||||
if(ai_GetAIMode(oAssociate, AI_MODE_AGGRESSIVE_SEARCH)) sSearch = " and searching";
|
||||
else sSearch = "";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 2, sDistance + sPickup + sStealth + sSearch + ".");
|
||||
}
|
||||
else if(sParam == "Healing")
|
||||
{
|
||||
string sHealingIn = IntToString(GetLocalInt(oAssociate, AI_HEAL_IN_COMBAT_LIMIT)) + "%";
|
||||
string sHealingOut = IntToString(GetLocalInt(oAssociate, AI_HEAL_OUT_OF_COMBAT_LIMIT)) + "%";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, "I'm healing our allies if they go below " +
|
||||
sHealingIn + " health in combat and " + sHealingOut + " out of combat.");
|
||||
}
|
||||
else if(sParam == "Spells")
|
||||
{
|
||||
string sCastingLevel = "[" + IntToString(GetLocalInt(oAssociate, AI_DIFFICULTY_ADJUSTMENT)) + "] ";
|
||||
string sCasting = "I'm casting";
|
||||
string sType = " spells I choose.";
|
||||
string sBuff = " I'll also targeting anyone that needs it ";
|
||||
string sDispel = "while using Dispel spells.";
|
||||
string sMagicItems = " Lastly I'll use any magic items I have.";
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_MASTER)) sBuff = " Ofcourse I'll target you first ";
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_STOP_DISPEL)) sDispel = "while not using Dispel spells.";
|
||||
if(GetLocalString(oAssociate, AI_COMBAT_SCRIPT) == "ai_a_cntrspell")
|
||||
{
|
||||
sCasting = "I'm ready to counter spell our enemies.";
|
||||
sType = "";
|
||||
sBuff = "";
|
||||
sDispel = "";
|
||||
}
|
||||
if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC))
|
||||
{
|
||||
sCasting = "I'm not use any magic.";
|
||||
sType = "";
|
||||
sBuff = "";
|
||||
sDispel = "";
|
||||
}
|
||||
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_DEFENSIVE_CASTING)) sType = " defensive spells only.";
|
||||
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_OFFENSIVE_CASTING))
|
||||
{
|
||||
sType = " offensive spells only.";
|
||||
sBuff = "";
|
||||
}
|
||||
else if(ai_GetMagicMode(oAssociate, AI_MAGIC_NO_MAGIC_ITEMS)) sMagicItems = " Finally I'll not use magic items.";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 5, sCastingLevel + sCasting + sType + sBuff + sDispel+ sMagicItems);
|
||||
}
|
||||
else if(sParam == "Objects")
|
||||
{
|
||||
int bTraps = ai_GetAIMode(oAssociate, AI_MODE_DISARM_TRAPS);
|
||||
int bLocks = ai_GetAIMode(oAssociate, AI_MODE_PICK_LOCKS);
|
||||
int bBash = ai_GetAIMode(oAssociate, AI_MODE_BASH_LOCKS);
|
||||
string sText = "I'm going to ignore all traps and locks.";
|
||||
if(bTraps && bLocks && bBash)
|
||||
{
|
||||
sText = "I'm disarming all the traps and am either picking or bashing any of the locks we find.";
|
||||
}
|
||||
else if(bTraps && bLocks) sText = "I'm going to disarm all the traps and I'll pick all the locks we encounter.";
|
||||
else if(bTraps && bBash) sText = "I shall disarm all the traps and will bash any locks we come across.";
|
||||
else if(bTraps) sText = "I will disarm all the traps I can but will leave any locks for you to deal with.";
|
||||
else if(bLocks && bBash) sText = "I will leave the traps for you but will either pick or bash any locks we see.";
|
||||
else if(bLocks) sText = "I'll keep my distance from any traps we see, but will pick the locks found.";
|
||||
else if(bBash) sText = "I'll let you mess with the traps, but I'll bash any locks that are out there.";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 3, sText);
|
||||
}
|
||||
else if(sParam == "RestBuffing")
|
||||
{
|
||||
string sRestBuffing = "";
|
||||
if(!ai_GetMagicMode(oAssociate, AI_MAGIC_BUFF_AFTER_REST)) sRestBuffing = "not ";
|
||||
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 10, "After we rest I am " + sRestBuffing + "casting my long buff spells on us.");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
22
src/module/nss/0c_if_assoc_mode.nss
Normal file
22
src/module/nss/0c_if_assoc_mode.nss
Normal file
@@ -0,0 +1,22 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_assoc_mode
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if the henchmen has a specific
|
||||
associate mode.
|
||||
Param:
|
||||
nMode - The mode to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
int nMode = StringToInt(GetScriptParam("nMode"));
|
||||
// This conversation line turns off picking up any items.
|
||||
if (nMode == -1)
|
||||
{
|
||||
if(ai_SetAIMode (oHenchman, AI_MODE_PICKUP_ITEMS)) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
return ai_GetAIMode (oHenchman, nMode);
|
||||
}
|
||||
17
src/module/nss/0c_if_cntrspell.nss
Normal file
17
src/module/nss/0c_if_cntrspell.nss
Normal file
@@ -0,0 +1,17 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_cntrspell
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that returns TRUE the server allows a henchman to
|
||||
use counterspell and if they don't have the counterspell ai script set.
|
||||
Param:
|
||||
sAIScript - The special combat script to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
return (AI_COUNTERSPELLING_ON &&
|
||||
ai_CheckClassType(oHenchman, AI_CLASS_TYPE_CASTER) &&
|
||||
GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_cntrspell");
|
||||
}
|
||||
16
src/module/nss/0c_if_com_script.nss
Normal file
16
src/module/nss/0c_if_com_script.nss
Normal file
@@ -0,0 +1,16 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_com_script
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that returns TRUE the caller does have an ai combat
|
||||
script set to sAIScript.
|
||||
Param:
|
||||
sAIScript - The special combat script to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
string sAIScript = GetScriptParam("sAIScript");
|
||||
string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT);
|
||||
return (sAIScript == sAICombatScript);
|
||||
}
|
||||
21
src/module/nss/0c_if_convo.nss
Normal file
21
src/module/nss/0c_if_convo.nss
Normal file
@@ -0,0 +1,21 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_if_convo
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that check if oCreature has a linked conversation.
|
||||
Only checks for Henchman.
|
||||
Allows use of ai_conversation for henchman in other modules.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "nw_inc_gff"
|
||||
#include "0i_messages"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
if(GetAssociateType(oHenchman) == ASSOCIATE_TYPE_HENCHMAN)
|
||||
{
|
||||
json jHenchman = ObjectToJson(oHenchman);
|
||||
string sConversation = JsonGetString(GffGetResRef(jHenchman, "Conversation"));
|
||||
if(sConversation != "") return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
18
src/module/nss/0c_if_has_assoc.nss
Normal file
18
src/module/nss/0c_if_has_assoc.nss
Normal file
@@ -0,0 +1,18 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_has_assoc
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if caller has the specified feat
|
||||
to summon either a companion or a familiar and they are not summoned.
|
||||
Param
|
||||
sAssociate - "Familiar" or "Companion"
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
string sAssociate = GetScriptParam("sAssociate");
|
||||
if(sAssociate == "Familiar" && GetHasFeat(FEAT_SUMMON_FAMILIAR, oHenchman) &&
|
||||
GetAssociate(ASSOCIATE_TYPE_FAMILIAR) == OBJECT_INVALID) return TRUE;
|
||||
return (sAssociate == "Companion" && GetHasFeat(FEAT_ANIMAL_COMPANION, oHenchman) &&
|
||||
GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION) == OBJECT_INVALID);
|
||||
}
|
||||
28
src/module/nss/0c_if_has_class.nss
Normal file
28
src/module/nss/0c_if_has_class.nss
Normal file
@@ -0,0 +1,28 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_has_class
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if conversation owner has a
|
||||
specified class. Multiple classes maybe selected.
|
||||
Param
|
||||
nClass# - the class to look for use nClass1, nClass2, nClass3 for each one to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
int nCntr = 1;
|
||||
int nClass;
|
||||
string sClass;
|
||||
while(nCntr < 10)
|
||||
{
|
||||
sClass = GetScriptParam("nClass" + IntToString(nCntr));
|
||||
if(sClass != "")
|
||||
{
|
||||
nClass = StringToInt(sClass);
|
||||
if(GetLevelByClass(nClass, oHenchman)) return TRUE;
|
||||
nCntr++;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
22
src/module/nss/0c_if_has_feat.nss
Normal file
22
src/module/nss/0c_if_has_feat.nss
Normal file
@@ -0,0 +1,22 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_has_feat
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if they have a specific feat.
|
||||
Param:
|
||||
sTarget - either "OBJECT_SELF", or "PCSpeaker", blanks defaults to "PCSpeaker"
|
||||
nFeat - the feat number from Feats.2da
|
||||
bNot - if 1 TRUE then this returns true for the target not having the feat.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_main"
|
||||
int StartingConditional()
|
||||
{
|
||||
string sTarget = GetScriptParam("sTarget");
|
||||
int nFeat = StringToInt(GetScriptParam("nFeat"));
|
||||
int bNot = StringToInt(GetScriptParam("bNot"));
|
||||
object oCreature;
|
||||
if(sTarget == "OBJECT_SELF") oCreature = OBJECT_SELF;
|
||||
else if(sTarget == "" || sTarget == "PCSpeaker") oCreature = GetPCSpeaker();
|
||||
if(bNot) return !GetHasFeat(nFeat, oCreature);
|
||||
return (GetHasFeat(nFeat ,oCreature) || ai_GetIsDungeonMaster(oCreature));
|
||||
}
|
||||
26
src/module/nss/0c_if_has_spell.nss
Normal file
26
src/module/nss/0c_if_has_spell.nss
Normal file
@@ -0,0 +1,26 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_has_spell
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if caster can cast the specified spell.
|
||||
Param
|
||||
nSpell# - the spell to look for nSpell1, sSpell2, nSpell3 for each spell to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_spells"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oCaster = OBJECT_SELF;
|
||||
int nCnt = 1;
|
||||
int nSpell;
|
||||
string sSpell;
|
||||
while(nCnt < 20)
|
||||
{
|
||||
sSpell = GetScriptParam("nSpell" + IntToString(nCnt));
|
||||
if(sSpell == "") return FALSE;
|
||||
nSpell = StringToInt(sSpell);
|
||||
if(GetHasSpell(nSpell, oCaster)) return TRUE;
|
||||
//else if(ai_GetKnownSpell(oCaster, nSpell)) return TRUE;
|
||||
nCnt++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
12
src/module/nss/0c_if_hen_leave.nss
Normal file
12
src/module/nss/0c_if_hen_leave.nss
Normal file
@@ -0,0 +1,12 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_hen_leave
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that check if allowing the player to remove a henchman
|
||||
is activated on this server.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
return AI_REMOVE_HENCHMAN_ON;
|
||||
}
|
||||
17
src/module/nss/0c_if_identify.nss
Normal file
17
src/module/nss/0c_if_identify.nss
Normal file
@@ -0,0 +1,17 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_identify
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if the henchmen has a better lore
|
||||
skill than the speaker.
|
||||
Also checks AI_IDENTIFY_ON to see if the server wants them to help.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
if (!AI_IDENTIFY_ON && !ai_CanISpeak (oHenchman)) return FALSE;
|
||||
int nHenchmanLore = GetSkillRank(SKILL_LORE, oHenchman);
|
||||
int nMasterLore = GetSkillRank(SKILL_LORE, GetMaster(oHenchman));
|
||||
return (nHenchmanLore > nMasterLore);
|
||||
}
|
||||
11
src/module/nss/0c_if_not_master.nss
Normal file
11
src/module/nss/0c_if_not_master.nss
Normal file
@@ -0,0 +1,11 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_not_master
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks if the speaker is the master of this
|
||||
henchman.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
int StartingConditional()
|
||||
{
|
||||
return !GetIsObjectValid(GetMaster());
|
||||
}
|
||||
13
src/module/nss/0c_if_open_inven.nss
Normal file
13
src/module/nss/0c_if_open_inven.nss
Normal file
@@ -0,0 +1,13 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_open_equip
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks if opening a henchmans inventory
|
||||
is activated on this server.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
if(GetAssociateType(OBJECT_SELF) != ASSOCIATE_TYPE_HENCHMAN) return FALSE;
|
||||
return AI_OPEN_INVENTORY;
|
||||
}
|
||||
12
src/module/nss/0c_if_pickuploot.nss
Normal file
12
src/module/nss/0c_if_pickuploot.nss
Normal file
@@ -0,0 +1,12 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_pickuploot
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that check if having associates picking up loot is
|
||||
activated on this server.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
return AI_PICKUP_LOOT;
|
||||
}
|
||||
11
src/module/nss/0c_if_polymorph.nss
Normal file
11
src/module/nss/0c_if_polymorph.nss
Normal file
@@ -0,0 +1,11 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_polymorph
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if the caller is polymorphed.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
if (GetLocalInt(OBJECT_SELF, AI_NORMAL_FORM) != 0) return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
11
src/module/nss/0c_if_scout.nss
Normal file
11
src/module/nss/0c_if_scout.nss
Normal file
@@ -0,0 +1,11 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_scout
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that check if scouting is activated on this server.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
return AI_SCOUT_AHEAD_ON;
|
||||
}
|
||||
18
src/module/nss/0c_if_skillrank.nss
Normal file
18
src/module/nss/0c_if_skillrank.nss
Normal file
@@ -0,0 +1,18 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_SkillRank
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that checks to see if the caller's skill ranks
|
||||
are above or equal to the param value.
|
||||
Param:
|
||||
nSkill - the skill number for the skill. See skills.2da.
|
||||
nRank - the rank required.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_main"
|
||||
int StartingConditional()
|
||||
{
|
||||
string sSkill = GetScriptParam("nSkill");
|
||||
if(sSkill == "") return FALSE;
|
||||
int nRank = StringToInt(GetScriptParam("nRank"));
|
||||
return (GetSkillRank(StringToInt(sSkill)) >= nRank);
|
||||
}
|
||||
15
src/module/nss/0c_if_taunt.nss
Normal file
15
src/module/nss/0c_if_taunt.nss
Normal file
@@ -0,0 +1,15 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_if_taunt
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that returns TRUE the server allows a henchman to
|
||||
taunt and if they have the don't have the taunt ai script set.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
object oHenchman = OBJECT_SELF;
|
||||
return (AI_TAUNTING_ON &&
|
||||
GetSkillRank(SKILL_TAUNT, oHenchman) > ai_GetCharacterLevels(oHenchman) &&
|
||||
GetLocalString(oHenchman, AI_COMBAT_SCRIPT) != "ai_a_taunter");
|
||||
}
|
||||
19
src/module/nss/0c_listhenchman.nss
Normal file
19
src/module/nss/0c_listhenchman.nss
Normal file
@@ -0,0 +1,19 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0c_cast_polymorp
|
||||
Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Conversation script to setup the tokens for the henchman in the speakers party
|
||||
except for who they are talking to.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void main()
|
||||
{
|
||||
object oSpeaker = OBJECT_SELF;
|
||||
object oPC = GetPCSpeaker();
|
||||
int nCntr = 1;
|
||||
object oHenchman = GetHenchman(oPC, nCntr);
|
||||
while(oHenchman != OBJECT_INVALID)
|
||||
{
|
||||
if(oHenchman != oSpeaker) SetCustomToken(77100 + nCntr, GetName(oHenchman));
|
||||
oHenchman = GetHenchman(oPC, ++nCntr);
|
||||
}
|
||||
}
|
||||
27
src/module/nss/0c_no_com_script.nss
Normal file
27
src/module/nss/0c_no_com_script.nss
Normal file
@@ -0,0 +1,27 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0c_no_com_script
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Text Appears When script that returns TRUE the caller does not have an ai combat
|
||||
script set to sAIScript.
|
||||
if sAIScript is blank then if its equal to all of them.
|
||||
Param: sAIScripts:"ai_a_ambusher", "ai_a_defensive", "ai_a_taunter", "ai_coward".
|
||||
sAIScript - The special combat script to check.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
int StartingConditional()
|
||||
{
|
||||
string sAIScript = GetScriptParam("sAIScript");
|
||||
string sAICombatScript = GetLocalString (OBJECT_SELF, AI_COMBAT_SCRIPT);
|
||||
// This is the value for do your own thing in combat!
|
||||
if (sAIScript == "")
|
||||
{
|
||||
return (sAICombatScript == "ai_a_ambusher" ||
|
||||
sAICombatScript == "ai_a_defensive" ||
|
||||
sAICombatScript == "ai_a_ranged" ||
|
||||
sAICombatScript == "ai_a_taunter" ||
|
||||
sAICombatScript == "ai_a_cntrspell" ||
|
||||
sAICombatScript == "ai_a_peaceful");
|
||||
}
|
||||
return (sAIScript != sAICombatScript);
|
||||
}
|
||||
14
src/module/nss/0c_remove_effect.nss
Normal file
14
src/module/nss/0c_remove_effect.nss
Normal file
@@ -0,0 +1,14 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script:0c_remove_effect
|
||||
Programmer:Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Actions Taken script that removes an effect from OBJECT_SELF.
|
||||
Param: nEffect - the EFFECT_TYPE_* number to remove.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_spells"
|
||||
void main ()
|
||||
{
|
||||
int nEffect = StringToInt (GetScriptParam ("nEffectType"));
|
||||
ai_RemoveASpecificEffect (OBJECT_SELF, nEffect);
|
||||
}
|
||||
|
||||
17
src/module/nss/0c_summon_assoc.nss
Normal file
17
src/module/nss/0c_summon_assoc.nss
Normal file
@@ -0,0 +1,17 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0c_summon_assoc
|
||||
Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Conversation script to have the caller summon either an animal companion or
|
||||
familiar associate.
|
||||
|
||||
Param
|
||||
sAssociate - which associate to summon.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
string sAssociate = GetScriptParam ("sAssociate");
|
||||
if (sAssociate == "Familiar") SummonFamiliar ();
|
||||
else if (sAssociate == "Companion") SummonAnimalCompanion ();
|
||||
}
|
||||
15
src/module/nss/0c_use_feat.nss
Normal file
15
src/module/nss/0c_use_feat.nss
Normal file
@@ -0,0 +1,15 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0c_summon_assoc
|
||||
Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Conversation script to have the caller use nFeat from the feat.2da.
|
||||
|
||||
Param
|
||||
nFeat - Feat number from the feat.2da.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
int nFeat = StringToInt (GetScriptParam ("nFeat"));
|
||||
ActionUseFeat(nFeat, OBJECT_SELF);
|
||||
}
|
||||
16
src/module/nss/0e_c2_1_hb.nss
Normal file
16
src/module/nss/0e_c2_1_hb.nss
Normal file
@@ -0,0 +1,16 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_c2_1_hb
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Monster OnHeartbeat script;
|
||||
This will usually fire every 6 seconds (1 game round).
|
||||
|
||||
I am reverting the AI script back to the games default scripts for efficiency.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_module"
|
||||
void main()
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE);
|
||||
ai_ChangeEventScriptsForMonster(OBJECT_SELF);
|
||||
ExecuteScript("nw_c2_default1");
|
||||
}
|
||||
32
src/module/nss/0e_c2_7_ondeath.nss
Normal file
32
src/module/nss/0e_c2_7_ondeath.nss
Normal file
@@ -0,0 +1,32 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_c2_7_ondeath
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Monster OnDeath script;
|
||||
This fires when the creature dies.
|
||||
*////////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_module"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Added code to allow for permanent associates in the battle!
|
||||
object oModule = GetModule();
|
||||
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
|
||||
{
|
||||
object oAssociate;
|
||||
int nIndex;
|
||||
for(nIndex = 1; nIndex < 5; nIndex++)
|
||||
{
|
||||
oAssociate = GetAssociate(nIndex, oCreature);
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
SetIsDestroyable(FALSE, FALSE, FALSE);
|
||||
DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(GetLocalInt(oModule, AI_RULE_CORPSES_STAY)) SetIsDestroyable(FALSE, FALSE, TRUE);
|
||||
ai_ClearCombatState(oCreature);
|
||||
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"));
|
||||
}
|
||||
|
||||
14
src/module/nss/0e_ch_1_hb.nss
Normal file
14
src/module/nss/0e_ch_1_hb.nss
Normal file
@@ -0,0 +1,14 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_ch_1_hb
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Associate(Summons, Familiar, Companion) OnHeart beat script when out of combat;
|
||||
This will usually fire every 6 seconds (1 game round).
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_module"
|
||||
void main()
|
||||
{
|
||||
SetLocalInt(OBJECT_SELF, AI_ONSPAWN_EVENT, TRUE);
|
||||
ai_ChangeEventScriptsForAssociate(OBJECT_SELF);
|
||||
ExecuteScript("nw_ch_ac1");
|
||||
}
|
||||
41
src/module/nss/0e_ch_7_ondeath.nss
Normal file
41
src/module/nss/0e_ch_7_ondeath.nss
Normal file
@@ -0,0 +1,41 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_ch_7_ondeath
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Associate OnSpawn script;
|
||||
This fires when an associate dies.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_module"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// Added code to allow for permanent associates in the battle!
|
||||
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!" +
|
||||
" AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(GetModule(), AI_RULE_PERM_ASSOC)));
|
||||
object oModule = GetModule();
|
||||
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
|
||||
{
|
||||
object oAssociate;
|
||||
int nIndex;
|
||||
for(nIndex = 2; nIndex < 5; nIndex++)
|
||||
{
|
||||
oAssociate = GetAssociate(nIndex, oCreature);
|
||||
if(oAssociate != OBJECT_INVALID)
|
||||
{
|
||||
SetIsDestroyable(FALSE, FALSE, FALSE);
|
||||
ChangeFaction(oAssociate, oCreature);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Remove the widget!
|
||||
object oPC = GetMaster(oCreature);
|
||||
if(oPC != OBJECT_INVALID)
|
||||
{
|
||||
NuiDestroy(oPC, NuiFindWindow(oPC, ai_GetAssociateType(oPC, oCreature) + AI_WIDGET_NUI));
|
||||
DelayCommand(0.5, ai_CheckXPPartyScale(oCreature));
|
||||
DelayCommand(2.0, ai_ClearCreatureActions(TRUE));
|
||||
}
|
||||
DelayCommand(2.0, ai_ClearCombatState(oCreature));
|
||||
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"));
|
||||
}
|
||||
|
||||
22
src/module/nss/0e_do_combat_rnd.nss
Normal file
22
src/module/nss/0e_do_combat_rnd.nss
Normal file
@@ -0,0 +1,22 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_do_combat_rnd
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Used to execute a combat round just after the current action is over.
|
||||
Note: Do not use with an attack action since it will continue until
|
||||
the attacked enemy is dead. We end attack actions with a ClearAllActions
|
||||
command and would also end this one so it will not work with attack actions.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_associates"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
if(AI_DEBUG) ai_Debug("0e_do_combat_rnd", "14", GetName(oCreature) + " is calculating a new round." +
|
||||
"nAction: " + IntToString(GetCurrentAction(oCreature)));
|
||||
if(ai_GetIsInCombat(oCreature))
|
||||
{
|
||||
if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_NONE &&
|
||||
!ai_GetIsCharacter(oCreature)) ai_DoMonsterCombatRound(oCreature);
|
||||
else if(ai_CanIAttack(oCreature)) ai_DoAssociateCombatRound(oCreature);
|
||||
}
|
||||
}
|
||||
60
src/module/nss/0e_gui_events.nss
Normal file
60
src/module/nss/0e_gui_events.nss
Normal file
@@ -0,0 +1,60 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0e_gui_events
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OnPlayerGUIEvent event script
|
||||
Used to allow PEPS to gain control of specific GUI events.
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_gui_events"
|
||||
#include "0i_menus"
|
||||
void main()
|
||||
{
|
||||
object oPC = GetLastGuiEventPlayer();
|
||||
int nEventType = GetLastGuiEventType();
|
||||
int nEventInt = GetLastGuiEventInteger();
|
||||
//object oEventObject = GetLastGuiEventObject();
|
||||
switch(nEventType)
|
||||
{
|
||||
case GUIEVENT_EFFECTICON_CLICK:
|
||||
{
|
||||
if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT))
|
||||
{
|
||||
ai_CreateEffectChatReport(oPC, nEventInt);
|
||||
return;
|
||||
}
|
||||
int nToken = NuiFindWindow(oPC, AI_EFFECT_ICON_NUI);
|
||||
json jData;
|
||||
if(nToken)
|
||||
{
|
||||
jData = NuiGetUserData(oPC, nToken);
|
||||
int nOldEffectIcon = JsonGetInt(JsonArrayGet(jData, 1));
|
||||
DelayCommand(0.0, NuiDestroy(oPC, nToken));
|
||||
if(nOldEffectIcon == nEventInt) return;
|
||||
}
|
||||
ai_CreateEffectIconMenu(oPC, nEventInt);
|
||||
}
|
||||
case GUIEVENT_PARTYBAR_PORTRAIT_CLICK:
|
||||
{
|
||||
object oAssociate = GetLastGuiEventObject();
|
||||
if(GetMaster(oAssociate) == oPC)
|
||||
{
|
||||
// If all the Command buttons are blocked then don't load the menu.
|
||||
if(GetLocalInt(GetModule(), sDMWidgetAccessVarname) != 7340028)
|
||||
{
|
||||
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
|
||||
if(IsWindowClosed(oPC, sAssociateType + AI_COMMAND_NUI))
|
||||
{
|
||||
ai_CreateAssociateCommandNUI(oPC, oAssociate);
|
||||
}
|
||||
IsWindowClosed(oPC, sAssociateType + AI_NUI);
|
||||
IsWindowClosed(oPC, sAssociateType + AI_LOOTFILTER_NUI);
|
||||
IsWindowClosed(oPC, sAssociateType + AI_COPY_NUI);
|
||||
IsWindowClosed(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
|
||||
IsWindowClosed(oPC, sAssociateType + AI_SPELL_MEMORIZE_NUI);
|
||||
IsWindowClosed(oPC, sAssociateType + AI_SPELL_KNOWN_NUI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/module/nss/0e_m1_3_endround.nss
Normal file
46
src/module/nss/0e_m1_3_endround.nss
Normal file
@@ -0,0 +1,46 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_m1_3_endround
|
||||
Original Script: m1_combanter_3
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Monster OnCombatRoundEnd event script used in the original campaign
|
||||
for monsters that may do a one liner during combat;
|
||||
|
||||
Fires at the end of each combat round (6 seconds).
|
||||
This will fire as long as oCreature is in combat (GetIsInCombat()).
|
||||
This event starts counting once a combat action is started.
|
||||
Every time a spell is cast it will queue another end combat round so haste with
|
||||
two spells cast will fire this twice in one round.
|
||||
It will also fire at the end of a hostile effect that stops actions i.e Stunned, Knockdown etc.
|
||||
Action modes are also cleared prior to this event executing!
|
||||
GetAttemptedAttackTarget() & GetAttemptedSpellTarget() also get cleared prior to this event.
|
||||
This event can be canceled with ClearAllActions(TRUE) and SurrenderToEnemies.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
if(AI_DEBUG) ai_Debug("0e_m1_3_endround", "23", GetName(oCreature) + " ends combat round.");
|
||||
// Action modes get cleared prior to each OnCombatRoundEnd!
|
||||
// We do this to keep the action mode going.
|
||||
int nActionMode = GetLocalInt(oCreature, AI_CURRENT_ACTION_MODE);
|
||||
if(nActionMode > 0)
|
||||
{
|
||||
SetActionMode(oCreature, nActionMode, TRUE);
|
||||
// We don't want to use up all of the Dwarven Defenders uses!
|
||||
if(nActionMode == 12) IncrementRemainingFeatUses(oCreature, FEAT_DWARVEN_DEFENDER_DEFENSIVE_STANCE);
|
||||
}
|
||||
if (ai_GetIsBusy(oCreature) || ai_Disabled(oCreature)) return;
|
||||
if(Random(4) == 0) SpeakOneLinerConversation();
|
||||
if(ai_GetIsInCombat(oCreature)) ai_DoMonsterCombatRound(oCreature);
|
||||
ai_SpellConcentrationCheck(oCreature);
|
||||
if(ai_GetBehaviorState(NW_FLAG_BEHAVIOR_SPECIAL)) ai_DetermineSpecialBehavior(oCreature);
|
||||
if(GetSpawnInCondition(NW_FLAG_END_COMBAT_ROUND_EVENT))
|
||||
{
|
||||
SignalEvent(OBJECT_SELF, EventUserDefined(1003));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
1975
src/module/nss/0e_nui.nss
Normal file
1975
src/module/nss/0e_nui.nss
Normal file
File diff suppressed because it is too large
Load Diff
700
src/module/nss/0e_nui_dm.nss
Normal file
700
src/module/nss/0e_nui_dm.nss
Normal file
@@ -0,0 +1,700 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0e_nui_dm
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Menu event script
|
||||
sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set).
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_menus_dm"
|
||||
void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem);
|
||||
void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken);
|
||||
// Adds a spell to a json AI restricted spell list then returns jRules.
|
||||
// bRestrict = TRUE will add to the list FALSE will remove it from the list.
|
||||
json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE);
|
||||
// Adds a selected creature to the group.
|
||||
void ai_SelectToGroup(object oDM, string sElem);
|
||||
// Does a selected action for nGroup.
|
||||
void ai_DMSelectAction(object oDM, string sElem);
|
||||
// Changes if the group will run (nSpeed: 1) or walk (nSpeed: 0).
|
||||
void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed);
|
||||
void main()
|
||||
{
|
||||
object oDM = NuiGetEventPlayer();
|
||||
int nToken = NuiGetEventWindow();
|
||||
string sEvent = NuiGetEventType();
|
||||
string sElem = NuiGetEventElement();
|
||||
int nIndex = NuiGetEventArrayIndex();
|
||||
string sWndId = NuiGetWindowId(oDM, nToken);
|
||||
//if(AI_DEBUG) ai_Debug ("0e_nui", "58", "sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
|
||||
// " nToken: " + IntToString(nToken) + " oPC: " + GetName(oPC));
|
||||
//WriteTimestampedLogEntry("0e_nui, 58, sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
|
||||
// " nToken: " + IntToString(nToken) + " oDM: " + GetName(oDM));
|
||||
//**************************************************************************
|
||||
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
|
||||
// Watch to see if the window moves and save.
|
||||
if(sElem == "window_geometry" && sEvent == "watch")
|
||||
{
|
||||
if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return;
|
||||
SaveMenuToCampaignDb(oDM, nToken, sWndId);
|
||||
}
|
||||
//**************************************************************************
|
||||
// Widget events.
|
||||
if(sWndId == "dm" + AI_WIDGET_NUI)
|
||||
{
|
||||
//if(GetLocalInt(oDM, AI_NO_NUI_SAVE)) return;
|
||||
if(sEvent == "click")
|
||||
{
|
||||
if(sElem == "btn_open_main")
|
||||
{
|
||||
if(IsWindowClosed(oDM, "dm" + AI_COMMAND_NUI)) ai_CreateDMCommandNUI(oDM);
|
||||
IsWindowClosed(oDM, "dm" + AI_MAIN_NUI);
|
||||
}
|
||||
else if(sElem == "btn_camera") ai_SelectCameraView(oDM);
|
||||
else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM);
|
||||
else if(GetStringLeft(sElem, 13) == "btn_cmd_group")
|
||||
{
|
||||
ai_DMSelectAction(oDM, sElem);
|
||||
}
|
||||
else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oDM, sElem, TRUE);
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
|
||||
if(nMouseScroll == 1.0) // Scroll up
|
||||
{
|
||||
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1);
|
||||
}
|
||||
if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0);
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousedown")
|
||||
{
|
||||
int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn"));
|
||||
if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT)
|
||||
{
|
||||
if(sElem == "btn_open_main")
|
||||
{
|
||||
if(IsWindowClosed(oDM, "dm" + AI_MAIN_NUI)) ai_CreateDMOptionsNUI(oDM);
|
||||
}
|
||||
else if(GetStringLeft(sElem, 13) == "btn_cmd_group")
|
||||
{
|
||||
ai_SelectToGroup(oDM, sElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sWndId == "dm" + AI_COMMAND_NUI)
|
||||
{
|
||||
if(sEvent == "click")
|
||||
{
|
||||
if(sElem == "btn_widget_lock")
|
||||
{
|
||||
if(ai_GetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK))
|
||||
{
|
||||
ai_SendMessages(GetName(oDM) + " AI widget unlocked.", AI_COLOR_YELLOW, oDM);
|
||||
ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_SendMessages(GetName(oDM) + " AI widget locked.", AI_COLOR_YELLOW, oDM);
|
||||
ai_SetDMWidgetButton(oDM, BTN_DM_WIDGET_LOCK, TRUE);
|
||||
}
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
else if(sElem == "btn_main_menu")
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMOptionsNUI(oDM));
|
||||
}
|
||||
else if(sElem == "btn_camera") ai_SelectCameraView(oDM);
|
||||
else if(sElem == "btn_inventory") ai_SelectOpenInventory(oDM);
|
||||
else if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMSelectAction(oDM, sElem);
|
||||
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 1);
|
||||
}
|
||||
else if(sEvent == "watch")
|
||||
{
|
||||
if(sElem == "chbx_cmd_group1_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP1, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_group2_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP2, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_group3_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP3, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_group4_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP4, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_group5_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP5, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_group6_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_GROUP6, nToken, sElem);
|
||||
else if(sElem == "chbx_camera_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_CAMERA, nToken, sElem);
|
||||
else if(sElem == "chbx_inventory_check") ai_SetDMWidgetButtonToCheckbox(oDM, BTN_DM_CMD_INVENTORY, nToken, sElem);
|
||||
if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check")
|
||||
{
|
||||
int nIndex = StringToInt(GetSubString(sElem, 12, 1));
|
||||
json jPlugins = ai_GetCampaignDbJson("plugins", sName, AI_DM_TABLE);
|
||||
json jPlugin = JsonArrayGet(jPlugins, nIndex);
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
ai_SetCampaignDbJson("plugins", jPlugins, sName, AI_DM_TABLE);
|
||||
}
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
|
||||
if(nMouseScroll == 1.0) // Scroll up
|
||||
{
|
||||
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 1);
|
||||
}
|
||||
if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
if(GetStringLeft(sElem, 13) == "btn_cmd_group") ai_DMChangeMoveSpeed(oDM, sElem, 0);
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousedown")
|
||||
{
|
||||
int nMouseButton = JsonGetInt(JsonObjectGet(NuiGetEventPayload(), "mouse_btn"));
|
||||
if(nMouseButton == NUI_MOUSE_BUTTON_RIGHT)
|
||||
{
|
||||
if(GetStringLeft(sElem, 13) == "btn_cmd_group")
|
||||
{
|
||||
ai_SelectToGroup(oDM, sElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
|
||||
if(nMouseScroll == 1.0) // Scroll up
|
||||
{
|
||||
}
|
||||
else if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
//**************************************************************************
|
||||
// Main AI events.
|
||||
if(sWndId == "dm" + AI_MAIN_NUI)
|
||||
{
|
||||
if(sEvent == "click")
|
||||
{
|
||||
if(sElem == "btn_plugin_manager")
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
}
|
||||
if(sElem == "btn_widget_manager")
|
||||
{
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
|
||||
}
|
||||
}
|
||||
if(sEvent == "watch")
|
||||
{
|
||||
if(sElem == "txt_max_henchman")
|
||||
{
|
||||
int nMaxHenchmen = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
|
||||
if(nMaxHenchmen > 12)
|
||||
{
|
||||
nMaxHenchmen = 12;
|
||||
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oDM);
|
||||
}
|
||||
SetMaxHenchmen(nMaxHenchmen);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_MAX_HENCHMAN, JsonInt(nMaxHenchmen));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
ai_SendMessages("Maximum henchmen has been changed to " + IntToString(nMaxHenchmen), AI_COLOR_YELLOW, oDM);
|
||||
}
|
||||
else if(sElem == "txt_ai_difficulty")
|
||||
{
|
||||
int nChance = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(nChance < 0) nChance = 0;
|
||||
else if(nChance > 100) nChance = 100;
|
||||
SetLocalInt(GetModule(), AI_RULE_AI_DIFFICULTY, nChance);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_AI_DIFFICULTY, JsonInt(nChance));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
}
|
||||
else if(sElem == "txt_perception_distance")
|
||||
{
|
||||
float fDistance = StringToFloat(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(fDistance < 10.0) fDistance = 10.0;
|
||||
else if(fDistance > 60.0) fDistance = 60.0;
|
||||
SetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE, fDistance);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_PERCEPTION_DISTANCE, JsonFloat(fDistance));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
}
|
||||
else if(sElem == "txt_inc_hp")
|
||||
{
|
||||
int nNumber = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
|
||||
if(nNumber < 0) nNumber = 0;
|
||||
else if(nNumber > 100) nNumber = 100;
|
||||
SetLocalInt(GetModule(), AI_INCREASE_MONSTERS_HP, nNumber);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
}
|
||||
else if(GetStringLeft(sElem, 4) == "chbx")
|
||||
{
|
||||
object oModule = GetModule();
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
if(sElem == "chbx_moral_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_MORAL_CHECKS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_MORAL_CHECKS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_buff_monsters_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_buff_summons_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_PRESUMMON, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_PRESUMMON, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_ambush_monsters_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_AMBUSH, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_AMBUSH, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_companions_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_SUMMON_COMPANIONS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_SUMMON_COMPANIONS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_advanced_movement_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_ADVANCED_MOVEMENT, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_ADVANCED_MOVEMENT, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_ilr_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_ILR, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_ILR, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_umd_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_ALLOW_UMD, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_ALLOW_UMD, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_use_healingkits_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_HEALERSKITS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_HEALERSKITS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_perm_assoc_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_PERM_ASSOC, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_PERM_ASSOC, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_corpses_stay_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_CORPSES_STAY, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_wander_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_WANDER, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_CORPSES_STAY, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_open_doors_check")
|
||||
{
|
||||
SetLocalInt(oModule, AI_RULE_OPEN_DOORS, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_OPEN_DOORS, JsonInt(bCheck));
|
||||
}
|
||||
else if(sElem == "chbx_party_scale_check")
|
||||
{
|
||||
if(bCheck)
|
||||
{
|
||||
SetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP, GetModuleXPScale());
|
||||
ai_CheckXPPartyScale(oDM);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetModuleXPScale(GetLocalInt(oModule, AI_RULE_DEFAULT_XP_SCALE));
|
||||
}
|
||||
SetLocalInt(oModule, AI_RULE_PARTY_SCALE, bCheck);
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_PARTY_SCALE, JsonInt(bCheck));
|
||||
string sText = IntToString(GetLocalInt(oModule, AI_BASE_PARTY_SCALE_XP));
|
||||
NuiSetBind(oDM, nToken, "chbx_party_scale_tooltip", JsonString(" PEPS adjusts your XP based on party size from (" + sText + ")."));
|
||||
sText = IntToString(GetModuleXPScale());
|
||||
NuiSetBind(oDM, nToken, "txt_xp_scale", JsonString(sText));
|
||||
}
|
||||
else if(sElem == "chbx_darkness_check")
|
||||
{
|
||||
if(bCheck)
|
||||
{
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS);
|
||||
jRules = ai_AddRestrictedSpell(jRules, 159);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS);
|
||||
jRules = ai_AddRestrictedSpell(jRules, 688); // WildShape_Darkness
|
||||
}
|
||||
else
|
||||
{
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_DARKNESS, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, 159, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELLABILITY_AS_DARKNESS, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, 688, FALSE); // WildShape_Darkness
|
||||
}
|
||||
}
|
||||
else if(sElem == "chbx_dispels_check")
|
||||
{
|
||||
if(bCheck)
|
||||
{
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION);
|
||||
}
|
||||
else
|
||||
{
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_LESSER_DISPEL, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_DISPEL_MAGIC, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_GREATER_DISPELLING, FALSE);
|
||||
jRules = ai_AddRestrictedSpell(jRules, SPELL_MORDENKAINENS_DISJUNCTION, FALSE);
|
||||
}
|
||||
}
|
||||
else if(sElem == "chbx_timestop_check")
|
||||
{
|
||||
if(bCheck) jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP);
|
||||
else jRules = ai_AddRestrictedSpell(jRules, SPELL_TIME_STOP, FALSE);
|
||||
}
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
}
|
||||
}
|
||||
else if(sEvent == "mousescroll")
|
||||
{
|
||||
float nMouseScroll = JsonGetFloat(JsonObjectGet(JsonObjectGet(NuiGetEventPayload(), "mouse_scroll"), "y"));
|
||||
if(nMouseScroll == 1.0) // Scroll up
|
||||
{
|
||||
// Follow range is only changed on non-pc's
|
||||
if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), 1, nToken);
|
||||
}
|
||||
else if(nMouseScroll == -1.0) // Scroll down
|
||||
{
|
||||
// Follow range is only changed on non-pc's
|
||||
if(sElem == "lbl_perc_dist") ai_RulePercDistInc(oDM, GetModule(), -1, nToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
//**************************************************************************
|
||||
// Plugins events.
|
||||
if(sWndId == "dmai_plugin_nui")
|
||||
{
|
||||
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
|
||||
json jPlugins = ai_GetCampaignDbJson("plugins");
|
||||
if(sEvent == "click")
|
||||
{
|
||||
if(sElem == "btn_load_plugins")
|
||||
{
|
||||
string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin"));
|
||||
if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray();
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_buffing");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_forcerest");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_henchmen");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_crafting");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_mod_set");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_debug");
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, "pi_test");
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
if(sElem == "btn_check_plugins")
|
||||
{
|
||||
int nIndex;
|
||||
json jPlugin = JsonArrayGet(jPlugins, nIndex);
|
||||
while(JsonGetType(jPlugin) != JSON_TYPE_NULL)
|
||||
{
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(TRUE));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
jPlugin = JsonArrayGet(jPlugins, ++nIndex);
|
||||
}
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
if(sElem == "btn_clear_plugins")
|
||||
{
|
||||
int nIndex;
|
||||
json jPlugin = JsonArrayGet(jPlugins, nIndex);
|
||||
while(JsonGetType(jPlugin) != JSON_TYPE_NULL)
|
||||
{
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(FALSE));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
jPlugin = JsonArrayGet(jPlugins, ++nIndex);
|
||||
}
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
else if(sElem == "btn_add_plugin")
|
||||
{
|
||||
string sScript = JsonGetString(NuiGetBind (oDM, nToken, "txt_plugin"));
|
||||
if(JsonGetType(JsonArrayGet(jPlugins, 0)) == JSON_TYPE_NULL) jPlugins = JsonArray();
|
||||
jPlugins = ai_Plugin_Add(oDM, jPlugins, sScript);
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
}
|
||||
else if(GetStringLeft(sElem, 18) == "btn_remove_plugin_")
|
||||
{
|
||||
int nIndex = StringToInt(GetStringRight(sElem, 1));
|
||||
jPlugins = JsonArrayDel(jPlugins, nIndex);
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMPluginManagerNUI(oDM));
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oDM, sElem, 2);
|
||||
}
|
||||
else if(sEvent == "watch")
|
||||
{
|
||||
if(GetStringLeft(sElem, 12) == "chbx_plugin_" && GetStringRight(sElem, 6) == "_check")
|
||||
{
|
||||
int nIndex = StringToInt(GetSubString(sElem, 12, 1));
|
||||
json jPlugin = JsonArrayGet(jPlugins, nIndex);
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
|
||||
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
|
||||
ai_SetCampaignDbJson("plugins", jPlugins);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI)));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetNUI(oDM));
|
||||
}
|
||||
}
|
||||
}
|
||||
if(sWndId == "dm_widget_manager_nui")
|
||||
{
|
||||
//SendMessageToDM(oDM, "sEvent: " + sEvent + " sElem: " + sElem);
|
||||
if(sEvent == "click")
|
||||
{
|
||||
if(sElem == "btn_clear_buttons")
|
||||
{
|
||||
object oModule = GetModule();
|
||||
SetLocalInt(oModule, sDMWidgetAccessVarname, 0);
|
||||
SetLocalInt(oModule, sDMAIAccessVarname, 0);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(0));
|
||||
jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(0));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
|
||||
return;
|
||||
}
|
||||
else if(sElem == "btn_check_buttons")
|
||||
{
|
||||
object oModule = GetModule();
|
||||
SetLocalInt(oModule, sDMWidgetAccessVarname, 7340028);
|
||||
SetLocalInt(oModule, sDMAIAccessVarname, 203423743);
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, sDMWidgetAccessVarname, JsonInt(7340028));
|
||||
jRules = JsonObjectSet(jRules, sDMAIAccessVarname, JsonInt(203423743));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
DelayCommand(0.0, NuiDestroy(oDM, nToken));
|
||||
DelayCommand(0.1, ai_CreateDMWidgetManagerNUI(oDM));
|
||||
return;
|
||||
}
|
||||
SetLocalInt(oDM, "CHBX_SKIP", TRUE);
|
||||
DelayCommand(2.0, DeleteLocalInt(oDM, "CHBX_SKIP"));
|
||||
if(sElem == "btn_cmd_action") NuiSetBind(oDM, nToken, "chbx_cmd_action_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ACTION)));
|
||||
else if(sElem == "btn_cmd_guard") NuiSetBind(oDM, nToken, "chbx_cmd_guard_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GUARD)));
|
||||
else if(sElem == "btn_cmd_hold") NuiSetBind(oDM, nToken, "chbx_cmd_hold_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_HOLD)));
|
||||
else if(sElem == "btn_cmd_attack") NuiSetBind(oDM, nToken, "chbx_cmd_attack_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_ATTACK)));
|
||||
else if(sElem == "btn_cmd_follow") NuiSetBind(oDM, nToken, "chbx_cmd_follow_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FOLLOW)));
|
||||
else if(sElem == "btn_follow_target") NuiSetBind(oDM, nToken, "chbx_follow_target_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOLLOW_TARGET)));
|
||||
else if(sElem == "btn_cmd_search") NuiSetBind(oDM, nToken, "chbx_cmd_search_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SEARCH)));
|
||||
else if(sElem == "btn_cmd_stealth") NuiSetBind(oDM, nToken, "chbx_cmd_stealth_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_STEALTH)));
|
||||
else if(sElem == "btn_cmd_ai_script") NuiSetBind(oDM, nToken, "chbx_cmd_ai_script_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_AI_SCRIPT)));
|
||||
else if(sElem == "btn_cmd_place_trap") NuiSetBind(oDM, nToken, "chbx_cmd_place_trap_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_PLACE_TRAP)));
|
||||
else if(sElem == "btn_quick_widget") NuiSetBind(oDM, nToken, "chbx_quick_widget_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_SPELL_WIDGET)));
|
||||
else if(sElem == "btn_spell_memorize") NuiSetBind(oDM, nToken, "chbx_spell_memorize_check", JsonBool(!ai_GetDMWAccessButton(BTN_DM_CMD_MEMORIZE)));
|
||||
else if(sElem == "btn_buff_short") NuiSetBind(oDM, nToken, "chbx_buff_short_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_SHORT)));
|
||||
else if(sElem == "btn_buff_long") NuiSetBind(oDM, nToken, "chbx_buff_long_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_LONG)));
|
||||
else if(sElem == "btn_buff_all") NuiSetBind(oDM, nToken, "chbx_buff_all_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_ALL)));
|
||||
else if(sElem == "btn_buff_rest") NuiSetBind(oDM, nToken, "chbx_buff_rest_check", JsonBool(!ai_GetDMWAccessButton(BTN_BUFF_REST)));
|
||||
else if(sElem == "btn_jump_to") NuiSetBind(oDM, nToken, "chbx_jump_to_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_JUMP_TO)));
|
||||
else if(sElem == "btn_ghost_mode") NuiSetBind(oDM, nToken, "chbx_ghost_mode_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_GHOST_MODE)));
|
||||
else if(sElem == "btn_camera") NuiSetBind(oDM, nToken, "chbx_camera_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_CAMERA)));
|
||||
else if(sElem == "btn_inventory") NuiSetBind(oDM, nToken, "chbx_inventory_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_INVENTORY)));
|
||||
else if(sElem == "btn_familiar") NuiSetBind(oDM, nToken, "chbx_familiar_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_FAMILIAR)));
|
||||
else if(sElem == "btn_companion") NuiSetBind(oDM, nToken, "chbx_companion_check", JsonBool(!ai_GetDMWAccessButton(BTN_CMD_COMPANION)));
|
||||
else if(sElem == "btn_ai") NuiSetBind(oDM, nToken, "chbx_ai_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_FOR_PC)));
|
||||
else if(sElem == "btn_quiet") NuiSetBind(oDM, nToken, "chbx_quiet_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REDUCE_SPEECH)));
|
||||
else if(sElem == "btn_ranged") NuiSetBind(oDM, nToken, "chbx_ranged_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_RANGED)));
|
||||
else if(sElem == "btn_search") NuiSetBind(oDM, nToken, "chbx_search_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_SEARCH)));
|
||||
else if(sElem == "btn_stealth") NuiSetBind(oDM, nToken, "chbx_stealth_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_USE_STEALTH)));
|
||||
else if(sElem == "btn_open_door") NuiSetBind(oDM, nToken, "chbx_open_door_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OPEN_DOORS)));
|
||||
else if(sElem == "btn_traps") NuiSetBind(oDM, nToken, "chbx_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_REMOVE_TRAPS)));
|
||||
else if(sElem == "btn_pick_locks") NuiSetBind(oDM, nToken, "chbx_pick_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PICK_LOCKS)));
|
||||
else if(sElem == "btn_bash_locks") NuiSetBind(oDM, nToken, "chbx_bash_locks_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_BASH_LOCKS)));
|
||||
else if(sElem == "btn_magic_level") NuiSetBind(oDM, nToken, "chbx_magic_level_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_MAGIC_LEVEL)));
|
||||
else if(sElem == "btn_spontaneous") NuiSetBind(oDM, nToken, "chbx_spontaneous_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_SPONTANEOUS)));
|
||||
else if(sElem == "btn_magic") NuiSetBind(oDM, nToken, "chbx_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_USE)));
|
||||
else if(sElem == "btn_magic_items") NuiSetBind(oDM, nToken, "chbx_magic_items_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_NO_MAGIC_ITEM_USE)));
|
||||
else if(sElem == "btn_def_magic") NuiSetBind(oDM, nToken, "chbx_def_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_DEF_MAGIC_USE)));
|
||||
else if(sElem == "btn_off_magic") NuiSetBind(oDM, nToken, "chbx_off_magic_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_OFF_MAGIC_USE)));
|
||||
else if(sElem == "btn_heal_out") NuiSetBind(oDM, nToken, "chbx_heal_out_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_OUT)));
|
||||
else if(sElem == "btn_heal_in") NuiSetBind(oDM, nToken, "chbx_heal_in_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_HEAL_IN)));
|
||||
else if(sElem == "btn_heals_onoff") NuiSetBind(oDM, nToken, "chbx_heals_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_SELF_HEALING)));
|
||||
else if(sElem == "btn_healp_onoff") NuiSetBind(oDM, nToken, "chbx_healp_onoff_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_STOP_PARTY_HEALING)));
|
||||
else if(sElem == "btn_loot") NuiSetBind(oDM, nToken, "chbx_loot_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_LOOT)));
|
||||
else if(sElem == "btn_ignore_assoc") NuiSetBind(oDM, nToken, "chbx_ignore_assoc_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_ASSOCIATES)));
|
||||
else if(sElem == "btn_ignore_traps") NuiSetBind(oDM, nToken, "chbx_ignore_traps_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_IGNORE_TRAPS)));
|
||||
else if(sElem == "btn_perc_range") NuiSetBind(oDM, nToken, "chbx_perc_range_check", JsonBool(!ai_GetDMAIAccessButton(BTN_AI_PERC_RANGE)));
|
||||
}
|
||||
if(sEvent == "watch")
|
||||
{
|
||||
if(GetLocalInt(oDM, "CHBX_SKIP")) return;
|
||||
if(sElem == "chbx_cmd_action_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ACTION, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_guard_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GUARD, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_hold_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_HOLD, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_attack_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_ATTACK, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_follow_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FOLLOW, nToken, sElem);
|
||||
else if(sElem == "chbx_follow_target_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOLLOW_TARGET, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_search_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SEARCH, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_stealth_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_STEALTH, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_ai_script_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_AI_SCRIPT, nToken, sElem);
|
||||
else if(sElem == "chbx_cmd_place_trap_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_PLACE_TRAP, nToken, sElem);
|
||||
else if(sElem == "chbx_quick_widget_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_SPELL_WIDGET, nToken, sElem);
|
||||
else if(sElem == "chbx_spell_memorize_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_DM_CMD_MEMORIZE, nToken, sElem);
|
||||
else if(sElem == "chbx_buff_short_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_SHORT, nToken, sElem);
|
||||
else if(sElem == "chbx_buff_long_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_LONG, nToken, sElem);
|
||||
else if(sElem == "chbx_buff_all_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_ALL, nToken, sElem);
|
||||
else if(sElem == "chbx_buff_rest_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_BUFF_REST, nToken, sElem);
|
||||
else if(sElem == "chbx_jump_to_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_JUMP_TO, nToken, sElem);
|
||||
else if(sElem == "chbx_ghost_mode_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_GHOST_MODE, nToken, sElem);
|
||||
else if(sElem == "chbx_camera_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_CAMERA, nToken, sElem);
|
||||
else if(sElem == "chbx_inventory_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_INVENTORY, nToken, sElem);
|
||||
else if(sElem == "chbx_familiar_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_FAMILIAR, nToken, sElem);
|
||||
else if(sElem == "chbx_companion_check") ai_SetDMWAccessButtonToCheckbox(oDM, BTN_CMD_COMPANION, nToken, sElem);
|
||||
else if(sElem == "chbx_ai_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_FOR_PC, nToken, sElem);
|
||||
else if(sElem == "chbx_quiet_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REDUCE_SPEECH, nToken, sElem);
|
||||
else if(sElem == "chbx_ranged_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_RANGED, nToken, sElem);
|
||||
else if(sElem == "chbx_search_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_SEARCH, nToken, sElem);
|
||||
else if(sElem == "chbx_stealth_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_USE_STEALTH, nToken, sElem);
|
||||
else if(sElem == "chbx_open_door_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OPEN_DOORS, nToken, sElem);
|
||||
else if(sElem == "chbx_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_REMOVE_TRAPS, nToken, sElem);
|
||||
else if(sElem == "chbx_pick_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PICK_LOCKS, nToken, sElem);
|
||||
else if(sElem == "chbx_bash_locks_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_BASH_LOCKS, nToken, sElem);
|
||||
else if(sElem == "chbx_magic_level_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_MAGIC_LEVEL, nToken, sElem);
|
||||
else if(sElem == "chbx_spontaneous_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_SPONTANEOUS, nToken, sElem);
|
||||
else if(sElem == "chbx_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_USE, nToken, sElem);
|
||||
else if(sElem == "chbx_magic_items_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_NO_MAGIC_ITEM_USE, nToken, sElem);
|
||||
else if(sElem == "chbx_def_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_DEF_MAGIC_USE, nToken, sElem);
|
||||
else if(sElem == "chbx_off_magic_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_OFF_MAGIC_USE, nToken, sElem);
|
||||
else if(sElem == "chbx_heal_out_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_OUT, nToken, sElem);
|
||||
else if(sElem == "chbx_heal_in_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_HEAL_IN, nToken, sElem);
|
||||
else if(sElem == "chbx_heals_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_SELF_HEALING, nToken, sElem);
|
||||
else if(sElem == "chbx_healp_onoff_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_STOP_PARTY_HEALING, nToken, sElem);
|
||||
else if(sElem == "chbx_loot_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_LOOT, nToken, sElem);
|
||||
else if(sElem == "chbx_ignore_assoc_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_ASSOCIATES, nToken, sElem);
|
||||
else if(sElem == "chbx_ignore_traps_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_IGNORE_TRAPS, nToken, sElem);
|
||||
else if(sElem == "chbx_perc_range_check") ai_SetDMAIAccessButtonToCheckbox(oDM, BTN_AI_PERC_RANGE, nToken, sElem);
|
||||
}
|
||||
}
|
||||
}
|
||||
void ai_SetDMWidgetButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
|
||||
{
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
ai_SetDMWidgetButton(oDM, nButton, bCheck);
|
||||
}
|
||||
void ai_SetDMWAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
|
||||
{
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
ai_SetDMWAccessButton(nButton, bCheck);
|
||||
}
|
||||
void ai_SetDMAIAccessButtonToCheckbox(object oDM, int nButton, int nToken, string sElem)
|
||||
{
|
||||
int bCheck = JsonGetInt(NuiGetBind(oDM, nToken, sElem));
|
||||
ai_SetDMAIAccessButton(nButton, bCheck);
|
||||
}
|
||||
void ai_RulePercDistInc(object oDM, object oModule, int nIncrement, int nToken)
|
||||
{
|
||||
int nAdjustment = GetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE) + nIncrement;
|
||||
if(nAdjustment < 8 || nAdjustment > 11) return;
|
||||
SetLocalInt(oModule, AI_RULE_MON_PERC_DISTANCE, nAdjustment);
|
||||
string sText;
|
||||
if(nAdjustment == 8) sText = " Monster perception: Short [10 Sight / 10 Listen]";
|
||||
else if(nAdjustment == 9) sText = " Monster perception: Medium [20 Sight / 20 Listen]";
|
||||
else if(nAdjustment == 10) sText = " Monster perception: Long [35 Sight / 20 Listen]";
|
||||
else sText = " Monster perception: Default [Monster's default values]";
|
||||
NuiSetBind(oDM, nToken, "lbl_perc_dist_label", JsonString(sText));
|
||||
json jRules = ai_GetCampaignDbJson("rules");
|
||||
jRules = JsonObjectSet(jRules, AI_RULE_MON_PERC_DISTANCE, JsonInt(nAdjustment));
|
||||
ai_SetCampaignDbJson("rules", jRules);
|
||||
}
|
||||
json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE)
|
||||
{
|
||||
object oModule = GetModule();
|
||||
json jRSpells = GetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS);
|
||||
int nIndex, nMaxIndex = JsonGetLength(jRSpells);
|
||||
if(bRestrict)
|
||||
{
|
||||
while(nIndex < nMaxIndex)
|
||||
{
|
||||
if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell) return jRules;
|
||||
nIndex++;
|
||||
}
|
||||
jRSpells = JsonArrayInsert(jRSpells, JsonInt(nSpell));
|
||||
}
|
||||
else
|
||||
{
|
||||
while(nIndex < nMaxIndex)
|
||||
{
|
||||
if(JsonGetInt(JsonArrayGet(jRSpells, nIndex)) == nSpell)
|
||||
{
|
||||
jRSpells = JsonArrayDel(jRSpells, nIndex);
|
||||
break;
|
||||
}
|
||||
nIndex++;
|
||||
}
|
||||
}
|
||||
SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells);
|
||||
return JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells);
|
||||
}
|
||||
void ai_SelectToGroup(object oDM, string sElem)
|
||||
{
|
||||
string sGroup = GetStringRight(sElem, 1);
|
||||
SetLocalString(oDM, AI_TARGET_MODE, "DM_SELECT_GROUP" + sGroup);
|
||||
ai_SendMessages("Select a creature to add to group " + sGroup + ". Selecting yourself will clear group1.", AI_COLOR_YELLOW, oDM);
|
||||
EnterTargetingMode(oDM, OBJECT_TYPE_CREATURE, MOUSECURSOR_PICKUP, MOUSECURSOR_PICKUP_DOWN);
|
||||
}
|
||||
void ai_DMSelectAction(object oDM, string sElem)
|
||||
{
|
||||
string sGroup = GetStringRight(sElem, 1);
|
||||
SetLocalString(oDM, AI_TARGET_MODE, "DM_ACTION_GROUP" + sGroup);
|
||||
ai_SendMessages(GetName(oDM) + " select an action for group" + sGroup + ".", AI_COLOR_YELLOW, oDM);
|
||||
EnterTargetingMode(oDM, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
|
||||
}
|
||||
void ai_DMChangeMoveSpeed(object oDM, string sElem, int nSpeed)
|
||||
{
|
||||
string sGroup = GetStringRight(sElem, 1);
|
||||
json jGroup = GetLocalJson(oDM, "DM_GROUP" + sGroup);
|
||||
if(JsonGetType(jGroup) == JSON_TYPE_NULL)
|
||||
{
|
||||
ai_SendMessages("This group does not contain any creatures!", AI_COLOR_RED, oDM);
|
||||
return;
|
||||
}
|
||||
jGroup = JsonArraySet(jGroup, 0, JsonInt(nSpeed));
|
||||
SetLocalJson(oDM, "DM_GROUP" + sGroup, jGroup);
|
||||
object oLeader = GetObjectByUUID(JsonGetString(JsonArrayGet(jGroup, 1)));
|
||||
string sName = GetName(oLeader);
|
||||
string sText = " " + sName + "'s group";
|
||||
if(nSpeed == 0) sText += " [Walk]";
|
||||
else sText += " [Run]";
|
||||
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_WIDGET_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText));
|
||||
NuiSetBind(oDM, NuiFindWindow(oDM, "dm" + AI_COMMAND_NUI), "btn_cmd_group" + sGroup + "_tooltip", JsonString(sText));
|
||||
}
|
||||
23
src/module/nss/0e_onclientload.nss
Normal file
23
src/module/nss/0e_onclientload.nss
Normal file
@@ -0,0 +1,23 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script: 0e_onclientload
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Monster OnClientLoad script;
|
||||
This will fire when the client is loading.
|
||||
|
||||
If you have your own OnClientLoad event script just take the below
|
||||
script lines and add them into your OnClientLoad script.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_menus_dm"
|
||||
#include "0i_module"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
// This can be moved to the OnClientLoad script event of your module.
|
||||
if(ai_GetIsCharacter(oCreature)) ai_CheckPCStart(oCreature);
|
||||
// If this is a server you can add this as well.
|
||||
else if(AI_SERVER && (GetIsDM(oCreature) || GetIsPlayerDM(oCreature)))
|
||||
{
|
||||
ai_CheckPCStart(oCreature);
|
||||
}
|
||||
}
|
||||
154
src/module/nss/0e_player_target.nss
Normal file
154
src/module/nss/0e_player_target.nss
Normal file
@@ -0,0 +1,154 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
Script Name: 0e_player_target
|
||||
Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
OnPlayerTarget event script
|
||||
Used to allow player targeting while passing any module player targeting
|
||||
script through to work as intended.
|
||||
|
||||
We Use a string variable upon the player using the targeting mode to define the
|
||||
action of the target.
|
||||
AI_TARGET_MODE is the constant used.
|
||||
AI_TARGET_ASSOCIATE is the associate that triggered the target mode.
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_player_target"
|
||||
void main()
|
||||
{
|
||||
object oPC = GetLastPlayerToSelectTarget();
|
||||
// Get any plugin target scripts and run it instead of this one.
|
||||
string sPluginTargetScript = GetLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT);
|
||||
if(sPluginTargetScript != "")
|
||||
{
|
||||
DeleteLocalString(oPC, AI_PLUGIN_TARGET_SCRIPT);
|
||||
ExecuteScript(sPluginTargetScript, oPC);
|
||||
// Remove the plugin script as it must be set each time the plugin uses the target event.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the targeting mode data
|
||||
object oTarget = GetTargetingModeSelectedObject();
|
||||
vector vTarget = GetTargetingModeSelectedPosition();
|
||||
location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC));
|
||||
object oAssociate = GetLocalObject(oPC, AI_TARGET_ASSOCIATE);
|
||||
string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE);
|
||||
// ********************* Exiting Target Actions ************************
|
||||
// If the user manually exited targeting mode without selecting a target, return
|
||||
if(!GetIsObjectValid(oTarget) && vTarget == Vector())
|
||||
{
|
||||
if(sTargetMode == "ASSOCIATE_ACTION_ALL")
|
||||
{
|
||||
ai_SendMessages("You have exited selecting an action for the party.", AI_COLOR_YELLOW, oPC);
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
{
|
||||
if(GetLocalInt(oPC, sGhostModeVarname)) ai_OriginalRemoveAllActionMode(oPC);
|
||||
}
|
||||
else ai_RemoveAllActionMode(oPC);
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_ACTION")
|
||||
{
|
||||
ai_SendMessages("You have exited selecting an action for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
{
|
||||
if(GetLocalInt(oPC, sGhostModeVarname))
|
||||
{
|
||||
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
|
||||
DeleteLocalInt(oAssociate, sGhostModeVarname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ai_SetAIMode(oAssociate, AI_MODE_COMMANDED, FALSE);
|
||||
if(ai_GetAIMode(oPC, AI_MODE_ACTION_GHOST) && !ai_GetAIMode(oPC, AI_MODE_GHOST) &&
|
||||
GetLocalInt(oAssociate, sGhostModeVarname))
|
||||
{
|
||||
|
||||
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
|
||||
DeleteLocalInt(oAssociate, sGhostModeVarname);
|
||||
}
|
||||
ExecuteScript("nw_ch_ac1", oAssociate);
|
||||
}
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
|
||||
{
|
||||
ai_SendMessages(GetName(oAssociate) + " has exited selecing a trap!", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
|
||||
{
|
||||
ai_SendMessages(GetName(oAssociate) + " has exited placing the trap!", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(sTargetMode == "DM_SELECT_CAMERA_VIEW")
|
||||
{
|
||||
AttachCamera(oPC, oPC);
|
||||
ai_SendMessages(GetName(oPC) + " has defaulted camera view back to the player!", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// ************************* Targeted Actions **************************
|
||||
else
|
||||
{
|
||||
// This action makes an associates move to vTarget.
|
||||
if(sTargetMode == "ASSOCIATE_ACTION_ALL")
|
||||
{
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
{
|
||||
ai_OriginalActionAllAssociates(oPC, oTarget, lLocation);
|
||||
}
|
||||
else ai_ActionAllAssociates(oPC, oTarget, lLocation);
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_ACTION")
|
||||
{
|
||||
if(ResManGetAliasFor("ai_a_default", RESTYPE_NCS) == "")
|
||||
{
|
||||
AssignCommand(oAssociate, ai_OriginalActionAssociate(oPC, oTarget, lLocation));
|
||||
}
|
||||
else AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_FOLLOW_TARGET") ai_SelectFollowTarget(oPC, oAssociate, oTarget);
|
||||
else if(sTargetMode == "ASSOCIATE_GET_TRAP") ai_SelectTrap(oPC, oAssociate, oTarget);
|
||||
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP") AssignCommand(oAssociate, ai_PlaceTrap(oPC, lLocation));
|
||||
else if(sTargetMode == "ASSOCIATE_USE_ITEM")
|
||||
{
|
||||
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
|
||||
ai_UseWidgetItem(oPC, oAssociate, oTarget, lLocation);
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_USE_FEAT")
|
||||
{
|
||||
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
|
||||
ai_UseWidgetFeat(oPC, oAssociate, oTarget, lLocation);
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
}
|
||||
else if(sTargetMode == "ASSOCIATE_CAST_SPELL")
|
||||
{
|
||||
if(oTarget == GetArea(oPC)) oTarget = OBJECT_INVALID;
|
||||
ai_CastWidgetSpell(oPC, oAssociate, oTarget, lLocation);
|
||||
DelayCommand(6.0, ai_UpdateAssociateWidget(oPC, oAssociate));
|
||||
}
|
||||
else if(sTargetMode == "DM_SELECT_CAMERA_VIEW")
|
||||
{
|
||||
AttachCamera(oPC, oTarget);
|
||||
ai_SendMessages(GetName(oPC) + " has changed the camera view to " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(sTargetMode == "DM_SELECT_OPEN_INVENTORY")
|
||||
{
|
||||
if(LineOfSightObject(oPC, oTarget))
|
||||
{
|
||||
OpenInventory(oTarget, oPC);
|
||||
ai_SendMessages("You have opened the inventory of "+ GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else ai_SendMessages(GetName(oTarget) + " is not in your line of sight!", AI_COLOR_YELLOW, oPC);
|
||||
}
|
||||
else if(GetStringLeft(sTargetMode, 15) == "DM_SELECT_GROUP")
|
||||
{
|
||||
ai_AddToGroup(oPC, oTarget, sTargetMode);
|
||||
}
|
||||
else if(GetStringLeft(sTargetMode, 15) == "DM_ACTION_GROUP")
|
||||
{
|
||||
ai_DMAction(oPC, oTarget, lLocation, sTargetMode);
|
||||
}
|
||||
// Get saved module player target script and execute it for pass through compatibility.
|
||||
string sModuleTargetScript = GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT);
|
||||
ExecuteScript(sModuleTargetScript);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
src/module/nss/0e_prc_ch_events.nss
Normal file
78
src/module/nss/0e_prc_ch_events.nss
Normal file
@@ -0,0 +1,78 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: 0e_prc_ch_events
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
associate event handler while using the PRC.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
#include "0i_actions"
|
||||
#include "x0_i0_assoc"
|
||||
void main()
|
||||
{
|
||||
object oCreature = OBJECT_SELF;
|
||||
int nEvent = GetCurrentlyRunningEvent();
|
||||
//WriteTimestampedLogEntry("0e_prc_ch_events [13] " + GetName(oCreature) + " nEvent: " + IntToString(nEvent));
|
||||
switch (nEvent)
|
||||
{
|
||||
case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT:
|
||||
{
|
||||
if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_hb");
|
||||
ExecuteScript("nw_ch_ac1", oCreature);
|
||||
ExecuteScript("prc_npc_hb", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_NOTICE:
|
||||
{
|
||||
ExecuteScript("nw_ch_ac2", oCreature);
|
||||
ExecuteScript("prc_npc_percep", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DIALOGUE:
|
||||
{
|
||||
//if(GetLocalInt(oCreature, "CohortID")) ExecuteScript("prc_ai_coh_conv");
|
||||
ExecuteScript("nw_ch_ac4", oCreature);
|
||||
//ExecuteScript("prc_npc_conv", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED:
|
||||
{
|
||||
ExecuteScript("nw_ch_ac5", oCreature);
|
||||
ExecuteScript("prc_npc_physatt", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DAMAGED:
|
||||
{
|
||||
ExecuteScript("nw_ch_ac6", oCreature);
|
||||
ExecuteScript("prc_npc_damaged", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT:
|
||||
{
|
||||
ExecuteScript("nw_ch_acb", oCreature);
|
||||
ExecuteScript("prc_npc_spellat", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND:
|
||||
{
|
||||
ExecuteScript("nw_ch_ac3", oCreature);
|
||||
ExecuteScript("prc_npc_combat", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR:
|
||||
{
|
||||
ExecuteScript("nw_ch_ace", oCreature);
|
||||
ExecuteScript("prc_npc_blocked", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_RESTED:
|
||||
{
|
||||
ExecuteScript("nw_ch_aca", oCreature);
|
||||
//ExecuteScript("prc_npc_rested", oCreature);
|
||||
break;
|
||||
}
|
||||
case EVENT_SCRIPT_CREATURE_ON_DISTURBED:
|
||||
{
|
||||
ExecuteScript("nw_ch_ac8", oCreature);
|
||||
ExecuteScript("prc_npc_disturb", oCreature);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
2325
src/module/nss/0i_actions.nss
Normal file
2325
src/module/nss/0i_actions.nss
Normal file
File diff suppressed because it is too large
Load Diff
2192
src/module/nss/0i_associates.nss
Normal file
2192
src/module/nss/0i_associates.nss
Normal file
File diff suppressed because it is too large
Load Diff
70
src/module/nss/0i_color.nss
Normal file
70
src/module/nss/0i_color.nss
Normal file
@@ -0,0 +1,70 @@
|
||||
/*////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Script Name: 0i_color
|
||||
// Programmer: Philos
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Include scripts that are used to change the color of names and text.
|
||||
*/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Basic color codes. Message Notes
|
||||
const string AI_COLOR_BLACK = "000"; // <c > <c\x20\x20\x20> Nothing.
|
||||
const string AI_COLOR_WHITE = "999"; // <c<><63><EFBFBD>> <c\xFF\xFF\xFF> _Debug messages.
|
||||
const string AI_COLOR_GRAY = "666"; // <c<><63><EFBFBD>> <c\xAA\xAA\xAA> Server messages
|
||||
const string AI_COLOR_YELLOW = "990"; // <c<><63> > <c\xFF\xFF\x20> Generic messages to players.
|
||||
const string AI_COLOR_DARK_YELLOW = "660"; // <c <20>> <c\xAA\xAA\x20>
|
||||
const string AI_COLOR_RED = "900"; // <c<> > <c\xFF\x20\x20> Negative message to players.
|
||||
const string AI_COLOR_DARK_RED = "600"; // <c <20>> <c\xAA\x20\x20>
|
||||
const string AI_COLOR_GREEN = "080"; // <c <20> > <c\x20\xFF\x20> Positive message to players.
|
||||
const string AI_COLOR_DARK_GREEN = "060"; // <c <20> > <c\x20\xAA\x20>
|
||||
const string AI_COLOR_BLUE = "009"; // <c <20>> <c\x20\x20\xFF>
|
||||
const string AI_COLOR_DARK_BLUE = "006"; // <c <20>> <c\x20\x20\xAA> In game descriptive text.
|
||||
const string AI_COLOR_CYAN = "099"; // <c <20><>> <c\x20\xFF\xFF>
|
||||
const string AI_COLOR_DARK_CYAN = "066"; // <c <20><>> <c\x20\xAA\xAA>
|
||||
const string AI_COLOR_MAGENTA = "909"; // <c<> <20>> <c\xFF\x20\xFF>
|
||||
const string AI_COLOR_DARK_MAGENTA = "606";// <c<> <20>> <c\xAA\x20\xAA>
|
||||
const string AI_COLOR_LIGHT_MAGENTA = "868"; // <<3C>c<EFBFBD>> <c\xAA\xE2\xAA> Combat text: Enemy name color.
|
||||
const string AI_COLOR_ORANGE = "950"; // <c<><63> > <c\xFF\x8E\x20>
|
||||
const string AI_COLOR_DARK_ORANGE = "940"; // <c<>q > <c\xFF\x71\x20> Combat text: base text color.
|
||||
const string AI_COLOR_GOLD = "860"; // <c<><63> > <c\xE2\xAA\x20>
|
||||
// Strips the color codes from sText
|
||||
string ai_StripColorCodes(string sText);
|
||||
// This function will make sString be the specified color
|
||||
// as specified in sRGB. RGB is the Red, Green, and Blue
|
||||
// Each color can have a value from 0 to 9.
|
||||
// 1 - 0(20)[ ] 142 - 5(8E)[?]
|
||||
// 32 - 1(20)[ ] 170 - 6(AA)[<5B>]
|
||||
// 57 - 2(39)[9] 198 - 7(C6)[<5B>]
|
||||
// 85 - 3(55)[U] 226 - 8(E2)[<5B>]
|
||||
// 113 - 4(71)[q] 255 - 9(FE)[<5B>]
|
||||
string ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE);
|
||||
|
||||
string ai_StripColorCodes(string sText)
|
||||
{
|
||||
string sColorCode, sChar;
|
||||
int nStringLength = GetStringLength(sText);
|
||||
int i = FindSubString(sText, "<c", 0);
|
||||
while(i != -1)
|
||||
{
|
||||
sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 6));
|
||||
nStringLength = GetStringLength(sText);
|
||||
i = FindSubString(sText, "<c", i);
|
||||
}
|
||||
i = FindSubString(sText, "</", 0);
|
||||
while(i != -1)
|
||||
{
|
||||
sText = GetStringLeft(sText, i) + GetStringRight(sText, nStringLength -(i + 4));
|
||||
nStringLength = GetStringLength(sText);
|
||||
i = FindSubString(sText, "</", i);
|
||||
}
|
||||
return sText;
|
||||
}
|
||||
string ai_AddColorToText(string sText, string sRGB = AI_COLOR_WHITE)
|
||||
{
|
||||
// Old info The magic characters(padded -- the last three characters are the same).
|
||||
string sColorCodes = "\x20\x20\x39\x55\x71\x8E\xAA\xC6\xE2\xFF";
|
||||
if(FindSubString(sText, "<c", 0) != -1) sText = ai_StripColorCodes(sText);
|
||||
return "<c" + // Begin the color token.
|
||||
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 0, 1)), 1) + // red
|
||||
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 1, 1)), 1) + // green
|
||||
GetSubString(sColorCodes, StringToInt(GetSubString(sRGB, 2, 1)), 1) + // blue
|
||||
">" + // End the color token
|
||||
sText + "</c>";
|
||||
}
|
||||
3498
src/module/nss/0i_combat.nss
Normal file
3498
src/module/nss/0i_combat.nss
Normal file
File diff suppressed because it is too large
Load Diff
667
src/module/nss/0i_constants.nss
Normal file
667
src/module/nss/0i_constants.nss
Normal file
@@ -0,0 +1,667 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// Name: 0i_constants
|
||||
// Programmer: Philos
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
Include script for handling all constants for the ai.
|
||||
These constants are static and can only be changed in the toolset.
|
||||
Changes to any constants will not take effect until the scripts are recompiled.
|
||||
*///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const string PHILOS_VERSION = "Philos' Enhancing Player System (PEPS) version:07.12.25";
|
||||
// The following constants are designed to be changed to allow the AI to work
|
||||
// differently based on what a developer wants.
|
||||
// If you change these constants make sure the database has been removed
|
||||
// so the ai_SetAIRules() will rewrite the new server rule values.
|
||||
// File Name: peps_database.sqlite3
|
||||
//********************************** SERVER ***********************************
|
||||
// Turn On/Off Debug. You can only use the debug with the pi_debug/pe_debug scripts.
|
||||
// This will only work if you are using the PEPS menu system.
|
||||
const int AI_DEBUG = FALSE;
|
||||
// Defines if we are compiling for single player or a server. Always on for servers!
|
||||
const int AI_SERVER = FALSE;
|
||||
// The number of classes allowed for a creature to take in the server/module.
|
||||
const int AI_MAX_CLASSES_PER_CHARACTER = 8;
|
||||
// Taunts cool down time before the AI attemps another Taunt.
|
||||
const int AI_TAUNT_COOLDOWN = 3;
|
||||
// Animal Empathy cool down time before the AI attemps another check.
|
||||
const int AI_EMPATHY_COOLDOWN = 3;
|
||||
// Arcane Spell failure% or less than, for a caster to still try to cast a spell.
|
||||
const int AI_ASF_WILL_USE = 15;
|
||||
// Monsters chance to heal while in combat per round.
|
||||
const int AI_MONSTER_HEAL_IN_COMBAT_CHANCE = 70;
|
||||
// Monsters chance to heal when out of combat per heart beat.
|
||||
const int AI_MONSTER_HEAL_OUT_COMBAT_CHANCE = 70;
|
||||
// Allows Henchman to have a widget if using the henchman AI.
|
||||
const int AI_HENCHMAN_WIDGET = TRUE;
|
||||
// Change the Custom token number if it conflicts with your server.
|
||||
const int AI_BASE_CUSTOM_TOKEN = 1000;
|
||||
// Delay between creatures casting Buff spells. Must be minimum of 0.1 seconds.
|
||||
const float AI_HENCHMAN_BUFF_DELAY = 0.2;
|
||||
|
||||
//******************* These can be changed within the game *******************
|
||||
// Moral checks on or off. If wounded they will make Will saves, if they fail the flee.
|
||||
const int AI_MORAL_CHECKS = FALSE;
|
||||
// Allows monsters to prebuff before combat starts.
|
||||
const int AI_PREBUFF = TRUE;
|
||||
// Allows monsters cast summons spells when prebuffing.
|
||||
const int AI_PRESUMMONS = TRUE;
|
||||
// Allows monsters to use tactical AI scripts such as ambush, flanker, ranged.
|
||||
const int AI_TACTICAL = TRUE;
|
||||
// Enemies may summon familiars and Animal companions and will be randomized.
|
||||
const int AI_SUMMON_COMPANIONS = FALSE;
|
||||
// Allow the AI to move during combat base on the situation and action taking.
|
||||
const int AI_ADVANCED_MOVEMENT = TRUE;
|
||||
// Follow Item Level Restrictions for AI.
|
||||
const int AI_ITEM_LEVEL_RESTRICTIONS = FALSE;
|
||||
// Allow the AI to use Use Magic Device.
|
||||
const int AI_USE_MAGIC_DEVICE = TRUE;
|
||||
// Allow the AI to use healing kits.
|
||||
const int AI_HEALING_KITS = TRUE;
|
||||
// Associates are permanent and don't get removed when the master dies.
|
||||
const int AI_COMPANIONS_PERMANENT = FALSE;
|
||||
// Monster AI's chance (0 to 100) to attack the weakest target instead of the nearest.
|
||||
// The higher the number the harder the encounter with monsters!
|
||||
const int AI_TARGET_WEAKEST = 0;
|
||||
// Variable that can change the distance creatures will come and attack after
|
||||
// hearing a shout from an ally that sees or hears an enemy.
|
||||
// Or when searching for an invisible, heard enemy.
|
||||
// 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge.
|
||||
const float AI_SEARCH_DISTANCE = 30.0;
|
||||
// Enemy corpses remain on the floor instead of dissappearing.
|
||||
const int AI_CORPSE_REMAIN = FALSE;
|
||||
// Monsters will wander around when not in combat.
|
||||
const int AI_WANDER = FALSE;
|
||||
// Variable distance monsters can wander away from their spawn point.
|
||||
const float AI_WANDER_DISTANCE = 0.0;
|
||||
// Variable that allows monsters to open doors when wandering around out of combat.
|
||||
const int AI_OPEN_DOORS = FALSE;
|
||||
// Monster's actual perception distance.
|
||||
// 8 Short(10 sight/listen) 9 Medium(20 sight/listen) 10 Long(35 sight/20 listen)
|
||||
// 11 Default(Based on appearance.2da Most creatures use 9, bosses use 10).
|
||||
const int AI_MONSTER_PERCEPTION = 11;
|
||||
// Should the AI auto adjust the XP scale to remove party size penalty?
|
||||
const int AI_PARTY_SCALE = FALSE;
|
||||
|
||||
//**************************** DM Based Constants ****************************
|
||||
// The constant the server wants set to allow players to use specific widgets buttons.
|
||||
// 0 Allows all buttons. See ASSOCIATE_WIDGET_BUTTONS below for values needed to be
|
||||
// added to block those buttons.
|
||||
// Example: BTN_CMD_GHOST_MODE = 0x00000800; To remove you would put 2048 below.
|
||||
// Since Hex 800 is Decimal 2048.
|
||||
const int AI_DM_WIDGET_ACCESS_BUTTONS = 0;
|
||||
// The constant the server wants set to allow players to use specific AI buttons.
|
||||
// 0 Allows all buttons. See ASSOCIATE_AI_BUTTONS below for values needed to be
|
||||
// added to block those buttons.
|
||||
// Example: BTN_AI_MAGIC_LEVEL = 0x00000040; To remove you would put 64 below.
|
||||
// Since Hex 40 is Decimal 64. Adding BTN_AI_LOOT = 0x00001000; to that would be
|
||||
// 64 + 4096 = 4160 to Block Magic Level and Auto Looting.
|
||||
const int AI_DM_AI_ACCESS_BUTTONS = 0;
|
||||
//************************** CONVERSATION CONSTANTS **************************
|
||||
// Player's can tell their associates to ignore enemy associates.
|
||||
const int AI_IGNORE_ASSOCIATES_ON = TRUE;
|
||||
// Associates with a Taunt skill higher than their level can be told to taunt.
|
||||
const int AI_TAUNTING_ON = TRUE;
|
||||
// Associates that cast spells can be told to use counterspell.
|
||||
const int AI_COUNTERSPELLING_ON = TRUE;
|
||||
// Associates with lore skill higher than the master can identify items.
|
||||
const int AI_IDENTIFY_ON = TRUE;
|
||||
// Associates can be called upon to scout ahead for monsters.
|
||||
const int AI_SCOUT_AHEAD_ON = TRUE;
|
||||
// A player can open a henchmen's inventory.
|
||||
const int AI_OPEN_INVENTORY = TRUE;
|
||||
// Allows players to have associates pickup loot.
|
||||
const int AI_PICKUP_LOOT = TRUE;
|
||||
// Allows players to remove a henchman.
|
||||
const int AI_REMOVE_HENCHMAN_ON = FALSE;
|
||||
//***************************** Health Constants *****************************
|
||||
// % of health for when a creature is considered wounded.
|
||||
const int AI_HEALTH_WOUNDED = 50;
|
||||
// % of health when creature is considered badly wounded.
|
||||
const int AI_HEALTH_BLOODY = 25;
|
||||
//***************************** MORAL CONSTANTS ******************************
|
||||
// Moral checks are only made once a creature is below AI_HEALTH_WOUNDED.
|
||||
// The moral DC is AI_MORAL_DC - the number of Allies. Default: 5
|
||||
const int AI_WOUNDED_MORAL_DC = 5;
|
||||
// Once a creature goes below AI_HEALTHY_BLOODY then it uses this moral DC. Default: 15
|
||||
const int AI_BLOODY_MORAL_DC = 15;
|
||||
//******************************* WINDOW CONSTANTS *****************************
|
||||
const string AI_MAIN_NUI = "ai_main_nui";
|
||||
const string AI_COMMAND_NUI = "_command_nui";
|
||||
const string AI_NUI = "_ai_nui";
|
||||
const string AI_WIDGET_NUI = "_widget_nui";
|
||||
const string AI_LOOTFILTER_NUI = "_lootfilter_nui";
|
||||
const string AI_COPY_NUI = "_copy_nui";
|
||||
const string AI_PLUGIN_NUI = "ai_plugin_nui";
|
||||
const string AI_QUICK_WIDGET_NUI = "_quick_widget_nui";
|
||||
const string AI_SPELL_MEMORIZE_NUI = "_spell_memorize_nui";
|
||||
const string AI_SPELL_KNOWN_NUI = "_spell_known_nui";
|
||||
const string AI_SPELL_DESCRIPTION_NUI = "ai_spell_desc_nui";
|
||||
const string AI_EFFECT_ICON_NUI = "ai_effect_icon_nui";
|
||||
//******************************* CORE CONSTANTS *******************************
|
||||
// The following constants are core constants and changing any of these without
|
||||
// understanding the whole system could cause unforseen results.
|
||||
// CHANGE AT YOUR OWN RISK.
|
||||
// Variable used to asave a monster object for changing.
|
||||
const string AI_MONSTER_OBJECT = "AI_MONSTER_OBJECT";
|
||||
// Variable used to save a monsters json for changing.
|
||||
const string AI_MONSTER_JSON = "AI_MONSTER_JSON";
|
||||
// Variable used to let PEPS know that a monster plugin changed the monster.
|
||||
const string AI_MONSTER_CHANGED = "AI_MONSTER_CHANGED";
|
||||
// Variable used to save an associates class list to change known list json.
|
||||
const string AI_CLASS_LIST_JSON = "AI_CLASS_LIST_JSON";
|
||||
// Startup variable to tell plugins that we have started.
|
||||
const string AI_STARTING_UP = "AI_STARTING_UP";
|
||||
// Add plugin variable to tell plugins that we are adding them to PEPS.
|
||||
const string AI_ADD_PLUGIN = "AI_ADD_PLUGIN";
|
||||
// Startup variable to tell plugins what json array to add their plugin to.
|
||||
const string AI_JSON_PLUGINS = "AI_JSON_PLUGINS";
|
||||
// Plugin variable to have plugins return if they setup the plugin in the json for PEPS.
|
||||
const string AI_PLUGIN_SET = "AI_PLUGIN_SET";
|
||||
// Monster modification variable to let PEPS know what mods are available.
|
||||
const string AI_MONSTER_MOD_JSON = "AI_MONSTER_MOD_JSON";
|
||||
// The maximum number of henchman the code works with.
|
||||
const int AI_MAX_HENCHMAN = 12;
|
||||
// Delay between Henchman casting Healing spells. Must be minimum of 0.5 seconds.
|
||||
const float AI_HENCHMAN_HEALING_DELAY = 6.0;
|
||||
// A variable that can be set on creatures to stop mobile animations.
|
||||
const string AI_NO_ANIMATION = "AI_NO_ANIMATION";
|
||||
// How many seconds in a combat round.
|
||||
const int AI_COMBAT_ROUND_IN_SECONDS = 6;
|
||||
// Used for actions that take x seconds but don't have an action constant.
|
||||
const string AI_COMBAT_WAIT_IN_SECONDS = "AI_COMBAT_WAIT_IN_SECONDS";
|
||||
// Constants used to define the difficulty of the battle for associates.
|
||||
// 20+ : Impossible - Cannot win.
|
||||
// 17 to 19 : Overpowering - Use all of our powers.
|
||||
// 15 to 16 : Very Difficult - Use all of our power (Highest level spells).
|
||||
// 11 to 14 : Challenging - Use most of our power (Higher level powers).
|
||||
// 8 to 10 : Moderate - Use half of our power (Mid level powers and less).
|
||||
// 5 to 7 : Easy - Use our weaker powers (Lowest level powers).
|
||||
// 2 to 4 : Effortless - Don't waste spells and powers on this.
|
||||
// 1 or less: Pointless - We probably should ignore these dangers.
|
||||
const int AI_COMBAT_IMPOSSIBLE = 21;
|
||||
const int AI_COMBAT_OVERPOWERING = 17;
|
||||
const int AI_COMBAT_VERY_DIFFICULT = 15;
|
||||
const int AI_COMBAT_CHALLENGING = 11;
|
||||
const int AI_COMBAT_MODERATE = 10;
|
||||
const int AI_COMBAT_EASY = 7;
|
||||
const int AI_COMBAT_EFFORTLESS = 4;
|
||||
// Variables used to keep track of enemies in combat.
|
||||
const string AI_ENEMY = "AI_ENEMY"; // The enemy objects.
|
||||
const string AI_ENEMY_DISABLED = "AI_ENEMY_DISABLED"; // Int if they are disabled.
|
||||
const string AI_ENEMY_PERCEIVED = "AI_ENEMY_PERCEIVED"; // TRUE if we have seen or heard them, FALSE if not.
|
||||
const string AI_ENEMY_RANGE = "AI_ENEMY_RANGE"; // The range from OBJECT_SELF.
|
||||
const string AI_ENEMY_COMBAT = "AI_ENEMY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2
|
||||
const string AI_ENEMY_MELEE = "AI_ENEMY_MELEE"; // Enemies within 5 meters - Allies within 5 meters.
|
||||
const string AI_ENEMY_HEALTH = "AI_ENEMY_HEALTH"; // % of hitpoints.
|
||||
const string AI_ENEMY_NUMBERS = "AI_ENEMY_NUM"; // Number of enemies in combat.
|
||||
const string AI_ENEMY_POWER = "AI_ENEMY_POWER"; // (Level * Health %) / 100 added for each enemy to this.
|
||||
const string AI_ENEMY_NEAREST = "AI_ENEMY_NEAREST"; // Nearest enemy to OBJECT_SELF.
|
||||
// Variables used to keep track of allies in combat.
|
||||
const string AI_ALLY = "AI_ALLY"; // All friendly creatures
|
||||
const string AI_ALLY_DISABLED = "AI_ALLY_DISABLED"; // Int if they are disabled.
|
||||
const string AI_ALLY_PERCEIVED = "AI_ALLY_PERCEIVED"; // All allies are set to be seen and heard.
|
||||
const string AI_ALLY_RANGE = "AI_ALLY_RANGE"; // The range from OBJECT_SELF.
|
||||
const string AI_ALLY_COMBAT = "AI_ALLY_COMBAT"; // Combat rating: (BAB + AC - 10) / 2
|
||||
const string AI_ALLY_MELEE = "AI_ALLY_MELEE"; // Enemies within 5 meters - Allies within 5 meters.
|
||||
const string AI_ALLY_HEALTH = "AI_ALLY_HEALTH"; // % of hitpoints.
|
||||
const string AI_ALLY_NUMBERS = "AI_ALLY_NUM"; // Number of allies in combat.
|
||||
const string AI_ALLY_POWER = "AI_ALLY_POWER"; // (Level * Health %) / 100 added for each enemy to this.
|
||||
// Variable name used to define the ai scripts being used by creatures.
|
||||
const string AI_DEFAULT_SCRIPT = "AI_DEFAULT_SCRIPT";
|
||||
const string AI_COMBAT_SCRIPT = "AI_COMBAT_SCRIPT";
|
||||
// Constants used in a creatures listening patterns.
|
||||
const string AI_I_SEE_AN_ENEMY = "AI_I_SEE_AN_ENEMY";
|
||||
const string AI_I_HEARD_AN_ENEMY = "AI_I_HEARD_AN_ENEMY";
|
||||
const string AI_ATKED_BY_WEAPON = "AI_ATK_BY_WEAPON";
|
||||
const string AI_ATKED_BY_SPELL = "AI_ATK_BY_SPELL";
|
||||
const string AI_I_AM_WOUNDED = "AI_I_AM_WOUNDED";
|
||||
const string AI_I_AM_DEAD = "AI_I_AM_DEAD";
|
||||
const string AI_I_AM_DISEASED = "AI_I_AM_DISEASED";
|
||||
const string AI_I_AM_POISONED = "AI_I_AM_POISONED";
|
||||
const string AI_I_AM_WEAK = "AI_I_AM_WEAK";
|
||||
const int AI_ALLY_SEES_AN_ENEMY = 1;
|
||||
const int AI_ALLY_HEARD_AN_ENEMY = 2;
|
||||
const int AI_ALLY_ATKED_BY_WEAPON = 3;
|
||||
const int AI_ALLY_ATKED_BY_SPELL = 4;
|
||||
const int AI_ALLY_IS_WOUNDED = 5;
|
||||
const int AI_ALLY_IS_DEAD = 6;
|
||||
const int AI_ALLY_IS_DISEASED = 7;
|
||||
const int AI_ALLY_IS_POISONED = 8;
|
||||
const int AI_ALLY_IS_WEAK = 9;
|
||||
const string AI_MY_TARGET = "AI_MY_TARGET";
|
||||
// Constant used by monsters to reduce checks while searching for unseen targets.
|
||||
const string AI_AM_I_SEARCHING = "AI_AM_I_SEARCHING";
|
||||
// Used to keep track of oCreature attempting to hide.
|
||||
const string AI_TRIED_TO_HIDE = "AI_TRIED_TO_HIDE";
|
||||
// Constant used by creatures to keep track of invisible creatures.
|
||||
const string AI_IS_INVISIBLE = "AI_IS_INVISIBLE";
|
||||
// Constants used in combat to keep track of a creatures last action.
|
||||
// 0+ is the last spell cast from the line number in Spells.2da.
|
||||
const string sLastActionVarname = "AI_LAST_ACTION";
|
||||
const int AI_LAST_ACTION_CAST_SPELL = -1;
|
||||
const int AI_LAST_ACTION_NONE = -2;
|
||||
const int AI_LAST_ACTION_MELEE_ATK = -3;
|
||||
const int AI_LAST_ACTION_RANGED_ATK = -4;
|
||||
const int AI_LAST_ACTION_USED_FEAT = -5;
|
||||
const int AI_LAST_ACTION_USED_ITEM = -6;
|
||||
const int AI_LAST_ACTION_USED_SKILL = -7;
|
||||
const int AI_LAST_ACTION_MOVE = -8;
|
||||
// Variable name used to keep track of Action Modes.
|
||||
const string AI_CURRENT_ACTION_MODE = "AI_CURRENT_ACTION_MODE";
|
||||
// Variable name used to keep track of object usage by the AI.
|
||||
const string AI_OBJECT_IN_USE = "AI_OBJECT_IN_USE";
|
||||
// Variable name used to keep a creatures attacked targets.
|
||||
const string AI_ATTACKED_PHYSICAL = "AI_ATTACKED_PHYSICAL";
|
||||
const string AI_ATTACKED_SPELL = "AI_ATTACKED_SPELL";
|
||||
// Variable name used to keep track of a creatures normal polymorph form.
|
||||
const string AI_NORMAL_FORM = "AI_NORMAL_FORM";
|
||||
// Variable name used to keep track if a creature has been buffed yet.
|
||||
const string AI_CASTER_BUFFS_SET = "AI_CASTER_BUFFS_SET";
|
||||
// Variable name used to keep track of rounds in combat for a custom ai script.
|
||||
const string AI_ROUND = "AI_ROUND";
|
||||
// Combat Ranges
|
||||
const float AI_RANGE_MELEE = 5.0f; // Anyone within this is considered to be in melee.
|
||||
const float AI_RANGE_CLOSE = 8.0f; // For anything requiring to be within 30'.
|
||||
const float AI_RANGE_LONG = 15.0f; // Mainly used for distance ranged attacks.
|
||||
const float AI_RANGE_PERCEPTION = 35.0f; // This is the distance for perception in battle.
|
||||
const float AI_RANGE_BATTLEFIELD = 40.0f; // This is the size of the battlefield area.
|
||||
// Spell ranges.
|
||||
const float AI_SHORT_DISTANCE = 8.0f;
|
||||
const float AI_MEDIUM_DISTANCE = 20.0f;
|
||||
const float AI_LONG_DISTANCE = 40.0f;
|
||||
// When computer checks if a creature should cast a specific spell at a target.
|
||||
// Computer makes a spell check vs the targets saving throw.
|
||||
// Spell check roll for the caster is
|
||||
// [Innate spell Level + Random (AI_SPELL_CHECK_DIE) + AI_SPELL_CHECK_BONUS]
|
||||
// If the spell gives a save for half (i.e. FireBall) and the target does not have
|
||||
// Evasion then they get an additional bonus of AI_SPELL_CHECK_NO_EVASION_BONUS.
|
||||
const int AI_SPELL_CHECK_DIE = 6;
|
||||
const int AI_SPELL_CHECK_BONUS = 3;
|
||||
const int AI_SPELL_CHECK_NO_EVASION_BONUS = 10;
|
||||
// When the computer checks if a creature should use defensive casting it looks
|
||||
// at the spell level + AI_DEFENSIVE_CASTING_DC vs casters concentration
|
||||
// and feat bonuses (i.e. COMBAT_CASTING) + Random (AI_DEFENSIVE_CASTING_ROLL).
|
||||
const int AI_DEFENSIVE_CASTING_DC = 19; // 19 will allow them to use it at 50% effectiveness.
|
||||
const int AI_DEFENSIVE_CASTING_DIE = 10;
|
||||
// When the computer checks to see if it should cast in melee combat it looks
|
||||
// at CASTING_IN_MELEE_DC + SpellLevel + (Num of creatures in melee * GetHitDice (NearestEnemy));
|
||||
// vs the casters concentration + Random (AI_CASTING_IN_MELEE_ROLL).
|
||||
const int AI_CASTING_IN_MELEE_DC = 10;
|
||||
const int AI_CASTING_IN_MELEE_ROLL = 10;
|
||||
// For getting a specific class the following constants were added to flesh out
|
||||
// the CLASS_TYPE_*
|
||||
const int AI_CLASS_TYPE_CASTER = -1;
|
||||
const int AI_CLASS_TYPE_DIVINE = -2;
|
||||
const int AI_CLASS_TYPE_ARCANE = -3;
|
||||
const int AI_CLASS_TYPE_WARRIOR = -4;
|
||||
// For getting a specific race the following constants were added to flesh out
|
||||
// the RACIAL_TYPE_*
|
||||
const int AI_RACIAL_TYPE_ANIMAL_BEAST = -1;
|
||||
const int AI_RACIAL_TYPE_HUMANOID = -2;
|
||||
// Bitwise constants for negative conditions we might want to try to cure
|
||||
const int AI_CONDITION_POISON = 0x00000001;
|
||||
const int AI_CONDITION_DISEASE = 0x00000002;
|
||||
const int AI_CONDITION_BLINDDEAF = 0x00000004;
|
||||
const int AI_CONDITION_ATK_DECREASE = 0x00000008;
|
||||
const int AI_CONDITION_DMG_DECREASE = 0x00000010;
|
||||
const int AI_CONDITION_DMG_I_DECREASE = 0x00000020;
|
||||
const int AI_CONDITION_SKILL_DECREASE = 0x00000040;
|
||||
const int AI_CONDITION_SAVE_DECREASE = 0x00000080;
|
||||
const int AI_CONDITION_SR_DECREASE = 0x00000100;
|
||||
const int AI_CONDITION_AC_DECREASE = 0x00000200;
|
||||
const int AI_CONDITION_SLOW = 0x00000400;
|
||||
const int AI_CONDITION_ABILITY_DRAIN = 0x00000800;
|
||||
const int AI_CONDITION_LEVEL_DRAIN = 0x00001000;
|
||||
const int AI_CONDITION_CHARMED = 0x00002000;
|
||||
const int AI_CONDITION_DAZED = 0x00004000;
|
||||
const int AI_CONDITION_STUNNED = 0x00008000;
|
||||
const int AI_CONDITION_FRIGHTENED = 0x00010000;
|
||||
const int AI_CONDITION_CONFUSED = 0x00020000;
|
||||
const int AI_CONDITION_CURSE = 0x00040000;
|
||||
const int AI_CONDITION_PARALYZE = 0x00080000;
|
||||
const int AI_CONDITION_DOMINATED = 0x00100000;
|
||||
// Database constants for Associate modes.
|
||||
const string AI_MODE_DB_TABLE = "AI_MODE_DB_TABLE";
|
||||
// Bitwise constants for Associate modes that are used with Get/SetAssociateMode().
|
||||
const string sAIModeVarname = "ASSOCIATE_MODES";
|
||||
//const int AI_MODE_DISTANCE_CLOSE = 0x00000001; // Stays within AI_DISTANCE_CLOSE of master.
|
||||
//const int AI_MODE_DISTANCE_MEDIUM = 0x00000002; // Stays within AI_DISTANCE_MEDIUM of master.
|
||||
const int AI_MODE_ACTION_GHOST = 0x00000004; // Defines if the player is using Ghost mode when using associate actions.
|
||||
const int AI_MODE_SELF_HEALING_OFF = 0x00000008; // Creature will not use healing items or spells on self.
|
||||
const int AI_MODE_PARTY_HEALING_OFF = 0x00000010; // Creature will not use healing items or spells on party.
|
||||
const int AI_MODE_GHOST = 0x00000020; // Creature can move through other creatures.
|
||||
const int AI_MODE_OPEN_DOORS = 0x00000040; // Creature will attempted to open all doors.
|
||||
const int AI_MODE_EQUIP_WEAPON_OFF = 0x00000080; // The AI will not equip weapons.
|
||||
const int AI_MODE_BASH_LOCKS = 0x00000100; // Will bash locks if cannot open door/placeable.
|
||||
const int AI_MODE_AGGRESSIVE_SEARCH = 0x00000200; // Sets associate to continuous search mode.
|
||||
const int AI_MODE_AGGRESSIVE_STEALTH = 0x00000400; // Sets associate to continuous stealth mode.
|
||||
const int AI_MODE_PICK_LOCKS = 0x00000800; // Will pick locks if possible.
|
||||
const int AI_MODE_DISARM_TRAPS = 0x00001000; // Will disarm traps.
|
||||
const int AI_MODE_SCOUT_AHEAD = 0x00002000; // Will move ahead of master and scout.
|
||||
const int AI_MODE_DEFEND_MASTER = 0x00004000; // Will attack enemies attacking our master.
|
||||
const int AI_MODE_STAND_GROUND = 0x00008000; // Will stay in one place until new command.
|
||||
const int AI_MODE_STOP_RANGED = 0x00010000; // Will not use ranged weapons.
|
||||
const int AI_MODE_FOLLOW = 0x00020000; // Keeps associate following master ignoring combat.
|
||||
const int AI_MODE_PICKUP_ITEMS = 0x00040000; // Will pickup up all items for master.
|
||||
const int AI_MODE_COMMANDED = 0x00080000; // In Command mode then don't follow, search, etc.
|
||||
const int AI_MODE_IGNORE_TRAPS = 0x00100000; // Creature will ignore traps on the floor.
|
||||
const int AI_MODE_NO_STEALTH = 0x00200000; // Will not cast invisibilty or use stealth.
|
||||
const int AI_MODE_DO_NOT_SPEAK = 0x00400000; // Tells the henchmen to be silent and not talk.
|
||||
const int AI_MODE_CHECK_ATTACK = 0x00800000; // Will only engage in combats they think they can win.
|
||||
const int AI_MODE_IGNORE_ASSOCIATES = 0x01000000; // Will ignore associates in combat.
|
||||
//const int AI_MODE_ = 0x02000000; // Not used.
|
||||
//const int AI_MODE_ = 0x04000000; // Not used.
|
||||
//const int AI_MODE_ = 0x08000000; // Not used.
|
||||
//const int AI_MODE_ = 0x10000000; // Not used.
|
||||
//const int AI_MODE_ = 0x20000000; // Not used.
|
||||
//const int AI_MODE_ = 0x40000000; // Not used.
|
||||
//const int AI_MODE_ = 0x80000000; // Not used.
|
||||
// Bitwise constants for Associate magic modes that are used with Get/SetAssociateMagicMode().
|
||||
const string sMagicModeVarname = "ASSOCIATE_MAGIC_MODES";
|
||||
const int AI_MAGIC_BUFF_MASTER = 0x00000001; // Buffs master before other allies.
|
||||
const int AI_MAGIC_NO_MAGIC = 0x00000002; // Will not use any magic (Spells, abilities).
|
||||
const int AI_MAGIC_DEFENSIVE_CASTING = 0x00000004; // Will only cast defensive spells.
|
||||
const int AI_MAGIC_OFFENSIVE_CASTING = 0x00000008; // Will only cast offensive spells.
|
||||
const int AI_MAGIC_STOP_DISPEL = 0x00000010; // Will not cast dispel type spells.
|
||||
const int AI_MAGIC_BUFF_AFTER_REST = 0x00000020; // Will buff the party after resting.
|
||||
const int AI_MAGIC_NO_MAGIC_ITEMS = 0x00000040; // Will not use magic items in combat.
|
||||
const int AI_MAGIC_CURE_SPELLS_OFF = 0x00000080; // Will not cast cure spells.
|
||||
const int AI_MAGIC_EFFECT_ICON_REPORT = 0x00000100; // Sets each player to report Effect Icons to chat.
|
||||
//const int = 0x00000200; // Not used.
|
||||
//const int = 0x00000400; // Not used.
|
||||
const int AI_MAGIC_NO_SPONTANEOUS_CURE = 0x00000800; // Caster will stop using spontaneous cure spells.
|
||||
//const int AI_MAGIC_ = 0x00001000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00002000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00004000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00008000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00010000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00020000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00040000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00080000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00100000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00200000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00400000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x00800000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x01000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x02000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x04000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x08000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x10000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x20000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x40000000; // Not used.
|
||||
//const int AI_MAGIC_ = 0x80000000; // Not used.
|
||||
// Use by NUI windows to stop saving move states while loading.
|
||||
const string AI_NO_NUI_SAVE = "AI_NO_NUI_SAVE";
|
||||
// Bitwise menu constants for Widget buttons that are used with Get/SetAssociateWidgetButtons().
|
||||
const string sWidgetButtonsVarname = "ASSOCIATE_WIDGET_BUTTONS";
|
||||
const int BTN_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
|
||||
const int BTN_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
|
||||
const int BTN_CMD_GUARD = 0x00000004; // Command associates to Guard Me. PC widget only.
|
||||
const int BTN_CMD_FOLLOW = 0x00000008; // Command associates to Follow. PC widget only.
|
||||
const int BTN_CMD_HOLD = 0x00000010; // Command associates to Stand Ground. PC widget only.
|
||||
const int BTN_CMD_ATTACK = 0x00000020; // Command associates to Attack Nearest. PC widget only.
|
||||
const int BTN_BUFF_REST = 0x00000040; // Buffs with long duration spells after resting. Associate widget only.
|
||||
const int BTN_BUFF_SHORT = 0x00000080; // Buffs with short duration spells.
|
||||
const int BTN_BUFF_LONG = 0x00000100; // Buffs with long duration spells.
|
||||
const int BTN_BUFF_ALL = 0x00000200; // Buffs with all spells.
|
||||
const int BTN_CMD_ACTION = 0x00000400; // Command associate to do an action.
|
||||
const int BTN_CMD_GHOST_MODE = 0x00000800; // Toggle's associates ghost mode.
|
||||
const int BTN_CMD_AI_SCRIPT = 0x00001000; // Toggle's special tactics ai scripts.
|
||||
const int BTN_CMD_PLACE_TRAP = 0x00002000; // A trapper may place traps.
|
||||
const int BTN_CMD_CAMERA = 0x00004000; // Places camera view on associate.
|
||||
const int BTN_CMD_INVENTORY = 0x00008000; // Opens inventory of associate.
|
||||
const int BTN_CMD_FAMILIAR = 0x00010000; // Summons familiar.
|
||||
const int BTN_CMD_COMPANION = 0x00020000; // Summons Companion.
|
||||
const int BTN_CMD_SEARCH = 0x00040000; // Command all associates to use search mode. PC widget only.
|
||||
const int BTN_CMD_STEALTH = 0x00080000; // Command all associates to use stealth mode. PC widget only.
|
||||
const int BTN_CMD_SCOUT = 0x00100000; // Command associate to scout ahead of the part.
|
||||
const int BTN_CMD_SPELL_WIDGET = 0x00200000; // Allows adding or removing spells from Spell Widget.
|
||||
const int BTN_CMD_JUMP_TO = 0x00400000; // Player can make associates jump to them.
|
||||
const int BTN_WIDGET_VERTICAL = 0x80000000; // Widget will be displayed vertical.
|
||||
// Bitwise menu constants for Associate AI buttons that are used with Get/SetAssociateAIButtons().
|
||||
const string sAIButtonsVarname = "ASSOCIATE_AI_BUTTONS";
|
||||
const int BTN_AI_FOR_PC = 0x00000001; // PC use AI. PC widget only.
|
||||
const int BTN_AI_USE_RANGED = 0x00000002; // AI uses ranged attacks.
|
||||
const int BTN_AI_USE_SEARCH = 0x00000004; // AI uses Search.
|
||||
const int BTN_AI_USE_STEALTH = 0x00000008; // AI uses Stealth.
|
||||
const int BTN_AI_REMOVE_TRAPS = 0x00000010; // AI seeks out and removes traps.
|
||||
const int BTN_AI_PICK_LOCKS = 0x00000020; // AI will attempt to pick locks.
|
||||
const int BTN_AI_MAGIC_LEVEL = 0x00000040; // Increase chance to use magic in battle.
|
||||
const int BTN_AI_NO_SPONTANEOUS = 0x00000080; // Stops the use of spontaneous spells.
|
||||
const int BTN_AI_NO_MAGIC_USE = 0x00000100; // Will not use magic in battle.
|
||||
const int BTN_AI_NO_MAGIC_ITEM_USE = 0x00000200; // Will not use magic items in battle.
|
||||
const int BTN_AI_DEF_MAGIC_USE = 0x00000400; // Will use Defensive spells only in battle.
|
||||
const int BTN_AI_OFF_MAGIC_USE = 0x00000800; // Will use Offensive spells only in battle.
|
||||
const int BTN_AI_LOOT = 0x00001000; // Auto picking up loot on/off.
|
||||
const int BTN_AI_FOLLOW_TARGET = 0x00002000; // Selects a target to follow.
|
||||
const int BTN_AI_HEAL_OUT = 0x00004000; // Increase minimum hp required before ai heals out of combat.
|
||||
const int BTN_AI_PERC_RANGE = 0x00008000; // Adjust the perception range of the henchman.
|
||||
const int BTN_AI_HEAL_IN = 0x00010000; // Increase minimum hp required before ai heals in combat.
|
||||
const int BTN_AI_OPEN_DOORS = 0x00020000; // AI will open all closed doors.
|
||||
const int BTN_AI_STOP_SELF_HEALING = 0x00040000; // Stops AI from using any healing on self.
|
||||
const int BTN_AI_STOP_PARTY_HEALING = 0x00080000; // Stops AI from using any healing on party.
|
||||
const int BTN_AI_IGNORE_ASSOCIATES = 0x00100000; // AI will deprioritize enemy associates.
|
||||
const int BTN_AI_STOP_CURE_SPELLS = 0x00200000; // AI uses cure spells.
|
||||
const int BTN_AI_STOP_WEAPON_EQUIP = 0x00400000; // AI can equip different weapons.
|
||||
const int BTN_AI_IGNORE_TRAPS = 0x00800000; // AI will ignore traps on the floor.
|
||||
//const int BTN_AI = 0x01000000; // Not used.
|
||||
//const int BTN_AI = 0x02000000; // Not used.
|
||||
const int BTN_AI_BASH_LOCKS = 0x04000000; // AI will attempt to bash any locks they can't get past.
|
||||
const int BTN_AI_REDUCE_SPEECH = 0x08000000; // Reduce the associates speaking.
|
||||
// Bitwise menu constants for DM access for players Widget buttons uses BTN_CMD and BTN_BUFF bitwise see above.
|
||||
const string sDMWidgetAccessVarname = "AI_RULES_WIDGET_BUTTONS_ACCESS";
|
||||
// Bitwise menu constants for DM access for players AI buttons uses BTN_AI bitwise see above.
|
||||
const string sDMAIAccessVarname = "AI_RULES_AI_BUTTONS_ACCESS";
|
||||
// Variable name for DM widget buttons.
|
||||
const string sDMWidgetButtonVarname = "DM_WIDGET_BUTTONS";
|
||||
// DM Widget buttons states.
|
||||
const int BTN_DM_WIDGET_OFF = 0x00000001; // Removes the widget from the screen, For PC it removes all associates.
|
||||
const int BTN_DM_WIDGET_LOCK = 0x00000002; // Locks the widget to the current coordinates.
|
||||
const int BTN_DM_CMD_GROUP1 = 0x00000004; // Does all the group 1 commands.
|
||||
const int BTN_DM_CMD_GROUP2 = 0x00000008; // Does all the group 2 commands.
|
||||
const int BTN_DM_CMD_GROUP3 = 0x00000010; // Does all the group 3 commands.
|
||||
const int BTN_DM_CMD_GROUP4 = 0x00000020; // Does all the group 4 commands.
|
||||
const int BTN_DM_CMD_GROUP5 = 0x00000040; // Does all the group 5 commands.
|
||||
const int BTN_DM_CMD_GROUP6 = 0x00000080; // Does all the group 6 commands.
|
||||
const int BTN_DM_CMD_CAMERA = 0x00000100; // Selects new object to hold the camera view.
|
||||
const int BTN_DM_CMD_INVENTORY = 0x00000200; // Selects a creature to open the inventory of.
|
||||
const int BTN_DM_CMD_MEMORIZE = 0x00000400; // Allows associate to change memorized spells.
|
||||
// Bitwise constants for Associate loot options that are used with Get/SetAssociateLootMode().
|
||||
const string sLootFilterVarname = "ASSOCIATE_LOOT_MODES";
|
||||
const int AI_LOOT_PLOT = 0x00000001;
|
||||
const int AI_LOOT_WEAPONS = 0x00000002;
|
||||
const int AI_LOOT_ARMOR = 0x00000004;
|
||||
const int AI_LOOT_SHIELDS = 0x00000008;
|
||||
const int AI_LOOT_HEADGEAR = 0x00000010;
|
||||
const int AI_LOOT_BELTS = 0x00000020;
|
||||
const int AI_LOOT_BOOTS = 0x00000040;
|
||||
const int AI_LOOT_CLOAKS = 0x00000080;
|
||||
const int AI_LOOT_GLOVES = 0x00000100;
|
||||
const int AI_LOOT_JEWELRY = 0x00000200;
|
||||
const int AI_LOOT_POTIONS = 0x00000400;
|
||||
const int AI_LOOT_SCROLLS = 0x00000800;
|
||||
const int AI_LOOT_WANDS_RODS_STAVES = 0x00001000;
|
||||
const int AI_LOOT_GEMS = 0x00002000;
|
||||
const int AI_LOOT_MISC = 0x00004000;
|
||||
const int AI_LOOT_ARROWS = 0x00008000;
|
||||
const int AI_LOOT_BOLTS = 0x00010000;
|
||||
const int AI_LOOT_BULLETS = 0x00020000;
|
||||
const int AI_LOOT_GIVE_TO_PC = 0x80000000;
|
||||
// Default value for all loot filters to be on.
|
||||
const int AI_LOOT_ALL_ON = 262143;
|
||||
// Variable to keep track of who is in ghost mode.
|
||||
const string sGhostModeVarname = "AI_GHOST_MODE_ON";
|
||||
// Variables for gold piece value to pickup items.
|
||||
const string AI_MIN_GOLD_ = "AI_MIN_GOLD_";
|
||||
// Variable used to limit the spamming of NUI buttons.
|
||||
const string AI_DELAY_NUI_USE = "AI_DELAY_NUI_USE";
|
||||
// Variable for maximum weight to pickup from looting.
|
||||
const string AI_MAX_LOOT_WEIGHT = "AI_MAX_LOOT_WEIGHT";
|
||||
// Variable to change the size of the widget buttons.
|
||||
const string AI_WIDGET_BUTTON_SIZE = "AI_WIDGET_BUTTON_SIZE";
|
||||
// Variable to change the difficulty so a player can adjust spell usage.
|
||||
const string AI_DIFFICULTY_ADJUSTMENT = "AI_DIFFICULTY_ADJUSTMENT";
|
||||
// Variable to change the Healing % limit for out of combat.
|
||||
const string AI_HEAL_OUT_OF_COMBAT_LIMIT = "AI_HEAL_OUT_OF_COMBAT_LIMIT";
|
||||
// Variable to change the Healing % limit for in combat.
|
||||
const string AI_HEAL_IN_COMBAT_LIMIT = "AI_HEAL_IN_COMBAT_LIMIT";
|
||||
// Variable to change the looting range.
|
||||
const string AI_LOOT_CHECK_RANGE = "AI_LOOT_CHECK_RANGE";
|
||||
// Variable to change the lock checking range.
|
||||
const string AI_LOCK_CHECK_RANGE = "AI_LOCK_CHECK_RANGE";
|
||||
// Variable to change the trap checking range.
|
||||
const string AI_TRAP_CHECK_RANGE = "AI_TRAP_CHECK_RANGE";
|
||||
// Variable to change the range an associate follows the pc.
|
||||
const string AI_FOLLOW_RANGE = "AI_FOLLOW_RANGE";
|
||||
// Variable that holds the target for an associate to follow.
|
||||
const string AI_FOLLOW_TARGET = "AI_FOLLOW_TARGET";
|
||||
// Variable that holds the perception range of associates i.e. 8, 9, 10, 11.
|
||||
const string AI_ASSOCIATE_PERCEPTION = "AI_PERCEPTION_RANGE";
|
||||
// Variable that holds the perception distance of associates i.e. 30.0 meters.
|
||||
const string AI_ASSOC_PERCEPTION_DISTANCE = "AI_ASSOC_PERCEPTION_DISTANCE";
|
||||
// Variable that holds the open doors range of the henchman.
|
||||
const string AI_OPEN_DOORS_RANGE = "AI_OPEN_DOORS_RANGE";
|
||||
// Variable that holds the Spell widgets json data.
|
||||
const string AI_SPELLS_WIDGET = "AI_SPELLS_WIDGET";
|
||||
// The number of Buff Groups
|
||||
const int AI_BUFF_GROUPS = -17;
|
||||
// Variable name used to keep track if we have set our talents.
|
||||
const string AI_TALENTS_SET = "AI_TALENTS_SET";
|
||||
// New talent categories
|
||||
const string AI_TALENT_ENHANCEMENT = "E";
|
||||
const string AI_TALENT_PROTECTION = "P";
|
||||
const string AI_TALENT_SUMMON = "S";
|
||||
const string AI_TALENT_HEALING = "H";
|
||||
const string AI_TALENT_CURE = "C";
|
||||
const string AI_TALENT_INDISCRIMINANT_AOE = "I";
|
||||
const string AI_TALENT_DISCRIMINANT_AOE = "D";
|
||||
const string AI_TALENT_RANGED = "R";
|
||||
const string AI_TALENT_TOUCH = "T";
|
||||
// Talent types.
|
||||
const int AI_TALENT_TYPE_SPELL = 1;
|
||||
const int AI_TALENT_TYPE_SP_ABILITY = 2;
|
||||
const int AI_TALENT_TYPE_FEAT = 3;
|
||||
const int AI_TALENT_TYPE_ITEM = 4;
|
||||
// Variable name used to have associates fight the pc's selected target.
|
||||
const string AI_PC_LOCKED_TARGET = "AI_PC_LOCKED_TARGET";
|
||||
// Variable name of json talent immunity.
|
||||
const string AI_TALENT_IMMUNITY = "AI_TALENT_IMMUNITY";
|
||||
// Variables keeps track of the maximum level for the talent category.
|
||||
const string AI_MAX_TALENT = "AI_MAX_TALENT_";
|
||||
// Backward compatability constants.
|
||||
const int X2_EVENT_CONCENTRATION_BROKEN = 12400;
|
||||
// Variable set on the module if the module is using PRC.
|
||||
const string AI_USING_PRC = "AI_USING_PRC";
|
||||
// Variable that sets if the rules have been added to the module.
|
||||
const string AI_RULES_SET = "AI_RULES_SET";
|
||||
// Variable that tells us that oCreature has run our OnSpawn event.
|
||||
const string AI_ONSPAWN_EVENT = "AI_ONSPAWN_EVENT";
|
||||
// Variable used to define a creatures unique Tag for widgets.
|
||||
const string AI_TAG = "AI_TAG";
|
||||
// Variable that saves any module target event script so we can pass it along.
|
||||
const string AI_MODULE_TARGET_EVENT = "AI_MODULE_TARGET_EVENT";
|
||||
// Variable for plugins to inject Targeting mode code into PEPS.
|
||||
const string AI_PLUGIN_TARGET_SCRIPT = "AI_PLUGIN_TARGET_SCRIPT";
|
||||
// Variable for PEPS to inject effect icons NUI information.
|
||||
const string AI_MODULE_GUI_EVENT = "AI_MODULE_GUI_EVENT";
|
||||
// Variable used on the player to define the targeting action in the OnPlayerTarget event script.
|
||||
const string AI_TARGET_MODE = "AI_TARGET_MODE";
|
||||
// Variable used on the player to define which associate triggered the OnPlayer Target.
|
||||
const string AI_TARGET_ASSOCIATE = "AI_TARGET_ASSOCIATE";
|
||||
// Bitwise constants for immune damage item properties that is used with Get/SetItemProperty().
|
||||
const string sIPImmuneVarname = "AI_IP_IMMUNE";
|
||||
// Bitwise constants for resisted damage item properties that is used with Get/SetItemProperty().
|
||||
const string sIPResistVarname = "AI_IP_RESIST";
|
||||
// Variable name for the Int constant for reduced damage item property set to the bonus of the weapon required.
|
||||
const string sIPReducedVarname = "AI_IP_REDUCED";
|
||||
// Variable name for the Int (Bool) constant for the haste item property.
|
||||
const string sIPHasHasteVarname = "AI_IP_HAS_HASTE";
|
||||
// Variable name used to hold the party xp base needed to adjust party xp.
|
||||
const string AI_BASE_PARTY_SCALE_XP = "AI_BASE_PARTY_SCALE_XP";
|
||||
//***************************** AI RULES CONSTANTS *****************************
|
||||
// Variable name set to a creatures full name to set debugging on.
|
||||
const string AI_RULE_DEBUG_CREATURE = "AI_RULE_DEBUG_CREATURE";
|
||||
// Moral checks on or off.
|
||||
const string AI_RULE_MORAL_CHECKS = "AI_RULE_MORAL_CHECKS";
|
||||
// Allows monsters to prebuff before combat starts.
|
||||
const string AI_RULE_BUFF_MONSTERS = "AI_RULE_BUFF_MONSTERS";
|
||||
// Allows monsters to use the ambush AI scripts.
|
||||
const string AI_RULE_AMBUSH = "AI_RULE_AMBUSH";
|
||||
// Enemies may summon familiars and Animal companions and will be randomized.
|
||||
const string AI_RULE_SUMMON_COMPANIONS = "AI_RULE_SUMMON_COMPANIONS";
|
||||
// Allows monsters cast summons spells when prebuffing.
|
||||
const string AI_RULE_PRESUMMON = "AI_RULE_PRESUMMON";
|
||||
// Allow the AI move during combat base on the situation and action taking.
|
||||
const string AI_RULE_ADVANCED_MOVEMENT = "AI_RULE_ADVANCED_MOVEMENT";
|
||||
// Follow Item Level Restrictions for monsters/associates.
|
||||
// Usually off in Single player and on in Multi player.
|
||||
const string AI_RULE_ILR = "AI_RULE_ILR";
|
||||
// Allow the AI to use Use Magic Device.
|
||||
const string AI_RULE_ALLOW_UMD = "AI_RULE_ALLOW_UMD";
|
||||
// Allow the AI to use healing kits.
|
||||
const string AI_RULE_HEALERSKITS = "AI_RULE_HEALERSKITS";
|
||||
// Summoned associates are permanent and don't disappear when the caster dies.
|
||||
const string AI_RULE_PERM_ASSOC = "AI_RULE_PERM_ASSOC";
|
||||
// Monster AI's chance to attack the weakest target instead of the nearest.
|
||||
const string AI_RULE_AI_DIFFICULTY = "AI_RULE_AI_DIFFICULTY";
|
||||
// Variable that can change the distance creatures will come and attack after
|
||||
// hearing a shout from an ally that sees or hears an enemy.
|
||||
// Or when searching for an invisible, heard enemy.
|
||||
// 10.0 Short, 30.0 Average, 40.0 Long, 60.0 Huge.
|
||||
const string AI_RULE_PERCEPTION_DISTANCE = "AI_RULE_PERCEPTION_DISTANCE";
|
||||
// Enemy corpses remain on the floor instead of dissappearing.
|
||||
const string AI_RULE_CORPSES_STAY = "AI_RULE_CORPSES_STAY";
|
||||
// Monsters will wander around when not in combat.
|
||||
const string AI_RULE_WANDER = "AI_RULE_WANDER";
|
||||
// Increase the number of encounter creatures.
|
||||
const string AI_INCREASE_ENC_MONSTERS = "AI_INCREASE_ENC_MONSTERS";
|
||||
// Increase all monsters hitpoints by this percentage.
|
||||
const string AI_INCREASE_MONSTERS_HP = "AI_INCREASE_MONSTERS_HP";
|
||||
// Variable that can change the distance monsters can hear and see.
|
||||
const string AI_RULE_MON_PERC_DISTANCE = "AI_RULE_MON_PERC_DISTANCE";
|
||||
// Variable name set to hold the maximum number of henchman the player wants.
|
||||
const string AI_RULE_MAX_HENCHMAN = "AI_RULE_MAX_HENCHMAN";
|
||||
// Variable name set to hold the distance monsters can wander away.
|
||||
const string AI_RULE_WANDER_DISTANCE = "AI_RULE_WANDER_DISTANCE";
|
||||
// Variable name set to allow wandering monsters to open doors.
|
||||
const string AI_RULE_OPEN_DOORS = "AI_RULE_OPEN_DOORS";
|
||||
// Variable name set to hold the modules default xp scale for use later.
|
||||
const string AI_RULE_DEFAULT_XP_SCALE = "AI_RULE_DEFAULT_XP_SCALE";
|
||||
// Variable name set to allow the game to regulate experience based on party size.
|
||||
const string AI_RULE_PARTY_SCALE = "AI_RULE_PARTY_SCALE";
|
||||
// Variable name set to restrict the AI's use of Darkness.
|
||||
const string AI_RULE_RESTRICTED_SPELLS = "AI_RULE_RESTRICTED_SPELLS";
|
||||
/*/ Special behavior constants from x0_i0_behavior
|
||||
const int NW_FLAG_BEHAVIOR_SPECIAL = 0x00000001;
|
||||
//Will always attack regardless of faction
|
||||
const int NW_FLAG_BEHAVIOR_CARNIVORE = 0x00000002;
|
||||
//Will only attack if approached
|
||||
const int NW_FLAG_BEHAVIOR_OMNIVORE = 0x00000004;
|
||||
//Will never attack. Will alway flee.
|
||||
const int NW_FLAG_BEHAVIOR_HERBIVORE = 0x00000008;
|
||||
// This is the name of the local variable that holds the spawn-in conditions
|
||||
const string sSpawnCondVarname = "NW_GENERIC_MASTER";
|
||||
// The available spawn-in conditions from x0_i0_spawncond
|
||||
const int NW_FLAG_ESCAPE_RETURN = 0x00000020; //Failed
|
||||
const int NW_FLAG_ESCAPE_LEAVE = 0x00000040;
|
||||
const int NW_FLAG_TELEPORT_RETURN = 0x00000080; //Failed
|
||||
const int NW_FLAG_TELEPORT_LEAVE = 0x00000100;
|
||||
const int NW_FLAG_END_COMBAT_ROUND_EVENT = 0x00004000;
|
||||
const int NW_FLAG_ON_DIALOGUE_EVENT = 0x00008000;
|
||||
const int NW_FLAG_AMBIENT_ANIMATIONS = 0x00080000;
|
||||
const int NW_FLAG_HEARTBEAT_EVENT = 0x00100000;
|
||||
const int NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS = 0x00200000;
|
||||
const int NW_FLAG_DAY_NIGHT_POSTING = 0x00400000;
|
||||
const int NW_FLAG_AMBIENT_ANIMATIONS_AVIAN = 0x00800000;
|
||||
const string sWalkwayVarname = "NW_WALK_CONDITION";
|
||||
// If set, the creature's waypoints have been initialized.
|
||||
const int NW_WALK_FLAG_INITIALIZED = 0x00000001;
|
||||
// If set, the creature will walk its waypoints constantly,
|
||||
// moving on in each OnHeartbeat event. Otherwise,
|
||||
// it will walk to the next only when triggered by an
|
||||
// OnPerception event.
|
||||
const int NW_WALK_FLAG_CONSTANT = 0x00000002;
|
||||
// Set when the creature is walking day waypoints.
|
||||
const int NW_WALK_FLAG_IS_DAY = 0x00000004;
|
||||
// Set when the creature is walking back
|
||||
const int NW_WALK_FLAG_BACKWARDS = 0x00000008;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user