From a7b4036deb20ae702d7e46690f21b0f8e6f94aec Mon Sep 17 00:00:00 2001 From: Gary Tierney Date: Fri, 29 Jan 2016 22:12:13 +0000 Subject: [PATCH] Add Attack / AttackRequirement docs --- data/plugins/combat/attack.rb | 47 +++++++++++++++++++--- data/plugins/combat/attack_requirements.rb | 11 ++++- data/plugins/combat/combat.rb | 13 +++--- data/plugins/combat/spellbook.rb | 11 ----- data/plugins/combat/spellbooks.rb | 5 +++ data/plugins/combat/spells/strikes.rb | 0 6 files changed, 63 insertions(+), 24 deletions(-) delete mode 100644 data/plugins/combat/spellbook.rb create mode 100644 data/plugins/combat/spells/strikes.rb diff --git a/data/plugins/combat/attack.rb b/data/plugins/combat/attack.rb index 42ad25ca..b991a2a5 100644 --- a/data/plugins/combat/attack.rb +++ b/data/plugins/combat/attack.rb @@ -2,9 +2,40 @@ java_import 'org.apollo.cache.def.ItemDefinition' java_import 'org.apollo.game.model.Animation' java_import 'org.apollo.game.model.Graphic' +## +# The {@code BaseAttack} which all other {@code Attack}s derive from. +# +# Supports most general attacks by playing an {@code Animation} and an optional {@code Graphic}. +# Default options are: +# * a range of 1 +# * no requirements +# * no graphic class BaseAttack - attr_reader :requirements, :range, :speed + ## + # The {@code AttackRequirement}s a {@code Player} must meet to use this attack. + + attr_reader :requirements + ## + # The maximum range this {@code Attack} can be executed from. + + attr_reader :range + + ## + # How often this {@code Attack} can be executed in ticks. + + attr_reader :speed + + ## + # Create a new {@code Attack} with the given properties. + # + # @param [Number] speed The minimum number of ticks to wait before this attack can be executed after + # a previous {@code Attack}. + # @param [Number] animation The {@code Animation} to play on the player when executing this {@code Attack}. + # @param [Hash] graphic The {@code Graphic} to play on the player when executing this {@code Attack}. + # @param [Number] range The maximum distance this {@code Attack} can be executed from. + # @param [Array] requirements The requirements that must be met to execute this {@code Attack}. + def initialize(speed:, animation:, graphic: nil, range: 1, requirements: []) fail 'Attack speed must be a non-negative number' if speed < 0 fail 'Attack range must be a non-negative number' if range < 0 @@ -16,6 +47,12 @@ class BaseAttack @requirements = requirements end + ## + # Execute this {@code Attack} and apply its effect. + # + # @param [Mob] source The attacker. + # @param [Mob] target The target. + def do(source, target) source.play_animation(Animation.new(@animation)) @@ -86,9 +123,9 @@ class MagicAttack < BaseAttack distance = source.position.get_distance(target.position) damage_delay = (@projectile_type.delay + @projectile_type.speed + distance * 5) * 0.02857 - + schedule_damage!(source, target, rand(@damage), damage_delay) do - + unless @hit_graphic.nil? if @hit_graphic.is_a?(Hash) target.play_graphic(Graphic.new(@hit_graphic[:id], @hit_graphic[:delay] || 0, @hit_graphic[:height] || 0)) @@ -96,10 +133,10 @@ class MagicAttack < BaseAttack target.play_graphic(Graphic.new(@hit_graphic)) end end - + end end - + end ## diff --git a/data/plugins/combat/attack_requirements.rb b/data/plugins/combat/attack_requirements.rb index afb449b9..09554dcf 100644 --- a/data/plugins/combat/attack_requirements.rb +++ b/data/plugins/combat/attack_requirements.rb @@ -3,6 +3,8 @@ java_import 'org.apollo.game.model.entity.EquipmentConstants' java_import 'org.apollo.game.model.entity.Skill' java_import 'org.apollo.cache.def.EquipmentDefinition' +## +# An {@code Exception} thrown by an {@code AttackRequirement} if a player doesn't atch its requirements. class AttackRequirementException < Exception attr_reader :message @@ -11,11 +13,18 @@ class AttackRequirementException < Exception end end +## +# A requirement which is checked before an {@code Attack} is executed. class AttackRequirement + ## + # Verify that {@code _player} meets the requirements, throwing an AttackRequirementException with an appropriate + # message if not. def validate(_player) throw RuntimeError.new('validate! not implemented') end + ## + # Do any destructive actions (e.g., remove items) after all requirements for an {@code Attack} have been met. def apply!(_player) throw RuntimeError.new('apply not implemented') end @@ -44,7 +53,6 @@ class AttackRequirementDSL def skill(skill, level:) requirements << LevelRequirement.new(skill, level) end - end class SpecialEnergyRequirement < AttackRequirement @@ -70,7 +78,6 @@ class SpecialEnergyRequirement < AttackRequirement end class LevelRequirement < AttackRequirement - SKILLS = { :magic => Skill::MAGIC } diff --git a/data/plugins/combat/combat.rb b/data/plugins/combat/combat.rb index 98be870f..7aa05b9f 100644 --- a/data/plugins/combat/combat.rb +++ b/data/plugins/combat/combat.rb @@ -20,24 +20,25 @@ end on :message, :magic_on_mob do |player, message| target = $world.npc_repository.get(message.index) + + next unless SPELLBOOKS.has_key? message.interface_id player_combat_state = player.get_combat_state player_combat_state.target = target - - spellbook = spellbook_for(message.interface_id) + + spellbook = SPELLBOOKS[message.interface_id] spell = spell_for(spellbook, message.spell_id) + player_combat_state.queue_attack(spell.attack) player.walking_queue.clear - player.start_action CombatAction.new(player) - - magic_attack = MagicAttack.new(spell) - player_combat_state.queue_attack(magic_attack) + player.start_action CombatAction.new(player, true) end on :message, :player_action do |player, message| end +## TODO: another way of handling this schedule 0 do |_task| $world.player_repository.each { |player| player.attack_timer = player.attack_timer + 1 } $world.npc_repository.each { |npc| npc.attack_timer = npc.attack_timer + 1 } diff --git a/data/plugins/combat/spellbook.rb b/data/plugins/combat/spellbook.rb deleted file mode 100644 index 9c31636a..00000000 --- a/data/plugins/combat/spellbook.rb +++ /dev/null @@ -1,11 +0,0 @@ -SPELLBOOKS = {} - -def create_spellbook(identifier, interface_id:) - SPELLBOOKS[interface_id] = identifier -end - -def spellbook_for(interface_id) - fail "Could not find spellbook for #{interface_id}" unless SPELLBOOKS.has_key?(interface_id) - - return SPELLBOOKS[interface_id] -end \ No newline at end of file diff --git a/data/plugins/combat/spellbooks.rb b/data/plugins/combat/spellbooks.rb index 8b41f425..189da025 100644 --- a/data/plugins/combat/spellbooks.rb +++ b/data/plugins/combat/spellbooks.rb @@ -1,2 +1,7 @@ +SPELLBOOKS = {} + +def create_spellbook(identifier, interface_id:) + SPELLBOOKS[interface_id] = identifier +end create_spellbook :modern, interface_id: 192 \ No newline at end of file diff --git a/data/plugins/combat/spells/strikes.rb b/data/plugins/combat/spells/strikes.rb new file mode 100644 index 00000000..e69de29b