module Natural20::Weapons
reusable utility methods for weapon calculations
Public Instance Methods
compute_advantages_and_disadvantages(battle, source, target, weapon, source_pos: nil)
click to toggle source
Compute all advantages and disadvantages @param battle [Natural20::Battle] @param source [Natural20::Entity] @param target [Natural20::Entity] @option weapon type [String] @return [Array]
# File lib/natural_20/utils/weapons.rb, line 22 def compute_advantages_and_disadvantages(battle, source, target, weapon, source_pos: nil) weapon = battle.session.load_weapon(weapon) if weapon.is_a?(String) || weapon.is_a?(Symbol) advantage = [] disadvantage = [] disadvantage << :prone if source.prone? disadvantage << :squeezed if source.squeezed? disadvantage << :target_dodge if target.dodge?(battle) disadvantage << :armor_proficiency unless source.proficient_with_equipped_armor? advantage << :squeezed if target.squeezed? advantage << :being_helped if battle.help_with?(target) disadvantage << :target_long_range if battle.map && weapon && battle.map.distance(source, target, entity_1_pos: source_pos) > weapon[:range] if weapon && weapon[:type] == 'ranged_attack' && battle.map disadvantage << :ranged_with_enemy_in_melee if battle.enemy_in_melee_range?(source, source_pos: source_pos) disadvantage << :target_is_prone_range if target.prone? end if source.class_feature?('pack_tactics') && battle.ally_within_enemey_melee_range?(source, target, source_pos: source_pos) advantage << :pack_tactics end if weapon && weapon[:properties]&.include?('heavy') && source.size == :small disadvantage << :small_creature_using_heavy end advantage << :target_is_prone if weapon && weapon[:type] == 'melee_attack' && target.prone? advantage << :unseen_attacker if battle.map && !battle.can_see?(target, source, entity_2_pos: source_pos) disadvantage << :invisible_attacker if battle.map && !battle.can_see?(source, target, entity_1_pos: source_pos) [advantage, disadvantage] end
damage_modifier(entity, weapon, second_hand: false)
click to toggle source
Calculates weapon damage roll @param entity [Natural20::Entity] @param weapon [Hash] weapon descriptor @param second_hand [Boolean] Second hand to be used for two weapon fighting @return [String]
# File lib/natural_20/utils/weapons.rb, line 61 def damage_modifier(entity, weapon, second_hand: false) damage_mod = entity.attack_ability_mod(weapon) damage_mod = [damage_mod, 0].min if second_hand && !entity.class_feature?('two_weapon_fighting') # compute damage roll using versatile weapon property damage_roll = if weapon[:properties]&.include?('versatile') && entity.used_hand_slots <= 1.0 weapon[:damage_2] else weapon[:damage] end # duelist class feature if entity.class_feature?('dueling') && weapon[:type] == 'melee_attack' && entity.used_hand_slots(weapon_only: true) <= 1.0 damage_mod += 2 end "#{damage_roll}#{damage_mod >= 0 ? "+#{damage_mod}" : damage_mod}" end
target_advantage_condition(battle, source, target, weapon, source_pos: nil)
click to toggle source
Check all the factors that affect advantage/disadvantage in attack rolls
# File lib/natural_20/utils/weapons.rb, line 4 def target_advantage_condition(battle, source, target, weapon, source_pos: nil) advantages, disadvantages = compute_advantages_and_disadvantages(battle, source, target, weapon, source_pos: source_pos) return [0, [advantages, disadvantages]] if advantages.empty? && disadvantages.empty? return [0, [advantages, disadvantages]] if !advantages.empty? && !disadvantages.empty? return [1, [advantages, disadvantages]] unless advantages.empty? [-1, [advantages, disadvantages]] end