2025/12/24 Update

Hooked up new GUI module event.
Updated PEPS.
Updated PRC8 includes.
Updated nasher.cfg.
This commit is contained in:
Jaysyn904
2025-12-24 22:10:16 -05:00
parent 584a0f89ab
commit fc7c3485be
176 changed files with 11289 additions and 3566 deletions

View File

@@ -21,6 +21,7 @@ description = "PRC8 version of D3 - Vault of the Drow."
include = "src/module/**/*"
include = "src/include/**/*"
filter = "bnd_inc_bndfunc.nss"
filter = "bnd_inc_bndfunc.nss"
filter = "bnd_vestig_const.nss"
filter = "inc_2dacache.nss"
filter = "inc_abil_damage.nss"
@@ -231,9 +232,16 @@ description = "PRC8 version of D3 - Vault of the Drow."
filter = "prc_nui_sc_inc.nss"
filter = "prc_nui_scd_inc.nss"
filter = "prc_nui_consts.nss"
filter = "nw_inc_nui"
filter = "nw_inc_nui.nss"
filter = "xchst_inc.nss"
filter = "prc_nui_sbd_inc.nss"
filter = "prc_nui_sb_inc.nss"
filter = "prc_nui_lv_inc.nss"
filter = "prc_nui_com_inc.nss"
filter = "prc_inc_size.nss"
filter = "prc_inc_json.nss"
filter = "prc_inc_gff.nss"
filter = "inc_infusion.nss"
[target.rules]
"*" = "src/module/$ext"

View File

@@ -12,6 +12,7 @@
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//PRC8 Token pre-fix = 161838
//////////////////////////////////////////////////
/* Constant definitions */
@@ -21,23 +22,23 @@ const int DYNCONV_EXITED = -2;
const int DYNCONV_ABORTED = -3;
const int DYNCONV_SETUP_STAGE = -1;
const int DYNCONV_TOKEN_HEADER = 99;
const int DYNCONV_TOKEN_REPLY_0 = 100;
const int DYNCONV_TOKEN_REPLY_1 = 101;
const int DYNCONV_TOKEN_REPLY_2 = 102;
const int DYNCONV_TOKEN_REPLY_3 = 103;
const int DYNCONV_TOKEN_REPLY_4 = 104;
const int DYNCONV_TOKEN_REPLY_5 = 105;
const int DYNCONV_TOKEN_REPLY_6 = 106;
const int DYNCONV_TOKEN_REPLY_7 = 107;
const int DYNCONV_TOKEN_REPLY_8 = 108;
const int DYNCONV_TOKEN_REPLY_9 = 109;
const int DYNCONV_TOKEN_EXIT = 110;
const int DYNCONV_TOKEN_WAIT = 111;
const int DYNCONV_TOKEN_NEXT = 112;
const int DYNCONV_TOKEN_PREV = 113;
const int DYNCONV_MIN_TOKEN = 99;
const int DYNCONV_MAX_TOKEN = 113;
const int DYNCONV_TOKEN_HEADER = 16183899;
const int DYNCONV_TOKEN_REPLY_0 = 161838100;
const int DYNCONV_TOKEN_REPLY_1 = 161838101;
const int DYNCONV_TOKEN_REPLY_2 = 161838102;
const int DYNCONV_TOKEN_REPLY_3 = 161838103;
const int DYNCONV_TOKEN_REPLY_4 = 161838104;
const int DYNCONV_TOKEN_REPLY_5 = 161838105;
const int DYNCONV_TOKEN_REPLY_6 = 161838106;
const int DYNCONV_TOKEN_REPLY_7 = 161838107;
const int DYNCONV_TOKEN_REPLY_8 = 161838108;
const int DYNCONV_TOKEN_REPLY_9 = 161838109;
const int DYNCONV_TOKEN_EXIT = 161838110;
const int DYNCONV_TOKEN_WAIT = 161838111;
const int DYNCONV_TOKEN_NEXT = 161838112;
const int DYNCONV_TOKEN_PREV = 161838113;
const int DYNCONV_MIN_TOKEN = 16183899;
const int DYNCONV_MAX_TOKEN = 161838113;
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
@@ -477,9 +478,28 @@ void _DynConvInternal_ExitedConvo(object oPC, int bAbort)
DeleteLocalInt(oPC, DYNCONV_STAGE);
DeleteLocalString(oPC, DYNCONV_SCRIPT);
DeleteLocalString(oPC, "DynConv_HeaderText");
int i;
for(i = DYNCONV_MIN_TOKEN; i <= DYNCONV_MAX_TOKEN; i++)
DeleteLocalString(oPC, GetTokenIDString(i));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_HEADER));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_0));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_1));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_2));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_3));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_4));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_5));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_6));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_7));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_8));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_REPLY_9));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_EXIT));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_WAIT));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_NEXT));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_TOKEN_PREV));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_MIN_TOKEN));
DeleteLocalString(oPC, GetTokenIDString(DYNCONV_MAX_TOKEN));
//int i;
//for(i = DYNCONV_MIN_TOKEN; i <= DYNCONV_MAX_TOKEN; i++)
//DeleteLocalString(oPC, GetTokenIDString(i));
}
}
}

View File

@@ -26,7 +26,7 @@ int GetSpellFromAbrev(string sAbrev);
//////////////////////////////////////////////////
#include "inc_utility"
//#include "inc_epicspelldef"
#include "inc_epicspells"
// SEED FUNCTIONS

View File

@@ -303,11 +303,18 @@ int GetIsEpicShaman(object oPC)
&& GetAbilityScore(oPC, ABILITY_WISDOM) > 18;
}
int GetIsEpicSorcerer(object oPC)
int GetIsEpicSorcerer(object oPC)
{
return GetHitDice(oPC) >= 21
&& GetCasterLvl(CLASS_TYPE_SORCERER, oPC) > 17
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
}
/* int GetIsEpicSorcerer(object oPC)
{
return GetPrCAdjustedCasterLevel(CLASS_TYPE_SORCERER, oPC, FALSE) > 17
&& GetAbilityScore(oPC, ABILITY_CHARISMA) > 18;
}
} */
int GetIsEpicSublimeChord(object oPC)
{

View File

@@ -1643,7 +1643,60 @@ int GetIsMagicItem(object oItem)
int FeatToIprop(int nFeat)
{
switch(nFeat)
{//: Weapon Focus
{
//:: Weapon Proficiencies
case FEAT_WEAPON_PROFICIENCY_SHORTSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
case FEAT_WEAPON_PROFICIENCY_LONGSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LONGSWORD;
case FEAT_WEAPON_PROFICIENCY_BATTLEAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
case FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
case FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
case FEAT_WEAPON_PROFICIENCY_WARHAMMER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_WARHAMMER;
case FEAT_WEAPON_PROFICIENCY_LONGBOW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LONGBOW;
case FEAT_WEAPON_PROFICIENCY_LIGHT_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
case FEAT_WEAPON_PROFICIENCY_HALBERD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HALBERD;
case FEAT_WEAPON_PROFICIENCY_SHORTBOW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTBOW;
case FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD;
case FEAT_WEAPON_PROFICIENCY_GREATSWORD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GREATSWORD;
case FEAT_WEAPON_PROFICIENCY_GREATAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GREATAXE;
case FEAT_WEAPON_PROFICIENCY_DART: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DART;
case FEAT_WEAPON_PROFICIENCY_DIRE_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DIRE_MACE;
case FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE;
case FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL;
case FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER;
case FEAT_WEAPON_PROFICIENCY_HANDAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HANDAXE;
case FEAT_WEAPON_PROFICIENCY_KAMA: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KAMA;
case FEAT_WEAPON_PROFICIENCY_KATANA: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KATANA;
case FEAT_WEAPON_PROFICIENCY_KUKRI: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KUKRI;
case FEAT_WEAPON_PROFICIENCY_MORNINGSTAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_MORNINGSTAR;
case FEAT_WEAPON_PROFICIENCY_RAPIER: return IP_CONST_FEAT_WEAPON_PROFICIENCY_RAPIER;
case FEAT_WEAPON_PROFICIENCY_SCIMITAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SCIMITAR;
case FEAT_WEAPON_PROFICIENCY_SCYTHE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SCYTHE;
case FEAT_WEAPON_PROFICIENCY_SHORTSPEAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHORTSPEAR;
case FEAT_WEAPON_PROFICIENCY_SHURIKEN: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SHURIKEN;
case FEAT_WEAPON_PROFICIENCY_SICKLE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SICKLE;
case FEAT_WEAPON_PROFICIENCY_SLING: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SLING;
case FEAT_WEAPON_PROFICIENCY_THROWING_AXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_THROWING_AXE;
case FEAT_WEAPON_PROFICIENCY_TRIDENT: return IP_CONST_FEAT_WEAPON_PROFICIENCY_TRIDENT;
case FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE;
case FEAT_WEAPON_PROFICIENCY_WHIP: return IP_CONST_FEAT_WEAPON_PROFICIENCY_WHIP;
case FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE;
case FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE;
case FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE;
case FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE;
case FEAT_WEAPON_PROFICIENCY_HEAVY_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
case FEAT_WEAPON_PROFICIENCY_LIGHT_PICK: return IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
case FEAT_WEAPON_PROFICIENCY_SAI: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAI;
case FEAT_WEAPON_PROFICIENCY_NUNCHAKU: return IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
case FEAT_WEAPON_PROFICIENCY_FALCHION: return IP_CONST_FEAT_WEAPON_PROFICIENCY_FALCHION;
case FEAT_WEAPON_PROFICIENCY_SAP: return IP_CONST_FEAT_WEAPON_PROFICIENCY_SAP;
case FEAT_WEAPON_PROFICIENCY_KATAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_KATAR;
case FEAT_WEAPON_PROFICIENCY_HEAVY_MACE: return IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_MACE;
case FEAT_WEAPON_PROFICIENCY_MAUL: return IP_CONST_FEAT_WEAPON_PROFICIENCY_MAUL;
case FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR: return IP_CONST_FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR;
case FEAT_WEAPON_PROFICIENCY_GOAD: return IP_CONST_FEAT_WEAPON_PROFICIENCY_GOAD;
case FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW: return IP_CONST_FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW;
//: Weapon Focus
case FEAT_WEAPON_FOCUS_BASTARD_SWORD: return IP_CONST_FEAT_WEAPON_FOCUS_BASTARD_SWORD;
case FEAT_WEAPON_FOCUS_BATTLE_AXE: return IP_CONST_FEAT_WEAPON_FOCUS_BATTLE_AXE;
case FEAT_WEAPON_FOCUS_CLUB: return IP_CONST_FEAT_WEAPON_FOCUS_CLUB;

View File

@@ -20,6 +20,8 @@ Add class to GetCasterLvl() in prc_inc_spells
Add Practiced Spellcaster feat to feat.2da and to PracticedSpellcasting() in prc_inc_castlvl
Run the assemble_spellbooks.bat file
Make the prc_* scripts in newspellbook. The filenames can be found under the spell entries for the class in spells.2da.
Update the fileends for all relevant files in inc_switch_setup
Delete prc_data in the \database\ folder before testing new spells.
Spont:
Make cls_spgn_*.2da
@@ -41,6 +43,8 @@ Add class to prc_amagsys_gain if(CheckMissingSpells(oPC, CLASS_TYPE_SORCERER, Mi
Add class to ExecuteScript("prc_amagsys_gain", oPC) list in EvalPRCFeats in prc_inc_function
Run the assemble_spellbooks.bat file
Make the prc_* scripts in newspellbook
Update the fileends for all relevant files in inc_switch_setup
Delete prc_data in the \database\ folder before testing new spells.
prc_classes.2da entry:
Label - name for the class
@@ -104,11 +108,10 @@ void ProcessPreparedSpellLevel(object oPC, int nClass, int nSpellLevel, int nLev
//#include "prc_effect_inc" //access via prc_inc_core
//#include "inc_lookups" //access via prc_inc_core
#include "prc_inc_core"
#include "inc_sp_gain_mem" //providing child access to prc_inc_core
//Must load in this order.
#include "inc_sp_gain_mem"
//#include "prc_inc_castlvl" //access via prc_inc_core
//#include "prc_inc_descrptr" //access via prc_inc_core
#include "inc_item_props"
//////////////////////////////////////////////////
/* Function definitions */
@@ -1618,6 +1621,3 @@ void DoCleanUp(int nMetamagic)
DeleteLocalInt(OBJECT_SELF, "NSB_SpellLevel");
DeleteLocalInt(OBJECT_SELF, "NSB_SpellbookID");
}
//:: Test Void
//:: void main (){}

View File

@@ -7,8 +7,11 @@
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
//:: Levels up an NPC according to variables set on NPC.
void LevelUpSummon(object oSummon, int iTargetLvl);
// Get the master of oAssociate.
object GetMasterNPC(object oAssociate=OBJECT_SELF);
object GetMasterNPC(object oAssociate0 = OBJECT_SELF);
// Returns the associate type of the specified creature.
// - Returns ASSOCIATE_TYPE_NONE if the creature is not the associate of anyone.
@@ -75,7 +78,6 @@ void DestroySummon(object oSummon)
DestroyObject(oSummon);
}
object CreateLocalNPC(object oMaster,int nAssociateType,string sTemplate,location loc,int Nth=1,string sTag="")
{
object oSummon=CreateObject(OBJECT_TYPE_CREATURE,sTemplate,loc,FALSE,sTag);
@@ -111,7 +113,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
SetLocalObject(oMaster, IntToString(nAssociateType)+"oHench"+IntToString(nCount), oSummon);
SetLocalInt(oSummon, "iAssocNth", nCount);
SetAssociateState(NW_ASC_HAVE_MASTER,TRUE,oSummon);
SetAssociateState(NW_ASC_HAVE_MASTER, TRUE, oSummon);
SetAssociateState(NW_ASC_DISTANCE_2_METERS);
SetAssociateState(NW_ASC_DISTANCE_4_METERS, FALSE);
SetAssociateState(NW_ASC_DISTANCE_6_METERS, FALSE);
@@ -122,6 +124,7 @@ object CreateLocalNextNPC(object oMaster,int nAssociateType,string sTemplate,loc
return oSummon;
}
object GetMasterNPC(object oAssociate=OBJECT_SELF)
{
object oMaster = GetLocalObject(oAssociate, "oMaster");
@@ -220,4 +223,173 @@ int GetAssociateHealMasterNPC()
return FALSE;
}
/**
* @brief Levels up a summoned creature based on its master's total casting level,
* while respecting configured HD limits and multiclass transition rules.
* Should only be called on the NPC onSpawn event.
*
* This function:
* - Retrieves the master<65>s total casting level and clamps it to the creature<72>s
* minimum and maximum HD (iMinHD, iMaxHD).
* - Repeatedly calls LevelUpHenchman() until the creature reaches that level,
* switching classes when the creature's stored "ClassXStart" thresholds are met.
*
* Local variables recognized on the summoned creature:
*
* | Variable Name | Purpose |
* |-----------------|-------------------------------------------------------------|
* | iMinHD | Minimum HD allowed |
* | iMaxHD | Maximum HD allowed |
* | Class2Start | Level to begin second class progression |
* | Class2 | Class type for second progression |
* | Class2Package | Package for second progression |
* | Class3Start | Level to begin third class progression |
* | Class3 | Class type for third progression |
* | Class3Package | Package for third progression |
* | Class4Start | Level to begin fourth class progression |
* | Class4 | Class type for fourth progression |
* | Class4Package | Package for fourth progression |
*
* Behavior notes:
* - Leveling continues until the creature reaches the master<65>s effective
* casting level (bounded by iMinHD/iMaxHD).
* - If LevelUpHenchman() returns 0, the creature shouts a failure message.
* - CLASS_TYPE_INVALID causes the creature to level in its current class.
*
* @param oCreature The summoned creature being leveled. Defaults to OBJECT_SELF.
*
* @see LevelUpHenchman
* @see GetLocalInt
* @see GetHitDice
*/
void LevelUpSummon(object oSummon, int iTargetLvl)
{
int nCurrentHD = GetHitDice(oSummon);
int iNewHD = nCurrentHD;
// Read multiclassing info from locals
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
int iClass2 = GetLocalInt(oSummon, "Class2");
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
int iClass3 = GetLocalInt(oSummon, "Class3");
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
int iClass4 = GetLocalInt(oSummon, "Class4");
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
int iClass; // current class to level
int iPackage; // package to use
// Main leveling loop
while (nCurrentHD < iTargetLvl && nCurrentHD > 0)
{
// Determine which class and package to use
if (iClass4Start != 0 && nCurrentHD >= iClass4Start)
{
iClass = iClass4;
iPackage = iClass4Package;
}
else if (iClass3Start != 0 && nCurrentHD >= iClass3Start)
{
iClass = iClass3;
iPackage = iClass3Package;
}
else if (iClass2Start != 0 && nCurrentHD >= iClass2Start)
{
iClass = iClass2;
iPackage = iClass2Package;
}
else
{
// Base class (first class in the sheet)
iClass = CLASS_TYPE_INVALID; // keeps current
iPackage = PACKAGE_INVALID;
}
// Level up one HD
iNewHD = LevelUpHenchman(oSummon, iClass, TRUE, iPackage);
if (iNewHD == 0)
{
SpeakString(GetName(oSummon) + " failed to level properly!", TALKVOLUME_SHOUT);
break;
}
nCurrentHD = iNewHD;
}
// Force the creature to rest to memorize spells
// PRCForceRest(oSummon);
}
/* void LevelUpSummon(object oSummon, int iTargetLvl)
{
//get the default hit dice of the summon
int nDefaultHD = GetHitDice(oSummon);
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: nDefaultHD = " +IntToString(nDefaultHD)+".");
if (DEBUG) DoDebug("inc_npc >> LevelUpSummon: iTargetLvl = " +IntToString(iTargetLvl)+".");
//get the multiclassing variables to see if we need to change classes from its base class
int iClass2Start = GetLocalInt(oSummon, "Class2Start");
int iClass2 = GetLocalInt(oSummon, "Class2");
int iClass2Package = GetLocalInt(oSummon, "Class2Package");
int iClass3Start = GetLocalInt(oSummon, "Class3Start");
int iClass3 = GetLocalInt(oSummon, "Class3");
int iClass3Package = GetLocalInt(oSummon, "Class3Package");
int iClass4Start = GetLocalInt(oSummon, "Class4Start");
int iClass4 = GetLocalInt(oSummon, "Class4");
int iClass4Package = GetLocalInt(oSummon, "Class4Package");
//check for zero cause thats an error
//if creatures are not leveling then best bet is they are not legal creatures
while( (nDefaultHD < iTargetLvl) && (nDefaultHD > 0) )
{
//check the multiclassing numbers to change classes
if( (iClass4Start != 0) && (nDefaultHD >= iClass4Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass4 ,TRUE, iClass4Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on fourth class", TALKVOLUME_SHOUT);
}
else if( (iClass3Start != 0) && (nDefaultHD >= iClass3Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass3 ,TRUE, iClass3Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on third class", TALKVOLUME_SHOUT);
}
else if( (iClass2Start != 0) && (nDefaultHD >= iClass2Start) )
{
//level up using the new class and Packageage
nDefaultHD = LevelUpHenchman(oSummon, iClass2 ,TRUE, iClass2Package);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed on second class", TALKVOLUME_SHOUT);
}
else
{
//just level up using the class it already has
nDefaultHD = LevelUpHenchman(oSummon, CLASS_TYPE_INVALID ,TRUE);
if(nDefaultHD == 0)
SpeakString(GetName(oSummon) + " Failed to level properly", TALKVOLUME_SHOUT);
}
}
}
*/
//:: void main() {}

View File

@@ -3433,6 +3433,7 @@ int PrimoGetWeaponSize(object oItem)
case BASE_ITEM_LIGHTFLAIL:
case BASE_ITEM_KATANA:
case BASE_ITEM_MAGICSTAFF:
case BASE_ITEM_CRAFTED_SCEPTER:
case BASE_ITEM_LONGSWORD:
case BASE_ITEM_TRIDENT:
case BASE_ITEM_MORNINGSTAR:

View File

@@ -30,6 +30,7 @@ int GetDamageFromConstant(int nIPConst);
void DoFrostRend(object oTarget, object oAttacker, object oWeapon);
#include "moi_inc_moifunc"
#include "prc_inc_combat"
//////////////////////////////////////////////////
/* Function defintions */

View File

@@ -17,9 +17,6 @@ Created: May 1, 2008
//:: Updated for .35 by Jaysyn 2023/03/11
//:: Test Void
//void main (){}
//:://////////////////////////////////////////////
//:: Constants
//:://////////////////////////////////////////////
@@ -63,6 +60,14 @@ string GetMetaMagicString(int nMetaMagic);
int GetMetaMagicFromFeat(int nFeat);
int GetMetaMagicOfCaster(object oPC = OBJECT_SELF);
string GetFileForClass(int nClass);
int GetSpellslotLevel(int nClass, object oPC);
int GetSpellKnownMaxCount(int nLevel, int nSpellLevel, int nClass, object oPC);
int GetSpellbookTypeForClass(int nClass);
#include "inc_pers_array"
#include "inc_2dacache"
// name of the new spellbook file (cls_spell_*)
string GetNSBDefinitionFileName(int nClass)
{

View File

@@ -44,6 +44,7 @@ void CreateSwitchNameArray();
#include "prc_inc_array" // Needs direct include instead of inc_utility
#include "prc_inc_switch"
#include "inc_2dacache"
//////////////////////////////////////////////////
/* Function definitions */
@@ -221,9 +222,9 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_cls_spcr_bard", 144);
SetPRCSwitch("PRC_FILE_END_cls_spcr_beguil", 142);
SetPRCSwitch("PRC_FILE_END_cls_spcr_blkgrd", 47);
SetPRCSwitch("PRC_FILE_END_cls_spcr_dnecro", 137);
SetPRCSwitch("PRC_FILE_END_cls_spcr_dnecro", 138);
SetPRCSwitch("PRC_FILE_END_cls_spcr_duskbl", 69);
SetPRCSwitch("PRC_FILE_END_cls_spcr_favsol", 290);
SetPRCSwitch("PRC_FILE_END_cls_spcr_favsol", 300);
SetPRCSwitch("PRC_FILE_END_cls_spcr_harper", 35);
SetPRCSwitch("PRC_FILE_END_cls_spcr_healer", 77);
SetPRCSwitch("PRC_FILE_END_cls_spcr_hexbl", 73);
@@ -251,9 +252,9 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_cls_spell_bard", 169);
SetPRCSwitch("PRC_FILE_END_cls_spell_beguil", 119);
SetPRCSwitch("PRC_FILE_END_cls_spell_blkgrd", 163);
SetPRCSwitch("PRC_FILE_END_cls_spell_dnecro", 134);
SetPRCSwitch("PRC_FILE_END_cls_spell_dnecro", 135);
SetPRCSwitch("PRC_FILE_END_cls_spell_duskbl", 84);
SetPRCSwitch("PRC_FILE_END_cls_spell_favsol", 363);
SetPRCSwitch("PRC_FILE_END_cls_spell_favsol", 373);
SetPRCSwitch("PRC_FILE_END_cls_spell_harper", 21);
SetPRCSwitch("PRC_FILE_END_cls_spell_healer", 271);
SetPRCSwitch("PRC_FILE_END_cls_spell_hexbl", 79);
@@ -267,7 +268,7 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_cls_spell_sod", 110);
SetPRCSwitch("PRC_FILE_END_cls_spell_sohei", 131);
SetPRCSwitch("PRC_FILE_END_cls_spell_sol", 114);
SetPRCSwitch("PRC_FILE_END_cls_spell_sorc", 541);
SetPRCSwitch("PRC_FILE_END_cls_spell_sorc", 550);
SetPRCSwitch("PRC_FILE_END_cls_spell_suel", 160);
SetPRCSwitch("PRC_FILE_END_cls_spell_templ", 95);
SetPRCSwitch("PRC_FILE_END_cls_spell_tfshad", 70);
@@ -335,7 +336,7 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_craft_golem", 40);
SetPRCSwitch("PRC_FILE_END_craft_ring", 41);
SetPRCSwitch("PRC_FILE_END_craft_weapon", 46);
SetPRCSwitch("PRC_FILE_END_craft_wondrous", 115);
SetPRCSwitch("PRC_FILE_END_craft_wondrous", 131);
SetPRCSwitch("PRC_FILE_END_creaturesize", 5);
SetPRCSwitch("PRC_FILE_END_creaturespeed", 8);
SetPRCSwitch("PRC_FILE_END_crtemplates", 10);
@@ -355,7 +356,7 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_des_crft_poison", 100);
SetPRCSwitch("PRC_FILE_END_des_crft_props", 27);
SetPRCSwitch("PRC_FILE_END_des_crft_scroll", 3999);
SetPRCSwitch("PRC_FILE_END_des_crft_spells", 19348);
SetPRCSwitch("PRC_FILE_END_des_crft_spells", 20000);
SetPRCSwitch("PRC_FILE_END_des_crft_weapon", 29);
SetPRCSwitch("PRC_FILE_END_des_cutconvdur", 26);
SetPRCSwitch("PRC_FILE_END_des_feat2item", 1000);
@@ -408,7 +409,7 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_iprp_ammocost", 15);
SetPRCSwitch("PRC_FILE_END_iprp_ammotype", 2);
SetPRCSwitch("PRC_FILE_END_iprp_amount", 4);
SetPRCSwitch("PRC_FILE_END_iprp_aoe", 7);
SetPRCSwitch("PRC_FILE_END_iprp_aoe", 8);
SetPRCSwitch("PRC_FILE_END_iprp_arcspell", 19);
SetPRCSwitch("PRC_FILE_END_iprp_base1", -1);
SetPRCSwitch("PRC_FILE_END_iprp_bladecost", 5);
@@ -423,15 +424,15 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_iprp_damvulcost", 7);
SetPRCSwitch("PRC_FILE_END_iprp_decvalue1", 9);
SetPRCSwitch("PRC_FILE_END_iprp_decvalue2", 9);
SetPRCSwitch("PRC_FILE_END_iprp_feats", 24819);
SetPRCSwitch("PRC_FILE_END_iprp_feats", 26999);
SetPRCSwitch("PRC_FILE_END_iprp_immuncost", 7);
SetPRCSwitch("PRC_FILE_END_iprp_immunity", 9);
SetPRCSwitch("PRC_FILE_END_iprp_incvalue1", 9);
SetPRCSwitch("PRC_FILE_END_iprp_incvalue2", 9);
SetPRCSwitch("PRC_FILE_END_iprp_kitcost", 50);
SetPRCSwitch("PRC_FILE_END_iprp_lightcost", 4);
SetPRCSwitch("PRC_FILE_END_iprp_matcost", 77);
SetPRCSwitch("PRC_FILE_END_iprp_material", 77);
SetPRCSwitch("PRC_FILE_END_iprp_matcost", 145);
SetPRCSwitch("PRC_FILE_END_iprp_material", 145);
SetPRCSwitch("PRC_FILE_END_iprp_maxpp", 8);
SetPRCSwitch("PRC_FILE_END_iprp_meleecost", 20);
SetPRCSwitch("PRC_FILE_END_iprp_metamagic", 6);
@@ -458,11 +459,11 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_iprp_soakcost", 50);
SetPRCSwitch("PRC_FILE_END_iprp_speed_dec", 9);
SetPRCSwitch("PRC_FILE_END_iprp_speed_enh", 9);
SetPRCSwitch("PRC_FILE_END_iprp_spellcost", 243);
SetPRCSwitch("PRC_FILE_END_iprp_spellcost", 298);
SetPRCSwitch("PRC_FILE_END_iprp_spellcstr", 42);
SetPRCSwitch("PRC_FILE_END_iprp_spelllvcost", 9);
SetPRCSwitch("PRC_FILE_END_iprp_spelllvlimm", 9);
SetPRCSwitch("PRC_FILE_END_iprp_spells", 1456);
SetPRCSwitch("PRC_FILE_END_iprp_spells", 1552);
SetPRCSwitch("PRC_FILE_END_iprp_spellshl", 7);
SetPRCSwitch("PRC_FILE_END_iprp_srcost", 99);
SetPRCSwitch("PRC_FILE_END_iprp_staminacost", -1);
@@ -492,9 +493,9 @@ void SetDefaultFileEnds()
SetPRCSwitch("PRC_FILE_END_itmwizwands", 38);
SetPRCSwitch("PRC_FILE_END_keymap", 70);
SetPRCSwitch("PRC_FILE_END_lightcolor", 32);
SetPRCSwitch("PRC_FILE_END_loadhints", 88);
SetPRCSwitch("PRC_FILE_END_loadhints", 101);
SetPRCSwitch("PRC_FILE_END_loadscreens", 259);
SetPRCSwitch("PRC_FILE_END_masterfeats", 113);
SetPRCSwitch("PRC_FILE_END_masterfeats", 125);
SetPRCSwitch("PRC_FILE_END_materialcomp", 200);
SetPRCSwitch("PRC_FILE_END_metamagic", 6);
SetPRCSwitch("PRC_FILE_END_namefilter", 3);
@@ -866,6 +867,31 @@ void CreateSwitchNameArray()
//if you add more switches, add them to this list
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DEBUG);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_COMBAT_DEBUG);
//craft
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
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"), 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);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CREATE_INFUSION_OPTIONAL_HERBS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_SCEPTER_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_MATERIAL_COMPONENTS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_COMPONENTS_SHOP);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_TRUESEEING);
@@ -876,6 +902,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_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS);
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);
@@ -994,7 +1022,7 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_COUNT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_USES_PER_WEAPON_POISON_DIE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_POISON_ALLOW_CLEAN_IN_EQUIP);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_POISON_USE_INGREDIENTS);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_USE_2DA);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_PNP_RAPID_METABOLISM);
@@ -1058,31 +1086,31 @@ void CreateSwitchNameArray()
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_UNICORN_SQL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_LETOSCRIPT_GETNEWESTBIC);
//craft
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_DISABLE_CRAFT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MULTIPLIER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MAX);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_TIMER_MIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_BREW_POTION_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_SCRIBE_SCROLL_CASTER_LEVEL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_CRAFT_WAND_CASTER_LEVEL);
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"), 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
//shifter
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_USECR);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_HUGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_LARGE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_MEDIUM);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_SMALL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_S_TINY);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OUTSIDER);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ELEMENTAL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_CONSTRUCT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_UNDEAD);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_DRAGON);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ABERRATION);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_OOZE);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MAGICALBEAST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_GIANT);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_VERMIN);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_BEAST);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_ANIMAL);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_MONSTROUSHUMANOID);
array_set_string(oWP, "Switch_Name", array_get_size(oWP, "Switch_Name"), PNP_SHFT_F_HUMANOID);
//general

View File

@@ -1,4 +1,5 @@
#include "prc_inc_clsfunc"
#include "prc_inc_sp_tch"
int GetBlastDamageDices(object oInvoker, int nInvokerLevel)
{

View File

@@ -135,6 +135,9 @@ int GetHasInvocation(int nInvocation, object oCreature = OBJECT_SELF);
/* Includes */
//////////////////////////////////////////////////
int GetPrimaryInvocationClass(object oCreature = OBJECT_SELF);
int GetInvocationPRCLevels(object oCaster);
#include "inc_item_props"
#include "prc_x2_itemprop"
#include "inc_lookups"

View File

@@ -123,7 +123,7 @@ void DeleteLocalInvocation(object oObject, string sName);
/* Includes */
//////////////////////////////////////////////////
//#include "inv_inc_invfunc" //Access in parent
#include "inv_inc_invfunc" //Access in parent
#include "prc_spellf_inc"
//////////////////////////////////////////////////

View File

@@ -77,6 +77,15 @@ int PreInvocationCastCode()
int nContinue = !ExecuteScriptAndReturnInt("prespellcode", oInvoker);
//---------------------------------------------------------------------------
// Block forsakers from using invocations
//---------------------------------------------------------------------------
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oInvoker) > 0)
{
SendMessageToPC(oInvoker, "Forsakers cannot use invocations.");
return FALSE;
}
//---------------------------------------------------------------------------
// Break any spell require maintaining concentration
//---------------------------------------------------------------------------
@@ -168,3 +177,4 @@ int PreInvocationCastCode()
return nContinue;
}
//:: void main (){}

View File

