This has been much requested on our server. Imbue and death arrow have been much improved, and even though hail and seeker have been modified these latter two are still seriously lacking.
The problem from my view point for hail and seeker is that it doesn’t actually uses the equipped arrows, nor does it apply our mod’s post 40 mele dmg (for the most part anyways, it does apply one component of it however not the majority which is applied as a supernatural effect to the toon itself), and because of this it is seriously underpowered at higher levels.
Here are our Hail and Seeker scripts, and the include associated to them. I would be very interested in any ideas to get them to actually use the equipped arrows (and subsequently our standard post 40 mele dmg hopefully), and not just do low lvl dmg based off the dmg types of the equipped arrows as a spell effect as it appears to be now.
Any ideas would be welcomed.
The Include:
#include "x0_i0_spells"
#include "core_inc_post40"
//This include file contains funstions for the improved hail of arrows and seeking arrow scripts
// Written by Twainer for the Aventia persistant world 20/10/2005
// This Function Retrieves the values stored in StoreArrowDamage and returns
// an effect with all the calculated damage in it.
// If nCrit is 1 the damage is tripled
effect GetArcaneArrowDamage(object oUser, object oTarget, int nCrit = 0);
// This examines the arrows in oUsers arrow slot and determines and damge modifiers
// or damage vs alignment group modifers that those arrows has.
// Values are then stored on the arrows for later use.
void StoreArrowDamage(object oUser);
effect GetArcaneArrowDamage(object oUser, object oTarget, int nCrit = 0)
{
object oArrows = GetItemInSlot(INVENTORY_SLOT_ARROWS, oUser);
object oBow = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oUser);
int nBonus = ArcaneArcherCalculateBonus();
int dieSize, dieCount, damtype, nDamage, i,j, nPierce, align;
effect eTemp, eTotal;
string sDam;
if (GetIsObjectValid(oBow) == TRUE){
if (GetBaseItemType(oBow) == BASE_ITEM_LONGBOW ){
nPierce = d8();
if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_LONGBOW, oUser))
nPierce += 2;
if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_LONGBOW, oUser))
nPierce += 4;
}else if (GetBaseItemType(oBow) == BASE_ITEM_SHORTBOW){
nPierce = d6();
if (GetHasFeat(FEAT_WEAPON_SPECIALIZATION_SHORTBOW, oUser))
nPierce += 2;
if (GetHasFeat(FEAT_EPIC_WEAPON_SPECIALIZATION_SHORTBOW, oUser))
nPierce += 4;
}
else
return eTemp;
}
else
return eTemp;
// add strength bonus if bow has mighty (im lazy so i wont cap it properly)
if (GetItemHasItemProperty(oBow, ITEM_PROPERTY_MIGHTY))
nPierce += GetAbilityModifier(ABILITY_STRENGTH,oUser);
//add AA damage bonus
nPierce += nBonus;
//add post 40 melee damage
int nXP = GetXP( oUser );
int nLevel = pf_GetLevelFromXP( nXP );
int nP40Bonus;
if ( nLevel > 39 )
{
nP40Bonus = ( nLevel - 40 ) / 2;
float fMeleeFactor = calcMeleeFactor( oUser );
if ( GetIsObjectValid( GetItemPossessedBy( oUser, "GrtrMeleeRunV2" )))
{
fMeleeFactor *= 1.5;
}
else if ( GetIsObjectValid( GetItemPossessedBy( oUser, "LesrMeleeRunV2" )))
{
fMeleeFactor *= 1.25;
}
nP40Bonus = FloatToInt( IntToFloat( nP40Bonus ) * fMeleeFactor );
}
nPierce += nP40Bonus;
// Check Arrows Now
int pcount = GetLocalInt(oArrows, "scy_AA_prop_count");
if (pcount == 255)
pcount = 0;
for (j = 1; j <= pcount; j++){
damtype = GetLocalInt(oArrows, "scy_AA_prop" + IntToString(j) + "_damtype");
dieSize = GetLocalInt(oArrows, "scy_AA_prop" + IntToString(j) + "_diesize");
dieCount = GetLocalInt(oArrows, "scy_AA_prop" + IntToString(j) + "_diecount");
align = GetLocalInt(oArrows, "scy_AA_prop" + IntToString(j) + "_align");
if (align == 0 || align == GetAlignmentGoodEvil(oTarget) || align == GetAlignmentLawChaos(oTarget)){
// non-random case
if(dieCount == 0)
nDamage = dieSize;
else{
nDamage = 0;
for(i = 1; i <= dieCount; i++)
nDamage += 1+ Random(dieSize);
}
//SendMessageToPC(oUser, IntToString(idamage) + " " + sDam + " " + Get2DAString("iprp_damagetype", "Label", damtype) + " damage");
// If its piercing, add it to the bow damage
//Happy Edit - also add the slash / bludge
if(damtype == DAMAGE_TYPE_PIERCING || damtype == DAMAGE_TYPE_BLUDGEONING || damtype == DAMAGE_TYPE_SLASHING)
nPierce += nDamage;
else{
eTemp = EffectDamage(nDamage*(nCrit*2 + 1), damtype, IPGetDamagePowerConstantFromNumber(nBonus));
eTotal = EffectLinkEffects(eTotal, eTemp);
}
}
}
// now chuck all that pierce on as well
eTemp = EffectDamage(nPierce*(nCrit*2 + 1), DAMAGE_TYPE_PIERCING, IPGetDamagePowerConstantFromNumber(nBonus));
eTotal = EffectLinkEffects(eTotal, eTemp);
return eTotal;
}
void StoreArrowDamage(object oUser)
{
object oArrows = GetItemInSlot(INVENTORY_SLOT_ARROWS, oUser);
if (!GetIsObjectValid(oArrows))
return;
if(GetLocalInt(oArrows, "scy_AA_prop_count") == 0){
itemproperty prop = GetFirstItemProperty(oArrows);
int add, dloc, damtype, dam, dieS, dieC, subtype, pcount, type, i;
string sDam;
while(GetIsItemPropertyValid(prop)){
add = 0;
type = GetItemPropertyType(prop);
// Only deal with damage and damage vs alignment for the moment
if(type == ITEM_PROPERTY_DAMAGE_BONUS){
add = 1;
damtype = GetItemPropertySubType(prop);
dam = GetItemPropertyCostTableValue(prop);
subtype = 0;
}else if(type == ITEM_PROPERTY_DAMAGE_BONUS_VS_ALIGNMENT_GROUP){
subtype = GetItemPropertySubType(prop);
add = 1;
damtype = GetItemPropertyParam1Value(prop);
dam = GetItemPropertyCostTableValue(prop);
}
if(add == 1){
pcount ++;
/* This code works and is elegant (well i think so) but it uses a 2da fetch so i changed it
// Get the damage amount from the label in the 2da
sDam = Get2DAString("iprp_damagecost", "Label", dam);
// This section extracts the die size and count from the string
// First find the "d" position
dloc = 0;
for(i = 0;i < GetStringLength(sDam); i++){
if(GetSubString(sDam, i, 1) == "d"){
dloc = i;
i = 100;
}
}
// if there is no "d" the damage is not random
if(dloc == 0){
dieS = StringToInt(sDam);
dieC = 0;
}else{
dieS = StringToInt(GetStringRight(sDam, GetStringLength(sDam) - (dloc + 1)));
dieC = StringToInt(GetStringLeft(sDam, dloc));
} */
// Instead just use a really big switch statement
// See iprp_damagecost.2da
switch (dam){
case 1:
case 2:
case 3:
case 4:
case 5://+1-5
dieS = dam; dieC = 0; break;
case 6:
case 7:
case 8:
case 9://+1d4 1d6 1d8 1d10
dieS = 2*(dam - 4); dieC = 1; break;
case 10://+2d6
dieS = 6; dieC = 2; break;
case 11://+2d8
dieS = 8; dieC = 2; break;
case 12://+2d4
dieS = 4; dieC = 2; break;
case 13://+2d10
dieS = 10; dieC = 2; break;
case 14://+1d12
dieS = 12; dieC = 1; break;
case 15://+2d12
dieS = 12; dieC = 2; break;
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30://+6-20
dieS = dam - 10; dieC = 0; break;
}
SendMessageToPC(oUser, IntToString(dieC)+ "d" + IntToString(dieS) + " " + Get2DAString("iprp_damagetype", "Label", damtype) + " damage");
// iprp_damagetypes has two unused damage lines, need to "delete" them
if(damtype > 2)
damtype -= 2;
// the bitshift is because the damage types are 1 2 4 8 etc in nwscript
damtype = 1 << damtype;
//Store the values on the arrows themselves
SetLocalInt(oArrows, "scy_AA_prop" + IntToString(pcount) + "_damtype", damtype);
SetLocalInt(oArrows, "scy_AA_prop" + IntToString(pcount) + "_diesize", dieS);
SetLocalInt(oArrows, "scy_AA_prop" + IntToString(pcount) + "_diecount", dieC);
SetLocalInt(oArrows, "scy_AA_prop" + IntToString(pcount) + "_align", subtype);
}
prop = GetNextItemProperty(oArrows);
}
// If we have no props, make sure it doesnt check them again
if (pcount == 0)
SetLocalInt(oArrows, "scy_AA_prop_count", 255);
else
SetLocalInt(oArrows, "scy_AA_prop_count", pcount);
}
}
/*void main()
{
effect en = GetArcaneArrowDamage(GetPCSpeaker(), GetPCSpeaker());
ApplyEffectToObject(DURATION_TYPE_INSTANT, en, GetPCSpeaker());
} */
Hail:
//::///////////////////////////////////////////////
//:: x1_s2_hailarrow
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
One arrow per arcane archer level at all targets
GZ SEPTEMBER 2003
Added damage penetration
Twainer 20/10/2005
Updated to use my arrow damage functions
Also uses up arrows now
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On:
//:://////////////////////////////////////////////
#include "x0_i0_spells"
#include "scy_aa_inc"
// GZ: 2003-07-23 fixed criticals not being honored
void DoAttack(object oTarget)
{
//
int nTouch = TouchAttackRanged(oTarget);
if (nTouch > 0)
{
effect eDamage = GetArcaneArrowDamage(OBJECT_SELF, oTarget, nTouch == 2);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
}
}
void main()
{
object oTarget;
int nLevel = GetLevelByclass(class_TYPE_ARCANE_ARCHER, OBJECT_SELF);
int i = 0;
int ntargets = 0;
float fDist = 0.0;
float fDelay = 0.0;
object oArrows = GetItemInSlot(INVENTORY_SLOT_ARROWS);
if (GetLocalInt(oArrows, "scy_AA_prop_count") == 0)
{
StoreArrowDamage(OBJECT_SELF);
}
for (i = 1; i <= nLevel; i++)
{
oTarget = GetNearestCreature(CREATURE_TYPE_REPUTATION, REPUTATION_TYPE_ENEMY, OBJECT_SELF, i);
if (GetIsObjectValid(oTarget) == TRUE)
{
fDist = GetDistanceBetween(OBJECT_SELF, oTarget);
fDelay = fDist/(3.0 * log(fDist) + 2.0);
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 603));
effect eArrow = EffectVisualEffect(357);
ApplyEffectToObject(DURATION_TYPE_INSTANT, eArrow, oTarget);
DelayCommand(fDelay, DoAttack(oTarget));
ntargets++;
}
}
//SendMessageToPC(OBJECT_SELF, IntToString(ntargets) + " Targets " + IntToString(GetItemStackSize(oArrows)));
SetItemStackSize(oArrows, GetItemStackSize(oArrows) - ntargets);
// If they need more arrows than they had (or just enough) destroy the stack
if (GetItemStackSize(oArrows) - ntargets <= 0)
DestroyObject(oArrows, fDelay + 0.5);
//recharge the feat
DelayCommand(10.0f, IncrementRemainingFeatUses(OBJECT_SELF, FEAT_PRESTIGE_HAIL_OF_ARROWS));
}
Seeker:
//::///////////////////////////////////////////////
//:: x1_s2_seeker
//:: Copyright © 2001 Bioware Corp.
//:://////////////////////////////////////////////
/*
Seeker Arrow
- creates an arrow that automatically hits target.
- normal arrow damage, based on base item type
- Must have shortbow or longbow in hand.
APRIL 2003
- gave it double damage to balance for the fact
that since its a spell you are losing
all your other attack actions
SEPTEMBER 2003 (GZ)
Added damage penetration
Added correct enchantment bonus
Twainer 20/10/2005
Updated to use my arrow damage funtions
Does x3 damage (bow crit) instead of x2
Uses an arrow
*/
//:://////////////////////////////////////////////
//:: Created By:
//:: Created On:
//:://////////////////////////////////////////////
#include "x0_i0_spells"
#include "scy_aa_inc"
void main()
{
object oTarget = GetSpellTargetObject();
object oArrows = GetItemInSlot(INVENTORY_SLOT_ARROWS);
if (GetLocalInt(oArrows, "scy_AA_prop_count") == 0)
{
StoreArrowDamage(OBJECT_SELF);
}
if (GetIsObjectValid(oTarget) == TRUE){
effect eDamage = GetArcaneArrowDamage(OBJECT_SELF, oTarget, 1);
//Fire cast spell at event for the specified target
SignalEvent(oTarget, EventSpellCastAt(OBJECT_SELF, 601));
ApplyEffectToObject(DURATION_TYPE_INSTANT, eDamage, oTarget);
}
if (GetItemStackSize(oArrows) == 1)
DestroyObject(oArrows);
else
SetItemStackSize(oArrows, GetItemStackSize(oArrows) -1);
}
Lastly the whole switch statement in the include. This is another problem with AAs as I understand it. The default enhanced arrows only apply for arrows with out properties. This switch statement I believe was meant to override that, however a) it seems a bit off to me. although I am not a scripter, and
I believe it only applies to hail and seeker (not AA arrows in general), so I would also be interested in any ideas for modifying enhanced arrows (both for seeker and hail, as well as just generally) so that the enhancement applies to arrows with properites, or provides some other sort of bonus.
Cheers all!
Laz
Modifié par Lazarus Magni, 04 décembre 2011 - 06:55 .