diff --git a/data/plugins/combat/attack.rb b/data/plugins/combat/attack.rb new file mode 100644 index 00000000..dac67141 --- /dev/null +++ b/data/plugins/combat/attack.rb @@ -0,0 +1,88 @@ +java_import 'org.apollo.cache.def.ItemDefinition' +java_import 'org.apollo.game.model.Animation' +java_import 'org.apollo.game.model.Graphic' + +class BaseAttack + attr_reader :requirements, :range + + def initialize(animation, graphic = nil, range = 1, requirements = []) + @animation = animation + @graphic = graphic + @range = range + @requirements = requirements + end + + def do(source, target) + source.play_animation(Animation.new(@animation)) + + unless @graphic.nil? + if @graphic.is_a?(Hash) + source.play_graphic(Graphic.new(@graphic[:id], @graphic[:delay] || 0, @graphic[:height] | 0)) + else + source.play_graphic(Graphic.new(@graphic)) + end + end + + apply(source, target) + end + + def apply(source, target) + raise "BaseAttack#apply unimplemented" + end + + def damage!(source, target, amount, delay = 0) + schedule delay do |task| + task.stop && return if source.dead or target.dead + + target_combat_state = get_combat_state target + target_hitpoints = target.skill_set.get_skill(Skill::HITPOINTS).get_current_level + amount = target_hitpoints if target_hitpoints < amount + + type = amount > 0 ? 1 : 0 + target.play_animation(Animation.new(424)) unless target_combat_state.state == :attacking + target.damage(amount, type, false) + + task.stop + end + end +end + +class ProcAttack < BaseAttack + def initialize(block, animation:, graphic:, range: 1, requirements: []) + super(animation, graphic, range, requirements) + + @block = block + end + + def apply(source, target) + self.instance_exec(source, target, &@block) + end +end + +class RangedAttack < BaseAttack + def initialize(animation:, graphic:, requirements: []) + + end + + def calculate_delay(source, target) + + end + + def apply(source, target) + + end + + def projectile!(source, target, projectile_id) + + end +end + +class Attack < BaseAttack + def initialize(animation:, graphic: nil, range: 1, requirements: []) + super(animation, graphic, range, requirements) + end + + def apply(source, target) + damage! source, target, CombatUtil::calculate_hit(source, target) + end +end diff --git a/data/plugins/combat/attack_requirements.rb b/data/plugins/combat/attack_requirements.rb new file mode 100644 index 00000000..9c2fe1c6 --- /dev/null +++ b/data/plugins/combat/attack_requirements.rb @@ -0,0 +1,56 @@ +java_import 'org.apollo.cache.def.ItemDefinition' + +class AttackRequirementException < Exception + attr_reader :message + + def initialize(message) + @message = message + end +end + +class AttackRequirement + def validate!(player) + throw RuntimeError.new('validate! not implemented') + end + + def apply(player) + throw RuntimeError.new('apply not implemented') + end +end + +class SpecialEnergyRequirement < AttackRequirement + def initialize(amount) + @amount = amount + end + + def validate!(player) + throw AttackRequirementException.new('Not enough special attack energy.') unless player.special_energy >= @amount + end + + def apply(player) + player.special_energy = player.special_energy - @amount + end +end + +class ItemRequirement < AttackRequirement + def initialize(item, amount) + @item = item + @amount = amount + end + + def validate!(player) + throw AttackRequirementException.new(item_missing_message) unless player.inventory.get_amount(@item) >= @amount + end + + def apply(player) + player.inventory.remove(@item, @amount) + end + + private + + def item_missing_message + definition = ItemDefinition.lookup(@item) + + "You don't have enough #{lookup_item(@item).name}s" + end +end diff --git a/data/plugins/combat/attributes.rb b/data/plugins/combat/attributes.rb new file mode 100644 index 00000000..2b0bcd07 --- /dev/null +++ b/data/plugins/combat/attributes.rb @@ -0,0 +1,29 @@ +module CombatModule + ## + # The delay a Mob must wait before attacking again. + declare_attribute(:attack_delay, 0) + + ## + # A flag indicating whether this Mob is currently in combat. + declare_attribute(:attacking, false) + + ## + # A flag indicating whether our Mob is dead. + declare_attribute(:dead, false) + + ## + # The amount of ticks a Player must wait before logging out after combat. + declare_attribute(:logout_timer, Time.now.to_i) + + ## + # The CombatStyle offset that a Mob is currently using. + declare_attribute(:combat_style, 0, :persistent) + + ## + # A flag indicating whether the special bar is flagged for the next attack. + declare_attribute(:using_special, false, :persistent) + + ## + # An integer between 0 and 100 indicating the amount of special energy a Player has. + declare_attribute(:special_energy, 100, :persistent) +end \ No newline at end of file diff --git a/data/plugins/combat/bonuses.rb b/data/plugins/combat/bonuses.rb new file mode 100644 index 00000000..e13ee709 --- /dev/null +++ b/data/plugins/combat/bonuses.rb @@ -0,0 +1,44 @@ +module Combat + # A module for units which can have their own bonuses. E.G., weapons, equipment, ammo. + module BonusContainer + def attack_bonus(type) + @attack_bonuses[type] + end + + def defence_bonus(type) + @defence_bonuses[type] + end + + def other_bonus(type) + @other_bonuses[type] + end + + def other_bonuses(melee_strength: 0, ranged_strength: 0, prayer: 0) + @other_bonuses = { + :melee_strength => melee_strength, + :ranged_strength => ranged_strength, + :prayer => prayer + } + end + + def defence_bonuses(stab: 0, slash: 0, crush: 0, magic: 0, range: 0) + @defence_bonuses = { + :stab => stab, + :slash => slash, + :crush => crush, + :magic => magic, + :range => range + } + end + + def attack_bonuses(stab: 0, slash: 0, crush: 0, magic: 0, range: 0) + @attack_bonuses = { + :stab => stab, + :slash => slash, + :crush => crush, + :magic => magic, + :range => range + } + end + end +end \ No newline at end of file diff --git a/data/plugins/combat/combat.rb b/data/plugins/combat/combat.rb new file mode 100644 index 00000000..6cf9ead0 --- /dev/null +++ b/data/plugins/combat/combat.rb @@ -0,0 +1,12 @@ +on :message, :npc_action do |player, message| + player_combat_state = get_combat_state player + player_combat_state.target = $world.npc_repository.get message.index + + unless player.attacking + player.start_action CombatAction.new(player) + end +end + +on :message, :player_action do |player, message| + +end \ No newline at end of file diff --git a/data/plugins/combat/combat_action.rb b/data/plugins/combat/combat_action.rb new file mode 100644 index 00000000..b886a8ce --- /dev/null +++ b/data/plugins/combat/combat_action.rb @@ -0,0 +1,106 @@ +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 \ No newline at end of file diff --git a/data/plugins/combat/combat_state.rb b/data/plugins/combat/combat_state.rb new file mode 100644 index 00000000..8bc0f025 --- /dev/null +++ b/data/plugins/combat/combat_state.rb @@ -0,0 +1,49 @@ +def get_combat_state(mob) + mob.is_a?(Player) ? type = :player : type = :npc + + unless MOB_COMBAT_STATE_CACHE[type].has_key? mob.index + MOB_COMBAT_STATE_CACHE[type][mob.index] = CombatState.new(mob) + end + + MOB_COMBAT_STATE_CACHE[type][mob.index] +end + +private + +class CombatState + attr_accessor :state, :next_attack + attr_reader :queued_attacks, :supports_weapon + + def initialize(mob, supports_weapon = true) + @mob = mob + @supports_weapon = supports_weapon + reset + end + + def reset + @state = :idle + @target = nil + @next_attack = nil + @queued_attacks = [] + @mob.reset_interacting_mob + end + + def target + @target + end + + def target=(target) + @mob.reset_interacting_mob + @mob.interacting_mob = target + @target = target + end + + def queue_attack(attack) + @queued_attacks.push(attack) + end +end + +MOB_COMBAT_STATE_CACHE = { + :player => {}, + :npc => {} +} diff --git a/data/plugins/combat/equipment.rb b/data/plugins/combat/equipment.rb new file mode 100644 index 00000000..cfec43f3 --- /dev/null +++ b/data/plugins/combat/equipment.rb @@ -0,0 +1,18 @@ +java_import 'org.apollo.cache.def.EquipmentDefinition' + +EQUIPMENT = {} + +def create_equipment(item, &block) + equipment = Equipment.new + equipment.instance_eval block + + find_entities :item, item do |equipment_item| + EQUIPMENT[id] = equipment + end +end + +private + +class Equipment + include Combat::BonusContainer +end \ No newline at end of file diff --git a/data/plugins/combat/plugin.xml b/data/plugins/combat/plugin.xml index b236b6b2..a05b0548 100644 --- a/data/plugins/combat/plugin.xml +++ b/data/plugins/combat/plugin.xml @@ -1,17 +1,36 @@ - combat - 1 - Combat - Manages combat between game characters. - - Ryley - - - - - - attributes - areas - + combat + 0.1 + combat + Adds fully functioning melee, ranged and magic combat. + + garyttierney + + + + + + + + + + + + + + + + + + + + + + + + + attributes + util + diff --git a/data/plugins/combat/projectile.rb b/data/plugins/combat/projectile.rb new file mode 100644 index 00000000..d740e2d8 --- /dev/null +++ b/data/plugins/combat/projectile.rb @@ -0,0 +1,3 @@ +def create_projectile(item, drop_rate:, graphic:, projectile:) + items = i +end \ No newline at end of file diff --git a/data/plugins/combat/util.rb b/data/plugins/combat/util.rb new file mode 100644 index 00000000..d41caf17 --- /dev/null +++ b/data/plugins/combat/util.rb @@ -0,0 +1,70 @@ +java_import 'org.apollo.game.model.entity.EquipmentConstants' + +class CombatUtil + + def self.calculate_max_hit(source) + strength = source.skill_set.get_skill(Skill::STRENGTH) + strength_stat = 5 #source.bonus_stat(:other, :strength) + + effective_strength_damage = (strength.current_level) #* prayer_multiplier + + if [:aggressive, :alt_aggressive].include? source.combat_style + effective_strength_damage += 3 + end + + (1.3 + (effective_strength_damage / 10) + (strength_stat / 80) + + ((effective_strength_damage * strength_stat) / 640)) + end + + def self.calculate_accuracy(source, target) + weapon = EquipmentUtil.equipped_weapon source + weapon_class = weapon.weapon_class + combat_style = weapon_class.style_at source.combat_style + attack_type = weapon.weapon_class.attack_type combat_style + + attack_stat = [1, 1].max + defence_stat = [1, 1].max + + attack = source.skill_set.get_skill(Skill::ATTACK).current_level.to_f + defence = target.skill_set.get_skill(Skill::DEFENCE).current_level.to_f + + attack_prayer_multiplier = 1 #TODO: Prayer + attack_accuracy = attack_stat * attack * attack_prayer_multiplier + attack_accuracy = 0.1 if attack_accuracy < 0 + + defence_prayer_multiplier = 1 #TODO: Prayer + defence_accuracy = defence_stat * defence * defence_prayer_multiplier + defence_accuracy = 1 if defence_accuracy < 0 + + base = attack_accuracy / defence_accuracy + base > 1 ? 0.9 : base * 0.9 + end + + # Calculates a hit for the given Mob and special attack flag. + def self.calculate_hit(source, target) + accuracy = calculate_accuracy source, target + max_hit = calculate_max_hit(source) + 1 + + if rand <= accuracy + return rand(max_hit) + else + return 0 + end + end +end + +class EquipmentUtil + def self.equipped_weapon(source) + item = source.equipment.get(EquipmentConstants::WEAPON) + + if item.nil? + return NAMED_WEAPONS[:no_weapon] + end + + WEAPONS[item.id] + end + + def self.equipped_projectile(source) + item = source.equipment.get(EquipmentConstants::ARROWS) + end +end \ No newline at end of file diff --git a/data/plugins/combat/weapon.rb b/data/plugins/combat/weapon.rb new file mode 100644 index 00000000..428efe52 --- /dev/null +++ b/data/plugins/combat/weapon.rb @@ -0,0 +1,135 @@ +java_import 'org.apollo.cache.def.ItemDefinition' +java_import 'org.apollo.game.model.inv.InventoryAdapter' +java_import 'org.apollo.game.model.entity.EquipmentConstants' +java_import 'org.apollo.game.model.entity.AnimationSet' +java_import 'org.apollo.game.model.Animation' +java_import 'org.apollo.game.model.inv.SynchronizationInventoryListener' + +WEAPONS = {} +NAMED_WEAPONS = {} + +COMBAT_STYLES = [ + :accurate, + :aggressive, + :defensive, + :controlled, + :alt_aggressive +] + +def create_weapon(identifier, class_name = nil, named: false, &block) + if named + create_named_weapon(identifier, class_name, &block) + else + create_normal_weapon(identifier, class_name, &block) + end +end + + +private + +def create_normal_weapon(item_matcher, class_name = nil, &block) + items = find_entities :item, item_matcher.to_s.gsub(/_/, ' '), -1 + items.each do |item_id| + definition = ItemDefinition.lookup(item_id) + definition_name = definition.name.downcase.to_s + + if class_name.nil? + class_name = + case definition_name + when /[a-zA-Z]+ 2h sword/ + :two_handed_sword + when /[a-zA-Z]+ scimitar/ + :scimitar + else + raise "Couldn't find a suitable weapon class for the given weapon." + end + end + + WEAPONS[item_id] = Weapon.new(WEAPON_CLASSES[class_name]) + WEAPONS[item_id].instance_eval &block + end +end + +def create_named_weapon(name, class_name, &block) + NAMED_WEAPONS[name] = Weapon.new WEAPON_CLASSES[class_name] + NAMED_WEAPONS[name].instance_eval &block +end + +# Represents an equippable weapon, and the class it belongs to. +# +# * has an optional special_attack +# * belongs to a certain WeaponClass, and inherits bonuses from it. +class Weapon + attr_reader :weapon_class, :special_attack + + include Combat::BonusContainer + + def initialize(weapon_class) + @weapon_class = weapon_class + @special_attack = nil + end + + def special_attack? + not special_attack.nil? + end + + def set_special_attack(energy_requirement:, animation:, graphic: nil, &block) + + end +end + + +def update_weapon_animations(player) + default_animations = AnimationSet::DEFAULT_ANIMATION_SET + player_animations = player.animation_set + + player_animations.stand = default_animations.stand + player_animations.walking = default_animations.walking + player_animations.running = default_animations.running + player_animations.idle_turn = default_animations.idle_turn + player_animations.turn_around = default_animations.turn_around + player_animations.turn_left = default_animations.turn_left + player_animations.turn_right = default_animations.turn_right + + weapon = EquipmentUtil.equipped_weapon(player) + weapon_class = weapon.weapon_class + + [:stand, :walk, :run, :idle_turn, :turn_around, :turn_left, :turn_right].each do |key| + animation = weapon_class.other_animation(key) + puts animation + + puts key + unless animation.nil? + case key + when :stand + player_animations.stand = animation + when :walk + player_animations.walking = animation + when :run + player_animations.running = animation + when :idle_turn + player_animations.idle_turn = animation + when :turn_around + player_animations.turn_around = animation + when :turn_left + player_animations.turn_left = animation + when :turn_right + player_animations.turn_right = animation + else + # type code here + end + end + end +end + +on :message, :item_option do |player, message| + update_weapon_animations(player) if message.option == 2 and message.interface_id == SynchronizationInventoryListener::INVENTORY_ID +end + +on :login do |event| + update_weapon_animations(event.player) +end + +on :message, :item_action do |player, message| + update_weapon_animations(player) if message.interface_id == SynchronizationInventoryListener::EQUIPMENT_ID and message.slot == EquipmentConstants::WEAPON +end diff --git a/data/plugins/combat/weapon_class.rb b/data/plugins/combat/weapon_class.rb new file mode 100644 index 00000000..c427644a --- /dev/null +++ b/data/plugins/combat/weapon_class.rb @@ -0,0 +1,119 @@ +COMBAT_STYLES = [ + :accurate, + :aggressive, + :defensive, + :controlled, + :alt_aggressive, + :accurate_ranged, + :rapid, + :long_range +] + +MELEE_COMBAT_STYLES = [ + :accurate, + :aggressive, + :alt_aggressive, + :controlled, + :defensive +] + +RANGE_COMBAT_STYLES = [ + :accurate_ranged, + :rapid, + :long_range +] + +class WeaponClass + attr_reader :widget, :name + + include Combat::BonusContainer + + def initialize(name, widget) + @name = name + @widget = widget + @styles = {} + @style_attacks = {} + @style_offsets = [] + @animations = {} + end + + def add_style(style, attack_type: nil, speed: nil, animation: nil, block_animation: nil, range: 1) + raise 'Invalid combat style given' unless COMBAT_STYLES.include? style + + @styles[style] = { + :attack_type => attack_type, + :speed => speed, + :animation => animation, + :block_animation => block_animation, + :range => range + } + + @style_offsets.push style + + if MELEE_COMBAT_STYLES.include? style + @style_attacks[style] = Attack.new(animation: animation) + end + end + + def attack(style) + @style_attacks[style] + end + + def attack_type(style) + @styles[style][:attack_type] + end + + def block_animation(style) + @styles[style][:block_animation] + end + + def other_animation(type) + @animations[type] + end + + def speed(style) + @styles[style][:speed] || default_speed + end + + def style_at(offset) + @style_offsets[offset] + end + + def default_speed(speed = nil) + unless speed.nil? + @default_speed = speed + end + + @default_speed + end + + def special_bar(id = nil) + unless id.nil? + @special_bar = id + end + + @special_bar + end + + def animations(stand: nil, walk: nil, run: nil, idle_turn: nil, turn_around: nil, turn_left: nil, turn_right: nil) + @animations = { + :stand => stand, + :walk => walk, + :run => run, + :idle_turn => idle_turn, + :turn_around => turn_around, + :turn_left => turn_left, + :turn_right => turn_right + } + end +end + +WEAPON_CLASSES = {} +WEAPON_CLASS_INTERFACE_MAP = {} + +def create_weapon_class(name, widget:, &block) + weapon_class = WeaponClass.new(name, widget) + weapon_class.instance_eval &block + + WEAPON_CLASSES[name.to_sym] = weapon_class +end diff --git a/data/plugins/combat/weapons/bows.rb b/data/plugins/combat/weapons/bows.rb new file mode 100644 index 00000000..b2f242ed --- /dev/null +++ b/data/plugins/combat/weapons/bows.rb @@ -0,0 +1,20 @@ +BOW_WIDGET_ID = 10 +BOW_SPECIAL_BAR_ID = 10 +# +# create_weapon_class :longbow, widget: BOW_WIDGET_ID do +# special_bar = BOW_SPECIAL_BAR_ID +# +# +# add_style :accurate, speed: 6, range: 7 +# add_style :rapid, speed: 6, range: 7 +# add_style :long_range, speed: 6, range: 9 +# end +# +# create_weapon_class :shortbow, widget: BOW_WIDGET_ID do +# special_bar = BOW_SPECIAL_BAR_ID +# +# add_style :accurate, speed: 4, range: 7 +# add_style :rapid, speed: 3, range: 7 +# add_style :long_range, speed: 4, range: 9 +# end +# diff --git a/data/plugins/combat/weapons/daggers.rb b/data/plugins/combat/weapons/daggers.rb new file mode 100644 index 00000000..e69de29b diff --git a/data/plugins/combat/weapons/scimitars.rb b/data/plugins/combat/weapons/scimitars.rb new file mode 100644 index 00000000..74e94692 --- /dev/null +++ b/data/plugins/combat/weapons/scimitars.rb @@ -0,0 +1,50 @@ +SCIMITAR_WIDGET_ID = 81 +SCIMITAR_SPECIAL_BAR_ID = 21 + +create_weapon_class :scimitar, widget: SCIMITAR_WIDGET_ID do + default_speed 4 + special_bar SCIMITAR_SPECIAL_BAR_ID + + attack_bonuses crush: -2 + defence_bonuses slash: -1 + + add_style :accurate, attack_type: :slash, animation: 390 + add_style :aggressive, attack_type: :slash, animation: 390 + add_style :alt_aggressive, attack_type: :stab, animation: 391 + add_style :defensive, attack_type: :slash, animation: 390 +end + +create_weapon :iron_scimitar do + attack_bonuses stab: 2, slash: 10 + other_bonuses melee_strength: 9 +end + +create_weapon :steel_scimitar do + attack_bonuses stab: 3, slash: 15 + other_bonuses melee_strength: 14 +end + +create_weapon /(black|white) scimitar/ do + attack_bonuses stab: 4, slash: 19 + other_bonuses melee_strength: 14 +end + +create_weapon :mithril_scimitar do + attack_bonuses stab: 5, slash: 21 + other_bonuses melee_strength: 20 +end + +create_weapon :adamant_scimitar do + attack_bonuses stab: 6, slash: 29 + other_bonuses melee_strength: 28 +end + +create_weapon :rune_scimitar do + attack_bonuses stab: 7, slash: 45 + other_bonuses melee_strength: 44 +end + +create_weapon :dragon_scimitar do + attack_bonuses :stab => 8, slash: 67 + other_bonuses melee_strength: 66 +end diff --git a/data/plugins/combat/weapons/swords.rb b/data/plugins/combat/weapons/swords.rb new file mode 100644 index 00000000..e69de29b diff --git a/data/plugins/combat/weapons/two_handed_swords.rb b/data/plugins/combat/weapons/two_handed_swords.rb new file mode 100644 index 00000000..a70efb1a --- /dev/null +++ b/data/plugins/combat/weapons/two_handed_swords.rb @@ -0,0 +1,52 @@ +TWO_HANDED_SWORD_WIDGET_ID = 82 +TWO_HANDED_SWORD_SPECIAL_ID = 12 + +create_weapon_class :two_handed_sword, widget: TWO_HANDED_SWORD_WIDGET_ID do + default_speed 7 + special_bar TWO_HANDED_SWORD_SPECIAL_ID + + 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 + defence_bonuses range: -1 + + add_style :accurate, attack_type: :slash, animation: 7041 + add_style :aggressive, attack_type: :crush, animation: 7041 + add_style :alt_aggressive, attack_type: :crush, animation: 7048 + add_style :defensive, attack_type: :slash, animation: 7049 +end + +create_weapon :iron_2h_sword do + attack_bonuses slash: 13, crush: 10 + other_bonuses melee_strength: 14 +end + +create_weapon :steel_2h_sword do + attack_bonuses slash: 21, crush: 16 + other_bonuses melee_strength: 22 +end + +create_weapon /(?:black|white) 2h sword/ do + attack_bonuses slash: 27, crush: 21 + other_bonuses melee_strength: 26 +end + +create_weapon :mithril_2h_sword do + attack_bonuses slash: 30, crush: 24 + other_bonuses melee_strength: 26 +end + +create_weapon :adamant_2h_sword do + attack_bonuses slash: 43, crush: 30 + other_bonuses melee_strength: 31 +end + +create_weapon :rune_2h_sword do + attack_bonuses slash: 69, crush: 50 + other_bonuses melee_strength: 70 +end + +create_weapon :dragon_2h_sword do + attack_bonuses slash: 92, crush: 80 + other_bonuses melee_strength: 70 +end \ No newline at end of file diff --git a/data/plugins/combat/weapons/unarmed.rb b/data/plugins/combat/weapons/unarmed.rb new file mode 100644 index 00000000..db15a953 --- /dev/null +++ b/data/plugins/combat/weapons/unarmed.rb @@ -0,0 +1,11 @@ +create_weapon_class :unarmed, widget: -1 do + default_speed 4 + + add_style :accurate, animation: 422, block_animation: 424 + add_style :aggressive, animation: 423, block_animation: 424 + add_style :defensive, animation: 422, block_animation: 424 +end + +create_weapon :no_weapon, :unarmed, named: true do + # Todo factor out empty blocks +end \ No newline at end of file diff --git a/data/plugins/combat/widgets/special_bar.rb b/data/plugins/combat/widgets/special_bar.rb new file mode 100644 index 00000000..e69de29b diff --git a/data/plugins/combat/wilderness.rb b/data/plugins/combat/wilderness.rb deleted file mode 100644 index e62989e4..00000000 --- a/data/plugins/combat/wilderness.rb +++ /dev/null @@ -1,66 +0,0 @@ -require 'java' - -java_import 'org.apollo.game.model.entity.Player' -java_import 'org.apollo.game.message.impl.SetWidgetTextMessage' -java_import 'org.apollo.game.message.impl.OpenOverlayMessage' - -declare_attribute(:wilderness_level, 0, :transient) - -# Constants constants related to the wilderness -module WildernessConstants - - # The wilderness level overlay interface id - OVERLAY_INTERFACE_ID = 197 - - # The wilderness level string id - LEVEL_STRING_ID = 199 - -end - -# Determines the wilderness level for the specified position -def wilderness_level(position) - ((position.y - 3520) / 8).ceil + 1 -end - -area_action :wilderness_level do - on_entry do |player, position| - player.wilderness_level = wilderness_level(position) - player.interface_set.open_overlay(WildernessConstants::OVERLAY_INTERFACE_ID) - - id = WildernessConstants::LEVEL_STRING_ID - player.send(SetWidgetTextMessage.new(id, "Level: #{player.wilderness_level}")) - show_action(player, ATTACK_ACTION) - end - - while_in do |player, position| - current = player.wilderness_level - updated = wilderness_level(position) - - if current != updated - player.wilderness_level = updated - - id = WildernessConstants::LEVEL_STRING_ID - player.send(SetWidgetTextMessage.new(id, "Level: #{player.wilderness_level}")) - end - end - - on_exit do |player, position| - player.wilderness_level = 0 - player.interface_set.close - - player.send(OpenOverlayMessage.new(-1)) - hide_action(player, ATTACK_ACTION) - end -end - -# Monkey patch the existing player class to add method of checking whether or not a player is -# within the wilderness -class Player - - def in_wilderness - wilderness_level > 0 - end - -end - -area name: :wilderness, coordinates: [2945, 3522, 3390, 3972, 0], actions: :wilderness_level