@@ -1170,7 +1170,10 @@ int GetMaxEssentiaCapacityFeat(object oMeldshaper)
{
int nMax = 1; // Always can invest one
int nHD = GetHitDice(oMeldshaper);
if (nHD >= 31) nMax = 5;
if (nHD >= 61) nMax = 8;
else if (nHD >= 51) nMax = 7;
else if (nHD >= 41) nMax = 6;
else if (nHD >= 31) nMax = 5;
else if (nHD >= 18) nMax = 4;
else if (nHD >= 12) nMax = 3;
else if (nHD >= 6) nMax = 2;

View File

@@ -10,9 +10,586 @@ void ShifterCheck(object oPC);
#include "pnp_shft_main"
#include "prc_inc_shifting"
//::////////////////Begin Werewolf//////////////////
const string PRC_PNP_SHIFTING = "PRC_Shift";
////////////////Begin Werewolf//////////////////
void LycanthropePoly(object oPC, int nPoly)
{
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
if (GetIsObjectValid(oShield))
{
int nShieldType = GetBaseItemType(oShield);
if (nShieldType != BASE_ITEM_LARGESHIELD &&
nShieldType != BASE_ITEM_SMALLSHIELD &&
nShieldType != BASE_ITEM_TOWERSHIELD)
{
oShield = OBJECT_INVALID;
}
}
ShifterCheck(oPC);
ClearAllActions();
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
//:: Weapon & Armor merge block
object oMergeWeaponSource = OBJECT_INVALID;
object oMergeArmorSource = OBJECT_INVALID;
//:: Determine Weapon Merge Source
if (bWeapon)
{
if (bMonkGloves)
{
if (GetIsObjectValid(oGlovesOld))
oMergeWeaponSource = oGlovesOld;
}
else
{
//:: Always attempt to merge melee weapon to creature weapon
oMergeWeaponSource = oWeaponOld; // even if empty, ensures proper state
}
}
else
{
//:: Weapon not requested, but arms-slot allowed monk gloves can merge via armor branch
if (bMonkGloves && bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
oMergeWeaponSource = oGlovesOld;
}
//:: Determine Armor Merge Source
if (bArmor && GetIsObjectValid(oArmorNew))
{
if (!bMonkGloves)
{
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
oMergeArmorSource = oGlovesOld;
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
}
else
{
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
}
}
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
{
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
}
//:: Apply Weapon Merge
if (GetIsObjectValid(oMergeWeaponSource) || bWeapon)
{
//:: Always attempt to merge weapon properties even if source is OBJECT_INVALID
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewBite, TRUE);
}
//:: Apply Armor Merge
if (GetIsObjectValid(oMergeArmorSource))
{
if (GetIsObjectValid(oArmorNew)) IPWildShapeCopyItemProperties(oMergeArmorSource, oArmorNew);
}
//:: General item merge block
if (bItems && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
}
}
//::////////////////End Werewolf//////////////////
/* //::////////////////Begin Werewolf//////////////////
const string PRC_PNP_SHIFTING = "PRC_Shift";
void LycanthropePoly(object oPC, int nPoly)
{
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
if (GetIsObjectValid(oShield))
{
int nShieldType = GetBaseItemType(oShield);
if (nShieldType != BASE_ITEM_LARGESHIELD &&
nShieldType != BASE_ITEM_SMALLSHIELD &&
nShieldType != BASE_ITEM_TOWERSHIELD)
{
oShield = OBJECT_INVALID;
}
}
ShifterCheck(oPC);
ClearAllActions();
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
//:: Weapon & Armor merge block
object oMergeWeaponSource = OBJECT_INVALID;
object oMergeArmorSource = OBJECT_INVALID;
// ---- Determine Weapon Merge Source ----
if (bWeapon)
{
if (bMonkGloves)
{
if (GetIsObjectValid(oGlovesOld))
oMergeWeaponSource = oGlovesOld;
}
else
{
if (GetIsObjectValid(oWeaponOld))
oMergeWeaponSource = oWeaponOld;
}
}
else
{
if (bMonkGloves && bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
oMergeWeaponSource = oGlovesOld;
}
// ---- Determine Armor Merge Source ----
if (bArmor && GetIsObjectValid(oArmorNew))
{
if (!bMonkGloves)
{
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
oMergeArmorSource = oGlovesOld;
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
}
else
{
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
}
}
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
{
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
}
// ---- Apply Weapon Merge ----
if (GetIsObjectValid(oMergeWeaponSource))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeWeaponSource, oWeaponNewBite, TRUE);
}
// ---- Apply Armor Merge ----
if (GetIsObjectValid(oMergeArmorSource))
{
if (GetIsObjectValid(oArmorNew)) IPWildShapeCopyItemProperties(oMergeArmorSource, oArmorNew);
}
//:: General item merge block
if (bItems && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
}
}
//::////////////////End Werewolf////////////////// */
/* //::////////////////Begin Werewolf//////////////////
const string PRC_PNP_SHIFTING = "PRC_Shift";
void LycanthropePoly(object oPC, int nPoly)
{
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
if (GetIsObjectValid(oShield))
{
int nShieldType = GetBaseItemType(oShield);
if (nShieldType != BASE_ITEM_LARGESHIELD &&
nShieldType != BASE_ITEM_SMALLSHIELD &&
nShieldType != BASE_ITEM_TOWERSHIELD)
{
oShield = OBJECT_INVALID;
}
}
ShifterCheck(oPC);
ClearAllActions();
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
//:: Weapon merge block
if (bWeapon)
{
object oMergeSource = OBJECT_INVALID;
// Priority: monk gloves override if worn and arms-slot not allowed
if (bMonkGloves && !bArmsSlotAllowed)
{
if (GetIsObjectValid(oGlovesOld))
oMergeSource = oGlovesOld;
}
else
{
// Otherwise use main-hand weapon if it exists
if (GetIsObjectValid(oWeaponOld))
oMergeSource = oWeaponOld;
}
// Apply merge to creature weapons if we have a source
if (GetIsObjectValid(oMergeSource))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oMergeSource, oWeaponNewBite, TRUE);
}
}
//:: Armor merge block
if (bArmor && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
// Arms-slot allowed -> apply gloves & bracers to creature weapons
if (bArmsSlotAllowed && GetIsObjectValid(oGlovesOld))
{
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves/bracers to creature weapons from armor branch.");
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
}
}
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
{
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
}
//:: General item merge block
if (bItems && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
}
}
//::////////////////End Werewolf//////////////////
*/
/* //::////////////////Begin Werewolf//////////////////
const string PRC_PNP_SHIFTING = "PRC_Shift";
void LycanthropePoly(object oPC, int nPoly)
{
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
if (GetIsObjectValid(oShield))
{
int nShieldType = GetBaseItemType(oShield);
if (nShieldType != BASE_ITEM_LARGESHIELD &&
nShieldType != BASE_ITEM_SMALLSHIELD &&
nShieldType != BASE_ITEM_TOWERSHIELD)
{
oShield = OBJECT_INVALID;
}
}
ShifterCheck(oPC);
ClearAllActions();
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
//:: Weapon merge block
//:: Only blocked if monk gloves are equipped AND arms-slot merge is NOT allowed
if (bWeapon && !bMonkGloves)
{
if (GetIsObjectValid(oWeaponOld))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewBite, TRUE);
}
}
else if (bWeapon && bMonkGloves && !bArmsSlotAllowed)
{
if (DEBUG) DoDebug("LycanthropePoly: Monk gloves overriding weapon merge (arms slot NOT allowed).");
if (GetIsObjectValid(oGlovesOld))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
}
}
//:: Armor merge block
//:: Apply armor and gloves (if arms-slot allowed)
if (bArmor && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
if (bArmsSlotAllowed && bMonkGloves && GetIsObjectValid(oGlovesOld))
{
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves to creature weapons from armor branch.");
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
}
}
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
{
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
}
//:: General item merge block
if (bItems && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
}
}
//::////////////////End Werewolf////////////////// */
/* //::////////////////Begin Werewolf//////////////////
const string PRC_PNP_SHIFTING = "PRC_Shift";
void LycanthropePoly(object oPC, int nPoly)
{
effect eVis = EffectVisualEffect(VFX_IMP_POLYMORPH);
effect ePoly = SupernaturalEffect(EffectPolymorph(nPoly));
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
int bArmsSlotAllowed = GetPRCSwitch(PRC_WILDSHAPE_ALLOWS_ARMS_SLOT);
int bWeapon = StringToInt(Get2DACache("polymorph","MergeW",nPoly)) == 1;
int bArmor = StringToInt(Get2DACache("polymorph","MergeA",nPoly)) == 1;
int bItems = StringToInt(Get2DACache("polymorph","MergeI",nPoly)) == 1;
object oWeaponOld = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
object oArmorOld = GetItemInSlot(INVENTORY_SLOT_CHEST,oPC);
object oRing1Old = GetItemInSlot(INVENTORY_SLOT_LEFTRING,oPC);
object oRing2Old = GetItemInSlot(INVENTORY_SLOT_RIGHTRING,oPC);
object oAmuletOld = GetItemInSlot(INVENTORY_SLOT_NECK,oPC);
object oCloakOld = GetItemInSlot(INVENTORY_SLOT_CLOAK,oPC);
object oBootsOld = GetItemInSlot(INVENTORY_SLOT_BOOTS,oPC);
object oBeltOld = GetItemInSlot(INVENTORY_SLOT_BELT,oPC);
object oHelmetOld = GetItemInSlot(INVENTORY_SLOT_HEAD,oPC);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND,oPC);
object oGlovesOld = GetItemInSlot(INVENTORY_SLOT_ARMS,oPC);
if (GetIsObjectValid(oShield))
{
int nShieldType = GetBaseItemType(oShield);
if (nShieldType != BASE_ITEM_LARGESHIELD &&
nShieldType != BASE_ITEM_SMALLSHIELD &&
nShieldType != BASE_ITEM_TOWERSHIELD)
{
oShield = OBJECT_INVALID;
}
}
ShifterCheck(oPC);
ClearAllActions();
ApplyEffectToObject(DURATION_TYPE_INSTANT, eVis, oPC);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, ePoly, oPC);
object oWeaponNewRight = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R,oPC);
object oWeaponNewLeft = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L,oPC);
object oWeaponNewBite = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B,oPC);
object oArmorNew = GetItemInSlot(INVENTORY_SLOT_CARMOUR,oPC);
//:: Weapon merge block
//:: Only blocked if monk gloves are equipped AND arms-slot merge is NOT allowed
if (bWeapon && !bMonkGloves)
{
if (GetIsObjectValid(oWeaponOld))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oWeaponOld, oWeaponNewBite, TRUE);
}
}
else if (bWeapon && bMonkGloves && !bArmsSlotAllowed)
{
if (DEBUG) DoDebug("LycanthropePoly: Monk gloves overriding weapon merge (arms slot NOT allowed).");
if (GetIsObjectValid(oGlovesOld))
{
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
}
}
//:: Armor merge block
//:: Apply armor and gloves (if arms-slot allowed)
if (bArmor && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oShield)) IPWildShapeCopyItemProperties(oShield, oArmorNew);
if (GetIsObjectValid(oHelmetOld)) IPWildShapeCopyItemProperties(oHelmetOld, oArmorNew);
if (GetIsObjectValid(oArmorOld)) IPWildShapeCopyItemProperties(oArmorOld, oArmorNew);
if (bArmsSlotAllowed && bMonkGloves && GetIsObjectValid(oGlovesOld))
{
if (DEBUG) DoDebug("LycanthropePoly: Arms-slot allowed -> applying gloves to creature weapons from armor branch.");
if (GetIsObjectValid(oWeaponNewLeft)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewLeft, TRUE);
if (GetIsObjectValid(oWeaponNewRight)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewRight, TRUE);
if (GetIsObjectValid(oWeaponNewBite)) IPWildShapeCopyItemProperties(oGlovesOld, oWeaponNewBite, TRUE);
}
}
else if (bArmor && !GetIsObjectValid(oArmorNew) && DEBUG)
{
DoDebug("LycanthropePoly: MergeA set, but oArmorNew invalid.");
}
//:: General item merge block
if (bItems && GetIsObjectValid(oArmorNew))
{
if (GetIsObjectValid(oRing1Old)) IPWildShapeCopyItemProperties(oRing1Old, oArmorNew);
if (GetIsObjectValid(oRing2Old)) IPWildShapeCopyItemProperties(oRing2Old, oArmorNew);
if (GetIsObjectValid(oAmuletOld)) IPWildShapeCopyItemProperties(oAmuletOld, oArmorNew);
if (GetIsObjectValid(oCloakOld)) IPWildShapeCopyItemProperties(oCloakOld, oArmorNew);
if (GetIsObjectValid(oBootsOld)) IPWildShapeCopyItemProperties(oBootsOld, oArmorNew);
if (GetIsObjectValid(oBeltOld)) IPWildShapeCopyItemProperties(oBeltOld, oArmorNew);
}
}
//::////////////////End Werewolf////////////////// */
/* ////////////////Begin Werewolf//////////////////
void LycanthropePoly(object oPC, int nPoly)
{
@@ -84,7 +661,7 @@ void LycanthropePoly(object oPC, int nPoly)
}
////////////////End Werewolf//////////////////
////////////////End Werewolf////////////////// */
void ShifterCheck(object oPC)
{
@@ -246,4 +823,6 @@ void DoTail(object oPC, int nTailType)
SetCreatureTailType(nTailType, oPC);
//override any stored default appearance
SetPersistantLocalInt(oPC, "AppearanceStoredTail", nTailType);
}
}
//::void main (){}

View File

@@ -54,11 +54,11 @@ int SPGetPenetrAOE(object oCaster = OBJECT_SELF, int nCasterLvl = 0);
/* Includes */
//////////////////////////////////////////////////
//#include "prc_inc_spells"
#include "prc_inc_spells"
//#include "prc_alterations"
//#include "prcsp_archmaginc"
//#include "prc_inc_racial"
#include "inc_2dacache"
//////////////////////////////////////////////////
/* Function definitions */

View File

@@ -444,6 +444,7 @@ int Get2DALineFromItemprop(string sFile, itemproperty ip, object oItem)
}
break;
}
case ITEM_PROPERTY_ECHOBLADE: return 46; break;
}
}
return -1;
@@ -1529,7 +1530,12 @@ void ApplyItemProps(object oItem, string sFile, int nLine)
break; //no more itemprops, no gaps, assuming no errors
}
if(sFile != "craft_weapon" && sFile != "craft_armour")
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
{
SetName(oItem, GetStringByStrRef(StringToInt(Get2DACache(sFile, "Name", nLine))));
string sDescRef = Get2DACache(sFile, "CraftedDescription", nLine);
if(sDescRef != "")
SetDescription(oItem, GetStringByStrRef(StringToInt(sDescRef)));
}
}
//Partly ripped off the lexicon :P
@@ -1620,7 +1626,8 @@ string GetCrafting2DA(object oItem)
(nBase == BASE_ITEM_BOOTS) ||
(nBase == BASE_ITEM_GLOVES) ||
(nBase == BASE_ITEM_BRACER) ||
(nBase == BASE_ITEM_CLOAK))
(nBase == BASE_ITEM_CLOAK) ||
(nBase == BASE_ITEM_CRAFTED_VIAL))
)
return "craft_wondrous";
@@ -1657,19 +1664,28 @@ int GetCraftingFeat(object oItem)
if(nBase == BASE_ITEM_RING) return FEAT_FORGE_RING;
//routing bioware feats through this convo
if((nBase == BASE_ITEM_CRAFTED_SCEPTER) ||
(nBase == BASE_ITEM_CRAFTED_SCEPTER)
)
return FEAT_CRAFT_SCEPTER;
if((nBase == BASE_ITEM_MAGICROD) ||
(nBase == BASE_ITEM_CRAFTED_ROD)
)
return FEAT_CRAFT_ROD;
if((nBase == BASE_ITEM_MAGICSTAFF) ||
(nBase == BASE_ITEM_CRAFTED_STAFF)
)
return FEAT_CRAFT_STAFF;
if((nBase == BASE_ITEM_MAGICWAND) ||
(nBase == BASE_ITEM_BLANK_WAND)
)
return FEAT_CRAFT_WAND;
if(nBase == BASE_ITEM_BLANK_POTION) return FEAT_BREW_POTION;
if(nBase == BASE_ITEM_BLANK_SCROLL) return FEAT_SCRIBE_SCROLL;
if(((nBase == BASE_ITEM_HELMET) ||
@@ -1678,7 +1694,8 @@ int GetCraftingFeat(object oItem)
(nBase == BASE_ITEM_BOOTS) ||
(nBase == BASE_ITEM_GLOVES) ||
(nBase == BASE_ITEM_BRACER) ||
(nBase == BASE_ITEM_CLOAK))
(nBase == BASE_ITEM_CLOAK) ||
(nBase == BASE_ITEM_CRAFTED_VIAL))
)
return FEAT_CRAFT_WONDROUS;

View File

@@ -75,10 +75,11 @@ 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
* @return the Gaze Immunity effect
*/
effect EffectGazeImmune();
@@ -89,6 +90,9 @@ effect EffectGazeImmune();
*/
effect EffectDazzle();
//ebonfowl: adding this function to check if a target is already shaken
int GetIsShaken(object oTarget);
/**
* Shaken effect: -2 to attack, all skills and saving throws
*
@@ -177,14 +181,11 @@ effect EffectAbilityBasedSkillIncrease(int iAbility, int iIncrease = 1);
*/
effect EffectAbilityBasedSkillDecrease(int iAbility, int iDecrease = 1);
//ebonfowl: adding this function to check if a target is already shaken
int GetIsShaken(object oTarget);
//////////////////////////////////////////////////
/* Include section */
//////////////////////////////////////////////////
#include "prc_inc_castlvl" // get prc_racial_const, prc_inc_nwscript, prc_inc_newip
#include "inc_epicspelldef"
//////////////////////////////////////////////////
/* Internal functions */
@@ -268,6 +269,8 @@ object GetObjectToApplyNewEffect(string sTag, object oPC, int nStripEffects = TR
SetCreatureAppearanceType(oWP, APPEARANCE_TYPE_INVISIBLE_HUMAN_MALE);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectVisualEffect(VFX_DUR_CUTSCENE_INVISIBILITY), oWP);
ApplyEffectToObject(DURATION_TYPE_PERMANENT, EffectCutsceneGhost(), oWP);
AssignCommand(oWP, ActionUseSkill(SKILL_HIDE, oWP));
}
//remove previous effects
if(nStripEffects)
@@ -746,7 +749,6 @@ effect EffectImmunityMiscAll()
//:: Immunity to all gaze attacks
effect EffectGazeImmune()
{
effect eBlank;
effect eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CHARM);
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_CONFUSION);
@@ -768,6 +770,23 @@ effect EffectGazeImmune()
return eReturn;
}
//:: Immunity to all perification attacks
effect EffectPetrificationImmune()
{
effect eReturn = EffectSpellImmunity(SPELLABILITY_TOUCH_PETRIFY);
eReturn = EffectSpellImmunity(SPELLABILITY_BREATH_PETRIFY);
eReturn = EffectSpellImmunity(SPELL_FLESH_TO_STONE);
eReturn = EffectSpellImmunity(SPELL_STONEHOLD);
eReturn = EffectSpellImmunity(SPELL_EPIC_A_STONE);
eReturn = EffectSpellImmunity(POWER_CRYSTALLIZE);
eReturn = EffectSpellImmunity(MELD_BASILISK_MASK);
eReturn = EffectSpellImmunity(SPELLABILITY_GAZE_PETRIFY);
eReturn = TagEffect(eReturn, "PRCPetrificationImmune");
return eReturn;
}
int GetIsShaken(object oTarget)
{
effect eEffect = GetFirstEffect(oTarget);
@@ -785,5 +804,11 @@ int GetIsShaken(object oTarget)
return FALSE;
}
// Forward declarations for size change effects
// Implementations are in prc_inc_size
effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges);
void DelayedSetVisualTransform(int nExpectedGeneration, object oTarget, int nTransform, float fValue);
void DelaySetVisualTransform(float fDelay, object oTarget, string sGenerationName, int nTransform, float fValue);
//:: Test void
//:: void main() {}
//::void main() {}

View File

@@ -4,6 +4,11 @@
//:: PRC Options Conversation
const int FEAT_OPTIONS_CONVERSATION = 2285;
//;; Builder Feats
const int FEAT_ARCHETYPAL_FORM = 2918;
const int FEAT_INTRINSIC_ARMOR = 25990;
const int FEAT_INTRINSIC_WEAPON = 25991;
//:: Missing Bioware Feats
const int FEAT_EPIC_PLANAR_TURNING = 854;
@@ -219,6 +224,9 @@ const int FEAT_MAGICAL_ARTISAN_CREATE_INFUSION = 25961;
const int FEAT_PLANT_DEFIANCE = 25992;
const int FEAT_PLANT_CONTROL = 25993;
//:: Lost Empires of Faerun feats
const int FEAT_CRAFT_SCEPTER = 25962;
const int FEAT_MAGICAL_ARTISAN_CRAFT_SCEPTER = 25963;
//:: Racial Feats
const int FEAT_WEMIC_JUMP_8 = 4518;
@@ -1314,6 +1322,7 @@ const int FEAT_SOMATIC_WEAPONRY = 5186;
// Forgotten Realms Campaign Setting
const int FEAT_INSCRIBE_RUNE = 2462;
const int EPIC_FEAT_INSCRIBE_EPIC_RUNES = 2549;
// Miniature Handbook
const int FEAT_SHIELDMATE = 3258;
@@ -3726,6 +3735,9 @@ const int FEAT_EPIC_ARTIFICER = 4072;
//////////////// END INFUSIONS /////////////////
//////////////////////////////////////////////////*/
//:: Monk
const int FEAT_MONK_ABUNDANT_STEP = 2351;
//Justice of Weald and Woe
const int FEAT_LUCKY_SHOT = 24021;
@@ -6275,6 +6287,7 @@ const int FEAT_DSONG_SPELLCASTING_NONE = 19592;
const int FEAT_OLLAM_SPELLCASTING_NONE = 19593;
//:: PRC8 Hidden Talent Feats
const int FEAT_HIDDEN_TALENT = 25900;
const int FEAT_HIDDEN_TALENT_BIOFEEDBACK = 25901;
const int FEAT_HIDDEN_TALENT_BITE_WOLF = 25902;
const int FEAT_HIDDEN_TALENT_BOLT = 25903;

View File

@@ -400,5 +400,4 @@ int GetBestAvailableSpell(object oTarget)
if(nBestSpell == 99999) nBestSpell = GetBestL1Spell(oTarget, nBestSpell);
if(nBestSpell == 99999) nBestSpell = GetBestL0Spell(oTarget, nBestSpell);
return nBestSpell;
}
}

View File

@@ -124,6 +124,8 @@ void ApplyBreath(struct breath BreathUsed, location lTargetArea, int bLinger = F
//////////////////////////////////////////////////
#include "prc_alterations"
#include "prcsp_archmaginc"
#include "prc_inc_spells"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -3859,7 +3859,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_ARCHIVIST, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_ARCHIVIST, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_ARCHIVIST, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -4193,7 +4196,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_CLERIC, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_CLERIC, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_CLERIC, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -4309,9 +4315,12 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_DRUID, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_DRUID, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_DRUID, oCaster))
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_DRUID, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_BFZ, oCaster + 1) / 2 */
// if(GetHasFeat(FEAT_BRIMSTONE_SPEAKER_SPELLCASTING_DRUID, oCaster))
@@ -4421,7 +4430,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_FAVOURED_SOUL, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_FAVOURED_SOUL, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_FAVOURED_SOUL, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -4534,7 +4546,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
/* if(GetHasFeat(FEAT_BFZ_SPELLCASTING_HEALER, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2; */
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2; */
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_HEALER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BRIMSTONE_SPEAKER_SPELLCASTING_HEALER, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BRIMSTONE_SPEAKER, oCaster) + 1) / 2;
@@ -4641,7 +4656,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_JUSTICEWW, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_JOWAW, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_JUSTICEWW, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -4742,6 +4760,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_KNIGHT_CHALICE, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_KOTC, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_KNIGHT_CHALICE, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
@@ -4849,6 +4870,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_KOTMC, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_KNIGHT_MIDDLECIRCLE, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
@@ -4962,6 +4986,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_NENTYAR_HUNTER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_NENTYAR_HUNTER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_NENTYAR_HUNTER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster); */
@@ -5164,6 +5191,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_PALADIN, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_PALADIN, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_PALADIN, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
@@ -5272,7 +5302,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_RANGER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_RANGER, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_RANGER, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -5385,7 +5418,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_OASHAMAN, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_OASHAMAN, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_OASHAMAN, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -5599,7 +5635,10 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_SOHEI, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_SOHEI, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
if(GetHasFeat(FEAT_BFZ_SPELLCASTING_SOHEI, oCaster))
nDivine += (GetLevelByClass(CLASS_TYPE_BFZ, oCaster) + 1) / 2;
@@ -5704,6 +5743,9 @@ int GetDivinePRCLevels(object oCaster, int nCastingClass = CLASS_TYPE_INVALID)
if(GetHasFeat(FEAT_SWIFT_WING_SPELLCASTING_SOL, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_SWIFT_WING, oCaster);
if(GetHasFeat(FEAT_VERDANT_LORD_SPELLCASTING_SOL, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_VERDANT_LORD, oCaster);
/* if(GetHasFeat(FEAT_TENEBROUS_APOSTATE_SPELLCASTING_SOL, oCaster))
nDivine += GetLevelByClass(CLASS_TYPE_TENEBROUS_APOSTATE, oCaster);

View File

@@ -16,6 +16,7 @@ Command summary:
*/
#include "prc_inc_chat"
#include "inc_persist_loca"
const string CMD_POWER_ATTACK = "pow-erattack";

View File

@@ -380,6 +380,7 @@ int Vile_Feat(int iTypeWeap)
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_VILE_MARTIAL_BASTARDSWORD);
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_VILE_MARTIAL_BATTLEAXE);
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_VILE_MARTIAL_CLUB);
case BASE_ITEM_CRAFTED_SCEPTER: return GetHasFeat(FEAT_VILE_MARTIAL_CLUB);
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_VILE_MARTIAL_DAGGER);
case BASE_ITEM_DART: return GetHasFeat(FEAT_VILE_MARTIAL_DART);
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_VILE_MARTIAL_DIREMACE);
@@ -426,7 +427,7 @@ int Vile_Feat(int iTypeWeap)
GetHasFeat(FEAT_VILE_MARTIAL_RAPIER) ||
GetHasFeat(FEAT_VILE_MARTIAL_ELVEN_THINBLADE));
case BASE_ITEM_ELVEN_COURTBLADE: return GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD ||
case BASE_ITEM_ELVEN_COURTBLADE: return (GetHasFeat(FEAT_VILE_MARTIAL_GREATSWORD) ||
GetHasFeat(FEAT_VILE_MARTIAL_ELVEN_COURTBLADE));
case BASE_ITEM_DOUBLE_SCIMITAR: return GetHasFeat(FEAT_VILE_MARTIAL_DBL_SCIMITAR);
@@ -461,6 +462,7 @@ int GetSanctifedMartialFeat(int iTypeWeap)
case BASE_ITEM_BASTARDSWORD: return FEAT_SANCTIFY_MARTIAL_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_SANCTIFY_MARTIAL_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_SANCTIFY_MARTIAL_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_SANCTIFY_MARTIAL_CLUB;
case BASE_ITEM_DAGGER: return FEAT_SANCTIFY_MARTIAL_DAGGER;
case BASE_ITEM_DART: return FEAT_SANCTIFY_MARTIAL_DART;
case BASE_ITEM_DIREMACE: return FEAT_SANCTIFY_MARTIAL_DIREMACE;
@@ -535,6 +537,7 @@ int Sanctify_Feat(int iTypeWeap)
case BASE_ITEM_BASTARDSWORD: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BASTARDSWORD);
case BASE_ITEM_BATTLEAXE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_BATTLEAXE);
case BASE_ITEM_CLUB: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_CLUB);
case BASE_ITEM_CRAFTED_SCEPTER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_CLUB);
case BASE_ITEM_DAGGER: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DAGGER);
case BASE_ITEM_DART: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DART);
case BASE_ITEM_DIREMACE: return GetHasFeat(FEAT_SANCTIFY_MARTIAL_DIREMACE);

View File

