Get Modified Attack Roll
#1
Posté 23 juillet 2011 - 05:33
Has anyone come up with a way to accurately do this?
#2
Posté 23 juillet 2011 - 06:36
Hopefully someone does know of one, or a way to access the stored numbers on the character, because I'd love to know about it as well.
Modifié par Failed.Bard, 24 juillet 2011 - 01:26 .
#3
Posté 23 juillet 2011 - 07:54
+ ability modifier
check weapon type, check finesse&zen archery and use the proper modifier
+ check weapon properties
Attack Bonus, Enchantments, use higher one... And don't forget the Decreased ... properties.
+ feats
Check if weapon matches weapon focus feats, epic prowess...
The above shouldn't be too hard to shape up, but...
+ effects (buffs, debuffs)
This is more difficult... Im not sure if you can get the value of an effect like you can get its type.
You also must check weapon properties and effects against the 20 cap.
Modifié par Xardex, 23 juillet 2011 - 07:56 .
#4
Posté 24 juillet 2011 - 01:32
/*
* This method returns the size of a weaponBaseType
* nWeaponBaseType = the base type id of a weapon.
* returns WSIZE_TINY = 1 or WSIZE_SMALL = 2 or WSIZE_MEDIUM = 3 or WSIZE_LARGE = 4 or WSIZE_HUGE = 5
*/
int GetWeaponSize(int nWeapBaseType){
return StringToInt(Get2DAString("BASEITEMS","WeaponSize",nWeapBaseType));
}
/*
* This method checks if the weapon is considered "small" for the oPC
* If this is the case, the method returns 2 , otherwise 0 is returned.
* - oPC = The toon
* - oWeaponOffHand = The weapon
*/
int GetIsOffHandWeaponSmallModif(object oPC, object oWeaponOffHand){
int nCSize = GetCreatureSize(oPC);
int nWeaponBaseItem = GetBaseItemType(oWeaponOffHand);
int nWSize = GetWeaponSize(nWeaponBaseItem);
int nRetVal = 0;
switch (nWSize) {
case 1: if(nCSize > CREATURE_SIZE_TINY) nRetVal = 2; break;
case 2: if(nCSize > CREATURE_SIZE_SMALL) nRetVal = 2; break;
case 3: if(nCSize > CREATURE_SIZE_MEDIUM) nRetVal = 2; break;
case 4: if(nCSize > CREATURE_SIZE_LARGE) nRetVal = 2; break;
case 5: if(nCSize > CREATURE_SIZE_HUGE) nRetVal = 2; break;
}
return nRetVal;
}
/*
* This method returns the maximul weapon enhancement that is on a weapon (including the fixed weapon enhancement)
* - oPC = The toon
* - oWeapon = The weapon
*/
int getWeaponEnhancementBonus(object oPC,object oWeapon){
itemproperty ip = GetFirstItemProperty(oWeapon);
int nType, nFound, nReturn;
while (GetIsItemPropertyValid(ip)) {
nType = GetItemPropertyType(ip);
if (nType == ITEM_PROPERTY_ENHANCEMENT_BONUS ||
nType == ITEM_PROPERTY_ATTACK_BONUS) {
nFound = GetItemPropertyCostTableValue(ip);
if (nFound > nReturn)
nReturn = nFound;
}
ip = GetNextItemProperty(oWeapon);
}
return nReturn;
}
/*
* This method calculates the dual wielding modifier
* - oPC = The toon
* - nSlot = INVENTORY_SLOT_RIGHTHAND or INVENTORY_SLOT_LEFTHAND
* - nOffSmall =The amount that can be substracted from the dualing penalties (Currently only should be 0 or 2 for small weapons)
*/
int GetDualWieldingModifier(object oPC,int nSlot, int nOffSmall){
int nTotal;
int nTwoWeaponFight, nAmbidexTerity;
if(nSlot == INVENTORY_SLOT_RIGHTHAND){
nTotal = -6 + nOffSmall;
}
else if (nSlot == INVENTORY_SLOT_LEFTHAND){
nTotal = -10 + nOffSmall;
if(GetHasFeat(FEAT_AMBIDEXTERITY,oPC)){
nTotal = nTotal + 4;
}
}
if(GetHasFeat(FEAT_TWO_WEAPON_FIGHTING,oPC)){
nTotal = nTotal +2;
}
return nTotal;
}
// This method finds all the MAGICAL AB increases on a toon.
// oPC = The toon
// returns the amount
// Stores the "result-strings" (for the feedback in the combat log) in a Local string on the oPC with name = gol_tmp_ab
// DO NOT FORGET TO DELETE TEMPSTRING!
int GetMagicABIncrease(object oPC){
int nAmount = 0;
string sResultStrings;
string sName;
effect eEff;
for (eEff = GetFirstEffect(oPC); GetIsEffectValid(eEff); eEff = GetNextEffect(oPC)) {
if (GetEffectType(eEff) == EFFECT_TYPE_ATTACK_INCREASE) {
nAmount += GetEffectInteger(eEff, 0);
int nEffectId = GetEffectSpellId(eEff);
if(nEffectId == HGEFFECT_BARDSONG_AB_00 ||
nEffectId == HGEFFECT_BARDSONG_AB_01 ||
nEffectId == HGEFFECT_BARDSONG_AB_03 ||
nEffectId == HGEFFECT_BARDSONG_AB_04 ||
nEffectId == HGEFFECT_BARDSONG_AB_05 ||
nEffectId == HGEFFECT_BARDSONG_AB_06 ||
nEffectId == HGEFFECT_BARDSONG_AB_07){
sName = "Bard Song";
}
else{
sName = SFGetSpellName(GetEffectSpellId(eEff));
}
if(GetStringLength(sName) <= 0){
sName = "generic";
}
sResultStrings += (COLOR_GREEN +" "+ sName + " : +"+IntToString(GetEffectInteger(eEff, 0))+"\\n");
}
}
SetLocalString(oPC,"gol_tmp_ab",sResultStrings);
return nAmount;
}
/*
* This method Lists the attack bonus for a weapon
* - oPC = The actual toon
* - oWeapon = The weapon
* - nSlot = INVENTORY_SLOT_RIGHTHAND or INVENTORY_SLOT_LEFTHAND
* - nDualing = If the toon is dualing melee weapons, make this 1
* - nOffSmall = The amount that can be substracted from the dualing penalties (Currently only can be 0 or 2 for small weapons)
*/
string ListAttackBonusForWeapon (object oPC, object oWeapon, int nSlot, int nDualing, int nOffSmall) {
/* include +20 magical bonus always */
int nBAB = GetBaseAttackBonus(oPC), nHD = GetHitDice(oPC);
int nEBAB, nLBAB, nWF, nGWF, nEWF, nLWF, nPWF, nEP, nCW, nWM, nAA, nAbil, nDual, nSize, nMagicIncrease, nWeaponModifs ,nOther;
string sTempIncMagicAbStrings,sTempDecMagicAbStrings;
if(nDualing > 0){
nDual = GetDualWieldingModifier(oPC,nSlot,nOffSmall);
}
if (nHD == 40) {
nBAB -= 30;
nEBAB = 10;
nLBAB = GetLocalInt(oPC, "LegendaryBAB");
} else if (nHD == 64) {
nBAB -= 50;
nEBAB = 50;
} else if (nHD > 20) {
nEBAB = (nHD - 19) / 2;
nBAB -= nEBAB;
}
int nBaseItem = BASE_ITEM_GLOVES;
if (GetIsObjectValid(oWeapon))
nBaseItem = GetBaseItemType(oWeapon);
nEP = ListAttackBonusABFeat(oPC, FEAT_EPIC_PROWESS, 1);
nWF = ListAttackBonusABFeat(oPC, GetWeaponFocusFeat(nBaseItem), 1);
nGWF = ListAttackBonusABFeat(oPC, GetWeaponGreaterFocusFeat(nBaseItem), 1);
nEWF = ListAttackBonusABFeat(oPC, GetWeaponEpicFocusFeat(nBaseItem), 2);
nLWF = ListAttackBonusABFeat(oPC, GetWeaponLegendaryFocusFeat(nBaseItem), (nEP ? 3 : 2));
nPWF = 0;
nAbil = GetAttackBonusAdjustment(oPC, oWeapon, GetItemIsRangedWeapon(oWeapon)) - (nGWF + nLWF);
nSize = GetCreatureSizeACModifier(oPC);
if (nBaseItem != BASE_ITEM_GLOVES) {
nCW = GetSkillRank(SKILL_CRAFT_WEAPON, oPC) / 40;
nAbil -= nCW;
}
int nWMLevel = GetLevelByclass(class_TYPE_WEAPON_MASTER, oPC);
if (nWMLevel >= 5 && ListAttackBonusABFeat(oPC, GetWeaponOfChoiceFeat(nBaseItem), 1) > 0) {
nWM++;
if (nWMLevel >= 10) {
nWM += (nWMLevel - 10) / 3;
if (GetIsPC(oPC)) {
nWM++;
nAbil--;
if (nWMLevel == 29) {
nAbil--;
nWM++;
} else if (nWMLevel == 30) {
nWM += 3;
nAbil -= 3;
}
}
}
}
if (GetHasSpellImmunity(SPELL_TRUE_STRIKE, oPC)) {
int nTrue = 0;
effect eEff;
for (eEff = GetFirstEffect(oPC); GetIsEffectValid(eEff); eEff = GetNextEffect(oPC)) {
if (GetEffectType(eEff) == EFFECT_TYPE_SPELL_IMMUNITY &&
GetEffectInteger(eEff, 0) == SPELL_TRUE_STRIKE) {
int nTrueBuff = GetEffectInteger(eEff, 1);
if (nTrueBuff > nTrue)
nTrue = nTrueBuff;
}
}
nTrue -= nWM;
if (nTrue > 0) {
nOther += nTrue;
nAbil -= nTrue;
}
}
if (GetBaseItemType(oWeapon) == BASE_ITEM_SHORTBOW || GetBaseItemType(oWeapon) == BASE_ITEM_LONGBOW)
nAA = (GetLevelByclass(class_TYPE_ARCANE_ARCHER, oPC) + 1) / 2;
nMagicIncrease = GetMagicABIncrease(oPC);
if(nMagicIncrease >0){
sTempIncMagicAbStrings = GetLocalString(oPC,"gol_tmp_ab");
}
DeleteLocalString(oPC,"gol_tmp_ab");
nWeaponModifs = getWeaponEnhancementBonus(oPC,oWeapon);
int nMagicTotal = nMagicIncrease + nWeaponModifs;
int nMagicMax = 20;
if(nMagicTotal > nMagicMax)
nMagicTotal = nMagicMax;
if(nMagicTotal < -20)
nMagicTotal = -20;
int nAB = nBAB + nEBAB + nLBAB + nWF + nGWF + nEWF + nLWF + nPWF + nEP + nCW + nWM + nAA + nAbil + nDual + nSize + nOther + nMagicTotal;
string sMessage = COLOR_WHITE;
if(nAB>= 0){
sMessage += "(+";
}
else{
sMessage += "(";
}
sMessage += IntToString(nAB) + ")\\n";
if (nBAB > 0)
sMessage += COLOR_PURPLE + " BAB: " + COLOR_LT_PURPLE + IntToString(nBAB) + "\\n";
if (nEBAB > 0)
sMessage += COLOR_PURPLE + " EBAB: " + COLOR_LT_PURPLE + IntToString(nEBAB) + "\\n";
if (nLBAB > 0)
sMessage += COLOR_PURPLE + " LBAB: " + COLOR_LT_PURPLE + IntToString(nLBAB) + "\\n";
if (nAbil != 0)
sMessage += COLOR_PURPLE + " Ability: " + COLOR_LT_PURPLE + IntToString(nAbil) + "\\n";
if (nWF > 0)
sMessage += COLOR_PURPLE + " Weapon Focus: " + COLOR_LT_PURPLE + IntToString(nWF) + "\\n";
if (nGWF > 0)
sMessage += COLOR_PURPLE + " Greater Weapon Focus: " + COLOR_LT_PURPLE + IntToString(nGWF) + "\\n";
if (nEWF > 0)
sMessage += COLOR_PURPLE + " Epic Weapon Focus: " + COLOR_LT_PURPLE + IntToString(nEWF) + "\\n";
if (nLWF > 0)
sMessage += COLOR_PURPLE + " Legendary Weapon Focus: " + COLOR_LT_PURPLE + IntToString(nLWF) + "\\n";
if (nPWF > 0)
sMessage += COLOR_PURPLE + " Paragon Weapon Focus: " + COLOR_LT_PURPLE + IntToString(nPWF) + "\\n";
if (nEP > 0)
sMessage += COLOR_PURPLE + " Epic Prowess: " + COLOR_LT_PURPLE + IntToString(nEP) + "\\n";
if (nCW > 0)
sMessage += COLOR_PURPLE + " Craft Weapon: " + COLOR_LT_PURPLE + IntToString(nCW) + "\\n";
if (nWM > 0)
sMessage += COLOR_PURPLE + " Weapon Master: " + COLOR_LT_PURPLE + IntToString(nWM) + "\\n";
if (nAA > 0)
sMessage += COLOR_PURPLE + " Arcane Archer: " + COLOR_LT_PURPLE + IntToString(nAA) + "\\n";
if (nDual != 0)
sMessage += COLOR_PURPLE + " Dual Wielding: " + COLOR_LT_PURPLE + IntToString(nDual) + "\\n";
if (nSize != 0)
sMessage += COLOR_PURPLE + " Size: " + COLOR_LT_PURPLE + IntToString(nSize) + "\\n";
if (nOther != 0)
sMessage += COLOR_PURPLE + " Other: " + COLOR_LT_PURPLE + IntToString(nOther) + "\\n";
if(nMagicTotal != 0){
sMessage += COLOR_PURPLE + " Magic: " + COLOR_LT_PURPLE + IntToString(nMagicTotal) + COLOR_LT_PURPLE + " (Max = +"+IntToString(nMagicMax)+")\\n";
if(nMagicIncrease > 0){
sMessage += COLOR_BLUE + " -General inc : +" + COLOR_BLUE + IntToString(nMagicIncrease) + "\\n";
sMessage += sTempIncMagicAbStrings;
}
if(nWeaponModifs > 0){
sMessage += COLOR_BLUE + " -Weapon modifs : +" + COLOR_BLUE + IntToString(nWeaponModifs) + "\\n";
}
}
return (sMessage + "\\n");
}
/*
* This method lists the attack bonus (!List ab command) of a toon
* -oTarget = The target we want the attack bonus for
* -oPC = The player character
*
*/
void ListAttackBonus (object oTarget, object oPC) {
string sMessage;
object oWeapon;
int nSmall = 0;
int nDual = 0;
if (oTarget != oPC)
sMessage = COLOR_WHITE + "Attack bonus for " + GetName(oTarget) + ":\\n";
else
sMessage = COLOR_WHITE + "Attack bonus:\\n";
object oWeaponR = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget);
object oWeaponL = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget);
if( GetIsObjectValid(oWeaponR) && GetItemIsMeleeWeapon(oWeaponR) && GetIsObjectValid(oWeaponL) && GetItemIsMeleeWeapon(oWeaponL)){
// DUAL WIELDING
nSmall = GetIsOffHandWeaponSmallModif(oPC,oWeaponL);
nDual = 1;
}
if (GetIsObjectValid(oWeapon = GetItemInSlot(INVENTORY_SLOT_RIGHTHAND, oTarget)))
sMessage += COLOR_GOLD + "Right Hand: " + COLOR_LT_YELLOW + GetName(oWeapon) + " ";
else
sMessage += COLOR_GOLD + "Right Hand: " + COLOR_LT_YELLOW + "(unarmed) ";
sMessage += COLOR_ORANGE + "(" + IntToString(GetCriticalHitRange(oTarget, FALSE)) + "-20/x" +
IntToString(GetCriticalHitMultiplier(oTarget, FALSE)) + ") ";
sMessage += ListAttackBonusForWeapon(oTarget, oWeapon, INVENTORY_SLOT_RIGHTHAND,nDual,nSmall);
if (GetIsObjectValid(oWeapon = GetItemInSlot(INVENTORY_SLOT_LEFTHAND, oTarget)) &&
GetItemIsMeleeWeapon(oWeapon)) {
sMessage += COLOR_GOLD + "Left Hand: " + COLOR_LT_YELLOW + GetName(oWeapon) + " ";
sMessage += COLOR_ORANGE + "(" + IntToString(GetCriticalHitRange(oTarget, TRUE)) + "-20/x" +
IntToString(GetCriticalHitMultiplier(oTarget, TRUE)) + ") ";
sMessage += ListAttackBonusForWeapon(oTarget, oWeapon, INVENTORY_SLOT_LEFTHAND,nDual,nSmall);
}
SendChatLogMessage(oPC, sMessage + COLOR_END, oPC, 5);
}
Funky
#5
Posté 24 juillet 2011 - 02:20
Xardex wrote...
+ effects (buffs, debuffs)
This is more difficult... Im not sure if you can get the value of an effect like you can get its type.
You are quite right.
But you ought to point out that it is _horribly_ complex to implement that.
You should take note of the properties used to create the effect, the intended duration of the effect, and also Who has created the effect. Then you much keep an eye on every usage of RemoveEffect(), ForceRest(), EffectDispelMagic*() functions, as well as canonical Resting, Clients Leaving, Players dieing and respawning... in short: every thing that can cause the premature departure of an effect is to be kept under constant vigilance.
And finally, because you can not retrieve the parameters used to create an effect... you have to compare the effect with _itself_ if you want to determine whether or not said effect is still active. Which means that you have to preemptively "save" said effect on a creature locked in some unreachable service-Area where no player can go screw up.
Seriously, it is a scary amount of work.
Unless the ability to track the Modified Attack Roll is pivotal to a full fledged module, it will not be worth the effort to go through ALL that... and just to determine the current value of 1 number anyway.
NWNX and a slick plugin would do far better -- incidentally sparing you the trouble to brutalize a module as well as a good hundred of the original bioware scripts.
-fox
#6
Posté 24 juillet 2011 - 05:28
the.gray.fox wrote...
And finally, because you can not retrieve the parameters used to create an effect... you have to compare the effect with _itself_ if you want to determine whether or not said effect is still active. Which means that you have to preemptively "save" said effect on a creature locked in some unreachable service-Area where no player can go screw up
....
NWNX and a slick plugin would do far better -- incidentally sparing you the trouble to brutalize a module as well as a good hundred of the original bioware scripts.
Actually, you CAN retrieve the effect params, using nwnx_structs. That's what the code I posted above does, and it makes tallying effects bonuses child's play:
if (GetEffectType(eEff) == EFFECT_TYPE_ATTACK_INCREASE) {
nAmount += GetEffectInteger(eEff, 0);
Funky
Modifié par FunkySwerve, 24 juillet 2011 - 05:29 .
#7
Posté 24 juillet 2011 - 05:46
But linux only. There is no global solution yet and without linux nwnx its not even worth to try, otherwise yo end up like PRCFunkySwerve wrote...
the.gray.fox wrote...
And finally, because you can not retrieve the parameters used to create an effect... you have to compare the effect with _itself_ if you want to determine whether or not said effect is still active. Which means that you have to preemptively "save" said effect on a creature locked in some unreachable service-Area where no player can go screw up
....
NWNX and a slick plugin would do far better -- incidentally sparing you the trouble to brutalize a module as well as a good hundred of the original bioware scripts.
Actually, you CAN retrieve the effect params, using nwnx_structs. That's what the code I posted above does, and it makes tallying effects bonuses child's play:if (GetEffectType(eEff) == EFFECT_TYPE_ATTACK_INCREASE) { nAmount += GetEffectInteger(eEff, 0);
Funky
#8
Posté 24 juillet 2011 - 06:57
But yeah, it would be pretty sweet if NWNX would be able to find and pull that info. I'll keep dreaming of a NWNFuncs_GetAttackBonus in nwnx_funcs or something. Until then, at least for my purposes, it's just not worth the effort for what I would have liked it for.
#9
Posté 26 juillet 2011 - 12:12
The game already computes it for you -- It makes sense to go get just that, rather than recalculate it off equipment and effects.
-fox





Retour en haut







