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 = {