@@ -1082,7 +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_MAGICSTAFF: return TRUE;
case BASE_ITEM_ELVEN_COURTBLADE: return TRUE;
case BASE_ITEM_MAUL: return TRUE;
case BASE_ITEM_FALCHION: return TRUE;
@@ -1141,8 +1141,8 @@ int GetIsSimpleWeaponType(int iWeaponType)
case BASE_ITEM_CSLSHPRCWEAP: return 1;
case BASE_ITEM_GLOVES: return 1;
case BASE_ITEM_BRACER: return 1;
case BASE_ITEM_CLUB: return 2;
case BASE_ITEM_CRAFTED_SCEPTER: return 1;
case BASE_ITEM_DAGGER: return 2;
case BASE_ITEM_LIGHTMACE: return 2;
case BASE_ITEM_SICKLE: return 2;
@@ -1279,6 +1279,19 @@ struct WeaponFeat GetAllFeatsOfWeaponType(int iWeaponType)
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
break;
}
case BASE_ITEM_CRAFTED_SCEPTER: {
sFeat.Focus = FEAT_WEAPON_FOCUS_CLUB;
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_CLUB;
sFeat.EpicFocus = FEAT_EPIC_WEAPON_FOCUS_CLUB;
sFeat.EpicSpecialization = FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
sFeat.ImprovedCritical = FEAT_IMPROVED_CRITICAL_CLUB;
sFeat.OverwhelmingCritical = FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
sFeat.DevastatingCritical = FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
sFeat.WeaponOfChoice = FEAT_WEAPON_OF_CHOICE_CLUB;
sFeat.SanctifyMartialStrike = FEAT_SANCTIFY_MARTIAL_CLUB;
sFeat.VileMartialStrike = FEAT_VILE_MARTIAL_CLUB;
break;
}
case BASE_ITEM_DAGGER: {
sFeat.Focus = FEAT_WEAPON_FOCUS_DAGGER;
sFeat.Specialization = FEAT_WEAPON_SPECIALIZATION_DAGGER;
@@ -8090,7 +8103,12 @@ void AttackLoopLogic(object oDefender, object oAttacker,
if (DEBUG) DoDebug("entered AttackLoopLogic: bFirstAttack = " + IntToString(bFirstAttack) + ", cleave = " + IntToString(bIsCleaveAttack) + ", current action = " + GetActionName(iAction));
if (DEBUG) DoDebug("AttackLoopLogic: iMainAttacks = " + IntToString(iMainAttacks) + ", iOffHandAttacks = " + IntToString(iOffHandAttacks) + ", iBonusAttacks = " + IntToString(iBonusAttacks));
int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
//int bIsRangedAttack = sAttackVars.bIsRangedWeapon || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL || sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED;
int bIsRangedAttack = sAttackVars.bIsRangedWeapon ||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED_SPELL ||
sAttackVars.iTouchAttackType == TOUCH_ATTACK_RANGED ||
GetLocalInt(oAttacker, "WhirlingBlade");
// check for valid target etc., but only if it is not a cleave or circle kick (in this case we checked all of this before)
if (!bIsCleaveAttack)

View File

@@ -273,6 +273,7 @@ void TigerBlooded(object oInitiator, object oTarget);
#include "prc_inc_combat"
#include "prc_inc_sp_tch"
#include "prc_feat_const"
//////////////////////////////////////////////////
/* Internal functions */
@@ -1321,7 +1322,29 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
DelayCommand(0.0, PerformAttack(oTarget, oPC, eNone, 0.0, 0, 0, 0, "Improved Trip Free Attack Hit", "Improved Trip Free Attack Miss"));
}
}
else // If you fail, enemy gets a counter trip attempt, using Strength
else // If you fail, enemy gets a counter trip attempt, using Strength
{
if(!nCounterTrip)
{
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
// Roll counter trip attempt
nTargetCheck = nTargetStat + nTargetBonus + d20();
nPCCheck = nPCStat + nPCBonus + d20();
// If counters aren't allowed, don't knock em down
// Its down here to allow the text message to go through
SendMessageToPC(oPC, "Enemy Counter Trip Check: "+IntToString(nPCCheck)+" vs "+IntToString(nTargetCheck));
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
}
if (nTargetCheck >= nPCCheck && nCounterTrip)
{
// Knock em down
ApplyEffectToObject(DURATION_TYPE_TEMPORARY, ExtraordinaryEffect(EffectKnockdown()), oPC, 6.0);
}
}
/* else // If you fail, enemy gets a counter trip attempt, using Strength
{
nTargetStat = GetAbilityModifier(ABILITY_STRENGTH, oTarget) + GetCombatMoveCheckBonus(oTarget, COMBAT_MOVE_TRIP, FALSE, TRUE);
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
@@ -1338,7 +1361,7 @@ int DoTrip(object oPC, object oTarget, int nExtraBonus, int nGenerateAoO = TRUE,
}
SetLocalInt(oPC, "TripDifference", nTargetCheck - nPCCheck);
DelayCommand(2.0, DeleteLocalInt(oPC, "TripDifference"));
}
} */
}
else
FloatingTextStringOnCreature("You have failed on your Trip attempt",oPC, FALSE);
@@ -1941,10 +1964,21 @@ void TigerBlooded(object oInitiator, object oTarget)
int DoDisarm(object oPC, object oTarget, int nExtraBonus = 0, int nGenerateAoO = TRUE, int nCounter = TRUE)
{
object oTargetWep = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
int bNoDisarm = GetHasFeat(FEAT_INTRINSIC_WEAPON, oTarget);
string sName = GetName(oTarget);
if(bNoDisarm)
{
FloatingTextStringOnCreature(sName+" is wielding an intrinsic weapon", oPC, FALSE);
AssignCommand(oPC, ActionAttack(oTarget));
return FALSE;
}
if (!GetIsObjectValid(oTargetWep) || GetPlotFlag(oTargetWep) || (!GetIsCreatureDisarmable(oTarget) && !GetPRCSwitch(PRC_PNP_DISARM)) || GetLocalInt(oTarget, "TigerFangDisarm"))
{
FloatingTextStringOnCreature("Target is not a legal target", oPC, FALSE);
FloatingTextStringOnCreature(sName+" is not a legal target", oPC, FALSE);
AssignCommand(oPC, ActionAttack(oTarget));
return FALSE;
}

View File

@@ -133,6 +133,7 @@ const int METAMAGIC_QUICKEN_LEVEL = 4;
#include "prc_inc_damage"
#include "prc_inc_sb_const" // Spell Book Constants
#include "x0_i0_position"
#include "inc_newspellbook"
/*
access to prc_inc_nwscript via prc_inc_damage
@@ -410,6 +411,8 @@ int PRCGetSpellLevelForClass(int nSpell, int nClass)
sSpellLevel = Get2DACache("spells", "Cleric", nSpell);
else if (nClass == CLASS_TYPE_BARD)
sSpellLevel = Get2DACache("spells", "Bard", nSpell);
else if (nClass == CLASS_TYPE_ASSASSIN)
sSpellLevel = Get2DACache("spells", "Assassin", nSpell);
else if (nClass == CLASS_TYPE_CULTIST_SHATTERED_PEAK)
sSpellLevel = Get2DACache("spells", "Cultist", nSpell);
else if (nClass == CLASS_TYPE_NENTYAR_HUNTER)

View File

@@ -169,8 +169,8 @@ int GetSubschoolFlags(int nSpellID);
/* Includes */
//////////////////////////////////////////////////
#include "inc_2dacache" // already has access via inc_utility
//#include "inc_utility"
#include "inc_2dacache"
#include "inc_utility"
//////////////////////////////////////////////////
/* Function definitions */

View File

@@ -49,6 +49,8 @@ const int BRILLIANCE_SLOT_3 = 3919;
//////////////////////////////////////////////////
/* Function definitions */
//////////////////////////////////////////////////
void TriggerInspiration(object oPC, int nCombat);
void PrepareArcDilSpell(object oPC, int nSpell)
{
@@ -188,7 +190,8 @@ void SetInspiration(object oPC)
for(i = FEAT_FONT_INSPIRATION_1; i <= FEAT_FONT_INSPIRATION_10; i++)
if(GetHasFeat(i, oPC)) nFont++;
nInspiration += nFont * (1 + nFont + 1) / 2;
//nInspiration += nFont * (1 + nFont + 1) / 2;
nInspiration += nFont * (nFont + 1) / 2;
SetLocalInt(oPC, "InspirationPool", nInspiration);
FloatingTextStringOnCreature("Encounter begins with "+IntToString(nInspiration)+" inspiration", oPC, FALSE);
}
@@ -201,6 +204,8 @@ void ClearInspiration(object oPC)
int ExpendInspiration(object oPC, int nCost)
{
if (nCost <= 0) return FALSE;
int nInspiration = GetLocalInt(oPC, "InspirationPool");
if (nInspiration >= nCost)
{
@@ -261,6 +266,21 @@ void FactotumTriggerAbil(object oPC, int nAbil)
IPSafeAddItemProperty(oSkin, ipIP, 60.0, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE);
}
void TriggerInspiration(object oPC, int nCombat)
{
SetLocalInt(oPC, "InspirationHBRunning", TRUE);
DelayCommand(0.249, DeleteLocalInt(oPC, "InspirationHBRunning"));
int nCurrent = GetIsInCombat(oPC);
// We just entered combat
if (nCurrent == TRUE && nCombat == FALSE)
SetInspiration(oPC);
else if (nCurrent == FALSE && nCombat == TRUE) // Just left combat
ClearInspiration(oPC);
DelayCommand(0.25, TriggerInspiration(oPC, nCurrent));
}
/*void AddCunningBrillianceAbility(object oPC, int nAbil)
{
if (DEBUG) DoDebug("AddCunningBrillianceAbility "+IntToString(nAbil));

View File

@@ -23,11 +23,14 @@ const int FEAT_TYPE_IMPROVED_CRITICAL = 5;
const int FEAT_TYPE_OVERWHELMING_CRITICAL = 6;
const int FEAT_TYPE_DEVASTATING_CRITICAL = 7;
const int FEAT_TYPE_WEAPON_OF_CHOICE = 8;
const int FEAT_TYPE_WEAPON_PROFICIENCY = 9;
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////
int GetProficiencyFeatOfWeaponType(int iWeaponType);
/**
* Returns the appropriate weapon feat given a weapon type.
*
@@ -210,10 +213,86 @@ int GetFeatOfWeaponType(int iWeaponType, int iFeatType)
case FEAT_TYPE_OVERWHELMING_CRITICAL: return GetOverwhelmingCriticalFeatOfWeaponType(iWeaponType);
case FEAT_TYPE_DEVASTATING_CRITICAL: return GetDevastatingCriticalFeatOfWeaponType(iWeaponType);
case FEAT_TYPE_WEAPON_OF_CHOICE: return GetWeaponOfChoiceFeatOfWeaponType(iWeaponType);
case FEAT_TYPE_WEAPON_PROFICIENCY: return GetProficiencyFeatOfWeaponType(iWeaponType);
}
return -1;
}
int GetProficiencyFeatOfWeaponType(int iWeaponType)
{
switch(iWeaponType)
{
case BASE_ITEM_CBLUDGWEAPON:
case BASE_ITEM_CPIERCWEAPON:
case BASE_ITEM_CSLASHWEAPON:
case BASE_ITEM_CSLSHPRCWEAP: return FEAT_WEAPON_PROFICIENCY_CREATURE;
case BASE_ITEM_INVALID: return FEAT_IMPROVED_UNARMED_STRIKE;
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_PROFICIENCY_BASTARD_SWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_PROFICIENCY_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_WEAPON_PROFICIENCY_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_PROFICIENCY_CLUB;
case BASE_ITEM_DAGGER: return FEAT_WEAPON_PROFICIENCY_DAGGER;
case BASE_ITEM_DART: return FEAT_WEAPON_PROFICIENCY_DART;
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_PROFICIENCY_DIRE_MACE;
case BASE_ITEM_DOUBLEAXE: return FEAT_WEAPON_PROFICIENCY_DOUBLE_AXE;
case BASE_ITEM_DWARVENWARAXE: return FEAT_WEAPON_PROFICIENCY_DWARVEN_WARAXE;
case BASE_ITEM_GREATAXE: return FEAT_WEAPON_PROFICIENCY_GREATAXE;
case BASE_ITEM_GREATSWORD: return FEAT_WEAPON_PROFICIENCY_GREATSWORD;
case BASE_ITEM_HALBERD: return FEAT_WEAPON_PROFICIENCY_HALBERD;
case BASE_ITEM_HANDAXE: return FEAT_WEAPON_PROFICIENCY_HANDAXE;
case BASE_ITEM_HEAVYCROSSBOW: return FEAT_WEAPON_PROFICIENCY_HEAVY_XBOW;
case BASE_ITEM_HEAVYFLAIL: return FEAT_WEAPON_PROFICIENCY_HEAVY_FLAIL;
case BASE_ITEM_KAMA: return FEAT_WEAPON_PROFICIENCY_KAMA;
case BASE_ITEM_KATANA: return FEAT_WEAPON_PROFICIENCY_KATANA;
case BASE_ITEM_KUKRI: return FEAT_WEAPON_PROFICIENCY_KUKRI;
case BASE_ITEM_LIGHTCROSSBOW: return FEAT_WEAPON_PROFICIENCY_LIGHT_XBOW;
case BASE_ITEM_LIGHTFLAIL: return FEAT_WEAPON_PROFICIENCY_LIGHT_FLAIL;
case BASE_ITEM_LIGHTHAMMER: return FEAT_WEAPON_PROFICIENCY_LIGHT_HAMMER;
case BASE_ITEM_LIGHTMACE: return FEAT_WEAPON_PROFICIENCY_LIGHT_MACE;
case BASE_ITEM_LONGBOW: return FEAT_WEAPON_PROFICIENCY_LONGBOW;
case BASE_ITEM_LONGSWORD: return FEAT_WEAPON_PROFICIENCY_LONGSWORD;
case BASE_ITEM_MORNINGSTAR: return FEAT_WEAPON_PROFICIENCY_MORNINGSTAR;
case BASE_ITEM_QUARTERSTAFF: return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
case BASE_ITEM_MAGICSTAFF: return FEAT_WEAPON_PROFICIENCY_QUARTERSTAFF;
case BASE_ITEM_RAPIER: return FEAT_WEAPON_PROFICIENCY_RAPIER;
case BASE_ITEM_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_SCIMITAR;
case BASE_ITEM_SCYTHE: return FEAT_WEAPON_PROFICIENCY_SCYTHE;
case BASE_ITEM_SHORTBOW: return FEAT_WEAPON_PROFICIENCY_SHORTBOW;
case BASE_ITEM_SHORTSPEAR: return FEAT_WEAPON_PROFICIENCY_SHORTSPEAR;
case BASE_ITEM_SHORTSWORD: return FEAT_WEAPON_PROFICIENCY_SHORTSWORD;
case BASE_ITEM_SHURIKEN: return FEAT_WEAPON_PROFICIENCY_SHURIKEN;
case BASE_ITEM_SICKLE: return FEAT_WEAPON_PROFICIENCY_SICKLE;
case BASE_ITEM_SLING: return FEAT_WEAPON_PROFICIENCY_SLING;
case BASE_ITEM_THROWINGAXE: return FEAT_WEAPON_PROFICIENCY_THROWING_AXE;
case BASE_ITEM_TRIDENT: return FEAT_WEAPON_PROFICIENCY_TRIDENT;
case BASE_ITEM_TWOBLADEDSWORD: return FEAT_WEAPON_PROFICIENCY_TWO_BLADED_SWORD;
case BASE_ITEM_WARHAMMER: return FEAT_WEAPON_PROFICIENCY_WARHAMMER;
case BASE_ITEM_WHIP: return FEAT_WEAPON_PROFICIENCY_WHIP;
//:: new item types
case BASE_ITEM_DOUBLE_SCIMITAR: return FEAT_WEAPON_PROFICIENCY_DOUBLE_SCIMITAR;
case BASE_ITEM_EAGLE_CLAW: return FEAT_WEAPON_PROFICIENCY_EAGLE_CLAW;
case BASE_ITEM_ELVEN_COURTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_COURTBLADE;
case BASE_ITEM_ELVEN_LIGHTBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_LIGHTBLADE;
case BASE_ITEM_ELVEN_THINBLADE: return FEAT_WEAPON_PROFICIENCY_ELVEN_THINBLADE;
case BASE_ITEM_FALCHION: return FEAT_WEAPON_PROFICIENCY_FALCHION;
case BASE_ITEM_GOAD: return FEAT_WEAPON_PROFICIENCY_GOAD;
case BASE_ITEM_HEAVY_MACE: return FEAT_WEAPON_PROFICIENCY_HEAVY_MACE;
case BASE_ITEM_HEAVY_PICK: return FEAT_WEAPON_PROFICIENCY_HEAVY_PICK;
case BASE_ITEM_KATAR: return FEAT_WEAPON_PROFICIENCY_KATAR;
case BASE_ITEM_LIGHT_LANCE: return FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE;
case BASE_ITEM_LIGHT_PICK: return FEAT_WEAPON_PROFICIENCY_LIGHT_PICK;
case BASE_ITEM_MAUL: return FEAT_WEAPON_PROFICIENCY_MAUL;
case BASE_ITEM_NUNCHAKU: return FEAT_WEAPON_PROFICIENCY_NUNCHAKU;
case BASE_ITEM_SAI: return FEAT_WEAPON_PROFICIENCY_SAI;
case BASE_ITEM_SAP: return FEAT_WEAPON_PROFICIENCY_SAP;
}
return -1;
}
int GetFocusFeatOfWeaponType(int iWeaponType)
{
switch(iWeaponType)
@@ -226,6 +305,7 @@ int GetFocusFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_FOCUS_BASTARD_SWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_FOCUS_BATTLE_AXE;
case BASE_ITEM_CLUB: return FEAT_WEAPON_FOCUS_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_FOCUS_CLUB;
case BASE_ITEM_DAGGER: return FEAT_WEAPON_FOCUS_DAGGER;
case BASE_ITEM_DART: return FEAT_WEAPON_FOCUS_DART;
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_FOCUS_DIRE_MACE;
@@ -297,6 +377,7 @@ int GetSpecializationFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_SPECIALIZATION_BASTARD_SWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_SPECIALIZATION_BATTLE_AXE;
case BASE_ITEM_CLUB: return FEAT_WEAPON_SPECIALIZATION_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_SPECIALIZATION_CLUB;
case BASE_ITEM_DAGGER: return FEAT_WEAPON_SPECIALIZATION_DAGGER;
case BASE_ITEM_DART: return FEAT_WEAPON_SPECIALIZATION_DART;
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_SPECIALIZATION_DIRE_MACE;
@@ -368,6 +449,7 @@ int GetEpicFocusFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_WEAPON_FOCUS_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_WEAPON_FOCUS_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_EPIC_WEAPON_FOCUS_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_WEAPON_FOCUS_CLUB;
case BASE_ITEM_DAGGER: return FEAT_EPIC_WEAPON_FOCUS_DAGGER;
case BASE_ITEM_DART: return FEAT_EPIC_WEAPON_FOCUS_DART;
case BASE_ITEM_DIREMACE: return FEAT_EPIC_WEAPON_FOCUS_DIREMACE;
@@ -439,6 +521,7 @@ int GetEpicSpecializationFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_WEAPON_SPECIALIZATION_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_WEAPON_SPECIALIZATION_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_WEAPON_SPECIALIZATION_CLUB;
case BASE_ITEM_DAGGER: return FEAT_EPIC_WEAPON_SPECIALIZATION_DAGGER;
case BASE_ITEM_DART: return FEAT_EPIC_WEAPON_SPECIALIZATION_DART;
case BASE_ITEM_DIREMACE: return FEAT_EPIC_WEAPON_SPECIALIZATION_DIREMACE;
@@ -510,6 +593,7 @@ int GetImprovedCriticalFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_IMPROVED_CRITICAL_BASTARD_SWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_IMPROVED_CRITICAL_BATTLE_AXE;
case BASE_ITEM_CLUB: return FEAT_IMPROVED_CRITICAL_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_IMPROVED_CRITICAL_CLUB;
case BASE_ITEM_DAGGER: return FEAT_IMPROVED_CRITICAL_DAGGER;
case BASE_ITEM_DART: return FEAT_IMPROVED_CRITICAL_DART;
case BASE_ITEM_DIREMACE: return FEAT_IMPROVED_CRITICAL_DIRE_MACE;
@@ -581,6 +665,7 @@ int GetOverwhelmingCriticalFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_OVERWHELMING_CRITICAL_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_OVERWHELMING_CRITICAL_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_OVERWHELMING_CRITICAL_CLUB;
case BASE_ITEM_DAGGER: return FEAT_EPIC_OVERWHELMING_CRITICAL_DAGGER;
case BASE_ITEM_DART: return FEAT_EPIC_OVERWHELMING_CRITICAL_DART;
case BASE_ITEM_DIREMACE: return FEAT_EPIC_OVERWHELMING_CRITICAL_DIREMACE;
@@ -652,6 +737,7 @@ int GetDevastatingCriticalFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_EPIC_DEVASTATING_CRITICAL_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_EPIC_DEVASTATING_CRITICAL_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_EPIC_DEVASTATING_CRITICAL_CLUB;
case BASE_ITEM_DAGGER: return FEAT_EPIC_DEVASTATING_CRITICAL_DAGGER;
case BASE_ITEM_DART: return FEAT_EPIC_DEVASTATING_CRITICAL_DART;
case BASE_ITEM_DIREMACE: return FEAT_EPIC_DEVASTATING_CRITICAL_DIREMACE;
@@ -718,6 +804,7 @@ int GetWeaponOfChoiceFeatOfWeaponType(int iWeaponType)
case BASE_ITEM_BASTARDSWORD: return FEAT_WEAPON_OF_CHOICE_BASTARDSWORD;
case BASE_ITEM_BATTLEAXE: return FEAT_WEAPON_OF_CHOICE_BATTLEAXE;
case BASE_ITEM_CLUB: return FEAT_WEAPON_OF_CHOICE_CLUB;
case BASE_ITEM_CRAFTED_SCEPTER: return FEAT_WEAPON_OF_CHOICE_CLUB;
case BASE_ITEM_DAGGER: return FEAT_WEAPON_OF_CHOICE_DAGGER;
case BASE_ITEM_DIREMACE: return FEAT_WEAPON_OF_CHOICE_DIREMACE;
case BASE_ITEM_DOUBLEAXE: return FEAT_WEAPON_OF_CHOICE_DOUBLEAXE;
@@ -844,4 +931,6 @@ int PRCLargeWeaponCheck(int iBaseType, int nSize)
}
}
return sTest != "" && sTest != IntToString(nSize);
}
}
//::void main(){}

View File

@@ -109,7 +109,7 @@ void SetupCharacterData(object oPC)
case CLASS_TYPE_ARCANE_DUELIST: sScript = "prc_arcduel"; break;
case CLASS_TYPE_ARCHIVIST: sScript = "prc_archivist"; iData |= 0x01; break;
case CLASS_TYPE_ASSASSIN: break;
//case CLASS_TYPE_BAELNORN: sScript = "prc_baelnorn"; 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;
@@ -431,7 +431,7 @@ void EvalPRCFeats(object oPC)
ExecuteScript("moi_events", oPC);
if (GetIsBinder(oPC))
ExecuteScript("bnd_events", oPC);
ExecuteScript("bnd_events", oPC);
// check if character with crafting feat has appropriate base item in her inventory
// x - moved from prc_onhb_indiv.nss

View File

@@ -1,4 +1,6 @@
#include "prc_feat_const"
#include "inc_item_props"
#include "prc_inc_spells"
const string BRUTAL_STRIKE_MODE_VAR = "PRC_BRUTAL_STRIKE_MODE";

View File

@@ -36,6 +36,8 @@ void CheckForPnPHolyAvenger(object oItem);
#include "inc_utility"
#include "prc_inc_newip"
#include "prc_inc_castlvl"
#include "inc_newspellbook"
//////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@@ -430,8 +430,8 @@ string GetMaterialName( int iMaterialType, int bLowerCase = FALSE)
case IP_MATERIAL_ROPE_GIANT_HAIR: sName = IP_MATERIAL_NAME_ROPE_GIANT_HAIR; break;
case IP_MATERIAL_OBSIDIAN: sName = IP_MATERIAL_NAME_OBSIDIAN; break;
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_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 "";

View File

@@ -1,9 +1,68 @@
//:: prc_inc_nat_hb
//::
//:: void main(){}
void DoNaturalWeaponHB(object oPC = OBJECT_SELF);
#include "prc_inc_combat"
#include "prc_inc_template"
object GetProperTarget(object oPC, object oTarget)
/**
* Finds a valid enemy target in melee range when the original target is invalid.
* Now includes input validation, LOS checks, configurable radius, and target priority.
*
* @param oPC The creature seeking a new target
* @param oTarget The original (invalid) target
* @param fRadius Search radius in meters (optional, defaults to melee range)
* @return A valid enemy target or OBJECT_INVALID if none found
*/
object GetProperTarget(object oPC, object oTarget, float fRadius = MELEE_RANGE_METERS)
{
// Input validation
if(!GetIsObjectValid(oPC))
{
DoDebug("GetProperTarget(): Invalid oPC parameter");
return OBJECT_INVALID;
}
// Use target list system for better target selection
PurgeTargetList(oPC);
location lPC = GetLocation(oPC);
object oTest = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
while(GetIsObjectValid(oTest))
{
// Basic validation checks
if(oTest != oPC && // Not self
GetIsEnemy(oPC, oTest) && // Is enemy
GetIsInMeleeRange(oPC, oTest) && // In melee range
!GetIsDead(oTest) && // Is alive
LineOfSightObject(oPC, oTest)) // Has line of sight
{
// Add to target list with priority based on distance (nearest first)
AddToTargetList(oTest, oPC, INSERTION_BIAS_DISTANCE, FALSE);
}
oTest = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lPC, TRUE, OBJECT_TYPE_CREATURE);
}
// Get the highest priority target (nearest enemy)
object oBestTarget = GetTargetListHead(oPC);
PurgeTargetList(oPC);
if(GetIsObjectValid(oBestTarget))
{
DoDebug("GetProperTarget(): Selected target " + GetName(oBestTarget) +
" for " + GetName(oPC));
return oBestTarget;
}
// No valid target found
DoDebug("GetProperTarget(): No valid target found for " + GetName(oPC));
return OBJECT_INVALID;
}
/* object GetProperTarget(object oPC, object oTarget)
{
location lTarget = GetLocation(oPC);
// Use the function to get the closest creature as a target
@@ -21,7 +80,7 @@ object GetProperTarget(object oPC, object oTarget)
}
return oTarget;
}
} */
void DoNaturalAttack(object oWeapon)
{
@@ -289,59 +348,72 @@ void DoOverflowOnhandAttack(int nAttackMod)
);
}
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
/* void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
{
//not in combat, abort
if(!GetIsInCombat(oPC))
return;
// if(DEBUG) DoDebug("entered DoNaturalWeaponHB");
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
//no natural weapons, abort
//in a different form, abort for now fix it later
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
{
// DoDebug("DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
if(sResRef != "")
{
//get the resref to use
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
//if null, move to next
if(sResRef != "")
// Get stored weapon object, or create if doesn't exist
object oWeapon = GetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef);
if(!GetIsObjectValid(oWeapon))
{
//get the created item
object oWeapon = GetObjectByTag(sResRef);
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creating and storing creature weapon " + sResRef);
oWeapon = CreateItemOnObject(sResRef, oPC);
if(!GetIsObjectValid(oWeapon))
{
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
location lLimbo = GetLocation(oLimbo);
if(!GetIsObjectValid(oLimbo))
lLimbo = GetStartingLocation();
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - CreateItemOnObject FAILED for " + sResRef);
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: SUCCESS - weapon created, tag=" + GetTag(oWeapon) + ", name=" + GetName(oWeapon));
SetIdentified(oWeapon, TRUE);
SetLocalObject(oPC, "NAT_SEC_WEAP_" + sResRef, oWeapon);
}
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: using stored creature weapon object");
}
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
//do the attack within a delay
/*
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
*/
// Double-check validity before scheduling
if(GetIsObjectValid(oWeapon))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
//calculate the delay to use next time
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
fDelay -= 6.0;
}
else
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: ERROR - weapon object is INVALID, cannot schedule attack");
}
i++;
}
i++;
}
}
int iMod = 5; // motu99: added check for monk weapon
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
@@ -357,10 +429,10 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
for(i = 0; i < nOverflowAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
/*
// motu99: see comment above why this is commented out
AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
*/
//AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
//calculate the delay to use
@@ -399,6 +471,128 @@ void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
}
}
}
*/
void DoNaturalWeaponHB(object oPC = OBJECT_SELF)
{
//not in combat, abort
if(!GetIsInCombat(oPC))
return;
if(DEBUG) DoDebug("prc_inc_nat_hb: entered DoNaturalWeaponHB");
float fDelay = 0.1 + IntToFloat(Random(10))/100.0;
//no natural weapons, abort
//in a different form, abort for now fix it later
if(array_exists(oPC, ARRAY_NAT_SEC_WEAP_RESREF)
&& !GetIsPolyMorphedOrShifted(oPC))
{
DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: creature has natural secondary weapons");
UpdateSecondaryWeaponSizes(oPC);
int i;
while(i < array_get_size(oPC, ARRAY_NAT_SEC_WEAP_RESREF))
{
//get the resref to use
string sResRef = array_get_string(oPC, ARRAY_NAT_SEC_WEAP_RESREF, i);
//if null, move to next
if(sResRef != "")
{
//get the created item
object oWeapon = GetObjectByTag(sResRef);
if(!GetIsObjectValid(oWeapon))
{
object oLimbo = GetObjectByTag("HEARTOFCHAOS");
location lLimbo = GetLocation(oLimbo);
if(!GetIsObjectValid(oLimbo))
lLimbo = GetStartingLocation();
oWeapon = CreateObject(OBJECT_TYPE_ITEM, sResRef, lLimbo);
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: creature weapon object found!!!");
}
// Check for enhancements after creating the weapon object
int nEnhance = GetLocalInt(oPC, "PRC_NAT_WEAPON_ENHANCE");
if(nEnhance > 0)
{
DoDebug(PRC_TEXT_WHITE + "prc_inc_nat_hb >> DoNaturalWeaponHB: Applying enhancement.");
float fDuration = GetLocalFloat(oPC, "PRC_NAT_WEAPON_ENH_DUR");
IPSafeAddItemProperty(oWeapon, ItemPropertyEnhancementBonus(nEnhance), fDuration, X2_IP_ADDPROP_POLICY_REPLACE_EXISTING, FALSE, TRUE);
}
if(DEBUG) DoDebug("prc_inc_nat_hb >> DoNaturalWeaponHB: scheduling a secondary natural attack with "+GetName(oWeapon)+" at delay "+FloatToString(fDelay));
//do the attack within a delay
// motu99: commented this out; AssignCommand ist not needed, because OBJECT_SELF is oPC - using AssignCommand will only degrade performance
//AssignCommand(oPC, DelayCommand(fDelay, DoNaturalAttack(oWeapon)));
DelayCommand(fDelay, DoNaturalAttack(oWeapon));
//calculate the delay to use next time
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
}
i++;
}
}
int iMod = 5; // motu99: added check for monk weapon
if(GetHasMonkWeaponEquipped(oPC)) iMod = 3;
// check for overflow (main hand) attacks
int nOverflowAttackCount = GetLocalInt(oPC, "OverflowBaseAttackCount");
if(nOverflowAttackCount)
{
int i;
// the first overflow attack would be the seventh main hand attack, at an AB of -30
int nAttackPenalty = -6 * iMod; // -30 for normal bab, -18 for monks
// DoDebug("DoNaturalWeaponHB(): number of scripted overflow attacks: "+IntToString(nOverflowAttackCount));
for(i = 0; i < nOverflowAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted overflow attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
// motu99: see comment above why this is commented out
// AssignCommand(oPC, DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty)));
DelayCommand(fDelay, DoOverflowOnhandAttack(nAttackPenalty));
//calculate the delay to use
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
//calculate new attack penalty
nAttackPenalty -= iMod; // motu99: usually -5, for monks -3 (unarmed or kama)
}
}
// motu99: this is only here for debugging in order to test PerformAttackRound()
// must be deleted after debugging!!!
//if (GetPRCSwitch(PRC_PNP_TRUESEEING)) DelayCommand(0.01, DoOffhandAttackRound());
// check for overflow offhand attacks
int nOffhandAttackCount = GetLocalInt(oPC, "OffhandOverflowAttackCount");
// if (DEBUG) DoDebug("DoNaturalWeaponHB: number of scripted offhand attacks = "+IntToString(nOffhandAttackCount));
if(nOffhandAttackCount)
{
int i;
int nAttackPenalty = -2 * iMod; // offhand attacks always come at -5 per additional attack (but for monks we assume -3)
for(i = 0; i < nOffhandAttackCount; i++)
{
// DoDebug(COLOR_WHITE + "DoNaturalWeaponHB(): scheduling a scripted offhand attack with attack mod "+IntToString(nAttackPenalty)+" at delay "+FloatToString(fDelay));
DelayCommand(fDelay, DoOffhandAttack(nAttackPenalty));
//calculate the delay to use
fDelay += 2.05;
if(fDelay > 6.0)
fDelay -= 6.0;
//calculate new attack penalty
nAttackPenalty -= iMod;
}
}
}
/*
* motu99's test functions. Not actually used by PRC scripts

View File

@@ -277,6 +277,32 @@ void ClearNaturalWeapons(object oPC)
array_delete(oPC, ARRAY_NAT_PRI_WEAP_ATTACKS);
}
/**
* @brief Adds a natural primary weapon to a creature (PC/NPC).
*
* This function manages a creature's natural primary weapons by storing their
* resource references and attack counts in persistent arrays. If the weapon
* being added is the first natural weapon, it may automatically become the
* creature's active primary natural weapon, unless the creature is a Monk or
* Brawler. Optionally, the weapon can be forced to become the active primary
* weapon regardless of class.
*
* @param oPC The creature object to which the natural weapon will be added.
* @param sResRef The resource reference string of the natural weapon.
* @param nCount (Optional) The number of attacks this natural weapon provides.
* Default is 1.
* @param nForceUse (Optional) If TRUE, forces this weapon to become the active
* primary natural weapon regardless of the creature's class.
* Default is FALSE.
*
* @details
* - Creates persistent arrays for weapon references and attack counts if they
* do not already exist.
* - Checks if the weapon is already present to avoid duplicates.
* - Adds the weapon and attack count to the arrays.
* - Sets the primary natural weapon index to this weapon if it is the first
* natural weapon added, unless the creature is a Monk or Brawler.
*/
void AddNaturalPrimaryWeapon(object oPC, string sResRef, int nCount = 1, int nForceUse = FALSE)
{
int nFirstNaturalWeapon = FALSE;

View File

@@ -572,7 +572,10 @@ int GetMaxEssentiaCapacity(object oMeldshaper, int nClass, int nMeld)
{
int nMax = 1; // Always can invest one
int nHD = GetHitDice(oMeldshaper);
if (nHD >= 31) nMax = 5;
if (nHD >= 61) nMax = 8;
else if (nHD >= 51) nMax = 7;
else if (nHD >= 41) nMax = 6;
else if (nHD >= 31) nMax = 5;
else if (nHD >= 18) nMax = 4;
else if (nHD >= 12) nMax = 3;
else if (nHD >= 6) nMax = 2;

View File

@@ -808,7 +808,24 @@ int GetIsOnHitCastSpell(object oSpellTarget = OBJECT_INVALID, object oSpellCastI
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is armor; attacker = "+GetName(oAttacker)+", defender = "+GetName(oDefender));
}
// is the spell type item a weapon?
else if (iWeaponType == StringToInt(Get2DACache("baseitems", "WeaponType", iBaseType)))
int nWT = StringToInt(Get2DACache("baseitems", "WeaponType", iBaseType));
if (nWT > 0)
{
if (oSpellTarget == OBJECT_INVALID)
oSpellTarget = PRCGetSpellTargetObject(oSpellOrigin);
oAttacker = oSpellOrigin;
oDefender = oSpellTarget;
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is weapon [WT="+IntToString(nWT)+"]; attacker="+GetName(oAttacker)+", defender="+GetName(oDefender));
}
else
{
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is neither weapon nor armor; returning FALSE");
return FALSE;
}
/* else if (iWeaponType == StringToInt(Get2DACache("baseitems", "WeaponType", iBaseType)))
{
// determine the target, if not already given
if (oSpellTarget == OBJECT_INVALID)
@@ -823,7 +840,7 @@ int GetIsOnHitCastSpell(object oSpellTarget = OBJECT_INVALID, object oSpellCastI
{
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is neither weapon nor armor; returning FALSE");
return FALSE;
}
} */
// the spell origin must possess the item that cast the spell (at least for the aurora engine, in prc_inc_combat that may differ)

View File

@@ -1370,7 +1370,9 @@ void _prc_inc_shifting_ShiftIntoTemplateAux(object oShifter, int nShifterType, o
if(GetIsObjectValid(oShifterCWpR)) MyDestroyObject(oShifterCWpR);
if(GetIsObjectValid(oShifterCWpL)) MyDestroyObject(oShifterCWpL);
if(GetIsObjectValid(oShifterCWpB)) MyDestroyObject(oShifterCWpB);
oShifterCWpR = oShifterCWpL = oShifterCWpR = OBJECT_INVALID;
oShifterCWpR = OBJECT_INVALID;
oShifterCWpL = OBJECT_INVALID;
oShifterCWpB = OBJECT_INVALID;
// Copy the template's weapons and assign equipping

View File

@@ -0,0 +1,154 @@
#include "prc_inc_util"
#include "prc_inc_spells"
#include "prc_inc_function"
// Wrapper function for delayed visual transform with generation tracking
void DelayedSetVisualTransform(int nExpectedGeneration, object oTarget, int nTransform, float fValue)
{
// Read current generation at execution time, not when scheduled
if (nExpectedGeneration != GetLocalInt(oTarget, "PRC_SIZE_GENERATION"))
{
// Generation has changed, don't apply the transform
return;
}
SetObjectVisualTransform(oTarget, nTransform, fValue);
}
// Main wrapper function that handles generation tracking
void DelaySetVisualTransform(float fDelay, object oTarget, string sGenerationName, int nTransform, float fValue)
{
int nExpectedGeneration = GetLocalInt(oTarget, sGenerationName);
DelayCommand(fDelay, DelayedSetVisualTransform(nExpectedGeneration, oTarget, nTransform, fValue));
}
/**
* Creates a size change effect that can enlarge or reduce a creature
*
* @param oTarget Object to affect
* @param nObjectType Object type filter (OBJECT_TYPE_CREATURE, etc.)
* @param bEnlarge TRUE to enlarge, FALSE to reduce
* @param nChanges Number of size categories to change (0 = reset to original)
* @return The size change effect
*/
effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges)
{
effect eBlank;
// Increment generation for any size change
int nGeneration = PRC_NextGeneration(GetLocalInt(oTarget, "PRC_SIZE_GENERATION"));
SetLocalInt(oTarget, "PRC_SIZE_GENERATION", nGeneration);
// Store original size if not already stored - READ ACTUAL CURRENT SCALE
if(GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE") == 0.0f)
{
float fCurrentScale = GetObjectVisualTransform(oTarget, OBJECT_VISUAL_TRANSFORM_SCALE);
SetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE", fCurrentScale);
}
// Reset to original size
if(nChanges == 0)
{
float fOriginalSize = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fOriginalSize);
// DON'T delete PRC_ORIGINAL_SIZE here - keep it for future casts
return eBlank;
}
// Get the original scale
float fOriginalScale = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
// Calculate scale factor relative to original size
float fScale = fOriginalScale;
if(bEnlarge)
fScale = fOriginalScale * pow(1.5f, IntToFloat(nChanges));
else
fScale = fOriginalScale * pow(0.5f, IntToFloat(nChanges));
// Create the effect link with sanctuary VFX
effect eReturn = EffectLinkEffects(EffectVisualEffect(VFX_DUR_SANCTUARY),
EffectVisualEffect(VFX_DUR_CESSATE_POSITIVE));
if(bEnlarge)
{
eReturn = EffectLinkEffects(eReturn, EffectAttackDecrease(nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_DEXTERITY, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_STRENGTH, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectACDecrease(nChanges));
eReturn = TagEffect(eReturn, "PRC_SIZE_INCREASE");
}
else
{
eReturn = EffectLinkEffects(eReturn, EffectAttackIncrease(nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_DEXTERITY, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_STRENGTH, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectACIncrease(nChanges));
eReturn = TagEffect(eReturn, "PRC_SIZE_DECREASE");
}
// Apply visual transform using wrapper
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fScale);
return eReturn;
}
/* effect EffectSizeChange(object oTarget, int nObjectType, int bEnlarge, int nChanges)
{
effect eBlank;
// Increment generation for any size change
int nGeneration = PRC_NextGeneration(GetLocalInt(oTarget, "PRC_SIZE_GENERATION"));
SetLocalInt(oTarget, "PRC_SIZE_GENERATION", nGeneration);
// Store original size if not already stored (fixed check)
if(GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE") == 0.0f)
{
SetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE", 1.0f);
}
// Reset to original size
if(nChanges == 0)
{
float fOriginalSize = GetLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fOriginalSize);
DeleteLocalFloat(oTarget, "PRC_ORIGINAL_SIZE");
return eBlank;
}
// Calculate scale factor using pow() for multi-step changes
float fScale = 1.0f;
if(bEnlarge)
fScale = pow(1.5f, IntToFloat(nChanges)); // 1.5, 2.25, 3.375...
else
fScale = pow(0.5f, IntToFloat(nChanges)); // 0.5, 0.25, 0.125...
// Create the effect link based on enlarge/reduce
effect eReturn;
if(bEnlarge)
{
eReturn = EffectLinkEffects(EffectAttackDecrease(nChanges),
EffectAbilityDecrease(ABILITY_DEXTERITY, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityIncrease(ABILITY_STRENGTH, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectACDecrease(nChanges));
eReturn = TagEffect(eReturn, "PRC_SIZE_INCREASE");
}
else
{
eReturn = EffectLinkEffects(EffectAttackIncrease(nChanges),
EffectAbilityIncrease(ABILITY_DEXTERITY, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectAbilityDecrease(ABILITY_STRENGTH, 2 * nChanges));
eReturn = EffectLinkEffects(eReturn, EffectACIncrease(nChanges));
eReturn = TagEffect(eReturn, "PRC_SIZE_DECREASE");
}
// Apply visual transform using wrapper
DelaySetVisualTransform(0.0f, oTarget, "PRC_SIZE_GENERATION", OBJECT_VISUAL_TRANSFORM_SCALE, fScale);
return eReturn;
}
*/
//:: void main(){}

View File

@@ -363,8 +363,11 @@ int PRCIsFlying(object oCreature)
bFlying = TRUE;
}
if(!bFlying
&& ((nWings > 0 && nWings < 79) || nWings == 90))//CEP and Project Q wing models
bFlying = TRUE;
&& ((nWings > 0 && nWings < 79)
|| (nWings > 1959 && nWings < 1962)
|| (nWings > 1962 && nWings < 1966)
|| nWings == 90))//CEP and Project Q wing models
bFlying = TRUE;
if (GetHasSpellEffect(MOVE_SH_BALANCE_SKY, oCreature))
bFlying = TRUE;

View File

@@ -1011,11 +1011,16 @@ int PRCMySavingThrow(int nSavingThrow, object oTarget, int nDC, int nSaveType =
// Plague Resistant gives a +4 bonus on disease saves
if(GetHasFeat(FEAT_PLAGUE_RESISTANT, oTarget))
nDC -= 4;
// Racial +2 vs disease saves
if(GetHasFeat(FEAT_RACE_HARDINESS_VS_DISEASE, oTarget))
nDC -= 2;
// +4/+2 bonus on saves against disease, done here
if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 13)
nDC -= 4;
else if(GetLevelByClass(CLASS_TYPE_DREAD_NECROMANCER, oTarget) > 3)
nDC -= 2;
}
else if(nSaveType == SAVING_THROW_TYPE_POISON)
{

View File

@@ -70,13 +70,13 @@
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
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!!! */
const string PRC_VERSION = "PRC 3.9.0";
const string PRC_VERSION = "PRC8 4.76";
/* This variable MUST be updated every time 'assemble_spellbooks.bat' is run!!! */
@@ -91,11 +91,11 @@
* This allows material components in NWN through the materialcomp.2da
* Just put the SpellID and UTC resref in, MINUS the .utc on the end.
* This also requires the names of the items, formatted like so ("" included): "Object Name"
*
*
* Set switch to 2 to activate this
* Deducts gold instead of requiring material components
* Put the gold value in the Cost column
* Set switch to 3 to activate both at the same time
* WARNING: This will slow spellcasting down due to 2da reads and inventory loops
*/
@@ -129,7 +129,7 @@ const string PRC_BIOWARE_NEUTRALIZE_POISON = "PRC_BIOWARE_NEUTRALIZE_P
/** Remove the cap PRC added to this spell */
const string PRC_BIOWARE_REMOVE_DISEASE = "PRC_BIOWARE_REMOVE_DISEASE";
/**
/**
* This replaces the 3.0 Spell Focus bonuses with the 3.5 edition ones
*/
const string PRC_35_SPELL_FOCUS = "PRC_35_SPELL_FOCUS";
@@ -263,8 +263,8 @@ const string PRC_165_DEATH_IMMUNITY = "PRC_165_DEATH_IMMUNITY";
/*
* PRC_ACTIVATE_MAX_SPELL_DC_CAP: activate a max cap on DC casted by creature/player
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
*
* PRC_SET_MAX_SPELL_DC_CAP: the max value ex: 99
*
*/
const string PRC_ACTIVATE_MAX_SPELL_DC_CAP = "PRC_ACTIVATE_MAX_SPELL_DC_CAP";
const string PRC_SET_MAX_SPELL_DC_CAP = "PRC_SET_MAX_SPELL_DC_CAP";
@@ -291,8 +291,8 @@ const string PRC_DC_BASE_OVERRIDE = "PRC_DC_BASE_OVERRIDE";
const string PRC_DC_ADJUSTMENT = "PRC_DC_ADJUSTMENT";
/*
* By default when calculating caster level for characters with PrCs, the highest class rule will
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
* By default when calculating caster level for characters with PrCs, the highest class rule will
* be used (ie. Bard 2/Wizard 4/Elemental Savant 6 - Wizard is the highest arcane class so levels
* form PrC will be added to that class, and the caster level will be 2 for Bard and 10 for Wizard).
* When this is set, the first class rule will be used (with the same character caster level would
* be 8 for Bard and 4 for Wizard).
@@ -572,12 +572,12 @@ const string PRC_SOUL_EATER_MAX_SLAVES = "PRC_SOUL_EATER_MAX_SLAVES";
* For the Psionic Slayer prestige class, this switch limits the Favored Enemy selection
* to the Aberration racial type.
*
* This switch is provided to allow builders to more closely represent the Pen and Paper
* This switch is provided to allow builders to more closely represent the Pen and Paper
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Favored Enemy racial type is not limited)
* 1 (Favored Enemy race is limited to Aberration only)
* 1 (Favored Enemy race is limited to Aberration only)
*/
const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY";
@@ -585,20 +585,20 @@ const string PRC_PSIONIC_SLAYER_FAV_ENEMY_ABERRATION_ONLY = "PRC_PSIONIC_S
* For the Psionic Slayer prestige class, this switch requires a character to make a "kill"
* of a specific type of creature before the class becomes available.
*
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
* (included in the PRC Items) to the designated creature.
* Use of this switch requires that the module builder add a "Psionic Slayer Kill Token"
* (included in the PRC Items) to the designated creature.
*
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
* Alternately, a script or item can be made that will run the script "prc_psysly_killt"
* on the PC. This script will set the flag that allows the target PC to take the Psionic Slayer Class.
* Example code:
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
* Example code:
* ExecuteScript("prc_psysly_killt", oPC); // Where oPC is an player charcter object
*
* This switch is provided to allow builders to more closely represent the Pen and Paper
* This switch is provided to allow builders to more closely represent the Pen and Paper
* Illithid Slayer class, instead of the broader Open Game License "Slayer" class.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Kill Token / Script NOT required for taking the Psionic Slayer Class)
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
* 1 (Kill Token / Script REQUIRED before the Psionic Slayer Class is available to take)
*/
const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN";
@@ -607,19 +607,19 @@ const string PRC_PSIONIC_SLAYER_REQUIRE_KILL_TOKEN = "PRC_PSIONIC_SLAYER_R
* By default the Werewolf class uses the Bioware Polymorph effect to perfrom its
* Hybrid Form Shapchange.
*
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
* Shapchange code instead.
* This switch allows the Werewolf class to be toggled to use the PRC Shifter
* Shapchange code instead.
*
* Type: Int
* Type: Int
* Values: 0 [Default] (Werewolf Hybrid Shapchange uses Bioware Polymorph)
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
* 1 (Werewolf Hybrid Shapchange uses PRC Shifter shape change code)
*/
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPCHANGE";
const string PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE = "PRC_WEREWOLF_HYBRID_USE_SHIFTER_SHAPECHANGE";
/**
* Sets the max bonus for the PnP Shifter shifting systems
*
* Type: Int
* Type: Int
* Values: any greater than 0
*/
const string PRC_PNP_SHIFTER_BONUS = "PRC_PNP_SHIFTER_BONUS";
@@ -783,7 +783,7 @@ const string PRC_STAFF_CASTER_LEVEL = "PRC_STAFF_CASTER_LEVEL";
/**
* [DEFUNCT]
* A wand must be equipped before it can cast a spell
*
*
* Any value above 0 turns off the requirement to have a wand equipped to use it
*
* This switch is defunct, wands must *always* be equipped to use them.
@@ -931,7 +931,7 @@ const string PRC_PNP_FAMILIAR_FEEDING = "PRC_PNP_FAMILIAR_FEEDING
/**
* Use PRC henchmen-familiars instead of BioWare's - this will allow
* new classes to have familiars, but summoned creatures will no longer
* new classes to have familiars, but summoned creatures will no longer
* be 'true' familiars (ie. can't possess PRC familiar)
*/
const string PRC_FAMILIARS = "PRC_FAMILIARS";
@@ -1114,7 +1114,7 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
* Disable registration of custom cohorts
*/
const string PRC_DISABLE_REGISTER_COHORTS = "PRC_DISABLE_REGISTER_COHORTS";
/*
* Disable cohorts starting with gear
*/
@@ -1144,19 +1144,19 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
* Medium armor is a 25% speed reduction, Heavy is a 33% reduction
*/
const string PRC_PNP_ARMOR_SPEED = "PRC_PNP_ARMOR_SPEED";
/*
* Applies a 99% speed boost when out of combat
* Warning that it will likely cause PCs to be overly speedy when combat starts
* Potential problem causer
*/
const string PRC_FAST_TRAVEL_SPEED = "PRC_FAST_TRAVEL_SPEED";
/*
* Applys a Discipline bonus equal to BAB to all characters if turned on
* Bonus only applies to characters with 0 ranks in Discipline
*/
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
const string PRC_PNP_KNOCKDOWN = "PRC_PNP_KNOCKDOWN";
/*
* by Bioware rules, PCs have approximatly a 7th faster movement than NPCs
@@ -1204,8 +1204,11 @@ const string PRC_SPELL_ALIGNMENT_RESTRICT = "PRC_SPELL_ALIGNMENT_REST
*/
const string PRC_APPEARNCE_CHANGE_DISABLE = "PRC_APPEARNCE_CHANGE_DISABLE";
/*
* Allow "Monk" gloves to merge with a creature weapons when Wildshaped.
* Will also merge bracers with creature hides when Wildshaped.
*/
const string PRC_WILDSHAPE_ALLOWS_ARMS_SLOT = "PRC_WILDSHAPE_ALLOWS_ARMS_SLOT";
/******************************************************************************\
* Death/Bleeding system *
@@ -1223,7 +1226,7 @@ const string PRC_PNP_DEATH_ENABLE = "PRC_PNP_DEATH_ENA
* if FALSE, dont bleed just die
* By PnP this would be 1 round, or 6 seconds
*/
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
const string PRC_DEATH_OR_BLEED = "PRC_DEATH_OR_BLEED";
/*
* Damage when bleeding
@@ -1316,7 +1319,7 @@ const string PRC_ACP_DELAY = "PRC_ACP_DELAY";
/******************************************************************************
* File End switches
* File End switches
******************************************************************************/
/**
@@ -1490,10 +1493,10 @@ const string PRC_POISON_IS_FOOD_SCRIPT_NAME = "PRC_POISON_IS_FOOD_SCRIP
const string PRC_POISON_ALLOW_CLEAN_IN_EQUIP = "PRC_POISON_ALLOW_CLEAN_IN_EQUIP";
/**
*
*
* Default: crafting requires only gold and xp
*/
const string PRC_CRAFT_POISON_USE_INGREDIENST = "PRC_CRAFT_POISON_USE_INGREDIENST";
const string PRC_CRAFT_POISON_USE_INGREDIENTS = "PRC_CRAFT_POISON_USE_INGREDIENTS";
/******************************************************************************\
* PRGT system switches *
@@ -1542,10 +1545,10 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
/**
* If this is set, The Astral Seed power will attempt to use the provided string as
* the ResRef to create the Astral Seed object instead of the of the phylactery
* the ResRef to create the Astral Seed object instead of the of the phylactery
* ResRef("x2_plc_phylact").
* May be used by builders to create an object that CAN be destroyed, or has other traits,
* as desired.
* as desired.
* Type: String
* Values: "" [Default] (Blank, or not set: Use default phylactery ResRef for Astral Seed)
* STRING (Entered String will be used as the ResRef of created Astral Seed object)
@@ -1553,14 +1556,14 @@ const string PRC_PSI_ASTRAL_CONSTRUCT_DUR_MOD = "PRC_PSI_ASTRAL_CONSTRUCT
const string PRC_PSI_ASTRAL_SEED_RESREF = "PRC_PSI_ASTRAL_SEED_RESREF";
/**
* By default the Astral Seed power respawns the player, and then makes them immobile for
* By default the Astral Seed power respawns the player, and then makes them immobile for
* 24-game-hours.
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
* If this switch is set, it will adjust the imobility time period; shortening it, lengthing it, or
* effectively eliminating it.
* Type: Int
* Values: 0 [Default] (Not set: Use default 24 hour duration)
* -1 (Any negative value will result in a fixed duratoion of 2 seconds, which effectively eliminates the wait period)
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
* 1 (Any potitive value: multiply duration by the value provided and then divide result by 1000.
* Values less than 1000 will shorten the duration, values higher than 1000 will lengthen it.)
*/
const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000";
@@ -1571,7 +1574,7 @@ const string PRC_PSI_ASTRAL_SEED_RESPAWN_DELAY_X1000 = "PRC_PSI_ASTRAL_SE
* If this flag is set, the XP loss is completely eliminated. The standard PRC event hook script
* of "prc_pw_astralseed" may be used to script any additional effects to occure upon Astral Seed
* respawning, including scripting specific XP loss amount.
* Type: Int
* Type: Int
* Values: 0 [Default] (Not set: lose 1 level worth of XP upon Astral Seed respawn)
* 1 (Any potitive value: Remove all XP loss from Astral Seed respawn)
*/
@@ -1908,7 +1911,7 @@ const string PRC_CRAFT_TIMER_MAX = "PRC_CRAFT_TIMER_MAX";
*/
const string PRC_CRAFT_TIMER_MIN = "PRC_CRAFT_TIMER_MIN";
/**
/*
* These three switches modify Bioware crafting so that the items produced have the
* casterlevel of the spellcaster who created them. Normally under Bioware, it is possible
* for a level 3 caster to produce level 9 items and for a level 40 caster to only produce
@@ -1955,16 +1958,21 @@ 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
* As above, except it applies to scepters
*/
const string PRC_CREATE_INFUSION_CASTER_LEVEL = "PRC_CREATE_INFUSION_CASTER_LEVEL";
const string PRC_CRAFT_SCEPTER_CASTER_LEVEL = "PRC_CRAFT_SCEPTER_CASTER_LEVEL";
/*
* Builder's Option: Enables the optional PnP herbs for creating infusions.
* 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";
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
@@ -2015,6 +2023,13 @@ const string PRC_X2_CRAFTWAND_COSTMODIFIER = "PRC_X2_CRAFTWAND_COSTMO
*/
const string PRC_X2_CRAFTROD_COSTMODIFIER = "PRC_X2_CRAFTROD_COSTMODIFIER";
/*
* cost modifier of spells crafted into scepters
* note that adding a second spell costs 75%
* defaults to 750
*/
const string PRC_X2_CRAFTSCEPTER_COSTMODIFIER = "PRC_X2_CRAFTSCEPTER_COSTMODIFIER";
/*
* cost modifier of spells crafted into staffs
* note that adding a second spell costs 75% and 3 or more costs 50%
@@ -2342,7 +2357,7 @@ const string PRC_XP_GIVE_XP_TO_NPCS = "PRC_XP_GIVE_XP_TO_NPCS";
/**
* Setting this switch will turn off the messages about being too far awy to gain XP
*/
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
const string PRC_XP_DISABLE_SPAM = "PRC_XP_DISABLE_SPAM";
/**
* PCs must be in the same area as the CR to gain XP.
@@ -2901,13 +2916,13 @@ const string PRC_PERFECTED_MAP_MULTIPLIER = "PRC_PERFECTED_MAP_MULTIP
\******************************************************************************/
/**
* Sets how many seconds it takes to contact a vestige.
* Sets how many seconds it takes to contact a vestige.
* Any number less than 6 is ignored
*/
const string PRC_CONTACT_VESTIGE_TIMER = "PRC_CONTACT_VESTIGE_TIMER";
/**
* Sets how many seconds it takes to bind a vestige.
* Sets how many seconds it takes to bind a vestige.
* Any number less than 12 is ignored
*/
const string PRC_BIND_VESTIGE_TIMER = "PRC_BIND_VESTIGE_TIMER";
@@ -2941,6 +2956,20 @@ const string PRC_PW_SECURITY_CD_CHECK = "PRC_PW_SECURITY_CD_CHECK";
*/
const string PRC_DEBUG = "PRC_DEBUG";
/******************************************************************************\
* Duration NUI Switches *
\******************************************************************************/
/**
* Toggles allowing player to remove friendly PC spells on player through Duration NUI
* instead of just their own spells.
*/
const string PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS = "PRC_ALLOWED_TO_REMOVE_FRIENDLY_SPELLS";
/**
* Toggles allowing players to see the duration of hostile spells on them.
*/
const string PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS = "PRC_ALLOWED_TO_SEE_HOSTILE_SPELLS";

