Further file organization
Further file organization
This commit is contained in:
685
nwn/nwnprc/trunk/include/prc_inc_sneak.nss
Normal file
685
nwn/nwnprc/trunk/include/prc_inc_sneak.nss
Normal file
@@ -0,0 +1,685 @@
|
||||
|
||||
// * Various functions to determine sneak dice.
|
||||
|
||||
// * Used to find the total sneak dice a character is capable of.
|
||||
int GetTotalSneakAttackDice(object oPC);
|
||||
|
||||
// * Used to find the total rogue sneak dice a character is capable of.
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Future PRC's go here. DO NOT ADD ROGUE/BLACKGUARD/ASSASSIN SNEAK ATTACKS AS CLASS FEATS.
|
||||
// Placeholder feats are fine, even encouraged. Example: "Ranged Sneak Attack +1d6".
|
||||
// The feat should do nothing, just show that you have the bonus.
|
||||
// -----------------------------------------------------------------------------------------
|
||||
int GetRogueSneak(object oPC);
|
||||
|
||||
// * Used to find the total blackguard sneak dice a character is capable of.
|
||||
int GetBlackguardSneak(object oPC);
|
||||
|
||||
// * Used to find the total assassin sneak dice a character is capable of.
|
||||
int GetAssassinSneak(object oPC);
|
||||
|
||||
// * Used to find how much a character has taken "Improved Sneak Attack".
|
||||
int GetEpicFeatSneak(object oPC);
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Sneak Attack Functions
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
// Checks if attacker is flanking the defender or not
|
||||
int GetIsFlanked(object oDefender, object oAttacker);
|
||||
|
||||
// Checks if an AoE spell is flanking the defender
|
||||
int GetIsAOEFlanked(object oDefender, object oAttacker);
|
||||
|
||||
// Determines if a creature is helpless.
|
||||
// (effective dex modifier of 0, and can be Coup De Graced).
|
||||
int GetIsHelpless(object oDefender);
|
||||
|
||||
// Returns if oDefender is denied dex bonus to AC from spells
|
||||
// int nIgnoreUD - ignores Uncanny Dodge
|
||||
int GetIsDeniedDexBonusToAC(object oDefender, object oAttacker, int nIgnoreUD = FALSE);
|
||||
|
||||
// Returns FALSE if oDefender has no concealment
|
||||
// or the int amount of concealment on the defender.
|
||||
int GetIsConcealed(object oDefender, object oAttacker);
|
||||
|
||||
// Returns true if the Attacker can Sneak Attack the target
|
||||
int GetCanSneakAttack(object oDefender, object oAttacker);
|
||||
|
||||
// Returns Sneak Attack Damage
|
||||
int GetSneakAttackDamage(int iSneakAttackDice);
|
||||
|
||||
//Returns applicable elemental type for Dragonfire Strike
|
||||
int GetDragonfireDamageType(object oPC);
|
||||
|
||||
// * Used to find the total favoured enemy bonus a character is capable of.
|
||||
int GetFavouredEnemyBonus(object oPC);
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Includes
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
//#include "prc_class_const"
|
||||
//#include "prc_feat_const"
|
||||
#include "tob_move_const"
|
||||
#include "prc_x2_itemprop"
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Definitions
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
int GetTotalSneakAttackDice(object oPC)
|
||||
{
|
||||
int iSneakAttackDice = GetRogueSneak(oPC) + GetBlackguardSneak(oPC) +
|
||||
GetAssassinSneak(oPC) + GetEpicFeatSneak(oPC);
|
||||
return iSneakAttackDice;
|
||||
}
|
||||
|
||||
int GetRogueSneak(object oPC)
|
||||
{
|
||||
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
int nWeaponType = GetBaseItemType(oWeapon);
|
||||
|
||||
int iClassLevel;
|
||||
int iRogueSneak = 0;
|
||||
|
||||
// Rogue
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_ROGUE, oPC);
|
||||
// Daring Outlaw
|
||||
if (iClassLevel && GetHasFeat(FEAT_DARING_OUTLAW, oPC))
|
||||
iClassLevel += GetLevelByClass(CLASS_TYPE_SWASHBUCKLER, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Arcane Trickster (Epic)
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_ARCTRICK, oPC);
|
||||
if (iClassLevel >= 12) iRogueSneak += (iClassLevel - 10) / 2;
|
||||
|
||||
// Black Flame Zealot
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_BFZ, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 3;
|
||||
|
||||
// Nightshade
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_NIGHTSHADE, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 3;
|
||||
|
||||
// Outlaw Crimson Road
|
||||
//iClassLevel = GetLevelByClass(CLASS_TYPE_OUTLAW_CRIMSON_ROAD, oPC);
|
||||
//if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Temple Raider
|
||||
//iClassLevel = GetLevelByClass(CLASS_TYPE_TEMPLE_RAIDER, oPC);
|
||||
//if (iClassLevel>= 2) iRogueSneak += (iClassLevel + 1) / 3;
|
||||
|
||||
// Ghost-Faced Killer
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_GHOST_FACED_KILLER, oPC);
|
||||
if (iClassLevel >= 2) iRogueSneak += ((iClassLevel + 1) / 3);
|
||||
|
||||
// Ninja
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_NINJA, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Shadow Thief of Amn
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SHADOW_THIEF_AMN, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Slayer of Domiel
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SLAYER_OF_DOMIEL, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Crinti Shadow Marauder
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_CRINTI_SHADOW_MARAUDER, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 2;
|
||||
|
||||
// Cultist of the Shattered Peak
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_CULTIST_SHATTERED_PEAK, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 2;
|
||||
|
||||
// Skullclan Hunter
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SKULLCLAN_HUNTER, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 3;
|
||||
|
||||
// Shadowmind
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWMIND, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Psychic Rogue
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 2) / 3;
|
||||
|
||||
// Unseen Seer
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_UNSEEN_SEER, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 2) / 3;
|
||||
|
||||
// Fist of Dal Quor
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_FIST_DAL_QUOR, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
// Umbral Disciple
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_UMBRAL_DISCIPLE, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 3;
|
||||
|
||||
//Dragon Devotee and Hand of the Winged Masters
|
||||
int nBonusFeatDice = 0;
|
||||
int nCount;
|
||||
for(nCount = FEAT_SPECIAL_SNEAK_ATTACK_5D6; nCount >= FEAT_SPECIAL_SNEAK_ATTACK_1D6; nCount--)
|
||||
{
|
||||
if (GetHasFeat(nCount,oPC))
|
||||
{
|
||||
nBonusFeatDice = nCount - FEAT_SPECIAL_SNEAK_ATTACK_1D6 + 1;
|
||||
//if (DEBUG) DoDebug("prc_inc_sneak: Bonus Sneak Dice: " + IntToString(nBonusFeatDice));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Shadowbane Inquisitor
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWBANE_INQUISITOR, oPC);
|
||||
if (iClassLevel >= 4) iRogueSneak++;
|
||||
if (iClassLevel >= 7) iRogueSneak++;
|
||||
if (iClassLevel >= 10) iRogueSneak++;
|
||||
|
||||
// Shadowbane Stalker
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWBANE_STALKER, oPC);
|
||||
if (iClassLevel) iRogueSneak += iClassLevel / 3;
|
||||
|
||||
//Naztharune Rakshasa racial sneak attack
|
||||
if(GetHasFeat(FEAT_RACIAL_SNEAK_6D6)) iRogueSneak += 6;
|
||||
|
||||
if (GetRacialType(oPC) == RACIAL_TYPE_MARRULURK) iRogueSneak += 2;
|
||||
|
||||
if(nWeaponType == BASE_ITEM_LONGBOW || nWeaponType == BASE_ITEM_SHORTBOW)
|
||||
{
|
||||
// Peerless Archer
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_PEERLESS, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 2) / 3;
|
||||
}
|
||||
else if(nWeaponType == BASE_ITEM_SLING)
|
||||
{
|
||||
// Halfling Warslinger
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_HALFLING_WARSLINGER, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
}
|
||||
else if(nWeaponType == BASE_ITEM_WHIP)
|
||||
{
|
||||
// Lasher
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_LASHER, oPC);
|
||||
if (iClassLevel > 0) iRogueSneak += ((iClassLevel - 1) / 4) + 1;
|
||||
}
|
||||
|
||||
//Justice of Weald and Woe
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_JUSTICEWW, oPC);
|
||||
if(iClassLevel > 1) iRogueSneak++;
|
||||
if(iClassLevel > 6) iRogueSneak++;
|
||||
|
||||
//Shadowblade
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_SHADOWBLADE, oPC);
|
||||
if (iClassLevel) iRogueSneak += (iClassLevel + 1) / 2;
|
||||
|
||||
if(GetHasSpellEffect(MOVE_SH_ASSASSINS_STANCE, oPC))
|
||||
{
|
||||
iRogueSneak += 2;
|
||||
}
|
||||
|
||||
if(GetLocalInt(oPC, "SacredStrike"))
|
||||
{
|
||||
iRogueSneak += GetLocalInt(oPC, "SacredStrike");
|
||||
}
|
||||
if(GetLocalInt(oPC, "PsyRogueSneak"))
|
||||
{
|
||||
iRogueSneak += GetLocalInt(oPC, "PsyRogueSneak");
|
||||
}
|
||||
if(GetLocalInt(oPC, "CunningStrike"))
|
||||
{
|
||||
iRogueSneak += 1;
|
||||
}
|
||||
if(GetLocalInt(oPC, "UmbralSneak"))
|
||||
{
|
||||
iRogueSneak += GetLocalInt(oPC, "UmbralSneak");
|
||||
}
|
||||
if(GetLocalInt(oPC, "MalphasSneak"))
|
||||
{
|
||||
iRogueSneak += GetLocalInt(oPC, "MalphasSneak");
|
||||
}
|
||||
if(GetLocalInt(oPC, "AndroSneak"))
|
||||
{
|
||||
iRogueSneak += GetLocalInt(oPC, "AndroSneak");
|
||||
}
|
||||
if (GetLocalInt(oPC, "FactotumSneak"))
|
||||
{
|
||||
iRogueSneak += (GetLevelByClass(CLASS_TYPE_FACTOTUM, oPC) + 1) / 2;
|
||||
}
|
||||
|
||||
if(iRogueSneak > 0) //the feats only apply if you already have Sneak Attack
|
||||
iRogueSneak += nBonusFeatDice;
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Future PRC's go here. DO NOT ADD ROGUE/BLACKGUARD/ASSASSIN SNEAK ATTACKS AS CLASS FEATS.
|
||||
// Placeholder feats are fine, even encouraged. Example: "Ranged Sneak Attack +1d6".
|
||||
// The feat should do nothing, just show that you have the bonus.
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
//if (DEBUG) DoDebug("prc_inc_sneak: Rogue Sneak Dice: " + IntToString(iRogueSneak));
|
||||
return iRogueSneak;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// PLEASE DO NOT ADD ANY NEW CLASSES TO THIS FUNCTION
|
||||
// --------------------------------------------------
|
||||
int GetBlackguardSneak(object oPC)
|
||||
{
|
||||
int iClassLevel;
|
||||
int iBlackguardSneak = 0;
|
||||
|
||||
// Blackguard
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_BLACKGUARD, oPC);
|
||||
if (iClassLevel) iBlackguardSneak += (iClassLevel - 1) / 3;
|
||||
if ((iClassLevel) && (GetLevelByClass(CLASS_TYPE_PALADIN) >= 5)) iBlackguardSneak++; // bonus for pal/bg
|
||||
|
||||
// Ninja Spy
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_NINJA_SPY, oPC);
|
||||
if (iClassLevel) iBlackguardSneak += (iClassLevel + 1) / 3;
|
||||
|
||||
// Arcane Trickster (Pre-Epic)
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_ARCTRICK, oPC);
|
||||
if ((iClassLevel >= 2) && (iClassLevel < 11)) iBlackguardSneak += iClassLevel / 2;
|
||||
if (iClassLevel >= 11) iBlackguardSneak += 5;
|
||||
|
||||
// Disciple of Baalzebul
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_DISC_BAALZEBUL, oPC);
|
||||
if ((iClassLevel >= 2) && (iClassLevel < 5)) iBlackguardSneak++;
|
||||
if ((iClassLevel >= 5) && (iClassLevel < 8)) iBlackguardSneak += 2;
|
||||
if (iClassLevel >= 8) iBlackguardSneak += 3;
|
||||
|
||||
//if (DEBUG) DoDebug("prc_inc_sneak: Blackguard Sneak Dice: " + IntToString(iBlackguardSneak));
|
||||
return iBlackguardSneak;
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// PLEASE DO NOT ADD ANY NEW CLASSES TO THIS FUNCTION
|
||||
// --------------------------------------------------
|
||||
int GetAssassinSneak(object oPC)
|
||||
{
|
||||
int iClassLevel;
|
||||
int iAssassinSneakDice = 0;
|
||||
|
||||
// Assassin
|
||||
iClassLevel = GetLevelByClass(CLASS_TYPE_ASSASSIN, oPC);
|
||||
if (iClassLevel) iAssassinSneakDice += (iClassLevel + 1) / 2;
|
||||
|
||||
// Telflammar Shadowlord
|
||||
if(GetLevelByClass(CLASS_TYPE_SHADOWLORD, oPC) > 5) iAssassinSneakDice++;
|
||||
|
||||
//if (DEBUG) DoDebug("prc_inc_sneak: Assassin Sneak Dice: " + IntToString(iAssassinSneakDice));
|
||||
return iAssassinSneakDice;
|
||||
}
|
||||
|
||||
int GetEpicFeatSneak(object oPC)
|
||||
{
|
||||
int iEpicFeatDice = 0;
|
||||
int iCount;
|
||||
|
||||
// Basically searches top-down for improved sneak attack feats until it finds one.
|
||||
for(iCount = FEAT_EPIC_IMPROVED_SNEAK_ATTACK_10; iCount >= FEAT_EPIC_IMPROVED_SNEAK_ATTACK_1; iCount--)
|
||||
{
|
||||
if (GetHasFeat(iCount,oPC))
|
||||
{
|
||||
iEpicFeatDice = (iCount + 1) - FEAT_EPIC_IMPROVED_SNEAK_ATTACK_1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if (DEBUG) DoDebug("prc_inc_sneak: Epic Sneak Dice: " + IntToString(iEpicFeatDice));
|
||||
return iEpicFeatDice;
|
||||
}
|
||||
|
||||
//:://////////////////////////////////////////////
|
||||
//:: Sneak Attack Function Definitions
|
||||
//:://////////////////////////////////////////////
|
||||
|
||||
int GetIsFlanked(object oDefender, object oAttacker)
|
||||
{
|
||||
int bReturnVal = FALSE;
|
||||
//if (DEBUG) DoDebug("Starting GetIsFlanked");
|
||||
|
||||
if(GetIsObjectValid(oAttacker) && GetIsObjectValid(oDefender))
|
||||
{
|
||||
// I am assuming that if the Defender is facing away from the
|
||||
// Attacker then the Defender is flanked, as NWN "turns" an
|
||||
// attacker towards the defender
|
||||
|
||||
vector vDefender = AngleToVector(GetFacing(oDefender));
|
||||
vector vAttacker = AngleToVector(GetFacing(oAttacker));
|
||||
vector vResult = vDefender + vAttacker;
|
||||
//if (DEBUG) DoDebug("GetIsFlanked: End Section #1");
|
||||
float iMagDefender = VectorMagnitude(vDefender);
|
||||
float iMagResult = VectorMagnitude(vResult);
|
||||
|
||||
// If the magnitude of the Defenders facing vector is greater than the
|
||||
// result of the magnitude of the vector addition of the Attackers and
|
||||
// Defenders facing then the Defender is flanked.
|
||||
|
||||
if(iMagDefender < iMagResult)
|
||||
{
|
||||
bReturnVal = TRUE;
|
||||
}
|
||||
}
|
||||
//if (DEBUG) DoDebug("GetIsFlanked: End Section #2");
|
||||
return bReturnVal;
|
||||
}
|
||||
|
||||
// Checks if an AoE spell is against someone distracted in meleee combat
|
||||
int GetIsAOEFlanked(object oDefender, object oAttacker)
|
||||
{
|
||||
int bReturnVal = TRUE;
|
||||
|
||||
// if they are not in combat then they are automatically flanked (surprise round)
|
||||
if(!PRCGetIsFighting(oDefender) || !GetIsInCombat(oDefender) )
|
||||
{
|
||||
// checks if they are attacking something other than the caster
|
||||
object oTarget = GetAttackTarget(oDefender);
|
||||
if(oTarget == oAttacker) bReturnVal = FALSE;
|
||||
}
|
||||
|
||||
return bReturnVal;
|
||||
}
|
||||
|
||||
int GetIsHelpless(object oDefender)
|
||||
{
|
||||
// Does not apply when grappled
|
||||
if (GetLocalInt(oDefender, "IsGrappled") && !GetLocalInt(oDefender, "UnconsciousGrapple")) return FALSE;
|
||||
|
||||
// PnP describes a helpless defender as
|
||||
// A helpless foe - one who is bound, held, sleeping, paralyzed,
|
||||
// unconscious, or otherwise at your mercy - is an easy target.
|
||||
return ( PRCGetHasEffect(EFFECT_TYPE_PARALYZE, oDefender)
|
||||
|| PRCGetHasEffect(EFFECT_TYPE_SLEEP, oDefender)
|
||||
|| PRCGetHasEffect(EFFECT_TYPE_PETRIFY, oDefender)
|
||||
|| PRCGetHasEffect(EFFECT_TYPE_CUTSCENE_PARALYZE, oDefender) );
|
||||
}
|
||||
|
||||
int GetIsDeniedDexBonusToAC(object oDefender, object oAttacker, int nIgnoreUD = FALSE)
|
||||
{
|
||||
int bIsDeniedDex = FALSE;
|
||||
int bDefenderHasTrueSight = PRCGetHasEffect(EFFECT_TYPE_TRUESEEING, oDefender);
|
||||
int bDefenderCanSeeInvisble = PRCGetHasEffect(EFFECT_TYPE_SEEINVISIBLE, oDefender);
|
||||
int bDefenderIsKnockedDown = GetHasFeatEffect(FEAT_KNOCKDOWN, oDefender) || GetHasFeatEffect(FEAT_IMPROVED_KNOCKDOWN, oDefender);
|
||||
|
||||
// if the player is helpess, they are automatically denied dex bonus.
|
||||
if( GetIsHelpless(oDefender) ) return TRUE;
|
||||
|
||||
// Forces it
|
||||
if (GetLocalInt(oAttacker, "PRC_SB_UNEXPECTED")) return TRUE;
|
||||
|
||||
// if the player is not fighting, then this is the "surprise round"
|
||||
if( !PRCGetIsFighting(oDefender) || !GetIsInCombat(oDefender) )
|
||||
{
|
||||
bIsDeniedDex = TRUE;
|
||||
}
|
||||
|
||||
// In NwN, knocked down targets are counted as denied dex bonus to AC.
|
||||
if( bDefenderIsKnockedDown ) bIsDeniedDex = TRUE;
|
||||
|
||||
// if defender has spell effect on them causing them to be denied dex bonus to AC.
|
||||
if( PRCGetHasEffect(EFFECT_TYPE_BLINDNESS, oDefender) ) bIsDeniedDex = TRUE;
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_ENTANGLE, oDefender) ) bIsDeniedDex = TRUE;
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_FRIGHTENED, oDefender) ) bIsDeniedDex = TRUE;
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_STUNNED, oDefender) ) bIsDeniedDex = TRUE;
|
||||
|
||||
// Note: This is wrong by PnP rules... but Bioware allows auto sneaks on Dazed targets.
|
||||
// to keep in tune with the game engine I'll leave this active.
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_DAZED, oDefender) ) bIsDeniedDex = TRUE;
|
||||
|
||||
// if attacker is invisvisible/hiding/etc.
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_INVISIBILITY, oAttacker) && !bDefenderHasTrueSight && !bDefenderCanSeeInvisble )
|
||||
{
|
||||
bIsDeniedDex = TRUE;
|
||||
}
|
||||
else if( PRCGetHasEffect(EFFECT_TYPE_IMPROVEDINVISIBILITY, oAttacker) && !bDefenderHasTrueSight && !bDefenderCanSeeInvisble )
|
||||
{
|
||||
bIsDeniedDex = TRUE;
|
||||
}
|
||||
else if( !GetObjectSeen(oAttacker, oDefender) )
|
||||
{
|
||||
bIsDeniedDex = TRUE;
|
||||
}
|
||||
|
||||
// Check for Uncanny Dodge Vs. Sneak Attack.
|
||||
if( GetHasFeat(FEAT_UNCANNY_DODGE_2, oDefender) && !nIgnoreUD )
|
||||
{
|
||||
if(GetLevelByClass(CLASS_TYPE_DWARVENDEFENDER, oDefender))
|
||||
return FALSE;
|
||||
|
||||
// +4 because a rogue has to be 4 levels higher to flank
|
||||
int iUncannyDodgeLevels = GetLevelByClass(CLASS_TYPE_ASSASSIN , oDefender)
|
||||
+ GetLevelByClass(CLASS_TYPE_BARBARIAN , oDefender)
|
||||
+ GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE , oDefender)
|
||||
+ GetLevelByClass(CLASS_TYPE_ROGUE , oDefender)
|
||||
+ GetLevelByClass(CLASS_TYPE_SHADOWDANCER, oDefender)
|
||||
+ 4;
|
||||
|
||||
int iSneakAttackLevels = GetLevelByClass(CLASS_TYPE_BOWMAN , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_NINJA , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_PSYCHIC_ROGUE , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_ROGUE , oAttacker)
|
||||
|
||||
// add other sneak attacking PrC's here
|
||||
+ GetLevelByClass(CLASS_TYPE_ARCTRICK , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_ASSASSIN , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_BFZ , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_BLACKGUARD , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_BLARCHER , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_DISC_BAALZEBUL , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_FIST_DAL_QUOR , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_GHOST_FACED_KILLER , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_HALFLING_WARSLINGER, oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_JUSTICEWW , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_LASHER , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_NIGHTSHADE , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_NINJA_SPY , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_PEERLESS , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_SHADOWBLADE , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_SHADOWLORD , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_SHADOWMIND , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_SKULLCLAN_HUNTER , oAttacker)
|
||||
+ GetLevelByClass(CLASS_TYPE_SLAYER_OF_DOMIEL , oAttacker);
|
||||
|
||||
if(iUncannyDodgeLevels > iSneakAttackLevels)
|
||||
{
|
||||
bIsDeniedDex = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return bIsDeniedDex;
|
||||
}
|
||||
|
||||
int GetIsConcealed(object oDefender, object oAttacker)
|
||||
{
|
||||
int bIsConcealed = FALSE;
|
||||
|
||||
int bAttackerHasTrueSight = PRCGetHasEffect(EFFECT_TYPE_TRUESEEING, oAttacker);
|
||||
int bAttackerCanSeeInvisble = PRCGetHasEffect(EFFECT_TYPE_SEEINVISIBLE, oAttacker);
|
||||
int bAttackerUltraVision = PRCGetHasEffect(EFFECT_TYPE_ULTRAVISION, oAttacker);
|
||||
|
||||
if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_50, oDefender) ) bIsConcealed = 50;
|
||||
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_40, oDefender) ) bIsConcealed = 40;
|
||||
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_30, oDefender) ) bIsConcealed = 30;
|
||||
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_20, oDefender) ) bIsConcealed = 20;
|
||||
else if(GetHasFeat(FEAT_EPIC_SELF_CONCEALMENT_10, oDefender) ) bIsConcealed = 10;
|
||||
|
||||
// darkness, invisible, imp invisible
|
||||
else if(GetStealthMode(oDefender) == STEALTH_MODE_ACTIVATED && !GetObjectSeen(oDefender, oAttacker) ) bIsConcealed = TRUE;
|
||||
else if(PRCGetHasEffect(EFFECT_TYPE_SANCTUARY, oDefender) && !bAttackerHasTrueSight )
|
||||
{
|
||||
// if they player is hidden you know enough to try attacking, give 50% miss chance
|
||||
// as that is the highest concealment normally allowed.
|
||||
// couldn't find any rules that governed this though.
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
else if(PRCGetHasEffect(EFFECT_TYPE_INVISIBILITY, oDefender) && !bAttackerHasTrueSight && !bAttackerCanSeeInvisble )
|
||||
{
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
else if(PRCGetHasEffect(EFFECT_TYPE_IMPROVEDINVISIBILITY, oDefender) && !bAttackerHasTrueSight && !bAttackerCanSeeInvisble )
|
||||
{
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
else if(PRCGetHasEffect(EFFECT_TYPE_DARKNESS, oDefender) && !bAttackerHasTrueSight && !bAttackerUltraVision)
|
||||
{
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
else if(GetHasFeatEffect(FEAT_EMPTY_BODY, oDefender) )
|
||||
{
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
//else if(PRCGetHasEffect(EFFECT_TYPE_ETHEREAL, oDefender) && !bAttackerHasTrueSight && !bAttackerCanSeeInvisble )
|
||||
//{
|
||||
// bIsConcealed = TRUE;
|
||||
//}
|
||||
|
||||
// spell effects
|
||||
else if(GetHasSpellEffect(1764 , oDefender) && !bAttackerHasTrueSight) // blur spell
|
||||
{
|
||||
bIsConcealed = 20;
|
||||
}
|
||||
else if(GetHasSpellEffect(SPELL_DISPLACEMENT , oDefender) && !bAttackerHasTrueSight)
|
||||
{
|
||||
bIsConcealed = 50;
|
||||
}
|
||||
else if(GetHasSpellEffect(SPELL_SHADOW_EVADE , oDefender) && !bAttackerHasTrueSight)
|
||||
{
|
||||
int iSDlevel = GetLevelByClass(CLASS_TYPE_SHADOWDANCER, oDefender);
|
||||
if(iSDlevel <= 4) bIsConcealed = 5;
|
||||
if(iSDlevel <= 6) bIsConcealed = 10;
|
||||
if(iSDlevel <= 8) bIsConcealed = 15;
|
||||
if(iSDlevel <= 10) bIsConcealed = 20;
|
||||
}
|
||||
|
||||
// this is the catch-all effect
|
||||
else if(PRCGetHasEffect(EFFECT_TYPE_CONCEALMENT, oDefender) && !bAttackerHasTrueSight)
|
||||
{
|
||||
if(bIsConcealed == FALSE) bIsConcealed = TRUE;
|
||||
}
|
||||
|
||||
if(GetLocalInt(oAttacker, "PRC_SB_UNERRING"))
|
||||
{
|
||||
bIsConcealed = FALSE;
|
||||
return bIsConcealed;
|
||||
}
|
||||
return bIsConcealed;
|
||||
}
|
||||
|
||||
int GetCanSneakAttack(object oDefender, object oAttacker)
|
||||
{
|
||||
//cant sneak non-creatures
|
||||
if(GetObjectType(oDefender) != OBJECT_TYPE_CREATURE)
|
||||
return FALSE;
|
||||
|
||||
// Can't sneak attack if you're in a grapple
|
||||
if(GetLocalInt(oAttacker, "IsGrappled"))
|
||||
return FALSE;
|
||||
|
||||
int bReturnVal = FALSE;
|
||||
int bIsInRange = FALSE;
|
||||
int bIsFlanked = GetIsFlanked(oDefender, oAttacker);
|
||||
int bIsDeniedDex = GetIsDeniedDexBonusToAC(oDefender, oAttacker);
|
||||
|
||||
float fDistance = GetDistanceBetween(oAttacker, oDefender);
|
||||
if(fDistance <= FeetToMeters(30.0f) ) bIsInRange = TRUE;
|
||||
|
||||
// Is only run if enemy is indeed flanked or denied dex bonus to AC
|
||||
// otherwise there is no reason to check further
|
||||
if(bIsFlanked || bIsDeniedDex && bIsInRange)
|
||||
{
|
||||
// so far they can be sneaked
|
||||
bReturnVal = TRUE;
|
||||
|
||||
// checking for other factors that remove sneak attack
|
||||
if( GetIsImmune(oDefender, IMMUNITY_TYPE_CRITICAL_HIT, OBJECT_INVALID) ) bReturnVal = FALSE;
|
||||
if( GetIsImmune(oDefender, IMMUNITY_TYPE_SNEAK_ATTACK, OBJECT_INVALID) ) bReturnVal = FALSE;
|
||||
// Skullclan Hunters can sneak attack undead, so they return true here.
|
||||
if( GetLevelByClass(CLASS_TYPE_SKULLCLAN_HUNTER, oAttacker) && GetRacialType(oDefender) == RACIAL_TYPE_UNDEAD) bReturnVal = TRUE;
|
||||
|
||||
if( GetIsConcealed(oDefender, oAttacker) )
|
||||
bReturnVal = FALSE;
|
||||
}
|
||||
|
||||
return bReturnVal;
|
||||
}
|
||||
|
||||
int GetSneakAttackDamage(int iSneakAttackDice)
|
||||
{
|
||||
int iSneakAttackDamage = d6(iSneakAttackDice);
|
||||
return iSneakAttackDamage;
|
||||
}
|
||||
|
||||
int GetDragonfireDamageType(object oPC)
|
||||
{
|
||||
//Elemental Immunities for various dragon types.
|
||||
int iType = GetHasFeat(FEAT_BLACK_DRAGON, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_BROWN_DRAGON, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_COPPER_DRAGON, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_GREEN_DRAGON, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_BRASS_DRAGON, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_GOLD_DRAGON, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_RED_DRAGON, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_LUNG_WANG_DRAGON, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_BATTLE_DRAGON, oPC) ? DAMAGE_TYPE_SONIC :
|
||||
GetHasFeat(FEAT_EMERALD_DRAGON, oPC) ? DAMAGE_TYPE_SONIC :
|
||||
GetHasFeat(FEAT_HOWLING_DRAGON, oPC) ? DAMAGE_TYPE_SONIC :
|
||||
GetHasFeat(FEAT_BLUE_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_BRONZE_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_OCEANUS_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_SAPPHIRE_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_SONG_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_SHEN_LUNG_DRAGON, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_CRYSTAL_DRAGON, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_TOPAZ_DRAGON, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_SILVER_DRAGON, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_WHITE_DRAGON, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_BK, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_CP, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_GR, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_BS, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_GD, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_RD, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_EM, oPC) ? DAMAGE_TYPE_SONIC :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_BL, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_BZ, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_SA, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_CR, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_TP, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_SR, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_DRACONIC_HERITAGE_WH, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_BK, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_CP, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_GR, oPC) ? DAMAGE_TYPE_ACID :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_BS, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_GD, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_RD, oPC) ? DAMAGE_TYPE_FIRE :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_EM, oPC) ? DAMAGE_TYPE_SONIC :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_BL, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_BZ, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_SA, oPC) ? DAMAGE_TYPE_ELECTRICAL :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_CR, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_TP, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_SR, oPC) ? DAMAGE_TYPE_COLD :
|
||||
GetHasFeat(FEAT_KOB_DRAGONWROUGHT_WH, oPC) ? DAMAGE_TYPE_COLD :
|
||||
DAMAGE_TYPE_FIRE; // If none match, make the itemproperty invalid
|
||||
|
||||
return iType;
|
||||
}
|
||||
|
||||
int GetFavouredEnemyBonus(object oPC)
|
||||
{
|
||||
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oPC);
|
||||
int nWeaponType = GetBaseItemType(oWeapon);
|
||||
|
||||
int nClass;
|
||||
int nFE = 0;
|
||||
|
||||
// Ranger
|
||||
nClass = GetLevelByClass(CLASS_TYPE_RANGER, oPC);
|
||||
if (nClass) nFE += nClass/5 + 1;
|
||||
|
||||
if (DEBUG) DoDebug("prc_inc_sneak: Favoured Enemy Bonus: " + IntToString(nFE));
|
||||
return nFE;
|
||||
}
|
Reference in New Issue
Block a user