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.
This commit is contained in:
Gary Tierney
2016-02-29 22:21:21 +00:00
parent 064f22d2e0
commit 17e8d02886
2 changed files with 51 additions and 16 deletions
+33 -15
View File
@@ -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
+18 -1
View File
@@ -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 = {