View File

@@ -10,6 +10,8 @@
//:://////////////////////////////////////////////
//:://////////////////////////////////////////////
#include "prc_spell_const"
//////////////////////////////////////////////////
/* Function prototypes */
//////////////////////////////////////////////////

View File

@@ -91,6 +91,107 @@ float DamageAvg(int iDamage);
/* Function defintions */
//////////////////////////////////////////////////
// StepDie: increases a damage die by 'nSteps' steps according to d20 SRD progression
// Increment the unarmed damage by nSteps
int StepDie(int nDamage, int nSteps)
{
int i;
for (i = 0; i < nSteps; i++)
{
switch (nDamage)
{
// 1-dice increments
case IP_CONST_MONSTERDAMAGE_1d2: nDamage = IP_CONST_MONSTERDAMAGE_1d3; break;
case IP_CONST_MONSTERDAMAGE_1d3: nDamage = IP_CONST_MONSTERDAMAGE_1d4; break;
case IP_CONST_MONSTERDAMAGE_1d4: nDamage = IP_CONST_MONSTERDAMAGE_1d6; break;
case IP_CONST_MONSTERDAMAGE_1d6: nDamage = IP_CONST_MONSTERDAMAGE_1d8; break;
case IP_CONST_MONSTERDAMAGE_1d8: nDamage = IP_CONST_MONSTERDAMAGE_1d10; break;
case IP_CONST_MONSTERDAMAGE_1d10: nDamage = IP_CONST_MONSTERDAMAGE_1d12; break;
case IP_CONST_MONSTERDAMAGE_1d12: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
// 2-dice increments
//case IP_CONST_MONSTERDAMAGE_2d3: nDamage = IP_CONST_MONSTERDAMAGE_2d4; break;
case IP_CONST_MONSTERDAMAGE_2d4: nDamage = IP_CONST_MONSTERDAMAGE_2d6; break;
case IP_CONST_MONSTERDAMAGE_2d6: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
case IP_CONST_MONSTERDAMAGE_2d8: nDamage = IP_CONST_MONSTERDAMAGE_2d10; break;
case IP_CONST_MONSTERDAMAGE_2d10: nDamage = IP_CONST_MONSTERDAMAGE_2d12; break;
case IP_CONST_MONSTERDAMAGE_2d12: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
// 3-dice increments
case IP_CONST_MONSTERDAMAGE_3d4: nDamage = IP_CONST_MONSTERDAMAGE_3d6; break;
case IP_CONST_MONSTERDAMAGE_3d6: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
case IP_CONST_MONSTERDAMAGE_3d8: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
case IP_CONST_MONSTERDAMAGE_3d10: nDamage = IP_CONST_MONSTERDAMAGE_3d12; break;
case IP_CONST_MONSTERDAMAGE_3d12: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
// 4-dice increments
case IP_CONST_MONSTERDAMAGE_4d4: nDamage = IP_CONST_MONSTERDAMAGE_4d6; break;
case IP_CONST_MONSTERDAMAGE_4d6: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
case IP_CONST_MONSTERDAMAGE_4d8: nDamage = IP_CONST_MONSTERDAMAGE_4d10; break;
case IP_CONST_MONSTERDAMAGE_4d10: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
case IP_CONST_MONSTERDAMAGE_4d12: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
// 5-dice increments
case IP_CONST_MONSTERDAMAGE_5d4: nDamage = IP_CONST_MONSTERDAMAGE_5d6; break;
case IP_CONST_MONSTERDAMAGE_5d6: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
case IP_CONST_MONSTERDAMAGE_5d8: nDamage = IP_CONST_MONSTERDAMAGE_5d10; break;
case IP_CONST_MONSTERDAMAGE_5d10: nDamage = IP_CONST_MONSTERDAMAGE_5d12; break;
case IP_CONST_MONSTERDAMAGE_5d12: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
// 6-dice increments
//case IP_CONST_MONSTERDAMAGE_6d4: nDamage = IP_CONST_MONSTERDAMAGE_6d6; break;
case IP_CONST_MONSTERDAMAGE_6d6: nDamage = IP_CONST_MONSTERDAMAGE_6d8; break;
case IP_CONST_MONSTERDAMAGE_6d8: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
case IP_CONST_MONSTERDAMAGE_6d10: nDamage = IP_CONST_MONSTERDAMAGE_6d12; break;
case IP_CONST_MONSTERDAMAGE_6d12: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
// 7-dice increments
case IP_CONST_MONSTERDAMAGE_7d4: nDamage = IP_CONST_MONSTERDAMAGE_7d6; break;
case IP_CONST_MONSTERDAMAGE_7d6: nDamage = IP_CONST_MONSTERDAMAGE_7d8; break;
case IP_CONST_MONSTERDAMAGE_7d8: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
case IP_CONST_MONSTERDAMAGE_7d10: nDamage = IP_CONST_MONSTERDAMAGE_7d12; break;
case IP_CONST_MONSTERDAMAGE_7d12: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
// 8-dice increments
//case IP_CONST_MONSTERDAMAGE_8d4: nDamage = IP_CONST_MONSTERDAMAGE_8d6; break;
case IP_CONST_MONSTERDAMAGE_8d6: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
case IP_CONST_MONSTERDAMAGE_8d8: nDamage = IP_CONST_MONSTERDAMAGE_8d10; break;
case IP_CONST_MONSTERDAMAGE_8d10: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
case IP_CONST_MONSTERDAMAGE_8d12: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
// 9-dice increments
//case IP_CONST_MONSTERDAMAGE_9d4: nDamage = IP_CONST_MONSTERDAMAGE_9d6; break;
case IP_CONST_MONSTERDAMAGE_9d6: nDamage = IP_CONST_MONSTERDAMAGE_9d8; break;
case IP_CONST_MONSTERDAMAGE_9d8: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
case IP_CONST_MONSTERDAMAGE_9d10: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break;
case IP_CONST_MONSTERDAMAGE_9d12: nDamage = IP_CONST_MONSTERDAMAGE_6d20; break;
// 10-dice increments
//case IP_CONST_MONSTERDAMAGE_10d4: nDamage = IP_CONST_MONSTERDAMAGE_10d6; break;
case IP_CONST_MONSTERDAMAGE_10d6: nDamage = IP_CONST_MONSTERDAMAGE_10d8; break;
case IP_CONST_MONSTERDAMAGE_10d8: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
case IP_CONST_MONSTERDAMAGE_10d10: nDamage = IP_CONST_MONSTERDAMAGE_10d12; break;
case IP_CONST_MONSTERDAMAGE_10d12: nDamage = IP_CONST_MONSTERDAMAGE_7d20; break;
// d20 increments
case IP_CONST_MONSTERDAMAGE_1d20: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
case IP_CONST_MONSTERDAMAGE_2d20: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
case IP_CONST_MONSTERDAMAGE_3d20: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
case IP_CONST_MONSTERDAMAGE_4d20: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
case IP_CONST_MONSTERDAMAGE_5d20: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break; //:: Everything breaks down here
case IP_CONST_MONSTERDAMAGE_6d20: nDamage = IP_CONST_MONSTERDAMAGE_1d20; break;
case IP_CONST_MONSTERDAMAGE_7d20: nDamage = IP_CONST_MONSTERDAMAGE_8d20; break;
case IP_CONST_MONSTERDAMAGE_8d20: nDamage = IP_CONST_MONSTERDAMAGE_9d20; break;
case IP_CONST_MONSTERDAMAGE_9d20: nDamage = IP_CONST_MONSTERDAMAGE_10d20; break;
default: break; // top tier or unknown
}
}
return nDamage;
}
// Clean up any extras in the inventory.
void CleanExtraFists(object oCreature)
{
@@ -168,12 +269,169 @@ void ApplyUnarmedAttackEffects(object oCreature)
}
// Determines the amount of damage a character can do.
// IoDM: +1 dice at level 4, +2 dice at level 8
// IoDM: +1 die at level 4, +2 dice at level 8
// Sacred Fist: Levels add to monk levels, or stand alone as monk levels.
// Shou: 1d6 at level 1, 1d8 at level 2, 1d10 at level 3, 2d6 at level 5
// Monk: 1d6 at level 1, 1d8 at level 4, 1d10 at level 8, 2d6 at level 12, 2d8 at level 16, 2d10 at level 20
// Frostrager: 1d6 at level 1, 1d8 at level 4
int FindUnarmedDamage(object oCreature)
{
int iDamage = 0;
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
int iSacredFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
int iEnlightenedFist = GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oCreature);
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
int iFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature);
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
int iRonove = 0;
int iMonkDamage = 1;
int iShouDamage = 1;
int iBrawlerDamage = 1;
int iFrostDamage = 1;
int iSUSDamage = 1;
int iDieIncrease = 0;
int iSize;
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
iRonove = GetLocalInt(oCreature, "RonovesFists");
//:: Determine creature size
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
{
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
}
else
{
iSize = 5; // medium
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
if (iSize < 1) iSize = 1;
if (iSize > 9) iSize = 9;
}
// Sacred Fist code break protection
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
// Combine monk-like levels
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
// Superior Unarmed Strike
if (GetHasFeat(FEAT_SUPERIOR_UNARMED_STRIKE, oCreature))
{
iMonk += 4;
int nHD = GetHitDice(oCreature);
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
}
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonk += iAscetic;
// Cap monk progression
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
else if (iMonk > 20) iMonk = 20;
// Ronove replacement
if (iRonove > iMonk) iMonk = iRonove;
// Monk damage calculation (2DA row)
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
if (iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
iMonkDamage = 8;
// Shou Disciple base damage
if (iShou > 0)
{
int nRow;
if (iShou == 1) nRow = 3;
else if (iShou == 2) nRow = 4;
else if (iShou == 3) nRow = 5;
else if (iShou == 4) nRow = 5;
else if (iShou == 5) nRow = 6;
else nRow = 3;
if (nRow > 6) nRow = 6;
iShouDamage = StringToInt(Get2DACache("unarmed_dmg", "size" + IntToString(iSize), nRow));
}
// Frostrager
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
// Brawler
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
if (iBrawler >= 36) iBrawlerDamage += 2;
// Armor/shield penalties
if (iMonkDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 0 || bShieldEq)
iMonkDamage = 1;
}
if (iShouDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 3 || bShieldEq)
iShouDamage = 1;
}
// Determine IoDM die increase
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
// Lookup monk damage in 2DA
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
// 3.0e monk special cases
if (iSize <= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
{
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
}
// Apply IoDM die increase last, after 2DA lookups
if (iMonkDamage > 0) iMonkDamage = StepDie(iMonkDamage, iDieIncrease);
if (iShouDamage > 0) iShouDamage = StepDie(iShouDamage, iDieIncrease);
if (iBrawlerDamage > 0) iBrawlerDamage = StepDie(iBrawlerDamage, iDieIncrease);
if (iFrostDamage > 0) iFrostDamage = StepDie(iFrostDamage, iDieIncrease);
if (iSUSDamage > 0) iSUSDamage = StepDie(iSUSDamage, iDieIncrease);
// Select best damage
iDamage = iMonkDamage;
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
iDamage = (DamageAvg(iBrawlerDamage) > DamageAvg(iDamage)) ? iBrawlerDamage : iDamage;
if (DEBUG) DoDebug("prc_inc_unarmed: iDamage "+IntToString(iDamage));
return iDamage;
}
/* int FindUnarmedDamage(object oCreature)
{
int iDamage = 0;
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
@@ -195,36 +453,30 @@ int FindUnarmedDamage(object oCreature)
int iDieIncrease = 0;
int iSize;
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature)) iRonove = GetLocalInt(oCreature, "RonovesFists");
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
iRonove = GetLocalInt(oCreature, "RonovesFists");
// if the creature is shifted, use model size
// otherwise, we want to stick to what the feats say they "should" be.
// No making pixies with Dragon Appearance for "huge" fist damage.
if( GetIsPolyMorphedOrShifted(oCreature)
|| GetPRCSwitch(PRC_APPEARANCE_SIZE))
// Determine creature size
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
{
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5; // medium is size 5 for us
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
}
else
{
// Determine creature size by feats.
iSize = 5; // medium is size 5 for us
iSize = 5; // medium
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
// include size changes
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
// cap if needed
if (iSize < 1) iSize = 1;
if (iSize > 9) iSize = 9;
}
// Sacred Fist cannot add their levels if they've broken their code.
// Sacred Fist code break protection
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
// several classes add their levels to the monk class,
// or use monk progression if the character has no monk levels
// Combine monk-like levels
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
// Superior Unarmed Strike
@@ -232,49 +484,66 @@ int FindUnarmedDamage(object oCreature)
{
iMonk += 4;
int nHD = GetHitDice(oCreature);
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
}
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonk += iAscetic;
// In 3.0e, Monk progression stops after level 16:
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonk = 16;
// in 3.5e, monk progression stops at 20.
else if(iMonk > 20) iMonk = 20;
// Cap monk progression
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
else if (iMonk > 20) iMonk = 20;
// Ronove is in place of monk, does not stack
// Ronove replacement
if (iRonove > iMonk) iMonk = iRonove;
// monks damage progesses every four levels, starts at 1d6
if (iMonk > 0)
iMonkDamage = iMonk / 4 + 3;
// Monk damage calculation
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
// For medium monks in 3.0e skip 2d8 and go to 1d20
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonkDamage = 8;
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
iMonkDamage = 8;
// Shou Disciple either adds its level to existing class or does its own damage, depending
// on which is better. Here we will determine how much damage the Shou Disciple does
// without stacking.
if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
// Frostrager does not stack with other damage types
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6; // Lv. 1: 1d6
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8; // Lv. 3: 1d8
//if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
//if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
//iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
if (iShou > 0)
{
// Determine 2DA row for Shou progression
int nRow;
if (iShou == 1) nRow = 3; // monk1
else if (iShou == 2) nRow = 4; // monk2
else if (iShou == 3) nRow = 5; // monk3
else if (iShou == 4) nRow = 6; // monk4
else if (iShou == 5) nRow = 7; // monk5
else if (iShou == 6) nRow = 8; // monk6
else if (iShou == 7) nRow = 9; // monk7
else nRow = 10; // monk8+
nRow += iDieIncrease;
if (nRow > 10) nRow = 10; // clamp to max row
// Brawler follows monk progression except for the last one (3d8)
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3; // 1d6, 1d8, 1d10, 2d6, 2d8, 2d10
if (iBrawler >= 36) iBrawlerDamage += 2; // 3d8
// Lookup damage in unarmed_damage.2da using size column
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), nRow));
}
// Monks and monk-like classes deal no additional damage when wearing any armor, at
// least in NWN. This is to reflect that. No shields too.
// Frostrager
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
// Brawler
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
if (iBrawler >= 36) iBrawlerDamage += 2;
// Armor/shield penalties
if (iMonkDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
@@ -284,13 +553,10 @@ int FindUnarmedDamage(object oCreature)
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 0 || bShieldEq)
{
iMonkDamage = 1;
}
}
// Shou Disciples can wear light armor
if (iShouDamage > 1)
if (iShouDamage > 1)
{
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
@@ -299,53 +565,31 @@ int FindUnarmedDamage(object oCreature)
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
if (GetBaseAC(oArmor) > 3 || bShieldEq)
{
iShouDamage = 1;
}
iShouDamage = 1;
}
// For Initiate of Draconic Mysteries
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
//:: Expansion / Compression powers
int nExpansion = GetLocalInt(oCreature, "PRC_Power_Expansion_SizeIncrease");
int nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
if (nExpansion)
{
iSize += nExpansion;
}
if (nCompression)
{
iSize -= nCompression;
}
// IoDM die increase
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease += 2;
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease += 1;
iMonkDamage += iDieIncrease;
iShouDamage += iDieIncrease;
iBrawlerDamage += iDieIncrease;
iFrostDamage += iDieIncrease;
iSUSDamage += iDieIncrease;
//FloatingTextStringOnCreature("prc_inc_unarmed: Size is: "+IntToString(iSize)+".", oCreature);
//FloatingTextStringOnCreature("prc_inc_unarmed: Pre 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
// now, read the damage from the table in unarmed_dmg.2da
// Lookup final monk damage in 2DA
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
//FloatingTextStringOnCreature("prc_inc_unarmed: Post 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
// Medium+ monks have some special values on the table in 3.0:
// 3.0e monk special cases
if (iSize >= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
{
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
}
// Select best damage
iDamage = iMonkDamage;
// Future unarmed classes: if you do your own damage, add in "comparisons" below here.
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
@@ -354,6 +598,8 @@ int FindUnarmedDamage(object oCreature)
return iDamage;
}
*/
// Adds appropriate feats to the skin. Stolen from SoulTaker + expanded with overwhelming/devastating critical.
void UnarmedFeats(object oCreature)
@@ -426,13 +672,13 @@ void UnarmedFists(object oCreature)
// Sacred Fists who break their code get no benefits.
if (GetHasFeat(FEAT_SF_CODE,oCreature)) iSacFist = 0;
// The monk adds all these classes.
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
// Ascetic Stalker
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
iMonkEq += iAscetic;
iMonkEq += iAscetic;
// Determine the type of damage the character should do.
string sWeapType;

View File

@@ -1,6 +1,6 @@
//::///////////////////////////////////////////////
//:: Weapon Restriction System Include
//:: prc_inc_restwpn.nss
//:: prc_inc_wpnrest.nss
//::///////////////////////////////////////////////
/*
Functions to support PnP Weapon Proficiency and
@@ -15,6 +15,56 @@
#include "inc_item_props"
#include "prc_x2_itemprop"
//:: Detects if "monk" gloves are being equipped & set a
//:: variable if TRUE for use with other functions
void DetectMonkGloveEquip(object oItem)
{
int nItemType = GetBaseItemType(oItem);
object oPC = GetItemPossessor(oItem);
if (!GetIsObjectValid(oItem))
{
if (DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Unable to determine item possessor");
return;
}
if(nItemType != BASE_ITEM_GLOVES && nItemType != BASE_ITEM_BRACER) {return;}
else if (nItemType == BASE_ITEM_BRACER)
{
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloveEquip(): Bracer found!");
DeleteLocalInt(oPC, "WEARING_MONK_GLOVES");
return;
}
else
{
itemproperty ipG = GetFirstItemProperty(oItem);
while(GetIsItemPropertyValid(ipG))
{
int nTypeG = GetItemPropertyType(ipG);
// Damage related properties we care about
if(nTypeG == ITEM_PROPERTY_DAMAGE_BONUS
|| nTypeG == ITEM_PROPERTY_ATTACK_BONUS
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nTypeG == ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT)
{
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves found!");
SetLocalInt(oPC, "WEARING_MONK_GLOVES", 1);
return;
}
else
{
if(DEBUG) DoDebug("prc_inc_wpnrest >> DetectMonkGloves(): Monk gloves not found! You should never see this.");
DeleteLocalInt(oPC, "WEARING_MONK_GLOVES");
return;
}
}
}
}
/**
* All of the following functions use the following parameters:
*
@@ -23,6 +73,69 @@
* @param nHand The hand the weapon is wielded in. In the form of
* ATTACK_BONUS_ONHAND or ATTACK_BONUS_OFFHAND.
*/
//:: returns TRUE if the wielded weapon works with the Swashbuckler's class abilities.
int GetHasSwashbucklerWeapon(object oPC)
{
object oWeap = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
if (!GetIsObjectValid(oWeap)) return FALSE;
int nType = GetBaseItemType(oWeap);
switch (nType)
{
case BASE_ITEM_DAGGER:
case BASE_ITEM_KATAR:
case BASE_ITEM_HANDAXE:
case BASE_ITEM_KAMA:
case BASE_ITEM_KUKRI:
case BASE_ITEM_LIGHTHAMMER:
case BASE_ITEM_LIGHTMACE:
case BASE_ITEM_LIGHT_PICK:
case BASE_ITEM_RAPIER:
case BASE_ITEM_SHORTSWORD:
case BASE_ITEM_SICKLE:
case BASE_ITEM_WHIP:
case BASE_ITEM_SAI:
case BASE_ITEM_SAP:
case BASE_ITEM_NUNCHAKU:
case BASE_ITEM_GOAD:
case BASE_ITEM_ELVEN_LIGHTBLADE:
case BASE_ITEM_ELVEN_THINBLADE:
case BASE_ITEM_EAGLE_CLAW:
return TRUE;
}
// Iaijutsu Master allows katana
if (GetLevelByClass(CLASS_TYPE_IAIJUTSU_MASTER, oPC) > 0)
{
if (nType == BASE_ITEM_KATANA) return TRUE;
}
return FALSE;
}
//:: returns TRUE if the wielded weapon works with the Champion of Corellon's Elegant Strike.
int GetHasCorellonWeapon(object oPC)
{
object oWeap = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
if (!GetIsObjectValid(oWeap)) return FALSE;
int nType = GetBaseItemType(oWeap);
switch (nType)
{
case BASE_ITEM_SCIMITAR:
case BASE_ITEM_LONGSWORD:
case BASE_ITEM_RAPIER:
case BASE_ITEM_ELVEN_COURTBLADE:
case BASE_ITEM_ELVEN_LIGHTBLADE:
case BASE_ITEM_ELVEN_THINBLADE:
return TRUE;
}
return FALSE;
}
void DoRacialEquip(object oPC, int nBaseType);
//return if PC has proficiency in an item
@@ -763,6 +876,7 @@ int IsMeleeWeapon(int nBaseItemType)
case BASE_ITEM_CLOAK:
case BASE_ITEM_CRAFTED_ROD:
case BASE_ITEM_CRAFTED_STAFF:
case BASE_ITEM_CRAFTED_SCEPTER:
case BASE_ITEM_CRAFTMATERIALMED:
case BASE_ITEM_CRAFTMATERIALSML:
case BASE_ITEM_CREATUREITEM:

View File

@@ -262,7 +262,7 @@ const int IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_LANCE = 4638;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_HEAVY_PICK = 4639;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_LIGHT_PICK = 4640;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_SAI = 4641;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHUKU = 4642;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_NUNCHAKU = 4642;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_FALCHION = 4643;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_SAP = 4644;
const int IP_CONST_FEAT_WEAPON_PROFICIENCY_KATAR = 4645;

View File

@@ -29,8 +29,8 @@ 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_CRAFTED_SCEPTER = 249;
const int BASE_ITEM_CRAFTED_VIAL = 250;
const int BASE_ITEM_MUNDANE_HERB = 252;
const int BASE_ITEM_INFUSED_HERB = 253;

View File

