Add Shadow Servant and unarmed system updates
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.
This commit is contained in:
19
Notes/INFO-prc8_unarmed_dmg.2da
Normal file
19
Notes/INFO-prc8_unarmed_dmg.2da
Normal file
@@ -0,0 +1,19 @@
|
||||
This is a version of prc_unarmed_dmg.2da that has been modified to show the damage amounts along with the constant
|
||||
|
||||
2DA V2.0
|
||||
|
||||
Label size1 size2 size3 size4 size5 size6 size7 size8 size9
|
||||
0 **** **** **** **** **** **** **** **** **** ****
|
||||
1 normal1 "1 / 1d2" "1 / 1d2" "1 / 1d2" "1 / 1d2" "2 / 1d3" "3 /1d4" "4 / 1d8" "18 / 1d8" "9 / 2d6"
|
||||
2 normal2 "1 / 1d2" "1 / 1d2" "1 / 1d2" "2 / 1d3" "3 /1d4" "8 / 1d6" "18 / 1d8" "9 / 2d6" "10 / 3d6"
|
||||
3 monk1 "1 / 1d2" "1 / 1d2" "2 / 1d3" "3 /1d4" "8 / 1d6" "18 / 1d8" "9 / 2d6" "10 / 3d6" "11 / 4d6"
|
||||
4 monk2 "1 / 1d2" "2 / 1d3" "3 /1d4" "8 / 1d6" "18 / 1d8" "9 / 2d6" "10 / 3d6" "11 / 4d6" "13 / 2d6"
|
||||
5 monk3 "2 / 1d3" "3 /1d4" "8 / 1d6" "18 / 1d8" "28 / 1d10" "19 /2d8" "20 / 3d8" "21 / 4d8" "23 / 6d8"
|
||||
6 monk4 "3 /1d4" "8 / 1d6" "18 / 1d8" "28 / 1d10" "9 / 2d6" "10 / 3d6" "11 / 4d6" "13 / 2d6" "15 / 8d6"
|
||||
7 monk5 "8 / 1d6" "18 / 1d8" "28 / 1d10" "9 / 2d6" "19 /2d8" "20 / 3d8" "21 / 4d8" "23 / 6d8" "25 / 8d8"
|
||||
8 monk6 "18 / 1d8" "28 / 1d10" "9 / 2d6" "19 /2d8" "29 / 2d10" "21 / 4d8" "23 / 6d8" "25 / 8d8" "52 / 5d20"
|
||||
9 monk7 "28 / 1d10" "9 / 2d6" "19 /2d8" "29 / 2d10" "11 / 4d6" "13 / 2d6" "15 / 8d6" "51 / 4d20" "37 / 10d10"
|
||||
10 monk8 "9 / 2d6" "19 /2d8" "29 / 2d10" "11 / 4d6" "21 / 4d8" "23 / 6d8" "25 / 8d8" "52 / 5d20" "54 / 7d20"
|
||||
11 brawler7 "18 / 1d8" "28 / 1d10" "5 / 3d4" "10 / 3d6" "20 / 3d8" "21 / 4d8" "23 / 6d8" "25 / 8d8" "52 / 5d20"
|
||||
12 brawler8 "28 / 1d10" "5 / 3d4" "10 / 3d6" "20 / 3d8" "30 / 3d10" "23 / 6d8" "25 / 8d8" "52 / 5d20" "54 / 7d20"
|
||||
13 brawler9 "5 / 3d4" "10 / 3d6" "20 / 3d8" "30 / 3d10" "13 / 6d6" "15 / 8d6" "51 / 4d20" "37 / 10d10" "55 / 8d20"
|
||||
57
Notes/PnP Shadow Familiar.txt
Normal file
57
Notes/PnP Shadow Familiar.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
Shadow Servant
|
||||
Medium Elemental (Extraplanar and Incorporeal)
|
||||
Initiative: +5; Senses: blindsight 60 ft., Listen +3, and Spot +4
|
||||
AC: 12 (+1 Dex, +1 deflection), touch 12, flat-footed 11
|
||||
Hit Dice: 4d8+8 (26 hp)
|
||||
Fort +3, Ref +5, Will +1 Speed: Fly 40 ft. (perfect)
|
||||
Space: 5 ft./5 ft.
|
||||
Base Attack +3; Grapple +3
|
||||
Attack: Incorporeal touch +4 melee
|
||||
Damage: Incorporeal touch 1d6 plus 1d6 cold
|
||||
Special Attacks/Actions: Shadow mastery, dusk and dawn
|
||||
|
||||
Abilities: Str -, Dex 12, Con 14, Int 4, Wis 11, Cha 11
|
||||
Special Qualities: elemental traits, incorporeal traits
|
||||
Feats: Combat Reflexes; Improved Initiative
|
||||
Skills: Listen +3 and Spot +4
|
||||
|
||||
|
||||
PC Lvl Bonus HD Dex Adj. Stat Increase Special Feat Master's Bidding
|
||||
0th +0 - - Weapon Finesse Alertness# -
|
||||
0th +0 - - - - -
|
||||
0th +0 - - - Imp. Initiative -
|
||||
0th +0 - - - - -
|
||||
1st +0 - - - - Interact with corporeal, fast healing 1
|
||||
2nd +1 - - Resistance to cold 5 WF: Creature (291) Extra attack
|
||||
3rd +2 - +4 CON,-2 DEX Size becomes Large - -
|
||||
4th +3 - +1 CON Resistance to cold 10 - Cold damage +1d8
|
||||
5th +4 +2 - Deliver touch spells Dodge (10) -
|
||||
6th +5 - - Resistance to cold 20 - -
|
||||
7th +6 +4 - - - Reach +5 ft.
|
||||
8th +7 - +1 CON - Mobility (26) DR 5/-
|
||||
9th +8 +6 - - - Speed +20 ft.
|
||||
10th +9 - - Immunity to cold - -
|
||||
11th +10 +8 - - Spr. Attack (392) -
|
||||
12th +11 - +1 CON - - -
|
||||
13th +12 +10 - - - -
|
||||
14th +13 - - - Iron Will (22) -
|
||||
15th +14 +12 - - - -
|
||||
16th +15 - +1 CON - - -
|
||||
17th +16 +14 - - Lightn. Ref. (24) -
|
||||
18th +17 - - - - -
|
||||
19th +18 +16 - - - -
|
||||
20th +19 - +1 CON - Imp. Crit (292) -
|
||||
21st +20 +18 - - - -
|
||||
22nd +21 - - - - -
|
||||
23rd +22 +20 - - Blind-Fight (408) -
|
||||
24th +23 - +1 CON - - -
|
||||
25th +24 +22 - - - -
|
||||
26th +25 - - - Toughness (40) -
|
||||
27th +26 +24 - - - -
|
||||
28th +27 - +1 CON - - -
|
||||
29th +28 +26 - - Gr. Fort (14) -
|
||||
30th +29 - - - - -
|
||||
|
||||
+1 Listen per Bonus HD
|
||||
|
||||
# Replaces Combat Reflexes
|
||||
168
Notes/mshdw_shadserv.nss
Normal file
168
Notes/mshdw_shadserv.nss
Normal file
@@ -0,0 +1,168 @@
|
||||
//::////////////////////////////////////////////////////////
|
||||
//:: ;-. ,-. ,-. ,-.
|
||||
//:: | ) | ) / ( )
|
||||
//:: |-' |-< | ;-:
|
||||
//:: | | \ \ ( )
|
||||
//:: ' ' ' `-' `-'
|
||||
//::///////////////////////////////////////////////////////
|
||||
//::
|
||||
/*
|
||||
Impactscript for Shadow Servant.
|
||||
(this is handled in the Familiar script)
|
||||
|
||||
Shadow Servant (Su): At 1st level, your shadow familiar permanently
|
||||
transforms into a Medium shadow elemental. It loses all familiar
|
||||
traits, but gains new abilities as your shadow servant.
|
||||
|
||||
Should your shadow servant die, you can summon a replacement after
|
||||
24 hours pass. Your shadow servant cannot travel farther from you
|
||||
than 30 feet + 10 feet for each of your master of shadow levels
|
||||
(40 feet at 1st level and a maximum of 130 feet at 10th level). If
|
||||
it is forcibly separated from you by more than this distance, the
|
||||
servant dissipates instantly, and you must wait 24 hours to summon
|
||||
a new one.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
//::
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Script: mshadw_shadserv.nss
|
||||
//:: Author: Jaysyn
|
||||
//:: Created: 2025-11-11 19:25:58
|
||||
//:://////////////////////////////////////////////
|
||||
#include "prc_inc_json"
|
||||
#include "prc_inc_spells"
|
||||
|
||||
const string SHADOW_SERVANT_RESREF = "prc_shadow_serv";
|
||||
|
||||
// Watch function: despawns Shadow Servant if master is dead or out of range
|
||||
void ShadowServantWatch(object oShadow, object oPC)
|
||||
{
|
||||
if(DEBUG) DoDebug("mshadw_shadserv >> ShadowServantWatch: Starting function.");
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
if (!GetIsObjectValid(oShadow) || !GetIsObjectValid(oPC)) return;
|
||||
|
||||
if (GetIsDead(oPC) ||
|
||||
GetDistanceBetween(oShadow, oPC) > FeetToMeters(fRange))
|
||||
{
|
||||
DestroyObject(oShadow);
|
||||
return;
|
||||
}
|
||||
|
||||
DelayCommand(1.0, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
object oPC = OBJECT_SELF;
|
||||
|
||||
int nMaster = GetLevelByClass(CLASS_TYPE_MASTER_OF_SHADOW, oPC);
|
||||
|
||||
int nDexBonus = (nMaster >= 5 && (nMaster % 2)) ? (nMaster - 3) : 0;
|
||||
|
||||
float fRange = 30.0 + (nMaster * 10);
|
||||
|
||||
// Target location
|
||||
location lTarget = GetSpellTargetLocation();
|
||||
|
||||
// Distance check
|
||||
if (GetDistanceBetweenLocations(GetLocation(oPC), lTarget) > FeetToMeters(fRange))
|
||||
{
|
||||
SendMessageToPC(oPC, "That location is too far away.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Load template
|
||||
json jShadow = TemplateToJson(SHADOW_SERVANT_RESREF, RESTYPE_UTC);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: TemplateToJson failed <20> bad resref or resource missing.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Original HD
|
||||
int nOriginalHD = json_GetCreatureHD(jShadow);
|
||||
if (nOriginalHD <= 0)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_GetCreatureHD failed <20> template missing HD data.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Add Hit Dice
|
||||
int nHDToAdd = nMaster -1;
|
||||
|
||||
if (nHDToAdd < 0) nHDToAdd = 0;
|
||||
|
||||
jShadow = json_AddHitDice(jShadow, nHDToAdd);
|
||||
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddHitDice failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update feats
|
||||
jShadow = json_AddFeatsFromCreatureVars(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AddFeatsFromCreatureVars failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Update stats
|
||||
jShadow = json_ApplyAbilityBoostFromHD(jShadow, nOriginalHD);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_ApplyAbilityBoostFromHD failed <20> JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
|
||||
//:: Bonus DEX from Shadow Servant class ability
|
||||
jShadow = json_UpdateTemplateStats(jShadow, 0, nDexBonus);
|
||||
|
||||
// Size increase
|
||||
if (nMaster > 2)
|
||||
{
|
||||
jShadow = json_AdjustCreatureSize(jShadow, 1, TRUE);
|
||||
if (jShadow == JSON_NULL)
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: json_AdjustCreatureSize failed - JSON became invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
object oShadow = JsonToObject(jShadow, lTarget);
|
||||
effect eSummon = ExtraordinaryEffect(EffectSummonCreature("", VFX_FNF_SUMMON_UNDEAD, 0.0, 0, VFX_IMP_UNSUMMON, oShadow));
|
||||
|
||||
ApplyEffectAtLocation(DURATION_TYPE_PERMANENT, eSummon, lTarget);
|
||||
|
||||
if (!GetIsObjectValid(oShadow))
|
||||
{
|
||||
SendMessageToPC(oPC, "mshdw_shadserv: JsonToObject failed - could not create creature from edited template.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set faction to caster<65>s
|
||||
ChangeFaction(oShadow, oPC);
|
||||
SetLocalObject(oShadow, "ANIMATOR", oPC);
|
||||
|
||||
SetCurrentHitPoints(oShadow, GetMaxPossibleHP(oShadow));
|
||||
|
||||
effect eGhost = EffectVisualEffect(VFX_DUR_GHOST_TRANSPARENT);
|
||||
eGhost = UnyieldingEffect(eGhost);
|
||||
|
||||
ApplyEffectToObject(DURATION_TYPE_PERMANENT, eGhost, oShadow);
|
||||
|
||||
// Full round wait then move
|
||||
AssignCommand(oShadow, ClearAllActions());
|
||||
AssignCommand(oShadow, ActionWait(6.0));
|
||||
AssignCommand(oShadow, ActionMoveToObject(oPC));
|
||||
|
||||
// Start watch loop
|
||||
DelayCommand(6.1, ShadowServantWatch(oShadow, oPC));
|
||||
}
|
||||
596
Notes/prc_inc_unarmed.nss
Normal file
596
Notes/prc_inc_unarmed.nss
Normal file
@@ -0,0 +1,596 @@
|
||||
//:://////////////////////////////////////////////
|
||||
//:: 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 */
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
// 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 dice 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;
|
||||
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");
|
||||
|
||||
// if the creature is shifted, use model size
|
||||
// otherwise, we want to stick to what the feats say they "should" be.
|
||||
// No making pixies with Dragon Appearance for "huge" fist damage.
|
||||
if( GetIsPolyMorphedOrShifted(oCreature)
|
||||
|| GetPRCSwitch(PRC_APPEARANCE_SIZE))
|
||||
{
|
||||
iSize = PRCGetCreatureSize(oCreature) - CREATURE_SIZE_MEDIUM + 5; // medium is size 5 for us
|
||||
}
|
||||
else
|
||||
{
|
||||
// Determine creature size by feats.
|
||||
iSize = 5; // medium is size 5 for us
|
||||
if (GetHasFeat(FEAT_TINY, oCreature)) iSize = 3;
|
||||
if (GetHasFeat(FEAT_SMALL, oCreature)) iSize = 4;
|
||||
if (GetHasFeat(FEAT_LARGE, oCreature)) iSize = 6;
|
||||
if (GetHasFeat(FEAT_HUGE, oCreature)) iSize = 7;
|
||||
// include size changes
|
||||
iSize += PRCGetCreatureSize(oCreature) - PRCGetCreatureSize(oCreature, PRC_SIZEMASK_NONE);
|
||||
// cap if needed
|
||||
if (iSize < 1) iSize = 1;
|
||||
if (iSize > 9) iSize = 9;
|
||||
}
|
||||
|
||||
// Sacred Fist cannot add their levels if they've broken their code.
|
||||
if (GetHasFeat(FEAT_SF_CODE, oCreature)) iSacredFist = 0;
|
||||
|
||||
// several classes add their levels to the monk class,
|
||||
// or use monk progression if the character has no monk levels
|
||||
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;
|
||||
|
||||
// In 3.0e, Monk progression stops after level 16:
|
||||
if (iMonk > 16 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonk = 16;
|
||||
// in 3.5e, monk progression stops at 20.
|
||||
else if(iMonk > 20) iMonk = 20;
|
||||
|
||||
// Ronove is in place of monk, does not stack
|
||||
if (iRonove > iMonk) iMonk = iRonove;
|
||||
|
||||
// monks damage progesses every four levels, starts at 1d6
|
||||
if (iMonk > 0)
|
||||
iMonkDamage = iMonk / 4 + 3;
|
||||
|
||||
// For medium monks in 3.0e skip 2d8 and go to 1d20
|
||||
if(iSize == 5 && iMonkDamage == 7 && !GetPRCSwitch(PRC_3_5e_FIST_DAMAGE) ) iMonkDamage = 8;
|
||||
|
||||
// Shou Disciple either adds its level to existing class or does its own damage, depending
|
||||
// on which is better. Here we will determine how much damage the Shou Disciple does
|
||||
// without stacking.
|
||||
if (iShou > 0) iShouDamage = iShou + 2; // Lv. 1: 1d6, Lv. 2: 1d8, Lv. 3: 1d10
|
||||
if (iShou > 3) iShouDamage--; // Lv. 4: 1d10, Lv. 5: 2d6
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
||||
|
||||
// Frostrager does not stack with other damage types
|
||||
if (iFrost > 0) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d6; // Lv. 1: 1d6
|
||||
if (iFrost > 3) iFrostDamage = IP_CONST_MONSTERDAMAGE_1d8; // Lv. 3: 1d8
|
||||
|
||||
// Brawler follows monk progression except for the last one (3d8)
|
||||
if (iBrawler > 0) iBrawlerDamage = iBrawler / 6 + 3; // 1d6, 1d8, 1d10, 2d6, 2d8, 2d10
|
||||
if (iBrawler >= 36) iBrawlerDamage += 2; // 3d8
|
||||
|
||||
// Monks and monk-like classes deal no additional damage when wearing any armor, at
|
||||
// least in NWN. This is to reflect that. No shields too.
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Shou Disciples can wear light armor
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// For Initiate of Draconic Mysteries
|
||||
if (GetHasFeat(FEAT_INCREASE_DAMAGE2, oCreature)) iDieIncrease += 2;
|
||||
else if (GetHasFeat(FEAT_INCREASE_DAMAGE1, oCreature)) iDieIncrease += 1;
|
||||
|
||||
/* //:: Expansion / Compression powers (Double dipping?)
|
||||
int nExpansion = GetLocalInt(oCreature, "PRC_Power_Expansion_SizeIncrease");
|
||||
int nCompression = GetLocalInt(oCreature, "PRC_Power_Compression_SizeReduction");
|
||||
|
||||
if (nExpansion)
|
||||
{
|
||||
iSize += nExpansion;
|
||||
}
|
||||
|
||||
if (nCompression)
|
||||
{
|
||||
iSize -= nCompression;
|
||||
} */
|
||||
|
||||
iMonkDamage += iDieIncrease;
|
||||
iShouDamage += iDieIncrease;
|
||||
iBrawlerDamage += iDieIncrease;
|
||||
iFrostDamage += iDieIncrease;
|
||||
iSUSDamage += iDieIncrease;
|
||||
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Size is: "+IntToString(iSize)+".", oCreature);
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Pre 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
|
||||
|
||||
// now, read the damage from the table in unarmed_dmg.2da
|
||||
iMonkDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iMonkDamage));
|
||||
iShouDamage = StringToInt(Get2DACache("unarmed_dmg","size" + IntToString(iSize), iShouDamage));
|
||||
|
||||
//FloatingTextStringOnCreature("prc_inc_unarmed: Post 2DA Lookup >> iMonkDamage = "+IntToString(iMonkDamage)+".", oCreature);
|
||||
|
||||
// Medium+ monks have some special values on the table in 3.0:
|
||||
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;
|
||||
}
|
||||
|
||||
iDamage = iMonkDamage;
|
||||
// Future unarmed classes: if you do your own damage, add in "comparisons" below here.
|
||||
iDamage = (DamageAvg(iShouDamage ) > DamageAvg(iDamage)) ? iShouDamage : iDamage;
|
||||
iDamage = (DamageAvg(iFrostDamage ) > DamageAvg(iDamage)) ? iFrostDamage : iDamage;
|
||||
iDamage = (DamageAvg(iSUSDamage ) > DamageAvg(iDamage)) ? iSUSDamage : iDamage;
|
||||
|
||||
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 (){}
|
||||
Reference in New Issue
Block a user