From 17e8d02886a3f07114783bb188fac3909533d8a1 Mon Sep 17 00:00:00 2001 From: Gary Tierney Date: Mon, 29 Feb 2016 22:21:21 +0000 Subject: [PATCH] Move next_attack logic to CombatState * Moves the decision of what attack is used next to CombatState and defers selecting the attack until the player is actually ready to hit their target for damage. * Adds a distance check so combat is only initiated within the correct range. If the player isn't close enough to their target, they will run towards it and check every tick if they're close enough to make an attack. --- data/plugins/combat/combat_action.rb | 48 +++++++++++++++++++--------- data/plugins/combat/combat_state.rb | 19 ++++++++++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/data/plugins/combat/combat_action.rb b/data/plugins/combat/combat_action.rb index 57d9fa33..b97149a6 100644 --- a/data/plugins/combat/combat_action.rb +++ b/data/plugins/combat/combat_action.rb @@ -50,7 +50,19 @@ class CombatAction < Action end def update_idle - if @combat_state.queued_attacks.empty? and @combat_state.supports_weapon + next_attack = @combat_state.next_attack true + current_distance = mob.position.get_distance @combat_state.target.position + + if current_distance > next_attack.range + @combat_state.state = :chasing + + mob.follow @combat_state.target, next_attack.range + set_delay 0 + + return + end + + if @combat_state.supports_weapon weapon = EquipmentUtil.equipped_weapon mob weapon_class = weapon.weapon_class combat_style = weapon_class.style_at mob.combat_style @@ -62,16 +74,7 @@ class CombatAction < Action mob.attacking = true end - if mob.using_special and weapon.special_attack? - @combat_state.next_attack = weapon.special_attack - else - @combat_state.next_attack = weapon_class.attack(combat_style) - end - @combat_state.state = :attacking - elsif @combat_state.queued_attacks.size > 0 - @combat_state.next_attack = @combat_state.queued_attacks.pop - @combat_state.state = :attacking else stop @combat_state.reset @@ -79,20 +82,35 @@ class CombatAction < Action end def update_attacking - raise RuntimeError.new('no attack when in :attacking state') if @combat_state.next_attack.nil? - begin - @combat_state.next_attack.do(mob, @combat_state.target) + next_attack = @combat_state.next_attack + next_attack.requirements.each do |requirement| + requirement.validate! mob + end - @combat_state.state = :idle - set_delay 0 + next_attack.requirements.each do |requirement| + requirement.apply mob + end + + next_attack.do(mob, @combat_state.target) rescue AttackRequirementException => e mob.send_message e.message + ensure + @combat_state.state = :idle + set_delay 0 end end def update_chasing + next_attack = @combat_state.next_attack true + current_distance = mob.position.get_distance @combat_state.target.position + if current_distance <= next_attack.range + @combat_state.state = :attacking + + mob.following = -1 + set_delay 0 + end end def stop diff --git a/data/plugins/combat/combat_state.rb b/data/plugins/combat/combat_state.rb index 8bc0f025..9c0088a6 100644 --- a/data/plugins/combat/combat_state.rb +++ b/data/plugins/combat/combat_state.rb @@ -11,7 +11,7 @@ end private class CombatState - attr_accessor :state, :next_attack + attr_accessor :state attr_reader :queued_attacks, :supports_weapon def initialize(mob, supports_weapon = true) @@ -41,6 +41,23 @@ class CombatState def queue_attack(attack) @queued_attacks.push(attack) end + + def next_attack(peek = false) + if @queued_attacks.size > 0 + peek ? @queued_attacks.first : @queued_attacks.pop + else + weapon = EquipmentUtil.equipped_weapon @mob + + if @mob.using_special and weapon.special_attack? + weapon.special_attack + else + weapon_class = weapon.weapon_class + combat_style = weapon_class.style_at @mob.combat_style + + weapon_class.attack combat_style + end + end + end end MOB_COMBAT_STATE_CACHE = {