@@ -3,6 +3,7 @@
#include "psi_inc_psifunc"
#include "inc_lookups"
#include "nw_inc_nui"
#include "tob_inc_tobfunc"
//
// GetCurrentSpellLevel
@@ -153,8 +154,53 @@ json GreyOutButton(json jButton, float w, float h);
//
json CreateGreyOutRectangle(float w, float h);
//
// GetTrueClassType
// Gets the true class Id for a provided class Id, mostly for RHD and for
// ToB prestige classes
//
// Arguments:
// nClass:int classId
//
// Returns:
// int the true classId based off nClass
//
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0, int nClass=0);
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel);
void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF);
void RemoveIPFeat(object oPC, int ipFeatID);
void CallSpellUnlevelScript(object oPC, int nClass, int nLevel)
{
SetScriptParam("UnLevel_ClassChoice", IntToString(nClass));
SetScriptParam("UnLevel_LevelChoice", IntToString(nLevel));
ExecuteScript("prc_unlvl_script", oPC);
}
void RemoveIPFeat(object oPC, int ipFeatID)
{
object oSkin = GetPCSkin(oPC);
itemproperty ipTest = GetFirstItemProperty(oSkin);
while(GetIsItemPropertyValid(ipTest))
{
// Check if the itemproperty is a bonus feat that has been marked for removal
if(GetItemPropertyType(ipTest) == ITEM_PROPERTY_BONUS_FEAT)
{
if (GetItemPropertySubType(ipTest) == ipFeatID)
{
if(DEBUG) DoDebug("_ManeuverRecurseRemoveArray(): Removing bonus feat itemproperty:\n" + DebugIProp2Str(ipTest));
// If so, remove it
RemoveItemProperty(oSkin, ipTest);
}
}
ipTest = GetNextItemProperty(oSkin);
}
}
int GetCurrentSpellLevel(int nClass, int nLevel)
{
@@ -401,6 +447,9 @@ json GetSpellIcon(int spellId,int featId=0,int nClass=0)
// the FeatID holds the accurate spell icon, not the SpellID
int nFeatID = StringToInt(Get2DACache("spells", "FeatID", spellId));
// however if no featId was found use the spell's icon instead
if (!nFeatID)
return JsonString(Get2DACache("spells", "IconResRef", spellId));
return JsonString(Get2DACache("feat", "Icon", nFeatID));
}
@@ -528,3 +577,39 @@ void ClearSpellDescriptionNUI(object oPlayer=OBJECT_SELF)
DeleteLocalInt(oPlayer, NUI_SPELL_DESCRIPTION_CLASSID_VAR);
}
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
{
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
{
int trueClass = GetPrimaryBladeMagicClass(oPC);
return trueClass;
}
if ((nClass == CLASS_TYPE_SHAPECHANGER
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|| (nClass == CLASS_TYPE_OUTSIDER
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|| (nClass == CLASS_TYPE_ABERRATION
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
return CLASS_TYPE_SORCERER;
if (nClass == CLASS_TYPE_FEY
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
return CLASS_TYPE_BARD;
return nClass;
}

View File

@@ -156,3 +156,16 @@ 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";
//////////////////////////////////////////////////
// //
// Spell Duration NUI //
// //
//////////////////////////////////////////////////
const string DURATION_NUI_WINDOW_ID = "DurationNUI";
const string NUI_DURATION_MANUALLY_OPENED_PARAM = "DurationNUIManuallyOpenedParam";
const string NUI_DURATION_NO_LOOP_PARAM = "DurationNUINoLoopParam";
const string NUI_DURATION_TRACKED_SPELLS = "durationNUI_trackedSpellList";
const string NUI_SPELL_DURATION_BASE_BIND = "durationNUI_durationSpellId";
const string NUI_SPELL_DURATION_SPELLID_BASE_CANCEL_BUTTON = "NuiDurationCancelButtonSpellID";

View File

@@ -98,21 +98,9 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF);
//
// CloseNUILevelUpWindow
// Closes the NUI Level Up Window if its open
// setting reset to 1 will make it clear the entire cache as if the NUI was never opened
//
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF);
//
// GetTrueClassType
// Gets the true class Id for a provided class Id, mostly for RHD and for
// ToB prestige classes
//
// Arguments:
// nClass:int classId
//
// Returns:
// int the true classId based off nClass
//
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF);
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0);
//
// GetRemainingSpellChoices
@@ -432,7 +420,7 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF);
// Returns:
// int:Boolean TRUE if the spell is a expanded knowledge spell, FALSE otherwise
//
int IsExpKnowledgePower(int nClass, int spellbookId);
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF);
//
// GetExpKnowledgePowerListRequired
@@ -861,7 +849,7 @@ void AddSpellToChosenList(int nClass, int spellbookId, int spellCircle, object o
// if the power is a expanded knowledge than we immediatly add it to the
// extra list, otherwise check to make sure we have made all choices in our
// base list first before adding it to the extra list.
if (IsExpKnowledgePower(nClass, spellbookId)
if (IsExpKnowledgePower(nClass, spellbookId, oPC)
|| GetRemainingPowerChoices(nClass, spellCircle, oPC, FALSE) == 0)
{
string sFile = GetClassSpellbookFile(nClass);
@@ -1061,53 +1049,20 @@ void OpenNUILevelUpWindow(int nClass, object oPC=OBJECT_SELF)
// figure out what the true base class is (mostly true for RHD)
int chosenClass = GetTrueClassType(nClass, oPC);
SetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR, chosenClass);
ExecuteScript("prc_nui_lv_view", oPC);
}
int GetTrueClassType(int nClass, object oPC=OBJECT_SELF)
{
if (nClass == CLASS_TYPE_JADE_PHOENIX_MAGE
|| nClass == CLASS_TYPE_MASTER_OF_NINE
|| nClass == CLASS_TYPE_DEEPSTONE_SENTINEL
|| nClass == CLASS_TYPE_BLOODCLAW_MASTER
|| nClass == CLASS_TYPE_RUBY_VINDICATOR
|| nClass == CLASS_TYPE_ETERNAL_BLADE
|| nClass == CLASS_TYPE_SHADOW_SUN_NINJA)
{
int trueClass = GetPrimaryBladeMagicClass(oPC);
return trueClass;
}
if ((nClass == CLASS_TYPE_SHAPECHANGER
&& GetRacialType(oPC) == RACIAL_TYPE_ARANEA)
|| (nClass == CLASS_TYPE_OUTSIDER
&& GetRacialType(oPC) == RACIAL_TYPE_RAKSHASA)
|| (nClass == CLASS_TYPE_ABERRATION
&& GetRacialType(oPC) == RACIAL_TYPE_DRIDER)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_ARKAMOI)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_HOBGOBLIN_WARSOUL)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_REDSPAWN_ARCANISS)
|| (nClass == CLASS_TYPE_MONSTROUS
&& GetRacialType(oPC) == RACIAL_TYPE_MARRUTACT))
return CLASS_TYPE_SORCERER;
if (nClass == CLASS_TYPE_FEY
&& GetRacialType(oPC) == RACIAL_TYPE_GLOURA)
return CLASS_TYPE_BARD;
return nClass;
}
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF)
void CloseNUILevelUpWindow(object oPC=OBJECT_SELF, int reset=0)
{
int currentClass = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CLASS_VAR);
// if we are refreshing the NUI but not finished we need to clear some caching done
// to save computation time as they will need to be reprocessed.
DeleteLocalJson(oPC, NUI_LEVEL_UP_DISCIPLINE_INFO_VAR + IntToString(currentClass));
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, -20);
if (reset)
{
ClearLevelUpNUICaches(currentClass, oPC);
}
int nPreviousToken = NuiFindWindow(oPC, NUI_LEVEL_UP_WINDOW_ID);
if (nPreviousToken != 0)
{
@@ -1126,7 +1081,7 @@ int ShouldSpellButtonBeEnabled(int nClass, int circleLevel, int spellbookId, obj
// if its an expanded knowledge choice and we have already made all our
// exp knowledge choices then it needs to be disabled.
if (IsExpKnowledgePower(nClass, spellbookId))
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
{
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
@@ -1540,7 +1495,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
totalSpellsKnown = GetSpellKnownMaxCount(casterLevel, circleLevel, nClass, oPC);
// Favoured Soul has more 0 choices than there are spells for some reason
if (nClass == CLASS_TYPE_FAVOURED_SOUL && circleLevel == 0 && totalSpellsKnown > 6)
totalSpellsKnown = 6;
totalSpellsKnown = 7;
// logic for spont casters
json selectedCircle = JsonObjectGet(chosenSpells, IntToString(circleLevel));
@@ -1554,6 +1509,7 @@ int GetRemainingSpellChoices(int nClass, int circleLevel, object oPC=OBJECT_SELF
if (chosenCircle == circleLevel)
SetLocalInt(oPC, NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR, remainingChoices);
if (DEBUG) DoDebug("Remaining spell choices is " + IntToString(remainingChoices));
return remainingChoices;
}
@@ -1664,11 +1620,13 @@ void RemoveSpells(int nClass, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
string sSpellBook = GetSpellsKnown_Array(nClass);
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
// remove the spell from the spellbook
array_extract_int(oPC, sSpellBook, nSpellbookID);
array_extract_int(oPC, spellsAtLevelList, nSpellbookID);
// wipe the spell from the player
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
WipeSpellFromHide(ipFeatID, oPC);
RemoveIPFeat(oPC, ipFeatID);
}
}
}
@@ -1779,6 +1737,7 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
// get location of persistant storage on the hide
string sSpellbook = GetSpellsKnown_Array(nClass, nSpellLevel);
if (DEBUG) DoDebug("Adding spell " + IntToString(nSpellbookID) + "to " + sSpellbook);
//object oToken = GetHideToken(oPC);
// Create spells known persistant array if it is missing
@@ -1789,13 +1748,25 @@ void LearnSpells(int nClass, object oPC=OBJECT_SELF)
nSize = 0;
}
string spellsAtLevelList = "SpellsKnown_" + IntToString(nClass) + "_AtLevel" + IntToString(GetHitDice(oPC));
int spellsAtLevelSize = persistant_array_get_size(oPC, spellsAtLevelList);
if (spellsAtLevelSize < 0)
{
persistant_array_create(oPC, spellsAtLevelList);
spellsAtLevelSize = 0;
}
// set the list of spells learned at this level
string sFile = GetClassSpellbookFile(nClass);
int spellId = StringToInt(Get2DACache(sFile, "SpellID", nSpellbookID));
persistant_array_set_int(oPC, spellsAtLevelList, spellsAtLevelSize, spellId);
if (DEBUG) DoDebug("Adding spells to array " + spellsAtLevelList);
// Mark the spell as known (e.g. add it to the end of oPCs spellbook)
persistant_array_set_int(oPC, sSpellbook, nSize, nSpellbookID);
if (nSpellbookType == SPELLBOOK_TYPE_SPONTANEOUS)
{
// add spell
string sFile = GetClassSpellbookFile(nClass);
string sArrayName = "NewSpellbookMem_" + IntToString(nClass);
int featId = StringToInt(Get2DACache(sFile, "FeatID", nSpellbookID));
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", nSpellbookID));
@@ -1975,7 +1946,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
//if we could not find the spell here, something went wrong
if (persistant_array_extract_int(oPC, sTestArray, spellID) < 0)
{
SendMessageToPC(oPC, "Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
if (DEBUG) DoDebug("Could not find spellID " + IntToString(spellID) + " in the class's spellbook!");
return;
}
}
@@ -2002,10 +1973,7 @@ void RemoveSpellKnown(int nClass, int spellbookId, object oPC=OBJECT_SELF, int n
// remove spell from player
int ipFeatID = StringToInt(Get2DACache(sFile, "IPFeatID", spellbookId));
itemproperty ipFeat = PRCItemPropertyBonusFeat(ipFeatID);
object oSkin = GetPCSkin(oPC);
RemoveItemProperty(oSkin, ipFeat);
CheckAndRemoveFeat(oSkin, ipFeat);
RemoveIPFeat(oPC, ipFeatID);
}
json GetSpellIDsKnown(int nClass, object oPC=OBJECT_SELF, int nList=0)
@@ -2088,7 +2056,7 @@ string ReasonForDisabledSpell(int nClass, int spellbookId, object oPC=OBJECT_SEL
// if its an expanded knowledge choice and we have already made all our
// exp knowledge choices then it needs to be disabled.
if (IsExpKnowledgePower(nClass, spellbookId))
if (IsExpKnowledgePower(nClass, spellbookId, oPC))
{
int remainingExp = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC)
+ GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
@@ -2322,11 +2290,15 @@ json GetChosenReplaceListObject(object oPC=OBJECT_SELF)
////////////////////////////////////////////////////////////////////////////
int IsExpKnowledgePower(int nClass, int spellbookId)
int IsExpKnowledgePower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
{
string sFile = GetClassSpellbookFile(nClass);
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
return isExp;
if (isExp)
return TRUE;
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
int isOuterDomain = (featId) ? !CheckPowerPrereqs(featId, oPC) : FALSE;
return isOuterDomain;
}
json GetCurrentPowerList(object oPC=OBJECT_SELF)
@@ -2346,12 +2318,8 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
string sFile = GetClassSpellbookFile(nClass);
int featId = StringToInt(Get2DACache(sFile, "FeatID", spellbookId));
int isExp = StringToInt(Get2DACache(sFile, "Exp", spellbookId));
// if you don't have the prereqs for a power then don't add it. Specific for
// psions
if (!CheckPowerPrereqs(featId, oPC))
return FALSE;
// if the power is a expanded knowledge power
if (isExp)
if (!CheckPowerPrereqs(featId, oPC) || isExp)
{
// and we have a expanded knowledge choice left to make then show
// the button
@@ -2360,10 +2328,12 @@ int ShouldAddPower(int nClass, int spellbookId, object oPC=OBJECT_SELF)
int currentCircle = GetLocalInt(oPC, NUI_LEVEL_UP_SELECTED_CIRCLE_VAR);
int choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EXP_KNOWLEDGE, oPC);
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " expanded power choices left!");
if (choicesLeft && (currentCircle <= (maxLevel-1)))
addPower = TRUE;
choicesLeft = GetRemainingExpandedChoices(nClass, POWER_LIST_EPIC_EXP_KNOWLEDGE, oPC);
if (choicesLeft)
if (DEBUG) DoDebug("You still have " + IntToString(choicesLeft) + " epic expanded power choices left!");
if (choicesLeft && (currentCircle <= (maxLevel-1)))
addPower = TRUE;
// otherwise don't show the button.
return addPower;
@@ -2383,7 +2353,7 @@ void LearnPowers(int nClass, object oPC=OBJECT_SELF)
int nSpellbookID = JsonGetInt(JsonArrayGet(powerList, i));
// get the expanded knowledge list we are adding to if any
int expKnow = GetExpKnowledgePowerListRequired(nClass, nSpellbookID, oPC);
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetManifesterLevel(oPC, nClass, TRUE), expKnow);
AddPowerKnown(oPC, nClass, nSpellbookID, TRUE, GetHitDice(oPC), expKnow);
}
}
@@ -2570,7 +2540,7 @@ int HasPreRequisitesForManeuver(int nClass, int spellbookId, object oPC=OBJECT_S
if (chosenDisc != JsonNull())
{
int nManCount = (JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_MANEUVER)))
+ JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE))));
+ JsonGetInt(JsonObjectGet(chosenDisc, IntToString(MANEUVER_TYPE_STANCE))));
if (nManCount >= prereqs)
return TRUE;
}
@@ -3166,13 +3136,18 @@ json GetInvokerKnownListObject(int nClass, object oPC=OBJECT_SELF)
}
SetLocalJson(oPC, NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR + IntToString(nClass), knownObject);
if (DEBUG) DoDebug("Printing json representation of allowed invocations for class " + IntToString(nClass));
if (DEBUG) DoDebug(JsonDump(knownObject, 2));
return knownObject;
}
int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJECT_SELF, int extra=TRUE)
{
if (DEBUG) DoDebug ("Getting remaining invocation choices at " + IntToString(chosenCircle) + " circle");
int remaining = 0;
int nLevel = GetInvokerLevel(oPC, nClass);
if (nClass == CLASS_TYPE_DRAGON_SHAMAN) nLevel = GetLevelByClass(nClass, oPC);
if (DEBUG) DoDebug("Invoker level is " + IntToString(nLevel));
json knownObject = GetInvokerKnownListObject(nClass, oPC);
json chosenInv = GetChosenSpellListObject(nClass, oPC);
@@ -3200,8 +3175,10 @@ int GetRemainingInvocationChoices(int nClass, int chosenCircle, object oPC=OBJEC
currentChosen += 1;
}
}
if (DEBUG) DoDebug(IntToString(currentChosen) + " incantations chosen at " + IntToString(chosenCircle) + " circle");
int allowedAtCircle = JsonGetInt(JsonObjectGet(currentLevelKnown, IntToString(i)));
if (DEBUG) DoDebug(IntToString(allowedAtCircle) + " incantations allowed at " + IntToString(chosenCircle) + " circle");
remaining = (allowedAtCircle - currentChosen + remaining);
// if the circle is below the chosen circle and we have a positive remaining,

View File

@@ -28,11 +28,17 @@ void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int re
void CreateSpellDescriptionNUI(object oPlayer, int featID, int spellId=0, int realSpellId=0)
{
// look for existing window and destroy
int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
int nPreviousToken = NuiFindWindow(oPlayer, NUI_SPELL_DESCRIPTION_WINDOW_ID);
if(nPreviousToken != 0)
{
NuiDestroy(oPlayer, nPreviousToken);
}
/* int nPreviousToken = NuiFindWindow(OBJECT_SELF, NUI_SPELL_DESCRIPTION_WINDOW_ID);
if(nPreviousToken != 0)
{
NuiDestroy(OBJECT_SELF, nPreviousToken);
}
} */
// in order of accuracy for names it goes RealSpellID > SpellID > FeatID
string spellName;

View File

@@ -180,6 +180,24 @@ void RunImpactScript(object oPC, int nSpellID, int nEventType)
DeleteLocalInt(oPC, PRC_SPELLID_OVERRIDE);
}
//Returns true if the spell is one of the repair spells
int IsRepair(int nSpellID)
{
return ((nSpellID >= SPELL_REPAIR_MINOR_DAMAGE) && (nSpellID <= SPELL_REPAIR_CRITICAL_DAMAGE));
}
//Returns true if the spell is one of the mass repair spells
int IsMassRepair(int nSpellID)
{
return ((nSpellID >= SPELL_MASS_REPAIR_LIGHT_DAMAGE) && (nSpellID <= SPELL_MASS_REPAIR_CRITICAL_DAMAGE));
}
//Returns true if the spell is one of the mass inflict damage spells
int IsMassInflictDamage(int nSpellID)
{
return ((nSpellID >= SPELL_MASS_INFLICT_LIGHT_DAMAGE) && (nSpellID <= SPELL_MASS_INFLICT_CRITICAL_DAMAGE));
}
//Returns true if the spell is one of the cure spells
int IsCure(int nSpellID)
{

View File

@@ -13,6 +13,9 @@ const int SPELL_BLACKLIGHT = 2091;
const int SPELL_BARD_SONG = 411;
const int SPELL_BARD_CURSE_SONG = 644;
//:: Monk
const int SPELL_MONK_ABUNDANT_STEP = 17986;
//:: Epic Level Handbook
const int SPELL_EPIC_SWARM_OF_ARROWS = 17996;
@@ -1359,8 +1362,27 @@ const int SPELL_SUMMON_NATURES_ALLY_9_ARANEA = 17085;
const int SPELL_CHASING_PERFECTION = 2479;
//:: Spell Compendium Spells
const int SPELL_SPIRIT_WORM = 17248;
const int SPELL_FORCE_MISSILES = 2480;
const int SPELL_FORCE_MISSILES = 2480;
const int SPELL_REPAIR_MINOR_DAMAGE = 17094;
const int SPELL_REPAIR_LIGHT_DAMAGE = 17095;
const int SPELL_REPAIR_MODERATE_DAMAGE = 17096;
const int SPELL_REPAIR_SERIOUS_DAMAGE = 17097;
const int SPELL_REPAIR_CRITICAL_DAMAGE = 17098;
const int SPELL_INFLICT_LIGHT_DAMAGE = 17100;
const int SPELL_INFLICT_MODERATE_DAMAGE = 17101;
const int SPELL_INFLICT_SERIOUS_DAMAGE = 17102;
const int SPELL_INFLICT_CRITICAL_DAMAGE = 17103;
const int SPELL_SPIRIT_WORM = 17248;
//:: Races of Eberron
const int SPELL_MASS_REPAIR_LIGHT_DAMAGE = 17105;
const int SPELL_MASS_REPAIR_MODERATE_DAMAGE = 17106;
const int SPELL_MASS_REPAIR_SERIOUS_DAMAGE = 17107;
const int SPELL_MASS_REPAIR_CRITICAL_DAMAGE = 17108;
const int SPELL_MASS_INFLICT_LIGHT_DAMAGE = 17110;
const int SPELL_MASS_INFLICT_MODERATE_DAMAGE = 17111;
const int SPELL_MASS_INFLICT_SERIOUS_DAMAGE = 17112;
const int SPELL_MASS_INFLICT_CRITICAL_DAMAGE = 17113;
//:: Masters of the Wild Spells
const int SPELL_FORESTFOLD = 17090;
@@ -1392,6 +1414,10 @@ const int SPELL_FOT_LEONALS_ROAR = 17993;
const int SPELL_FOT_LIONS_SWIFTNESS = 17994;
const int SPELL_FAVORED_OF_THE_COMPANIONS = 17995;
//:: Magic Item Compendium
const int SPELL_AROMA_OF_CURDLED_DEATH = 17987;
const int SPELL_ELIXIR_OF_THE_BEETLE = 17987;
//x
const int SPELL_TENSERS_FLOATING_DISK = 3849;
const int SPELL_WOLFSKIN = 3850;

View File

@@ -487,7 +487,8 @@ void SpellfireChargeItem(object oPC, object oItem)
AddSpellfireLevels(oPC, nNewCharges - 50);
nNewCharges = 50;
}
SetItemCharges(oItem, nCharges + nExpend);
//SetItemCharges(oItem, nCharges + nExpend);
SetItemCharges(oItem, nNewCharges);
//Assuming 50 is the maximum
//refunding excess charges
}

View File

@@ -47,12 +47,10 @@ int GetWeaponFocusFeatItemProperty(int nFeatNumber)
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_TRIDENT, IP_CONST_FEAT_WEAPON_FOCUS_TRIDENT);
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_LIGHT_LANCE, IP_CONST_FEAT_WEAPON_FOCUS_GOAD);
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW, IP_CONST_FEAT_WEAPON_FOCUS_GOAD);
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_LIGHTBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_LIGHTBLADE);
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW, IP_CONST_FEAT_WEAPON_FOCUS_EAGLE_CLAW);
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_THINBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_THINBLADE);
if(nItemProperty != -1) return nItemProperty;
nItemProperty = GetFeatItemProperty(nFeatNumber, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_COURTBLADE, IP_CONST_FEAT_WEAPON_FOCUS_ELVEN_COURTBLADE);

View File

