Updated Release Archive. Fixed Mage-killer prereqs. Removed old LETO & ConvoCC related files. Added organized spell scroll store. Fixed Gloura spellbook. Various TLK fixes. Reorganized Repo. Removed invalid user folders. Added DocGen back in.
165 lines
7.0 KiB
Plaintext
165 lines
7.0 KiB
Plaintext
int PRCDoRangedTouchAttack(object oTarget, int nDisplayFeedback = TRUE, object oCaster = OBJECT_SELF, int nAttackBonus = 0);
|
|
int PRCDoMeleeTouchAttack(object oTarget, int nDisplayFeedback = TRUE, object oCaster = OBJECT_SELF, int nAttackBonus = 0);
|
|
|
|
//#include "prc_inc_sneak"
|
|
#include "prc_inc_combat"
|
|
//#include "prc_inc_template"
|
|
|
|
int PRCDoRangedTouchAttack(object oTarget, int nDisplayFeedback = TRUE, object oCaster = OBJECT_SELF, int nAttackBonus = 0)
|
|
{
|
|
if(GetLocalInt(oTarget, "Dymond_Deflect"))
|
|
{
|
|
DeleteLocalInt(oTarget, "Dymond_Deflect");
|
|
return FALSE;
|
|
}
|
|
if(GetLocalInt(oCaster, "AttackHasHit"))
|
|
return GetLocalInt(oCaster, "AttackHasHit");
|
|
string sCacheName = "AttackHasHit_"+ObjectToString(oTarget);
|
|
if(GetLocalInt(oCaster, sCacheName))
|
|
return GetLocalInt(oCaster, sCacheName);
|
|
if(GetPersistantLocalInt(oCaster, "template_102")) // TEMPLATE_DEMILICH
|
|
nAttackBonus += GetHitDice(oCaster);
|
|
|
|
if(GetHasFeat(FEAT_SHIELD_WARD, oTarget))
|
|
{
|
|
int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD)
|
|
nAttackBonus -= GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
}
|
|
else if(GetHasFeat(FEAT_PARRYING_SHIELD, oTarget)) // Yes, these two are mostly identical
|
|
{
|
|
int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD)
|
|
nAttackBonus -= GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
}
|
|
|
|
int nResult = GetAttackRoll(oTarget,oCaster,OBJECT_INVALID,0,nAttackBonus,0,nDisplayFeedback,0.0,TOUCH_ATTACK_RANGED_SPELL);
|
|
//Ranged Recall only applies on misses, need a swift action
|
|
if (GetHasFeat(FEAT_RANGED_RECALL, oCaster) && nResult == 0)
|
|
{
|
|
int nRecall = GetLocalInt(oCaster, "RangedRecall");
|
|
// Only get three uses a day
|
|
if (3 > nRecall)
|
|
{
|
|
if (TakeSwiftAction(oCaster))
|
|
{
|
|
SetLocalInt(oCaster, "RangedRecall", nRecall+1);
|
|
// Reroll with a -5 penalty
|
|
nResult = GetAttackRoll(oTarget,oCaster,OBJECT_INVALID,0,nAttackBonus-5,0,nDisplayFeedback,0.0,TOUCH_ATTACK_MELEE_SPELL);
|
|
}
|
|
}
|
|
}
|
|
SetLocalInt(oCaster, sCacheName, nResult);
|
|
DelayCommand(1.0, DeleteLocalInt(oCaster, sCacheName));
|
|
return nResult;
|
|
}
|
|
|
|
int PRCDoMeleeTouchAttack(object oTarget, int nDisplayFeedback = TRUE, object oCaster = OBJECT_SELF, int nAttackBonus = 0)
|
|
{
|
|
if(GetLocalInt(oCaster, "AttackHasHit"))
|
|
return GetLocalInt(oCaster, "AttackHasHit");
|
|
string sCacheName = "AttackHasHit_"+ObjectToString(oTarget);
|
|
if(GetLocalInt(oCaster, sCacheName))
|
|
return GetLocalInt(oCaster, sCacheName);
|
|
if(GetPersistantLocalInt(oCaster, "template_102")) // TEMPLATE_DEMILICH
|
|
nAttackBonus += GetHitDice(oCaster);
|
|
if(GetHasFeat(FEAT_SHIELD_WARD, oTarget))
|
|
{
|
|
int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD)
|
|
nAttackBonus -= GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
}
|
|
else if(GetHasFeat(FEAT_PARRYING_SHIELD, oTarget)) // Yes, these two are mostly identical
|
|
{
|
|
int nBase = GetBaseItemType(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
if (nBase == BASE_ITEM_SMALLSHIELD || nBase == BASE_ITEM_LARGESHIELD || nBase == BASE_ITEM_TOWERSHIELD)
|
|
nAttackBonus -= GetItemACValue(GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget));
|
|
}
|
|
int nResult = GetAttackRoll(oTarget,oCaster,OBJECT_INVALID,0,nAttackBonus,0,nDisplayFeedback,0.0,TOUCH_ATTACK_MELEE_SPELL);
|
|
SetLocalInt(oCaster, sCacheName, nResult);
|
|
DelayCommand(1.0, DeleteLocalInt(oCaster, sCacheName));
|
|
return nResult;
|
|
}
|
|
|
|
// return sneak attack damage for a spell
|
|
// requires caster, target, and spell damage type
|
|
int SpellSneakAttackDamage(object oCaster, object oTarget)
|
|
{
|
|
if (GetLocalInt(oCaster, "NoSpellSneak"))
|
|
return 0;
|
|
|
|
int numDice = GetTotalSneakAttackDice(oCaster);
|
|
|
|
if(numDice != 0 && GetCanSneakAttack(oTarget, oCaster) )
|
|
{
|
|
FloatingTextStringOnCreature("*Sneak Attack Spell*", oCaster, TRUE);
|
|
return GetSneakAttackDamage(numDice);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//Applies damage from touch attacks,
|
|
// returns result of attack roll
|
|
//
|
|
// object oCaster, the attacker
|
|
// object oTarget, the victim
|
|
// int iAttackRoll, the result of a touch
|
|
// attack roll, 1 for hit, 2 for
|
|
// critical hit
|
|
// int iDamage, the normal amount of damage done
|
|
// int iDamageType, the damage type
|
|
// int iDamageType2, the 2nd damage type
|
|
// if 2 types of damage are applied
|
|
int ApplyTouchAttackDamage(object oCaster, object oTarget, int iAttackRoll, int iDamage, int iDamageType, int iDamageType2 = -1)
|
|
{
|
|
iDamage *= iAttackRoll;
|
|
if(iDamage)
|
|
{
|
|
if(!GetPRCSwitch(PRC_SPELL_SNEAK_DISABLE))
|
|
iDamage += SpellSneakAttackDamage(oCaster, oTarget);
|
|
|
|
effect eDamage;
|
|
if(iDamageType2 == -1)
|
|
eDamage = PRCEffectDamage(oTarget, iDamage, iDamageType);
|
|
else
|
|
{ //for touch attacks with 2 damage types, 1st damage type has priority
|
|
eDamage = PRCEffectDamage(oTarget, iDamage / 2, iDamageType);
|
|
eDamage = EffectLinkEffects(eDamage, EffectDamage(iDamage - (iDamage / 2), iDamageType2));
|
|
}
|
|
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
|
|
}
|
|
|
|
return iAttackRoll;
|
|
}
|
|
|
|
//routes to DoRacialSLA, but checks that the ray hits first
|
|
//not sure how this will work if the spell does multiple touch attack, hopefully that shouldnt apply
|
|
//this is Base DC, not total DC. SLAs are still spells, so spell focus should still apply.
|
|
void DoSpellRay(int nSpellID, int nCasterlevel = 0, int nTotalDC = 0)
|
|
{
|
|
int nAttack = PRCDoRangedTouchAttack(PRCGetSpellTargetObject());
|
|
if(nAttack)
|
|
{
|
|
ActionDoCommand(SetLocalInt(OBJECT_SELF, "AttackHasHit", nAttack)); //preserve crits
|
|
if(DEBUG) DoDebug("Spell DC passed to DoSpellRay: " + IntToString(nTotalDC));
|
|
DoRacialSLA(nSpellID, nCasterlevel, nTotalDC, TRUE);
|
|
ActionDoCommand(DeleteLocalInt(OBJECT_SELF, "AttackHasHit"));
|
|
}
|
|
}
|
|
|
|
//routes to DoRacialSLA, but checks that the rouch hits first
|
|
//not sure how this will work if the spell does multiple touch attack, hopefully that shouldnt apply
|
|
//this is Base DC, not total DC. SLAs are still spells, so spell focus should still apply.
|
|
void DoSpellMeleeTouch(int nSpellID, int nCasterlevel = 0, int nTotalDC = 0)
|
|
{
|
|
int nAttack = PRCDoMeleeTouchAttack(PRCGetSpellTargetObject());
|
|
if(nAttack)
|
|
{
|
|
ActionDoCommand(SetLocalInt(OBJECT_SELF, "AttackHasHit", nAttack)); //preserve crits
|
|
DoRacialSLA(nSpellID, nCasterlevel, nTotalDC);
|
|
ActionDoCommand(DeleteLocalInt(OBJECT_SELF, "AttackHasHit"));
|
|
}
|
|
} |