Recursive plugin loading.

This commit is contained in:
Nikki
2014-05-01 13:37:44 -04:00
parent 1561e56c82
commit 9a7210deb1
50 changed files with 38 additions and 6 deletions
+90
View File
@@ -0,0 +1,90 @@
require 'java'
java_import 'org.apollo.game.action.Action'
# A herb is an ingredient that requires identification before being used.
class Herb < Ingredient
include HerbloreMethod
attr_reader :unidentified, :level, :experience
def initialize(item_id, unidentified, level, experience)
super item_id
@unidentified = unidentified
@level = level
@experience = experience
end
def invoke(player, id, slot)
item = player.inventory.get(slot)
player.start_action(HerbIdentificationAction.new(player, self, slot, item))
end
end
# An action that makes a player identify a herb.
class HerbIdentificationAction < Action
attr_reader :herb, :slot, :item, :pulses
def initialize(player, herb, slot, item)
super(0, true, player)
@herb = herb
@slot = slot
@item = item
@pulses = 0
end
def execute
if @pulses == 0
unless check_skill(mob, @herb.level, "identify this herb")
stop
return
end
end
execute_action
@pulses += 1
end
def execute_action
player = mob
inventory = player.inventory
if inventory.remove_slot(@slot, 1) == 1
identified = @herb.item
inventory.add(identified)
player.skill_set.add_experience(HERBLORE_ID, @herb.experience)
player.send_message("You identify the herb as a #{identified.definition.name}.", true)
end
stop
end
def equals(other)
return (get_class == other.get_class and slot == other.slot and herb == other.herb)
end
end
# Appends a herb to the InventoryItemEvent interception.
def append_herb(item_id, unidentified, level, experience)
herb = Herb.new(item_id, unidentified, level, experience)
append_herblore_item(herb, unidentified)
return herb
end
# Herbs
GUAM_LEAF = append_herb(249, 199, 1, 2.5) # 3, 2.5
MARRENTILL = append_herb(251, 201, 5, 3.8)
TARROMIN = append_herb(253, 203, 11, 5)
HARRALANDER = append_herb(255, 205, 20, 6.3)
RANARR = append_herb(257, 207, 25, 7.5)
TOADFLAX = append_herb(2998, 3049, 30, 8)
IRIT_LEAF = append_herb(259, 209, 40, 8.8)
AVANTOE = append_herb(261, 211, 48, 10)
KWUARM = append_herb(263, 213, 54, 11.3)
SNAPDRAGON = append_herb(3000, 3051, 59, 11.8)
CADANTINE = append_herb(265, 215, 65, 12.5)
LANTADYME = append_herb(2481, 2485, 67, 13.1)
DWARF_WEED = append_herb(267, 217, 70, 13.8)
TORSTOL = append_herb(269, 219, 75, 15)
+101
View File
@@ -0,0 +1,101 @@
# Thanks to Sillhouette <http://www.rune-server.org/members/silhouette/> for posting
# a large amount of Herblore skill data which has been thankfully used in this plugin.
require 'java'
java_import 'org.apollo.game.event.impl.SetWidgetItemModelEvent'
java_import 'org.apollo.game.model.Skill'
HERBLORE_DIALOGUE = 4429
HERBLORE_ITEM = {}
HERBLORE_ITEM_ON_ITEM = {}
DRINK_ITEM = {}
# A module which describes an invocable method of the Herblore skill.
module HerbloreMethod
def self.new
raise 'You cannot instantiate this module!'
end
def invoke(player, primary, secondary)
raise NotImplementedError.new('You must implement the invocation of HerbloreMethod!')
end
end
# The ItemOnItemEvent handler for all Herblore-related functions.
on :event, :item_on_item do |ctx, player, event|
primary = event.id
secondary = event.target_id
hash = HERBLORE_ITEM_ON_ITEM[primary]
if hash == nil
secondary = event.id
primary = event.target_id
hash = HERBLORE_ITEM_ON_ITEM[primary]
end
if hash != nil
method = hash[secondary]
if method != nil
method.invoke(player, primary, secondary)
ctx.break_handler_chain
end
end
end
# The ItemOptionEvent handler for all Herblore-related functions.
on :event, :item_option do |ctx, player, event|
if event.option == 1
id = event.id
method = HERBLORE_ITEM[id]
if method != nil
method.invoke(player, id, event.slot)
ctx.break_handler_chain
end
method = DRINK_ITEM[id]
if method != nil
method.invoke(player, id, event.slot)
ctx.break_handler_chain
end
end
end
# Utility for adding the various Herblore methods to the handled constant arrays.
def append_herblore_item(method, key, secondary = -1)
if secondary == -1
HERBLORE_ITEM[key] = method
else
hash = HERBLORE_ITEM_ON_ITEM[key]
hash = {} if hash == nil
hash[secondary] = method
HERBLORE_ITEM_ON_ITEM[key] = hash
end
end
# Utility method for checking if a player's inventory has an item of the specified id, with optionally the specified amount (1 by default), at the specified slot.
def check_slot(player, slot, id, amount = 1)
item = player.inventory.get(slot)
return (item != nil and item.id == id and item.amount >= amount)
end
# Utility method for checking if a player's Herblore (maximum) level is at a required height. Also informs the player if this is not the case with use of the action
# variable, like so: "You need a Herblore level of at least #{required.to_s} to #{action}."
def check_skill(player, required, action)
if required > player.skill_set.skill(HERBLORE_SKILL_ID).current_level
player.send_message("You need a Herblore level of at least #{required} to #{action}.")
return false
end
return true
end
# Opens a 'make' dialogue for the specified player, displaying the specified item. Optionally, a listener can be used for the dialogue.
def open_dialogue(player, item, listener = nil)
player.send(SetWidgetItemModelEvent.new(1746, item, 170))
player.interface_set.open_dialogue(listener, HERBLORE_DIALOGUE)
end
+255
View File
@@ -0,0 +1,255 @@
require 'java'
java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Item'
java_import 'org.apollo.game.model.def.ItemDefinition'
java_import 'org.apollo.game.model.inter.EnterAmountListener'
java_import 'org.apollo.game.model.inter.dialogue.DialogueAdapter'
GRINDING_ANIM = Animation.new(364)
PESTLE_MORTAR = 233
# An ingredient which can be used for making (unfinished) potions.
class Ingredient
attr_reader :item_id, :item
def initialize(item)
@item_id = item
@item = Item.new(item) # Share item instances.
end
# Checks if the specified player has the specified amount of this ingredient. Optionally, they can immediately be removed if that
# amount was indeed found.
def check_remove(player, amount, remove)
inventory = player.inventory
counter = 0
inventory.items.each do |inv_item|
break unless counter < amount
next if inv_item == nil
id = inv_item.id
inventory_amount = inv_item.amount
if id == @item_id
if inventory_amount >= amount
inventory.remove(@item_id, amount) if remove
return true
else
counter += inventory_amount
end
end
end
if counter >= amount
inventory.remove(@item_id, amount) if remove
return true
end
return false
end
end
# An ingredient which needs to be grinded before being usable for Herblore.
class GroundIngredient < Ingredient
include HerbloreMethod
attr_reader :raw
def initialize(item_id, raw)
super(item_id)
@raw = raw
end
def invoke(player, pestle_mortar, ingredient)
action = GrindingAction.new(player, self)
listener = GrindingDialogueListener.new(player, action)
open_dialogue(player, @item_id, listener)
end
end
# A DialogueAdapter used for grinding ingredients. It is also used as an EnterAmountListener for the amount of grinding actions.
class GrindingDialogueListener < DialogueAdapter
include EnterAmountListener
attr_reader :player, :action
def initialize(player, action)
super()
@player = player
@action = action
end
# Called when a button has been clicked whilst the dialogue was opened.
def buttonClicked(button)
amount = get_amount(button)
return false if amount == 0
interfaces = @player.interface_set
interfaces.close
if amount == -1
interfaces.open_enter_amount_dialogue(self)
return true
end
amount = player.inventory.get_amount(@action.ingredient.raw) if amount == -2
execute(amount)
end
# Called when an amount of grinding actions has been entered.
def amountEntered(amount)
if amount <= 0 then return else execute(amount) end
end
# Called to set the action(s) in motion.
def execute(amount)
@action.set_amount(amount)
@player.start_action(@action)
end
# Gets the amount of actions based on the specified button id.
def get_amount(button)
case button
when 2799 then return 1
when 2798 then return 5
when 1748 then return -1
when 1747 then return -2
else return 0
end
end
end
# An action which makes the player grind one or more GrindedIngredients from their 'raw' form.
class GrindingAction < Action
attr_reader :ingredient, :amount, :pulses, :slot, :listener
def initialize(player, ingredient)
super 0, true, player
@ingredient = ingredient
@pulses = 0
end
def execute
grind
@pulses += 1
end
# Performs the grinding action once the materials have been checked.
def grind
if @pulses == 0
mob.play_animation GRINDING_ANIM
elsif @pulses == 1
if not gather_materials
stop
return
end
player = mob
inventory = player.inventory
item = inventory.get(@slot)
name = item.definition.name.downcase
player.send_message("You grind the #{name} to dust.", true)
inventory.reset(@slot)
inventory.add(@ingredient.item)
set_delay(1)
elsif @pulses == 2
mob.stop_animation
continue()
end
end
# Checks if the player has the required materials to perform the (next) action.
def gather_materials
items = mob.inventory.items
pst_mrt = false
ingr = false
raw = @ingredient.raw
(0...items.length).each do |slot|
item = items[slot]
next if item == nil
id = item.id
if id == PESTLE_MORTAR and !pst_mrt
pst_mrt = true
elsif id == raw and !ingr
ingr = true
@slot = slot
end
return true if pst_mrt and ingr
end
ingr = ItemDefinition.lookup(raw).name.downcase
mob.send_message("You do not have any more #{ingr}s.")
return false
end
# Either invokes the stop() method in Action to shut it down
# or continues to the next ingredient.
def continue
@amount -= 1
if @amount > 0
set_delay(0)
@pulses = -1
else
stop
end
end
# Sets the amount of actions.
def set_amount(amount)
@amount = amount
end
def stop
super
mob.inventory.remove_listener(@listener) unless listener == nil
end
def equals(other)
return (get_class == other.get_class and @ingredient == other.ingredient)
end
end
# Appends a grinded ingredient to the ItemOnItemEvent handler interception.
def append_ground(id, raw)
grinded = GroundIngredient.new(id, raw)
append_herblore_item(grinded, PESTLE_MORTAR, raw)
return grinded
end
# Normal ingredients
EYE_NEWT = Ingredient.new(221)
RED_SPIDERS_EGGS = Ingredient.new(223)
LIMPWURT_ROOT = Ingredient.new(225)
SNAPE_GRASS = Ingredient.new(231)
WHITE_BERRIES = Ingredient.new(239)
WINE_ZAMORAK = Ingredient.new(245)
JANGERBERRIES = Ingredient.new(247)
TOADS_LEGS = Ingredient.new(2152)
MORT_MYRE_FUNGI = Ingredient.new(2970)
POTATO_CACTUS = Ingredient.new(3138)
PHOENIX_FEATHER = Ingredient.new(4621)
FROG_SPAWN = Ingredient.new(5004)
PAPAYA_FRUIT = Ingredient.new(5972)
POISON_IVY_BERRIES = Ingredient.new(6018)
YEW_ROOTS = Ingredient.new(6049)
MAGIC_ROOTS = Ingredient.new(6051)
# Ground ingredients
UNICORN_HORN_DUST = append_ground(235, 237)
DRAGON_SCALE_DUST = append_ground(241, 243)
CHOCOLATE_DUST = append_ground(1975, 1973)
# CRUSHED_NEST = append_ground(6693, 5075)
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<plugin>
<id>skill-herblore</id>
<version>0.9</version>
<name>Herblore</name>
<description>Adds the Herblore skill.</description>
<authors>
<author>Chris Fletcher</author>
<author>Major</author>
</authors>
<scripts>
<script>herblore.rb</script>
<script>ingredient.rb</script>
<script>herb.rb</script>
<script>potion.rb</script>
</scripts>
<dependencies />
</plugin>
+365
View File
@@ -0,0 +1,365 @@
require 'java'
java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Item'
java_import 'org.apollo.game.model.def.ItemDefinition'
java_import 'org.apollo.game.model.inter.EnterAmountListener'
java_import 'org.apollo.game.model.inter.dialogue.DialogueAdapter'
WATER_VIAL_ID = 227
EMPTY_VIAL_ID = 229
MIXING_ANIM = Animation.new(363)
# Represents an unfinished potion which can be invoked as a HerbloreMethod and used as an ingredient.
class UnfinishedPotion < Ingredient
include HerbloreMethod
attr_reader :herb, :level
def initialize(item_id, herb, level)
super item_id
@herb = herb
@level = level
end
def invoke(player, primary, secondary)
action = UnfinishedMixingAction.new(player, self)
listener = UnfinishedMixingDialogueListener.new(player, action)
open_dialogue(player, @item_id, listener)
end
end
# Represents a finished potion which can be invoked as a HerbloreMethod.
class FinishedPotion
include HerbloreMethod
attr_reader :item, :ingredients, :level, :experience
def initialize(item, ingredients, level, experience)
@item = Item.new(item)
@ingredients = ingredients
@level = level
@experience = experience
end
def invoke(player, primary, secondary)
action = FinishedMixingAction.new(player, primary, secondary, self)
listener = FinishedMixingDialogueListener.new(player, action)
open_dialogue(player, @item.id, listener)
end
end
# A DialogueAdapter used for mixing potions. It is also used as an EnterAmountListener for the amount of mixing actions.
class MixingDialogueListener < DialogueAdapter
include EnterAmountListener
attr_reader :player, :action
def initialize(player, action)
super()
@player = player
@action = action
end
# Called when a button has been clicked whilst the dialogue was opened.
def buttonClicked(button)
amount = get_amount(button)
return false if amount == 0
interfaces = @player.interface_set
interfaces.close
if amount == -1
interfaces.open_enter_amount_dialogue(self)
return true
end
amount = calculate_maximum if amount == -2
execute(amount)
return true
end
# Called when an amount of mixing actions has been entered.
def amountEntered(amount)
if amount <= 0 then return else execute(amount) end
end
# Called to set the action(s) in motion.
def execute(amount)
@action.set_amount(amount)
@player.start_action(@action)
end
def calculate_maximum(code)
# Override for potion-specific amount calculation.
end
# Gets the amount of actions based on the specified button id.
def get_amount(button)
case button
when 2799 then return 1
when 2798 then return 5
when 1748 then return -1
when 1747 then return -2
else return 0
end
end
end
# A MixingDialogueListener used for mixing unfinished potions.
class UnfinishedMixingDialogueListener < MixingDialogueListener
def calculate_maximum
inventory = @player.inventory
amount = inventory.get_amount(WATER_VIAL_ID)
return 0 if amount <= 0
herbs = inventory.get_amount(@action.potion.herb.item.id)
amount = herbs if amount > herbs
return amount
end
end
# A MixingDialogueListener used for mixing finished potions.
class FinishedMixingDialogueListener < MixingDialogueListener
def calculate_maximum
inventory = @player.inventory
amount = inventory.capacity
@action.potion.ingredients.each do |ingredient|
item_amount = inventory.get_amount(ingredient.item.id)
amount = item_amount if amount > item_amount
end
return amount
end
end
# An Action which handles the none-finished-dependent mixing.
class MixingAction < Action
attr_reader :potion, :amount, :started, :pulses, :action, :listener
def initialize(player, potion, action)
super(1, true, player)
@potion = potion
@started = false
@pulses = 0
@action = action
@action.freeze
end
def execute
if @pulses == 0
unless @started
unless check_skill(mob, @potion.level, @action)
stop
return
end
@started = true
end
unless gather_materials
stop
return
end
end
mob.play_animation(MIXING_ANIM)
execute_action
if (@amount -= 1) > 0 then @pulses = 0 else stop end
end
def stop
super()
mob.inventory.remove_listener(@listener) unless @listener == nil
end
def execute_action
# Override for action execution.
end
def gather_materials
# Override for ingredient checking and gathering
return false
end
# Sets the amount of actions.
def set_amount(amount)
@amount = amount
end
def equals(other)
return (get_class == other.get_class and @potion == other.potion)
end
end
# A MixingAction which handles the execution of making UnfinishedPotions.
class UnfinishedMixingAction < MixingAction
attr_reader :slots
def initialize(player, potion)
super(player, potion, "use this herb.")
end
def execute_action
name = @potion.herb.item.definition.name
player = mob
inventory = player.inventory
player.send_message("You put the #{name} in the water to make an unfinished #{name.sub(/ leaf$/, "")} potion.", true)
@slots.each do |slot, amount|
unless inventory.remove_slot(slot, amount)
stop
return
end
end
inventory.add(@potion.item)
end
def gather_materials
@slots = {}
inventory = mob.inventory
vial_slot = inventory.slot_of(WATER_VIAL_ID)
if vial_slot == -1
mob.send_message('You do not have any more vials of water.')
return false
end
item = @potion.herb.item
herb_slot = inventory.slot_of(item.id)
if herb_slot == -1
mob.send_message("You do not have any more #{item.definition.name}.")
return false
end
@slots[vial_slot] = 1
@slots[herb_slot] = 1
return true
end
end
# A MixingAction which handles the execution of making FinishedPotions.
class FinishedMixingAction < MixingAction
attr_reader :unfinished, :ingredient, :slots
def initialize(player, unfinished, ingredient, potion)
super(player, potion, "mix this potion")
@unfinished = unfinished
@ingredient = ingredient
end
def execute_action
player = mob
ingredient = ItemDefinition.lookup(@ingredient).name.downcase
name = @potion.item.definition.name.sub('(3)', '')
player.send_message("You add the #{ingredient} to the mixture to make an #{name}.", true)
player.skill_set.add_experience(HERBLORE_SKILL_ID, @potion.experience)
inventory = player.inventory
@slots.each do |slot, amount|
if not inventory.remove_slot(slot, amount)
stop
return
end
end
inventory.add(@potion.item)
end
def gather_materials
@slots = {}
inventory = mob.inventory
vial_slot = inventory.slot_of(@unfinished)
if vial_slot == -1
mob.send_message('You do not have enough unfinished potions.')
return false
end
ingredient_slot = inventory.slot_of(@ingredient)
if ingredient_slot == -1
mob.send_message('You do not have enough ingredients.')
return false
end
@slots[vial_slot] = 1
@slots[ingredient_slot] = 1
return true
end
end
# Appends a finished potion to the ItemOnItemEvent handling interception.
def append_finished_potion(item, unfinished, ingredient, level, experience)
potion = FinishedPotion.new(item, [ unfinished, ingredient ], level, experience)
append_herblore_item(potion, unfinished.item_id, ingredient.item_id)
return potion
end
# Appends an unfinished potion to the ItemOnItemEvent handling interception.
def append_unfinished_potion(item, herb, level)
potion = UnfinishedPotion.new(item, herb, level)
append_herblore_item(potion, herb.item_id, WATER_VIAL_ID)
return potion
end
# Unfinished potions
UNF_GUAM = append_unfinished_potion(91, GUAM_LEAF, 1) # 3
UNF_MARRENTILL = append_unfinished_potion(93, MARRENTILL, 5)
UNF_TARROMIN = append_unfinished_potion(95, TARROMIN, 12)
UNF_HARRALANDER = append_unfinished_potion(97, HARRALANDER, 22)
UNF_RANARR = append_unfinished_potion(99, RANARR, 30)
UNF_TOADFLAX = append_unfinished_potion(3002, TOADFLAX, 34)
UNF_IRIT = append_unfinished_potion(101, IRIT_LEAF, 45)
UNF_AVANTOE = append_unfinished_potion(103, AVANTOE, 50)
UNF_KWUARM = append_unfinished_potion(105, KWUARM, 55)
UNF_SNAPDRAGON = append_unfinished_potion(3004, SNAPDRAGON, 63)
UNF_CADANTINE = append_unfinished_potion(107, CADANTINE, 66)
UNF_LANTADYME = append_unfinished_potion(2483, LANTADYME, 69)
UNF_DWARF_WEED = append_unfinished_potion(109, DWARF_WEED, 72)
UNF_TORSTOL = append_unfinished_potion(111, TORSTOL, 78)
# Finished potions
ATTACK_POT = append_finished_potion(121, UNF_GUAM, EYE_NEWT, 1, 25) # 3, 25
ANTIPOISON_POT = append_finished_potion(175, UNF_MARRENTILL, UNICORN_HORN_DUST, 5, 37.5)
STRENGTH_POT = append_finished_potion(115, UNF_TARROMIN, LIMPWURT_ROOT, 12, 50)
RESTORE_POT = append_finished_potion(127, UNF_HARRALANDER, RED_SPIDERS_EGGS, 18, 62.5)
ENERGY_POT = append_finished_potion(3010, UNF_HARRALANDER, CHOCOLATE_DUST, 26, 67.5)
DEFENCE_POT = append_finished_potion(133, UNF_RANARR, WHITE_BERRIES, 30, 75)
AGILITY_POT = append_finished_potion(3034, UNF_TOADFLAX, TOADS_LEGS, 34, 80)
PRAYER_POT = append_finished_potion(139, UNF_RANARR, SNAPE_GRASS, 38, 87.5)
SUPER_ATTACK_POT = append_finished_potion(145, UNF_IRIT, EYE_NEWT, 45, 100)
SUPER_ANTIPOISON_POT = append_finished_potion(181, UNF_IRIT, UNICORN_HORN_DUST, 48, 106.3)
FISHING_POT = append_finished_potion(151, UNF_AVANTOE, SNAPE_GRASS, 50, 112.5)
SUPER_ENERGY_POT = append_finished_potion(3018, UNF_AVANTOE, MORT_MYRE_FUNGI, 52, 117.5)
SUPER_STRENGTH_POT = append_finished_potion(157, UNF_KWUARM, LIMPWURT_ROOT, 55, 125)
WEAPON_POISON = append_finished_potion(187, UNF_KWUARM, DRAGON_SCALE_DUST, 60, 137.5)
SUPER_RESTORE_POT = append_finished_potion(3026, UNF_SNAPDRAGON, RED_SPIDERS_EGGS, 63, 142.5)
SUPER_DEFENCE_POT = append_finished_potion(163, UNF_CADANTINE, WHITE_BERRIES, 66, 150)
ANTIFIRE_POT = append_finished_potion(2428, UNF_LANTADYME, DRAGON_SCALE_DUST, 69, 157.5)
RANGING_POT = append_finished_potion(169, UNF_DWARF_WEED, WINE_ZAMORAK, 72, 162.5)
MAGIC_POT = append_finished_potion(3042, UNF_LANTADYME, POTATO_CACTUS, 76, 172.5)
ZAMORAK_BREW = append_finished_potion(189, UNF_TORSTOL, JANGERBERRIES, 78, 175)
+70
View File
@@ -0,0 +1,70 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
ALCHEMY_SPELLS = {}
LOW_ALCH_ANIM = Animation.new(712)
LOW_ALCH_GRAPHIC = Graphic.new(112, 0, 100)
LOW_ALCH_MULTIPLIER = 0.4
HIGH_ALCH_ANIM = Animation.new(713)
HIGH_ALCH_GRAPHIC = Graphic.new(113, 0, 100)
HIGH_ALCH_MULTIPLIER = 0.6
ILLEGAL_ALCH_ITEMS = [ 995, 6529, 6306, 6307, 6308, 6309, 6310 ]
class AlchemySpell < Spell
attr_reader :high, :animation, :graphic, :multiplier, :experience, :delay
def initialize(level, elements, high, animation, graphic, multiplier, experience, delay)
super(level, elements, experience)
@high = high
@animation = animation
@graphic = graphic
@multiplier = multiplier
@delay = delay
end
end
class AlchemyAction < ItemSpellAction
def initialize(player, alchemy, slot, item)
super(player, alchemy, slot, item)
end
def illegal_item?
return ILLEGAL_ALCH_ITEMS.include?(@item.id)
end
def execute_action
if @pulses == 0
mob.play_animation(@spell.animation)
mob.play_graphic(@spell.graphic)
mob.send(DISPLAY_SPELLBOOK)
inventory = mob.inventory
gold = (item.definition.value * @spell.multiplier) + 1
inventory.remove(inventory.get(@slot).id, 1)
inventory.add(995, gold)
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
set_delay(@spell.delay)
elsif @pulses == 1
mob.stop_animation
mob.stop_graphic
stop
end
end
end
def append_alchemy(button, level, elements, high, animation, graphic, multiplier, experience, delay)
ALCHEMY_SPELLS[button] = AlchemySpell.new(level, elements, high, animation, graphic, multiplier, experience, delay)
end
append_alchemy(1162, 21, { FIRE => 3, NATURE => 1 }, false, LOW_ALCH_ANIM, LOW_ALCH_GRAPHIC, 0.48, 31, 1) # Low level alchemy
append_alchemy(1178, 55, { FIRE => 5, NATURE => 1 }, true, HIGH_ALCH_ANIM, HIGH_ALCH_GRAPHIC, 0.72, 65, 4) # High level alchemy
+86
View File
@@ -0,0 +1,86 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Item'
CONVERT_SPELLS = {}
BONES_ID = 526
CONVERT_ANIM = Animation.new(722)
CONVERT_GRAPHIC = Graphic.new(141, 0, 100)
class ConvertSpell < Spell
attr_reader :reward
def initialize(level, elements, experience, reward)
super(level, elements, experience)
@reward = Item.new(reward)
end
end
class ConvertingAction < SpellAction
attr_reader :slots
def initialize(player, spell, slots)
super(player, spell)
@slots = slots
end
def execute_action
if @pulses == 0
mob.play_animation(CONVERT_ANIM)
mob.play_graphic(CONVERT_GRAPHIC)
inventory = mob.inventory
firing = (@slots.length * 2) < inventory.capacity
inventory.stop_firing_events unless firing # In the case of many changes, wait with firing events
reward = @spell.reward
@slots.each do |slot|
inventory.set(slot, reward) # Share the instance
end
unless firing # If we waited with firing events, restore it now and force a refresh
inventory.start_firing_events
inventory.force_refresh
end
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
set_delay(2)
elsif @pulses == 1
mob.stop_animation
mob.stop_graphic
stop
end
end
end
def bone_slots(player)
inventory = player.inventory
items = inventory.items
size = inventory.size
counter = 0
slots = []
(0...inventory.capacity).each do |slot|
break unless counter <= size
item = items[slot]
slots << slot if (item != nil and item.id == BONES_ID)
counter += 1
end
return slots
end
def append_convert(button, level, elements, experience, reward)
CONVERT_SPELLS[button] = ConvertSpell.new(level, elements, experience, reward)
end
append_convert 1159, 15, { EARTH => 2, WATER => 2, NATURE => 1 }, 25, 1963 # Bones to bananas
#append_convert 15877, 60, { NATURE => 2, WATER => 4, EARTH => 4 }, 35.5, 6883 # Bones to peaches
+112
View File
@@ -0,0 +1,112 @@
require 'java'
java_import 'org.apollo.game.model.EquipmentConstants'
AIR_ELEMENTS = {}
WATER_ELEMENTS = {}
EARTH_ELEMENTS = {}
FIRE_ELEMENTS = {}
AIR_RUNE = 556
WATER_RUNE = 555
EARTH_RUNE = 557
FIRE_RUNE = 554
MIND_RUNE = 558
CHAOS_RUNE = 562
DEATH_RUNE = 560
BLOOD_RUNE = 565
COSMIC_RUNE = 564
LAW_RUNE = 563
NATURE_RUNE = 561
SOUL_RUNE = 566
MIST_RUNE = 4695
DUST_RUNE = 4696
SMOKE_RUNE = 4697
MUD_RUNE = 4698
STEAM_RUNE = 4694
LAVA_RUNE = 4699
class Element
attr_reader :runes, :staffs, :name
def initialize(runes, staffs, name="Null")
@runes = runes
@staffs = staffs
@name = name
end
def check_remove(player, amount, remove)
weapon = player.equipment.get(EquipmentConstants::WEAPON)
if @staffs != nil && weapon != nil
@staffs.each do |staff|
return true if weapon.id == staff
end
end
inventory = player.inventory
found = {}
counter = 0
inventory.items.each do |item|
break unless counter < amount
next if item == nil
amt = item.amount
@runes.each do |rune|
break unless counter < amount
id = item.id
if id == rune
if amt >= amount
inventory.remove(id, amount) if remove
return true
else
found[id] = amt
counter += amt
end
end
end
end
if counter >= amount
if remove
found.each do |id, amt|
inventory.remove(id, amt)
end
end
return true
end
return false
end
end
AIR_RUNES = [ 556, 4695, 4696, 4697 ]
WATER_RUNES = [ 555, 4695, 4698, 4694 ]
EARTH_RUNES = [ 557, 4696, 4697, 4698 ]
FIRE_RUNES = [ 554, 4697, 4694, 4699 ]
AIR_STAFFS = [ 1381, 1397, 1405 ]
WATER_STAFFS = [ 1383, 1395, 1403 ]
EARTH_STAFFS = [ 1385, 1399, 1407, 3053, 3054 ]
FIRE_STAFFS = [ 1387, 1393, 1401, 3053, 3054 ]
AIR = Element.new(AIR_RUNES, AIR_STAFFS, "Air rune")
WATER = Element.new(WATER_RUNES, WATER_STAFFS, "Water rune")
EARTH = Element.new(EARTH_RUNES, EARTH_STAFFS, "Earth rune")
FIRE = Element.new(FIRE_RUNES, FIRE_STAFFS, "Fire rune")
MIND = Element.new([MIND_RUNE], nil, "Mind rune")
CHAOS = Element.new([CHAOS_RUNE], nil, "Chaos rune")
DEATH = Element.new([DEATH_RUNE], nil, "Death rune")
BLOOD = Element.new([BLOOD_RUNE], nil, "Blood rune")
COSMIC = Element.new([COSMIC_RUNE], nil, "Cosmic rune")
LAW = Element.new([LAW_RUNE], nil, "Law rune")
NATURE = Element.new([NATURE_RUNE], nil, "Nature rune")
SOUL = Element.new([SOUL_RUNE], nil, "Soul rune")
+109
View File
@@ -0,0 +1,109 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Item'
ENCHANT_SPELLS = {}
ENCHANT_ITEMS = {}
RING_GFX = Graphic.new(238, 0, 100)
RING_ANIM = Animation.new(713) # TODO: No way we need one of the alchemy anims for enchanting...
LOW_NECK_GFX = Graphic.new(114, 0, 100)
LOW_NECK_ANIM = Animation.new(719)
MED_NECK_GFX = Graphic.new(115, 0, 100)
MED_NECK_ANIM = Animation.new(720)
HIGH_NECK_GFX = Graphic.new(116, 0, 100)
HIGH_NECK_ANIM = Animation.new(721)
ONYX_NECK_GFX = Graphic.new(452, 0, 100)
class EnchantSpell < Spell
attr_reader :button, :animation, :graphic, :delay
def initialize(button, level, elements, animation, graphic, delay, experience)
super(level, elements, experience)
@button = button
@animation = animation
@graphic = graphic
@delay = delay
end
end
class EnchantAction < ItemSpellAction
attr_reader :reward
def initialize(player, enchant, slot, item, reward)
super(player, enchant, slot, item)
@reward = Item.new(reward)
end
def illegal_item?
return ENCHANT_ITEMS[@item.id] == nil
end
def execute_action
if @pulses == 0
mob.play_animation(@spell.animation)
mob.play_graphic(@spell.graphic)
mob.send(DISPLAY_SPELLBOOK)
mob.inventory.set(@slot, @reward)
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
set_delay(@spell.delay)
elsif @pulses == 1
mob.stop_animation
mob.stop_graphic
stop
end
end
end
def append_enchant(button, level, elements, item, animation, graphic, delay, experience, reward)
enchant = EnchantSpell.new(button, level, elements, animation, graphic, delay, experience)
ENCHANT_SPELLS[item] = enchant
ENCHANT_ITEMS[item] = reward
end
SAPPHIRE_ELEMENTS = { WATER => 1, COSMIC => 1 }
EMERALD_ELEMENTS = { AIR => 1, COSMIC => 1 }
RUBY_ELEMENTS = { FIRE => 5, COSMIC => 1 }
DIAMOND_ELEMENTS = { EARTH => 10, COSMIC => 1 }
DSTONE_ELEMENTS = { WATER => 15, EARTH => 15, COSMIC => 1 }
ONYX_ELEMENTS = { EARTH => 20, FIRE => 20, COSMIC => 1 }
# Sapphire
append_enchant 1155, 7, SAPPHIRE_ELEMENTS, 1637, RING_ANIM, RING_GFX, 2, 17.5, 2550 # Ring
append_enchant 1155, 7, SAPPHIRE_ELEMENTS, 1656, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 17.5, 3853 # Necklace
append_enchant 1155, 7, SAPPHIRE_ELEMENTS, 1692, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 17.5, 1727 # Amulet
# Emerald
append_enchant 1165, 27, EMERALD_ELEMENTS, 1639, RING_ANIM, RING_GFX, 2, 37, 2552 # Ring
append_enchant 1165, 27, EMERALD_ELEMENTS, 1658, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 37, 5521 # Necklace
append_enchant 1165, 27, EMERALD_ELEMENTS, 1696, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 37, 1729 # Amulet
# Ruby
append_enchant 1176, 49, RUBY_ELEMENTS, 1641, RING_ANIM, RING_GFX, 2, 59, 2568 # Ring
# append_enchant 1176, 49, RUBY_ELEMENTS, 1660, MED_NECK_ANIM, MED_NECK_GFX, 2, 59, # Necklace - not found in 317 or 377
append_enchant 1176, 49, RUBY_ELEMENTS, 1698, MED_NECK_ANIM, MED_NECK_GFX, 2, 59, 1725 # Amulet
# Diamond
append_enchant 1180, 57, DIAMOND_ELEMENTS, 1643, RING_ANIM, RING_GFX, 2, 67, 2570 # Ring
# append_enchant 1180, 57, DIAMOND_ELEMENTS, 1662, MED_NECK_ANIM, MED_NECK_GFX, 2, 67, # Necklace - not found in 317 or 377
append_enchant 1180, 57, DIAMOND_ELEMENTS, 1700, MED_NECK_ANIM, MED_NECK_GFX, 2, 67, 1731 # Amulet
# Dragonstone
append_enchant 1187, 68, DSTONE_ELEMENTS, 1645, RING_ANIM, RING_GFX, 2, 78, 2572 # Ring
# append_enchant 1187, 68, DSTONE_ELEMENTS, 1664, HIGH_NECK_ANIM, HIGH_NECK_GFX, 3, 78, # Necklace - not found in 317 or 377
append_enchant 1187, 68, DSTONE_ELEMENTS, 1702, HIGH_NECK_ANIM, HIGH_NECK_GFX, 3, 78, 1712 # Amulet
# Onyx
append_enchant 6003, 87, ONYX_ELEMENTS, 6575, RING_ANIM, RING_GFX, 2, 97, 6583 # Ring
# append_enchant 6003, 87, ONYX_ELEMENTS, 6577, HIGH_NECK_ANIM, ONYX_NECK_GFX, 3, 97, # Necklace - not found in 317 or 377
append_enchant 6003, 87, ONYX_ELEMENTS, 6581, HIGH_NECK_ANIM, ONYX_NECK_GFX, 2, 97, 6585 # Amulet
+161
View File
@@ -0,0 +1,161 @@
require 'java'
java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.event.impl.DisplayTabInterfaceEvent'
java_import 'org.apollo.game.model.EquipmentConstants'
java_import 'org.apollo.game.model.Skill'
DISPLAY_SPELLBOOK = DisplayTabInterfaceEvent.new(6)
class Spell
attr_reader :level, :elements, :experience
def initialize(level, elements, experience)
@level = level
@elements = elements
@experience = experience
end
end
class SpellAction < Action
attr_reader :spell, :pulses
def initialize(mob, spell)
super(0, true, mob)
@spell = spell
@pulses = 0
end
def execute
if @pulses == 0
unless (check_skill and process_elements)
stop
return
end
end
execute_action
@pulses += 1
end
def execute_action
stop
end
def check_skill
required = @spell.level
if required > mob.skill_set.skill(MAGIC_SKILL_ID).maximum_level
mob.send_message("You need a Magic level of at least #{required} to cast this spell.")
return false
end
return true
end
def process_elements
elements = @spell.elements
elements.each do |element, amount|
unless element.check_remove(mob, amount, false)
mob.send_message("You do not have enough #{element.name}s to cast this spell.")
return false
end
end
elements.each do |element, amount|
element.check_remove(mob, amount, true)
end
return true
end
def equals(other)
return (get_class == other.get_class and @spell == other.spell)
end
end
class ItemSpellAction < SpellAction
attr_reader :slot, :item
def initialize(mob, spell, slot, item)
super(mob, spell)
@slot = slot
@item = item
end
# We override SpellAction#execute to implement an illegal item check (e.g. coins for alchemy)
def execute
if @pulses == 0
if illegal_item?
mob.send_message('You cannot use that spell on this item!')
stop
next
end
id = @item.id
# TODO: There has to be a better way to do this.
@spell.elements.each do |element, amount|
element.runes.each do |rune|
if id == rune && !element.check_remove(mob, amount + 1, false)
mob.send_message("You do not have enough #{element.name}s to cast this spell.")
stop
return false
end
end
end
end
super
end
def illegal_item?
# Override this method if necessary
return false
end
end
# Intercepts the magic on item event.
on :event, :magic_on_item do |ctx, player, event|
spell = event.spell_id
alch = ALCHEMY_SPELLS[spell]
if alch != nil
slot = event.slot
item = player.inventory.get(slot)
player.start_action(AlchemyAction.new(player, alch, slot, item))
ctx.break_handler_chain
return
end
ench = ENCHANT_SPELLS[event.id]
if ench != nil and ench.button == spell
slot = event.slot
item = player.inventory.get(slot)
player.start_action(EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id]))
ctx.break_handler_chain
end
end
# Intercepts the button event
on :event, :button do |ctx, player, event|
button = event.widget_id
tele = TELEPORT_SPELLS[button]
if tele != nil
player.start_action(TeleportingAction.new(player, tele))
ctx.break_handler_chain
return
end
conv = CONVERT_SPELLS[button]
if conv != nil
slots = bone_slots player
if slots.length == 0 then player.send_message("You cant convert these bones!") else player.start_action(ConvertingAction.new(player, conv, slots)) end
ctx.break_handler_chain
end
end
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<plugin>
<id>skill-magic</id>
<version>1</version>
<name>Magic</name>
<description>Adds the Magic skill.</description>
<authors>
<author>Chris Fletcher</author>
<author>Major</author>
</authors>
<scripts>
<script>magic.rb</script>
<script>element.rb</script>
<script>teleport.rb</script>
<script>alchemy.rb</script>
<script>enchant.rb</script>
<script>convert.rb</script>
</scripts>
<dependencies />
</plugin>
+94
View File
@@ -0,0 +1,94 @@
# Thanks to phl0w <http://www.rune-server.org/members/phl0w/> for providing
# the correct destination coordinates of the ancient teleports.
require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Position'
TELEPORT_SPELLS = {}
MODERN_TELE_ANIM = Animation.new(714)
MODERN_TELE_END_ANIM = Animation.new(715)
MODERN_TELE_GRAPHIC = Graphic.new(308, 15, 100)
ANCIENT_TELE_END_GRAPHIC = Graphic.new(455)
ANCIENT_TELE_ANIM = Animation.new(1979)
ANCIENT_TELE_GRAPHIC = Graphic.new(392)
class TeleportSpell < Spell
attr_reader :ancient, :destination, :experience, :name
def initialize(ancient, level, elements, destination, experience, name)
super(level, elements, experience)
@ancient = ancient
@destination = destination
@name = name
end
end
class TeleportingAction < SpellAction
def initialize(mob, spell)
super(mob, spell)
end
def execute_action
@spell.ancient ? execute_ancient : execute_modern
end
def execute_modern
if @pulses == 0
mob.play_animation(MODERN_TELE_ANIM)
elsif @pulses == 1
mob.play_graphic(MODERN_TELE_GRAPHIC)
delay = 1
elsif @pulses == 2
mob.stop_graphic
mob.play_animation(MODERN_TELE_END_ANIM)
mob.teleport(@spell.destination)
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
stop
end
end
def execute_ancient
if @pulses == 0
mob.play_graphic(ANCIENT_TELE_GRAPHIC)
mob.play_animation(ANCIENT_TELE_ANIM)
delay = 2
elsif @pulses == 2
mob.stop_graphic
mob.stop_animation
mob.teleport(@spell.destination)
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
stop
end
end
end
def append_tele(ancient, button, level, elements, x, y, experience, name)
TELEPORT_SPELLS[button] = TeleportSpell.new(ancient, level, elements, Position.new(x, y), experience, name)
end
# Modern teleports
append_tele(false, 1164, 25, { FIRE => 1, AIR => 3, LAW => 1 }, 3213, 3424, 35, "Varrock")
append_tele(false, 1167, 31, { EARTH => 1, AIR => 3, LAW => 1 }, 3222, 3219, 41, "Lumbridge")
append_tele(false, 1170, 37, { WATER => 1, AIR => 3, LAW => 1 }, 2965, 3379, 47, "Falador")
append_tele(false, 1174, 45, { AIR => 5, LAW => 1 }, 2757, 3478, 55.5, "Camelot")
append_tele(false, 1540, 51, { WATER => 2, LAW => 2 }, 2662, 3306, 61, "Ardougne")
append_tele(false, 1541, 58, { EARTH => 2, LAW => 2 }, 2549, 3114, 68, "the Watchtower")
append_tele(false, 7455, 61, { FIRE => 2, LAW => 2 }, 2871, 3590, 68, "Trollheim")
append_tele(false, 18470, 64, { FIRE => 2, WATER => 2, LAW => 2, Element.new([1963], nil, "Banana") => 1 }, 2754, 2785, 76, "Ape Atoll")
# Ancient teleports
append_tele(true, 13035, 54, { LAW => 2, FIRE => 1, AIR => 1 }, 3098, 9882, 64, "Paddewwa")
append_tele(true, 13045, 60, { LAW => 2, SOUL => 2 }, 3320, 3338, 70, "Senntisten")
append_tele(true, 13053, 66, { LAW => 2, BLOOD => 1 }, 3493, 3472, 76, "Kharyll")
append_tele(true, 13061, 72, { LAW => 2, WATER => 4 }, 3003, 3470, 82, "Lassar")
append_tele(true, 13069, 78, { LAW => 2, FIRE => 3, AIR => 2 }, 2966, 3696, 88, "Dareeyak")
append_tele(true, 13079, 84, { LAW => 2, SOUL => 2 }, 3163, 3664, 94, "Carrallangar")
append_tele(true, 13087, 90, { LAW => 2, BLOOD => 2 }, 3287, 3883, 100, "Annakarl")
append_tele(true, 13095, 96, { LAW => 2, WATER => 8 }, 2972, 3873, 106, "Ghorrock")
+19
View File
@@ -0,0 +1,19 @@
GEMSTONES = {}
class Gemstone
attr_reader :id, :chance
def initialize(id, chance)
@id = id
@chance = chance
end
end
def append_gem(gem)
GEMSTONES[gem.id] = gem
end
append_gem(Gemstone.new(1623, 0)) # uncut sapphire
append_gem(Gemstone.new(1605, 0)) # uncut emerald
append_gem(Gemstone.new(1619, 0)) # uncut ruby
append_gem(Gemstone.new(1617, 0)) # uncut diamond
+162
View File
@@ -0,0 +1,162 @@
require 'java'
java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.EquipmentConstants'
java_import 'org.apollo.game.model.def.ItemDefinition'
PROSPECT_PULSES = 3
ORE_SIZE = 1
# TODO: finish implementing this
class MiningAction < DistancedAction
attr_reader :position, :ore, :counter, :started
def initialize(mob, position, ore)
super(0, true, mob, position, ORE_SIZE)
@position = position
@ore = ore
@started = false
@counter = 0
end
def find_pickaxe
PICKAXE_IDS.each do |id|
weapon = mob.equipment.get(EquipmentConstants::WEAPON)
if weapon != nil && weapon.id == id
return PICKAXES[id]
end
if mob.inventory.contains(id)
return PICKAXES[id]
end
end
return nil
end
# starts the mining animation, sets counters/flags and turns the mob to
# the ore
def start_mine(pickaxe)
@started = true
mob.send_message('You swing your pick at the rock.', true)
mob.turn_to(@position)
mob.play_animation(pickaxe.animation)
@counter = pickaxe.pulses
end
def executeAction
skills = mob.skill_set
level = skills.get_skill(MINING_SKILL_ID).current_level
pickaxe = find_pickaxe
# verify the mob can mine with their pickaxe
unless (pickaxe != nil and level >= pickaxe.level)
mob.send_message('You do not have a pickaxe for which you have the level to use.')
stop
return
end
# verify the mob can mine the ore
if ore.level > level
mob.send_message('You do not have the required level to mine this rock.')
stop
return
end
# check if we need to kick start things
unless @started
start_mine(pickaxe)
else
# count down and check if we can have a chance at some ore now
if @counter == 0
# TODO: calculate the chance that the mob can actually get the rock
if mob.inventory.add(ore.id)
ore_def = ItemDefinition.lookup(@ore.id) # TODO: split off into some method
name = ore_def.name.sub(/ ore$/, '').downcase
mob.send_message("You manage to mine some #{name}.")
skills.add_experience(MINING_SKILL_ID, ore.exp)
# TODO: expire the rock
end
stop
end
@counter -= 1
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position and @ore == other.ore)
end
end
class ExpiredProspectingAction < DistancedAction
attr_reader :position
def initialize(mob, position)
super(0, true, mob, position, ORE_SIZE)
end
def executeAction
mob.send_message('There is currently no ore available in this rock.')
stop
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
end
end
class ProspectingAction < DistancedAction
attr_reader :position, :ore
def initialize(mob, position, ore)
super(PROSPECT_PULSES, true, mob, position, ORE_SIZE)
@position = position
@ore = ore
@started = false
end
def executeAction
if not @started
@started = true
mob.send_message('You examine the rock for ores...')
mob.turn_to(@position)
else
ore_def = ItemDefinition.lookup(@ore.id)
name = ore_def.name.sub(/ ore$/, '').downcase
mob.send_message("This rock contains #{name}.")
stop
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position and @ore == other.ore)
end
end
on :event, :object_action do |ctx, mob, event|
if event.option == 1
ore = ORES[event.id]
if ore != nil
mob.start_action(MiningAction.new(mob, event.position, ore))
end
end
end
on :event, :object_action do |ctx, mob, event|
if event.option == 2
ore = ORES[event.id]
if ore != nil
mob.start_action(ProspectingAction.new(mob, event.position, ore))
elsif EXPIRED_ORES[event.id] != nil
mob.start_action(ExpiredProspectingAction.new(mob, event.position))
end
end
end
+96
View File
@@ -0,0 +1,96 @@
# Thanks to Mikey` <http://www.rune-server.org/members/mikey%60/> for helping
# to find some of the item/object IDs, minimum levels and experiences.
#
# Thanks to Clifton <http://www.rune-server.org/members/clifton/> for helping
# to find some of the expired object IDs.
ORES = {}
EXPIRED_ORES = {}
class Ore
attr_reader :id, :objects, :level, :exp, :respawn
def initialize(id, objects, level, exp, respawn)
@id = id
@objects = objects
@level = level
@exp = exp
@respawn = respawn
end
end
def append_ore(ore)
ore.objects.each do |obj, expired_obj|
ORES[obj] = ore
EXPIRED_ORES[expired_obj] = true
end
end
CLAY_OBJECTS = {
2180 => 450 , 2109 => 451 , 14904 => 14896, 14905 => 14897
}
COPPER_OBJECTS = {
11960 => 11555, 11961 => 11556, 11962 => 11557, 11936 => 11552,
11937 => 11553, 11938 => 11554, 2090 => 450 , 2091 => 451 ,
14906 => 14898, 14907 => 14899, 14856 => 14832, 14857 => 14833,
14858 => 14834
}
TIN_OBJECTS = {
11597 => 11555, 11958 => 11556, 11959 => 11557, 11933 => 11552,
11934 => 11553, 11935 => 11554, 2094 => 450 , 2095 => 451 ,
14092 => 14894, 14903 => 14895
}
IRON_OBJECTS = {
11954 => 11555, 11955 => 11556, 11956 => 11557, 2092 => 450 ,
2093 => 451 , 14900 => 14892, 14901 => 14893, 14913 => 14915,
14914 => 14916
}
COAL_OBJECTS = {
11963 => 11555, 11964 => 11556, 11965 => 11557, 11930 => 11552,
11931 => 11553, 11932 => 11554, 2096 => 450 , 2097 => 451 ,
14850 => 14832, 14851 => 14833, 14852 => 14834
}
SILVER_OBJECTS = {
11948 => 11555, 11949 => 11556, 11950 => 11557, 2100 => 450 ,
2101 => 451
}
GOLD_OBJECTS = {
11951 => 11555, 11952 => 11556, 11953 => 11557, 2098 => 450 ,
2099 => 451
}
MITHRIL_OBJECTS = {
11945 => 11555, 11946 => 11556, 11947 => 11557, 11942 => 11552,
11943 => 11553, 11944 => 11554, 2102 => 450 , 2103 => 451 ,
14853 => 14832, 14854 => 14833, 14855 => 14834
}
ADAMANT_OBJECTS = {
11939 => 11552, 11940 => 11553, 11941 => 11554, 2104 => 450 ,
2105 => 451 , 14862 => 14832, 14863 => 14833, 14864 => 14834
}
RUNITE_OBJECTS = {
2106 => 450 , 2107 => 451 , 14859 => 14832, 14860 => 14833,
14861 => 14834
}
append_ore Ore.new(434, CLAY_OBJECTS, 1, 5, 3 ) # clay
append_ore Ore.new(436, COPPER_OBJECTS, 1, 17.5, 6 ) # copper ore
append_ore Ore.new(438, TIN_OBJECTS, 1, 17.5, 6 ) # tin ore
append_ore Ore.new(440, IRON_OBJECTS, 15, 35, 16 ) # iron ore
append_ore Ore.new(453, COAL_OBJECTS, 30, 50, 100 ) # coal
append_ore Ore.new(444, GOLD_OBJECTS, 40, 65, 200 ) # gold ore
append_ore Ore.new(442, SILVER_OBJECTS, 20, 40, 200 ) # silver ore
append_ore Ore.new(447, MITHRIL_OBJECTS, 55, 80, 400 ) # mithril ore
append_ore Ore.new(449, ADAMANT_OBJECTS, 70, 95, 800 ) # adamant ore
append_ore Ore.new(451, RUNITE_OBJECTS, 85, 125, 2500) # runite ore
# TODO: rune essence object id = 2491
# level 1, exp 5, rune ess = 1436, pure ess = 7936
+32
View File
@@ -0,0 +1,32 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
PICKAXES = {}
PICKAXE_IDS = []
class Pickaxe
attr_reader :id, :level, :animation, :pulses
def initialize(id, level, animation, pulses)
@id = id
@level = level
@animation = Animation.new(animation)
@pulses = pulses
end
end
def append_pickaxe(pickaxe)
PICKAXES[pickaxe.id] = pickaxe
PICKAXE_IDS << pickaxe.id # tacky way of keeping things in order
end
# NOTE: ADD LOWER LEVEL PICKAXES FIRST
append_pickaxe(Pickaxe.new(1265, 1, 625, 8)) # bronze pickaxe
append_pickaxe(Pickaxe.new(1267, 1, 626, 7)) # iron pickaxe
append_pickaxe(Pickaxe.new(1269, 1, 627, 6)) # steel pickaxe
append_pickaxe(Pickaxe.new(1273, 21, 629, 5)) # mithril pickaxe
append_pickaxe(Pickaxe.new(1271, 31, 628, 4)) # adamant pickaxe
append_pickaxe(Pickaxe.new(1275, 41, 624, 3)) # rune pickaxe
PICKAXE_IDS.reverse!
+22
View File
@@ -0,0 +1,22 @@
<?xml version="1.0"?>
<plugin>
<id>skill-mining</id>
<version>1</version>
<name>Mining</name>
<description>Adds the mining skill.</description>
<authors>
<author>Graham</author>
<author>Mikey`</author>
<author>WH:II:DOW</author>
<author>Requa</author>
<author>Clifton</author>
</authors>
<scripts>
<script>pickaxe.rb</script>
<script>ore.rb</script>
<script>gem.rb</script>
<script>respawn.rb</script>
<script>mining.rb</script>
</scripts>
<dependencies />
</plugin>
+16
View File
@@ -0,0 +1,16 @@
# Calculates the number of pulses it takes for an ore to respawn based on the
# number of players currently online.
#
# The 'base' argument is the number of pulses it takes with no players online.
# The 'players' argument is the number of players currently logged into the
# current world.
#
# The base times can be found on this website:
# http://runescape.salmoneus.net/mining.html#respawn
#
# These must be converted to pulses (seconds * 10 / 6) to work with this
# function. The rest of the mining plugin rounds the base respawn times in
# pulses down where appropriate.
def respawn_pulses(base, players)
base - players * base / (World.world.player_repository.size * 2)
end
+82
View File
@@ -0,0 +1,82 @@
require 'java'
java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Skill'
BURY_BONE_ANIMATION = 827
BONES = {}
# Represents a bone with a name, id, and experience.
class Bone
attr_reader :id, :exp
def initialize(id, exp)
@id = id
@exp = exp
end
end
# An action where a bone in a player's inventory is buried.
class BuryBoneAction < Action
def initialize(mob, slot, bone)
super(1, false, mob)
@slot = slot
@bone = bone
mob.play_animation(Animation.new(BURY_BONE_ANIMATION))
mob.send_message('You dig a hole in the ground...')
end
def execute
if mob.inventory.get(@slot).id == @bone.id
mob.send_message('You bury the bones.')
mob.inventory.reset(@slot)
mob.skill_set.add_experience(Skill::PRAYER, @bone.exp)
end
stop
end
end
# Intercepts the first item option event,
on :event, :item_option do |ctx, player, event|
if event.option == 1
bone = BONES[event.id]
unless bone == nil
player.start_action(BuryBoneAction.new(player, event.slot, bone))
ctx.break_handler_chain
end
end
end
# Appends a bone to the array
def append_bone(hash)
raise 'Hash must contain an id and an experience value.' unless hash.has_key?(:id) && hash.has_key?(:experience)
id = hash[:id]
BONES[id] = Bone.new(id, hash[:experience])
end
append_bone :name => :regular_bones, :id => 526, :experience => 5
append_bone :name => :burnt_bones, :id => 528, :experience => 5
append_bone :name => :bat_bones, :id => 530, :experience => 4
append_bone :name => :big_bones, :id => 532, :experience => 45
append_bone :name => :babydragon_bones, :id => 534, :experience => 30
append_bone :name => :dragon_bones, :id => 536, :experience => 72
append_bone :name => :wolf_bones, :id => 2859, :experience => 14
append_bone :name => :shaikahan_bones, :id => 3123, :experience => 25
append_bone :name => :jogre_bones, :id => 3125, :experience => 15
append_bone :name => :burnt_zogre_bones, :id => 3127, :experience => 25
append_bone :name => :monkey_bones, :id => 3179, :experience => 14 # smallish
append_bone :name => :monkey_bones, :id => 3180, :experience => 14 # medium
append_bone :name => :monkey_bones, :id => 3181, :experience => 14 # quite large
append_bone :name => :monkey_bones, :id => 3182, :experience => 14 # quite large
append_bone :name => :monkey_bones, :id => 3183, :experience => 14 # small
append_bone :name => :shaking_bones, :id => 3187, :experience => 14
append_bone :name => :zogre_bones, :id => 4812, :experience => 23
append_bone :name => :fayrg_bones, :id => 4830, :experience => 84
append_bone :name => :raurg_bones, :id => 4832, :experience => 96
append_bone :name => :ourg_bones, :id => 4834, :experience => 140
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<plugin>
<id>skill-prayer</id>
<version>1</version>
<name>Prayer</name>
<description>Adds the Prayer skill.</description>
<authors>
<author>Major</author>
<author>010253</author>
</authors>
<scripts>
<script>bury.rb</script>
</scripts>
<dependencies />
</plugin>
+89
View File
@@ -0,0 +1,89 @@
require 'java'
java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.Position'
PORTALS = {}
ENTRANCE_ALTARS = {}
CRAFTING_ALTARS = {}
# Represents a runecrafting altar.
class Altar
attr_reader :entrance_altar, :crafting_altar, :portal_id, :entrance_position, :exit_position, :crafting_centre
def initialize(entrance_altar, crafting_altar, portal_id, entrance_position, exit_position,crafting_centre)
@entrance_altar = entrance_altar
@altar = crafting_altar
@portal_id = portal_id
@entrance_position = entrance_position
@exit_position = exit_position
@crafting_centre = crafting_centre
end
end
# Intercepts the item on object event.
on :event, :item_on_object do |ctx, player, event|
talisman = TALISMANS[event.id]; altar = ENTRANCE_ALTARS[event.object_id]
if (talisman != nil && altar != nil)
player.start_action(TeleportAction.new(player, event.position, 2, altar.entrance_position))
ctx.break_handler_chain
end
end
# Intercepts the first object action event.
on :event, :object_action do |ctx, player, event|
if (event.option == 1)
object_id = event.id
if (altar = PORTALS[object_id]) != nil # Get the altar associated with this exit portal.
player.start_action(TeleportAction.new(player, altar.entrance_position, 1, altar.exit_position))
elsif (rune = RUNES[object_id]) != nil # Get the rune associated with this altar.
altar = CRAFTING_ALTARS[object_id]
player.start_action(RunecraftingAction.new(player, rune, altar.crafting_centre))
end
ctx.break_handler_chain
end
end
# An action that causes a mob to teleport when it comes within the specified distance of a specified position.
class TeleportAction < DistancedAction
attr_reader :teleport_position
def initialize(mob, position, distance, teleport_position)
super(0, true, mob, position, distance)
@teleport_position = teleport_position
end
def executeAction
mob.teleport(@teleport_position)
stop
end
def equals(other)
return (get_class == other.get_class && mob == other.mob && @teleport_position == other.teleport_position)
end
end
# Appends an altar to the list.
def append_altar(hash)
#raise 'Hash must contain an entrance altar id, crafting altar id, entrance portal position, and altar centre position.'
entrance_altar = hash[:entrance_altar]; crafting_altar = hash[:crafting_altar]; portal_id = hash[:exit_portal]; entrance_position = hash[:entrance_position]; exit_position = hash[:exit_position]; altar_centre = hash[:altar_centre]
PORTALS[portal_id] = ENTRANCE_ALTARS[entrance_altar] = CRAFTING_ALTARS[crafting_altar] = Altar.new(entrance_altar, crafting_altar, portal_id, Position.new(*entrance_position), Position.new(*exit_position), Position.new(*altar_centre))
end
# Appends an altar to the list.
append_altar :name => :air_altar, :entrance_altar => 2452, :crafting_altar => 2478, :exit_portal => 2465, :entrance_position => [ 2841, 4829 ], :exit_position => [ 2983, 3292 ], :altar_centre => [ 2844, 4834 ]
append_altar :name => :mind_altar, :entrance_altar => 2453, :crafting_altar => 2479, :exit_portal => 2466, :entrance_position => [ 2793, 4828 ], :exit_position => [ 2980, 3514 ], :altar_centre => [ 2786, 4841 ]
append_altar :name => :water_altar, :entrance_altar => 2454, :crafting_altar => 2480, :exit_portal => 2467, :entrance_position => [ 2726, 4832 ], :exit_position => [ 3187, 3166 ], :altar_centre => [ 2716, 4836 ]
append_altar :name => :earth_altar, :entrance_altar => 2455, :crafting_altar => 2481, :exit_portal => 2468, :entrance_position => [ 2655, 4830 ], :exit_position => [ 3304, 3474 ], :altar_centre => [ 2658, 4841 ]
append_altar :name => :fire_altar, :entrance_altar => 2456, :crafting_altar => 2482, :exit_portal => 2469, :entrance_position => [ 2574, 4849 ], :exit_position => [ 3311, 3256 ], :altar_centre => [ 2585, 4838 ]
append_altar :name => :body_altar, :entrance_altar => 2457, :crafting_altar => 2483, :exit_portal => 2470, :entrance_position => [ 2524, 4825 ], :exit_position => [ 3051, 3445 ], :altar_centre => [ 2525, 4832 ]
append_altar :name => :cosmic_altar, :entrance_altar => 2458, :crafting_altar => 2484, :exit_portal => 2471, :entrance_position => [ 2142, 4813 ], :exit_position => [ 2408, 4379 ], :altar_centre => [ 2142, 4833 ]
append_altar :name => :law_altar, :entrance_altar => 2459, :crafting_altar => 2485, :exit_portal => 2472, :entrance_position => [ 2464, 4818 ], :exit_position => [ 2858, 3379 ], :altar_centre => [ 2464, 4832 ]
append_altar :name => :nature_altar, :entrance_altar => 2460, :crafting_altar => 2486, :exit_portal => 2473, :entrance_position => [ 2400, 4835 ], :exit_position => [ 2867, 3019 ], :altar_centre => [ 2400, 4841 ]
append_altar :name => :chaos_altar, :entrance_altar => 2461, :crafting_altar => 2487, :exit_portal => 2474, :entrance_position => [ 2268, 4842 ], :exit_position => [ 3058, 3591 ], :altar_centre => [ 2271, 4842 ]
append_altar :name => :death_altar, :entrance_altar => 2462, :crafting_altar => 2488, :exit_portal => 2475, :entrance_position => [ 2208, 4830 ], :exit_position => [ 3222, 3222 ], :altar_centre => [ 2205, 4836 ]
+17
View File
@@ -0,0 +1,17 @@
<?xml version="1.0"?>
<plugin>
<id>skill-runecraft</id>
<version>0.9</version>
<name>Runecraft</name>
<description>Adds the Runecraft skill.</description>
<authors>
<author>Major</author>
</authors>
<scripts>
<script>altar.rb</script>
<script>rune.rb</script>
<script>runecraft.rb</script>
<script>talisman.rb</script>
</scripts>
<dependencies />
</plugin>
+47
View File
@@ -0,0 +1,47 @@
require 'java'
java_import 'org.apollo.game.model.def.ItemDefinition'
# The list of runes.
RUNES = {}
# Represents a rune that can be crafted.
class Rune
attr_reader :name, :id, :level, :experience
def initialize(id, level, experience, multiplier)
@id = id
@name = ItemDefinition.lookup(id).name.downcase
@level = level
@experience = experience
@multiplier = multiplier
end
def multiplier(level)
return @multiplier.call(level)
end
def equals(other)
return (get_class == other.get_class && id == other.id)
end
end
# Appends a rune to the list.
def append_rune(hash)
raise 'Hash must contain an id, experience, .' unless hash.has_key?(:id) && hash.has_key?(:level) && hash.has_key?(:experience) && hash.has_key?(:multiplier)
id = hash[:id]; altar = hash[:altar]; level = hash[:level]; experience = hash[:experience]; multiplier = hash[:multiplier]
RUNES[altar] = Rune.new(id, level, experience, multiplier)
end
append_rune :name => :air_rune, :altar => 2478, :id => 556, :level => 1, :experience => 5, :multiplier => lambda { |level| (level / 11).floor + 1 }
append_rune :name => :mind_rune, :altar => 2479, :id => 558, :level => 1, :experience => 5.5, :multiplier => lambda { |level| (level / 14).floor + 1 }
append_rune :name => :water_rune, :altar => 2480, :id => 555, :level => 5, :experience => 6, :multiplier => lambda { |level| (level / 19).floor + 1 }
append_rune :name => :earth_rune, :altar => 2481, :id => 557, :level => 9, :experience => 6.5, :multiplier => lambda { |level| (level / 26).floor + 1 }
append_rune :name => :fire_rune, :altar => 2482, :id => 554, :level => 14, :experience => 7, :multiplier => lambda { |level| (level / 35).floor + 1 }
append_rune :name => :body_rune, :altar => 2483, :id => 559, :level => 20, :experience => 7.5, :multiplier => lambda { |level| (level / 46).floor + 1 }
append_rune :name => :cosmic_rune, :altar => 2484, :id => 564, :level => 27, :experience => 8, :multiplier => lambda { |level| level >= 59 ? 2 : 1 }
append_rune :name => :chaos_rune, :altar => 2487, :id => 562, :level => 35, :experience => 8.5, :multiplier => lambda { |level| level >= 74 ? 2 : 1 }
append_rune :name => :nature_rune, :altar => 2486, :id => 561, :level => 44, :experience => 9, :multiplier => lambda { |level| level >= 91 ? 2 : 1 }
append_rune :name => :law_rune, :altar => 2485, :id => 563, :level => 54, :experience => 9.5, :multiplier => lambda { |level| 1 }
append_rune :name => :death_rune, :altar => 2488, :id => 560, :level => 65, :experience => 10, :multiplier => lambda { |level| 1 }
+53
View File
@@ -0,0 +1,53 @@
require 'java'
java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
RUNECRAFTING_ANIMATION = Animation.new(791)
RUNECRAFTING_GRAPHIC = Graphic.new(186, 0, 100)
RUNE_ESSENCE_ID = 1436
# An action when the player crafts a rune.
class RunecraftingAction < DistancedAction
attr_reader :player, :rune
def initialize(player, rune, object_position)
super(1, true, player, object_position, 3)
@player = player
@rune = rune
@position = object_position
@executions = 0
end
def executeAction
runecrafting_level = @player.skill_set.get_skill(RUNECRAFT_SKILL_ID).current_level
if (runecrafting_level < @rune.level)
@player.send_message("You need a runecrafting level of #{@rune.level} to craft this rune.")
stop
elsif !@player.inventory.contains(RUNE_ESSENCE_ID)
@player.send_message('You need rune essence to craft runes.')
stop
elsif @executions == 0
@player.turn_to(@position)
@player.play_animation(RUNECRAFTING_ANIMATION)
@player.play_graphic(RUNECRAFTING_GRAPHIC)
@executions += 1
elsif @executions == 1
removed = @player.inventory.remove(RUNE_ESSENCE_ID, @player.inventory.get_amount(RUNE_ESSENCE_ID))
added = removed * @rune.multiplier(runecrafting_level)
@player.inventory.add(@rune.id, added)
@player.send_message("Your craft the rune essence into #{added > 1 ? 'some ' + @rune.name + 's' : 'an ' + @rune.name}.", true)
@player.skill_set.add_experience(RUNECRAFT_SKILL_ID, removed * @rune.experience)
stop
end
end
def equals(other)
return (get_class == other.get_class && @player == other.player && @rune == other.rune)
end
end
+54
View File
@@ -0,0 +1,54 @@
require 'java'
java_import 'org.apollo.game.model.Position'
# The list of talismans.
TALISMANS = {}
# A talisman that will indicate a direction when activated.
class Talisman
def initialize(entrance_altar_position)
@locate_position = entrance_altar_position
end
def get_message(player_position)
return 'Your talisman glows brightly.' if player_position.is_within_distance(@locate_position, 10)
direction = (player_position.y > @locate_position.y ? 'North' : 'South') + '-' + (player_position.x > @locate_position.x ? 'East' : 'West')
return "The talisman pulls toward the #{direction}."
end
end
# Appends a talisman to the list.
def append_talisman(hash)
raise 'Hash must contain an id and an altar position.' unless hash.has_key?(:id) && hash.has_key?(:altar)
id = hash[:id]; altar_position = Position.new(*hash[:altar])
TALISMANS[id] = Talisman.new(altar_position)
end
# Intercepts the item option event.
on :event, :item_option do |ctx, player, event|
if (event.option == 4)
talisman = TALISMANS[event.id]
if (talisman != nil)
player.send_message(talisman.get_message(player.position))
ctx.break_handler_chain
end
end
end
# Appends talismans to the list.
append_talisman :name => :air_talisman, :id => 1438, :altar => [ 2985, 3292 ]
append_talisman :name => :earth_talisman, :id => 1440, :altar => [ 3306, 3474 ]
append_talisman :name => :fire_talisman, :id => 1442, :altar => [ 3313, 3255 ]
append_talisman :name => :water_talisman, :id => 1444, :altar => [ 3185, 3165 ]
append_talisman :name => :body_talisman, :id => 1446, :altar => [ 3053, 3445 ]
append_talisman :name => :mind_talisman, :id => 1448, :altar => [ 2982, 3514 ]
append_talisman :name => :chaos_talisman, :id => 1452, :altar => [ 3059, 3590 ]
append_talisman :name => :cosmic_talisman, :id => 1454, :altar => [ 2408, 4377 ]
append_talisman :name => :death_talisman, :id => 1456, :altar => [ 0, 0 ]
append_talisman :name => :law_talisman, :id => 1458, :altar => [ 2858, 3381 ]
append_talisman :name => :nature_talisman, :id => 1462, :altar => [ 2869, 3019 ]