@@ -61,6 +61,7 @@ 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 int X2_CI_CRAFTSCEPTER_FEAT_ID = 25962;
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
@@ -276,6 +277,7 @@ int CIGetIsCraftFeatBaseItem(object oItem)
nBt == BASE_ITEM_BLANK_WAND ||
nBt == BASE_ITEM_CRAFTED_ROD ||
nBt == BASE_ITEM_CRAFTED_STAFF ||
nBt == BASE_ITEM_CRAFTED_SCEPTER ||
nBt == BASE_ITEM_MUNDANE_HERB)
return TRUE;
else
@@ -302,7 +304,7 @@ object CICraftBrewPotion(object oCreator, int nSpellID )
return OBJECT_INVALID;
}
/* //just a tad retarded, don't you think? other crafting feats are not similarly restricted
/* //just a tad silly, don't you think? other crafting feats are not similarly restricted
//Uses per day
int nUsesAllowed;
@@ -529,6 +531,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
case CLASS_TYPE_WIZARD:
case CLASS_TYPE_SORCERER: sClass = "Wiz_Sorc"; break;
case CLASS_TYPE_CLERIC:
case CLASS_TYPE_OCULAR:
case CLASS_TYPE_UR_PRIEST: sClass = "Cleric"; break;
case CLASS_TYPE_PALADIN: sClass = "Paladin"; break;
case CLASS_TYPE_DRUID:
@@ -709,6 +712,7 @@ object CICraftScribeScroll(object oCreator, int nSpellID)
return oTarget;
}
*/
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to brew a potion
// -----------------------------------------------------------------------------
@@ -864,7 +868,6 @@ These dont work as IPs since they are hardcoded */
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to create a scroll
// -----------------------------------------------------------------------------
@@ -1132,6 +1135,169 @@ These dont work as IPs since they are hardcoded */
return FALSE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a scepter
// -----------------------------------------------------------------------------
int CICraftCheckCraftScepter(object oSpellTarget, object oCaster, int nSpellID = 0)
{
if(nSpellID == 0) nSpellID = PRCGetSpellId();
int nCasterLevel = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
int bSuccess = TRUE;
int nCount = 0;
itemproperty ip = GetFirstItemProperty(oSpellTarget);
int nMetaMagic = PRCGetMetaMagicFeat();
while(GetIsItemPropertyValid(ip))
{
if(GetItemPropertyType(ip) == ITEM_PROPERTY_CAST_SPELL)
nCount++;
ip = GetNextItemProperty(oSpellTarget);
}
if(nCount >= 2) //:: Scepters are limited to two spells
{
FloatingTextStringOnCreature("* Failure - Too many castspell itemproperties *", oCaster);
return TRUE;
}
if(!GetHasFeat(X2_CI_CRAFTSCEPTER_FEAT_ID, oCaster))
{
FloatingTextStrRefOnCreature(40487, oCaster); // Item Creation Failed - Don't know how to create that type of item
return TRUE; // tried item creation but do not know how to do it
}
if(CIGetIsSpellRestrictedFromCraftFeat(nSpellID, X2_CI_CRAFTSCEPTER_FEAT_ID))
{
FloatingTextStrRefOnCreature(16829169, oCaster); // can not be used with this feat
return TRUE;
}
// Get the base spell level (circle) before metamagic adjustments
int nBaseLevel = CIGetSpellInnateLevel(nSpellID, TRUE);
// Check if spell circle is 7th level or lower
if (nBaseLevel > 7)
{
//FloatingTextStrRefOnCreature(83623, oCaster); // Spell level too high
FloatingTextStringOnCreature("* Failure - scepters can not hold spells higher than level 7", oCaster);
return TRUE;
}
int nLevel = nBaseLevel;
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
{
switch(nMetaMagic)
{
case METAMAGIC_EMPOWER:
nLevel += 2;
break;
case METAMAGIC_EXTEND:
nLevel += 1;
break;
case METAMAGIC_MAXIMIZE:
nLevel += 3;
break;
/* case METAMAGIC_QUICKEN:
nLevel += 1;
break;
case METAMAGIC_SILENT:
nLevel += 5;
break;
case METAMAGIC_STILL:
nLevel += 6;
break;
These dont work as IPs since they are hardcoded */
}
}
int nCostMod = GetPRCSwitch(PRC_X2_CRAFTSCEPTER_COSTMODIFIER);
if(!nCostMod) nCostMod = 750;
int nLvlRow = IPGetIPConstCastSpellFromSpellID(nSpellID);
int nCLevel = StringToInt(Get2DACache("iprp_spells","CasterLvl",nLvlRow));
int nCost = CIGetCraftGPCost(nLevel, nCostMod, PRC_CRAFT_SCEPTER_CASTER_LEVEL);
//discount for second spell
if(nCount+1 == 2)
nCost = (nCost/2);
//takes epic xp costs into account
struct craft_cost_struct costs = GetModifiedCostsFromBase(nCost, oCaster, FEAT_CRAFT_SCEPTER, (nMetaMagic > 0));
if(costs.nGoldCost < 1) costs.nXPCost = 1;
if(costs.nXPCost < 1) costs.nXPCost = 1;
//if(GetGold(oCaster) < nGoldCost) // enough gold?
if (!GetHasGPToSpend(oCaster, costs.nGoldCost))
{
FloatingTextStrRefOnCreature(3786, oCaster); // Item Creation Failed - not enough gold!
return TRUE;
}
int nHD = GetHitDice(oCaster);
int nMinXPForLevel = (nHD * (nHD - 1)) * 500;
int nNewXP = GetXP(oCaster) - costs.nXPCost;
//if (nMinXPForLevel > nNewXP || nNewXP == 0 )
if (!GetHasXPToSpend(oCaster, costs.nXPCost))
{
FloatingTextStrRefOnCreature(3785, oCaster); // Item Creation Failed - Not enough XP
return TRUE;
}
//check spell emulation
if(!CheckAlternativeCrafting(oCaster, nSpellID, costs))
{
FloatingTextStringOnCreature("*Crafting failed!*", oCaster, FALSE);
return TRUE;
}
int nPropID = IPGetIPConstCastSpellFromSpellID(nSpellID);
if (nPropID == 0 && nSpellID != 0)
{
FloatingTextStrRefOnCreature(84544,oCaster);
return TRUE;
}
if (nPropID != -1)
{
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpell(nPropID,IP_CONST_CASTSPELL_NUMUSES_1_CHARGE_PER_USE),oSpellTarget);
if(GetPRCSwitch(PRC_CRAFT_SCEPTER_CASTER_LEVEL))
{
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellCasterLevel(nSpellID, nCasterLevel),oSpellTarget);
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellMetamagic(nSpellID, PRCGetMetaMagicFeat()),oSpellTarget);
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyCastSpellDC(nSpellID, PRCGetSaveDC(PRCGetSpellTargetObject(), OBJECT_SELF)),oSpellTarget);
}
}
else
bSuccess = FALSE;
if(bSuccess)
{
//TakeGoldFromCreature(nGoldCost, oCaster, TRUE);
//SetXP(oCaster, nNewXP);
SpendXP(oCaster, costs.nXPCost);
SpendGP(oCaster, costs.nGoldCost);
//DestroyObject (oSpellTarget);
FloatingTextStrRefOnCreature(8502, oCaster); // Item Creation successful
//advance time here
if(!costs.nTimeCost) costs.nTimeCost = 1;
AdvanceTimeForPlayer(oCaster, RoundsToSeconds(costs.nTimeCost));
string sName;
sName = GetName(oCaster)+"'s Magic Scepter";
SetItemCharges(oSpellTarget, 50);
//sName = Get2DACache("spells", "Name", nID);
//sName = "Wand of "+GetStringByStrRef(StringToInt(sName));
SetName(oSpellTarget, sName);
SetItemCursedFlag(oSpellTarget, FALSE);
SetDroppableFlag(oSpellTarget, TRUE);
return TRUE;
}
else
{
FloatingTextStrRefOnCreature(76417, oCaster); // Item Creation Failed
return TRUE;
}
return TRUE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a staff
// -----------------------------------------------------------------------------
int CICraftCheckCraftStaff(object oSpellTarget, object oCaster, int nSpellID = 0)
{
@@ -1280,6 +1446,9 @@ These dont work as IPs since they are hardcoded */
return TRUE;
}
// -----------------------------------------------------------------------------
// Returns TRUE if the player used the last spell to craft a rod
// -----------------------------------------------------------------------------
int CICraftCheckCraftRod(object oSpellTarget, object oCaster, int nSpellID = 0)
{
@@ -1426,6 +1595,7 @@ These dont work as IPs since they are hardcoded */
return TRUE;
}
int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID, int nSpell = 0)
{
if(!GetIsObjectValid(oCaster)) oCaster = OBJECT_SELF;
@@ -1476,6 +1646,11 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
//:: Check for Inscribe Epic Runes and cap CL at 20 if it doesn't exist.
int bEpicRunes = GetHasFeat(EPIC_FEAT_INSCRIBE_EPIC_RUNES, oCaster);
if (!bEpicRunes) { if(nCaster > 20) nCaster = 20; }
int nDC = PRCGetSaveDC(oTarget, oCaster);
if(!nSpell) nSpell = PRCGetSpellId();
int nSpellLevel = 0;
@@ -1498,6 +1673,7 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
// Minimum level.
if (nSpellLevel == 0) nSpellLevel = 1;
// This will be modified with Runecaster code later.
int nCharges = 1;
if (GetLocalInt(oCaster, "RuneCharges")) nCharges = nCount;
@@ -1606,9 +1782,14 @@ int InscribeRune(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALI
// If they have this active, the bonuses are already added, so skip
// If they don't, add the bonuses down below
if(GetHasSpellEffect(SPELL_RUNE_CHANT))
nRuneChant = 0;
nRuneChant = 0;
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, PRCGetCasterLevel());
//:: Check for Inscribe Epic Runes and cap CL at 20 if it doesn't exist.
nCaster = PRCGetCasterLevel();
if (!bEpicRunes) { if(nCaster > 20) nCaster = 20; }
itemproperty ipLevel = ItemPropertyCastSpellCasterLevel(nSpell, nCaster);
AddItemProperty(DURATION_TYPE_PERMANENT,ipLevel,oRune);
itemproperty ipMeta = ItemPropertyCastSpellMetamagic(nSpell, PRCGetMetaMagicFeat());
AddItemProperty(DURATION_TYPE_PERMANENT,ipMeta,oRune);
@@ -1715,13 +1896,23 @@ int AttuneGem(object oTarget = OBJECT_INVALID, object oCaster = OBJECT_INVALID,
}
// oTarget here should be the gem. If it's not, fail.
if(!GetIsObjectValid(oTarget)) oTarget = PRCGetSpellTargetObject();
// Only accepts bioware gems
if (GetStringLeft(GetResRef(oTarget), 5) == "it_gem")
// Only accepts bioware gems & Craftable Natural Resources gems, but not gem dust.
int bIsBioGem = (GetStringLeft(GetResRef(oTarget), 5) == "it_gem");
int bIsCNRGem = (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem");
int bIsDust = (GetStringLeft(GetResRef(oTarget), 10) == "cnrgemdust");
if (!(bIsBioGem || bIsCNRGem) || bIsDust)
{
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
return TRUE;
}
/* if ((GetStringLeft(GetResRef(oTarget), 5) == "it_gem") || (GetStringLeft(GetResRef(oTarget), 6) == "cnrgem") && (GetStringLeft(GetResRef(oTarget), 10) != "cnrgemdust"))
{
FloatingTextStringOnCreature("Spell target is not a valid gem.", oCaster, FALSE);
// And out we go
return TRUE;
}
} */
int nCaster = GetAlternativeCasterLevel(oCaster, PRCGetCasterLevel(oCaster));
int nDC = PRCGetSaveDC(oTarget, oCaster);
@@ -2117,6 +2308,13 @@ int CIGetSpellWasUsedForItemCreation(object oSpellTarget)
// -------------------------------------------------
nRet = CICraftCheckCraftStaff(oSpellTarget,oCaster);
break;
case BASE_ITEM_CRAFTED_SCEPTER :
// -------------------------------------------------
// Craft Scepter
// -------------------------------------------------
nRet = CICraftCheckCraftScepter(oSpellTarget,oCaster);
break;
case BASE_ITEM_MUNDANE_HERB :
// -------------------------------------------------
@@ -2916,7 +3114,12 @@ int GetMagicalArtisanFeat(int nCraftingFeat)
{
nReturn = FEAT_MAGICAL_ARTISAN_CREATE_INFUSION;
break;
}
}
case FEAT_CRAFT_SCEPTER:
{
nReturn = FEAT_MAGICAL_ARTISAN_CRAFT_SCEPTER;
break;
}
default:
{
if(DEBUG) DoDebug("GetMagicalArtisanFeat: invalid crafting feat");

View File

@@ -20,9 +20,6 @@
//:: Last Update: 2003-10-07
//:://////////////////////////////////////////////
//:: Test void
//:: void main (){}
//Changed by primogenitor to include CEP itemtypes
// * The tag of the ip work container, a placeable which has to be set into each
@@ -697,6 +694,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|| nItem == BASE_ITEM_SICKLE
|| nItem == BASE_ITEM_TWOBLADEDSWORD
|| nItem == BASE_ITEM_CLUB
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|| nItem == BASE_ITEM_DAGGER
|| nItem == BASE_ITEM_DIREMACE
|| nItem == BASE_ITEM_HEAVYFLAIL
@@ -729,6 +727,7 @@ if(nItem == BASE_ITEM_BASTARDSWORD
|| nItem == BASE_ITEM_ELVEN_THINBLADE
|| nItem == BASE_ITEM_ELVEN_COURTBLADE
|| nItem == BASE_ITEM_CRAFTED_STAFF
|| nItem == BASE_ITEM_CRAFTED_SCEPTER
|| nItem == 300 //CEP Trident
|| nItem == 303 //CEP Sai
|| nItem == 304 //CEP nunchaku
@@ -1612,31 +1611,140 @@ int IPGetDamageBonusConstantFromNumber(int nNumber)
// oOld - Item equipped before polymorphing (source for item props)
// oNew - Item equipped after polymorphing (target for item props)
// bWeapon - Must be set TRUE when oOld is a weapon.
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
{
if (GetIsObjectValid(oOld) && GetIsObjectValid(oNew))
{
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
if (bWeapon)
{
if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
ip = GetNextItemProperty(oOld);
// Invalid source/target
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
return;
// Determine possessor
object oPC = GetItemPossessor(oOld);
if (!GetIsObjectValid(oPC))
oPC = GetItemPossessor(oNew);
}
}
if (!GetIsObjectValid(oPC))
{
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
return;
}
// Determine glove state once
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
// Weapon ranged mismatch = do nothing (intent is no partial copy)
if (bWeapon && GetWeaponRanged(oOld) != GetWeaponRanged(oNew))
{
if (DEBUG) DoDebug("IPWS: Weapon ranged mismatch <20> skipping all IP copy");
return;
}
// Begin property copy
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
int nType = GetItemPropertyType(ip);
// If copying from gloves and monk gloves are active
if (bMonkGloves
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
{
// Always apply glove damage IPs
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
ip = GetNextItemProperty(oOld);
continue;
}
// Normal weapon pass
if (bWeapon)
{
// If monk gloves active ? skip ALL weapon damage IPs
if (bMonkGloves
&& (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP))
{
ip = GetNextItemProperty(oOld);
continue;
}
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
ip = GetNextItemProperty(oOld);
}
}
/* // ----------------------------------------------------------------------------
// GZ, Sept. 30 2003
// Special Version of Copy Item Properties for use with greater wild shape
// oOld - Item equipped before polymorphing (source for item props)
// oNew - Item equipped after polymorphing (target for item props)
// bWeapon - Must be set TRUE when oOld is a weapon.
// ----------------------------------------------------------------------------
void IPWildShapeCopyItemProperties(object oOld, object oNew, int bWeapon = FALSE)
{
if (!GetIsObjectValid(oOld) || !GetIsObjectValid(oNew))
return;
object oPC = GetItemPossessor(oOld);
if (!GetIsObjectValid(oPC))
{
oPC = GetItemPossessor(oNew);
}
if (!GetIsObjectValid(oPC))
{
if (DEBUG) DoDebug("IPWS: Unable to determine item possessor");
return;
}
int bMonkGloves = GetLocalInt(oPC, "WEARING_MONK_GLOVES");
itemproperty ip = GetFirstItemProperty(oOld);
while (GetIsItemPropertyValid(ip))
{
if (bWeapon)
{
// Gloves override weapon damage <20> skip weapon damage properties
if (bMonkGloves)
{
int nType = GetItemPropertyType(ip);
// skip damage props
if (nType == ITEM_PROPERTY_DAMAGE_BONUS
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP
|| nType == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP)
{
if (DEBUG) DoDebug("IPWS: SKIPPED weapon damage IP");
}
else
{
if (DEBUG) DoDebug("IPWS: Applied non-damage weapon IP");
AddItemProperty(DURATION_TYPE_PERMANENT, ip, oNew);
}
}
else if (GetWeaponRanged(oOld) == GetWeaponRanged(oNew) )
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
}
else
{
AddItemProperty(DURATION_TYPE_PERMANENT,ip,oNew);
}
ip = GetNextItemProperty(oOld);
}
} */
// ----------------------------------------------------------------------------
// Returns the current enhancement bonus of a weapon (+1 to +20), 0 if there is
// no enhancement bonus. You can test for a specific type of enhancement bonus
@@ -2018,4 +2126,6 @@ int IPOnHitSaveDC(int nSaveDC)
if (nSaveDC > 26) nIPBonus = IP_CONST_ONHIT_SAVEDC_26;
return nIPBonus;
} */
} */
//:: void main(){}

View File

@@ -73,6 +73,7 @@ void SetMasteryOfElements();
//#include "lookup_2da_spell"
#include "prcsp_reputation"
#include "prc_inc_core"
//#include "prc_inc_spells"

View File

@@ -11,6 +11,7 @@
#include "prc_ipfeat_const"
#include "prc_feat_const"
#include "inc_vfx_const"
#include "prc_inc_nwscript"
//////////////////////////////////////////////////

View File

@@ -41,6 +41,8 @@ const int POWER_LIST_WARMIND = CLASS_TYPE_WARMIND;
/* Function prototypes */
//////////////////////////////////////////////////
int IsHiddenTalent(object oPC = OBJECT_SELF);
/**
* Attempts to use psionic focus. If the creature was focused, it
* loses the focus. If it has Epic Psionic Focus feats, it will
@@ -520,9 +522,9 @@ void GainPsionicFocus(object oGainee = OBJECT_SELF)
{
int nPsySneak = 1;
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_2d6, oGainee))
nPsySneak += 2;
nPsySneak += 1;
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_3d6, oGainee))
nPsySneak += 3;
nPsySneak += 1;
SetLocalInt(oGainee, "PsyRogueSneak",nPsySneak);
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oGainee));
@@ -786,69 +788,12 @@ int GetIsPsionicCharacter(object oCreature)
GetHasFeat(FEAT_KALASHTAR_PP, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_1, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_2, oCreature) ||
GetHasFeat(FEAT_NATPSIONIC_3, oCreature)
GetHasFeat(FEAT_NATPSIONIC_3, oCreature) ||
IsHiddenTalent(oCreature)
// Racial psionicity signifying feats go here
);
}
int IsHiddenTalent(object oPC = OBJECT_SELF)
{
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
{
return TRUE;
}
else
{
return FALSE;
}
}
void LocalCleanExtraFists(object oCreature)
{
int iIsCWeap, iIsEquip;
@@ -985,6 +930,48 @@ int PracticedManifesting(object oManifester, int iManifestingClass, int iManifes
int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVALID, int nMaxPowerLevel = FALSE)
{
// Handle POWER_LIST_MISC (Hidden Talent) powers
// Check if this is a power list call
int nPowerType = GetLocalInt(oManifester, "PRC_UsePowerList");
if(nSpecificClass == CLASS_TYPE_INVALID && nPowerType == POWER_LIST_MISC)
{
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: CLASS_TYPE_INVALID + POWER_LIST_MISC found!");
// Check if character has psionic class levels
int nPsionLevel = GetLevelByClass(CLASS_TYPE_PSION, oManifester);
int nPsywarLevel = GetLevelByClass(CLASS_TYPE_PSYWAR, oManifester);
int nWilderLevel = GetLevelByClass(CLASS_TYPE_WILDER, oManifester);
int nWarmindLevel = GetLevelByClass(CLASS_TYPE_WARMIND, oManifester);
int nFistOfZuokenLevel = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oManifester);
int nPsychicRogueLevel = GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE, oManifester);
// If no psionic levels, use Charisma-based calculation (treat as 1st level)
if(nPsionLevel + nPsywarLevel + nWilderLevel + nWarmindLevel +
nFistOfZuokenLevel + nPsychicRogueLevel == 0)
{
// Hidden Talent: considered 1st-level manifester, but must have CHA 11+
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: Hidden Talent found!");
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
return 1;
else
return 0; // Cannot manifest without CHA 11+
}
if(DEBUG) DoDebug("psi_inc_core >> GetManifesterLevel: nSpecificClass=" + IntToString(nSpecificClass) +
", nPowerType=" + IntToString(nPowerType));
// Has psionic levels - return highest manifester level
int nHighest = 0;
if(nPsionLevel > 0) nHighest = GetManifesterLevel(oManifester, CLASS_TYPE_PSION);
if(nPsywarLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYWAR));
if(nWilderLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WILDER));
if(nWarmindLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_WARMIND));
if(nFistOfZuokenLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_FIST_OF_ZUOKEN));
if(nPsychicRogueLevel > 0) nHighest = PRCMax(nHighest, GetManifesterLevel(oManifester, CLASS_TYPE_PSYCHIC_ROGUE));
return nHighest;
}
int nLevel;
int nAdjust = GetLocalInt(oManifester, PRC_CASTERLEVEL_ADJUSTMENT);
nAdjust -= GetLocalInt(oManifester, "WoLManifPenalty");
@@ -1049,17 +1036,27 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
DelayCommand(1.0, DeleteLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE));
nLevel = GetLocalInt(oManifester, PRC_CASTERLEVEL_OVERRIDE);
}
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
{
//Gets the manifesting class
int nManifestingClass = GetManifestingClass(oManifester);
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
nLevel = GetLevelByClass(nManifestingClass, oManifester);
// Add levels from +ML PrCs only for the first manifesting class
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
//nLevel += nManifestingClass == GetPrimaryPsionicClass(oManifester) ? GetPsionicPRCLevels(oManifester) : 0;
}
else if(GetManifestingClass(oManifester) != CLASS_TYPE_INVALID)
{
//Gets the manifesting class
int nManifestingClass = GetManifestingClass(oManifester);
if(DEBUG) DoDebug("Manifesting Class #2: " + IntToString(nManifestingClass), oManifester);
nLevel = GetLevelByClass(nManifestingClass, oManifester);
// Add levels from +ML PrCs only for the first manifesting class
nLevel += GetPsionicPRCLevels(oManifester, nManifestingClass);
// CHECK: If this is Hidden Talent and character has no levels, set to 1
if(nLevel == 0 && GetLocalInt(oManifester, "PRC_UsePowerList") == TRUE &&
GetLocalInt(oManifester, "PRC_PowerListType") == POWER_LIST_MISC)
{
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
{
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent with no psionic levels, returning 1");
nLevel = 1;
}
}
// Psionic vestiges are tucked in here to override things.
// This assumes that there will never be a psion with this spell effect manifesting things
if (nManifestingClass == CLASS_TYPE_PSION && GetHasSpellEffect(VESTIGE_ARETE, oManifester) && !nMaxPowerLevel)
@@ -1085,7 +1082,37 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
// if(DEBUG) DoDebug("Level gotten via GetLevelByClass: " + IntToString(nLevel), oManifester);
}
// If you have a primary psionic class and no manifester level yet, get levels based on that
// If you have a primary psionic class and no manifester level yet, get levels based on that
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
{
int nClass = GetPrimaryPsionicClass(oManifester);
nLevel = GetLevelByClass(nClass, oManifester);
nLevel += GetPsionicPRCLevels(oManifester, nClass);
nLevel += PracticedManifesting(oManifester, nClass, nLevel);
}
// If everything else fails, check for Hidden Talent before returning 0
if(nLevel == 0)
{
// Check if this is a Hidden Talent power
if(GetLocalInt(oManifester, "PRC_UsePowerList") == POWER_LIST_MISC)
{
// Hidden Talent: manifester level is 1 if they have CHA 11+
if(GetAbilityScore(oManifester, ABILITY_CHARISMA) >= 11)
{
if(DEBUG) DoDebug("GetManifesterLevel: Hidden Talent character, returning level 1");
return 1;
}
}
if(DEBUG) DoDebug("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
//else WriteTimestampedLogEntry("Failed to get manifester level for creature " + DebugObject2Str(oManifester) + ", using first class slot");
return 0;
}
/* // If you have a primary psionic class and no manifester level yet, get levels based on that
if (GetPrimaryPsionicClass(oManifester) && nLevel == 0)
{
int nClass = GetPrimaryPsionicClass(oManifester);
@@ -1102,7 +1129,7 @@ int GetManifesterLevel(object oManifester, int nSpecificClass = CLASS_TYPE_INVAL
return 0;
}
*/
// The bonuses inside only apply to normal manifestation
if(!GetLocalInt(oManifester, PRC_IS_PSILIKE))
@@ -1665,4 +1692,225 @@ int GetMaxPowerLevel(object oManifester)
int nMax = StringToInt(Get2DACache(sFile, "MaxPowerLevel", nLevel));
if (DEBUG) DoDebug("GetMaxPowerLevel is "+IntToString(nMax));
return nMax;
}
}
//////////////////////////////////////////////////////
/* START HIDDEN TALENT */
//////////////////////////////////////////////////////
int IsHiddenTalent(object oPC = OBJECT_SELF)
{
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC) ||
//GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC) ||
GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC))
{
return TRUE;
}
else
{
return FALSE;
}
}
int GetHiddenTalentPowerFromFeat(int nFeatID)
{
// Map Hidden Talent feats to their corresponding power IDs
// Using the same mappings as GetIsHiddenTalentPower()
if(nFeatID == FEAT_HIDDEN_TALENT_BIOFEEDBACK) return POWER_BIOFEEDBACK;
if(nFeatID == FEAT_HIDDEN_TALENT_BITE_WOLF) return POWER_BITE_WOLF;
if(nFeatID == FEAT_HIDDEN_TALENT_BOLT) return POWER_BOLT;
if(nFeatID == FEAT_HIDDEN_TALENT_BURST) return POWER_BURST;
if(nFeatID == FEAT_HIDDEN_TALENT_CALLTOMIND) return POWER_CALLTOMIND;
if(nFeatID == FEAT_HIDDEN_TALENT_CALL_WEAPONRY) return POWER_CALL_WEAPONRY;
if(nFeatID == FEAT_HIDDEN_TALENT_CHAMELEON) return POWER_CHAMELEON;
if(nFeatID == FEAT_HIDDEN_TALENT_CLAWS_BEAST) return POWER_CLAWS_BEAST;
if(nFeatID == FEAT_HIDDEN_TALENT_COMPRESSION) return POWER_COMPRESSION;
if(nFeatID == FEAT_HIDDEN_TALENT_CONCEALTHOUGHT) return POWER_CONCEALTHOUGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_CREATESOUND) return POWER_CREATESOUND;
if(nFeatID == FEAT_HIDDEN_TALENT_CRYSTALSHARD) return POWER_CRYSTALSHARD;
if(nFeatID == FEAT_HIDDEN_TALENT_DAZE) return POWER_DAZE;
if(nFeatID == FEAT_HIDDEN_TALENT_DECELERATION) return POWER_DECELERATION;
if(nFeatID == FEAT_HIDDEN_TALENT_DEFPRECOG) return POWER_DEFPRECOG;
if(nFeatID == FEAT_HIDDEN_TALENT_DEMORALIZE) return POWER_DEMORALIZE;
if(nFeatID == FEAT_HIDDEN_TALENT_DISABLE) return POWER_DISABLE;
if(nFeatID == FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH)return POWER_DISSIPATINGTOUCH;
if(nFeatID == FEAT_HIDDEN_TALENT_DISTRACT) return POWER_DISTRACT;
if(nFeatID == FEAT_HIDDEN_TALENT_ELFSIGHT) return POWER_ELFSIGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_EMPATHY) return POWER_EMPATHY;
if(nFeatID == FEAT_HIDDEN_TALENT_EMPTYMIND) return POWER_EMPTYMIND;
if(nFeatID == FEAT_HIDDEN_TALENT_ENTANGLE) return POWER_ENTANGLE;
if(nFeatID == FEAT_HIDDEN_TALENT_EXPANSION) return POWER_EXPANSION;
if(nFeatID == FEAT_HIDDEN_TALENT_FARHAND) return POWER_FARHAND;
if(nFeatID == FEAT_HIDDEN_TALENT_FORCESCREEN) return POWER_FORCESCREEN;
if(nFeatID == FEAT_HIDDEN_TALENT_GREASE) return POWER_GREASE;
if(nFeatID == FEAT_HIDDEN_TALENT_HAMMER) return POWER_HAMMER;
if(nFeatID == FEAT_HIDDEN_TALENT_INERTIALARMOUR) return POWER_INERTIALARMOUR;
if(nFeatID == FEAT_HIDDEN_TALENT_MATTERAGITATION) return POWER_MATTERAGITATION;
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW) return POWER_METAPHYSICAL_CLAW;
if(nFeatID == FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON) return POWER_METAPHYSICAL_WEAPON;
if(nFeatID == FEAT_HIDDEN_TALENT_MINDTHRUST) return POWER_MINDTHRUST;
if(nFeatID == FEAT_HIDDEN_TALENT_MYLIGHT) return POWER_MYLIGHT;
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRECOG) return POWER_OFFPRECOG;
if(nFeatID == FEAT_HIDDEN_TALENT_OFFPRESC) return POWER_OFFPRESC;
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM) return POWER_PREVENOM;
if(nFeatID == FEAT_HIDDEN_TALENT_PREVENOM_WEAPON) return POWER_PREVENOM_WEAPON;
if(nFeatID == FEAT_HIDDEN_TALENT_SKATE) return POWER_SKATE;
if(nFeatID == FEAT_HIDDEN_TALENT_STOMP) return POWER_STOMP;
if(nFeatID == FEAT_HIDDEN_TALENT_SYNESTHETE) return POWER_SYNESTHETE;
if(nFeatID == FEAT_HIDDEN_TALENT_TELEMPATHICPRO) return POWER_TELEMPATHICPRO;
if(nFeatID == FEAT_HIDDEN_TALENT_THICKSKIN) return POWER_THICKSKIN;
if(nFeatID == FEAT_HIDDEN_TALENT_VIGOR) return POWER_VIGOR;
if(nFeatID == FEAT_HIDDEN_TALENT_GRIP_IRON) return POWER_GRIP_IRON;
return -1; // Not found
}
int GetHiddenTalentCount(object oPC = OBJECT_SELF)
{
int nCount = 0;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) nCount++;
//if (GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC))nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) nCount++;
if (GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) nCount++;
return nCount;
}
int GetIsHiddenTalentPower(object oPC, int nPower)
{
// Check each Hidden Talent feat to see if it grants this power
if(nPower == POWER_BIOFEEDBACK && GetHasFeat(FEAT_HIDDEN_TALENT_BIOFEEDBACK, oPC)) return TRUE;
if(nPower == POWER_BITE_WOLF && GetHasFeat(FEAT_HIDDEN_TALENT_BITE_WOLF, oPC)) return TRUE;
if(nPower == POWER_BOLT && GetHasFeat(FEAT_HIDDEN_TALENT_BOLT, oPC)) return TRUE;
if(nPower == POWER_BURST && GetHasFeat(FEAT_HIDDEN_TALENT_BURST, oPC)) return TRUE;
if(nPower == POWER_CALLTOMIND && GetHasFeat(FEAT_HIDDEN_TALENT_CALLTOMIND, oPC)) return TRUE;
if(nPower == POWER_CALL_WEAPONRY && GetHasFeat(FEAT_HIDDEN_TALENT_CALL_WEAPONRY, oPC)) return TRUE;
if(nPower == POWER_CHAMELEON && GetHasFeat(FEAT_HIDDEN_TALENT_CHAMELEON, oPC)) return TRUE;
if(nPower == POWER_CLAWS_BEAST && GetHasFeat(FEAT_HIDDEN_TALENT_CLAWS_BEAST, oPC)) return TRUE;
if(nPower == POWER_COMPRESSION && GetHasFeat(FEAT_HIDDEN_TALENT_COMPRESSION, oPC)) return TRUE;
if(nPower == POWER_CONCEALTHOUGHT && GetHasFeat(FEAT_HIDDEN_TALENT_CONCEALTHOUGHT, oPC)) return TRUE;
if(nPower == POWER_CREATESOUND && GetHasFeat(FEAT_HIDDEN_TALENT_CREATESOUND, oPC)) return TRUE;
if(nPower == POWER_CRYSTALSHARD && GetHasFeat(FEAT_HIDDEN_TALENT_CRYSTALSHARD, oPC)) return TRUE;
if(nPower == POWER_DAZE && GetHasFeat(FEAT_HIDDEN_TALENT_DAZE, oPC)) return TRUE;
if(nPower == POWER_DECELERATION && GetHasFeat(FEAT_HIDDEN_TALENT_DECELERATION, oPC)) return TRUE;
if(nPower == POWER_DEFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_DEFPRECOG, oPC)) return TRUE;
if(nPower == POWER_DEMORALIZE && GetHasFeat(FEAT_HIDDEN_TALENT_DEMORALIZE, oPC)) return TRUE;
if(nPower == POWER_DISABLE && GetHasFeat(FEAT_HIDDEN_TALENT_DISABLE, oPC)) return TRUE;
if(nPower == POWER_DISSIPATINGTOUCH && GetHasFeat(FEAT_HIDDEN_TALENT_DISSIPATINGTOUCH, oPC)) return TRUE;
if(nPower == POWER_DISTRACT && GetHasFeat(FEAT_HIDDEN_TALENT_DISTRACT, oPC)) return TRUE;
if(nPower == POWER_ELFSIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_ELFSIGHT, oPC)) return TRUE;
if(nPower == POWER_EMPATHY && GetHasFeat(FEAT_HIDDEN_TALENT_EMPATHY, oPC)) return TRUE;
if(nPower == POWER_EMPTYMIND && GetHasFeat(FEAT_HIDDEN_TALENT_EMPTYMIND, oPC)) return TRUE;
//if(nPower == POWER_ENERGYRAY && GetHasFeat(FEAT_HIDDEN_TALENT_ENERGYRAY, oPC)) return TRUE;
if(nPower == POWER_ENTANGLE && GetHasFeat(FEAT_HIDDEN_TALENT_ENTANGLE, oPC)) return TRUE;
if(nPower == POWER_EXPANSION && GetHasFeat(FEAT_HIDDEN_TALENT_EXPANSION, oPC)) return TRUE;
if(nPower == POWER_FARHAND && GetHasFeat(FEAT_HIDDEN_TALENT_FARHAND, oPC)) return TRUE;
if(nPower == POWER_FORCESCREEN && GetHasFeat(FEAT_HIDDEN_TALENT_FORCESCREEN, oPC)) return TRUE;
if(nPower == POWER_GREASE && GetHasFeat(FEAT_HIDDEN_TALENT_GREASE, oPC)) return TRUE;
if(nPower == POWER_HAMMER && GetHasFeat(FEAT_HIDDEN_TALENT_HAMMER, oPC)) return TRUE;
if(nPower == POWER_INERTIALARMOUR && GetHasFeat(FEAT_HIDDEN_TALENT_INERTIALARMOUR, oPC)) return TRUE;
if(nPower == POWER_MATTERAGITATION && GetHasFeat(FEAT_HIDDEN_TALENT_MATTERAGITATION, oPC)) return TRUE;
if(nPower == POWER_METAPHYSICAL_CLAW && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_CLAW, oPC)) return TRUE;
if(nPower == POWER_METAPHYSICAL_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_METAPHYSICAL_WEAPON, oPC)) return TRUE;
if(nPower == POWER_MINDTHRUST && GetHasFeat(FEAT_HIDDEN_TALENT_MINDTHRUST, oPC)) return TRUE;
if(nPower == POWER_MYLIGHT && GetHasFeat(FEAT_HIDDEN_TALENT_MYLIGHT, oPC)) return TRUE;
if(nPower == POWER_OFFPRECOG && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRECOG, oPC)) return TRUE;
if(nPower == POWER_OFFPRESC && GetHasFeat(FEAT_HIDDEN_TALENT_OFFPRESC, oPC)) return TRUE;
if(nPower == POWER_PREVENOM && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM, oPC)) return TRUE;
if(nPower == POWER_PREVENOM_WEAPON && GetHasFeat(FEAT_HIDDEN_TALENT_PREVENOM_WEAPON, oPC)) return TRUE;
if(nPower == POWER_SKATE && GetHasFeat(FEAT_HIDDEN_TALENT_SKATE, oPC)) return TRUE;
if(nPower == POWER_STOMP && GetHasFeat(FEAT_HIDDEN_TALENT_STOMP, oPC)) return TRUE;
if(nPower == POWER_SYNESTHETE && GetHasFeat(FEAT_HIDDEN_TALENT_SYNESTHETE, oPC)) return TRUE;
if(nPower == POWER_TELEMPATHICPRO && GetHasFeat(FEAT_HIDDEN_TALENT_TELEMPATHICPRO, oPC)) return TRUE;
if(nPower == POWER_THICKSKIN && GetHasFeat(FEAT_HIDDEN_TALENT_THICKSKIN, oPC)) return TRUE;
if(nPower == POWER_VIGOR && GetHasFeat(FEAT_HIDDEN_TALENT_VIGOR, oPC)) return TRUE;
if(nPower == POWER_GRIP_IRON && GetHasFeat(FEAT_HIDDEN_TALENT_GRIP_IRON, oPC)) return TRUE;
return FALSE;
}

View File

@@ -110,6 +110,7 @@ object GetSplitPsionicRayTarget(struct manifestation manif, object oPrimaryTarge
//////////////////////////////////////////////////
#include "psi_inc_core"
#include "psi_inc_psifunc"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -572,7 +572,11 @@ int GetMaxPowerCount(object oCreature, int nList)
int GetHasPower(int nPower, object oCreature = OBJECT_SELF)
{
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
// Check MISC list first (for Hidden Talent and similar feats)
if(GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_INVALID), oCreature))
return TRUE;
if((GetLevelByClass(CLASS_TYPE_PSION, oCreature)
&& GetHasFeat(GetClassFeatFromPower(nPower, CLASS_TYPE_PSION), oCreature)
) ||
(GetLevelByClass(CLASS_TYPE_PSYWAR, oCreature)

View File

@@ -93,9 +93,8 @@ void GainPowerPoints(object oChar, int nGain, int bCanExceedMax = FALSE, int bIn
* @param bInform If TRUE, runs TellCharacterPowerPointStatus() on oChar
* after making the modification.
*/
/*
void GainTemporaryPowerPoints(object oChar, int nGain, float fDuration, int bInform = TRUE);
*/
/**
* Decreases the character's current power point count by up to the given
* amount, limited to not going below 0.
@@ -138,8 +137,12 @@ int _GetFeatBonusPP(object oChar)
{
int nBonusPP = 0;
//:: Wild Talent & Hidden Talents
if(GetHasFeat(FEAT_WILD_TALENT, oChar) || IsHiddenTalent())
//:: Wild Talent
if(GetHasFeat(FEAT_WILD_TALENT, oChar))
nBonusPP += 2;
//:: Hidden Talent
if(GetHasFeat(FEAT_HIDDEN_TALENT, oChar))
nBonusPP += 2;
//:: Psionic Feats

View File

@@ -40,7 +40,8 @@ void IdentifyPower(object oManifester, int nPowerId);
// Always access via psi_inc_psifunc.
//#include "psi_inc_core"
#include "psi_inc_core"
#include "inc_2dacache"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -407,6 +407,8 @@ void _CleanManifestationVariables(object oManifester)
DeleteLocalInt(oManifester, PRC_POWER_LEVEL);
DeleteLocalInt(oManifester, PRC_IS_PSILIKE);
DeleteLocalInt(oManifester, PRC_AUGMENT_OVERRIDE);
DeleteLocalInt(oManifester, "PRC_UsePowerList");
DeleteLocalInt(oManifester, "PRC_PowerListType");
}
/** Internal function.
@@ -692,10 +694,28 @@ void _UsePowerAux(object oManifester, object oMfToken, int nSpellId,
struct manifestation EvaluateManifestation(object oManifester, object oTarget, struct power_augment_profile pap, int nMetaPsiFlags)
{
/* Get some data */
//:: Handle Hidden Talent
int nSpellID = PRCGetSpellId();
int bIsHiddenTalent = GetIsHiddenTalentPower(oManifester, nSpellID);
if(bIsHiddenTalent)
{
SetLocalInt(oManifester, "PRC_UsePowerList", TRUE);
SetLocalInt(oManifester, "PRC_PowerListType", POWER_LIST_MISC);
}
/* Get some data */
int bIgnoreConstraints = (DEBUG) ? GetLocalInt(oManifester, PRC_DEBUG_IGNORE_CONSTRAINTS) : FALSE;
// Manifester-related stuff
int nManifesterLevel = GetManifesterLevel(oManifester);
//int nManifesterLevel = GetManifesterLevel(oManifester);
int nManifesterLevel;
if(bIsHiddenTalent)
{
nManifesterLevel = GetManifesterLevel(oManifester, CLASS_TYPE_INVALID);
}
else
{
nManifesterLevel = GetManifesterLevel(oManifester);
}
int nPowerLevel = GetPowerLevel(oManifester);
int nClass = GetManifestingClass(oManifester);
int nWildSurge = GetWildSurge(oManifester);
@@ -714,6 +734,8 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
manif.nManifesterLevel = nManifesterLevel;
manif.nSpellID = PRCGetSpellId();
// Run an ability score check to see if the manifester can manifest the power at all
if (bIsPsiLike)
{
@@ -767,7 +789,9 @@ struct manifestation EvaluateManifestation(object oManifester, object oTarget, s
//If the manifester does not have enough points before hostile modifiers, cancel power
if(manif.nPPCost > nManifesterPP && !bIsPsiLike && !bIgnoreConstraints)
{
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
// DEBUG: show why the cost over cap branch triggered
FloatingTextStringOnCreature("DEBUG: manif.nManifesterLevel=" + IntToString(manif.nManifesterLevel) + " manif.nPPCost=" + IntToString(manif.nPPCost) +" PRC_UsePowerList=" + IntToString(GetLocalInt(manif.oManifester, "PRC_UsePowerList")), manif.oManifester, FALSE);
FloatingTextStrRefOnCreature(16826412, oManifester, FALSE); // "You do not have enough Power Points to manifest this power"
manif.bCanManifest = FALSE;
}
// The manifester has enough power points that they would be able to use the power, barring extra costs

View File

@@ -14,6 +14,7 @@
#include "prc_class_const"
*/
#include "prc_alterations"
#include "prcsp_engine"
// Constants that dictate ResistPower results
const int POWER_RESIST_FAIL = 1;

View File

@@ -75,6 +75,15 @@ int PsiPrePowerCastCode()
int nContinue = !ExecuteScriptAndReturnInt("prespellcode", oManifester);
//---------------------------------------------------------------------------
// Forsakers can't use psionics
//---------------------------------------------------------------------------
if (nContinue && GetLevelByClass(CLASS_TYPE_FORSAKER, oManifester))
{
FloatingTextStringOnCreature("Forsakers cannot manifest psionic powers!", oManifester, FALSE);
nContinue = FALSE;
}
//---------------------------------------------------------------------------
// Break any spell require maintaining concentration
//---------------------------------------------------------------------------
@@ -209,3 +218,4 @@ int PsiPrePowerCastCode()
return nContinue;
}
//:: void main (){}

View File

@@ -192,7 +192,8 @@ int PathFeatToIPFeat(int nFeat);
/* Includes */
//////////////////////////////////////////////////
#include "inc_lookups"
#include "inc_pers_array"
//////////////////////////////////////////////////
/* Internal functions */
@@ -519,7 +520,7 @@ int GetMaxMysteryLevelLearnable(object oShadow, int nClass, int nType)
if(DEBUG) DoDebug("GetMaxMysteryLevelLearnable nType: " + IntToString(nType));
// Rules Quote:
// Within a category<72>Apprentice, Initiate, Master<65>you must have at least two mysteries of any given level
// Within a category<72>Apprentice, Initiate, Master<65>you must have at least two mysteries of any given level
// before you can take any mysteries of the next higher level. For instance, you must have two 1st-level
// mysteries before you can take any 2nds, and at least two 2nds before you can take any 3rds.
int nMaxLrn, i, nMystLevel, nCount1, nCount2;

View File

@@ -210,6 +210,7 @@ int GetHasNocturnal(object oShadow, int nPath);
#include "prc_alterations"
#include "shd_inc_myst"
#include "shd_inc_mystknwn"
#include "lookup_2da_spell"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -17,6 +17,8 @@
#include "prc_inc_spells"
#include "inc_utility"
#include "prc_inc_itmrstr"
#include "shd_inc_shdfunc"
#include "lookup_2da_spell"
// This function holds all functions that are supposed to run before the actual
// spellscript gets run. If this functions returns FALSE, the spell is aborted
@@ -132,6 +134,15 @@ int ShadPreMystCastCode()
int nContinue = !ExecuteScriptAndReturnInt("prespellcode",oShadow);
//---------------------------------------------------------------------------
// Block forsakers from using shadowcasting
//---------------------------------------------------------------------------
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oShadow) > 0)
{
SendMessageToPC(oShadow, "Forsakers cannot use the power of shadowcasting.");
return FALSE;
}
//---------------------------------------------------------------------------
// Break any spell require maintaining concentration
//---------------------------------------------------------------------------
@@ -277,4 +288,6 @@ int ShadPreMystCastCode()
if(DEBUG) DoDebug("ShadPreMystCastCode nContinue #6: " + IntToString(nContinue));
return nContinue;
}
}
//:: void main (){}

View File

@@ -14,6 +14,7 @@
#include "prc_inc_spells"
#include "inc_utility"
#include "x2_inc_spellhook"
#include "tob_inc_tobfunc"
// This function holds all functions that are supposed to run before the actual
// spellscript gets run. If this functions returns FALSE, the spell is aborted
@@ -78,7 +79,14 @@ int PreManeuverCastCode()
//---------------------------------------------------------------------------
if(nContinue)
nContinue = !GetLocalInt(oInitiator, "CrusaderBreak");
//---------------------------------------------------------------------------
// Forsakers can't use supernatural maneuvers
//---------------------------------------------------------------------------
if (nContinue && GetIsManeuverSupernatural(nMoveId) && GetLevelByClass(CLASS_TYPE_FORSAKER, oInitiator))
{
FloatingTextStringOnCreature("Forsakers cannot use supernatural maneuvers!", oInitiator, FALSE);
nContinue = FALSE;
}
//---------------------------------------------------------------------------
// Run NullPsionicsField Check
//---------------------------------------------------------------------------

View File

@@ -109,11 +109,14 @@ int GetIsSyllable(int nSpellId);
*/
int DoSpellTruenameCheck(object oTrueSpeaker, object oTarget, int nPersonal = FALSE);
string GetNormalUtterSpellId(int nSpellId);
//////////////////////////////////////////////////
/* Includes */
//////////////////////////////////////////////////
#include "prc_inc_spells"
#include "true_inc_trufunc"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -260,6 +260,7 @@ int GetCadenceCount(object oTrueSpeaker);
#include "prc_alterations"
#include "true_inc_utter"
#include "true_inc_truknwn"
#include "true_inc_truespk"
//////////////////////////////////////////////////
/* Function definitions */

View File

@@ -141,6 +141,7 @@ int GetHasUtterance(int nUtter, object oCreature = OBJECT_SELF);
#include "inc_pers_array"
#include "prc_inc_nwscript"
#include "inc_lookups"
#include "prc_x2_itemprop"
//////////////////////////////////////////////////
/* Internal functions */

View File

@@ -18,6 +18,7 @@
#include "prc_inc_spells"
#include "inc_utility"
#include "prc_inc_itmrstr"
#include "true_inc_trufunc"
// This function holds all functions that are supposed to run before the actual
@@ -42,6 +43,16 @@ int TruePreUtterCastCode()
int nContinue = !ExecuteScriptAndReturnInt("prespellcode",oTrueSpeaker);
//---------------------------------------------------------------------------
// Block forsakers from using truenaming
//---------------------------------------------------------------------------
if(GetLevelByClass(CLASS_TYPE_FORSAKER, oTrueSpeaker) > 0)
{
SendMessageToPC(oTrueSpeaker, "Forsakers cannot use the power of truenaming.");
return FALSE;
}
//---------------------------------------------------------------------------
// Break any spell require maintaining concentration
//---------------------------------------------------------------------------

View File

@@ -2902,7 +2902,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
int nType = GetBaseItemType(oSpellCastItem);
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND) // Has to be a wand, obv
if(nType == BASE_ITEM_MAGICWAND || nType == BASE_ITEM_ENCHANTED_WAND || nType == BASE_ITEM_CRAFTED_SCEPTER) // Has to be a wand, obv
{
if(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCaster) == oSpellCastItem || GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCaster) == oSpellCastItem) // Needs to be equipped
{
@@ -2910,7 +2910,7 @@ int WandEquipped(object oCaster, object oSpellCastItem)
}
else
{
FloatingTextStringOnCreature("You must equip a wand to cast from it.", oCaster, FALSE);
FloatingTextStringOnCreature("You must equip this item to cast from it.", oCaster, FALSE);
return FALSE; // It's a wand not equipped
}
}

View File

