mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 00:38:21 +00:00
348e5cc8dc
* Uses a hierarchy of WeaponClasses -> Weapons for performing attacks, with WeaponClass having a set of styles and associated Attacks for those styles. Weapons and their classes are built with an easy to use and clean DSL. * Adds a BonusContainer mixin, so that Equipment, Weapons, and WeaponClasses can all have their own set of bonuses which apply to the player. * Allows attacks to be queued to the Mobs CombatState instance from external code, allowing e.g., NPCs or auto-cast to queue attacks to be executed.
106 lines
2.3 KiB
Ruby
106 lines
2.3 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
|
|
if @combat_state.queued_attacks.empty? and @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
|
|
|
|
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
|
|
end
|
|
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)
|
|
|
|
@combat_state.state = :idle
|
|
set_delay 0
|
|
rescue AttackRequirementException => e
|
|
mob.send_message e.message
|
|
end
|
|
end
|
|
|
|
def update_chasing
|
|
|
|
end
|
|
|
|
def stop
|
|
super
|
|
|
|
@combat_state.reset
|
|
mob.attacking = false
|
|
|
|
puts 'stopped combat action'
|
|
end
|
|
end |