2025/05/11 Update
Added confirmation to Cohort creation conversation. Fixed Hound Archon's Aura of Menace. Added Swarm of Arrows epic feat. Fixed HiPS on Brownie & Naz Rakshasa. Fixed 2DA Name error for Epic Weapon Focus: Maul. Clarified human only feats in TLK. Added new web enhancement Adventure Locale.
This commit is contained in:
104
nwn/nwnprc/trunk/scripts/prc_swarm_arrows.nss
Normal file
104
nwn/nwnprc/trunk/scripts/prc_swarm_arrows.nss
Normal file
@@ -0,0 +1,104 @@
|
||||
//:://////////////////////////////////////////////////////////////////
|
||||
//::
|
||||
//:: prc_swarm_arrows.nss
|
||||
//::
|
||||
//:://////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
Swarm Of Arrows [Epic]
|
||||
|
||||
Prerequisites
|
||||
Dex 23, Point Blank Shot, Rapid Shot, Weapon Focus (type of bow used).
|
||||
|
||||
Benefit
|
||||
As a full-round action, you may fire an arrow at your full base attack bonus at each opponent within 30 feet.
|
||||
*/
|
||||
#include "prc_x2_itemprop"
|
||||
#include "prc_inc_util"
|
||||
#include "prc_inc_combat"
|
||||
|
||||
// Swarm of Arrows implementation
|
||||
void EpicSwarmOfArrows(object oAttacker)
|
||||
{
|
||||
// Get right-hand weapon and ensure it's a bow
|
||||
object oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oAttacker);
|
||||
int nWeaponType = GetBaseItemType(oWeapon);
|
||||
|
||||
if (IPGetIsMeleeWeapon(oWeapon) || (nWeaponType != BASE_ITEM_LONGBOW && nWeaponType != BASE_ITEM_SHORTBOW))
|
||||
{
|
||||
SendMessageToPC(oAttacker, "You must be wielding a longbow or shortbow to use Swarm of Arrows.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get equipped ammo from the ammo slot
|
||||
object oAmmo = GetItemInSlot(INVENTORY_SLOT_ARROWS, oAttacker);
|
||||
int nStack = GetItemStackSize(oAmmo);
|
||||
|
||||
if (!GetIsObjectValid(oAmmo) || nStack <= 0)
|
||||
{
|
||||
SendMessageToPC(oAttacker, "You are out of arrows!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get location and orientation
|
||||
location lAttacker = GetLocation(oAttacker);
|
||||
float fRadius = FeetToMeters(30.0);
|
||||
|
||||
object oTarget = MyFirstObjectInShape(SHAPE_SPHERE, fRadius, lAttacker, TRUE, OBJECT_TYPE_CREATURE);
|
||||
while (GetIsObjectValid(oTarget))
|
||||
{
|
||||
if (oTarget != oAttacker && GetIsEnemy(oTarget, oAttacker))
|
||||
{
|
||||
// Must be in range, LOS, and seen by attacker
|
||||
if (GetDistanceBetween(oAttacker, oTarget) <= fRadius
|
||||
&& LineOfSightObject(oAttacker, oTarget)
|
||||
&& GetObjectSeen(oTarget, oAttacker))
|
||||
{
|
||||
// Check stack size again in case arrows are running low
|
||||
if (nStack <= 0)
|
||||
{
|
||||
SendMessageToPC(oAttacker, "You are out of arrows!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Consume one arrow
|
||||
if (nStack > 1)
|
||||
{
|
||||
SetItemStackSize(oAmmo, nStack - 1);
|
||||
nStack = nStack - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DestroyObject(oAmmo);
|
||||
nStack = 0;
|
||||
}
|
||||
|
||||
// Perform a single attack using full base attack bonus
|
||||
int iBAB = GetBaseAttackBonus(oAttacker);
|
||||
PerformAttack(
|
||||
oTarget,
|
||||
oAttacker,
|
||||
EffectVisualEffect(VFX_IMP_PDK_GENERIC_HEAD_HIT),
|
||||
0.0,
|
||||
iBAB,
|
||||
0,
|
||||
DAMAGE_TYPE_PIERCING,
|
||||
"*Swarm of Arrows Hit!*",
|
||||
"*Swarm of Arrows Miss*");
|
||||
}
|
||||
}
|
||||
oTarget = MyNextObjectInShape(SHAPE_SPHERE, fRadius, lAttacker, TRUE, OBJECT_TYPE_CREATURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
object oUser = OBJECT_SELF;
|
||||
if (!GetHasFeat(FEAT_EPIC_SWARM_OF_ARROWS, oUser))
|
||||
{
|
||||
SendMessageToPC(oUser, "You do not have the Swarm of Arrows feat.");
|
||||
return;
|
||||
}
|
||||
|
||||
EpicSwarmOfArrows(oUser);
|
||||
}
|
@@ -78,6 +78,10 @@ const int STAGE_SPELL_SHOPS_ALPHABETICAL_FILTER = 49;
|
||||
const int STAGE_PLANTSHAPE_SLOTS = 50;
|
||||
const int STAGE_PLANTSHAPE_SHAPE = 51;
|
||||
|
||||
// Confirmation stage for registering cohort
|
||||
const int STAGE_REGISTER_CONFIRM = 200;
|
||||
|
||||
|
||||
const int STAGE_CDKEY_ADD = 509;
|
||||
const int STAGE_APPEARANCE = 510;
|
||||
const int STAGE_HEAD = 520;
|
||||
@@ -713,7 +717,15 @@ void main()
|
||||
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_LEADERSHIP_ADD_STANDARD)
|
||||
else if(nStage == STAGE_REGISTER_CONFIRM)
|
||||
{
|
||||
SetHeader("Are you sure you want to register this character as a cohort?");
|
||||
AddChoice("Yes", 1);
|
||||
AddChoice("No", CHOICE_RETURN_TO_PREVIOUS);
|
||||
MarkStageSetUp(nStage, oPC);
|
||||
SetDefaultTokens();
|
||||
}
|
||||
else if(nStage == STAGE_LEADERSHIP_ADD_STANDARD)
|
||||
{
|
||||
SetHeader("Select a cohort:");
|
||||
|
||||
@@ -1344,11 +1356,17 @@ void main()
|
||||
}
|
||||
else if(nChoice == 5)
|
||||
nStage = STAGE_TEFLAMMAR_SHADOWLORD;
|
||||
else if(nChoice == 6)
|
||||
else if(nChoice == 6)
|
||||
{
|
||||
// Redirect to confirmation stage
|
||||
nStage = STAGE_REGISTER_CONFIRM;
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
/* else if(nChoice == 6)
|
||||
{
|
||||
RegisterAsCohort(oPC);
|
||||
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
|
||||
}
|
||||
} */
|
||||
else if(nChoice == 7)
|
||||
nStage = STAGE_LEADERSHIP;
|
||||
else if(nChoice == 8)
|
||||
@@ -1375,7 +1393,20 @@ void main()
|
||||
if(nStage != STAGE_ENTRY)
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SWITCHES)
|
||||
else if(nStage == STAGE_REGISTER_CONFIRM)
|
||||
{
|
||||
if(nChoice == 1) // Yes
|
||||
{
|
||||
RegisterAsCohort(oPC);
|
||||
AllowExit(DYNCONV_EXIT_FORCE_EXIT);
|
||||
}
|
||||
else if(nChoice == CHOICE_RETURN_TO_PREVIOUS) // No
|
||||
{
|
||||
nStage = STAGE_ENTRY;
|
||||
}
|
||||
MarkStageNotSetUp(nStage, oPC);
|
||||
}
|
||||
else if(nStage == STAGE_SWITCHES)
|
||||
{
|
||||
if(nChoice == CHOICE_RETURN_TO_PREVIOUS)
|
||||
nStage = STAGE_ENTRY;
|
||||
@@ -2064,4 +2095,4 @@ void main()
|
||||
// Store the stage value. If it has been changed, this clears out the choices
|
||||
SetStage(nStage, oPC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user