@@ -24,6 +24,7 @@
#include "x0_i0_position"
#include "X0_INC_HENAI"
#include "x3_inc_skin"
#include "prc_racial_const"
/*
@@ -638,7 +639,7 @@ int HorseGetMountTail(object oHorse);
// FILE: x3_inc_horse FUNCTION: HorseGetMountFailureMessage()
// This is a companion function to HorseGetCanBeMounted. If you need a text
// message that explains why the horse cannot be mounted.
string HorseGetMountFailureMessage(object oTarget,object oRider=OBJECT_INVALID);
string HorseGetMountFailureMessage(object oHorse,object oRider=OBJECT_INVALID);
// FILE: x3_inc_horse FUNCTION: HorseAddHorseMenu()
@@ -1050,6 +1051,8 @@ void HORSE_SupportOriginalSpeed(object oRider)
} // check to see if matches conditions
eSearch=GetNextEffect(oRider);
} // cycle through effects
} // HORSE_SupportOriginalSpeed()

View File

@@ -56,7 +56,50 @@
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTRUE"
},
"Value": {
"type": "cexostring",
"value": "0"
}
}
]
},
"Index": {
"type": "dword",
"value": 248
},
"IsChild": {
"type": "byte",
"value": 0
}
},
{
"__struct_id": 1,
"Active": {
"type": "resref",
"value": "0c_if_scout"
},
"ConditionParams": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTRUE"
},
"Value": {
"type": "cexostring",
"value": "1"
}
}
]
},
"Index": {
"type": "dword",
@@ -68,7 +111,7 @@
}
},
{
"__struct_id": 1,
"__struct_id": 2,
"Active": {
"type": "resref",
"value": "0c_if_identify"
@@ -87,7 +130,7 @@
}
},
{
"__struct_id": 2,
"__struct_id": 3,
"Active": {
"type": "resref",
"value": "0c_if_open_inven"
@@ -106,7 +149,7 @@
}
},
{
"__struct_id": 3,
"__struct_id": 4,
"Active": {
"type": "resref",
"value": ""
@@ -125,7 +168,7 @@
}
},
{
"__struct_id": 4,
"__struct_id": 5,
"Active": {
"type": "resref",
"value": "0c_if_has_class"
@@ -199,103 +242,6 @@
"value": 0
}
},
{
"__struct_id": 5,
"Active": {
"type": "resref",
"value": "0c_if_has_class"
},
"ConditionParams": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nClass1"
},
"Value": {
"type": "cexostring",
"value": "1"
}
},
{
"__struct_id": 1,
"Key": {
"type": "cexostring",
"value": "nClass2"
},
"Value": {
"type": "cexostring",
"value": "2"
}
},
{
"__struct_id": 2,
"Key": {
"type": "cexostring",
"value": "nClass3"
},
"Value": {
"type": "cexostring",
"value": "3"
}
},
{
"__struct_id": 3,
"Key": {
"type": "cexostring",
"value": "nClass4"
},
"Value": {
"type": "cexostring",
"value": "9"
}
},
{
"__struct_id": 4,
"Key": {
"type": "cexostring",
"value": "nClass5"
},
"Value": {
"type": "cexostring",
"value": "10"
}
},
{
"__struct_id": 5,
"Key": {
"type": "cexostring",
"value": "nClass6"
},
"Value": {
"type": "cexostring",
"value": "47"
}
},
{
"__struct_id": 6,
"Key": {
"type": "cexostring",
"value": "nClass7"
},
"Value": {
"type": "cexostring",
"value": "48"
}
}
]
},
"Index": {
"type": "dword",
"value": 109
},
"IsChild": {
"type": "byte",
"value": 0
}
},
{
"__struct_id": 6,
"Active": {
@@ -386,7 +332,7 @@
},
"Index": {
"type": "dword",
"value": 77
"value": 109
},
"IsChild": {
"type": "byte",
@@ -399,6 +345,103 @@
"type": "resref",
"value": "0c_if_has_class"
},
"ConditionParams": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nClass1"
},
"Value": {
"type": "cexostring",
"value": "1"
}
},
{
"__struct_id": 1,
"Key": {
"type": "cexostring",
"value": "nClass2"
},
"Value": {
"type": "cexostring",
"value": "2"
}
},
{
"__struct_id": 2,
"Key": {
"type": "cexostring",
"value": "nClass3"
},
"Value": {
"type": "cexostring",
"value": "3"
}
},
{
"__struct_id": 3,
"Key": {
"type": "cexostring",
"value": "nClass4"
},
"Value": {
"type": "cexostring",
"value": "9"
}
},
{
"__struct_id": 4,
"Key": {
"type": "cexostring",
"value": "nClass5"
},
"Value": {
"type": "cexostring",
"value": "10"
}
},
{
"__struct_id": 5,
"Key": {
"type": "cexostring",
"value": "nClass6"
},
"Value": {
"type": "cexostring",
"value": "47"
}
},
{
"__struct_id": 6,
"Key": {
"type": "cexostring",
"value": "nClass7"
},
"Value": {
"type": "cexostring",
"value": "48"
}
}
]
},
"Index": {
"type": "dword",
"value": 77
},
"IsChild": {
"type": "byte",
"value": 0
}
},
{
"__struct_id": 8,
"Active": {
"type": "resref",
"value": "0c_if_has_class"
},
"ConditionParams": {
"type": "list",
"value": [
@@ -502,7 +545,7 @@
}
},
{
"__struct_id": 8,
"__struct_id": 9,
"Active": {
"type": "resref",
"value": ""
@@ -521,7 +564,7 @@
}
},
{
"__struct_id": 9,
"__struct_id": 10,
"Active": {
"type": "resref",
"value": ""
@@ -540,7 +583,7 @@
}
},
{
"__struct_id": 10,
"__struct_id": 11,
"Active": {
"type": "resref",
"value": "0c_if_hen_leave"
@@ -559,7 +602,7 @@
}
},
{
"__struct_id": 11,
"__struct_id": 12,
"Active": {
"type": "resref",
"value": "0c_if_convo"
@@ -578,7 +621,7 @@
}
},
{
"__struct_id": 12,
"__struct_id": 13,
"Active": {
"type": "resref",
"value": ""
@@ -6591,7 +6634,19 @@
"__struct_id": 20,
"ActionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "sAction"
},
"Value": {
"type": "cexostring",
"value": "GetHenchTokens"
}
}
]
},
"Animation": {
"type": "dword",
@@ -6696,11 +6751,23 @@
"__struct_id": 4,
"Active": {
"type": "resref",
"value": "x2_d1_hashench1"
"value": "0c_if_hen_target"
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTarget"
},
"Value": {
"type": "cexostring",
"value": "3"
}
}
]
},
"Index": {
"type": "dword",
@@ -6715,11 +6782,23 @@
"__struct_id": 5,
"Active": {
"type": "resref",
"value": "x2_d1_hashench2"
"value": "0c_if_hen_target"
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTarget"
},
"Value": {
"type": "cexostring",
"value": "4"
}
}
]
},
"Index": {
"type": "dword",
@@ -6734,11 +6813,23 @@
"__struct_id": 6,
"Active": {
"type": "resref",
"value": "x2_d1_hashench3"
"value": "0c_if_hen_target"
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTarget"
},
"Value": {
"type": "cexostring",
"value": "5"
}
}
]
},
"Index": {
"type": "dword",
@@ -6753,11 +6844,23 @@
"__struct_id": 7,
"Active": {
"type": "resref",
"value": "x2_d1_hashench4"
"value": "0c_if_hen_target"
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "nTarget"
},
"Value": {
"type": "cexostring",
"value": "6"
}
}
]
},
"Index": {
"type": "dword",
@@ -6795,7 +6898,7 @@
},
"Script": {
"type": "resref",
"value": "x2_d1_gentags"
"value": "0c_assoc_actions"
},
"Sound": {
"type": "resref",
@@ -8530,6 +8633,55 @@
"type": "list",
"value": []
},
"Animation": {
"type": "dword",
"value": 0
},
"AnimLoop": {
"type": "byte",
"value": 1
},
"Comment": {
"type": "cexostring",
"value": ""
},
"Delay": {
"type": "dword",
"value": 0
},
"Quest": {
"type": "cexostring",
"value": ""
},
"RepliesList": {
"type": "list",
"value": []
},
"Script": {
"type": "resref",
"value": ""
},
"Sound": {
"type": "resref",
"value": ""
},
"Speaker": {
"type": "cexostring",
"value": ""
},
"Text": {
"type": "cexolocstring",
"value": {
"0": ""
}
}
},
{
"__struct_id": 29,
"ActionParams": {
"type": "list",
"value": []
},
"Animation": {
"type": "dword",
"value": 29
@@ -8565,7 +8717,7 @@
},
"Index": {
"type": "dword",
"value": 249
"value": 250
},
"IsChild": {
"type": "byte",
@@ -8584,7 +8736,7 @@
},
"Index": {
"type": "dword",
"value": 248
"value": 249
},
"IsChild": {
"type": "byte",
@@ -8616,7 +8768,7 @@
},
"NumWords": {
"type": "dword",
"value": 1148
"value": 1152
},
"PreventZoomIn": {
"type": "byte",
@@ -27034,12 +27186,69 @@
"Text": {
"type": "cexolocstring",
"value": {
"0": "I would like you to scout the area."
"0": "Would you stop patroling ahead."
}
}
},
{
"__struct_id": 248,
"ActionParams": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "sAction"
},
"Value": {
"type": "cexostring",
"value": "Scout"
}
}
]
},
"Animation": {
"type": "dword",
"value": 0
},
"AnimLoop": {
"type": "byte",
"value": 1
},
"Comment": {
"type": "cexostring",
"value": ""
},
"Delay": {
"type": "dword",
"value": 4294967295
},
"EntriesList": {
"type": "list",
"value": []
},
"Quest": {
"type": "cexostring",
"value": ""
},
"Script": {
"type": "resref",
"value": "0c_assoc_actions"
},
"Sound": {
"type": "resref",
"value": ""
},
"Text": {
"type": "cexolocstring",
"value": {
"0": "I would like you to patrol ahead."
}
}
},
{
"__struct_id": 249,
"ActionParams": {
"type": "list",
"value": []
@@ -27084,7 +27293,7 @@
}
},
{
"__struct_id": 249,
"__struct_id": 250,
"ActionParams": {
"type": "list",
"value": []
@@ -27141,7 +27350,46 @@
},
"ConditionParams": {
"type": "list",
"value": []
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "sInput"
},
"Value": {
"type": "cexostring",
"value": "Can_Hire_Henchman"
}
}
]
},
"Index": {
"type": "dword",
"value": 29
}
},
{
"__struct_id": 1,
"Active": {
"type": "resref",
"value": "0c_if_not_master"
},
"ConditionParams": {
"type": "list",
"value": [
{
"__struct_id": 0,
"Key": {
"type": "cexostring",
"value": "sInput"
},
"Value": {
"type": "cexostring",
"value": "Cannot_Hire_Henchman"
}
}
]
},
"Index": {
"type": "dword",
@@ -27149,7 +27397,7 @@
}
},
{
"__struct_id": 1,
"__struct_id": 2,
"Active": {
"type": "resref",
"value": "0c_if_ass_convo"

View File

@@ -904,7 +904,7 @@
},
"Mod_OnPlrGuiEvt": {
"type": "resref",
"value": ""
"value": "prc_onplayergui"
},
"Mod_OnPlrLvlUp": {
"type": "resref",

View File

@@ -17,10 +17,21 @@ void main()
// 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);
if(ai_GetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD))
{
ai_ClearCreatureActions();
ai_HaveCreatureSpeak(oAssociate, 6, ":29:35:46:10");
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, FALSE);
ai_SendMessages(GetName(oAssociate) + " has stopped patrolling ahead.", AI_COLOR_YELLOW, oPC);
}
else
{
ai_ClearCreatureActions();
ai_HaveCreatureSpeak(oAssociate, 6, ":29:35:46:22:");
ai_SetAIMode(oAssociate, AI_MODE_SCOUT_AHEAD, TRUE);
ai_SendMessages(GetName(oAssociate) + " is now patrolling ahead.", AI_COLOR_YELLOW, oPC);
ai_ScoutAhead(oAssociate);
}
}
else if(sAction == "BasicTactics")
{
@@ -168,5 +179,22 @@ void main()
}
return;
}
else if(sAction == "GetHenchTokens")
{
int nCount, nCntr = 1;
object oHenchman = GetHenchman(oPC, nCntr);
while(oHenchman != OBJECT_INVALID && nCntr <= AI_MAX_HENCHMAN)
{
if(oHenchman == OBJECT_INVALID) break;
if(oHenchman != oAssociate)
{
SetCustomToken(77101 + nCount, GetName(oHenchman));
nCount++;
}
oHenchman = GetHenchman(oPC, ++nCntr);
}
ai_SetupAllyTargets(oAssociate, oPC);
return;
}
aiSaveAssociateModesToDb(oPC, oAssociate);
}

View File

@@ -10,9 +10,6 @@ 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);
}

View File

@@ -9,8 +9,10 @@
Allows use of ai_conversation for henchman in other modules.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
#include "nw_inc_gff"
void BeginOriginalHenchmanConversation(string sDialog, object oPC)
{
if(AI_DEBUG) ai_Debug("0c_get_convo", "14", "sDialog: (" + sDialog + ")");
BeginConversation(sDialog, oPC);
}
void main()

View File

@@ -32,6 +32,7 @@ void main()
{
ai_ClearCreatureActions();
object oTarget = GetLocalObject(oCreature, "AI_ALLY_TARGET_" + IntToString(nTarget));
if(AI_DEBUG) ai_Debug("0c_henchmenspell", "36", " nTarget: " + IntToString(nTarget) + " oTarget: " + GetName(oTarget));
if(oTarget != OBJECT_INVALID && ai_CheckAndCastSpell(oCreature, nSpell, 0, 0.0f, oTarget, oPC))
{
DeleteLocalInt(oCreature, "0_SPELL_TO_CAST");

View File

@@ -68,7 +68,7 @@ int StartingConditional()
{
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 " +
SetCustomToken(AI_BASE_CUSTOM_TOKEN + 4, "I'm healing our allies if they go below " +
sHealingIn + " health in combat and " + sHealingOut + " out of combat.");
}
else if(sParam == "Spells")

View File

@@ -0,0 +1,16 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0c_if_assoc_mode
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that checks to see the ally targets have been set for
this number target.
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.
Param:
nTarget - The target to check and see if they are set.
*///////////////////////////////////////////////////////////////////////////////
int StartingConditional()
{
string sTarget = GetScriptParam("nTarget");
return GetIsObjectValid(GetLocalObject(OBJECT_SELF, "AI_ALLY_TARGET_" + sTarget));
}

View File

@@ -5,7 +5,11 @@
Text Appears When script that checks if the speaker is the master of this
henchman.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_constants"
int StartingConditional()
{
return !GetIsObjectValid(GetMaster());
string sInput = GetScriptParam("sInput");
if(sInput == "Can_Hire_Henchman" && AI_ALLOW_TAKING_HENCHMAN) return !GetIsObjectValid(GetMaster());
else if(sInput == "Cannot_Hire_Henchman") return !GetIsObjectValid(GetMaster());
return FALSE;
}

View File

@@ -3,9 +3,14 @@
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Text Appears When script that check if scouting is activated on this server.
Script Param: nTRUE -
if set to 1 then it will pass TRUE if they are in scout mode.
if set to 0 then it will pass TRUE if they are NOT in scout mode.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_associates"
int StartingConditional()
{
return AI_SCOUT_AHEAD_ON;
int nTRUE = StringToInt(GetScriptParam("nTRUE"));
return AI_SCOUT_AHEAD_ON && ai_GetAIMode(OBJECT_SELF, AI_MODE_SCOUT_AHEAD) == nTRUE;
}

View File

@@ -0,0 +1,26 @@
/*//////////////////////////////////////////////////////////////////////////////
Script: 0e_animations
Programmer: Philos
////////////////////////////////////////////////////////////////////////////////
Monster Ambient Animations and Walk Waypoint code.
This code uses the Bioware systems, but can be rewritten to use what ever you
want!
This is called in the nw_c2_default1 - monster heartbeat script.
*///////////////////////////////////////////////////////////////////////////////
#include "x0_i0_anims"
#include "0i_actions"
void main()
{
if(!IsInConversation (OBJECT_SELF))
{
if(GetWalkCondition(NW_WALK_FLAG_CONSTANT)) WalkWayPoints();
if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS)) PlayMobileAmbientAnimations_NonAvian();
else if(GetSpawnInCondition(NW_FLAG_AMBIENT_ANIMATIONS_AVIAN)) PlayMobileAmbientAnimations_Avian();
else if(GetSpawnInCondition(NW_FLAG_IMMOBILE_AMBIENT_ANIMATIONS)) PlayImmobileAmbientAnimations();
else if(GetLocalInt(GetModule(), AI_RULE_WANDER) && GetStandardFactionReputation(STANDARD_FACTION_HOSTILE) > 89)
{
ai_AmbientAnimations();
}
}
}

View File

@@ -11,17 +11,19 @@ void main()
object oCreature = OBJECT_SELF;
// Added code to allow for permanent associates in the battle!
object oModule = GetModule();
if(AI_DEBUG) ai_Debug("0e_c2_7_ondeath", "14", "AI_RULE_PERM_ASSOC: " + IntToString(GetLocalInt(oModule, AI_RULE_PERM_ASSOC)));
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
{
object oAssociate;
int nIndex;
for(nIndex = 1; nIndex < 5; nIndex++)
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oCreature);
if(oAssociate != OBJECT_INVALID)
{
SetIsDestroyable(FALSE, FALSE, FALSE);
SetIsDestroyable(FALSE, FALSE, FALSE, oAssociate);
DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE));
DelayCommand(3.0, SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate));
}
}
}

View File

@@ -10,32 +10,36 @@ 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)));
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "13", GetName(oCreature) + " has died!");
object oModule = GetModule();
if(GetLocalInt(oModule, AI_RULE_PERM_ASSOC))
{
object oAssociate;
int nIndex;
for(nIndex = 2; nIndex < 5; nIndex++)
for(nIndex = 2; nIndex < 6; nIndex++)
{
oAssociate = GetAssociate(nIndex, oCreature);
if(oAssociate != OBJECT_INVALID)
{
SetIsDestroyable(FALSE, FALSE, FALSE);
ChangeFaction(oAssociate, oCreature);
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "24", GetName(oAssociate) + " being set to permanent!");
SetIsDestroyable(FALSE, FALSE, FALSE, oAssociate);
DelayCommand(0.1, ChangeToStandardFaction(oAssociate, STANDARD_FACTION_HOSTILE));
DelayCommand(3.0, SetIsDestroyable(TRUE, FALSE, FALSE, oAssociate));
}
}
}
// Remove the widget!
object oPC = GetMaster(oCreature);
if(oPC != OBJECT_INVALID)
{
{
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "35", GetName(oPC) + " Removing associates widget!");
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"));
ChangeToStandardFaction(oCreature, STANDARD_FACTION_DEFENDER);
if(AI_DEBUG) ai_Debug("0e_ch_7_ondeath", "42", "Execute second OnDeath script: " + GetLocalString(oCreature, "AI_ON_DEATH"));
ExecuteScript(GetLocalString(oCreature, "AI_ON_DEATH"), oCreature);
}

View File

@@ -8,6 +8,7 @@
#include "nw_inc_gff"
#include "x0_i0_assoc"
#include "0i_menus"
#include "0i_module"
#include "0i_player_target"
// Save a window ID to the database.
void ai_SaveWindowLocation(object oPC, int nToken, string sAssociateType, string sWindowID);
@@ -32,10 +33,6 @@ void ai_RulePercDistInc(object oPC, 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);
// Turns on oAssociate AI, Setting all event scripts.
void ai_TurnOn(object oPC, object oAssociate, string sAssociateType);
// Turns off oAssociate AI, Setting all event scripts.
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType);
// Adds a henchman back into the players party.
object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion);
@@ -94,10 +91,20 @@ void main()
json jData = NuiGetUserData(oPC, nToken);
object oAssociate = StringToObject(JsonGetString(JsonArrayGet(jData, 0)));
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
if(ai_GetIsDungeonMaster(oPC))
{
if(!NuiFindWindow(oPC, "dm" + AI_WIDGET_NUI))
{
ai_SendMessages(GetName(oPC) + " is now a Dungeon Master! Loading Dungeon Master widget.", AI_COLOR_YELLOW, oPC);
ai_CheckDMStart(oPC);
}
DelayCommand(0.0, NuiDestroy(oPC, nToken));
return;
}
if(!ai_GetIsCharacter(oAssociate) && !GetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE") &&
(oAssociate == OBJECT_INVALID || GetMaster(oAssociate) != oPC))
{
ai_SendMessages("This creature is no longer in your party!", AI_COLOR_RED, oPC);
ai_SendMessages(GetName(oAssociate) + " is no longer in your party!", AI_COLOR_RED, oPC);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
return;
}
@@ -196,57 +203,6 @@ void main()
aiSaveAssociateModesToDb(oPC, oPC);
}
}
else if(sElem == "btn_toggle_assoc_widget")
{
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
string sAssocType;
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
int nIndex;
object oHenchman;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oHenchman != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oHenchman);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oHenchman);
}
}
}
else if(sElem == "btn_effect_icon")
{
if(ai_GetMagicMode(oPC, AI_MAGIC_EFFECT_ICON_REPORT))
@@ -280,10 +236,10 @@ void main()
{
int nMaxHenchmen = StringToInt(sText);
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
if(nMaxHenchmen > 12)
if(nMaxHenchmen > AI_MAX_HENCHMAN)
{
nMaxHenchmen = 12;
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oPC);
nMaxHenchmen = AI_MAX_HENCHMAN;
ai_SendMessages("The maximum henchmen for this mod is " + IntToString(AI_MAX_HENCHMAN) + "!", AI_COLOR_RED, oPC);
}
SetMaxHenchmen(nMaxHenchmen);
SetLocalInt(oModule, AI_RULE_MAX_HENCHMAN, nMaxHenchmen);
@@ -318,7 +274,7 @@ void main()
{
int nNumber = StringToInt(sText);
if(nNumber < 0) nNumber = 0;
else if(nNumber > 100) nNumber = 100;
else if(nNumber > 500) nNumber = 500;
SetLocalInt(oModule, AI_INCREASE_MONSTERS_HP, nNumber);
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
}
@@ -354,6 +310,12 @@ void main()
{
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
NuiSetBind(oPC, nToken, "chbx_full_buff_event", JsonBool(bCheck));
}
else if(sElem == "chbx_full_buff_check")
{
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_FULL_BUFF_MONSTERS, JsonInt(bCheck));
}
else if(sElem == "chbx_buff_summons_check")
{
@@ -579,6 +541,60 @@ void main()
else if(sElem == "btn_familiar_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR);
else if(sElem == "btn_companion_name") ai_SetCompanionName(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION);
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem);
else if(sElem == "btn_toggle_assoc_widget")
{
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
string sAssocType, sText;
if(bWidgetOff) sText = " Associate Widgets [Off]";
else sText = " Associate Widgets [On]";
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_toggle_assoc_widget_tooltip", sText);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
int nIndex;
object oHenchman;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oHenchman != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oHenchman);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oHenchman);
}
}
}
}
else if(sEvent == "watch")
{
@@ -597,10 +613,14 @@ void main()
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
}
else if(sElem == "chbx_buff_rest_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_BUFF_REST, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "chbx_toggle_assoc_widget_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_ASSOC_WIDGETS_OFF, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "chbx_cmd_action_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_ACTION, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "chbx_cmd_guard_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_GUARD, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "chbx_cmd_hold_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_HOLD, oAssociate, sAssociateType, nToken, sElem);
@@ -623,8 +643,11 @@ void main()
else if(sElem == "chbx_companion_check") ai_SetWidgetButtonToCheckbox(oPC, BTN_CMD_COMPANION, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "cmb_familiar_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_FAMILIAR);
else if(sElem == "cmb_companion_selected") ai_SetCompanionType(oPC, oAssociate, nToken, ASSOCIATE_TYPE_ANIMALCOMPANION);
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
}
else if(sEvent == "mousescroll")
{
@@ -635,6 +658,9 @@ void main()
if(sElem == "btn_cmd_follow" &&
oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, 1.0, sAssociateType);
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
}
else if(nMouseScroll == -1.0) // Scroll down
{
@@ -642,6 +668,9 @@ void main()
if(sElem == "btn_cmd_follow" &&
oPC != oAssociate) ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
else if(sElem == "btn_follow_target") ai_FollowIncrement(oPC, oAssociate, -1.0, sAssociateType);
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
}
}
return;
@@ -722,8 +751,11 @@ void main()
else if(sElem == "chbx_ignore_traps_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_IGNORE_TRAPS, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "chbx_perc_range_check") ai_SetAIButtonToCheckbox(oPC, BTN_AI_PERC_RANGE, oAssociate, sAssociateType, nToken, sElem);
else if(sElem == "cmb_ai_script_selected") ai_SetAIScript(oPC, oAssociate, nToken);
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, sAssociateType + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
}
else if(sEvent == "mousescroll")
{
@@ -863,6 +895,60 @@ void main()
else if(sElem == "btn_update_widget") ai_UpdateAssociateWidget(oPC, oAssociate);
else if(GetStringLeft(sElem, 15) == "btn_exe_plugin_") ai_Plugin_Execute(oPC, sElem);
else if(GetStringLeft(sElem, 11) == "btn_widget_") ai_SelectWidgetSpellTarget(oPC, oAssociate, sElem);
else if(sElem == "btn_toggle_assoc_widget")
{
int bWidgetOff = !ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc");
string sAssocType, sText;
if(bWidgetOff) sText = "Associate Widgets [Off]";
else sText = "Associate Widgets [On]";
ai_UpdateToolTipUI(oPC, sAssociateType + AI_COMMAND_NUI, sAssociateType + AI_WIDGET_NUI, "btn_toggle_assoc_widget_tooltip", sText);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oPC, "pc", bWidgetOff);
object oAssoc = GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_SUMMONED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
oAssoc = GetAssociate(ASSOCIATE_TYPE_DOMINATED, oPC);
if(oAssoc != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oAssoc);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oAssoc, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oAssoc);
}
int nIndex;
object oHenchman;
for(nIndex = 1; nIndex <= AI_MAX_HENCHMAN; nIndex++)
{
oHenchman = GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oPC, nIndex);
if(oHenchman != OBJECT_INVALID)
{
sAssocType = ai_GetAssociateType(oPC, oHenchman);
ai_SetWidgetButton(oPC, BTN_WIDGET_OFF, oHenchman, sAssocType, bWidgetOff);
if(bWidgetOff) IsWindowClosed(oPC, sAssocType + AI_WIDGET_NUI);
else ai_CreateWidgetNUI(oPC, oHenchman);
}
}
}
}
if(sEvent == "mousescroll")
{
@@ -881,6 +967,9 @@ void main()
else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, 5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, 1.0, sAssociateType);
else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, 1, sAssociateType, -1);
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, 0.1, sAssociateType);
}
if(nMouseScroll == -1.0) // Scroll down
{
@@ -897,6 +986,9 @@ void main()
else if(sElem == "btn_heal_in") ai_Heal_Button(oPC, oAssociate, -5, AI_HEAL_IN_COMBAT_LIMIT, sAssociateType);
else if(sElem == "btn_loot") ai_LootRangeIncrement(oPC, oAssociate, -1.0, sAssociateType);
else if(sElem == "btn_perc_range") ai_PercRangeIncrement(oPC, oAssociate, -1, sAssociateType, -1);
else if(sElem == "btn_buff_long") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
else if(sElem == "btn_buff_short") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
else if(sElem == "btn_buff_all") ai_DelaySpellSpeed(oPC, oAssociate, -0.1, sAssociateType);
}
}
if(sEvent == "mousedown")
@@ -1174,9 +1266,10 @@ void main()
{
json jPlugins = ai_GetAssociateDbJson(oPC, "pc", "plugins");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_buffing");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_forcerest");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_henchmen");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_crafting");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_forcerest");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_fast_travel");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_henchmen");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_mod_set");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_debug");
jPlugins = ai_Plugin_Add(oPC, jPlugins, "pi_test");
@@ -1209,8 +1302,11 @@ void main()
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
}
if(sElem == "btn_clear_plugins")
{
@@ -1229,8 +1325,11 @@ void main()
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
}
else if(sElem == "btn_add_plugin")
{
@@ -1249,8 +1348,11 @@ void main()
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreatePluginNUI(oPC));
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
}
else if(GetStringLeft(sElem, 11) == "btn_plugin_") ai_Plugin_Execute(oPC, sElem);
}
@@ -1265,8 +1367,11 @@ void main()
jPlugin = JsonArraySet(jPlugin, 1, JsonBool(bCheck));
jPlugins = JsonArraySet(jPlugins, nIndex, jPlugin);
ai_SetAssociateDbJson(oPC, "pc", "plugins", jPlugins);
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, NuiFindWindow(oPC, "pc" + AI_WIDGET_NUI)));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oPC));
}
}
}
return;
@@ -1311,7 +1416,8 @@ void main()
jWidget = JsonArray();
if(JsonGetLength(jSpells) == 2) jSpells = JsonArrayInsert(jSpells, JsonArray());
}
if(JsonGetLength(jWidget) < 20)
int nWidgetLength = JsonGetLength(jWidget);
if(nWidgetLength < 20)
{
json jData = NuiGetUserData(oPC, nToken);
json jQuickListArray = JsonArrayGet(jData, 1);
@@ -1320,8 +1426,7 @@ void main()
jSpells = JsonArraySet(jSpells, 2, jWidget);
jAIData = JsonArraySet(jAIData, 10, jSpells);
ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate));
ai_PopulateWidgetList(oPC, oAssociate, nToken, jWidget);
}
else ai_SendMessages("The quick widget can only have 20 abilities or spells!", AI_COLOR_RED, oPC);
}
@@ -1331,7 +1436,7 @@ void main()
json jSpell = JsonArrayGet(jQuickListArray, nIndex);
ai_CreateDescriptionNUI(oPC, jSpell);
}
else if(GetStringLeft(sElem, 11) == "btn_widget_")
else if(GetStringLeft(sElem, 11) == "btn_widget_") // Removes ability from quick use widget
{
string sIndex;
if(GetStringLength(sElem) == 13) sIndex = GetStringRight(sElem, 2);
@@ -1343,17 +1448,19 @@ void main()
jSpells = JsonArraySet(jSpells, 2, jWidget);
jAIData = JsonArraySet(jAIData, 10, jSpells);
ai_SetAssociateDbJson(oPC, sAssociateType, "aidata", jAIData);
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreateQuickWidgetSelectionNUI(oPC, oAssociate));
ai_PopulateWidgetList(oPC, oAssociate, nToken, jWidget);
}
}
else if(sEvent == "close")
{
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
if(nUIToken)
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
if(nUIToken)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
}
}
return;
@@ -1393,23 +1500,22 @@ void main()
int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate);
int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1));
json jSpellArray = JsonArrayGet(jData, 1);
int nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex));
string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
string sSpellIcon = Get2DAString("spells", "IconResRef", nSpell);
int nSlot;
int nMaxMemorizationSlot = GetMemorizedSpellCountByLevel(oAssociate, nClass, nLevel);
int nSlot, nSpell;
string sSlot;
while(nSlot < nMaxMemorizationSlot)
{
if(GetMemorizedSpellId(oAssociate, nClass, nLevel, nSlot) == -1)
{
nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex));
SetMemorizedSpell(oAssociate, nClass, nLevel, nSlot, nSpell, FALSE);
//NuiDestroy(oPC, nToken);
//ai_CreateSpellMemorizationNUI(oPC, oAssociate);
string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
string sSpellIcon = Get2DAString("spells", "IconResRef", nSpell);
string sIndex = IntToString(nSlot);
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(TRUE));
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString(sSpellIcon));
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
sSlot = IntToString(nSlot);
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_event", JsonBool(TRUE));
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_image", JsonString(sSpellIcon));
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + IntToString(nLevel) + ")"));
return;
}
nSlot++;
@@ -1422,28 +1528,29 @@ void main()
int nSpell = JsonGetInt(JsonArrayGet(jSpellArray, nIndex));
ai_CreateDescriptionNUI(oPC, JsonArray(), nSpell);
}
else if(GetStringLeft(sElem, 14) == "btn_memorized_")
else if(GetStringLeft(sElem, 14) == "btn_memorized_") // Remove memorized spell.
{
json jAIData = ai_GetAssociateDbJson(oPC, sAssociateType, "aidata");
json jSpells = JsonArrayGet(jAIData, 10);
int nClass = GetClassByPosition(JsonGetInt(JsonArrayGet(jSpells, 0)), oAssociate);
int nLevel = JsonGetInt(JsonArrayGet(jSpells, 1));
string sIndex = GetStringRight(sElem, 1);
ClearMemorizedSpell(oAssociate, nClass, nLevel, StringToInt(sIndex));
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_image", JsonString("ctl_cg_btn_splvl"));
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_tooltip", JsonString(""));
NuiSetBind(oPC, nToken, "btn_memorized_" + sIndex + "_event", JsonBool(FALSE));
//NuiDestroy(oPC, nToken);
//ai_CreateSpellMemorizationNUI(oPC, oAssociate);
string sSlot = GetStringRight(sElem, 1);
ClearMemorizedSpell(oAssociate, nClass, nLevel, StringToInt(sSlot));
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_image", JsonString("ctl_cg_btn_splvl"));
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_tooltip", JsonString(""));
NuiSetBind(oPC, nToken, "btn_memorized_" + sSlot + "_event", JsonBool(FALSE));
}
}
else if(sEvent == "close")
{
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
if(nUIToken)
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
int nUIToken = NuiFindWindow(oPC, sAssociateType + AI_QUICK_WIDGET_NUI);
if(nUIToken)
{
DelayCommand(0.0, NuiDestroy(oPC, nUIToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
}
}
return;
@@ -1500,6 +1607,7 @@ void main()
jKnownList = JsonArray();
}
int nMaxKnownSlots, nSlot;
string sClass, sName, sSpellIcon, sSlot;
string sSpellKnownTable = Get2DAString("classes", "SpellKnownTable", nClass);
if(sSpellKnownTable != "") nMaxKnownSlots = StringToInt(Get2DAString(sSpellKnownTable, "SpellLevel" + sLevel, GetLevelByClass(nClass, oAssociate) - 1));
else nMaxKnownSlots = 20;
@@ -1511,13 +1619,13 @@ void main()
jSpell = GffAddWord(JsonObject(), "Spell", nSpell);
jSpell = JsonObjectSet(jSpell, "__struct_id", JsonInt(3));
jKnownList = JsonArrayInsert(jKnownList, jSpell);
string sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
string sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
string sSpellIcon = Get2DAString("spells", "IconResRef", nSpell);
string sIndex = IntToString(nSlot);
NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_event", JsonBool(TRUE));
NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_image", JsonString(sSpellIcon));
NuiSetBind(oPC, nToken, "btn_known_" + sIndex + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + sLevel + ")"));
sClass = GetStringByStrRef(StringToInt(Get2DAString("classes", "Name", nClass)));
sName = GetStringByStrRef(StringToInt(Get2DAString("spells", "Name", nSpell)));
sSpellIcon = Get2DAString("spells", "IconResRef", nSpell);
sSlot = IntToString(nSlot);
NuiSetBind(oPC, nToken, "btn_known_" + sSlot + "_event", JsonBool(TRUE));
NuiSetBind(oPC, nToken, "btn_known_" + sSlot + "_image", JsonString(sSpellIcon));
NuiSetBind(oPC, nToken, "btn_known_" + sSlot + "_tooltip", JsonString(" " + sName + " (" + sClass + " / " + sLevel + ")"));
SetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE", TRUE);
break;
}
@@ -1618,6 +1726,7 @@ void main()
if(GetLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE"))
{
RemoveHenchman(oPC, oAssociate);
ChangeToStandardFaction(oAssociate, STANDARD_FACTION_DEFENDER);
json jHenchman = ObjectToJson(oAssociate, TRUE);
json jClassList = GetLocalJson(oAssociate, AI_CLASS_LIST_JSON);
jHenchman = GffReplaceList(jHenchman, "ClassList", jClassList);
@@ -1630,8 +1739,12 @@ void main()
AssignCommand(oAssociate, SetIsDestroyable(TRUE, FALSE, FALSE));
DestroyObject(oAssociate);
oAssociate = ai_AddHenchman(oPC, jHenchman, lLocation, nFamiliar, nCompanion);
DeleteLocalJson(oAssociate, AI_CLASS_LIST_JSON);
DeleteLocalInt(oAssociate, "AI_KNOWN_SPELL_CHANGE");
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
}
}
return;
@@ -1701,7 +1814,11 @@ void ai_AddAssociate(object oPC, int nToken, json jAssociate, location lLocation
AddHenchman(oPC, oAssociate);
DeleteLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE");
DelayCommand(0.0, NuiDestroy(oPC, nToken));
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
string sAssociateType = ai_GetAssociateType(oPC, oAssociate);
if(!ai_GetWidgetButton(oPC, BTN_WIDGET_OFF, oAssociate, sAssociateType) || oPC == oAssociate)
{
DelayCommand(0.1, ai_CreateWidgetNUI(oPC, oAssociate));
}
if(nRange) SetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION, nRange);
if(nFamiliar) SummonFamiliar(oAssociate);
if(nCompanion) SummonAnimalCompanion(oAssociate);
@@ -1819,12 +1936,12 @@ void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateT
SetLocalInt(oPC, "AI_IGNORE_NO_ASSOCIATE", TRUE);
int nBtnPercRange = GetLocalInt(oAssociate, AI_ASSOCIATE_PERCEPTION + "_MENU");
string sText, sText2;
float fRange = 20.0;
float fRange = 25.0;
if(nBtnPercRange == 8)
{
sText = "short";
sText2 = " Perception Range Short [10 meters Sight / 10 meters Listen]";
fRange = 10.0;
fRange = 15.0;
}
else if(nBtnPercRange == 9)
{
@@ -1835,7 +1952,7 @@ void ai_Perc_Range(object oPC, object oAssociate, int nToken, string sAssociateT
{
sText = "long";
sText2 = " Perception Range Long [35 meters Sight / 20 meters Listen]";
fRange = 35.0;
fRange = 40.0;
}
else if(nBtnPercRange == 11)
{
@@ -1917,49 +2034,6 @@ json ai_AddRestrictedSpell(json jRules, int nSpell, int bRestrict = TRUE)
SetLocalJson(oModule, AI_RULE_RESTRICTED_SPELLS, jRSpells);
return JsonObjectSet(jRules, AI_RULE_RESTRICTED_SPELLS, jRSpells);
}
void ai_TurnOn(object oPC, object oTarget, string sAssociateType)
{
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI On");
ai_SendMessages("AI turned on for " + GetName(oTarget) + ".", AI_COLOR_YELLOW, oPC);
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "xx_pc_1_hb");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_NOTICE, "xx_pc_2_percept");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "xx_pc_3_endround");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "xx_pc_4_convers");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "xx_pc_5_phyatked");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "xx_pc_6_damaged");
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "xx_pc_8_disturb");
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "xx_pc_b_castat");
SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "xx_pc_e_blocked");
//SetEventScript(oTarget, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
// This sets the script for the PC to run AI based on class.
ai_SetAssociateAIScript(oTarget, FALSE);
// Set so PC can hear associates talking in combat.
ai_SetListeningPatterns(oTarget);
}
void ai_TurnOff(object oPC, object oAssociate, string sAssociateType)
{
ai_UpdateToolTipUI(oPC, sAssociateType + AI_NUI, sAssociateType + AI_WIDGET_NUI, "btn_ai_tooltip", " AI Off");
ai_SendMessages("AI Turned off for " + GetName(oAssociate) + ".", AI_COLOR_YELLOW, oPC);
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_NOTICE, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DAMAGED, "");
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DEATH, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_DISTURBED, "");
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPAWN_IN, "");
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_RESTED, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, "");
SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, "");
//SetEventScript(oAssociate, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, "");
DeleteLocalInt(oAssociate, "AI_I_AM_BEING_HEALED");
DeleteLocalString(oAssociate, "AIScript");
ai_ClearCreatureActions();
}
object ai_AddHenchman(object oPC, json jHenchman, location lLocation, int nFamiliar, int nCompanion)
{
jHenchman = GffReplaceResRef(jHenchman, "ScriptSpawn", "");

View File

@@ -5,6 +5,7 @@
Menu event script
sEvent: close, click, mousedown, mouseup, watch (if bindwatch is set).
/*//////////////////////////////////////////////////////////////////////////////
#include "0i_menus"
#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);
@@ -32,6 +33,16 @@ void main()
// " nToken: " + IntToString(nToken) + " oPC: " + GetName(oPC));
//WriteTimestampedLogEntry("0e_nui, 58, sWndId: " + sWndId + " sEvent: " + sEvent + " sElem: " + sElem +
// " nToken: " + IntToString(nToken) + " oDM: " + GetName(oDM));
if(ai_GetIsCharacter(oDM))
{
if(!NuiFindWindow(oDM, "pc" + AI_WIDGET_NUI))
{
ai_SendMessages(GetName(oDM) + " is now a Player! Loading player widget.", AI_COLOR_YELLOW, oDM);
ai_CreateWidgetNUI(oDM, oDM);
}
DelayCommand(0.0, NuiDestroy(oDM, nToken));
return;
}
//**************************************************************************
string sName = ai_RemoveIllegalCharacters(GetName(oDM));
// Watch to see if the window moves and save.
@@ -197,10 +208,10 @@ void main()
{
int nMaxHenchmen = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(nMaxHenchmen < 1) nMaxHenchmen = 1;
if(nMaxHenchmen > 12)
if(nMaxHenchmen > AI_MAX_HENCHMAN)
{
nMaxHenchmen = 12;
ai_SendMessages("The maximum henchmen for this mod is 12!", AI_COLOR_RED, oDM);
nMaxHenchmen = AI_MAX_HENCHMAN;
ai_SendMessages("The maximum henchmen for this mod is " + IntToString(AI_MAX_HENCHMAN) + "!", AI_COLOR_RED, oDM);
}
SetMaxHenchmen(nMaxHenchmen);
json jRules = ai_GetCampaignDbJson("rules");
@@ -232,7 +243,7 @@ void main()
{
int nNumber = StringToInt(JsonGetString(NuiGetBind(oDM, nToken, sElem)));
if(nNumber < 0) nNumber = 0;
else if(nNumber > 100) nNumber = 100;
else if(nNumber > 500) nNumber = 500;
SetLocalInt(GetModule(), AI_INCREASE_MONSTERS_HP, nNumber);
json jRules = ai_GetCampaignDbJson("rules");
jRules = JsonObjectSet(jRules, AI_INCREASE_MONSTERS_HP, JsonInt(nNumber));
@@ -253,6 +264,11 @@ void main()
SetLocalInt(oModule, AI_RULE_BUFF_MONSTERS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_BUFF_MONSTERS, JsonInt(bCheck));
}
else if(sElem == "chbx_full_buff_check")
{
SetLocalInt(oModule, AI_RULE_FULL_BUFF_MONSTERS, bCheck);
jRules = JsonObjectSet(jRules, AI_RULE_FULL_BUFF_MONSTERS, JsonInt(bCheck));
}
else if(sElem == "chbx_buff_summons_check")
{
SetLocalInt(oModule, AI_RULE_PRESUMMON, bCheck);

View File

@@ -15,9 +15,5 @@ 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);
}
else if(ai_GetIsDungeonMaster(oCreature)) ai_CheckDMStart(oCreature);
}

View File

@@ -10,6 +10,8 @@
action of the target.
AI_TARGET_MODE is the constant used.
AI_TARGET_ASSOCIATE is the associate that triggered the target mode.
AI_TARGET_MODE_ON defines if the player is in target mode for a henchman instead of the PC.
/*//////////////////////////////////////////////////////////////////////////////
#include "0i_player_target"
void main()
@@ -31,6 +33,7 @@ void main()
location lLocation = Location(GetArea(oPC), vTarget, GetFacing(oPC));
object oAssociate = GetLocalObject(oPC, AI_TARGET_ASSOCIATE);
string sTargetMode = GetLocalString(oPC, AI_TARGET_MODE);
DeleteLocalString(oPC, AI_TARGET_MODE);
// ********************* Exiting Target Actions ************************
// If the user manually exited targeting mode without selecting a target, return
if(!GetIsObjectValid(oTarget) && vTarget == Vector())
@@ -38,50 +41,61 @@ void main()
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);
ai_RemoveAllActionMode(oPC);
return;
}
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) == "")
// Clean up any PC AI being turned on as well as variables.
DeleteLocalObject(oPC, AI_TARGET_ASSOCIATE);
DeleteLocalInt(oPC, AI_TARGET_MODE_ON);
DeleteLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE);
// Make sure the camera goes back to the player since we are leaving henchmen control.
if(GetLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE") != OBJECT_INVALID)
{
if(GetLocalInt(oPC, sGhostModeVarname))
{
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
DeleteLocalObject(oPC, "AI_CAMERA_ON_ASSOCIATE");
AttachCamera(oPC, oPC);
if(!GetLocalInt(GetModule(), AI_USING_PRC)) ai_TurnOff(oPC, oPC, "pc");
}
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_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);
ai_RemoveASpecificEffect(oAssociate, EFFECT_TYPE_CUTSCENEGHOST);
DeleteLocalInt(oAssociate, sGhostModeVarname);
}
ExecuteScript("nw_ch_ac1", oAssociate);
return;
}
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
{
ai_SendMessages(GetName(oAssociate) + " has exited selecing a trap!", AI_COLOR_YELLOW, oPC);
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
{
ai_SendMessages(GetName(oAssociate) + " has exited placing the trap!", AI_COLOR_YELLOW, oPC);
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
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;
}
// If these actions are canceled and we are in target mode with a henchmen
// then turn target mode back on for that henchmen.
else if(sTargetMode == "ASSOCIATE_USE_ITEM" ||
sTargetMode == "ASSOCIATE_USE_FEAT" ||
sTargetMode == "ASSOCIATE_CAST_SPELL" ||
sTargetMode == "ASSOCIATE_FOLLOW_TARGET")
{
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
return;
}
// ************************* Targeted Actions **************************
else
@@ -89,45 +103,60 @@ void main()
// 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);
ai_ActionAllAssociates(oPC, oTarget, lLocation);
SetLocalString(oPC, AI_TARGET_MODE, "ASSOCIATE_ACTION_ALL");
EnterTargetingMode(oPC, OBJECT_TYPE_ALL, MOUSECURSOR_ACTION, MOUSECURSOR_NOWALK);
return;
}
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));
AssignCommand(oAssociate, ai_ActionAssociate(oPC, oTarget, lLocation));
return;
}
else if(sTargetMode == "ASSOCIATE_FOLLOW_TARGET")
{
ai_SelectFollowTarget(oPC, oAssociate, oTarget);
return;
}
else if(sTargetMode == "ASSOCIATE_GET_TRAP")
{
ai_SelectTrap(oPC, oAssociate, oTarget);
return;
}
else if(sTargetMode == "ASSOCIATE_PLACE_TRAP")
{
AssignCommand(oAssociate, ai_PlaceTrap(oPC, lLocation));
return;
}
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));
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
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));
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
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));
if(GetLocalInt(oPC, AI_TARGET_MODE_ON)) ai_EnterAssociateTargetMode(oPC, GetLocalObject(oPC, AI_TARGET_MODE_ASSOCIATE));
return;
}
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);
return;
}
else if(sTargetMode == "DM_SELECT_OPEN_INVENTORY")
{
@@ -137,18 +166,20 @@ void main()
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);
return;
}
else if(GetStringLeft(sTargetMode, 15) == "DM_SELECT_GROUP")
{
ai_AddToGroup(oPC, oTarget, sTargetMode);
return;
}
else if(GetStringLeft(sTargetMode, 15) == "DM_ACTION_GROUP")
{
ai_DMAction(oPC, oTarget, lLocation, sTargetMode);
return;
}
// Get saved module player target script and execute it for pass through compatibility.
string sModuleTargetScript = GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT);
ExecuteScript(sModuleTargetScript);
}
// Get saved module player target script and execute it for pass through compatibility.
ExecuteScript(GetLocalString(GetModule(), AI_MODULE_TARGET_EVENT));
}
}

