private int OnGetRangedDamageBonus(void *pStats) { int damageBonus = getRangedDamageBonusHook.CallOriginal(pStats); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = stats.m_pBaseCreature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (weapon == null) { return(damageBonus); } uint baseItem = weapon.m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponSpecializationMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { return(damageBonus + GreaterWeaponSpecializationDamageBonus); } return(damageBonus); }
private int OnGetDamageBonus(void *pStats, void *pCreature, int bOffHand) { int damageBonus = getDamageBonusHook.CallOriginal(pStats, pCreature, bOffHand); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; bool offHand = bOffHand.ToBool(); CNWSItem?weapon = GetEquippedWeapon(creature, offHand); uint baseItem = weapon != null ? weapon.m_nBaseItem : (uint)BaseItem.Gloves; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponSpecializationMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { damageBonus += GreaterWeaponSpecializationDamageBonus; if ((*NWNXLib.EnableCombatDebugging()).ToBool() && stats.m_bIsPC.ToBool()) { CNWSCombatAttackData currentAttack = creature.m_pcCombatRound.GetAttack(creature.m_pcCombatRound.m_nCurrentAttack); StringBuilder debugMessage = new StringBuilder(currentAttack.m_sDamageDebugText.ToString()); debugMessage.Append(" + "); if (currentAttack.m_nAttackResult == 3) { int criticalThreat = stats.GetCriticalHitMultiplier(bOffHand); debugMessage.Append(GreaterWeaponSpecializationDamageBonus * criticalThreat); debugMessage.Append(" (Greater Weapon Specialization Feat) (Critical x"); debugMessage.Append(criticalThreat); debugMessage.Append(")"); } else { debugMessage.Append(GreaterWeaponSpecializationDamageBonus); debugMessage.Append(" (Greater Weapon Specialization Feat) "); } currentAttack.m_sDamageDebugText = debugMessage.ToString().ToExoString(); } } return(damageBonus); }
private int OnGetWeaponFinesse(void *pStats, void *pWeapon) { if (pStats == null) { return(false.ToInt()); } CNWSCreatureStats creatureStats = CNWSCreatureStats.FromPointer(pStats); if (!creatureStats.HasFeat((ushort)Feat.WeaponFinesse).ToBool()) { return(0); } return(IsWeaponLight(creatureStats, CNWSItem.FromPointer(pWeapon), true).ToInt()); }
private int OnGetEpicWeaponDevastatingCritical(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = CNWSItem.FromPointer(pWeapon); uint weaponType = weapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = epicWeaponDevastatingCriticalMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } bool canUseFeat = applicableFeatExists && hasApplicableFeat || getEpicWeaponDevastatingCriticalHook.CallOriginal(pStats, pWeapon).ToBool(); if (weapon != null && canUseFeat && OnDevastatingCriticalHit != null) { CNWSCreature creature = stats.m_pBaseCreature; CNWSCombatRound combatRound = creature.m_pcCombatRound; CNWSCombatAttackData attackData = combatRound.GetAttack(combatRound.m_nCurrentAttack); DevastatingCriticalData devastatingCriticalData = new DevastatingCriticalData { Weapon = weapon.ToNwObject <NwItem>() !, Target = creature.m_oidAttackTarget.ToNwObject <NwGameObject>() !, Damage = attackData.GetTotalDamage(1), }; OnDevastatingCriticalHit(devastatingCriticalData); if (devastatingCriticalData.Bypass) { attackData.m_bKillingBlow = 0; return(0); } } return(canUseFeat.ToInt()); }
private int OnGetRangedAttackBonus(void *pStats, int bIncludeBase, int bTouchAttack) { int attackBonus = getRangedAttackBonusHook.CallOriginal(pStats, bIncludeBase, bTouchAttack); if (bTouchAttack.ToBool()) { return(attackBonus); } CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSItem weapon = stats.m_pBaseCreature.m_pInventory.GetItemInSlot((uint)EquipmentSlot.RightHand); if (weapon == null) { return(attackBonus); } 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) { attackBonus += GreaterWeaponFocusAttackBonus; } if (EnableSlingGoodAimFeat && baseItem == (uint)BaseItem.Sling && stats.m_nRace != (ushort)RacialType.Halfling && stats.HasFeat((ushort)Feat.GoodAim).ToBool()) { attackBonus += 1; } return(attackBonus); }
private int OnGetIsWeaponOfChoice(void *pStats, uint nBaseItem) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); bool hasApplicableFeat = false; bool applicableFeatExists = weaponOfChoiceMap.TryGetValue(nBaseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } return(applicableFeatExists && hasApplicableFeat ? 1 : getIsWeaponOfChoiceHook.CallOriginal(pStats, nBaseItem)); }
private int OnGetWeaponImprovedCritical(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); uint weaponType = pWeapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = weaponImprovedCriticalMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } return(applicableFeatExists && hasApplicableFeat ? 1 : getWeaponImprovedCriticalHook.CallOriginal(pStats, pWeapon)); }
private int OnGetEpicWeaponFocus(void *pStats, void *pWeapon) { CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); uint weaponType = pWeapon == null ? (uint)BaseItem.Gloves : CNWSItem.FromPointer(pWeapon).m_nBaseItem; bool hasApplicableFeat = false; bool applicableFeatExists = epicWeaponFocusMap.TryGetValue(weaponType, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool() || feat == (ushort)Feat.EpicWeaponFocus_Creature && stats.HasFeat((ushort)Feat.EpicWeaponFocus_Unarmed).ToBool(); if (hasApplicableFeat) { break; } } } return(applicableFeatExists && hasApplicableFeat ? 1 : getEpicWeaponFocusHook.CallOriginal(pStats, pWeapon)); }
private int OnGetMeleeDamageBonus(void *pStats, int bOffHand, byte nCreatureWeaponIndex) { int damageBonus = getMeleeDamageBonusHook.CallOriginal(pStats, bOffHand, nCreatureWeaponIndex); CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; bool offHand = bOffHand.ToBool(); CNWSItem?weapon = null; if (nCreatureWeaponIndex == 255) { weapon = GetEquippedWeapon(creature, offHand); } uint baseItem = weapon != null ? weapon.m_nBaseItem : (uint)BaseItem.Gloves; bool hasApplicableFeat = false; bool applicableFeatExists = greaterWeaponSpecializationMap.TryGetValue(baseItem, out HashSet <ushort>?types); if (applicableFeatExists) { foreach (ushort feat in types !) { hasApplicableFeat = stats.HasFeat(feat).ToBool(); if (hasApplicableFeat) { break; } } } if (applicableFeatExists && hasApplicableFeat) { return(damageBonus + GreaterWeaponSpecializationDamageBonus); } return(damageBonus); }
private int OnGetMeleeAttackBonus(void *pStats, int bOffHand, int bIncludeBase, int bTouchAttack) { int attackBonus = getMeleeAttackBonusHook.CallOriginal(pStats, bOffHand, bIncludeBase, bTouchAttack); if (bTouchAttack.ToBool()) { return(attackBonus); } CNWSCreatureStats stats = CNWSCreatureStats.FromPointer(pStats); CNWSCreature creature = stats.m_pBaseCreature; bool offHand = bOffHand.ToBool(); CNWSItem?weapon = GetEquippedWeapon(creature, offHand); uint baseItem = weapon != null ? weapon.m_nBaseItem : (uint)BaseItem.Gloves; 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) { return(attackBonus + GreaterWeaponFocusAttackBonus); } return(attackBonus); }
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); }