Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74ede2e7dd |
@@ -4,8 +4,6 @@
|
|||||||
//:://////////////////////////////////////////////
|
//:://////////////////////////////////////////////
|
||||||
/** @file
|
/** @file
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@author Primogenitor
|
@author Primogenitor
|
||||||
@date 2005.09.23 - Rebuilt the system - Ornedan
|
@date 2005.09.23 - Rebuilt the system - Ornedan
|
||||||
*/
|
*/
|
||||||
@@ -21,29 +19,29 @@ const int DYNCONV_EXITED = -2;
|
|||||||
const int DYNCONV_ABORTED = -3;
|
const int DYNCONV_ABORTED = -3;
|
||||||
const int DYNCONV_SETUP_STAGE = -1;
|
const int DYNCONV_SETUP_STAGE = -1;
|
||||||
|
|
||||||
const int DYNCONV_TOKEN_HEADER = 99;
|
const int DYNCONV_TOKEN_HEADER = 16183899;
|
||||||
const int DYNCONV_TOKEN_REPLY_0 = 100;
|
const int DYNCONV_TOKEN_REPLY_0 = 161838100;
|
||||||
const int DYNCONV_TOKEN_REPLY_1 = 101;
|
const int DYNCONV_TOKEN_REPLY_1 = 161838101;
|
||||||
const int DYNCONV_TOKEN_REPLY_2 = 102;
|
const int DYNCONV_TOKEN_REPLY_2 = 161838102;
|
||||||
const int DYNCONV_TOKEN_REPLY_3 = 103;
|
const int DYNCONV_TOKEN_REPLY_3 = 161838103;
|
||||||
const int DYNCONV_TOKEN_REPLY_4 = 104;
|
const int DYNCONV_TOKEN_REPLY_4 = 161838104;
|
||||||
const int DYNCONV_TOKEN_REPLY_5 = 105;
|
const int DYNCONV_TOKEN_REPLY_5 = 161838105;
|
||||||
const int DYNCONV_TOKEN_REPLY_6 = 106;
|
const int DYNCONV_TOKEN_REPLY_6 = 161838106;
|
||||||
const int DYNCONV_TOKEN_REPLY_7 = 107;
|
const int DYNCONV_TOKEN_REPLY_7 = 161838107;
|
||||||
const int DYNCONV_TOKEN_REPLY_8 = 108;
|
const int DYNCONV_TOKEN_REPLY_8 = 161838108;
|
||||||
const int DYNCONV_TOKEN_REPLY_9 = 109;
|
const int DYNCONV_TOKEN_REPLY_9 = 161838109;
|
||||||
const int DYNCONV_TOKEN_EXIT = 110;
|
const int DYNCONV_TOKEN_EXIT = 161838110;
|
||||||
const int DYNCONV_TOKEN_WAIT = 111;
|
const int DYNCONV_TOKEN_WAIT = 161838111;
|
||||||
const int DYNCONV_TOKEN_NEXT = 112;
|
const int DYNCONV_TOKEN_NEXT = 161838112;
|
||||||
const int DYNCONV_TOKEN_PREV = 113;
|
const int DYNCONV_TOKEN_PREV = 161838113;
|
||||||
const int DYNCONV_MIN_TOKEN = 99;
|
const int DYNCONV_MIN_TOKEN = 16183899;
|
||||||
const int DYNCONV_MAX_TOKEN = 113;
|
const int DYNCONV_MAX_TOKEN = 161838113;
|
||||||
|
|
||||||
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
|
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
|
||||||
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
|
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
|
||||||
const int DYNCONV_STRREF_NEXT = 16824204; // "Next"
|
const int DYNCONV_STRREF_NEXT = 16824204; // "Next"
|
||||||
const int DYNCONV_STRREF_ABORT_CONVO = 16824212; // "Abort"
|
const int DYNCONV_STRREF_ABORT_CONVO = 16824212; // "Abort"
|
||||||
const int DYNCONV_STRREF_EXIT_CONVO = 78; // "Exit"
|
const int DYNCONV_STRREF_EXIT_CONVO = 16183878; // "Exit"
|
||||||
|
|
||||||
const string DYNCONV_SCRIPT = "DynConv_Script";
|
const string DYNCONV_SCRIPT = "DynConv_Script";
|
||||||
const string DYNCONV_VARIABLE = "DynConv_Var";
|
const string DYNCONV_VARIABLE = "DynConv_Var";
|
||||||
|
|||||||
@@ -1643,7 +1643,60 @@ int GetIsMagicItem(object oItem)
|
|||||||
int FeatToIprop(int nFeat)
|
int FeatToIprop(int nFeat)
|
||||||
{
|
{
|
||||||
switch(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_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_BATTLE_AXE: return IP_CONST_FEAT_WEAPON_FOCUS_BATTLE_AXE;
|
||||||
case FEAT_WEAPON_FOCUS_CLUB: return IP_CONST_FEAT_WEAPON_FOCUS_CLUB;
|
case FEAT_WEAPON_FOCUS_CLUB: return IP_CONST_FEAT_WEAPON_FOCUS_CLUB;
|
||||||
|
|||||||
@@ -401,4 +401,3 @@ int GetBestAvailableSpell(object oTarget)
|
|||||||
if(nBestSpell == 99999) nBestSpell = GetBestL0Spell(oTarget, nBestSpell);
|
if(nBestSpell == 99999) nBestSpell = GetBestL0Spell(oTarget, nBestSpell);
|
||||||
return nBestSpell;
|
return nBestSpell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -572,7 +572,10 @@ int GetMaxEssentiaCapacity(object oMeldshaper, int nClass, int nMeld)
|
|||||||
{
|
{
|
||||||
int nMax = 1; // Always can invest one
|
int nMax = 1; // Always can invest one
|
||||||
int nHD = GetHitDice(oMeldshaper);
|
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 >= 18) nMax = 4;
|
||||||
else if (nHD >= 12) nMax = 3;
|
else if (nHD >= 12) nMax = 3;
|
||||||
else if (nHD >= 6) nMax = 2;
|
else if (nHD >= 6) nMax = 2;
|
||||||
|
|||||||
@@ -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));
|
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is armor; attacker = "+GetName(oAttacker)+", defender = "+GetName(oDefender));
|
||||||
}
|
}
|
||||||
// is the spell type item a weapon?
|
// 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
|
// determine the target, if not already given
|
||||||
if (oSpellTarget == OBJECT_INVALID)
|
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");
|
if (DEBUG) DoDebug("GetIsOnHitCastSpell: item "+GetName(oSpellCastItem)+" is neither weapon nor armor; returning FALSE");
|
||||||
return 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)
|
// the spell origin must possess the item that cast the spell (at least for the aurora engine, in prc_inc_combat that may differ)
|
||||||
|
|||||||
@@ -308,7 +308,7 @@ int FindUnarmedDamage(object oCreature)
|
|||||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
||||||
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
|
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
|
||||||
|
|
||||||
//:: Expansion / Compression powers
|
/* //:: Expansion / Compression powers (Double dipping?)
|
||||||
int nExpansion = GetLocalInt(oCreature, "PRC_Power_Expansion_SizeIncrease");
|
int nExpansion = GetLocalInt(oCreature, "PRC_Power_Expansion_SizeIncrease");
|
||||||
int nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
|
int nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
|
||||||
|
|
||||||
@@ -320,7 +320,7 @@ int FindUnarmedDamage(object oCreature)
|
|||||||
if (nCompression)
|
if (nCompression)
|
||||||
{
|
{
|
||||||
iSize -= nCompression;
|
iSize -= nCompression;
|
||||||
}
|
} */
|
||||||
|
|
||||||
iMonkDamage += iDieIncrease;
|
iMonkDamage += iDieIncrease;
|
||||||
iShouDamage += iDieIncrease;
|
iShouDamage += iDieIncrease;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//::///////////////////////////////////////////////
|
//::///////////////////////////////////////////////
|
||||||
//:: Weapon Restriction System Include
|
//:: Weapon Restriction System Include
|
||||||
//:: prc_inc_restwpn.nss
|
//:: prc_inc_wpnrest.nss
|
||||||
//::///////////////////////////////////////////////
|
//::///////////////////////////////////////////////
|
||||||
/*
|
/*
|
||||||
Functions to support PnP Weapon Proficiency and
|
Functions to support PnP Weapon Proficiency and
|
||||||
@@ -23,6 +23,70 @@
|
|||||||
* @param nHand The hand the weapon is wielded in. In the form of
|
* @param nHand The hand the weapon is wielded in. In the form of
|
||||||
* ATTACK_BONUS_ONHAND or ATTACK_BONUS_OFFHAND.
|
* 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);
|
void DoRacialEquip(object oPC, int nBaseType);
|
||||||
|
|
||||||
//return if PC has proficiency in an item
|
//return if PC has proficiency in an item
|
||||||
|
|||||||
@@ -111,48 +111,3 @@ const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
|
|||||||
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
|
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
|
||||||
// Right Button Enabled Bind for Power Attack NUI
|
// Right Button Enabled Bind for Power Attack NUI
|
||||||
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
||||||
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
// //
|
|
||||||
// NUI Level Up //
|
|
||||||
// //
|
|
||||||
//////////////////////////////////////////////////
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_WINDOW_ID = "prcLevelUpNui";
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID = "NuiLevelUpCircleButton_";
|
|
||||||
const string NUI_LEVEL_UP_SPELL_BUTTON_BASEID = "NuiLevelUpSpellButton_";
|
|
||||||
const string NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledSpellButton_";
|
|
||||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID = "NuiLevelUpChosenSpellButton_";
|
|
||||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledChosenSpellButton_";
|
|
||||||
const string NUI_LEVEL_UP_DONE_BUTTON = "NuiLevelUpDoneButton";
|
|
||||||
const string NUI_LEVEL_UP_RESET_BUTTON = "NuiLevelUpResetButton";
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_SELECTED_CLASS_VAR = "NUILevelUpSelectedClass";
|
|
||||||
const string NUI_LEVEL_UP_SELECTED_CIRCLE_VAR = "NUILevelUpSelectedCircle";
|
|
||||||
const string NUI_LEVEL_UP_KNOWN_SPELLS_VAR = "NUILevelUpKnownSpells";
|
|
||||||
const string NUI_LEVEL_UP_CHOSEN_SPELLS_VAR = "NUILevelUpChosenSpells";
|
|
||||||
const string NUI_LEVEL_UP_EXPANDED_KNOW_LIST_VAR = "NUILevelUpExpKnowList";
|
|
||||||
const string NUI_LEVEL_UP_POWER_LIST_VAR = "NUILevelUpPowerList";
|
|
||||||
const string NUI_LEVEL_UP_DISCIPLINE_INFO_VAR = "GetDisciplineInfoObjectCache_";
|
|
||||||
const string NUI_LEVEL_UP_SPELLID_LIST_VAR = "NUILevelUpSpellIDList_";
|
|
||||||
const string NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR = "NUIRemainingChoicesCache";
|
|
||||||
const string NUI_LEVEL_UP_RELEARN_LIST_VAR = "NUILevelUpRelearnList";
|
|
||||||
const string NUI_LEVEL_UP_ARCHIVIST_NEW_SPELLS_LIST_VAR = "NUILevelUpArchivistNewSpellsList";
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_EXPANDED_CHOICES_VAR = "NUIExpandedChoices";
|
|
||||||
const string NUI_LEVEL_UP_EPIC_EXPANDED_CHOICES_VAR = "NUIEpicExpandedChoices";
|
|
||||||
|
|
||||||
const int NUI_LEVEL_UP_MANEUVER_PREREQ_LIMIT = 6;
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_MANEUVER_TOTAL = "ManeuverTotal";
|
|
||||||
const string NUI_LEVEL_UP_STANCE_TOTAL = "StanceTotal";
|
|
||||||
|
|
||||||
const string NUI_LEVEL_UP_SPELLBOOK_OBJECT_CACHE_VAR = "GetSpellListObjectCache_";
|
|
||||||
const string NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR = "GetInvokerKnownListObjectCache_";
|
|
||||||
|
|
||||||
const string NUI_SPELL_DESCRIPTION_FEATID_VAR = "NUISpellDescriptionFeatID";
|
|
||||||
const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
|
|
||||||
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
|
|
||||||
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,10 @@
|
|||||||
//:: Created By: Rakiov
|
//:: Created By: Rakiov
|
||||||
//:: Created On: 24.05.2005
|
//:: Created On: 24.05.2005
|
||||||
//:://////////////////////////////////////////////
|
//:://////////////////////////////////////////////
|
||||||
|
#include "inc_newspellbook"
|
||||||
#include "prc_nui_com_inc"
|
#include "psi_inc_psifunc"
|
||||||
|
#include "inc_lookups"
|
||||||
|
#include "prc_nui_consts"
|
||||||
|
|
||||||
//
|
//
|
||||||
// GetSpellListForCircle
|
// GetSpellListForCircle
|
||||||
@@ -41,6 +43,69 @@ json GetSpellListForCircle(object oPlayer, int nClass, int circle);
|
|||||||
//
|
//
|
||||||
json GetSupportedNUISpellbookClasses(object oPlayer);
|
json GetSupportedNUISpellbookClasses(object oPlayer);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetCurrentSpellLevel
|
||||||
|
// Gets the current spell level the class can achieve at the current
|
||||||
|
// caster level (ranging from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
// nLevel:int the caster level
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the circle the class can achieve currently
|
||||||
|
//
|
||||||
|
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetMaxSpellLevel
|
||||||
|
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the highest circle that can be achieved
|
||||||
|
//
|
||||||
|
int GetMaxSpellLevel(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetMinSpellLevel
|
||||||
|
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the lowest circle that can be achieved
|
||||||
|
//
|
||||||
|
int GetMinSpellLevel(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetHighestLevelPossibleInClass
|
||||||
|
// Given a class Id this will determine what the max level of a class can be
|
||||||
|
// achieved
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the ClassID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// int the highest possible level the class can achieve
|
||||||
|
//
|
||||||
|
int GetHighestLevelPossibleInClass(int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetClassSpellbookFile
|
||||||
|
// Gets the class 2da spellbook/ability for the given class Id
|
||||||
|
//
|
||||||
|
// Arguments:
|
||||||
|
// nClass:int the classID
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// string the 2da file name for the spell/abilities of the ClassID
|
||||||
|
//
|
||||||
|
string GetClassSpellbookFile(int nClass);
|
||||||
|
|
||||||
//
|
//
|
||||||
// IsSpellKnown
|
// IsSpellKnown
|
||||||
// Returns whether the player with the given class, spell file, and spellbook id
|
// Returns whether the player with the given class, spell file, and spellbook id
|
||||||
@@ -169,6 +234,23 @@ json GetMetaMysteryFeatList();
|
|||||||
//
|
//
|
||||||
int GetTrueClassIfRHD(object oPlayer, int nClass);
|
int GetTrueClassIfRHD(object oPlayer, int nClass);
|
||||||
|
|
||||||
|
//
|
||||||
|
// GetBinderSpellToFeatDictionary
|
||||||
|
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||||
|
// to their feat. This is constructed based off the binder's known location of
|
||||||
|
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||||
|
// this it will be saved to the player locally as a cached result since we do
|
||||||
|
// not need to call this again.
|
||||||
|
//
|
||||||
|
// Argument:
|
||||||
|
// oPlayer:object the player
|
||||||
|
//
|
||||||
|
// Returns:
|
||||||
|
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||||
|
// and the FeatID of a vestige ability
|
||||||
|
//
|
||||||
|
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||||
|
|
||||||
//
|
//
|
||||||
// ShouldAddSpell
|
// ShouldAddSpell
|
||||||
// Given a spellId and a class, determines if the spell should be added to the
|
// Given a spellId and a class, determines if the spell should be added to the
|
||||||
@@ -236,18 +318,6 @@ json GetInvokerEssenceSpellList(int nClass, object oPlayer=OBJECT_SELF);
|
|||||||
//
|
//
|
||||||
int JsonArrayContainsInt(json list, int item);
|
int JsonArrayContainsInt(json list, int item);
|
||||||
|
|
||||||
//
|
|
||||||
// IsSpellbookNUIOpen
|
|
||||||
// Checks to see if the Spellbook NUI is open on a given player.
|
|
||||||
//
|
|
||||||
// Arguments:
|
|
||||||
// oPC:object the player
|
|
||||||
//
|
|
||||||
// Returns:
|
|
||||||
// int:Boolean TRUE if window is open, FALSE otherwise
|
|
||||||
//
|
|
||||||
int IsSpellbookNUIOpen(object oPC);
|
|
||||||
|
|
||||||
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
|
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
|
||||||
{
|
{
|
||||||
json retValue = JsonArray();
|
json retValue = JsonArray();
|
||||||
@@ -327,6 +397,86 @@ int ShouldAddSpell(int nClass, int spellId, object oPlayer=OBJECT_SELF)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||||
|
{
|
||||||
|
// a dictionary of <SpellID, FeatID>
|
||||||
|
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||||
|
// if this hasn't been created, create it now.
|
||||||
|
if (binderDict == JsonNull())
|
||||||
|
binderDict = JsonObject();
|
||||||
|
else
|
||||||
|
return binderDict;
|
||||||
|
|
||||||
|
// the starting row for binder spells
|
||||||
|
int spellIndex = 19070;
|
||||||
|
// the starting row for binder feats
|
||||||
|
int featIndex = 9030;
|
||||||
|
//the end of the binder spells/feats
|
||||||
|
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||||
|
{
|
||||||
|
// get the SpellID tied to the feat
|
||||||
|
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||||
|
// if the spellID matches the current index, then this is the spell
|
||||||
|
// attached to the feat
|
||||||
|
if (spellID == spellIndex)
|
||||||
|
{
|
||||||
|
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||||
|
|
||||||
|
// move to next spell/feat
|
||||||
|
featIndex++;
|
||||||
|
spellIndex++;
|
||||||
|
}
|
||||||
|
// else we have reached a subdial spell
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// loop through until we reach back at spellID
|
||||||
|
while (spellIndex < spellID)
|
||||||
|
{
|
||||||
|
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||||
|
|
||||||
|
// add the sub radial to the dict, tied to the master's FeatID
|
||||||
|
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||||
|
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||||
|
|
||||||
|
spellIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||||
|
// if it happens then move on
|
||||||
|
if (spellIndex > spellID)
|
||||||
|
featIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache the result
|
||||||
|
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||||
|
return binderDict;
|
||||||
|
}
|
||||||
|
|
||||||
|
string GetClassSpellbookFile(int nClass)
|
||||||
|
{
|
||||||
|
string sFile;
|
||||||
|
// Spontaneous casters use a specific file name structure
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
sFile = GetFileForClass(nClass);
|
||||||
|
}
|
||||||
|
// everyone else uses this structure
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sFile = GetAMSDefinitionFileName(nClass);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
sFile = "vestiges";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sFile;
|
||||||
|
}
|
||||||
|
|
||||||
json GetSupportedNUISpellbookClasses(object oPlayer)
|
json GetSupportedNUISpellbookClasses(object oPlayer)
|
||||||
{
|
{
|
||||||
json retValue = JsonArray();
|
json retValue = JsonArray();
|
||||||
@@ -376,6 +526,167 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||||
|
{
|
||||||
|
int currentLevel = nLevel;
|
||||||
|
|
||||||
|
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||||
|
if(nClass == CLASS_TYPE_WARBLADE
|
||||||
|
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||||
|
|| nClass == CLASS_TYPE_CRUSADER
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||||
|
{
|
||||||
|
return 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Binders don't really have a concept of spell level
|
||||||
|
if (nClass == CLASS_TYPE_BINDER
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
//Shadowsmith has no concept of spell levels
|
||||||
|
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||||
|
return 4;
|
||||||
|
|
||||||
|
// Spont casters have their own function
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
|
||||||
|
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||||
|
return maxLevel;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// everyone else uses this
|
||||||
|
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||||
|
|
||||||
|
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_PSION
|
||||||
|
|| nClass == CLASS_TYPE_PSYWAR
|
||||||
|
|| nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND)
|
||||||
|
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||||
|
|
||||||
|
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||||
|
|
||||||
|
// in case we somehow go over bounds just don't :)
|
||||||
|
if (currentLevel >= totalLevel)
|
||||||
|
currentLevel = totalLevel - 1;
|
||||||
|
|
||||||
|
//Psionics have MaxPowerLevel as their column name
|
||||||
|
string columnName = "MaxPowerLevel";
|
||||||
|
|
||||||
|
//Invokers have MaxInvocationLevel
|
||||||
|
if (nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||||
|
columnName = "MaxInvocationLevel";
|
||||||
|
|
||||||
|
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||||
|
{
|
||||||
|
columnName = "EvolvingMind";
|
||||||
|
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
columnName = "VestigeLvl";
|
||||||
|
spellLevel2da = "cls_bind_binder";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToB doesn't have a concept of this, but we don't care.
|
||||||
|
|
||||||
|
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||||
|
return maxLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMinSpellLevel(int nClass)
|
||||||
|
{
|
||||||
|
// again sponts have their own function
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_PSION
|
||||||
|
|| nClass == CLASS_TYPE_PSYWAR
|
||||||
|
|| nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND
|
||||||
|
|| nClass == CLASS_TYPE_WARBLADE
|
||||||
|
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||||
|
|| nClass == CLASS_TYPE_CRUSADER
|
||||||
|
|| nClass == CLASS_TYPE_WARLOCK
|
||||||
|
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||||
|
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||||
|
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||||
|
|| nClass == CLASS_TYPE_BINDER)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return GetCurrentSpellLevel(nClass, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMaxSpellLevel(int nClass)
|
||||||
|
{
|
||||||
|
if (nClass == CLASS_TYPE_WILDER
|
||||||
|
|| nClass == CLASS_TYPE_PSION)
|
||||||
|
return 9;
|
||||||
|
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||||
|
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||||
|
|| nClass == CLASS_TYPE_WARMIND)
|
||||||
|
return 5;
|
||||||
|
if (nClass == CLASS_TYPE_PSYWAR)
|
||||||
|
return 6;
|
||||||
|
|
||||||
|
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetHighestLevelPossibleInClass(int nClass)
|
||||||
|
{
|
||||||
|
string sFile;
|
||||||
|
|
||||||
|
//sponts have their spells in the classes.2da
|
||||||
|
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||||
|
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||||
|
{
|
||||||
|
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// everyone else uses this
|
||||||
|
sFile = GetAMSKnownFileName(nClass);
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||||
|
{
|
||||||
|
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nClass == CLASS_TYPE_BINDER)
|
||||||
|
{
|
||||||
|
sFile = "cls_bind_binder";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Get2DARowCount(sFile);
|
||||||
|
}
|
||||||
|
|
||||||
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||||
{
|
{
|
||||||
// This controls who can use the Spellbook NUI, if for some reason you don't
|
// This controls who can use the Spellbook NUI, if for some reason you don't
|
||||||
@@ -387,7 +698,8 @@ int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
// Arcane Spont
|
// Arcane Spont
|
||||||
if (nClass == CLASS_TYPE_BEGUILER
|
if (nClass == CLASS_TYPE_ASSASSIN
|
||||||
|
|| nClass == CLASS_TYPE_BEGUILER
|
||||||
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|
||||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||||
|| nClass == CLASS_TYPE_DUSKBLADE
|
|| nClass == CLASS_TYPE_DUSKBLADE
|
||||||
@@ -505,7 +817,8 @@ int CanClassUseMetamagicFeats(int nClass)
|
|||||||
// I don't want to spend the time looping through each class's
|
// I don't want to spend the time looping through each class's
|
||||||
// feat 2da so this is the list of all classes that are allowed to use the
|
// feat 2da so this is the list of all classes that are allowed to use the
|
||||||
// Spellbook NUI and can use Metamagic
|
// Spellbook NUI and can use Metamagic
|
||||||
return (nClass == CLASS_TYPE_BARD
|
return (nClass == CLASS_TYPE_ASSASSIN
|
||||||
|
|| nClass == CLASS_TYPE_BARD
|
||||||
|| nClass == CLASS_TYPE_SORCERER
|
|| nClass == CLASS_TYPE_SORCERER
|
||||||
|| nClass == CLASS_TYPE_BEGUILER
|
|| nClass == CLASS_TYPE_BEGUILER
|
||||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||||
@@ -525,6 +838,7 @@ int CanClassUseSuddenMetamagicFeats(int nClass)
|
|||||||
// Spellbook NUI and can use Sudden Metamagic
|
// Spellbook NUI and can use Sudden Metamagic
|
||||||
return (nClass == CLASS_TYPE_SHADOWLORD
|
return (nClass == CLASS_TYPE_SHADOWLORD
|
||||||
|| nClass == CLASS_TYPE_ARCHIVIST
|
|| nClass == CLASS_TYPE_ARCHIVIST
|
||||||
|
|| nClass == CLASS_TYPE_ASSASSIN
|
||||||
|| nClass == CLASS_TYPE_BARD
|
|| nClass == CLASS_TYPE_BARD
|
||||||
|| nClass == CLASS_TYPE_BEGUILER
|
|| nClass == CLASS_TYPE_BEGUILER
|
||||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||||
@@ -832,14 +1146,3 @@ int JsonArrayContainsInt(json list, int item)
|
|||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsSpellbookNUIOpen(object oPC)
|
|
||||||
{
|
|
||||||
int nPreviousToken = NuiFindWindow(oPC, PRC_SPELLBOOK_NUI_WINDOW_ID);
|
|
||||||
if (nPreviousToken != 0)
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
@@ -180,6 +180,24 @@ void RunImpactScript(object oPC, int nSpellID, int nEventType)
|
|||||||
DeleteLocalInt(oPC, PRC_SPELLID_OVERRIDE);
|
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
|
//Returns true if the spell is one of the cure spells
|
||||||
int IsCure(int nSpellID)
|
int IsCure(int nSpellID)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -520,9 +520,9 @@ void GainPsionicFocus(object oGainee = OBJECT_SELF)
|
|||||||
{
|
{
|
||||||
int nPsySneak = 1;
|
int nPsySneak = 1;
|
||||||
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_2d6, oGainee))
|
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_2d6, oGainee))
|
||||||
nPsySneak += 2;
|
nPsySneak += 1;
|
||||||
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_3d6, oGainee))
|
if(GetHasFeat(FEAT_PSY_SNEAK_ATTACK_3d6, oGainee))
|
||||||
nPsySneak += 3;
|
nPsySneak += 1;
|
||||||
|
|
||||||
SetLocalInt(oGainee, "PsyRogueSneak",nPsySneak);
|
SetLocalInt(oGainee, "PsyRogueSneak",nPsySneak);
|
||||||
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oGainee));
|
DelayCommand(0.1, ExecuteScript("prc_sneak_att", oGainee));
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "x0_i0_position"
|
#include "x0_i0_position"
|
||||||
#include "X0_INC_HENAI"
|
#include "X0_INC_HENAI"
|
||||||
#include "x3_inc_skin"
|
#include "x3_inc_skin"
|
||||||
|
#include "prc_racial_const"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@@ -638,7 +639,7 @@ int HorseGetMountTail(object oHorse);
|
|||||||
// FILE: x3_inc_horse FUNCTION: HorseGetMountFailureMessage()
|
// FILE: x3_inc_horse FUNCTION: HorseGetMountFailureMessage()
|
||||||
// This is a companion function to HorseGetCanBeMounted. If you need a text
|
// This is a companion function to HorseGetCanBeMounted. If you need a text
|
||||||
// message that explains why the horse cannot be mounted.
|
// 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()
|
// FILE: x3_inc_horse FUNCTION: HorseAddHorseMenu()
|
||||||
@@ -1050,6 +1051,8 @@ void HORSE_SupportOriginalSpeed(object oRider)
|
|||||||
} // check to see if matches conditions
|
} // check to see if matches conditions
|
||||||
eSearch=GetNextEffect(oRider);
|
eSearch=GetNextEffect(oRider);
|
||||||
} // cycle through effects
|
} // cycle through effects
|
||||||
|
|
||||||
|
|
||||||
} // HORSE_SupportOriginalSpeed()
|
} // HORSE_SupportOriginalSpeed()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13852,7 +13852,7 @@
|
|||||||
"__struct_id": 0,
|
"__struct_id": 0,
|
||||||
"CR": {
|
"CR": {
|
||||||
"type": "float",
|
"type": "float",
|
||||||
"value": 0.5
|
"value": 0.3333
|
||||||
},
|
},
|
||||||
"FACTION": {
|
"FACTION": {
|
||||||
"type": "cexostring",
|
"type": "cexostring",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xp_multi", OBJECT_SELF);
|
//ExecuteScript("tab_xp_multi", OBJECT_SELF);
|
||||||
|
|
||||||
string sResref = GetResRef(OBJECT_SELF);
|
string sResref = GetResRef(OBJECT_SELF);
|
||||||
object oKiller = GetLastKiller();
|
object oKiller = GetLastKiller();
|
||||||
|
|||||||
@@ -13,5 +13,5 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,5 +13,5 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ void main()
|
|||||||
{
|
{
|
||||||
|
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
location lSource = GetLocation(OBJECT_SELF);
|
location lSource = GetLocation(OBJECT_SELF);
|
||||||
DelayCommand(1., ExplodeAtLocation(lSource, d12(55)));
|
DelayCommand(1., ExplodeAtLocation(lSource, d12(55)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
if (!GetIsPC(oPC)) return;
|
if (!GetIsPC(oPC)) return;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
object oTarget;
|
object oTarget;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ void main()
|
|||||||
{
|
{
|
||||||
|
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
SpeakString("Dont think you have won just yet!", TALKVOLUME_TALK);
|
SpeakString("Dont think you have won just yet!", TALKVOLUME_TALK);
|
||||||
|
|
||||||
object oSpawn;
|
object oSpawn;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
while (GetIsObjectValid(GetMaster(oPC)))
|
while (GetIsObjectValid(GetMaster(oPC)))
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
|
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
object oTarget;
|
object oTarget;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
/// Local Override (int): PS_FORCE_SEARCH_BUTTON
|
/// Local Override (int): PS_FORCE_SEARCH_BUTTON
|
||||||
/// 1 = PS_TRUE
|
/// 1 = PS_TRUE
|
||||||
/// -1 = PS_FALSE
|
/// -1 = PS_FALSE
|
||||||
const int PS_FORCE_SEARCH_BUTTON_DEFAULT = PS_FALSE;
|
const int PS_FORCE_SEARCH_BUTTON_DEFAULT = -1;
|
||||||
|
|
||||||
/// @brief Determines whether item object state is saved to the database. The
|
/// @brief Determines whether item object state is saved to the database. The
|
||||||
/// object state includes variables and effects.
|
/// object state includes variables and effects.
|
||||||
@@ -42,7 +42,7 @@ const int PS_FORCE_SEARCH_BUTTON_DEFAULT = PS_FALSE;
|
|||||||
/// Local Override (int): PS_FORCE_OBJECT_STATE
|
/// Local Override (int): PS_FORCE_OBJECT_STATE
|
||||||
/// 1 = PS_TRUE
|
/// 1 = PS_TRUE
|
||||||
/// -1 = PS_FALSE
|
/// -1 = PS_FALSE
|
||||||
const int PS_FORCE_OBJECT_STATE_DEFAULT = PS_TRUE;
|
const int PS_FORCE_OBJECT_STATE_DEFAULT = 1;
|
||||||
|
|
||||||
/// @brief Sets the item storage limit.
|
/// @brief Sets the item storage limit.
|
||||||
/// Configuration File:
|
/// Configuration File:
|
||||||
@@ -79,7 +79,7 @@ const float PS_DISTANCE_DEFAULT = 2.0;
|
|||||||
/// Local Override (int): PS_ACCESS_TYPE
|
/// Local Override (int): PS_ACCESS_TYPE
|
||||||
/// 1 = PS_ACCESS_EXCLUSIVE
|
/// 1 = PS_ACCESS_EXCLUSIVE
|
||||||
/// 2 = PS_ACCESS_CONTENTIOUS
|
/// 2 = PS_ACCESS_CONTENTIOUS
|
||||||
const int PS_ACCESS_TYPE_DEFAULT = PS_ACCESS_EXCLUSIVE;
|
const int PS_ACCESS_TYPE_DEFAULT = 1;
|
||||||
|
|
||||||
/// @brief Set the container type. Containers can be of multiple types:
|
/// @brief Set the container type. Containers can be of multiple types:
|
||||||
/// - Public: Any player can open, deposit and withdraw items from this
|
/// - Public: Any player can open, deposit and withdraw items from this
|
||||||
@@ -101,7 +101,7 @@ const int PS_ACCESS_TYPE_DEFAULT = PS_ACCESS_EXCLUSIVE;
|
|||||||
/// 1 = PS_CONTAINER_PUBLIC
|
/// 1 = PS_CONTAINER_PUBLIC
|
||||||
/// 2 = PS_CONTAINER_CHARACTER
|
/// 2 = PS_CONTAINER_CHARACTER
|
||||||
/// 3 = PS_CONTAINER_CDKEY
|
/// 3 = PS_CONTAINER_CDKEY
|
||||||
const int PS_CONTAINER_TYPE_DEFAULT = PS_CONTAINER_PUBLIC;
|
const int PS_CONTAINER_TYPE_DEFAULT = 1;
|
||||||
|
|
||||||
/// @brief Set the default container type, if the container is an item. Containers
|
/// @brief Set the default container type, if the container is an item. Containers
|
||||||
/// can be of multiple types:
|
/// can be of multiple types:
|
||||||
@@ -124,7 +124,7 @@ const int PS_CONTAINER_TYPE_DEFAULT = PS_CONTAINER_PUBLIC;
|
|||||||
/// 1 = PS_CONTAINER_PUBLIC
|
/// 1 = PS_CONTAINER_PUBLIC
|
||||||
/// 2 = PS_CONTAINER_CHARACTER
|
/// 2 = PS_CONTAINER_CHARACTER
|
||||||
/// 3 = PS_CONTAINER_CDKEY
|
/// 3 = PS_CONTAINER_CDKEY
|
||||||
const int PS_CONTAINER_ITEM_TYPE_DEFAULT = PS_CONTAINER_CHARACTER;
|
const int PS_CONTAINER_ITEM_TYPE_DEFAULT = 2;
|
||||||
|
|
||||||
/// @brief Determines whether the player's inventory window will be opened
|
/// @brief Determines whether the player's inventory window will be opened
|
||||||
/// when a container is opened.
|
/// when a container is opened.
|
||||||
@@ -135,7 +135,7 @@ const int PS_CONTAINER_ITEM_TYPE_DEFAULT = PS_CONTAINER_CHARACTER;
|
|||||||
/// Local Override (int): PS_OPEN_INVENTORY
|
/// Local Override (int): PS_OPEN_INVENTORY
|
||||||
/// 1 = PS_TRUE
|
/// 1 = PS_TRUE
|
||||||
/// -1 = PS_FALSE
|
/// -1 = PS_FALSE
|
||||||
const int PS_OPEN_INVENTORY_DEFAULT = PS_TRUE;
|
const int PS_OPEN_INVENTORY_DEFAULT = 1;
|
||||||
|
|
||||||
/// @brief Determines the maximum amount of gold a container can store.
|
/// @brief Determines the maximum amount of gold a container can store.
|
||||||
/// If the container is set to store no gold, the form controls that
|
/// If the container is set to store no gold, the form controls that
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
object oPC = GetLastKiller();
|
object oPC = GetLastKiller();
|
||||||
|
|
||||||
object oTarget;
|
object oTarget;
|
||||||
|
|||||||
@@ -24,13 +24,14 @@ void main()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
|
ExecuteScript("pwfxp",OBJECT_SELF);
|
||||||
|
|
||||||
SpeakString("NW_I_AM_DEAD", TALKVOLUME_SILENT_TALK);
|
SpeakString("NW_I_AM_DEAD", TALKVOLUME_SILENT_TALK);
|
||||||
//Shout Attack my target, only works with the On Spawn In setup
|
//Shout Attack my target, only works with the On Spawn In setup
|
||||||
SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
|
SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
|
||||||
|
|
||||||
if(NPC_XP == 1)
|
/* if(NPC_XP == 1)
|
||||||
{
|
{
|
||||||
float fCR = GetChallengeRating(OBJECT_SELF);
|
float fCR = GetChallengeRating(OBJECT_SELF);
|
||||||
int nMonsterXP;
|
int nMonsterXP;
|
||||||
@@ -167,5 +168,5 @@ void main()
|
|||||||
GiveXPToCreature(oPC, nCharXP);
|
GiveXPToCreature(oPC, nCharXP);
|
||||||
oPC = GetNextFactionMember(oKiller, TRUE);
|
oPC = GetNextFactionMember(oKiller, TRUE);
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
479
src/module/nss/pwfxp.nss
Normal file
479
src/module/nss/pwfxp.nss
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
//PRC racial pack compatible PWFXP script
|
||||||
|
//
|
||||||
|
//PRC Version: 3.1e
|
||||||
|
//Written by: Silvercloud (scl.vcs-online.com) & Ornedan
|
||||||
|
// Modified by fluffyamoeba for 3.x versions of the PRC
|
||||||
|
/*
|
||||||
|
|
||||||
|
changes: 2007-11-14
|
||||||
|
|
||||||
|
- pwfxp_prc_race now reads the 2da cache directly.
|
||||||
|
|
||||||
|
- the race LA is done entirely through this script. DO NOT set PRC_XP_USE_SIMPLE_LA
|
||||||
|
or the XP penalty will be applied twice
|
||||||
|
|
||||||
|
- if using this with the supplied prc_pwondeath script, you don't need to make any
|
||||||
|
changes to nw_c2_default7 (the OnDeath script)
|
||||||
|
|
||||||
|
- prc_racial_const no longer used
|
||||||
|
|
||||||
|
=================
|
||||||
|
|
||||||
|
Include added for prc races: pwfxp_prc_race, modify this file if you want to
|
||||||
|
adjust ECLs (the subrace constants in pwfxp_def is removed).
|
||||||
|
|
||||||
|
Main function for determining ECL rewritten to hook into getECLMod.
|
||||||
|
|
||||||
|
package includes prc_racial_const for completeness, but you do not have to over-
|
||||||
|
write the one in your world per se (for example if you have more races).
|
||||||
|
|
||||||
|
have fun,
|
||||||
|
|
||||||
|
Silvercloud
|
||||||
|
|
||||||
|
|
||||||
|
//::///////////////////////////////////////////////
|
||||||
|
//:: XP Distribution Script by Knat
|
||||||
|
//:: pwfxp v1.70
|
||||||
|
//:: Copyright (c) 2001 Bioware Corp.
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
|
IMPORTANT: see pwfxp_def modifier definition script...
|
||||||
|
|
||||||
|
check this link in case you want to discuss this script:
|
||||||
|
http://www.thefold.org/nuke/modules.php?name=Forums&file=viewforum&f=69
|
||||||
|
|
||||||
|
This is a more sophisticated XP distribution script geared towards PWs.
|
||||||
|
It comes with two dozen XP modifiers to fine tune XP output and
|
||||||
|
is losely based on the old but solid TTV XP script.
|
||||||
|
|
||||||
|
here is a small example of features, all modifiers are scalable:
|
||||||
|
|
||||||
|
- independent XP modifier for every single level. this breaks nwns linear
|
||||||
|
XP progression and enables you to define your own progression function.
|
||||||
|
you can give out fast xp early and let players slow down at any rate you want.
|
||||||
|
or model your own progression function with the manipulation of two constants
|
||||||
|
|
||||||
|
- PCs suffer XP reduction if their level is not close enough to the average
|
||||||
|
party level. level 1 grouping with level 10 is probably not a good idea...
|
||||||
|
|
||||||
|
- PCs suffer XP reduction if their level is not close enough to the CR of the killed MOB
|
||||||
|
(both directions independent now)
|
||||||
|
|
||||||
|
- Adjustable & cached ECL modifiers, easy to sync with any subrace scripts
|
||||||
|
|
||||||
|
- Group bonus. groups receive a small XP bonus (or big, if you wish) to encourage teamplay
|
||||||
|
|
||||||
|
- Groupmembers need to be within minimum distance to the killed MOB if they want to receive XP
|
||||||
|
|
||||||
|
- associates get a share of the xp, but you can set a different divisor for each associate type
|
||||||
|
e.g.: henchman soak up more XP then animal companions
|
||||||
|
|
||||||
|
- several counter exploit mechanisms included
|
||||||
|
|
||||||
|
- many more, see the constants...
|
||||||
|
|
||||||
|
- easy to add new modifiers..
|
||||||
|
|
||||||
|
all in all, this is pushing the nwn XP system more close to what you get in a MMORPG. You can
|
||||||
|
make it very hard to level or easy as hell, with good control of group impact and flexible
|
||||||
|
boundaries.
|
||||||
|
|
||||||
|
system went through extensive beta tests at www.thefold.org - thanks to all the great
|
||||||
|
players and staff there...
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
--- USAGE --- --- USAGE --- --- USAGE --- --- USAGE --- --- USAGE ------------------------
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
just add the following line to the onDeath script of your creatures (default: nw_c2_default7):
|
||||||
|
|
||||||
|
ExecuteScript("pwfxp",OBJECT_SELF);
|
||||||
|
|
||||||
|
Don't forget to set the XP-Scale slider to 0 (module properties)
|
||||||
|
|
||||||
|
*note* if using your own prc_pwondeath script add this to that script instead.
|
||||||
|
|
||||||
|
ATTENTION: HOW TO REMOVE THE DOUBLE XP MESSAGE !
|
||||||
|
|
||||||
|
put this code above the pwfxp execution in your onDeath script
|
||||||
|
|
||||||
|
// safety mechanism in case creature kills itself
|
||||||
|
if(GetLastKiller() == OBJECT_SELF) return;
|
||||||
|
|
||||||
|
put this code near the bottom of your onDeath script to remove the double-xp message
|
||||||
|
thanks to spider661/Sotae for this catch...
|
||||||
|
|
||||||
|
// resurrect & self kill to bypass bioware xp message
|
||||||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectResurrection(), OBJECT_SELF);
|
||||||
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, EffectDamage(10000, DAMAGE_TYPE_MAGICAL, DAMAGE_POWER_PLUS_TWENTY), OBJECT_SELF);
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
changelog:
|
||||||
|
|
||||||
|
v1.7 update (3/2004)
|
||||||
|
|
||||||
|
- added PWFXP_MAXIMUM_XP constant due to user request...
|
||||||
|
|
||||||
|
v1.62 update (2/2004)
|
||||||
|
|
||||||
|
- fixed documentation error. using the wrong info could lead to divide by zero error
|
||||||
|
|
||||||
|
if you want to eliminate mob CR < PC-Level reduction:
|
||||||
|
set PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION to PWFXP_CR_MAX and
|
||||||
|
PWFXP_CR_LESSTHAN_PCLEVEL_NOXP to PWFXP_CR_MAX + 1
|
||||||
|
|
||||||
|
if you want to eliminate mob CR > PC-Level reduction:
|
||||||
|
set PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION to PWFXP_CR_MAX and
|
||||||
|
PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP to PWFXP_CR_MAX + 1
|
||||||
|
|
||||||
|
if you want to eliminate Average Party Level reduction:
|
||||||
|
set PWFXP_APL_REDUCTION to 40 and
|
||||||
|
PWFXP_APL_NOXP to 41
|
||||||
|
|
||||||
|
thanx to tribble for the catch
|
||||||
|
|
||||||
|
v1.61 update(1/2004)
|
||||||
|
|
||||||
|
- fixed minor naming convention error
|
||||||
|
|
||||||
|
v1.6 update(1/2004)
|
||||||
|
|
||||||
|
- improved XP divisor. you can now distinct between animal companion,
|
||||||
|
familiar, dominated, summoned and henchman. you can set a different
|
||||||
|
xp divisor for each of them. (default: henchman has max reduction impact followed
|
||||||
|
by dominated, summoned, familiars, animal companion)
|
||||||
|
|
||||||
|
see PWFXP_XP_DIVISOR_* constants
|
||||||
|
|
||||||
|
- added PWFXP_USE_TOTAL_XP_TO_COMPUTE_PCLEVEL constant
|
||||||
|
pc level gets computed based on the total XP instead of
|
||||||
|
using GetLevelBy functions if set to TRUE. this way players ready to levelup
|
||||||
|
can't bunker XP to gain better XP bonuses/modifiers.
|
||||||
|
|
||||||
|
- removed dumb debug fragments, no more svirfneblin invasions...
|
||||||
|
thanks to Beowulf for the catch...
|
||||||
|
|
||||||
|
v1.5 update(12/2003)
|
||||||
|
|
||||||
|
- improved ECL modifier: added caching to decrease cpu use
|
||||||
|
improved parser
|
||||||
|
|
||||||
|
v1.4 update(12/2003)
|
||||||
|
|
||||||
|
- removed constant PWFXP_CR_REDUCTION and PWFXP_CR_NOXP
|
||||||
|
|
||||||
|
- added 4 new constants instead to distinct between..
|
||||||
|
PC-Level > CR
|
||||||
|
PC-Level < CR
|
||||||
|
..cases:
|
||||||
|
|
||||||
|
PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION
|
||||||
|
PWFXP_CR_LESSTHAN_PCLEVEL_NOXP
|
||||||
|
PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION
|
||||||
|
PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP
|
||||||
|
|
||||||
|
- added PWFXP_USE_SETXP constant
|
||||||
|
|
||||||
|
- split the script up. now all constants are isolated in their own
|
||||||
|
definiton file (pwfxp_def). easier to update that way...
|
||||||
|
|
||||||
|
v1.3 update (12/2003)
|
||||||
|
|
||||||
|
- added PWFXP_LEVEL_MODIFIERS. this removes the linear xp output... read more below
|
||||||
|
|
||||||
|
v1.2 update (10/2003)
|
||||||
|
|
||||||
|
- killer gets excluded from distance check now if he *is* a PC.
|
||||||
|
he gets XP even if his spell kills something far away (e.g. long range spells,
|
||||||
|
damage over time spells. maybe traps, not tested so far. this does not include NPCs)
|
||||||
|
every other groupmember gets still checked for distance...
|
||||||
|
[thanks to telstar for the report/request...]
|
||||||
|
|
||||||
|
v1.1 initial full release (10/2003)
|
||||||
|
|
||||||
|
- fine tuned and slightly optimized code
|
||||||
|
- added debug toggle
|
||||||
|
|
||||||
|
v1.0 beta (8/2003):
|
||||||
|
|
||||||
|
- distance check should now work correctly
|
||||||
|
|
||||||
|
- minimum XP award (see new PWFXP_MINIMUM_XP constant)
|
||||||
|
|
||||||
|
- henchman, familiars, animal companions, summoned creatures and other NPCs in a player
|
||||||
|
group now take away XP. see PWFXP_XP_DIVISOR_PC and PWFXP_XP_DIVISOR_NPC constants
|
||||||
|
|
||||||
|
- made it easier to manage ECL modifiers. see PWFXP_ECL_MODIFIERS string constant
|
||||||
|
|
||||||
|
*/
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
//:: Created By: LasCivious & Knat
|
||||||
|
//:: Created On: 7/2003
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "pwfxp_def"
|
||||||
|
#include "pwfxp_prc_race"
|
||||||
|
|
||||||
|
|
||||||
|
int PWFXP_GetLevel(object oPC)
|
||||||
|
{
|
||||||
|
// we need to use a derivation of the base xp formular to compute the
|
||||||
|
// pc level based on total XP.
|
||||||
|
//
|
||||||
|
// base XP formula (x = pc level, t = total xp):
|
||||||
|
//
|
||||||
|
// t = x * (x-1) * 500
|
||||||
|
//
|
||||||
|
// need to use some base math..
|
||||||
|
// transform for pq formula use (remove brackets with x inside and zero right side)
|
||||||
|
//
|
||||||
|
// x^2 - x - (t / 500) = 0
|
||||||
|
//
|
||||||
|
// use pq formula to solve it [ x^2 + px + q = 0, p = -1, q = -(t/500) ]...
|
||||||
|
//
|
||||||
|
// that's our new formular to get the level based on total xp:
|
||||||
|
// level = 0.5 + sqrt(0.25 + (t/500))
|
||||||
|
//
|
||||||
|
if(PWFXP_USE_TOTAL_XP_TO_COMPUTE_PCLEVEL) // use total XP to compute PC level
|
||||||
|
return FloatToInt(0.5 + sqrt(0.25 + ( IntToFloat(GetXP(oPC)) / 500 )));
|
||||||
|
else // use total class level to compute PC level
|
||||||
|
return GetLevelByPosition(1,oPC) + GetLevelByPosition(2,oPC) + GetLevelByPosition(3,oPC);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// see PWFXP_ECL_MODIFIERS constant description
|
||||||
|
float PWFXP_GetECLModifier(object oPC)
|
||||||
|
{
|
||||||
|
// get current
|
||||||
|
int nHD = GetHitDice(oPC);
|
||||||
|
|
||||||
|
// get last PC HD from cache
|
||||||
|
int nECLHitDice = GetLocalInt(oPC,"PWFXP_ECL_HITDICE");
|
||||||
|
|
||||||
|
// last PC HD = current PC HD ? get ECL modifier from cache and return...
|
||||||
|
if(nECLHitDice == nHD) return GetLocalFloat(oPC,"PWFXP_ECL_MODIFIER");
|
||||||
|
|
||||||
|
// recompute ECL modifier and cache it
|
||||||
|
// this code section will run only in the case of two circumstances:
|
||||||
|
//
|
||||||
|
// 1. first time kill
|
||||||
|
// 2. pc hitdice change (e.g. levelup)
|
||||||
|
float fECLMod;
|
||||||
|
fECLMod = IntToFloat(nHD) / (IntToFloat(nHD) + IntToFloat(GetECLMod(oPC)));
|
||||||
|
SetLocalFloat(oPC,"PWFXP_ECL_MODIFIER", fECLMod);
|
||||||
|
SetLocalInt(oPC,"PWFXP_ECL_HITDICE",nHD);
|
||||||
|
return fECLMod;
|
||||||
|
}
|
||||||
|
// see PWFXP_LEVEL_MODIFIER constant description
|
||||||
|
float PWFXP_GetLevelModifier(int nLevel)
|
||||||
|
{
|
||||||
|
return StringToFloat(GetSubString( PWFXP_LEVEL_MODIFIERS, (nLevel - 1) * 7, 6));
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_APL_REDUCTION & PWFXP_APL_NOXP constant description
|
||||||
|
float PWFXP_GetLevelDistanceModifier(float fLevelDistance)
|
||||||
|
{
|
||||||
|
if( fLevelDistance >= PWFXP_APL_NOXP )
|
||||||
|
{
|
||||||
|
// level distance greater than maximum allowed > no XP award at all
|
||||||
|
return 0.0; // -100%
|
||||||
|
}
|
||||||
|
else if(fLevelDistance >= PWFXP_APL_REDUCTION)
|
||||||
|
{
|
||||||
|
// level distance greater than reduction limit ? reduce xp
|
||||||
|
return 1 - ((fLevelDistance - PWFXP_APL_REDUCTION) * PWFXP_APL_MODIFIER);
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION, PWFXP_CR_LESSTHAN_PCLEVEL_NOXP
|
||||||
|
// PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION, PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP
|
||||||
|
// constant description
|
||||||
|
float PWFXP_GetCRDistanceModifier(float fCRDistance)
|
||||||
|
{
|
||||||
|
// PC level > creature CR ?
|
||||||
|
if(fCRDistance < 0.0)
|
||||||
|
{
|
||||||
|
fCRDistance = fabs(fCRDistance);
|
||||||
|
if( fCRDistance >= PWFXP_CR_LESSTHAN_PCLEVEL_NOXP )
|
||||||
|
{
|
||||||
|
// level distance greater than maximum allowed > no XP award at all
|
||||||
|
return 0.0; // -100%
|
||||||
|
}
|
||||||
|
else if(fCRDistance >= PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION)
|
||||||
|
{
|
||||||
|
// level distance greater than reduction limit ? reduce xp
|
||||||
|
return 1 - ((fCRDistance - PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION) * PWFXP_CR_LESSTHAN_PCLEVEL_MODIFIER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fCRDistance = fabs(fCRDistance);
|
||||||
|
if( fCRDistance >= PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP )
|
||||||
|
{
|
||||||
|
// level distance greater than maximum allowed > no XP award at all
|
||||||
|
return 0.0; // -100%
|
||||||
|
}
|
||||||
|
else if(fCRDistance >= PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION)
|
||||||
|
{
|
||||||
|
// level distance greater than reduction limit ? reduce xp
|
||||||
|
return 1 - ((fCRDistance - PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION) * PWFXP_CR_GREATERTHAN_PCLEVEL_MODIFIER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_KILLINGBLOW_MODIFIER constant description
|
||||||
|
float PWFXP_GetMiscModifier(object oPC, object oKiller)
|
||||||
|
{
|
||||||
|
if(oPC == oKiller && PWFXP_KILLINGBLOW_MODIFIER != 0.0)
|
||||||
|
{
|
||||||
|
return 1 + PWFXP_KILLINGBLOW_MODIFIER;
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_GROUPBONUS_MODIFIER constant description
|
||||||
|
float PWFXP_GetGroupBonusModifier(int nGroupSize)
|
||||||
|
{
|
||||||
|
return 1 + ((nGroupSize-1) * PWFXP_GROUPBONUS_MODIFIER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_XP_DIVISOR_* constants
|
||||||
|
float PWFXP_GetAssociateDivisor(object oCreature)
|
||||||
|
{
|
||||||
|
switch(GetAssociateType(oCreature))
|
||||||
|
{
|
||||||
|
case ASSOCIATE_TYPE_ANIMALCOMPANION: return PWFXP_XP_DIVISOR_ANIMALCOMPANION;
|
||||||
|
case ASSOCIATE_TYPE_DOMINATED: return PWFXP_XP_DIVISOR_DOMINATED;
|
||||||
|
case ASSOCIATE_TYPE_FAMILIAR: return PWFXP_XP_DIVISOR_FAMILIAR;
|
||||||
|
case ASSOCIATE_TYPE_HENCHMAN: return PWFXP_XP_DIVISOR_HENCHMAN;
|
||||||
|
case ASSOCIATE_TYPE_SUMMONED: return PWFXP_XP_DIVISOR_SUMMONED;
|
||||||
|
default: return PWFXP_XP_DIVISOR_UNKNOWN;
|
||||||
|
}
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_MAXIMUM_DISTANCE_TO_GROUP constant description
|
||||||
|
int PWFXP_CheckDistance(object oDead, object oGroupMbr)
|
||||||
|
{
|
||||||
|
return ( GetDistanceBetween(oDead, oGroupMbr) <= PWFXP_MAXIMUM_DISTANCE_TO_GROUP ) && ( GetArea(oDead) == GetArea(oGroupMbr) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// see PWFXP_USE_SETXP constant description
|
||||||
|
void PWFXP_GiveXP(object oPC, int nXP)
|
||||||
|
{
|
||||||
|
if(PWFXP_USE_SETXP)
|
||||||
|
SetXP(oPC, GetXP(oPC) + nXP);
|
||||||
|
else
|
||||||
|
GiveXPToCreature(oPC, nXP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
object oDead = OBJECT_SELF;
|
||||||
|
object oKiller = GetLastKiller();
|
||||||
|
|
||||||
|
// only continue if killer is valid and not from same faction...
|
||||||
|
if ((oKiller==OBJECT_INVALID) || (GetFactionEqual(oKiller, oDead))) return;
|
||||||
|
|
||||||
|
// average party level, xp divisor
|
||||||
|
float fAvgLevel, fDivisor;
|
||||||
|
// groupsize, only PCs count
|
||||||
|
int nGroupSize;
|
||||||
|
|
||||||
|
// get some basic group data like average PC level , PC group size, and XP divisor
|
||||||
|
object oGroupMbr = GetFirstFactionMember(oKiller, FALSE);
|
||||||
|
while(oGroupMbr != OBJECT_INVALID)
|
||||||
|
{
|
||||||
|
if( PWFXP_CheckDistance(oDead, oGroupMbr) || oGroupMbr == oKiller)
|
||||||
|
{
|
||||||
|
if(GetIsPC(oGroupMbr))
|
||||||
|
{
|
||||||
|
nGroupSize++;
|
||||||
|
// add pc divisor
|
||||||
|
fDivisor += PWFXP_XP_DIVISOR_PC;
|
||||||
|
fAvgLevel += IntToFloat(PWFXP_GetLevel(oGroupMbr));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fDivisor += PWFXP_GetAssociateDivisor(oGroupMbr); // add npc divisor
|
||||||
|
}
|
||||||
|
oGroupMbr = GetNextFactionMember(oKiller, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(nGroupSize == 0)
|
||||||
|
{
|
||||||
|
// NPC (Minion) killed something without a PC (Master) near enough to get XP
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate average partylevel
|
||||||
|
fAvgLevel /= IntToFloat(nGroupSize);
|
||||||
|
|
||||||
|
// modifiers
|
||||||
|
float fLevelModifier, fDistanceModifier, fCRModifier, fMiscModifier, fFinalModifier, fECLModifier, fGroupBonusModifier;
|
||||||
|
// groupmember level
|
||||||
|
float fMbrLevel;
|
||||||
|
// get creature CR
|
||||||
|
float fCR = GetChallengeRating(oDead);
|
||||||
|
// reduce CR if greater then maximum CR cap
|
||||||
|
if(fCR > PWFXP_CR_MAX) fCR = PWFXP_CR_MAX; // cap CR
|
||||||
|
// multiply CR with global XP modifier
|
||||||
|
float fModCR = fCR * PWFXP_GLOBAL_MODIFIER;
|
||||||
|
|
||||||
|
// calculate modifiers for each PC individually
|
||||||
|
oGroupMbr = GetFirstFactionMember(oKiller, TRUE);
|
||||||
|
while(oGroupMbr != OBJECT_INVALID)
|
||||||
|
{
|
||||||
|
fMbrLevel = IntToFloat(PWFXP_GetLevel(oGroupMbr));
|
||||||
|
if( PWFXP_CheckDistance(oDead, oGroupMbr) || oGroupMbr == oKiller)
|
||||||
|
{
|
||||||
|
// get global level modifier
|
||||||
|
fLevelModifier = PWFXP_GetLevelModifier(FloatToInt(fMbrLevel));
|
||||||
|
// get PC-level distance to average group-level and compute modifier
|
||||||
|
fDistanceModifier = PWFXP_GetLevelDistanceModifier(fabs(fAvgLevel - fMbrLevel));
|
||||||
|
// get PC-level distance to CR of dead creature and compute modifier
|
||||||
|
fCRModifier = PWFXP_GetCRDistanceModifier(fCR - fMbrLevel);
|
||||||
|
// get misc modifiers (right now only 10% for killing blow dealer)
|
||||||
|
fMiscModifier = PWFXP_GetMiscModifier(oGroupMbr, oKiller);
|
||||||
|
// get group bonus modifier
|
||||||
|
fGroupBonusModifier = PWFXP_GetGroupBonusModifier(nGroupSize);
|
||||||
|
// get subrace ECL modifier
|
||||||
|
fECLModifier = PWFXP_GetECLModifier(oGroupMbr);
|
||||||
|
// calculate final modifier
|
||||||
|
fFinalModifier = fLevelModifier * fDistanceModifier * fCRModifier * fMiscModifier * fGroupBonusModifier * fECLModifier;
|
||||||
|
|
||||||
|
// debug
|
||||||
|
if(PWFXP_DEBUG)
|
||||||
|
SendMessageToPC(oGroupMbr,GetName(oGroupMbr)+"'s XP Base: "+IntToString(FloatToInt(fModCR / fDivisor))+
|
||||||
|
" / Modifiers: LVL [" + IntToString(FloatToInt((fLevelModifier-1)*100)) +
|
||||||
|
"%] APD ["+IntToString(FloatToInt((fDistanceModifier-1)*100)) +
|
||||||
|
"%] CRD ["+IntToString((fCR-fMbrLevel) < 0.0) + "/" + IntToString(FloatToInt((fCRModifier-1)*100))+
|
||||||
|
"%] MSC ["+IntToString(FloatToInt((fMiscModifier-1)*100))+
|
||||||
|
"%] GRP ["+IntToString(FloatToInt((fGroupBonusModifier-1)*100))+
|
||||||
|
"%] ECL ["+IntToString(FloatToInt((fECLModifier-1)*100))+
|
||||||
|
"%] GRS ["+IntToString(nGroupSize)+
|
||||||
|
"] DIV ["+GetSubString(FloatToString(fDivisor),6,5) +
|
||||||
|
"] FIN ["+IntToString(FloatToInt((fFinalModifier-1)*100))+
|
||||||
|
"%]");
|
||||||
|
|
||||||
|
|
||||||
|
int nXP = FloatToInt((fModCR / fDivisor) * fFinalModifier);
|
||||||
|
|
||||||
|
// award minimum/maximum xp if needed
|
||||||
|
if(nXP < PWFXP_MINIMUM_XP)
|
||||||
|
nXP = PWFXP_MINIMUM_XP;
|
||||||
|
else if(nXP > PWFXP_MAXIMUM_XP)
|
||||||
|
nXP = PWFXP_MAXIMUM_XP;
|
||||||
|
|
||||||
|
// misc checks for reasons the party member might not get XP would go here (eg. if they are dead)
|
||||||
|
|
||||||
|
if(nXP > 0) PWFXP_GiveXP(oGroupMbr, nXP);
|
||||||
|
}
|
||||||
|
oGroupMbr = GetNextFactionMember(oKiller, TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
274
src/module/nss/pwfxp_def.nss
Normal file
274
src/module/nss/pwfxp_def.nss
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
//::///////////////////////////////////////////////
|
||||||
|
//:: XP Distribution Script by Knat
|
||||||
|
//:: pwfxp
|
||||||
|
//:: Copyright (c) 2001 Bioware Corp.
|
||||||
|
//:://////////////////////////////////////////////
|
||||||
|
//void main(){}
|
||||||
|
// note: default values are geared towards a LOW xp setting...
|
||||||
|
// with easy leveling early (level 1-5) and very hard xp gain later on (lvl 30+)
|
||||||
|
// all default values should be epic-level compatible
|
||||||
|
|
||||||
|
|
||||||
|
// this will modify global xp output similar to the module xp-slider
|
||||||
|
// higher value = more xp
|
||||||
|
// PC needs to kill a combined CR of (PC-LEVEL * 1000) / PWFXP_GLOBAL_MODIFIER
|
||||||
|
// on average to gain a level. use this as a rule of thumb and base to calculate
|
||||||
|
// the more advanced modifiers
|
||||||
|
//
|
||||||
|
// e.g. a level 10 needs to kill 100 CR-10 mobs to level (aprox.) using default 10.0 global modifier
|
||||||
|
// he will only need 50 CR-10 mobs if you set it to 20.0
|
||||||
|
// setting this to 1000.0 = he only needs one CR-10 mob to level
|
||||||
|
//
|
||||||
|
// you can further scale the leveling progress more precisely with the PWFXP_LEVEL_MODIFIERS constant
|
||||||
|
// just continue to read my comments...
|
||||||
|
const float PWFXP_GLOBAL_MODIFIER = 15.0;
|
||||||
|
|
||||||
|
// displays one-line XP status info after each kill
|
||||||
|
// useful while you fine tune the system.
|
||||||
|
// and check the readme.txt in case you want to remove
|
||||||
|
// the double-xp message from bioware...
|
||||||
|
const int PWFXP_DEBUG = TRUE;
|
||||||
|
|
||||||
|
// NEW & experimental:
|
||||||
|
// system will use the SetXP function instead of GiveXPToCreature if you set this to TRUE
|
||||||
|
// this should bypass any "possible" bioware xp modification, like multiclass penalties.
|
||||||
|
// i did not really test this so far, it's just some rumor i picked up from the
|
||||||
|
// bioboards. choose whatever you feel better with...
|
||||||
|
const int PWFXP_USE_SETXP = TRUE;
|
||||||
|
|
||||||
|
// NEW:
|
||||||
|
// pc level gets computed based on the total XP instead of
|
||||||
|
// using GetLevelBy functions if set to TRUE. this way players ready to levelup
|
||||||
|
// can't bunker XP to gain better XP bonuses. a level 2 player with
|
||||||
|
// 3500 total XP (thus, ready to levelup) gets considered
|
||||||
|
// level 3 by the XP script if you set this switch to TRUE
|
||||||
|
//
|
||||||
|
// setting this to FALSE will use the old way of GetLevelByPosition.
|
||||||
|
// i highly recommend the new way to counter XP (and probably more) exploits...
|
||||||
|
const int PWFXP_USE_TOTAL_XP_TO_COMPUTE_PCLEVEL = TRUE;
|
||||||
|
|
||||||
|
// this is where you apply your subrace ECL modifiers
|
||||||
|
// add them to the constant in this form "(ECL Modifier)-(Subrace)|...next|...etc"
|
||||||
|
// COMMENTED OUT as it is no longer used in the calculations.
|
||||||
|
//const string PWFXP_ECL_MODIFIERS = "1-ARCTIC DWARF|1-HALF OGRE|1-GITHYANKI|1-GITZERAI|1-OROG|1-GNOLL|1-LIZARDFOLK|1-AASIMAR|1-TIEFLING|1-HOBGOLBIN|1-GRAY DWARF|2-DROW MALE|2-DROW FEMALE|2-DEEP GNOME SVIRFNEBLIN|2-AVARIEL|2-MINOTAUR|2-BUGBEAR|2-FEY'RI|2-TANARUKK|3-OGRE|3-YUANTI PURE|3-AZER|4-PIXIE|4-ILLITHID|5-TROLL|6-RAKSHASHA";
|
||||||
|
|
||||||
|
// NEW:
|
||||||
|
//
|
||||||
|
// you can add a modifier to change XP output for every single level (including epic levels)
|
||||||
|
// this also enables you to break the linear nature of NWNs default XP output.
|
||||||
|
// you can change it to: logarithmic, exponential or any other non-linear
|
||||||
|
// mathematical function using the PWFXP_LEVEL_MODIFIERS table
|
||||||
|
//
|
||||||
|
// you can make the first few levels an easy catch but make the last a pain to reach.... very flexible now
|
||||||
|
//
|
||||||
|
// default setting:
|
||||||
|
//
|
||||||
|
// level 1 = 1000% xp bonus
|
||||||
|
// level 2 = 500% xp bonus
|
||||||
|
// level 3 = 300% xp bonus
|
||||||
|
// level 4 = 200% xp bonus
|
||||||
|
// level 5 = 100% xp bonus
|
||||||
|
//
|
||||||
|
// level 6 - 10 = no xp change
|
||||||
|
|
||||||
|
// level 11 = -15% xp penalty
|
||||||
|
// level 12 = -15%
|
||||||
|
// level 13 = -20%
|
||||||
|
// level 14 = -20%
|
||||||
|
// level 15 = -25%
|
||||||
|
// level 16 = -25%
|
||||||
|
// level 17 = -30%
|
||||||
|
// level 18 = -30%
|
||||||
|
// level 19 = -35%
|
||||||
|
// level 20 = -35%
|
||||||
|
//
|
||||||
|
// level 21 = -40% xp penalty
|
||||||
|
// level 22 = -45%
|
||||||
|
// level 23 = -50%
|
||||||
|
// level 24 = -55%
|
||||||
|
// level 25 = -60%
|
||||||
|
// level 26 = -65%
|
||||||
|
// level 27 = -70%
|
||||||
|
// level 28 = -80%
|
||||||
|
// level 29 = -90%
|
||||||
|
//
|
||||||
|
// level 30 = -91% xp penalty
|
||||||
|
// level 31 = -91%
|
||||||
|
// level 32 = -92%
|
||||||
|
// level 33 = -92%
|
||||||
|
// level 34 = -93%
|
||||||
|
// level 35 = -93%
|
||||||
|
// level 36 = -94%
|
||||||
|
// level 37 = -94%
|
||||||
|
// level 38 = -95%
|
||||||
|
// level 39 = -96%
|
||||||
|
//
|
||||||
|
// these settings make it easy first but very tough at later levels.
|
||||||
|
// the pc would need to kill 100 level 10 creatures to level from 10 to 11, but
|
||||||
|
// several thousand CR 40 creatures to level from 39 to 40, with the above settings.
|
||||||
|
// (not counting group bonus or other advanced modifiers)
|
||||||
|
//
|
||||||
|
// modifier explanation:
|
||||||
|
//
|
||||||
|
// a value of 1 (01.000) means no xp change.
|
||||||
|
//
|
||||||
|
// the actual xp bonus/penalty in % = (modifier - 1) * 100
|
||||||
|
//
|
||||||
|
// use value < 1.0 to reduce the xp
|
||||||
|
// e.g. 00.500 = -50%
|
||||||
|
// 00.010 = -99%
|
||||||
|
// 00.001 = -99.9%
|
||||||
|
//
|
||||||
|
// attention: syntax !!
|
||||||
|
// always pad with 0. each number must be 6 chars long
|
||||||
|
// otherwise the parser will fail and your players get 0xp
|
||||||
|
// i use very simplistic parsing to optimize cpu use...
|
||||||
|
//
|
||||||
|
// the first number modifies level 1, the last number level 40
|
||||||
|
//
|
||||||
|
// LEVEL-----01--|--02--|--03--|--04--|--05--|--06--|--07--|--08--|--09--|--10--|--11--|--12--|--13--|--14--|--15--|--16--|--17--|--18--|--19--|--20--|--21--|--22--|--23--|--24--|--25--|--26--|--27--|--28--|--29--|--30--|--31--|--32--|--33--|--34--|--35--|--36--|--37--|--38--|--39--|--40--|
|
||||||
|
const string PWFXP_LEVEL_MODIFIERS = "11.000|06.000|04.000|01.000|01.000|01.000|01.000|01.000|01.000|01.000|00.850|00.850|00.800|00.800|00.750|00.750|00.700|00.700|00.650|00.650|00.600|00.550|00.500|00.450|00.400|00.350|00.300|00.200|00.100|00.090|00.090|00.080|00.080|00.070|00.070|00.060|00.060|00.050|00.040|00.040";
|
||||||
|
|
||||||
|
// small bonus for killing blow dealer
|
||||||
|
const float PWFXP_KILLINGBLOW_MODIFIER = 1.5; // 0%
|
||||||
|
|
||||||
|
// PC level gets compared to the average party level.
|
||||||
|
// APL = Average Party Level
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// attention: the below example was from version 1.1
|
||||||
|
// most if not all constants have been changed (scalar for example is 100% now and thus fully linear)
|
||||||
|
//
|
||||||
|
// example uses below values
|
||||||
|
// const float PWFXP_APL_REDUCTION = 2.0;
|
||||||
|
// const float PWFXP_APL_NOXP = 4.0;
|
||||||
|
// const float PWFXP_SCALAR = 0.5
|
||||||
|
//
|
||||||
|
// XP gets reduced if PC-level > APL + APL_REDUCTION
|
||||||
|
// XP reduction is based on SCALAR, be careful if you change this
|
||||||
|
// right now its 0 - 50% (scalar 0.5) for delta 2 (APL_REDUCTION) .. delta 4 (APL_NOXP)
|
||||||
|
// delta = abs(APL - PC Level)
|
||||||
|
// this means it will switch from 50% reduction to 100% reduction in one leap in case the PC level
|
||||||
|
// is greater then APL + APL_NOXP.
|
||||||
|
// i did this for a better granularity for the given default values but
|
||||||
|
// you can freely change APL_REDUCTION and/or APL_NOXP. XP reduction gets auto-adjusted to the maximum
|
||||||
|
// of SCALAR (50% default).
|
||||||
|
//
|
||||||
|
// XP gets reduced to zero if PC-level > APL + APL_NOXP
|
||||||
|
//
|
||||||
|
// Example (using default values):
|
||||||
|
// PC A = level 7
|
||||||
|
// PC B = level 3
|
||||||
|
// PC C = level 1
|
||||||
|
//
|
||||||
|
// average party level (APL) = 3.66
|
||||||
|
//
|
||||||
|
// Distance PC A = abs(PClevel - AveragePartyLevel) = abs(7 - 3.66) = 3.34
|
||||||
|
// PC-A has a final distance of 1.34 (3.34 - APL_REDUCTION)
|
||||||
|
// XP reduction = (SCALAR / (APL_NOXP - APL_REDUCTION)) * 1.34 = (0.5 / 2) * 1.34 = 33.5% XP reduction
|
||||||
|
//
|
||||||
|
// Distance PC B = abs(PClevel - AveragePartyLevel) = abs(3 - 3.66) = 0.66
|
||||||
|
// PC-A has a final distance of -1.34 (0.66 - APL_REDUCTION)
|
||||||
|
// no XP reduction
|
||||||
|
//
|
||||||
|
// Distance PC C = abs(PClevel - AveragePartyLevel) = abs(1 - 3.66) = 2.66
|
||||||
|
// PC-A has a final distanceof 0.66 (2.66 - APL_REDUCTION)
|
||||||
|
// XP reduction = (SCALAR / (APL_NOXP - APL_REDUCTION)) * 0.66 = (0.5 / 2) * 0.66 = 16.5% XP reduction
|
||||||
|
//
|
||||||
|
// those PCs with the biggest impact to the average party level receive the biggest XP reduction
|
||||||
|
// (in the above case PC A)
|
||||||
|
//
|
||||||
|
// set _REDUCTION to 40 and _NOXP to 41 if you don't want any APL reduction
|
||||||
|
//
|
||||||
|
// changed default to a bit less harsh values
|
||||||
|
const float PWFXP_APL_REDUCTION = 3.0; // levels
|
||||||
|
const float PWFXP_APL_NOXP = 6.0;
|
||||||
|
|
||||||
|
// NEW:
|
||||||
|
// these 4 constants works like the APL constants above but it compares
|
||||||
|
// PC level vs challenge rating of the dead creature
|
||||||
|
//
|
||||||
|
// you can distinct two different cases now:
|
||||||
|
//
|
||||||
|
// PC level > CR of the creature (CR + PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION)
|
||||||
|
// PC level < CR of the creature (CR + PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION)
|
||||||
|
//
|
||||||
|
// math is the same as the APL example above, just exchange
|
||||||
|
// AveragePartyLevel with CR of dead creature and use
|
||||||
|
// PWFXP_CR_*_PCLEVEL_REDUCTION and PWFXP_CR_*_PCLEVEL_NOXP as the constants
|
||||||
|
//
|
||||||
|
// set _REDUCTION to CR_MAX and _NOXP to CR_MAX+1 if you don't want any cr reduction
|
||||||
|
//
|
||||||
|
// reduction constants for PCs fighting mobs with a CR below their level
|
||||||
|
const float PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION = 3.0;
|
||||||
|
const float PWFXP_CR_LESSTHAN_PCLEVEL_NOXP = 10.0;
|
||||||
|
|
||||||
|
// note: default setting only penalize PCs if they try to kill something
|
||||||
|
// that should be *impossible* for their level.
|
||||||
|
// a 40 level epic PC will be able to kill CR 60 creatures without
|
||||||
|
// penalty and a large low-level group of players will be able to
|
||||||
|
// kill a much higher CR creature without penalty...(a group of lvl5 players killing
|
||||||
|
// a CR 20 creature won't receive any penalty. penalty will start to kick in if they try
|
||||||
|
// to kill a creature with a CR > 25
|
||||||
|
// you can use this to counter low-level XP exploits. e.g. a level 40 player
|
||||||
|
// could mangle a mob down to 1 HP. then a low level comes in and deals the final
|
||||||
|
// blow -> classical xp exploit...
|
||||||
|
// default settings make sure that nothing can get out of hand, but you can make
|
||||||
|
// this harsher if you want (but keep in mind that creatures can have a higher
|
||||||
|
// CR than the players maximum level, like CR 60)
|
||||||
|
//
|
||||||
|
// set _REDUCTION to CR_MAX and _NOXP to CR_MAX+1 if you don't want any cr reduction
|
||||||
|
//
|
||||||
|
// reduction constants for PCs fighting mobs with a CR above their level
|
||||||
|
const float PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION = 20.0;
|
||||||
|
const float PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP = 30.0;
|
||||||
|
|
||||||
|
// described above
|
||||||
|
const float PWFXP_SCALAR = 1.0;
|
||||||
|
|
||||||
|
// maximum CR cap
|
||||||
|
// this stops creatures with sky-high CRs from giving godly XP
|
||||||
|
const float PWFXP_CR_MAX = 60.0;
|
||||||
|
|
||||||
|
// groups get a small xp bonus
|
||||||
|
// formular is groupsize-1 * modifier
|
||||||
|
// with a default value of 0.1 (10%) a party of 4 receives 30% XP bonus
|
||||||
|
// this should encourage grouping
|
||||||
|
// set it to 0.0 if you dont like that...
|
||||||
|
const float PWFXP_GROUPBONUS_MODIFIER = 0.1;
|
||||||
|
|
||||||
|
// groub members need to be within this distance to the dead creature
|
||||||
|
// if they want to get any XP during fights
|
||||||
|
const float PWFXP_MAXIMUM_DISTANCE_TO_GROUP = 70.0; // meters
|
||||||
|
|
||||||
|
// safety mechanism
|
||||||
|
// minimum XP for a kill
|
||||||
|
const int PWFXP_MINIMUM_XP = 1;
|
||||||
|
|
||||||
|
// safety mechanism
|
||||||
|
// maximum XP for a kill
|
||||||
|
const int PWFXP_MAXIMUM_XP = 1000;
|
||||||
|
|
||||||
|
// UPDATED:
|
||||||
|
// these constants determine how XP division works
|
||||||
|
// you can now distinct between animal companion,
|
||||||
|
// familiars, dominated, summoned and henchman. you can set a different
|
||||||
|
// xp divisor for each of them. (default: henchman has max reduction impact followed
|
||||||
|
// by dominated, summoned, familiars, animal companion)
|
||||||
|
// e.g.: a group with two PCs + 1 FAMILIAR + 1 SUMMONED CREATURE
|
||||||
|
// gets a total XP divisor of 2.5 (using default values).
|
||||||
|
// if they kill a 1000XP mob, both PCs only receive 400 XP
|
||||||
|
const float PWFXP_XP_DIVISOR_PC = 1.0;
|
||||||
|
const float PWFXP_XP_DIVISOR_DOMINATED = 0.5;
|
||||||
|
const float PWFXP_XP_DIVISOR_HENCHMAN = 0.5;
|
||||||
|
const float PWFXP_XP_DIVISOR_SUMMONED = 0.3;
|
||||||
|
const float PWFXP_XP_DIVISOR_ANIMALCOMPANION = 0.1;
|
||||||
|
const float PWFXP_XP_DIVISOR_FAMILIAR = 0.1;
|
||||||
|
// used in case i can't determine the associate type
|
||||||
|
const float PWFXP_XP_DIVISOR_UNKNOWN = 0.5;
|
||||||
|
|
||||||
|
// don't change these
|
||||||
|
float PWFXP_APL_MODIFIER = PWFXP_SCALAR / (PWFXP_APL_NOXP - PWFXP_APL_REDUCTION);
|
||||||
|
float PWFXP_CR_LESSTHAN_PCLEVEL_MODIFIER = PWFXP_SCALAR / (PWFXP_CR_LESSTHAN_PCLEVEL_NOXP - PWFXP_CR_LESSTHAN_PCLEVEL_REDUCTION);
|
||||||
|
float PWFXP_CR_GREATERTHAN_PCLEVEL_MODIFIER = PWFXP_SCALAR / (PWFXP_CR_GREATERTHAN_PCLEVEL_NOXP - PWFXP_CR_GREATERTHAN_PCLEVEL_REDUCTION);
|
||||||
|
|
||||||
16
src/module/nss/pwfxp_prc_race.nss
Normal file
16
src/module/nss/pwfxp_prc_race.nss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// written by fluffyamoeba 09-07-06
|
||||||
|
// actually gets the LA modifier, not ECL
|
||||||
|
// gets the LA from ecl.2da (actually the 2da cache)
|
||||||
|
// used to hand out XP adjusted for LA
|
||||||
|
|
||||||
|
int GetECLMod(object oCreature);
|
||||||
|
|
||||||
|
#include "inc_utility"
|
||||||
|
|
||||||
|
int GetECLMod(object oCreature)
|
||||||
|
{
|
||||||
|
int nRace = GetRacialType(oCreature); //note this is not MyPRCGetRacialType becuase we want to include subraces too
|
||||||
|
int nLA = 0;
|
||||||
|
nLA = StringToInt(Get2DACache("ECL", "LA", nRace));
|
||||||
|
return nLA;
|
||||||
|
}
|
||||||
@@ -13,5 +13,5 @@
|
|||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user