Fixed a bunch of TLK typos. Updated Master of Shadow's Shadow Servant. Added Maul to the Metal Domain feat choice. Drider is a large creature. Added missing Eagle Claw base weapon. Tentatively fixed NUI spell selector hang issue. Fixed Monk / Shou / IoDM die increasing bug. Added StepDie() function to progressively increase Monster damage constants. Clamped Skill increases to 128 in json_AdjustCreatureSkillByID Updated PRC8 Tester module to have new weapon types. Added all spell focus feats to Wizard's bonus feat list. Updated PRC8 manual. Added notes.
843 lines
37 KiB
Plaintext
843 lines
37 KiB
Plaintext
//:://////////////////////////////////////////////
|
|
//:: Unarmed evaluation include
|
|
//:: prc_inc_unarmed
|
|
//:://////////////////////////////////////////////
|
|
/*
|
|
Handles attack bonus, damage and itemproperties
|
|
for creature weapons created based on class
|
|
and race abilities.
|
|
*/
|
|
//:://////////////////////////////////////////////
|
|
//:://////////////////////////////////////////////
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Constant declarations */
|
|
//////////////////////////////////////////////////
|
|
|
|
const int ITEM_PROPERTY_WOUNDING = 69;
|
|
|
|
const string CALL_UNARMED_FEATS = "CALL_UNARMED_FEATS";
|
|
const string CALL_UNARMED_FISTS = "CALL_UNARMED_FISTS";
|
|
const string UNARMED_CALLBACK = "UNARMED_CALLBACK";
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function prototypes */
|
|
//////////////////////////////////////////////////
|
|
|
|
|
|
// Determines the amount of unarmed damage a character can do
|
|
// ==========================================================
|
|
// oCreature a creature whose unarmed damage dice are
|
|
// being evaluated
|
|
//
|
|
// Returns one of the IP_CONST_MONSTERDAMAGE_* constants
|
|
int FindUnarmedDamage(object oCreature);
|
|
|
|
// Adds appropriate unarmed feats to the skin. Goes with UnarmedFists()
|
|
// ====================================================================
|
|
// oCreature a creature whose unarmed combat feats to handle
|
|
//
|
|
// Do not call this directly from your evaluation script. Instead, set
|
|
// the local variable CALL_UNARMED_FEATS on the creature to TRUE.
|
|
// This is done to avoid bugs from redundant calls to these functions.
|
|
void UnarmedFeats(object oCreature);
|
|
|
|
// Creates/strips a creature weapon and applies bonuses. Goes with UnarmedFeats()
|
|
// ==============================================================================
|
|
// oCreature a creature whose creature weapon to handle
|
|
//
|
|
// Do not call this directly from your evaluation script. Instead, set
|
|
// the local variable CALL_UNARMED_FISTS on the creature to TRUE.
|
|
// This is done to avoid bugs from redundant calls to these functions.
|
|
//
|
|
// If you are going to add properties to the creature weapons, hook
|
|
// your script for callback after this is evaluated by calling
|
|
// AddEventScript(oPC, CALLBACKHOOK_UNARMED, "your_script", FALSE, FALSE);
|
|
// When the callback is running, a local int UNARMED_CALLBACK will be
|
|
// set on OBJECT_SELF
|
|
void UnarmedFists(object oCreature);
|
|
|
|
/**
|
|
* Determines whether the given object is one of the PRC creature weapons based
|
|
* on it's resref and tag. Resref is tested first, then tag.
|
|
*
|
|
* @param oTest Object to test
|
|
* @return TRUE if the object is a PRC creature weapon, FALSE otherwise
|
|
*/
|
|
int GetIsPRCCreatureWeapon(object oTest);
|
|
|
|
/**
|
|
* Determines the average damage of a IP_CONST_MONSTERDAMAGE_*** constant.
|
|
* Used to compare different unarmed damages.
|
|
*
|
|
* @param iDamage IP_CONST_MONSTERDAMAGE_*** constant
|
|
* @return average damage of that constant
|
|
*/
|
|
float DamageAvg(int iDamage);
|
|
|
|
//#include "prc_alterations"
|
|
//#include "pnp_shft_poly"
|
|
//#include "prc_feat_const"
|
|
//#include "prc_ipfeat_const"
|
|
//#include "prc_class_const"
|
|
//#include "prc_racial_const"
|
|
//#include "prc_spell_const"
|
|
//#include "inc_utility"
|
|
#include "prc_inc_natweap"
|
|
|
|
//////////////////////////////////////////////////
|
|
/* Function defintions */
|
|
//////////////////////////////////////////////////
|
|
|
|
// StepDie: increases a damage die by 'nSteps' steps according to d20 SRD progression
|
|
// Increment the unarmed damage by nSteps
|
|
int StepDie(int nDamage, int nSteps)
|
|
{
|
|
int i;
|
|
for (i = 0; i < nSteps; i++)
|
|
{
|
|
switch (nDamage)
|
|
{
|
|
// 1-dice increments
|
|
case IP_CONST_MONSTERDAMAGE_1d2: nDamage = IP_CONST_MONSTERDAMAGE_1d3; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d3: nDamage = IP_CONST_MONSTERDAMAGE_1d4; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d4: nDamage = IP_CONST_MONSTERDAMAGE_1d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d6: nDamage = IP_CONST_MONSTERDAMAGE_1d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d8: nDamage = IP_CONST_MONSTERDAMAGE_1d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d10: nDamage = IP_CONST_MONSTERDAMAGE_1d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_1d12: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
|
|
|
|
// 2-dice increments
|
|
//case IP_CONST_MONSTERDAMAGE_2d3: nDamage = IP_CONST_MONSTERDAMAGE_2d4; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d4: nDamage = IP_CONST_MONSTERDAMAGE_2d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d6: nDamage = IP_CONST_MONSTERDAMAGE_2d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d8: nDamage = IP_CONST_MONSTERDAMAGE_2d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d10: nDamage = IP_CONST_MONSTERDAMAGE_2d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d12: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
|
|
|
|
// 3-dice increments
|
|
case IP_CONST_MONSTERDAMAGE_3d4: nDamage = IP_CONST_MONSTERDAMAGE_3d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_3d6: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_3d8: nDamage = IP_CONST_MONSTERDAMAGE_3d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_3d10: nDamage = IP_CONST_MONSTERDAMAGE_3d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_3d12: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
|
|
|
|
// 4-dice increments
|
|
case IP_CONST_MONSTERDAMAGE_4d4: nDamage = IP_CONST_MONSTERDAMAGE_4d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_4d6: nDamage = IP_CONST_MONSTERDAMAGE_4d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_4d8: nDamage = IP_CONST_MONSTERDAMAGE_4d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_4d10: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_4d12: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
|
|
|
|
// 5-dice increments
|
|
case IP_CONST_MONSTERDAMAGE_5d4: nDamage = IP_CONST_MONSTERDAMAGE_5d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_5d6: nDamage = IP_CONST_MONSTERDAMAGE_5d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_5d8: nDamage = IP_CONST_MONSTERDAMAGE_5d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_5d10: nDamage = IP_CONST_MONSTERDAMAGE_5d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_5d12: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
|
|
|
|
// 6-dice increments
|
|
//case IP_CONST_MONSTERDAMAGE_6d4: nDamage = IP_CONST_MONSTERDAMAGE_6d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_6d6: nDamage = IP_CONST_MONSTERDAMAGE_6d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_6d8: nDamage = IP_CONST_MONSTERDAMAGE_6d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_6d10: nDamage = IP_CONST_MONSTERDAMAGE_6d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_6d12: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
|
|
|
|
// 7-dice increments
|
|
case IP_CONST_MONSTERDAMAGE_7d4: nDamage = IP_CONST_MONSTERDAMAGE_7d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_7d6: nDamage = IP_CONST_MONSTERDAMAGE_7d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_7d8: nDamage = IP_CONST_MONSTERDAMAGE_7d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_7d10: nDamage = IP_CONST_MONSTERDAMAGE_7d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_7d12: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
|
|
|
|
// 8-dice increments
|
|
//case IP_CONST_MONSTERDAMAGE_8d4: nDamage = IP_CONST_MONSTERDAMAGE_8d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_8d6: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_8d8: nDamage = IP_CONST_MONSTERDAMAGE_8d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_8d10: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_8d12: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
|
|
|
|
// 9-dice increments
|
|
//case IP_CONST_MONSTERDAMAGE_9d4: nDamage = IP_CONST_MONSTERDAMAGE_9d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_9d6: nDamage = IP_CONST_MONSTERDAMAGE_9d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_9d8: nDamage = IP_CONST_MONSTERDAMAGE_9d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_9d10: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_9d12: nDamage = IP_CONST_MONSTERDAMAGE_6d20; break;
|
|
|
|
// 10-dice increments
|
|
//case IP_CONST_MONSTERDAMAGE_10d4: nDamage = IP_CONST_MONSTERDAMAGE_10d6; break;
|
|
case IP_CONST_MONSTERDAMAGE_10d6: nDamage = IP_CONST_MONSTERDAMAGE_10d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_10d8: nDamage = IP_CONST_MONSTERDAMAGE_10d10; break;
|
|
case IP_CONST_MONSTERDAMAGE_10d10: nDamage = IP_CONST_MONSTERDAMAGE_10d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_10d12: nDamage = IP_CONST_MONSTERDAMAGE_7d20; break;
|
|
|
|
// d20 increments
|
|
case IP_CONST_MONSTERDAMAGE_1d20: nDamage = IP_CONST_MONSTERDAMAGE_3d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_2d20: nDamage = IP_CONST_MONSTERDAMAGE_4d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_3d20: nDamage = IP_CONST_MONSTERDAMAGE_8d8; break;
|
|
case IP_CONST_MONSTERDAMAGE_4d20: nDamage = IP_CONST_MONSTERDAMAGE_8d12; break;
|
|
case IP_CONST_MONSTERDAMAGE_5d20: nDamage = IP_CONST_MONSTERDAMAGE_9d12; break; //:: Everything breaks down here
|
|
case IP_CONST_MONSTERDAMAGE_6d20: nDamage = IP_CONST_MONSTERDAMAGE_1d20; break;
|
|
case IP_CONST_MONSTERDAMAGE_7d20: nDamage = IP_CONST_MONSTERDAMAGE_8d20; break;
|
|
case IP_CONST_MONSTERDAMAGE_8d20: nDamage = IP_CONST_MONSTERDAMAGE_9d20; break;
|
|
case IP_CONST_MONSTERDAMAGE_9d20: nDamage = IP_CONST_MONSTERDAMAGE_10d20; break;
|
|
|
|
default: break; // top tier or unknown
|
|
}
|
|
}
|
|
|
|
return nDamage;
|
|
}
|
|
|
|
|
|
// Clean up any extras in the inventory.
|
|
void CleanExtraFists(object oCreature)
|
|
{
|
|
int nItemType;
|
|
object oItem = GetFirstItemInInventory(oCreature);
|
|
object oCWPB = GetItemInSlot(INVENTORY_SLOT_CWEAPON_B, oCreature);
|
|
object oCWPL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCreature);
|
|
object oCWPR = GetItemInSlot(INVENTORY_SLOT_CWEAPON_R, oCreature);
|
|
object oCSkin = GetItemInSlot(INVENTORY_SLOT_CARMOUR, oCreature);
|
|
|
|
while(GetIsObjectValid(oItem))
|
|
{
|
|
nItemType = GetBaseItemType(oItem);
|
|
|
|
if(nItemType == BASE_ITEM_CBLUDGWEAPON ||
|
|
nItemType == BASE_ITEM_CPIERCWEAPON ||
|
|
nItemType == BASE_ITEM_CREATUREITEM ||
|
|
nItemType == BASE_ITEM_CSLASHWEAPON ||
|
|
nItemType == BASE_ITEM_CSLSHPRCWEAP
|
|
)
|
|
{
|
|
if(oItem != oCWPB &&
|
|
oItem != oCWPL &&
|
|
oItem != oCWPR &&
|
|
oItem != oCSkin
|
|
)
|
|
MyDestroyObject(oItem);
|
|
}
|
|
oItem = GetNextItemInInventory(oCreature);
|
|
}
|
|
}
|
|
|
|
int GetIsPRCCreatureWeapon(object oTest)
|
|
{
|
|
string sTest = GetStringUpperCase(GetResRef(oTest));
|
|
|
|
return // First, test ResRef
|
|
sTest == "PRC_UNARMED_B" ||
|
|
sTest == "PRC_UNARMED_S" ||
|
|
sTest == "PRC_UNARMED_P" ||
|
|
sTest == "PRC_UNARMED_SP" ||
|
|
sTest == "NW_IT_CREWPB010" || // Legacy item, should not be used anymore
|
|
// If resref doesn't match, try tag
|
|
(sTest = GetStringUpperCase(GetTag(oTest))) == "PRC_UNARMED_B" ||
|
|
sTest == "PRC_UNARMED_S" ||
|
|
sTest == "PRC_UNARMED_P" ||
|
|
sTest == "PRC_UNARMED_SP" ||
|
|
sTest == "NW_IT_CREWPB010"
|
|
;
|
|
}
|
|
|
|
// Remove the unarmed penalty effect
|
|
void RemoveUnarmedAttackEffects(object oCreature)
|
|
{
|
|
effect e = GetFirstEffect(oCreature);
|
|
|
|
while (GetIsEffectValid(e))
|
|
{
|
|
if (GetEffectSpellId(e) == SPELL_UNARMED_ATTACK_PEN)
|
|
RemoveEffect(oCreature, e);
|
|
|
|
e = GetNextEffect(oCreature);
|
|
}
|
|
}
|
|
|
|
// Add the unarmed penalty effect -- the DR piercing property gives an unwanted
|
|
// attack bonus. This clears it up.
|
|
void ApplyUnarmedAttackEffects(object oCreature)
|
|
{
|
|
object oCastingObject = CreateObject(OBJECT_TYPE_PLACEABLE, "x0_rodwonder", GetLocation(OBJECT_SELF));
|
|
|
|
AssignCommand(oCastingObject, ActionCastSpellAtObject(SPELL_UNARMED_ATTACK_PEN, oCreature, METAMAGIC_NONE, TRUE, 0, PROJECTILE_PATH_TYPE_DEFAULT, TRUE));
|
|
|
|
DestroyObject(oCastingObject, 6.0);
|
|
}
|
|
|
|
// Determines the amount of damage a character can do.
|
|
// IoDM: +1 die at level 4, +2 dice at level 8
|
|
// Sacred Fist: Levels add to monk levels, or stand alone as monk levels.
|
|
// Shou: 1d6 at level 1, 1d8 at level 2, 1d10 at level 3, 2d6 at level 5
|
|
// Monk: 1d6 at level 1, 1d8 at level 4, 1d10 at level 8, 2d6 at level 12, 2d8 at level 16, 2d10 at level 20
|
|
// Frostrager: 1d6 at level 1, 1d8 at level 4
|
|
int FindUnarmedDamage(object oCreature)
|
|
{
|
|
int iDamage = 0;
|
|
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
|
|
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
|
|
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
|
|
int iSacredFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
|
|
int iEnlightenedFist = GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oCreature);
|
|
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
|
|
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
|
|
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
|
|
int iFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature);
|
|
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
|
|
int iRonove = 0;
|
|
int iMonkDamage = 1;
|
|
int iShouDamage = 1;
|
|
int iBrawlerDamage = 1;
|
|
int iFrostDamage = 1;
|
|
int iSUSDamage = 1;
|
|
int iDieIncrease = 0;
|
|
int iSize;
|
|
|
|
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
|
|
iRonove = GetLocalInt(oCreature, "RonovesFists");
|
|
|
|
//:: Determine creature size
|
|
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
|
{
|
|
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
|
|
}
|
|
else
|
|
{
|
|
iSize = 5; // medium
|
|
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
|
|
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
|
|
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
|
|
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
|
|
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
|
|
if (iSize < 1) iSize = 1;
|
|
if (iSize > 9) iSize = 9;
|
|
}
|
|
|
|
// Sacred Fist code break protection
|
|
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
|
|
|
|
// Combine monk-like levels
|
|
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
|
|
|
|
// Superior Unarmed Strike
|
|
if (GetHasFeat(FEAT_SUPERIOR_UNARMED_STRIKE, oCreature))
|
|
{
|
|
iMonk += 4;
|
|
int nHD = GetHitDice(oCreature);
|
|
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
|
|
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
|
|
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
|
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
|
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
|
|
}
|
|
|
|
// Ascetic Stalker
|
|
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
|
iMonk += iAscetic;
|
|
|
|
// Cap monk progression
|
|
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
|
|
else if (iMonk > 20) iMonk = 20;
|
|
|
|
// Ronove replacement
|
|
if (iRonove > iMonk) iMonk = iRonove;
|
|
|
|
// Monk damage calculation (2DA row)
|
|
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
|
|
if (iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
|
iMonkDamage = 8;
|
|
|
|
// Shou Disciple base damage
|
|
if (iShou > 0)
|
|
{
|
|
int nRow;
|
|
if (iShou == 1) nRow = 3;
|
|
else if (iShou == 2) nRow = 4;
|
|
else if (iShou == 3) nRow = 5;
|
|
else if (iShou == 4) nRow = 5;
|
|
else if (iShou == 5) nRow = 6;
|
|
else nRow = 3;
|
|
|
|
if (nRow > 6) nRow = 6;
|
|
|
|
iShouDamage = StringToInt(Get2DACache("unarmed_dmg", "size" + IntToString(iSize), nRow));
|
|
}
|
|
|
|
// Frostrager
|
|
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
|
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
|
|
|
// Brawler
|
|
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
|
|
if (iBrawler >= 36) iBrawlerDamage += 2;
|
|
|
|
// Armor/shield penalties
|
|
if (iMonkDamage > 1)
|
|
{
|
|
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
|
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
|
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
|
if (GetBaseAC(oArmor) > 0 || bShieldEq)
|
|
iMonkDamage = 1;
|
|
}
|
|
|
|
if (iShouDamage > 1)
|
|
{
|
|
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
|
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
|
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
|
if (GetBaseAC(oArmor) > 3 || bShieldEq)
|
|
iShouDamage = 1;
|
|
}
|
|
|
|
// Determine IoDM die increase
|
|
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease = 2;
|
|
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease = 1;
|
|
|
|
// Lookup monk damage in 2DA
|
|
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
|
|
|
|
// 3.0e monk special cases
|
|
if (iSize <= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
|
{
|
|
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
|
|
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
|
|
}
|
|
|
|
// Apply IoDM die increase last, after 2DA lookups
|
|
if (iMonkDamage > 0) iMonkDamage = StepDie(iMonkDamage, iDieIncrease);
|
|
if (iShouDamage > 0) iShouDamage = StepDie(iShouDamage, iDieIncrease);
|
|
if (iBrawlerDamage > 0) iBrawlerDamage = StepDie(iBrawlerDamage, iDieIncrease);
|
|
if (iFrostDamage > 0) iFrostDamage = StepDie(iFrostDamage, iDieIncrease);
|
|
if (iSUSDamage > 0) iSUSDamage = StepDie(iSUSDamage, iDieIncrease);
|
|
|
|
// Select best damage
|
|
iDamage = iMonkDamage;
|
|
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
|
|
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
|
|
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
|
|
iDamage = (DamageAvg(iBrawlerDamage) > DamageAvg(iDamage)) ? iBrawlerDamage : iDamage;
|
|
|
|
if (DEBUG) DoDebug("prc_inc_unarmed: iDamage "+IntToString(iDamage));
|
|
|
|
return iDamage;
|
|
}
|
|
|
|
|
|
/* int FindUnarmedDamage(object oCreature)
|
|
{
|
|
int iDamage = 0;
|
|
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
|
|
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
|
|
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
|
|
int iSacredFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
|
|
int iEnlightenedFist = GetLevelByClass(CLASS_TYPE_ENLIGHTENEDFIST, oCreature);
|
|
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
|
|
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
|
|
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
|
|
int iFrost = GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature);
|
|
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
|
|
int iRonove;
|
|
int iMonkDamage = 1;
|
|
int iShouDamage = 1;
|
|
int iBrawlerDamage = 1;
|
|
int iFrostDamage = 1;
|
|
int iSUSDamage = 1;
|
|
int iDieIncrease = 0;
|
|
int iSize;
|
|
|
|
if (GetHasSpellEffect(VESTIGE_RONOVE, oCreature) && GetLevelByClass(CLASS_TYPE_BINDER, oCreature))
|
|
iRonove = GetLocalInt(oCreature, "RonovesFists");
|
|
|
|
// Determine creature size
|
|
if( GetIsPolyMorphedOrShifted(oCreature) || GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
|
{
|
|
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5;
|
|
}
|
|
else
|
|
{
|
|
iSize = 5; // medium
|
|
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
|
|
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
|
|
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
|
|
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
|
|
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
|
|
if (iSize < 1) iSize = 1;
|
|
if (iSize > 9) iSize = 9;
|
|
}
|
|
|
|
// Sacred Fist code break protection
|
|
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
|
|
|
|
// Combine monk-like levels
|
|
iMonk += iSacredFist + iHenshin + iEnlightenedFist + iShou + iZuoken + iShadowSunNinja;
|
|
|
|
// Superior Unarmed Strike
|
|
if (GetHasFeat(FEAT_SUPERIOR_UNARMED_STRIKE, oCreature))
|
|
{
|
|
iMonk += 4;
|
|
int nHD = GetHitDice(oCreature);
|
|
if (nHD >= 16) iSUSDamage = IP_CONST_MONSTERDAMAGE_2d6;
|
|
else if (nHD >= 12) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d10;
|
|
else if (nHD >= 8) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
|
else if (nHD >= 4) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
|
else if (nHD >= 3) iSUSDamage = IP_CONST_MONSTERDAMAGE_1d4;
|
|
}
|
|
|
|
// Ascetic Stalker
|
|
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
|
iMonk += iAscetic;
|
|
|
|
// Cap monk progression
|
|
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE)) iMonk = 16;
|
|
else if (iMonk > 20) iMonk = 20;
|
|
|
|
// Ronove replacement
|
|
if (iRonove > iMonk) iMonk = iRonove;
|
|
|
|
// Monk damage calculation
|
|
if (iMonk > 0) iMonkDamage = iMonk / 4 + 3;
|
|
|
|
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
|
iMonkDamage = 8;
|
|
|
|
// Shou Disciple either adds its level to existing class or does its own damage, depending
|
|
// on which is better. Here we will determine how much damage the Shou Disciple does
|
|
// without stacking.
|
|
//if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
|
|
//if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
|
|
//iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
|
|
|
if (iShou > 0)
|
|
{
|
|
// Determine 2DA row for Shou progression
|
|
int nRow;
|
|
if (iShou == 1) nRow = 3; // monk1
|
|
else if (iShou == 2) nRow = 4; // monk2
|
|
else if (iShou == 3) nRow = 5; // monk3
|
|
else if (iShou == 4) nRow = 6; // monk4
|
|
else if (iShou == 5) nRow = 7; // monk5
|
|
else if (iShou == 6) nRow = 8; // monk6
|
|
else if (iShou == 7) nRow = 9; // monk7
|
|
else nRow = 10; // monk8+
|
|
|
|
nRow += iDieIncrease;
|
|
if (nRow > 10) nRow = 10; // clamp to max row
|
|
|
|
// Lookup damage in unarmed_damage.2da using size column
|
|
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), nRow));
|
|
}
|
|
|
|
// Frostrager
|
|
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6;
|
|
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8;
|
|
|
|
// Brawler
|
|
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3;
|
|
if (iBrawler >= 36) iBrawlerDamage += 2;
|
|
|
|
// Armor/shield penalties
|
|
if (iMonkDamage > 1)
|
|
{
|
|
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
|
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
|
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
|
|
|
if (GetBaseAC(oArmor) > 0 || bShieldEq)
|
|
iMonkDamage = 1;
|
|
}
|
|
|
|
if (iShouDamage > 1)
|
|
{
|
|
object oArmor = GetItemInSlot(INVENTORY_SLOT_CHEST, oCreature);
|
|
object oShield = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
|
int bShieldEq = GetBaseItemType(oShield) == BASE_ITEM_SMALLSHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_LARGESHIELD ||
|
|
GetBaseItemType(oShield) == BASE_ITEM_TOWERSHIELD;
|
|
|
|
if (GetBaseAC(oArmor) > 3 || bShieldEq)
|
|
iShouDamage = 1;
|
|
}
|
|
|
|
// IoDM die increase
|
|
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease += 2;
|
|
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease += 1;
|
|
|
|
iMonkDamage += iDieIncrease;
|
|
iShouDamage += iDieIncrease;
|
|
iBrawlerDamage += iDieIncrease;
|
|
iFrostDamage += iDieIncrease;
|
|
iSUSDamage += iDieIncrease;
|
|
|
|
// Lookup final monk damage in 2DA
|
|
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
|
|
|
|
// 3.0e monk special cases
|
|
if (iSize >= 5 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE))
|
|
{
|
|
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d6) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d12;
|
|
if (iMonkDamage == IP_CONST_MONSTERDAMAGE_2d10) iMonkDamage = IP_CONST_MONSTERDAMAGE_1d20;
|
|
}
|
|
|
|
// Select best damage
|
|
iDamage = iMonkDamage;
|
|
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
|
|
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
|
|
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
|
|
|
|
if (DEBUG) DoDebug("prc_inc_unarmed: iDamage "+IntToString(iDamage));
|
|
|
|
return iDamage;
|
|
}
|
|
*/
|
|
|
|
|
|
// Adds appropriate feats to the skin. Stolen from SoulTaker + expanded with overwhelming/devastating critical.
|
|
void UnarmedFeats(object oCreature)
|
|
{
|
|
// If we are polymorphed/shifted, do not mess with the creature weapon.
|
|
if (GetIsPolyMorphedOrShifted(oCreature)) return;
|
|
|
|
object oSkin = GetPCSkin(oCreature);
|
|
|
|
if (!GetHasFeat(FEAT_WEAPON_PROFICIENCY_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WEAPON_PROF_CREATURE),oSkin);
|
|
|
|
//only roll unarmed feats into creature feats when not using natural weapons
|
|
if(!GetIsUsingPrimaryNaturalWeapons(oCreature))
|
|
{
|
|
if (GetHasFeat(FEAT_WEAPON_FOCUS_UNARMED_STRIKE, oCreature) && !GetHasFeat(FEAT_WEAPON_FOCUS_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapFocCreature),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_UNARMED_STRIKE, oCreature) && !GetHasFeat(FEAT_WEAPON_SPECIALIZATION_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapSpecCreature),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_IMPROVED_CRITICAL_UNARMED_STRIKE, oCreature) && !GetHasFeat(FEAT_IMPROVED_CRITICAL_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_ImpCritCreature),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_UNARMED, oCreature) && !GetHasFeat(FEAT_EPIC_WEAPON_FOCUS_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapEpicFocCreature),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_UNARMED, oCreature) && !GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_WeapEpicSpecCreature),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_EPIC_OVERWHELMING_CRITICAL_UNARMED, oCreature) && !GetHasFeat(FEAT_EPIC_OVERWHELMING_CRITICAL_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_OVERCRITICAL_CREATURE),oSkin);
|
|
|
|
if (GetHasFeat(FEAT_EPIC_DEVASTATING_CRITICAL_UNARMED, oCreature) && !GetHasFeat(FEAT_EPIC_DEVASTATING_CRITICAL_CREATURE, oCreature))
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,PRCItemPropertyBonusFeat(IP_CONST_FEAT_DEVCRITICAL_CREATURE),oSkin);
|
|
}
|
|
}
|
|
|
|
// Creates/strips a creature weapon and applies bonuses. Large chunks stolen from SoulTaker.
|
|
void UnarmedFists(object oCreature)
|
|
{
|
|
// If we are polymorphed/shifted, do not mess with the creature weapon.
|
|
if (GetIsPolyMorphedOrShifted(oCreature)) return;
|
|
|
|
RemoveUnarmedAttackEffects(oCreature);
|
|
|
|
object oRighthand = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oCreature);
|
|
object oLefthand = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oCreature);
|
|
object oWeapL = GetItemInSlot(INVENTORY_SLOT_CWEAPON_L, oCreature);
|
|
|
|
|
|
// Clean up the mess of extra fists made on taking first level.
|
|
DelayCommand(6.0f, CleanExtraFists(oCreature));
|
|
|
|
// Determine the character's capacity to pierce DR.
|
|
// only applies when not using natural weapons
|
|
if(!GetIsUsingPrimaryNaturalWeapons(oCreature))
|
|
{
|
|
|
|
int iRace = GetRacialType(oCreature);
|
|
int iMonk = GetLevelByClass(CLASS_TYPE_MONK, oCreature) + GetLocalInt(oCreature, "LiPengMonk");
|
|
int iShou = GetLevelByClass(CLASS_TYPE_SHOU, oCreature);
|
|
int iSacFist = GetLevelByClass(CLASS_TYPE_SACREDFIST, oCreature);
|
|
int iHenshin = GetLevelByClass(CLASS_TYPE_HENSHIN_MYSTIC, oCreature);
|
|
int iIoDM = GetLevelByClass(CLASS_TYPE_INITIATE_DRACONIC, oCreature);
|
|
int iBrawler = GetLevelByClass(CLASS_TYPE_BRAWLER, oCreature);
|
|
int iZuoken = GetLevelByClass(CLASS_TYPE_FIST_OF_ZUOKEN, oCreature);
|
|
int iShadowSunNinja = GetLevelByClass(CLASS_TYPE_SHADOW_SUN_NINJA, oCreature);
|
|
int iAscetic = GetLevelByClass(CLASS_TYPE_NINJA, oCreature);
|
|
|
|
// Sacred Fists who break their code get no benefits.
|
|
if (GetHasFeat(FEAT_SF_CODE,oCreature)) iSacFist = 0;
|
|
|
|
// The monk adds all these classes.
|
|
int iMonkEq = iMonk + iShou + iSacFist + iHenshin + iZuoken + iShadowSunNinja;
|
|
|
|
// Ascetic Stalker
|
|
if (GetHasFeat(FEAT_ASCETIC_STALKER, oCreature))
|
|
iMonkEq += iAscetic;
|
|
|
|
// Determine the type of damage the character should do.
|
|
string sWeapType;
|
|
if (GetHasFeat(FEAT_CLAWDRAGON, oCreature))
|
|
sWeapType = "PRC_UNARMED_S";
|
|
else
|
|
sWeapType = "PRC_UNARMED_B";
|
|
|
|
|
|
// Equip the creature weapon.
|
|
if (!GetIsObjectValid(oWeapL) || GetTag(oWeapL) != sWeapType)
|
|
{
|
|
if (GetHasItem(oCreature, sWeapType))
|
|
{
|
|
oWeapL = GetItemPossessedBy(oCreature, sWeapType);
|
|
SetIdentified(oWeapL, TRUE);
|
|
AssignCommand(oCreature, ActionEquipItem(oWeapL, INVENTORY_SLOT_CWEAPON_L));
|
|
}
|
|
else
|
|
{
|
|
oWeapL = CreateItemOnObject(sWeapType, oCreature);
|
|
SetIdentified(oWeapL, TRUE);
|
|
AssignCommand(oCreature,ActionEquipItem(oWeapL, INVENTORY_SLOT_CWEAPON_L));
|
|
}
|
|
}
|
|
|
|
int iKi = (iMonkEq > 9) ? 1 : 0;
|
|
iKi = (iMonkEq > 12) ? 2 : iKi;
|
|
iKi = (iMonkEq > 15) ? 3 : iKi;
|
|
|
|
int iDragClaw = GetHasFeat(FEAT_CLAWDRAGON,oCreature) ? 1: 0;
|
|
iDragClaw = GetHasFeat(FEAT_CLAWENH2,oCreature) ? 2: iDragClaw;
|
|
iDragClaw = GetHasFeat(FEAT_CLAWENH3,oCreature) ? 3: iDragClaw;
|
|
|
|
int iBrawlEnh = iBrawler / 6;
|
|
|
|
int iEpicKi = GetHasFeat(FEAT_EPIC_IMPROVED_KI_STRIKE_4,oCreature) ? 1 : 0 ;
|
|
iEpicKi = GetHasFeat(FEAT_EPIC_IMPROVED_KI_STRIKE_5,oCreature) ? 2 : iEpicKi ;
|
|
|
|
// The total enhancement to the fist is the sum of all the enhancements above
|
|
int iEnh = iKi + iDragClaw + iBrawlEnh + iEpicKi;
|
|
|
|
// Strip the Fist.
|
|
itemproperty ip = GetFirstItemProperty(oWeapL);
|
|
while (GetIsItemPropertyValid(ip))
|
|
{
|
|
RemoveItemProperty(oWeapL, ip);
|
|
ip = GetNextItemProperty(oWeapL);
|
|
}
|
|
|
|
// Leave the fist blank if weapons are equipped. The only way a weapon will
|
|
// be equipped on the left hand is if there is a weapon in the right hand.
|
|
if (GetIsObjectValid(oRighthand)) return;
|
|
|
|
// Add glove bonuses.
|
|
object oItem = GetItemInSlot(INVENTORY_SLOT_ARMS,oCreature);
|
|
int iGloveEnh = 0;
|
|
if (GetIsObjectValid(oItem))
|
|
{
|
|
int iType = GetBaseItemType(oItem);
|
|
if (iType == BASE_ITEM_GLOVES)
|
|
{
|
|
ip = GetFirstItemProperty(oItem);
|
|
while(GetIsItemPropertyValid(ip))
|
|
{
|
|
iType = GetItemPropertyType(ip);
|
|
switch (iType)
|
|
{
|
|
case ITEM_PROPERTY_DAMAGE_BONUS:
|
|
case ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP:
|
|
case ITEM_PROPERTY_DAMAGE_BONUS_VS_RACIAL_GROUP:
|
|
case ITEM_PROPERTY_DAMAGE_BONUS_VS_SPECIFIC_ALIGNMENT:
|
|
case ITEM_PROPERTY_ON_HIT_PROPERTIES:
|
|
case ITEM_PROPERTY_ONHITCASTSPELL:
|
|
case ITEM_PROPERTY_EXTRA_MELEE_DAMAGE_TYPE:
|
|
case ITEM_PROPERTY_KEEN:
|
|
case ITEM_PROPERTY_MASSIVE_CRITICALS:
|
|
case ITEM_PROPERTY_POISON:
|
|
case ITEM_PROPERTY_REGENERATION_VAMPIRIC:
|
|
case ITEM_PROPERTY_WOUNDING:
|
|
case ITEM_PROPERTY_DECREASED_DAMAGE:
|
|
case ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER:
|
|
DelayCommand(0.1, AddItemProperty(DURATION_TYPE_PERMANENT,ip,oWeapL));
|
|
break;
|
|
case ITEM_PROPERTY_ATTACK_BONUS:
|
|
int iCost = GetItemPropertyCostTableValue(ip);
|
|
iGloveEnh = (iCost>iGloveEnh) ? iCost:iGloveEnh;
|
|
iEnh = (iCost>iEnh) ? iCost:iEnh;
|
|
break;
|
|
}
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
// handles these seperately so as not to create "attack penalties vs. xxxx"
|
|
ip = GetFirstItemProperty(oItem);
|
|
while(GetIsItemPropertyValid(ip))
|
|
{
|
|
iType = GetItemPropertyType(ip);
|
|
switch (iType)
|
|
{
|
|
case ITEM_PROPERTY_ATTACK_BONUS_VS_SPECIFIC_ALIGNMENT:
|
|
case ITEM_PROPERTY_ATTACK_BONUS_VS_ALIGNMENT_GROUP:
|
|
case ITEM_PROPERTY_ATTACK_BONUS_VS_RACIAL_GROUP:
|
|
if (GetItemPropertyCostTableValue(ip) > iEnh)
|
|
DelayCommand(0.1, AddItemProperty(DURATION_TYPE_PERMANENT,ip,oWeapL));
|
|
break;
|
|
}
|
|
ip = GetNextItemProperty(oItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add damage resistance penetration.
|
|
DelayCommand(0.1, AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyAttackBonus(iEnh), oWeapL));
|
|
|
|
// Cool VFX when striking unarmed
|
|
if (iMonkEq > 9)
|
|
//DelayCommand(0.1, AddItemProperty(DURATION_TYPE_PERMANENT, PRCItemPropertyBonusFeat(IP_CONST_FEAT_KI_STRIKE), oWeapL));
|
|
DelayCommand(0.1, IPSafeAddItemProperty(oWeapL, PRCItemPropertyBonusFeat(IP_CONST_FEAT_KI_STRIKE), 0.0f, X2_IP_ADDPROP_POLICY_KEEP_EXISTING, FALSE, FALSE));
|
|
|
|
// This adds creature weapon finesse and a penalty to offset the DR penetration attack bonus.
|
|
SetLocalInt(oCreature, "UnarmedEnhancement", iEnh);
|
|
SetLocalInt(oCreature, "UnarmedEnhancementGlove", iGloveEnh);
|
|
}
|
|
|
|
// Weapon finesse or intuitive attack?
|
|
SetLocalInt(oCreature, "UsingCreature", TRUE);
|
|
ExecuteScript("prc_intuiatk", oCreature);
|
|
DelayCommand(1.0f, DeleteLocalInt(oCreature, "UsingCreature"));
|
|
ApplyUnarmedAttackEffects(oCreature);
|
|
|
|
// Add the appropriate damage to the fist.
|
|
int iMonsterDamage = FindUnarmedDamage(oCreature);
|
|
AddItemProperty(DURATION_TYPE_PERMANENT,ItemPropertyMonsterDamage(iMonsterDamage),oWeapL);
|
|
|
|
// Add OnHitCast: Unique if necessary. Frostrager level 5 grants Rend too
|
|
if(GetHasFeat(FEAT_REND, oCreature) || GetLevelByClass(CLASS_TYPE_FROSTRAGER, oCreature) > 4)
|
|
IPSafeAddItemProperty(oWeapL,
|
|
ItemPropertyOnHitCastSpell(IP_CONST_ONHIT_CASTSPELL_ONHIT_UNIQUEPOWER, 1));
|
|
|
|
// Friendly message to remind players that certain things won't appear correct.
|
|
if (GetLocalInt(oCreature, "UnarmedSubSystemMessage") != TRUE
|
|
&& GetHasSpellEffect(SPELL_UNARMED_ATTACK_PEN, oCreature))
|
|
{
|
|
SetLocalInt(oCreature, "UnarmedSubSystemMessage", TRUE);
|
|
DelayCommand(3.001f, SendMessageToPC(oCreature, "This character uses the PRC's unarmed system. This system has been created to"));
|
|
DelayCommand(3.002f, SendMessageToPC(oCreature, "work around many Aurora engine bugs and limitations. Your attack roll may appear to be"));
|
|
DelayCommand(3.003f, SendMessageToPC(oCreature, "incorrect on the character's stats. However, the attack rolls should be correct in"));
|
|
DelayCommand(3.004f, SendMessageToPC(oCreature, "combat. Disregard any attack effects that seem extra: they are part of the workaround."));
|
|
DelayCommand(600.0f, DeleteLocalInt(oCreature, "UnarmedSubSystemMessage"));
|
|
}
|
|
}
|
|
|
|
float DamageAvg(int iDamage)
|
|
{
|
|
int iDie = StringToInt(Get2DACache("iprp_monstcost", "Die", iDamage));
|
|
int iNum = StringToInt(Get2DACache("iprp_monstcost", "NumDice", iDamage));
|
|
|
|
return IntToFloat(iNum * (iDie+1)) / 2;
|
|
}
|
|
|
|
//:: void main (){}
|