mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
17e8d02886
* 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.
122 lines
2.6 KiB
Ruby
122 lines
2.6 KiB
Ruby
java_import 'org.apollo.game.action.Action'
|
|
|
|
# Represents a one off {@code Attack}, which will not continue a combat session
|
|
# upon completion.
|
|
class AttackAction < Action
|
|
|
|
def initialize(source, target, delay, attack)
|
|
@source = source
|
|
@target = target
|
|
@delay = delay
|
|
@attack = attack
|
|
end
|
|
|
|
def execute
|
|
begin
|
|
@attack.do(mob, @target)
|
|
|
|
stop
|
|
rescue AttackRequirementException => e
|
|
player.send_message e.message
|
|
stop
|
|
end
|
|
end
|
|
end
|
|
|
|
class CombatAction < Action
|
|
def initialize(source, attack = nil)
|
|
super(0, true, source)
|
|
|
|
@combat_state = get_combat_state(source)
|
|
@attack = attack
|
|
end
|
|
|
|
def execute
|
|
if @combat_state.target.nil? and @combat_state.queued_attacks.empty?
|
|
@combat_state.reset
|
|
stop
|
|
end
|
|
|
|
case @combat_state.state
|
|
when :idle
|
|
update_idle
|
|
when :attacking
|
|
update_attacking
|
|
when :chasing
|
|
update_chasing
|
|
else
|
|
throw ArgumentError.new('invalid combat state')
|
|
end
|
|
end
|
|
|
|
def update_idle
|
|
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
|
|
|
|
if mob.attacking
|
|
set_delay weapon_class.speed(combat_style) - 1
|
|
else
|
|
set_delay 0
|
|
mob.attacking = true
|
|
end
|
|
|
|
@combat_state.state = :attacking
|
|
else
|
|
stop
|
|
@combat_state.reset
|
|
end
|
|
end
|
|
|
|
def update_attacking
|
|
begin
|
|
next_attack = @combat_state.next_attack
|
|
next_attack.requirements.each do |requirement|
|
|
requirement.validate! mob
|
|
end
|
|
|
|
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
|
|
super
|
|
|
|
@combat_state.reset
|
|
mob.attacking = false
|
|
end
|
|
end |