Default apollo.

This commit is contained in:
Major-
2013-10-27 17:45:36 +00:00
commit 08c72bf9aa
406 changed files with 23043 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
require 'java'
java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.inter.bank.BankUtils'
BANK_BOOTH_ID = 2213
BANK_BOOTH_SIZE = 1
class BankAction < DistancedAction
attr_reader :position
def initialize(character, position)
super 0, true, character, position, BANK_BOOTH_SIZE
@position = position
end
def executeAction
character.turn_to @position
BankUtils.open_bank character
stop
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
end
end
on :event, :object_action do |ctx, player, event|
if event.option == 2 and event.id == BANK_BOOTH_ID
player.startAction BankAction.new(player, event.position)
end
end
# TODO: when we have NPCs/dialogue, also respond to clicking on them
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>bank</id>
<version>1</version>
<name>Bank</name>
<description>Opens the bank interface when players select 'use-quickly' on a bank booth.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>bank.rb</script>
</scripts>
<dependencies />
</plugin>
+167
View File
@@ -0,0 +1,167 @@
# A script to 'bootstrap' all of the other plugins, wrapping Apollo's verbose
# Java-style API in a Ruby-style API.
#
# Written by Graham.
# ********************************** WARNING **********************************
# * If you do not really understand what this is for, do not edit it without *
# * creating a backup! Many plugins rely on the behaviour of this script, and *
# * will break if you mess it up. *
# * *
# * This is actually part of the core server and in an ideal world shouldn't *
# * be changed. *
# *****************************************************************************
require 'java'
java_import 'org.apollo.game.event.handler.EventHandler'
java_import 'org.apollo.game.command.PrivilegedCommandListener'
java_import 'org.apollo.game.model.Player'
java_import 'org.apollo.game.model.World'
java_import 'org.apollo.game.scheduling.ScheduledTask'
# Alias the privilege levels.
RIGHTS_ADMIN = Player::PrivilegeLevel::ADMINISTRATOR
RIGHTS_MOD = Player::PrivilegeLevel::MODERATOR
RIGHTS_STANDARD = Player::PrivilegeLevel::STANDARD
# Extends the (Ruby) String class with a method to convert a lower case,
# underscore delimited string to camel-case.
class String
def camelize
gsub(/(?:^|_)(.)/) { $1.upcase }
end
end
# A CommandListener which executes a Proc object with two arguments: the player
# and the command.
class ProcCommandListener < PrivilegedCommandListener
def initialize(rights, block)
super rights
@block = block
end
def executePrivileged(player, command)
@block.call player, command
end
end
# An EventHandler which executes a Proc object with three arguments: the chain
# context, the player and the event.
class ProcEventHandler < EventHandler
def initialize(block)
super() # required (with brackets!), see http://jira.codehaus.org/browse/JRUBY-679
@block = block
end
def handle(ctx, player, event)
@block.call ctx, player, event
end
end
# A ScheduledTask which executes a Proc object with one argument (itself).
class ProcScheduledTask < ScheduledTask
def initialize(delay, immediate, block)
super delay, immediate
@block = block
end
def execute
@block.call self
end
end
# Schedules a ScheduledTask. Can be used in two ways: passing an existing
# ScheduledTask object or passing a block along with one or two parameters: the
# delay (in pulses) and, optionally, the immediate flag.
#
# If the immediate flag is not given, it defaults to false.
#
# The ScheduledTask object is passed to the block so that methods such as
# setDelay and stop can be called. execute MUST NOT be called - if it is, the
# behaviour is undefined (and most likely it'll be bad).
def schedule(*args, &block)
if block_given?
if args.length == 1 or args.length == 2
delay = args[0]
immediate = args.length == 2 ? args[1] : false
World.world.schedule ProcScheduledTask.new(delay, immediate, block)
else
raise "invalid combination of arguments"
end
elsif args.length == 1
World.world.schedule args[0]
else
raise "invalid combination of arguments"
end
end
# Defines some sort of action to take upon an event. The following 'kinds' of
# event are currently valid:
#
# * :command
# * :event
# * :button
#
# A command takes one or two arguments (the command name and optionally the
# minimum rights level to use it). The minimum rights level defaults to
# STANDARD. The block should have two arguments: player and command.
#
# An event takes no arguments. The block should have three arguments: the chain
# context, the player and the event object.
#
# A button takes one argument (the id). The block should have one argument: the
# player who clicked the button.
def on(kind, *args, &block)
case kind
when :command then on_command(args, block)
when :event then on_event(args, block)
when :button then on_button(args, block)
else raise "unknown event type"
end
end
# Defines an action to be taken upon a button press.
def on_button(args, proc)
if args.length != 1
raise "button must have one argument"
end
id = args[0].to_i
on :event, :button do |ctx, player, event|
if event.interface_id == id
proc.call player
end
end
end
# Defines an action to be taken upon an event.
# The event can either be a symbol with the lower case, underscored class name
# or the class itself.
def on_event(args, proc)
if args.length != 1
raise "event must have one argument"
end
evt = args[0]
if evt.is_a? Symbol
class_name = evt.to_s.camelize.concat "Event"
evt = Java::JavaClass.for_name("org.apollo.game.event.impl.".concat class_name)
end
$ctx.add_last_event_handler evt, ProcEventHandler.new(proc)
end
# Defines an action to be taken upon a command.
def on_command(args, proc)
if args.length != 1 and args.length != 2
raise "command event must have one or two arguments"
end
rights = RIGHTS_STANDARD
if args.length == 2
rights = args[1]
end
$ctx.add_command_listener args[0].to_s, ProcCommandListener.new(rights, proc)
end
+6
View File
@@ -0,0 +1,6 @@
require 'java'
java_import 'org.apollo.game.model.inter.bank.BankUtils'
on :command, :bank, RIGHTS_ADMIN do |player, command|
BankUtils.open_bank player
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>cmd-bank</id>
<version>1</version>
<name>Bank Command</name>
<description>Adds a ::bank command.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>bank.rb</script>
</scripts>
<dependencies />
</plugin>
+27
View File
@@ -0,0 +1,27 @@
on :command, :item, RIGHTS_ADMIN do |player, command|
args = command.arguments
if (1..2).include? args.length
id = args[0].to_i
amount = args.length == 2 ? args[1].to_i : 1
player.inventory.add id, amount
else
player.send_message "Syntax: ::item [id] [amount=1]"
end
end
on :command, :destroy, RIGHTS_ADMIN do |player, command|
args = command.arguments
if (1..2).include? args.length
id = args[0].to_i
amount = args.length == 2 ? args[1].to_i : 1
player.inventory.remove id, amount
else
player.send_message "Syntax: ::destroy [id] [amount=1]"
end
end
on :command, :empty, RIGHTS_ADMIN do |player, command|
player.inventory.clear
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>cmd-item</id>
<version>1</version>
<name>Item Commands</name>
<description>Adds ::item, ::destroy and ::empty commands.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>item.rb</script>
</scripts>
<dependencies />
</plugin>
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>cmd-skill</id>
<version>1</version>
<name>Skill Commands</name>
<description>Adds a ::max command.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>skill.rb</script>
</scripts>
<dependencies />
</plugin>
+9
View File
@@ -0,0 +1,9 @@
require 'java'
java_import 'org.apollo.game.model.SkillSet'
on :command, :max, RIGHTS_ADMIN do |player, command|
skills = player.skill_set
(0...skills.size).each do |skill|
skills.add_experience(skill, SkillSet::MAXIMUM_EXP)
end
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>cmd-teleport</id>
<version>1</version>
<name>Teleport Commands</name>
<description>Adds ::pos and ::tele commands.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>teleport.rb</script>
</scripts>
<dependencies />
</plugin>
+19
View File
@@ -0,0 +1,19 @@
require 'java'
java_import 'org.apollo.game.model.Position'
on :command, :pos, RIGHTS_ADMIN do |player, command|
player.send_message "You are at: " + player.position.to_s
end
on :command, :tele, RIGHTS_ADMIN do |player, command|
args = command.arguments
if (2..3).include? args.length
x = args[0].to_i
y = args[1].to_i
z = args.length == 3 ? args[2].to_i : 0
player.teleport Position.new(x, y, z)
else
player.send_message "Syntax: ::tele [x] [y] [z=0]"
end
end
+55
View File
@@ -0,0 +1,55 @@
require 'java'
java_import 'org.apollo.game.action.DistancedAction'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Skill'
# TODO: this shouldn't use the punch animation/delay, but should use the one
# from the active weapon/attack style (according to Scu11 anyway).
DUMMY_ID = 823
DUMMY_SIZE = 1
PUNCH_ANIMATION = 422
ANIMATION_PULSES = 0 # TODO: might be more if hitting it actually works instead of showing 'nothing more' msg?
LEVEL_THRESHOLD = 8
EXP_PER_HIT = 5
class DummyAction < DistancedAction
attr_reader :position
def initialize(character, position)
super ANIMATION_PULSES, true, character, position, DUMMY_SIZE
@position = position
@started = false
end
def executeAction
if not @started
@started = true
character.send_message "You hit the dummy."
character.turn_to @position
character.play_animation Animation.new(PUNCH_ANIMATION)
else
skills = character.skill_set
if skills.skill(Skill::ATTACK).maximum_level >= LEVEL_THRESHOLD then
character.send_message "There is nothing more you can learn from hitting a dummy."
else
skills.add_experience Skill::ATTACK, EXP_PER_HIT
end
stop
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
end
end
on :event, :object_action do |ctx, player, event|
if event.option == 2 and event.id == DUMMY_ID
player.start_action DummyAction.new(player, event.position)
end
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>dummy</id>
<version>1</version>
<name>Dummies</name>
<description>Allows low-level players to train on dummies.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>dummy.rb</script>
</scripts>
<dependencies />
</plugin>
+7
View File
@@ -0,0 +1,7 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
on :command, :hello do |player, command|
player.play_animation Animation::WAVE
player.send_message "Hello, World!"
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>hello</id>
<version>1</version>
<name>Hello World Command</name>
<description>Adds a ::hello command which simply prints 'Hello, World!'.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>hello.rb</script>
</scripts>
<dependencies />
</plugin>
+5
View File
@@ -0,0 +1,5 @@
LOGOUT_BUTTON_ID = 2458
on :button, LOGOUT_BUTTON_ID do |player|
player.logout
end
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<plugin>
<id>logout</id>
<version>1</version>
<name>Logout Button</name>
<description>Adds the logout button.</description>
<authors>
<author>Graham</author>
</authors>
<scripts>
<script>logout.rb</script>
</scripts>
<dependencies />
</plugin>
+19
View File
@@ -0,0 +1,19 @@
GEMS = {}
class Gem
attr_reader :id, :chance
def initialize(id, chance)
@id = id
@chance = chance
end
end
def append_gem(gem)
GEMS[gem.id] = gem
end
append_gem(Gem.new(1623, 0)) # uncut sapphire
append_gem(Gem.new(1605, 0)) # uncut emerald
append_gem(Gem.new(1619, 0)) # uncut ruby
append_gem(Gem.new(1617, 0)) # uncut diamond
+163
View File
@@ -0,0 +1,163 @@
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(character, position, ore)
super 0, true, character, position, ORE_SIZE
@position = position
@ore = ore
@started = false
@counter = 0
end
def find_pickaxe
PICKAXE_IDS.each do |id|
weapon = character.equipment.get EquipmentConstants::WEAPON
if weapon.id == id
return PICKAXES[id]
end
if character.inventory.contains id
return PICKAXES[id]
end
end
return nil
end
# starts the mining animation, sets counters/flags and turns the character to
# the ore
def start_mine(pickaxe)
@started = true
character.send_message "You swing your pick at the rock."
character.turn_to @position
character.play_animation pickaxe.animation
@counter = pickaxe.pulses
end
def executeAction
skills = character.skill_set
level = skills.get_skill(Skill::MINING).maximum_level # TODO: is using max level correct?
pickaxe = find_pickaxe
# verify the player can mine with their pickaxe
if not (pickaxe != nil and level >= pickaxe.level)
character.send_message "You do not have a pickaxe for which you have the level to use."
stop
return
end
# verify the player can mine the ore
if ore.level > level
character.send_message "You do not have the required level to mine this rock."
stop
return
end
# check if we need to kick start things
if not @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 player can actually get the rock
if character.inventory.add ore.id
ore_def = ItemDefinition.for_id @ore.id # TODO: split off into some method
name = ore_def.name.sub(/ ore$/, "").downcase
character.send_message "You manage to mine some #{name}."
skills.add_experience Skill::MINING, 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(character, position)
super 0, true, character, position, ORE_SIZE
end
def executeAction
character.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(character, position, ore)
super PROSPECT_PULSES, true, character, position, ORE_SIZE
@position = position
@ore = ore
@started = false
end
def executeAction
if not @started
@started = true
character.send_message "You examine the rock for ores..."
character.turn_to @position
else
ore_def = ItemDefinition.for_id @ore.id
name = ore_def.name.sub(/ ore$/, "").downcase
character.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, player, event|
if event.option == 1
ore = ORES[event.id]
if ore != nil
player.startAction MiningAction.new(player, event.position, ore)
end
end
end
on :event, :object_action do |ctx, player, event|
if event.option == 2
ore = ORES[event.id]
if ore != nil
player.startAction ProspectingAction.new(player, event.position, ore)
else
if EXPIRED_ORES[event.id] != nil
player.startAction ExpiredProspectingAction.new(player, event.position)
end
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
+31
View File
@@ -0,0 +1,31 @@
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>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>
+18
View File
@@ -0,0 +1,18 @@
MAX_PLAYERS = 2000 # TODO: obtain from a Java class
# 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 / (MAX_PLAYERS * 2)
end