Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74ede2e7dd |
@@ -4,8 +4,6 @@
|
||||
//:://////////////////////////////////////////////
|
||||
/** @file
|
||||
|
||||
|
||||
|
||||
@author Primogenitor
|
||||
@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_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"
|
||||
const int DYNCONV_STRREF_NEXT = 16824204; // "Next"
|
||||
const int DYNCONV_STRREF_ABORT_CONVO = 16824212; // "Abort"
|
||||
const int DYNCONV_STRREF_EXIT_CONVO = 78; // "Exit"
|
||||
const int DYNCONV_STRREF_PLEASE_WAIT = 16824202; // "Please wait"
|
||||
const int DYNCONV_STRREF_PREVIOUS = 16824203; // "Previous"
|
||||
const int DYNCONV_STRREF_NEXT = 16824204; // "Next"
|
||||
const int DYNCONV_STRREF_ABORT_CONVO = 16824212; // "Abort"
|
||||
const int DYNCONV_STRREF_EXIT_CONVO = 16183878; // "Exit"
|
||||
|
||||
const string DYNCONV_SCRIPT = "DynConv_Script";
|
||||
const string DYNCONV_VARIABLE = "DynConv_Var";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -400,5 +400,4 @@ int GetBestAvailableSpell(object oTarget)
|
||||
if(nBestSpell == 99999) nBestSpell = GetBestL1Spell(oTarget, nBestSpell);
|
||||
if(nBestSpell == 99999) nBestSpell = GetBestL0Spell(oTarget, nBestSpell);
|
||||
return nBestSpell;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -308,7 +308,7 @@ int FindUnarmedDamage(object oCreature)
|
||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
||||
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 nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
|
||||
|
||||
@@ -320,7 +320,7 @@ int FindUnarmedDamage(object oCreature)
|
||||
if (nCompression)
|
||||
{
|
||||
iSize -= nCompression;
|
||||
}
|
||||
} */
|
||||
|
||||
iMonkDamage += iDieIncrease;
|
||||
iShouDamage += iDieIncrease;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//::///////////////////////////////////////////////
|
||||
//:: Weapon Restriction System Include
|
||||
//:: prc_inc_restwpn.nss
|
||||
//:: prc_inc_wpnrest.nss
|
||||
//::///////////////////////////////////////////////
|
||||
/*
|
||||
Functions to support PnP Weapon Proficiency and
|
||||
@@ -23,6 +23,70 @@
|
||||
* @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
|
||||
|
||||
@@ -110,49 +110,4 @@ const string NUI_PRC_PA_TEXT_BIND = "nui_prc_pa_text_bind";
|
||||
// Left Button Enabled Bind for Power Attack NUI
|
||||
const string NUI_PRC_PA_LEFT_BUTTON_ENABLED_BIND = "leftButtonEnabled";
|
||||
// Right Button Enabled Bind for Power Attack NUI
|
||||
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
// //
|
||||
// NUI Level Up //
|
||||
// //
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
const string NUI_LEVEL_UP_WINDOW_ID = "prcLevelUpNui";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELL_CIRCLE_BUTTON_BASEID = "NuiLevelUpCircleButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_BUTTON_BASEID = "NuiLevelUpSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_BUTTON_BASEID = "NuiLevelUpChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_SPELL_CHOSEN_DISABLED_BUTTON_BASEID = "NuiLevelUpDisabledChosenSpellButton_";
|
||||
const string NUI_LEVEL_UP_DONE_BUTTON = "NuiLevelUpDoneButton";
|
||||
const string NUI_LEVEL_UP_RESET_BUTTON = "NuiLevelUpResetButton";
|
||||
|
||||
const string NUI_LEVEL_UP_SELECTED_CLASS_VAR = "NUILevelUpSelectedClass";
|
||||
const string NUI_LEVEL_UP_SELECTED_CIRCLE_VAR = "NUILevelUpSelectedCircle";
|
||||
const string NUI_LEVEL_UP_KNOWN_SPELLS_VAR = "NUILevelUpKnownSpells";
|
||||
const string NUI_LEVEL_UP_CHOSEN_SPELLS_VAR = "NUILevelUpChosenSpells";
|
||||
const string NUI_LEVEL_UP_EXPANDED_KNOW_LIST_VAR = "NUILevelUpExpKnowList";
|
||||
const string NUI_LEVEL_UP_POWER_LIST_VAR = "NUILevelUpPowerList";
|
||||
const string NUI_LEVEL_UP_DISCIPLINE_INFO_VAR = "GetDisciplineInfoObjectCache_";
|
||||
const string NUI_LEVEL_UP_SPELLID_LIST_VAR = "NUILevelUpSpellIDList_";
|
||||
const string NUI_LEVEL_UP_REMAINING_CHOICES_CACHE_VAR = "NUIRemainingChoicesCache";
|
||||
const string NUI_LEVEL_UP_RELEARN_LIST_VAR = "NUILevelUpRelearnList";
|
||||
const string NUI_LEVEL_UP_ARCHIVIST_NEW_SPELLS_LIST_VAR = "NUILevelUpArchivistNewSpellsList";
|
||||
|
||||
const string NUI_LEVEL_UP_EXPANDED_CHOICES_VAR = "NUIExpandedChoices";
|
||||
const string NUI_LEVEL_UP_EPIC_EXPANDED_CHOICES_VAR = "NUIEpicExpandedChoices";
|
||||
|
||||
const int NUI_LEVEL_UP_MANEUVER_PREREQ_LIMIT = 6;
|
||||
|
||||
const string NUI_LEVEL_UP_MANEUVER_TOTAL = "ManeuverTotal";
|
||||
const string NUI_LEVEL_UP_STANCE_TOTAL = "StanceTotal";
|
||||
|
||||
const string NUI_LEVEL_UP_SPELLBOOK_OBJECT_CACHE_VAR = "GetSpellListObjectCache_";
|
||||
const string NUI_LEVEL_UP_KNOWN_INVOCATIONS_CACHE_VAR = "GetInvokerKnownListObjectCache_";
|
||||
|
||||
const string NUI_SPELL_DESCRIPTION_FEATID_VAR = "NUISpellDescriptionFeatID";
|
||||
const string NUI_SPELL_DESCRIPTION_CLASSID_VAR = "NUISpellDescriptionClassID";
|
||||
const string NUI_SPELL_DESCRIPTION_SPELLID_VAR = "NUISpellDescriptionSpellID";
|
||||
const string NUI_SPELL_DESCRIPTION_REAL_SPELLID_VAR = "NUISpellDescriptionRealSpellID";
|
||||
|
||||
const string NUI_PRC_PA_RIGHT_BUTTON_ENABLED_BIND = "rightButtonEnabled";
|
||||
@@ -10,8 +10,10 @@
|
||||
//:: Created By: Rakiov
|
||||
//:: Created On: 24.05.2005
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
#include "prc_nui_com_inc"
|
||||
#include "inc_newspellbook"
|
||||
#include "psi_inc_psifunc"
|
||||
#include "inc_lookups"
|
||||
#include "prc_nui_consts"
|
||||
|
||||
//
|
||||
// GetSpellListForCircle
|
||||
@@ -41,6 +43,69 @@ json GetSpellListForCircle(object oPlayer, int nClass, int circle);
|
||||
//
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer);
|
||||
|
||||
//
|
||||
// GetCurrentSpellLevel
|
||||
// Gets the current spell level the class can achieve at the current
|
||||
// caster level (ranging from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
// nLevel:int the caster level
|
||||
//
|
||||
// Returns:
|
||||
// int the circle the class can achieve currently
|
||||
//
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel);
|
||||
|
||||
//
|
||||
// GetMaxSpellLevel
|
||||
// Gets the highest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest circle that can be achieved
|
||||
//
|
||||
int GetMaxSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetMinSpellLevel
|
||||
// Gets the lowest possible circle the class can achieve (from 0-9)
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the lowest circle that can be achieved
|
||||
//
|
||||
int GetMinSpellLevel(int nClass);
|
||||
|
||||
//
|
||||
// GetHighestLevelPossibleInClass
|
||||
// Given a class Id this will determine what the max level of a class can be
|
||||
// achieved
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the ClassID
|
||||
//
|
||||
// Returns:
|
||||
// int the highest possible level the class can achieve
|
||||
//
|
||||
int GetHighestLevelPossibleInClass(int nClass);
|
||||
|
||||
//
|
||||
// GetClassSpellbookFile
|
||||
// Gets the class 2da spellbook/ability for the given class Id
|
||||
//
|
||||
// Arguments:
|
||||
// nClass:int the classID
|
||||
//
|
||||
// Returns:
|
||||
// string the 2da file name for the spell/abilities of the ClassID
|
||||
//
|
||||
string GetClassSpellbookFile(int nClass);
|
||||
|
||||
//
|
||||
// IsSpellKnown
|
||||
// Returns whether the player with the given class, spell file, and spellbook id
|
||||
@@ -169,6 +234,23 @@ json GetMetaMysteryFeatList();
|
||||
//
|
||||
int GetTrueClassIfRHD(object oPlayer, int nClass);
|
||||
|
||||
//
|
||||
// GetBinderSpellToFeatDictionary
|
||||
// Sets up the Binder Spell Dictionary that is used to match a binder's vestige
|
||||
// to their feat. This is constructed based off the binder's known location of
|
||||
// their feat and spell ranges in the base 2das respectivly. After constructing
|
||||
// this it will be saved to the player locally as a cached result since we do
|
||||
// not need to call this again.
|
||||
//
|
||||
// Argument:
|
||||
// oPlayer:object the player
|
||||
//
|
||||
// Returns:
|
||||
// json:Dictionary<String,Int> a dictionary of mapping between the SpellID
|
||||
// and the FeatID of a vestige ability
|
||||
//
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF);
|
||||
|
||||
//
|
||||
// ShouldAddSpell
|
||||
// Given a spellId and a class, determines if the spell should be added to the
|
||||
@@ -236,18 +318,6 @@ json GetInvokerEssenceSpellList(int nClass, object oPlayer=OBJECT_SELF);
|
||||
//
|
||||
int JsonArrayContainsInt(json list, int item);
|
||||
|
||||
//
|
||||
// IsSpellbookNUIOpen
|
||||
// Checks to see if the Spellbook NUI is open on a given player.
|
||||
//
|
||||
// Arguments:
|
||||
// oPC:object the player
|
||||
//
|
||||
// Returns:
|
||||
// int:Boolean TRUE if window is open, FALSE otherwise
|
||||
//
|
||||
int IsSpellbookNUIOpen(object oPC);
|
||||
|
||||
json GetSpellListForCircle(object oPlayer, int nClass, int circle)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@@ -327,6 +397,86 @@ int ShouldAddSpell(int nClass, int spellId, object oPlayer=OBJECT_SELF)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
json GetBinderSpellToFeatDictionary(object oPlayer=OBJECT_SELF)
|
||||
{
|
||||
// a dictionary of <SpellID, FeatID>
|
||||
json binderDict = GetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR);
|
||||
// if this hasn't been created, create it now.
|
||||
if (binderDict == JsonNull())
|
||||
binderDict = JsonObject();
|
||||
else
|
||||
return binderDict;
|
||||
|
||||
// the starting row for binder spells
|
||||
int spellIndex = 19070;
|
||||
// the starting row for binder feats
|
||||
int featIndex = 9030;
|
||||
//the end of the binder spells/feats
|
||||
while (spellIndex <= 19156 && featIndex <= 9104)
|
||||
{
|
||||
// get the SpellID tied to the feat
|
||||
int spellID = StringToInt(Get2DACache("feat", "SPELLID", featIndex));
|
||||
// if the spellID matches the current index, then this is the spell
|
||||
// attached to the feat
|
||||
if (spellID == spellIndex)
|
||||
{
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellID), JsonInt(featIndex));
|
||||
|
||||
// move to next spell/feat
|
||||
featIndex++;
|
||||
spellIndex++;
|
||||
}
|
||||
// else we have reached a subdial spell
|
||||
else
|
||||
{
|
||||
// loop through until we reach back at spellID
|
||||
while (spellIndex < spellID)
|
||||
{
|
||||
int masterSpell = StringToInt(Get2DACache("spells", "Master", spellIndex));
|
||||
|
||||
// add the sub radial to the dict, tied to the master's FeatID
|
||||
int featId = JsonGetInt(JsonObjectGet(binderDict, IntToString(masterSpell)));
|
||||
binderDict = JsonObjectSet(binderDict, IntToString(spellIndex), JsonInt(featId));
|
||||
|
||||
spellIndex++;
|
||||
}
|
||||
|
||||
|
||||
// some feats overlap the same FeatID, can cause this to get stuck.
|
||||
// if it happens then move on
|
||||
if (spellIndex > spellID)
|
||||
featIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// cache the result
|
||||
SetLocalJson(oPlayer, NUI_SPELLBOOK_BINDER_DICTIONARY_CACHE_VAR, binderDict);
|
||||
return binderDict;
|
||||
}
|
||||
|
||||
string GetClassSpellbookFile(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
// Spontaneous casters use a specific file name structure
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = GetFileForClass(nClass);
|
||||
}
|
||||
// everyone else uses this structure
|
||||
else
|
||||
{
|
||||
sFile = GetAMSDefinitionFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "vestiges";
|
||||
}
|
||||
}
|
||||
|
||||
return sFile;
|
||||
}
|
||||
|
||||
json GetSupportedNUISpellbookClasses(object oPlayer)
|
||||
{
|
||||
json retValue = JsonArray();
|
||||
@@ -376,6 +526,167 @@ int IsSpellKnown(object oPlayer, int nClass, int spellId)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int GetCurrentSpellLevel(int nClass, int nLevel)
|
||||
{
|
||||
int currentLevel = nLevel;
|
||||
|
||||
// ToB doesn't have a concept of spell levels, but still match up to it
|
||||
if(nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER)
|
||||
{
|
||||
return 9;
|
||||
}
|
||||
|
||||
|
||||
// Binders don't really have a concept of spell level
|
||||
if (nClass == CLASS_TYPE_BINDER
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN) // they can only reach 1st circle
|
||||
return 1;
|
||||
|
||||
//Shadowsmith has no concept of spell levels
|
||||
if (nClass == CLASS_TYPE_SHADOWSMITH)
|
||||
return 2;
|
||||
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
return 4;
|
||||
|
||||
// Spont casters have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
|
||||
int maxLevel = GetMaxSpellLevelForCasterLevel(nClass, currentLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
string spellLevel2da = GetAMSKnownFileName(nClass);
|
||||
|
||||
currentLevel = nLevel - 1; // Level is 1 off of the row in the 2da
|
||||
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
currentLevel = GetManifesterLevel(OBJECT_SELF, nClass, TRUE) - 1;
|
||||
|
||||
int totalLevel = Get2DARowCount(spellLevel2da);
|
||||
|
||||
// in case we somehow go over bounds just don't :)
|
||||
if (currentLevel >= totalLevel)
|
||||
currentLevel = totalLevel - 1;
|
||||
|
||||
//Psionics have MaxPowerLevel as their column name
|
||||
string columnName = "MaxPowerLevel";
|
||||
|
||||
//Invokers have MaxInvocationLevel
|
||||
if (nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT)
|
||||
columnName = "MaxInvocationLevel";
|
||||
|
||||
// Truenamers have 3 sets of utterances, ranging from 1-6, EvolvingMind covers the entire range
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
columnName = "EvolvingMind";
|
||||
spellLevel2da = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
columnName = "VestigeLvl";
|
||||
spellLevel2da = "cls_bind_binder";
|
||||
}
|
||||
|
||||
// ToB doesn't have a concept of this, but we don't care.
|
||||
|
||||
int maxLevel = StringToInt(Get2DACache(spellLevel2da, columnName, currentLevel));
|
||||
return maxLevel;
|
||||
}
|
||||
}
|
||||
|
||||
int GetMinSpellLevel(int nClass)
|
||||
{
|
||||
// again sponts have their own function
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
return GetMinSpellLevelForCasterLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_PSION
|
||||
|| nClass == CLASS_TYPE_PSYWAR
|
||||
|| nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_WARMIND
|
||||
|| nClass == CLASS_TYPE_WARBLADE
|
||||
|| nClass == CLASS_TYPE_SWORDSAGE
|
||||
|| nClass == CLASS_TYPE_CRUSADER
|
||||
|| nClass == CLASS_TYPE_WARLOCK
|
||||
|| nClass == CLASS_TYPE_DRAGONFIRE_ADEPT
|
||||
|| nClass == CLASS_TYPE_DRAGON_SHAMAN
|
||||
|| nClass == CLASS_TYPE_SHADOWCASTER
|
||||
|| nClass == CLASS_TYPE_SHADOWSMITH
|
||||
|| nClass == CLASS_TYPE_BINDER)
|
||||
return 1;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int GetMaxSpellLevel(int nClass)
|
||||
{
|
||||
if (nClass == CLASS_TYPE_WILDER
|
||||
|| nClass == CLASS_TYPE_PSION)
|
||||
return 9;
|
||||
if (nClass == CLASS_TYPE_PSYCHIC_ROGUE
|
||||
|| nClass == CLASS_TYPE_FIST_OF_ZUOKEN
|
||||
|| nClass == CLASS_TYPE_WARMIND)
|
||||
return 5;
|
||||
if (nClass == CLASS_TYPE_PSYWAR)
|
||||
return 6;
|
||||
|
||||
return GetCurrentSpellLevel(nClass, GetHighestLevelPossibleInClass(nClass));
|
||||
}
|
||||
|
||||
int GetHighestLevelPossibleInClass(int nClass)
|
||||
{
|
||||
string sFile;
|
||||
|
||||
//sponts have their spells in the classes.2da
|
||||
if(GetSpellbookTypeForClass(nClass) == SPELLBOOK_TYPE_SPONTANEOUS
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST)
|
||||
{
|
||||
sFile = Get2DACache("classes", "SpellGainTable", nClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
// everyone else uses this
|
||||
sFile = GetAMSKnownFileName(nClass);
|
||||
|
||||
if (nClass == CLASS_TYPE_TRUENAMER)
|
||||
{
|
||||
sFile = "cls_true_maxlvl"; //has a different 2da we want to look at
|
||||
}
|
||||
|
||||
if (nClass == CLASS_TYPE_BINDER)
|
||||
{
|
||||
sFile = "cls_bind_binder";
|
||||
}
|
||||
}
|
||||
|
||||
return Get2DARowCount(sFile);
|
||||
}
|
||||
|
||||
int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||
{
|
||||
// This controls who can use the Spellbook NUI, if for some reason you don't
|
||||
@@ -387,7 +698,8 @@ int IsClassAllowedToUseNUISpellbook(object oPlayer, int nClass)
|
||||
return TRUE;
|
||||
|
||||
// Arcane Spont
|
||||
if (nClass == CLASS_TYPE_BEGUILER
|
||||
if (nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_CELEBRANT_SHARESS
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
|| 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
|
||||
// feat 2da so this is the list of all classes that are allowed to use the
|
||||
// Spellbook NUI and can use Metamagic
|
||||
return (nClass == CLASS_TYPE_BARD
|
||||
return (nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BARD
|
||||
|| nClass == CLASS_TYPE_SORCERER
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
@@ -525,6 +838,7 @@ int CanClassUseSuddenMetamagicFeats(int nClass)
|
||||
// Spellbook NUI and can use Sudden Metamagic
|
||||
return (nClass == CLASS_TYPE_SHADOWLORD
|
||||
|| nClass == CLASS_TYPE_ARCHIVIST
|
||||
|| nClass == CLASS_TYPE_ASSASSIN
|
||||
|| nClass == CLASS_TYPE_BARD
|
||||
|| nClass == CLASS_TYPE_BEGUILER
|
||||
|| nClass == CLASS_TYPE_DREAD_NECROMANCER
|
||||
@@ -830,16 +1144,5 @@ int JsonArrayContainsInt(json list, int item)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//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)
|
||||
{
|
||||
|
||||
@@ -520,9 +520,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));
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
|
||||
@@ -13852,7 +13852,7 @@
|
||||
"__struct_id": 0,
|
||||
"CR": {
|
||||
"type": "float",
|
||||
"value": 0.5
|
||||
"value": 0.3333
|
||||
},
|
||||
"FACTION": {
|
||||
"type": "cexostring",
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xp_multi", OBJECT_SELF);
|
||||
//ExecuteScript("tab_xp_multi", OBJECT_SELF);
|
||||
|
||||
string sResref = GetResRef(OBJECT_SELF);
|
||||
object oKiller = GetLastKiller();
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
void main()
|
||||
{
|
||||
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("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
location lSource = GetLocation(OBJECT_SELF);
|
||||
DelayCommand(1., ExplodeAtLocation(lSource, d12(55)));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
if (!GetIsPC(oPC)) return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
object oTarget;
|
||||
|
||||
@@ -2,7 +2,7 @@ void main()
|
||||
{
|
||||
|
||||
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);
|
||||
|
||||
object oSpawn;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xp_multi",OBJECT_SELF);
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
while (GetIsObjectValid(GetMaster(oPC)))
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
object oTarget;
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/// Local Override (int): PS_FORCE_SEARCH_BUTTON
|
||||
/// 1 = PS_TRUE
|
||||
/// -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
|
||||
/// 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
|
||||
/// 1 = PS_TRUE
|
||||
/// -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.
|
||||
/// Configuration File:
|
||||
@@ -79,7 +79,7 @@ const float PS_DISTANCE_DEFAULT = 2.0;
|
||||
/// Local Override (int): PS_ACCESS_TYPE
|
||||
/// 1 = PS_ACCESS_EXCLUSIVE
|
||||
/// 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:
|
||||
/// - 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
|
||||
/// 2 = PS_CONTAINER_CHARACTER
|
||||
/// 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
|
||||
/// can be of multiple types:
|
||||
@@ -124,7 +124,7 @@ const int PS_CONTAINER_TYPE_DEFAULT = PS_CONTAINER_PUBLIC;
|
||||
/// 1 = PS_CONTAINER_PUBLIC
|
||||
/// 2 = PS_CONTAINER_CHARACTER
|
||||
/// 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
|
||||
/// 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
|
||||
/// 1 = PS_TRUE
|
||||
/// -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.
|
||||
/// If the container is set to store no gold, the form controls that
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
void main()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
object oPC = GetLastKiller();
|
||||
|
||||
object oTarget;
|
||||
|
||||
@@ -24,13 +24,14 @@ void main()
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
ExecuteScript("pwfxp",OBJECT_SELF);
|
||||
|
||||
SpeakString("NW_I_AM_DEAD", TALKVOLUME_SILENT_TALK);
|
||||
//Shout Attack my target, only works with the On Spawn In setup
|
||||
SpeakString("NW_ATTACK_MY_TARGET", TALKVOLUME_SILENT_TALK);
|
||||
|
||||
if(NPC_XP == 1)
|
||||
/* if(NPC_XP == 1)
|
||||
{
|
||||
float fCR = GetChallengeRating(OBJECT_SELF);
|
||||
int nMonsterXP;
|
||||
@@ -167,5 +168,5 @@ void main()
|
||||
GiveXPToCreature(oPC, nCharXP);
|
||||
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()
|
||||
{
|
||||
ExecuteScript("nw_c2_default7", OBJECT_SELF);
|
||||
ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
//ExecuteScript("tab_xpscript",OBJECT_SELF);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user