private int OnGetAttackModifierVersus(void *pStats, void *pCreature) { int attackMod = getAttackModifierVersusHook.CallOriginal(pStats, pCreature); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; CNWSCombatRound combatRound = creature.m_pcCombatRound; if (combatRound == null) { return(attackMod); } CNWSItem weapon = combatRound.GetCurrentAttackWeapon(combatRound.GetWeaponAttackType()); if (weapon == null) { return(attackMod); } uint baseItem = weapon.m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponFocusMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { attackMod += GreaterWeaponFocusAttackBonus; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = combatRound.GetAttack(combatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); debugMessage.Append(GreaterWeaponFocusAttackBonus); debugMessage.Append(" (Greater Weapon Focus Feat)"); currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } if (EnableSlingGoodAimFeat && baseItem == (uint)BaseItem.Sling && stats.m_nRace != (ushort)RacialType.Halfling && stats.HasFeat((ushort)Feat.GoodAim).ToBool()) { int goodAimModifier = NWNXLib.Rules().GetRulesetIntEntry("GOOD_AIM_MODIFIER".ToExoString(), 1); attackMod += goodAimModifier; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = combatRound.GetAttack(combatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); debugMessage.Append(goodAimModifier); debugMessage.Append(" (Good Aim Feat)"); currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } return(attackMod); }