Module: Natural20::MovementHelper
- Included in:
- AiController::Standard, CommandlineUI, MoveAction, BattleMap
- Defined in:
- lib/natural_20/concerns/movement_helper.rb
Overview
typed: true
Defined Under Namespace
Classes: Movement
Instance Method Summary collapse
- #compute_actual_moves(entity, current_moves, map, battle, movement_budget, fixed_movement: false, test_placement: true, manual_jump: []) ⇒ Movement
-
#requires_squeeze?(entity, pos_x, pos_y, map, battle = nil) ⇒ Boolean
Determine if entity needs to squeeze to get through terrain.
-
#retrieve_opportunity_attacks(entity, move_list, battle) ⇒ Array<Hash>
Checks if a move provokes opportunity attacks.
-
#valid_move_path?(entity, path, battle, map, test_placement: true, manual_jump: []) ⇒ Boolean
Checks if move path is valid.
Instance Method Details
#compute_actual_moves(entity, current_moves, map, battle, movement_budget, fixed_movement: false, test_placement: true, manual_jump: []) ⇒ Movement
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/natural_20/concerns/movement_helper.rb', line 87 def compute_actual_moves(entity, current_moves, map, battle, movement_budget, fixed_movement: false, test_placement: true, manual_jump: []) actual_moves = [] provisional_moves = [] jump_budget = (entity.standing_jump_distance / map.feet_per_grid).floor running_distance = 1 jump_distance = 0 jumped = false acrobatics_check_locations = [] athletics_check_locations = [] jump_start_locations = [] land_locations = [] jump_locations = [] impediment = nil original_budget = movement_budget current_moves.each_with_index do |m, index| raise 'invalid move coordinate' unless m.size == 2 # assert move correctness unless index.positive? actual_moves << m next end unless map.passable?(entity, *m, battle) impediment = :path_blocked break end if fixed_movement movement_budget -= 1 else movement_budget -= if !manual_jump.include?(index) && map.difficult_terrain?(entity, *m, battle) 2 else 1 end movement_budget -= 1 if requires_squeeze?(entity, *m, map, battle) movement_budget -= 1 if entity.prone? movement_budget -= 1 if entity.grappling? end if movement_budget.negative? impediment = :movement_budget break end if !fixed_movement && (map.jump_required?(entity, *m) || manual_jump.include?(index)) if entity.prone? # can't jump if prone impediment = :prone_need_to_jump break end jump_start_locations << m unless jumped jump_locations << m jump_budget -= 1 jump_distance += 1 if !fixed_movement && jump_budget.negative? impediment = :jump_distance_not_enough break end running_distance = 0 jumped = true provisional_moves << m entity_at_square = map.entity_at(*m) athletics_check_locations << m if entity_at_square&.conscious? && !entity_at_square&.prone? else actual_moves += provisional_moves provisional_moves.clear land_locations << m if jumped acrobatics_check_locations << m if jumped && map.difficult_terrain?(entity, *m, battle) running_distance += 1 # if jump not required reset jump budgets jump_budget = if running_distance > 1 (entity.long_jump_distance / map.feet_per_grid).floor else (entity.standing_jump_distance / map.feet_per_grid).floor end jumped = false jump_distance = 0 actual_moves << m end end # handle case where end is a jump, in that case we land if this is possible unless provisional_moves.empty? actual_moves += provisional_moves m = actual_moves.last land_locations << m if jumped acrobatics_check_locations << m if jumped && map.difficult_terrain?(entity, *m, battle) jump_locations.delete(actual_moves.last) end while test_placement && !map.placeable?(entity, *actual_moves.last, battle) impediment = :not_placeable jump_locations.delete(actual_moves.last) actual_moves.pop end Movement.new(actual_moves, original_budget, acrobatics_check_locations, athletics_check_locations, jump_locations, jump_start_locations, land_locations, jump_budget, movement_budget, impediment) end |
#requires_squeeze?(entity, pos_x, pos_y, map, battle = nil) ⇒ Boolean
Determine if entity needs to squeeze to get through terrain
75 76 77 |
# File 'lib/natural_20/concerns/movement_helper.rb', line 75 def requires_squeeze?(entity, pos_x, pos_y, map, battle = nil) !map.passable?(entity, pos_x, pos_y, battle, false) && map.passable?(entity, pos_x, pos_y, battle, true) end |
#retrieve_opportunity_attacks(entity, move_list, battle) ⇒ Array<Hash>
Checks if a move provokes opportunity attacks
200 201 202 203 204 205 206 207 |
# File 'lib/natural_20/concerns/movement_helper.rb', line 200 def retrieve_opportunity_attacks(entity, move_list, battle) return [] if entity.disengage?(battle) opportunity_attacks = opportunity_attack_list(entity, move_list, battle, battle.map) opportunity_attacks.select do |enemy_opporunity| enemy_opporunity[:source].has_reaction?(battle) && !entity.grappling_targets.include?(enemy_opporunity[:source]) end end |
#valid_move_path?(entity, path, battle, map, test_placement: true, manual_jump: []) ⇒ Boolean
Checks if move path is valid
63 64 65 66 |
# File 'lib/natural_20/concerns/movement_helper.rb', line 63 def valid_move_path?(entity, path, battle, map, test_placement: true, manual_jump: []) path == compute_actual_moves(entity, path, map, battle, entity.available_movement(battle) / map.feet_per_grid, test_placement: test_placement, manual_jump: manual_jump).movement end |