View File

@@ -0,0 +1,317 @@
/*//////////////////////////////////////////////////////////////////////////////
// Script Name: 0e_prc_id_events
////////////////////////////////////////////////////////////////////////////////
Infinite Dungeons monster event handler while using the PRC.
*///////////////////////////////////////////////////////////////////////////////
#include "0i_actions"
#include "x0_i0_assoc"
// Followers special heartbeat script.
void ai_hen_id1_heart(object oCreature);
// Followers special conversation script.
void ai_hen_id1_convo(object oCreature, int nMatch);
// Followers special perception script.
void ai_hen_id1_percept(object oCreature);
// Followers special end of round script.
void ai_hen_id1_endcombat(object oCreature, int bFollower);
// Followers special castat script.
void ai_hen_id1_castat(object oCreature);
void main()
{
object oCreature = OBJECT_SELF;
int nEvent = GetCurrentlyRunningEvent();
int bFollower = GetLocalInt(oCreature, "bFollower");
switch (nEvent)
{
case EVENT_SCRIPT_CREATURE_ON_HEARTBEAT:
{
if(bFollower)
{
if(GetImmortal(oCreature)) SetImmortal(oCreature, FALSE);
ai_hen_id1_heart(oCreature);
}
else
{
ExecuteScript("nw_c2_default1", oCreature);
ExecuteScript("prc_npc_hb", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_NOTICE:
{
if(bFollower) ai_hen_id1_percept(oCreature);
else
{
ExecuteScript("nw_c2_default2", oCreature);
ExecuteScript("prc_npc_percep", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_DIALOGUE:
{
int nMatch = GetListenPatternNumber();
if(nMatch == -1)
{
if(ai_GetIsBusy(oCreature) || ai_Disabled(oCreature) ||
GetLocalInt(oCreature, AI_AM_I_SEARCHING)) return;
ai_ClearCreatureActions();
string sConversation = GetLocalString(oCreature, "sConversation");
if(sConversation != "") BeginConversation(sConversation);
else BeginConversation();
}
if(bFollower) ai_hen_id1_convo(oCreature, nMatch);
else
{
//ExecuteScript("nw_c2_default4", oCreature);
ExecuteScript("prc_npc_conv", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED:
{
if(bFollower) ExecuteScript("nw_ch_ac5", oCreature);
else
{
ExecuteScript("nw_c2_default5", oCreature);
ExecuteScript("prc_npc_physatt", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_DAMAGED:
{
if(bFollower) ExecuteScript("nw_ch_ac6", oCreature);
else
{
ExecuteScript("nw_c2_default6", oCreature);
ExecuteScript("prc_npc_damaged", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT:
{
if(bFollower) ai_hen_id1_castat(oCreature);
else
{
ExecuteScript("nw_c2_defaultb", oCreature);
ExecuteScript("prc_npc_spellat", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND:
{
if(bFollower) ai_hen_id1_endcombat(oCreature, bFollower);
else
{
ExecuteScript("nw_c2_default3", oCreature);
ExecuteScript("prc_npc_combat", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR:
{
if(bFollower) ExecuteScript("nw_ch_ace", oCreature);
else
{
ExecuteScript("nw_c2_defaulte", oCreature);
ExecuteScript("prc_npc_blocked", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_RESTED:
{
if(bFollower) ExecuteScript("nw_ch_aca", oCreature);
else ExecuteScript("prc_npc_rested", oCreature);
break;
}
case EVENT_SCRIPT_CREATURE_ON_DISTURBED:
{
if(bFollower) ExecuteScript("nw_ch_ac8", oCreature);
else
{
ExecuteScript("nw_c2_default8", oCreature);
ExecuteScript("prc_npc_disturb", oCreature);
}
break;
}
case EVENT_SCRIPT_CREATURE_ON_DEATH:
{
if(bFollower) ExecuteScript("nw_ch_ac7", oCreature);
else
{
ExecuteScript("nw_c2_default7", oCreature);
}
break;
}
}
}
void ai_hen_id1_heart(object oCreature)
{
// Sometimes they slip out of this mode!
if(GetAssociateState(NW_ASC_MODE_DYING, oCreature) &&
GetCommandable())
{
ActionPlayAnimation(ANIMATION_LOOPING_DEAD_FRONT, 1.0, 65.0);
SetCommandable(FALSE);
}
ExecuteScript("nw_ch_ac1", oCreature);
}
void ai_hen_id1_convo(object oCreature, int nMatch)
{
if(nMatch == ASSOCIATE_COMMAND_INVENTORY)
{
// * cannot modify disabled equipment
if(!GetLocalInt(OBJECT_SELF, "X2_JUST_A_DISABLEEQUIP"))
{
OpenInventory(oCreature, GetLastSpeaker());
}
// * feedback as to why
else SendMessageToPCByStrRef(GetMaster(), 100895);
return;
}
else if(nMatch == ASSOCIATE_COMMAND_LEAVEPARTY)
{
object oMaster = GetMaster();
string sTag = GetTag(GetArea(oMaster));
// * henchman cannot be kicked out in the reaper realm
// * Followers can never be kicked out
if (sTag == "GatesofCania" || GetIsFollower(oCreature)) return;
if(GetIsObjectValid(oMaster))
{
ai_ClearCreatureActions();
if(GetAssociateType(oCreature) == ASSOCIATE_TYPE_HENCHMAN)
{
string sConversation = GetLocalString(oCreature, "sConversation");
if (sConversation == "id1_plotgiver")
{
string sVariable = GetLocalString(oCreature, "sVariable");
object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon");
SetLocalInt(oDungeon, "b" + sVariable + "Gone", FALSE);
}
RemoveHenchman(oMaster);
DestroyObject(oCreature);
}
}
return;
}
ExecuteScript("nw_ch_ac4", oCreature);
}
void ai_hen_id1_percept(object oCreature)
{
// If henchman is dying and Player disappears then force a respawn of the henchman
if (GetIsHenchmanDying(oCreature))
{
// The henchman must be removed otherwise their corpse will follow the player
object oOldMaster = GetMaster();
object oPC = GetLastPerceived();
int bVanish = GetLastPerceptionVanished();
if(GetIsObjectValid(oPC) && bVanish)
{
if (oPC == oOldMaster)
{
RemoveHenchman(oPC, oCreature);
// Only in chapter 1
if(GetTag(GetModule()) == "x0_module1")
{
SetCommandable(TRUE);
DoRespawn(oPC, oCreature); // Should teleport henchman back
}
}
}
}
ExecuteScript("nw_ch_ac2", oCreature);
}
void ai_hen_id1_endcombat(object oCreature, int bFollower)
{
if (ai_GetIsInCombat(oCreature))
{
int nNum;
int nLine;
string sString;
int nCreature;
int bIntelligent;
int nRandom = d100();
// chance of a oneliner
int nOnelinerPercentage = GetLocalInt(GetModule(), "nFlagCombatOneLinerFrequencyValue");
if(nRandom <= nOnelinerPercentage)
{
string sCreature = GetLocalString(oCreature, "sVariable");
// if the current creature is hostile towards PCs
if(sCreature != "")
{
object oDungeon = GetLocalObject(GetModule(), "oCurrentDungeon");
if(GetIsReactionTypeHostile(GetFirstPC()))
{
nCreature = GetLocalInt(oDungeon, "n" + sCreature);
bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent");
if(bIntelligent)
{
nNum = GetLocalInt(GetModule(), "nLinesHostileNum");
nLine = Random(nNum) + 1;
if(nLine > 0)
{
sString = GetLocalString(GetModule(), "sLinesHostile" + IntToString(nLine));
SpeakString(sString, TALKVOLUME_SHOUT);
}
}
}
else
{
nCreature = GetLocalInt(oDungeon, "n" + sCreature);
bIntelligent = GetLocalInt(oDungeon, "bListCreature" + IntToString(nCreature) + "Intelligent");
if(bIntelligent)
{
nNum = GetLocalInt(GetModule(), "nLinesAlliesNum");
nLine = Random(nNum) + 1;
if (nLine > 0)
{
sString = GetLocalString(GetModule(), "sLinesAllies" + IntToString(nLine));
SpeakString(sString, TALKVOLUME_SHOUT);
}
}
}
}
}
}
if(bFollower) ExecuteScript("nw_ch_ac3", oCreature);
else ExecuteScript("nw_c2_default3", oCreature);
}
void ai_hen_id1_castat(object oCreature)
{
if(!GetLastSpellHarmful())
{
int nSpell = GetLastSpell();
if(nSpell == SPELL_RAISE_DEAD || nSpell == SPELL_RESURRECTION)
{
object oCaster = GetLastSpellCaster();
// Restore merchant faction to neutral
SetStandardFactionReputation(STANDARD_FACTION_MERCHANT, 100, oCaster);
SetStandardFactionReputation(STANDARD_FACTION_COMMONER, 100, oCaster);
SetStandardFactionReputation(STANDARD_FACTION_DEFENDER, 100, oCaster);
ClearPersonalReputation(oCaster, oCreature);
AssignCommand(oCreature, SurrenderToEnemies());
AssignCommand(oCreature, ai_ClearCreatureActions(TRUE));
// Reset henchmen attack state - Oct 28 (BK)
ai_SetAIMode(oCreature, AI_MODE_DEFEND_MASTER, FALSE);
ai_SetAIMode(oCreature, AI_MODE_STAND_GROUND, FALSE);
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE);
ai_SetAIMode(oCreature, AI_MODE_SCOUT_AHEAD, FALSE);
ai_SetAIMode(oCreature, AI_MODE_COMMANDED, FALSE);
// Oct 30 - If player previously hired this hench
// then just have them rejoin automatically
if(GetPlayerHasHired(oCaster, oCreature))
{
// Feb 11, 2004 - Jon: Don't fire the HireHenchman function if the
// henchman is already oCaster's associate. Fixes a silly little problem
// that occured when you try to raise a henchman who wasn't actually dead.
if(GetMaster(oCreature)!= oCaster) HireHenchman(oCaster, oCreature, TRUE);
}
else
{
string sFile = GetDialogFileToUse(oCaster);
AssignCommand(oCaster, ActionStartConversation(oCreature, sFile));
}
}
}
ExecuteScript("nw_ch_acb", oCreature);
}

View File

@@ -152,6 +152,8 @@ void ai_AmbientAnimations();
void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID)
{
object oMaster = GetMaster(oCreature);
if(GetLocalInt(oMaster, AI_TARGET_MODE_ON) && GetLocalObject(oMaster, AI_TARGET_MODE_ASSOCIATE) == oCreature) return;
if(ai_StayClose(oCreature)) return;
// Is the target our Player has locked in dead? If so then clear it.
if(GetIsDead(GetLocalObject(oCreature, AI_PC_LOCKED_TARGET))) DeleteLocalObject(oCreature, AI_PC_LOCKED_TARGET);
@@ -176,21 +178,27 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
// the polymorph AI script.
if(sAI != "ai_coward" && sAI != "ai_a_peaceful")
{
if(AI_DEBUG) ai_Debug("0i_actions", "173", "Should we use polymorph? " +
IntToString(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature)));
if(AI_DEBUG)
{
ai_Debug("0i_actions", "181", "Should we use polymorph? Current: " +
IntToString(GetAppearanceType(oCreature)) + " Normal: " + IntToString(ai_GetNormalAppearance(oCreature)));
if(ai_GetIsHidden(oCreature))
{
ai_Debug("0i_actions", "179", "We are hidden!" +
ai_Debug("0i_actions", "185", "We are hidden!" +
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oCreature)));
}
}
if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
else if(GetAppearanceType(oCreature) != ai_GetNormalAppearance(oCreature))
{
sAI = "ai_a_polymorphed";
if(!GetLocalInt(oCreature, AI_POLYMORPHED))
{
SetLocalInt(oCreature, AI_POLYMORPHED, TRUE);
ai_ClearTalents(oCreature);
ai_SetCreatureSpecialAbilityTalents(oCreature, FALSE, FALSE, FALSE);
}
}
else if(ai_GetIsHidden(oCreature) && !ai_GetNearestIndexThatSeesUs(oCreature)) sAI = "ai_a_invisible";
}
if(sAI == "") sAI = "ai_a_default";
if(AI_DEBUG) ai_Debug("0i_actions", "190", "********** " + GetName (oCreature) + " **********");
@@ -211,6 +219,7 @@ void ai_DoAssociateCombatRound(object oCreature, object oTarget = OBJECT_INVALID
void ai_StartAssociateCombat(object oAssociate, object oTarget = OBJECT_INVALID)
{
if(AI_DEBUG) ai_Debug("0i_actions", "217", "---------- " + GetName(oAssociate) + " is starting combat! ----------");
//ai_SetCreatureTalentsByLevel(oAssociate, FALSE);
ai_SetCreatureTalents(oAssociate, FALSE);
ai_CheckXPPartyScale(oAssociate);
ai_DoAssociateCombatRound(oAssociate, oTarget);
@@ -226,11 +235,24 @@ void ai_DoMonsterCombatRound(object oMonster)
string sAI = GetLocalString(oMonster, AI_COMBAT_SCRIPT);
if(sAI != "ai_coward")
{
if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
if(AI_DEBUG) ai_Debug("0i_actions", "235", "Should we use polymorph? Current: " +
IntToString(GetAppearanceType(oMonster)) + " Normal: " + IntToString(ai_GetNormalAppearance(oMonster)));
if(ai_GetIsHidden(oMonster))
{
if(AI_DEBUG) ai_Debug("0i_actions", "239", "We are hidden!" +
" Can they see us? " + IntToString(ai_GetNearestIndexThatSeesUs(oMonster)));
}
if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
else if(GetAppearanceType(oMonster) != ai_GetNormalAppearance(oMonster))
{
sAI = "ai_polymorphed";
if(!GetLocalInt(oMonster, AI_POLYMORPHED))
{
SetLocalInt(oMonster, AI_POLYMORPHED, TRUE);
ai_ClearTalents(oMonster);
ai_SetCreatureSpecialAbilityTalents(oMonster, TRUE, FALSE, FALSE);
}
}
else if(ai_GetIsHidden(oMonster) && !ai_GetNearestIndexThatSeesUs(oMonster)) sAI = "ai_invisible";
}
if(sAI == "") sAI = "ai_default";
if(AI_DEBUG) ai_Debug("0i_actions", "230", "********** " + GetName (oMonster) + " **********");
@@ -277,7 +299,7 @@ int ai_StayClose(object oCreature)
if(fPerceptionDistance == 0.0)
{
fPerceptionDistance = GetLocalFloat(oMaster, AI_ASSOC_PERCEPTION_DISTANCE);
if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0;
if(fPerceptionDistance == 0.0) fPerceptionDistance = 25.0;
}
object oTarget = GetLocalObject(oCreature, AI_FOLLOW_TARGET);
if(oTarget == OBJECT_INVALID) oTarget = oMaster;
@@ -389,9 +411,20 @@ int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oInvisible
}
}
float fPerceptionDistance, fDistance;
// Check to see if the creature is invisible because we cannot hurt them with our weapon.
// If so we need to stay away from them! Maybe add weapon swapping code later?
if(AI_DEBUG) ai_Debug("0i_actions", "415", GetName(oCreature) + "IsWeaponEffective? " +
IntToString(GetIsWeaponEffective(oInvisible)) + " oInvisible: " + GetName(oInvisible));
/*if(!GetIsWeaponEffective(oInvisible))
{
ai_HaveCreatureSpeak(oCreature, 20, ":21:47:7:");
fDistance = GetDistanceBetween(oCreature, oInvisible);
if(fDistance < AI_RANGE_LONG) ActionMoveAwayFromObject(oInvisible, TRUE, AI_RANGE_LONG);
return TRUE;
} */
if(bMonster)
{
GetDistanceBetween(oCreature, oInvisible);
fDistance = GetDistanceBetween(oCreature, oInvisible);
fPerceptionDistance = GetLocalFloat(GetModule(), AI_RULE_PERCEPTION_DISTANCE);
}
else
@@ -399,7 +432,7 @@ int ai_SearchForHiddenCreature(object oCreature, int bMonster, object oInvisible
// We want to use the distance between the PC and target not us.
object oMaster = GetMaster();
if(oMaster != OBJECT_INVALID) fDistance = GetDistanceBetween(oMaster, oInvisible);
else GetDistanceBetween(oCreature, oInvisible);
else fDistance = GetDistanceBetween(oCreature, oInvisible);
fPerceptionDistance = GetLocalFloat(oCreature, AI_ASSOC_PERCEPTION_DISTANCE);
if(fPerceptionDistance == 0.0) fPerceptionDistance = 20.0;
}
@@ -512,6 +545,9 @@ int ai_MoralCheck(object oCreature)
nRaceType == RACIAL_TYPE_UNDEAD ||
nRaceType == RACIAL_TYPE_CONSTRUCT ||
ai_GetIsCharacter(oCreature)) return FALSE;
int nAssociateType = GetAssociateType(oCreature);
//if(nAssociateType == ASSOCIATE_TYPE_FAMILIAR || nAssociateType == ASSOCIATE_TYPE_ANIMALCOMPANION ||
// nAssociateType == ASSOCIATE_TYPE_SUMMONED) return FALSE;
// Moral DC is AI_WOUNDED_MORAL_DC - The number of allies.
// or AI_BLOODY_MORAL_DC - number of allies.
int nDC;
@@ -521,11 +557,11 @@ int ai_MoralCheck(object oCreature)
if(nHpPercent <= AI_HEALTH_WOUNDED)
{
// Debug code to look for multiple moral checks at once by one creature?
if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
{
SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
}
//if(GetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE) == "")
//{
// SetLocalString(GetModule(), AI_RULE_DEBUG_CREATURE, GetName(oCreature));
// ai_Debug("0i_actions", "424", GetName(oCreature) + " starting debug mode to test Moral checks!");
//}
if(nHpPercent <= AI_HEALTH_BLOODY) nDC = AI_BLOODY_MORAL_DC;
else nDC = AI_WOUNDED_MORAL_DC;
nDC = nDC - GetLocalInt(oCreature, AI_ALLY_NUMBERS);
@@ -681,17 +717,17 @@ void ai_DoPhysicalAttackOnBest(object oCreature, int nInMelee, int bAlwaysAtk =
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -739,17 +775,17 @@ void ai_DoPhysicalAttackOnNearest(object oCreature, int nInMelee, int bAlwaysAtk
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "519", "Do ranged attack against nearest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -796,17 +832,17 @@ void ai_DoPhysicalAttackOnLowestCR(object oCreature, int nInMelee, int bAlwaysAt
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature);
}
else
{
if(ai_GetAIMode(oCreature, AI_MODE_DEFEND_MASTER)) oTarget = ai_GetLowestCRAttackerOnMaster(oCreature);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetNearestFavoredEnemyTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRTarget(oCreature, AI_RANGE_MELEE);
if(oTarget == OBJECT_INVALID) oTarget = ai_GetLowestCRPhysicalTarget(oCreature, AI_RANGE_MELEE);
}
if(oTarget != OBJECT_INVALID)
{
if(ai_TryRapidShotFeat(oCreature, oTarget, nInMelee)) return;
if(ai_TryRangedTalents(oCreature, oTarget, nInMelee)) return;
if(AI_DEBUG) ai_Debug("0i_actions", "559", GetName(OBJECT_SELF) + " does ranged attack on weakest: " + GetName(oTarget) + "!");
ai_ActionAttack(oCreature, AI_LAST_ACTION_RANGED_ATK, oTarget, nInMelee, TRUE);
return;
@@ -1112,7 +1148,7 @@ void ai_ActionTryHealing(object oCreature, object oTarget)
}
int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
{
if(AI_DEBUG) ai_Debug("0i_actions", "733", "Try healing: oCreature: " + GetName(oCreature) +
if(AI_DEBUG) ai_Debug("0i_actions", "1136", "Try healing: oCreature: " + GetName(oCreature) +
" oTarget: " + GetName(oTarget) + " No Party Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_PARTY_HEALING_OFF)) +
" No Self Healing: " + IntToString(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF)) +
" AI_I_AM_BEING_HEALED: " + IntToString(GetLocalInt(oTarget, "AI_I_AM_BEING_HEALED")) +
@@ -1133,52 +1169,92 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
oCreature != oTarget) return FALSE;
if(ai_GetAIMode(oCreature, AI_MODE_SELF_HEALING_OFF) &&
oCreature == oTarget) return FALSE;
// Undead don't heal so lets skip this for them, maybe later we can fix this.
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD) return FALSE;
int nHpLost = ai_GetPercHPLoss(oTarget);
// If the player is forcing a heal then we always heal.
if(bForce && nHpLost < 100) nHpLost = 0;
if(AI_DEBUG) ai_Debug("0i_actions", "743", "nHpLost: " + IntToString(nHpLost) +
if(AI_DEBUG) ai_Debug("0i_actions", "1160", "nHpLost: " + IntToString(nHpLost) +
" limit: " + IntToString(ai_GetHealersHpLimit(oTarget, FALSE)));
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE))
// Check to see if we need poison, disease, or ability drain removed.
int nEffectType;
effect eEffect = GetFirstEffect(oTarget);
while(GetIsEffectValid(eEffect))
{
// Check to see if we need poison, disease, or ability drain removed.
int nEffectType;
effect eEffect = GetFirstEffect(oTarget);
while(GetIsEffectValid(eEffect))
nEffectType = GetEffectType(eEffect);
if(AI_DEBUG) ai_Debug("0i_actions", "1168", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
if(nEffectType == EFFECT_TYPE_DISEASE)
{
nEffectType = GetEffectType(eEffect);
if(AI_DEBUG) ai_Debug("0i_actions", "1094", "Checking to cure(31/32/39) nEffectType: " + IntToString(nEffectType));
if(nEffectType == EFFECT_TYPE_DISEASE)
if(AI_DEBUG) ai_Debug("0i_actions", "1171", GetName(oTarget) + " is diseased!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1097", "I am diseased!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_DISEASED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 5, ":43:4:14:15:16:");
SpeakString(AI_I_AM_DISEASED, TALKVOLUME_SILENT_TALK);
}
else if(nEffectType == EFFECT_TYPE_POISON)
}
else if(nEffectType == EFFECT_TYPE_POISON)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1181", GetName(oTarget) + " is poisoned!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1107", "I am poisoned!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_POISONED, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 6, ":43:4:14:15:16:19:");
SpeakString(AI_I_AM_POISONED, TALKVOLUME_SILENT_TALK);
}
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
}
else if(nEffectType == EFFECT_TYPE_ABILITY_DECREASE)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1191", GetName(oTarget) + " is weak!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(AI_DEBUG) ai_Debug("0i_actions", "1117", "I am weak!");
if(ai_HealSickness(oCreature, oTarget, ai_GetPlayerMaster(oCreature), AI_ALLY_IS_WEAK, bForce)) return TRUE;
if(oCreature == oTarget)
{
if(!d20()) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
}
if(!Random(20)) ai_HaveCreatureSpeak(oCreature, 3, ":43:4:5:");
SpeakString(AI_I_AM_WEAK, TALKVOLUME_SILENT_TALK);
}
eEffect = GetNextEffect(oTarget);
}
eEffect = GetNextEffect(oTarget);
}
// Everything below here is for healing.
if(nHpLost >= ai_GetHealersHpLimit(oTarget, FALSE)) return FALSE;
// Undead require inflict spells to heal!
object oMaster = ai_GetPlayerMaster(oCreature);
if(GetRacialType(oTarget) == RACIAL_TYPE_UNDEAD)
{
// Do we have no magic on?
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{
int nClass, nPosition = 1;
string sMemorized;
while(nPosition <= AI_MAX_CLASSES_PER_CHARACTER)
{
nClass = GetClassByPosition(nPosition, oCreature);
if(AI_DEBUG) ai_Debug("0i_actions", "753", "nClass: " + IntToString(nClass));
if(nClass == CLASS_TYPE_INVALID) break;
sMemorized = Get2DAString("classes", "MemorizesSpells", nClass);
// If Memorized column is "" then they are not a caster.
if(sMemorized != "")
{
if(sMemorized == "1")
{
if(ai_CastMemorizedInflict(oCreature, oTarget, oMaster, nClass))
{
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
return TRUE;
}
}
else if(ai_CastKnownInflict(oCreature, oTarget, oMaster, nClass))
{
SetLocalInt(oTarget, "AI_I_AM_BEING_HEALED", TRUE);
return TRUE;
}
}
nPosition++;
}
}
// We can't heal ourselves! Can any of our allies? Lets ask.
if(oCreature == oTarget)
{
SetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT", GetLocalInt(oCreature, "AI_WOUNDED_SHOUT_LIMIT") + 1);
SpeakString(AI_I_AM_WOUNDED, TALKVOLUME_SILENT_TALK);
}
return FALSE;
}
@@ -1192,7 +1268,6 @@ int ai_TryHealing(object oCreature, object oTarget, int bForce = FALSE)
return TRUE;
}
}
object oMaster = ai_GetPlayerMaster(oCreature);
// Do we have no magic on?
if(!ai_GetMagicMode(oCreature, AI_MAGIC_NO_MAGIC))
{

Some files were not shown because too many files have changed in this diff Show More