Add more documentation and fix rubocop warnings

This commit is contained in:
Gary Tierney
2016-01-29 22:42:03 +00:00
parent a7b4036deb
commit 8e0b84a470
17 changed files with 77 additions and 80 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ def create_ammo(item_matcher, properties, &block)
items.each do |item_id| items.each do |item_id|
AMMO[item_id] = Ammo.new(item_id, properties) AMMO[item_id] = Ammo.new(item_id, properties)
AMMO[item_id].instance_eval &block if block_given? AMMO[item_id].instance_eval(&block) if block_given?
end end
end end
+12 -15
View File
@@ -13,29 +13,29 @@ java_import 'org.apollo.game.model.Graphic'
class BaseAttack class BaseAttack
## ##
# The {@code AttackRequirement}s a {@code Player} must meet to use this attack. # The {@code AttackRequirement}s a {@code Player} must meet to use this attack.
attr_reader :requirements attr_reader :requirements
## ##
# The maximum range this {@code Attack} can be executed from. # The maximum range this {@code Attack} can be executed from.
attr_reader :range attr_reader :range
## ##
# How often this {@code Attack} can be executed in ticks. # How often this {@code Attack} can be executed in ticks.
attr_reader :speed attr_reader :speed
## ##
# Create a new {@code Attack} with the given properties. # 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 # @param [Number] speed The minimum number of ticks to wait before this attack can be executed after
# a previous {@code Attack}. # a previous {@code Attack}.
# @param [Number] animation The {@code Animation} to play on the player when executing this {@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 [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 [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}. # @param [Array] requirements The requirements that must be met to execute this {@code Attack}.
def initialize(speed:, animation:, graphic: nil, range: 1, requirements: []) def initialize(speed:, animation:, graphic: nil, range: 1, requirements: [])
fail 'Attack speed must be a non-negative number' if speed < 0 fail 'Attack speed must be a non-negative number' if speed < 0
fail 'Attack range must be a non-negative number' if range < 0 fail 'Attack range must be a non-negative number' if range < 0
@@ -49,10 +49,10 @@ class BaseAttack
## ##
# Execute this {@code Attack} and apply its effect. # Execute this {@code Attack} and apply its effect.
# #
# @param [Mob] source The attacker. # @param [Mob] source The attacker.
# @param [Mob] target The target. # @param [Mob] target The target.
def do(source, target) def do(source, target)
source.play_animation(Animation.new(@animation)) source.play_animation(Animation.new(@animation))
@@ -95,11 +95,10 @@ class RangedAttack < BaseAttack
end end
## ##
# A simple magic attack, which sends a projectile based on the current spell that the player is casting and deals # A simple magic attack, which sends a projectile based on the current spell that the player is casting and deals
# damage delayed by the speed and travel distance of the projectile. # damage delayed by the speed and travel distance of the projectile.
class MagicAttack < BaseAttack class MagicAttack < BaseAttack
## ##
# The maximum distance that a magic attack can be performed from. # The maximum distance that a magic attack can be performed from.
MAX_DISTANCE = 8 MAX_DISTANCE = 8
@@ -118,7 +117,6 @@ class MagicAttack < BaseAttack
end end
def apply(source, target) def apply(source, target)
projectile!(source, target, @projectile, @projectile_type) projectile!(source, target, @projectile, @projectile_type)
distance = source.position.get_distance(target.position) distance = source.position.get_distance(target.position)
@@ -136,7 +134,6 @@ class MagicAttack < BaseAttack
end end
end end
end end
## ##
@@ -154,7 +151,7 @@ end
class AttackDSL class AttackDSL
attr_accessor :animation, :speed, :range, :graphic attr_accessor :animation, :speed, :range, :graphic
def initialize() def initialize
@requirements = [] @requirements = []
@subattacks = [] @subattacks = []
end end
@@ -200,11 +197,11 @@ end
private private
def schedule_damage!(source, target, amount, delay, secondary = false, &callback) def schedule_damage!(source, target, amount, delay, secondary = false, &_callback)
schedule delay do |task| schedule delay do |task|
do_damage!(source, target, amount, secondary) do_damage!(source, target, amount, secondary)
callback.call if block_given? yield if block_given?
task.stop task.stop
end end
@@ -225,7 +222,7 @@ end
def auto_retaliate!(source, target) def auto_retaliate!(source, target)
target_combat_state = target.get_combat_state target_combat_state = target.get_combat_state
if target.auto_retaliate && !target_combat_state.is_attacking? if target.auto_retaliate && !target_combat_state.attacking?
target_combat_state.target = source target_combat_state.target = source
target.start_action(CombatAction.new(target)) target.start_action(CombatAction.new(target))
end end
+15 -17
View File
@@ -32,9 +32,9 @@ end
class AttackRequirementDSL class AttackRequirementDSL
RUNES = { RUNES = {
:air => 556, :water => 555, :earth => 557, :fire => 554, air: 556, water: 555, earth: 557, fire: 554,
:mind => 558, :chaos => 562, :death => 560, :blood => 565, mind: 558, chaos: 562, death: 560, blood: 565,
:cosmic => 564, :law => 563, :nature => 561, :soul => 566 cosmic: 564, law: 563, nature: 561, soul: 566
} }
attr_reader :requirements attr_reader :requirements
@@ -65,7 +65,7 @@ class SpecialEnergyRequirement < AttackRequirement
player.using_special = false player.using_special = false
update_special_bar(player) update_special_bar(player)
fail AttackRequirementException.new('Not enough special attack energy.') fail AttackRequirementException, 'Not enough special attack energy.'
end end
end end
@@ -79,11 +79,11 @@ end
class LevelRequirement < AttackRequirement class LevelRequirement < AttackRequirement
SKILLS = { SKILLS = {
:magic => Skill::MAGIC magic: Skill::MAGIC
} }
def initialize(type, level) def initialize(type, level)
fail "Could not find '#{type}' skill." unless SKILLS.has_key?(type) fail "Could not find '#{type}' skill." unless SKILLS.key?(type)
@skill = SKILLS[type] @skill = SKILLS[type]
@level = level @level = level
@@ -91,8 +91,8 @@ class LevelRequirement < AttackRequirement
def validate(player) def validate(player)
current_level = player.skill_set.current_level(@skill) current_level = player.skill_set.current_level(@skill)
throw AttackRequirementException.new(skill_requirement_message) unless current_level >= @level fail AttackRequirementException, skill_requirement_message unless current_level >= @level
end end
def apply!(player) def apply!(player)
@@ -101,7 +101,7 @@ class LevelRequirement < AttackRequirement
private private
def skill_requirement_message def skill_requirement_message
"TODO" 'TODO'
end end
end end
@@ -112,7 +112,7 @@ class ItemRequirement < AttackRequirement
end end
def validate(player) def validate(player)
throw AttackRequirementException.new(item_missing_message) unless player.inventory.get_amount(@item) >= @amount fail AttackRequirementException, item_missing_message unless player.inventory.get_amount(@item) >= @amount
end end
def apply!(player) def apply!(player)
@@ -122,8 +122,6 @@ class ItemRequirement < AttackRequirement
private private
def item_missing_message def item_missing_message
definition = ItemDefinition.lookup(@item)
"You don't have enough #{lookup_item(@item).name}s" "You don't have enough #{lookup_item(@item).name}s"
end end
end end
@@ -141,22 +139,22 @@ class AmmoRequirement < AttackRequirement
equipped_ammo_amt = player.equipment.get(EquipmentConstants::AMMO).amount equipped_ammo_amt = player.equipment.get(EquipmentConstants::AMMO).amount
if equipped_ammo.nil? if equipped_ammo.nil?
fail AttackRequirementException.new('You have no ammo left in your quiver!') fail AttackRequirementException, 'You have no ammo left in your quiver!'
end end
if @amount > 1 && equipped_ammo_amt < @amount if @amount > 1 && equipped_ammo_amt < @amount
fail AttackRequirementException.new('You don\'t have enough ammo left in your quiver!') fail AttackRequirementException, 'You don\'t have enough ammo left in your quiver!'
end end
unless equipped_ammo.weapon_classes.include? equipped_weapon.weapon_class.name unless equipped_ammo.weapon_classes.include? equipped_weapon.weapon_class.name
fail AttackRequirementException.new('You can\'t use this ammo with this weapon.') fail AttackRequirementException, 'You can\'t use this ammo with this weapon.'
end end
if equipped_ammo.level_requirement > equipped_weapon_def.ranged_level if equipped_ammo.level_requirement > equipped_weapon_def.ranged_level
fail AttackRequirementException.new('You can\'t use this ammo with this weapon.') fail AttackRequirementException, 'You can\'t use this ammo with this weapon.'
end end
end end
def apply!(player) def apply!(player)
equipped_ammo = EquipmentUtil.equipped_ammo player equipped_ammo = EquipmentUtil.equipped_ammo player
+1
View File
@@ -1,4 +1,5 @@
module Combat module Combat
##
# A module for units which can have their own bonuses. E.G., weapons, equipment, ammo. # A module for units which can have their own bonuses. E.G., weapons, equipment, ammo.
module BonusContainer module BonusContainer
def attack_bonus(type) def attack_bonus(type)
+3 -3
View File
@@ -20,8 +20,8 @@ end
on :message, :magic_on_mob do |player, message| on :message, :magic_on_mob do |player, message|
target = $world.npc_repository.get(message.index) target = $world.npc_repository.get(message.index)
next unless SPELLBOOKS.has_key? message.interface_id next unless SPELLBOOKS.key? message.interface_id
player_combat_state = player.get_combat_state player_combat_state = player.get_combat_state
player_combat_state.target = target player_combat_state.target = target
@@ -29,7 +29,7 @@ on :message, :magic_on_mob do |player, message|
spellbook = SPELLBOOKS[message.interface_id] spellbook = SPELLBOOKS[message.interface_id]
spell = spell_for(spellbook, message.spell_id) spell = spell_for(spellbook, message.spell_id)
player_combat_state.queue_attack(spell.attack) player_combat_state.queue_attack(spell.attack)
player.walking_queue.clear player.walking_queue.clear
player.start_action CombatAction.new(player, true) player.start_action CombatAction.new(player, true)
end end
+5 -6
View File
@@ -4,22 +4,21 @@ java_import 'org.apollo.game.model.entity.EntityType'
class CombatAction < Action class CombatAction < Action
def initialize(source, once = false) def initialize(source, once = false)
super(0, true, source) super(0, true, source)
mob.attacking = true
@combat_state = source.get_combat_state @combat_state = source.get_combat_state
@attack_timer = 100 @attack_timer = 100
@once = once @once = once
mob.attacking = true
end end
def can_attack? def can_attack?
next_attack = @combat_state.next_attack true next_attack = @combat_state.next_attack true
target = @combat_state.target target = @combat_state.target
current_distance = mob.position.get_distance target.position current_distance = mob.position.get_distance target.position
attack_collision_type = next_attack.range > 1 ? EntityType::PROJECTILE : EntityType::NPC
in_range = current_distance <= next_attack.range# && !$world.intersects(mob.position, target.position, attack_collision_type)
in_range = current_distance <= next_attack.range
in_range = in_range && !$world.intersects(mob.position, target.position,
next_attack.range > 1 ? EntityType::PROJECTILE : EntityType::NPC)
unless in_range unless in_range
mob.follow @combat_state.target, next_attack.range mob.follow @combat_state.target, next_attack.range
+6 -11
View File
@@ -1,9 +1,8 @@
class CombatSpell class CombatSpell
attr_reader :button attr_reader :button
attr_reader :spellbook attr_reader :spellbook
attr_reader :requirements attr_reader :requirements
attr_reader :damage attr_reader :damage
@@ -29,11 +28,9 @@ class CombatSpell
@projectile = projectile @projectile = projectile
@projectile_type = projectile_type @projectile_type = projectile_type
end end
end end
class CombatSpellDSL class CombatSpellDSL
def initialize(&block) def initialize(&block)
instance_eval(&block) instance_eval(&block)
end end
@@ -53,10 +50,10 @@ class CombatSpellDSL
@projectile = id @projectile = id
@projectile_type = type @projectile_type = type
end end
def requirements(&block) def requirements(&block)
fail 'Block not given' unless block_given? fail 'Block not given' unless block_given?
@requirements = AttackRequirementDSL.new(&block).requirements @requirements = AttackRequirementDSL.new(&block).requirements
end end
@@ -73,9 +70,8 @@ class CombatSpellDSL
end end
def to_combat_spell def to_combat_spell
return CombatSpell.new(@button, @spellbook, @requirements, @damage, @animation, @graphic, @hit_graphic, @projectile, @projectile_type) CombatSpell.new(@button, @spellbook, @requirements, @damage, @animation, @graphic, @hit_graphic, @projectile, @projectile_type)
end end
end end
COMBAT_SPELLS = {} COMBAT_SPELLS = {}
@@ -89,10 +85,9 @@ def create_combat_spell(name, &block)
end end
def spell_for(spellbook, button) def spell_for(spellbook, button)
COMBAT_SPELLS.each do |_name, spell|
COMBAT_SPELLS.each do |name, spell|
return spell if spell.spellbook == spellbook && spell.button == button return spell if spell.spellbook == spellbook && spell.button == button
end end
fail "Unable to find a spell in spellbook '#{spellbook}' with button id '#{button}'" fail "Unable to find a spell in spellbook '#{spellbook}' with button id '#{button}'"
end end
+3 -5
View File
@@ -2,9 +2,7 @@ java_import 'org.apollo.game.model.entity.Mob'
module MobCombatState module MobCombatState
def get_combat_state def get_combat_state
if @combat_state.nil? @combat_state = CombatState.new(self, true) if @combat_state.nil?
@combat_state = CombatState.new(self, true)
end
@combat_state @combat_state
end end
@@ -30,10 +28,10 @@ class CombatState
end end
def will_attack? def will_attack?
is_attacking? && next_attack(true).speed >= @mob.attack_timer attacking? && next_attack(true).speed >= @mob.attack_timer
end end
def is_attacking? def attacking?
!target.nil? && @mob.attacking !target.nil? && @mob.attacking
end end
+1 -1
View File
@@ -4,4 +4,4 @@ def create_spellbook(identifier, interface_id:)
SPELLBOOKS[interface_id] = identifier SPELLBOOKS[interface_id] = identifier
end end
create_spellbook :modern, interface_id: 192 create_spellbook :modern, interface_id: 192
+6 -6
View File
@@ -1,18 +1,18 @@
create_combat_spell :wind_bolt do create_combat_spell :wind_bolt do
spellbook :modern, button: 10 spellbook :modern, button: 10
max_damage 8 max_damage 8
effects animation: 1162, graphic: {id: 117, height: 100}, hit_graphic: {id: 119, delay: 100} effects animation: 1162, graphic: { id: 117, height: 100 }, hit_graphic: { id: 119, delay: 100 }
projectile id: 118, type: :bolt_spells projectile id: 118, type: :bolt_spells
requirements do requirements do
rune :air, amount: 3 rune :air, amount: 3
rune :chaos, amount: 1 rune :chaos, amount: 1
skill :magic, level: 17 skill :magic, level: 17
end end
end end
create_projectile_type :bolt_spells, start_height: 46, end_height: 36, delay: 51, speed: 12, slope: 15, radius: 86 create_projectile_type :bolt_spells, start_height: 46, end_height: 36, delay: 51, speed: 12, slope: 15, radius: 86
+1 -1
View File
@@ -8,7 +8,7 @@ class CombatUtil
strength = source.skill_set.get_skill(Skill::STRENGTH) strength = source.skill_set.get_skill(Skill::STRENGTH)
strength_stat = 5 # source.bonus_stat(:other, :strength) strength_stat = 5 # source.bonus_stat(:other, :strength)
effective_strength_damage = (strength.current_level) # * prayer_multiplier effective_strength_damage = strength.current_level # * prayer_multiplier
if [:aggressive, :alt_aggressive].include? source.combat_style if [:aggressive, :alt_aggressive].include? source.combat_style
effective_strength_damage += 3 effective_strength_damage += 3
+10 -3
View File
@@ -8,6 +8,13 @@ java_import 'org.apollo.game.model.inv.SynchronizationInventoryListener'
WEAPONS = {} WEAPONS = {}
NAMED_WEAPONS = {} NAMED_WEAPONS = {}
##
# Create a new {@code Weapon} and configure it with the Weapon DSL.
#
# @param [Symbol] identifier A unique identifier for the weapon if {@code named} is true, otherwise the item name
# of the weapon
# @param [Symbol] class_name A symbol representing the {@code WeaponClass} this weapon belongs to.
# @param [Boolean] True if this is a uniquely identified weapon, false if it belongs to an item.
def create_weapon(identifier, class_name = nil, named: false, &block) def create_weapon(identifier, class_name = nil, named: false, &block)
if named if named
@@ -52,13 +59,13 @@ def create_normal_weapon(item_matcher, class_name = nil, &block)
end end
WEAPONS[item_id] = Weapon.new(definition.name, WEAPON_CLASSES[class_name]) WEAPONS[item_id] = Weapon.new(definition.name, WEAPON_CLASSES[class_name])
WEAPONS[item_id].instance_eval &block if block_given? WEAPONS[item_id].instance_eval(&block) if block_given?
end end
end end
def create_named_weapon(name, class_name, &block) def create_named_weapon(name, class_name, &block)
NAMED_WEAPONS[name] = Weapon.new name.to_s.capitalize, WEAPON_CLASSES[class_name] NAMED_WEAPONS[name] = Weapon.new name.to_s.capitalize, WEAPON_CLASSES[class_name]
NAMED_WEAPONS[name].instance_eval &block if block_given? NAMED_WEAPONS[name].instance_eval(&block) if block_given?
end end
# Represents an equippable weapon, and the class it belongs to. # Represents an equippable weapon, and the class it belongs to.
@@ -87,7 +94,7 @@ class Weapon
attack_dsl.animation = animation attack_dsl.animation = animation
attack_dsl.graphic = graphic attack_dsl.graphic = graphic
attack_dsl.add_requirement SpecialEnergyRequirement.new(energy_requirement) attack_dsl.add_requirement SpecialEnergyRequirement.new(energy_requirement)
attack_dsl.instance_eval &block attack_dsl.instance_eval(&block)
@special_attack = attack_dsl.to_attack @special_attack = attack_dsl.to_attack
end end
+6 -5
View File
@@ -88,12 +88,12 @@ class WeaponClass
def style(style, properties = {}, &block) def style(style, properties = {}, &block)
fail 'Invalid combat style given' unless COMBAT_STYLES.include? style fail 'Invalid combat style given' unless COMBAT_STYLES.include? style
properties = @defaults.merge properties properties = @defaults.merge properties
## The config ID used to set the active combat style, typically 0-3. TODO: does this always work? ## The config ID used to set the active combat style, typically 0-3. TODO: does this always work?
config = @styles.size config = @styles.size
button, attack_type, block_animation = properties[:button], properties[:attack_type], properties[:block_animation] button, attack_type, block_animation = properties[:button], properties[:attack_type], properties[:block_animation]
@styles[style] = CombatStyle.new(button, config, attack_type, block_animation) @styles[style] = CombatStyle.new(button, config, attack_type, block_animation)
if block_given? if block_given?
@@ -102,7 +102,7 @@ class WeaponClass
attack_dsl.graphic = properties[:graphic] attack_dsl.graphic = properties[:graphic]
attack_dsl.animation = properties[:animation] attack_dsl.animation = properties[:animation]
attack_dsl.range = properties[:range] attack_dsl.range = properties[:range]
properties[:requirements].each {|requirement| attack_dsl.add_requirement requirement } properties[:requirements].each { |requirement| attack_dsl.add_requirement requirement }
attack_dsl.instance_eval &block attack_dsl.instance_eval &block
@styles[style].attack = attack_dsl.to_attack @styles[style].attack = attack_dsl.to_attack
@@ -111,7 +111,7 @@ class WeaponClass
return unless @styles[style].attack.nil? return unless @styles[style].attack.nil?
## Get rid of any properties which aren't included in the keyword argument list ## Get rid of any properties which aren't included in the keyword argument list
properties.delete_if {|key| ![:speed, :animation, :range, :requirements, :graphic].include? key } properties.delete_if { |key| ![:speed, :animation, :range, :requirements, :graphic].include? key }
if @type == :melee if @type == :melee
@styles[style].attack = Attack.new(properties) @styles[style].attack = Attack.new(properties)
@@ -157,7 +157,8 @@ class WeaponClass
end end
## ##
# Set the character animations associated with this weapon class.
def animations(stand: nil, walk: nil, run: nil, idle_turn: nil, turn_around: nil, turn_left: nil, turn_right: nil) def animations(stand: nil, walk: nil, run: nil, idle_turn: nil, turn_around: nil, turn_left: nil, turn_right: nil)
@animations = { @animations = {
stand: stand, stand: stand,
+2 -2
View File
@@ -29,9 +29,9 @@ create_weapon_class :dragon_dagger, widget: DAGGER_WIDGET_ID do
style :defensive, button: 5 style :defensive, button: 5
end end
create_weapon /(?:drag|dragon) dagger.*/, :dragon_dagger do create_weapon(/(?:drag|dragon) dagger.*/, :dragon_dagger) do
set_special_attack speed: 4, energy_requirement: 25, animation: 1062, graphic: { id: 252, height: 100 } do set_special_attack speed: 4, energy_requirement: 25, animation: 1062, graphic: { id: 252, height: 100 } do
damage! damage!
damage! secondary: true damage! secondary: true
end end
end end
@@ -25,7 +25,7 @@ create_weapon :steel_scimitar do
other_bonuses melee_strength: 14 other_bonuses melee_strength: 14
end end
create_weapon /(black|white) scimitar/ do create_weapon(/(black|white) scimitar/) do
attack_bonuses stab: 4, slash: 19 attack_bonuses stab: 4, slash: 19
other_bonuses melee_strength: 14 other_bonuses melee_strength: 14
end end
@@ -6,7 +6,8 @@ create_weapon_class :two_handed_sword, widget: TWO_HANDED_SWORD_WIDGET_ID do
defaults speed: 7, animation: 7041, attack_type: :slash defaults speed: 7, animation: 7041, attack_type: :slash
special_bar TWO_HANDED_SWORD_SPECIAL_CONFIG_ID, TWO_HANDED_SWORD_SPECIAL_BUTTON_ID special_bar TWO_HANDED_SWORD_SPECIAL_CONFIG_ID, TWO_HANDED_SWORD_SPECIAL_BUTTON_ID
animations stand: 7047, walk: 7046, run: 7039, idle_turn: 7044, turn_around: 7044, turn_left: 7043, turn_right: 7044 animations stand: 7047, walk: 7046, run: 7039, idle_turn: 7044, turn_around: 7044,
turn_left: 7043, turn_right: 7044
attack_bonuses stab: -4, magic: -4 attack_bonuses stab: -4, magic: -4
defence_bonuses range: -1 defence_bonuses range: -1
@@ -27,7 +28,7 @@ create_weapon :steel_2h_sword do
other_bonuses melee_strength: 22 other_bonuses melee_strength: 22
end end
create_weapon /(?:black|white) 2h sword/ do create_weapon(/(?:black|white) 2h sword/) do
attack_bonuses slash: 27, crush: 21 attack_bonuses slash: 27, crush: 21
other_bonuses melee_strength: 26 other_bonuses melee_strength: 26
end end
@@ -8,4 +8,4 @@ create_weapon_class :crossbow, widget: CROSSBOW_WIDGET_ID, type: :ranged do
style :long_range, range: 9, button: 4 style :long_range, range: 9, button: 4
end end
create_weapon /rune c'bow/, :crossbow create_weapon(/rune c'bow/, :crossbow)