Update all plugins to conform to Rubocop.

This commit is contained in:
Major-
2015-08-27 18:17:58 +01:00
parent 424d2bda29
commit 8f3fd75b33
75 changed files with 1625 additions and 1537 deletions
+1 -5
View File
@@ -3,18 +3,14 @@ require 'java'
java_import 'org.apollo.game.message.impl.DisplayCrossbonesMessage'
java_import 'org.apollo.game.model.entity.Player'
# Registers an area action.
def area_action(name, &block)
AREA_ACTIONS[name] = action = AreaAction.new
action.instance_eval(&block)
end
AREA_ACTIONS = {}
private
# An action that is called when a player enters or exits an area.
@@ -50,4 +46,4 @@ class AreaAction
@on_exit.call(player) unless @on_exit.nil?
end
end
end
+16 -17
View File
@@ -4,19 +4,18 @@ java_import 'org.apollo.game.model.Position'
java_import 'org.apollo.game.model.entity.EntityType'
java_import 'org.apollo.game.model.entity.Player'
# Creates a new area and registers it with the supplied coordinates.
def area(hash)
raise 'Hash must contain a name, coordinates, and actions pair.' unless hash.has_keys?(:name, :coordinates, :actions)
name = hash[:name]; coordinates = hash[:coordinates]; actions = hash[:actions]
failure_message = 'Hash must contain a name, coordinates, and actions pair.'
fail failure_message unless hash.has_keys?(:name, :coordinates, :actions)
actions = [ actions ] if actions.is_a?(Symbol)
actions.map! { |action| AREA_ACTIONS[action]}
name, coordinates, actions = hash[:name], hash[:coordinates], hash[:actions]
actions = [actions] if actions.is_a?(Symbol)
actions.map! { |action| AREA_ACTIONS[action] }
@areas << Area.new(name, coordinates, actions)
end
private
# A map of coordinates (as an array) to areas.
@@ -31,23 +30,23 @@ class Area
@actions = actions
end
def min_x() # TODO better data structure and methods than this
def min_x # TODO: better data structure and methods than this
@coordinates[0]
end
def min_y()
def min_y
@coordinates[1]
end
def max_x()
def max_x
@coordinates[2]
end
def max_y()
def max_y
@coordinates[3]
end
def height()
def height
@coordinates[4]
end
@@ -79,7 +78,7 @@ on :mob_position_update do |event|
next_inside = event.next.inside(area)
if was_inside
if next_inside then area.inside(mob) else area.exited(mob) end
next_inside ? area.inside(mob) : area.exited(mob)
else
area.entered(mob) if next_inside
end
@@ -91,10 +90,10 @@ class Position
# Returns whether or not this Position is inside the specified Area.
def inside(area)
return false if (x < area.min_x() || x > area.max_x() || y < area.min_y() || y > area.max_y())
z = area.height()
return false if x < area.min_x || x > area.max_x || y < area.min_y || y > area.max_y
z = area.height
return true if (z.nil? || z == height)
z.nil? || z == height
end
end
end
+4 -3
View File
@@ -7,7 +7,8 @@ BANK_BOOTH_ID = 2213
BANK_BOOTH_SIZE = 1
# The npcs with a 'bank' menu action.
BANKER_NPCS = [ 166, 494, 495, 496, 497, 498, 499, 1036, 1360, 1702, 2163, 2164, 2354, 2355, 2568, 2569, 2570 ]
BANKER_NPCS = [166, 494, 495, 496, 497, 498, 499, 1036, 1360, 1702, 2163, 2164, 2354, 2355, 2568,
2569, 2570]
# A distanced action to open a new bank.
class BankAction < DistancedAction
@@ -25,7 +26,7 @@ class BankAction < DistancedAction
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
get_class == other.get_class && @position == other.position
end
end
@@ -43,4 +44,4 @@ on :message, :second_npc_action do |player, message|
player.start_action(BankAction.new(player, npc.position))
message.terminate
end
end
end
+27 -27
View File
@@ -1,7 +1,5 @@
# A script to 'bootstrap' all of the other plugins, wrapping Apollo's verbose
# Java-style API in a Ruby-style API.
#
# Written by Graham.
# A script bootstrapper for the rest of the plugins, which wraps Apollo's
# verbose Java-style API in a Ruby-style API.
# ********************************** WARNING **********************************
# * If you do not really understand what this is for, do not edit it without *
@@ -34,7 +32,7 @@ RIGHTS_STANDARD = PrivilegeLevel::STANDARD
class String
# Converts a ruby snake_case string to camel-case.
def camelize()
def camelize
gsub(/(?:^|_)(.)/) { $1.upcase }
end
@@ -53,7 +51,7 @@ class ProcCommandListener < CommandListener
def execute(player, command)
@block.call(player, command)
end
end
# A LogoutListener that executes a Proc object with the player argument.
@@ -68,8 +66,8 @@ class ProcEventListener
# Executes the block handling the Event.
def handle(event)
args = [ event ]
args << event.player if event.kind_of?(PlayerEvent)
args = [event]
args << event.player if event.is_a?(PlayerEvent)
@block.call(*args)
end
@@ -87,7 +85,7 @@ class ProcMessageHandler < MessageHandler
# Handles the message.
def handle(player, message)
@block.call(player, message) if (@option == 0 || @option == message.option)
@block.call(player, message) if @option == 0 || @option == message.option
end
end
@@ -119,14 +117,15 @@ end
# behaviour is undefined (and most likely it'll be bad).
def schedule(*args, &block)
if block_given?
raise 'Invalid combination of arguments.' unless (1..2).include?(args.length)
fail 'Invalid combination of arguments.' unless (1..2).include?(args.length)
delay = args[0]
immediate = args.length == 2 ? args[1] : false
$world.schedule(ProcScheduledTask.new(delay, immediate, block))
elsif args.length == 1
$world.schedule(args[0])
else
raise 'Invalid combination of arguments.'
fail 'Invalid combination of arguments.'
end
end
@@ -153,15 +152,15 @@ def on(type, *args, &block)
when :message then on_message(args, block)
when :button then on_button(args, block)
else
class_name = type.to_s.camelize.concat('Event')
type = Java::JavaClass.for_name("org.apollo.game.model.event.impl.#{class_name}")
$world.listen_for(type, ProcEventListener.new(block))
class_name = type.to_s.camelize.concat('Event')
type = Java::JavaClass.for_name("org.apollo.game.model.event.impl.#{class_name}")
$world.listen_for(type, ProcEventListener.new(block))
end
end
# Defines an action to be taken upon a button press.
def on_button(args, proc)
raise 'Button must have one argument.' unless args.length == 1
fail 'Button must have one argument.' unless args.length == 1
id = args[0].to_i
@@ -171,24 +170,25 @@ def on_button(args, proc)
end
# Defines an action to be taken upon a message.
# The message can either be a symbol with the lower-case underscored class name, or the class itself.
# The message can either be a symbol with the lowercase underscored class name, or the class itself.
def on_message(args, proc)
raise 'Message must have one or two arguments.' unless (1..2).include?(args.length)
numbers = [ 'first', 'second', 'third', 'fourth', 'fifth' ]
message = args[0]; option = 0
fail 'Message must have one or two arguments.' unless (1..2).include?(args.length)
numbers.each_index do |index|
numbers = %w(first second third fourth fifth)
message = args[0].to_s
option = 0
(0..numbers.length).each do |index|
number = numbers[index]
if message.to_s.start_with?(number)
if message.start_with?(number)
option = index + 1
message = message[number.length + 1, message.length].to_sym
message = message[number.length + 1, message.length]
break
end
end
class_name = message.to_s.camelize.concat('Message')
class_name = message.camelize.concat('Message')
message = Java::JavaClass.for_name("org.apollo.game.message.impl.#{class_name}")
$ctx.add_message_handler(message, ProcMessageHandler.new(proc, option))
@@ -196,8 +196,8 @@ end
# Defines an action to be taken upon a command.
def on_command(args, proc)
raise 'Command message must have one or two arguments.' unless (1..2).include?(args.length)
fail 'Command message must have one or two arguments.' unless (1..2).include?(args.length)
rights = args.length == 2 ? args[1] : RIGHTS_STANDARD
$world.command_dispatcher.register(args[0].to_s, ProcCommandListener.new(rights, proc))
end
end
+1 -1
View File
@@ -9,4 +9,4 @@ on :message, :privacy_option do |player, message|
player.trade_privacy = message.trade_privacy
update_friends(player, message.friend_privacy == PrivacyState::OFF ? 0 : player.world_id)
end
end
+33 -22
View File
@@ -8,9 +8,8 @@ java_import 'org.apollo.game.model.entity.setting.ServerStatus'
java_import 'org.apollo.game.model.entity.setting.PrivacyState'
java_import 'org.apollo.game.model.entity.Player'
# Processes an add friend message, updating the logged-in status of the player (and the person they added) if necessary.
# Processes an add friend message, updating the logged-in status of the player (and the person they
# added) if necessary.
on :message, :add_friend do |player, message|
friend_username = message.username
player_username = player.username
@@ -18,14 +17,23 @@ on :message, :add_friend do |player, message|
player.add_friend(friend_username)
friend = $world.get_player(friend_username)
if friend == nil # the friend the player added is offline
if friend.nil? # the friend the player added is offline
player.send(SendFriendMessage.new(friend_username, 0))
elsif friend.friends_with(player_username) # new friend already has the player added
friend.send(SendFriendMessage.new(player_username, player.world_id)) unless player.friend_privacy == PrivacyState::OFF # player's private chat state is not off, so notify the friend
elsif friend.friends_with(player_username)
player.send(SendFriendMessage.new(friend_username, friend.world_id)) unless friend.friend_privacy == PrivacyState::OFF # new friend's private chat state is not off, so notify the player
elsif friend.friend_privacy == PrivacyState::ON # new friend doesn't have the player added but their private chat state is on
player.send(SendFriendMessage.new(friend_username, friend.world_id)) # so we can let the player know what world they're on
# player's private chat state is not off, so notify the friend
unless player.friend_privacy == PrivacyState::OFF
friend.send(SendFriendMessage.new(player_username, player.world_id))
end
# new friend's private chat state is not off, so notify the player
unless friend.friend_privacy == PrivacyState::OFF
player.send(SendFriendMessage.new(friend_username, friend.world_id))
end
elsif friend.friend_privacy == PrivacyState::ON
# new friend doesn't have the player added but their private chat state is on, so inform the
# player of the world they are on.
player.send(SendFriendMessage.new(friend_username, friend.world_id))
end
end
@@ -35,24 +43,28 @@ on :message, :remove_friend do |player, message|
player_username = player.username
player.remove_friend(friend_username)
if ($world.is_player_online(friend_username))
if $world.is_player_online(friend_username)
friend = $world.get_player(friend_username)
friend.send(SendFriendMessage.new(player_username, 0)) if (friend.friends_with(player_username) && player.friend_privacy != PrivacyState::ON)
remove = friend.friends_with(player_username) && player.friend_privacy != PrivacyState::ON
friend.send(SendFriendMessage.new(player_username, 0)) if remove
end
end
# Update the friend server status and send the friend/ignore lists of the player logging in.
on :login do |event, player|
on :login do |_event, player|
player.send(FriendServerStatusMessage.new(ServerStatus::CONNECTING))
player.send(IgnoreListMessage.new(player.ignored_usernames)) if player.ignored_usernames.size > 0
username = player.username
world = $world
iterator = player.friend_usernames.iterator # Iterate the player's friend list and notify the player that they are online if they are
iterator = player.friend_usernames.iterator
# Iterate the player's friend list and notify the player that they are online if they are
while iterator.has_next
friend_username = iterator.next
friend = world.get_player(friend_username)
friend_world_id = (friend == nil || !viewable?(friend, username)) ? 0 : friend.world_id
friend_world_id = (friend.nil? || !viewable?(friend, username)) ? 0 : friend.world_id
player.send(SendFriendMessage.new(friend_username, friend_world_id))
end
@@ -62,22 +74,21 @@ on :login do |event, player|
end
# Notifies the player's friends that the player has logged out.
on :logout do |event, player|
on :logout do |_event, player|
update_friends(player, 0)
end
# Notifies the currently logged in players that the specified player has logged into the specified world, unless the
# newly logged-in player has their friend privacy state set to 'off'.
def update_friends(player, world=0)
# Notifies the currently logged in players that the specified player has logged into the specified
# world, unless the newly logged-in player has their friend privacy state set to 'off'.
def update_friends(player, world = 0)
privacy = player.friend_privacy
iterator = $world.player_repository.iterator
username = player.username
while iterator.has_next
other = iterator.next
next if (!other.friends_with(username) || other == player)
next if !other.friends_with(username) || other == player
world = viewable?(player, other.username) ? world : 0
other.send(SendFriendMessage.new(username, world))
@@ -87,5 +98,5 @@ end
# Checks if the specified player can be viewed by the player with the specified other username
def viewable?(player, other_username)
privacy = player.friend_privacy
return privacy != PrivacyState::OFF && player.friends_with(other_username) || privacy == PrivacyState::ON
privacy != PrivacyState::OFF && player.friends_with(other_username) || privacy == PrivacyState::ON
end
@@ -6,14 +6,18 @@ java_import 'org.apollo.game.model.entity.setting.PrivacyState'
on :message, :private_chat do |player, message|
friend = $world.get_player(message.username)
friend.send(ForwardPrivateChatMessage.new(player.username, player.privilege_level, message.compressed_chat)) if interaction_permitted(player, friend)
if interaction_permitted(player, friend)
chat = message.compressed_chat
friend.send(ForwardPrivateChatMessage.new(player.username, player.privilege_level, chat))
end
end
# Checks if the sender is permitted to interact with the friend they have added:
def interaction_permitted(sender, friend)
if friend.nil? || friend.has_ignored(sender.username)
return false
end
return friend.friends_with(sender.username) ? (friend.friend_privacy != PrivacyState::OFF) : (friend.friend_privacy == PrivacyState::ON)
end
username = sender.username
return false if friend.nil? || friend.has_ignored(username)
privacy = friend.friend_privacy
friend.friends_with(username) ? (privacy != PrivacyState::OFF) : (privacy == PrivacyState::ON)
end
+1 -1
View File
@@ -17,4 +17,4 @@ on :command, :graphic, RIGHTS_MOD do |player, command|
next unless valid_arg_length(args, 1, player, 'Invalid syntax - ::graphic [graphic-id]')
player.play_graphic(Graphic.new(args[0].to_i))
end
end
+2 -2
View File
@@ -1,6 +1,6 @@
require 'java'
# Opens the player's bank.
on :command, :bank, RIGHTS_ADMIN do |player, command|
on :command, :bank, RIGHTS_ADMIN do |player, _command|
player.open_bank
end
end
+8 -6
View File
@@ -6,10 +6,11 @@ java_import 'org.apollo.cache.def.ItemDefinition'
on :command, :item, RIGHTS_ADMIN do |player, command|
args = command.arguments
next unless valid_arg_length(args, (1..2), player, 'Invalid syntax - ::item [id] [amount]')
id = args[0].to_i
amount = args.length == 2 ? args[1].to_i : 1
if (id < 0 || id >= ItemDefinition.count)
if id < 0 || id >= ItemDefinition.count
player.send_message('The item id you specified is out of bounds!')
next
end
@@ -24,7 +25,8 @@ on :command, :remove, RIGHTS_MOD do |player, command|
id = args[0].to_i
amount = args.length == 2 ? args[1].to_i : 1
if (id < 0 || id >= ItemDefinition.count)
if id < 0 || id >= ItemDefinition.count
player.send_message('The item id you specified is out of bounds!')
next
end
@@ -33,11 +35,11 @@ on :command, :remove, RIGHTS_MOD do |player, command|
end
# Clears the player's inventory.
on :command, :empty, RIGHTS_MOD do |player, command|
on :command, :empty, RIGHTS_MOD do |player, _command|
player.inventory.clear
end
# Gives the player 1,000 of each rune.
on :command, :runes, RIGHTS_ADMIN do |player, command|
on :command, :runes, RIGHTS_ADMIN do |player, _command|
(554..566).each { |item| player.inventory.add(item, 1000) }
end
end
+17 -12
View File
@@ -9,20 +9,22 @@ java_import 'org.apollo.game.model.entity.Player'
on :command, :lookup, RIGHTS_ADMIN do |player, command|
args = command.arguments.to_a
next unless valid_arg_length(args, (1..10), player, 'Invalid syntax - ::lookup [npc/object/item] [name]')
message = 'Invalid syntax - ::lookup [npc/object/item] [name]'
next unless valid_arg_length(args, (1..10), player, message)
type = args.shift.downcase
limit = args.first.to_i == 0 ? 5 : args.shift.to_i;
limit = args.first.to_i == 0 ? 5 : args.shift.to_i
name = args.join(' ').downcase
if ['npc', 'object', 'item'].index(type) == nil
player.send_message('Invalid syntax - ::lookup [npc/object/item] [name]')
if %w(npc object item).index(type).nil?
player.send_message('Invalid syntax - ::lookup [npc/object/item] [name]')
next
end
ids = find_entities(type, name, limit).join(', ')
message = ids.empty? ? "Could not find an #{type} called #{name}." : "Possible ids for \"#{name}\" are: #{ids}."
message = ids.empty? ? "Could not find an #{type} called #{name}." :
"Possible ids for \"#{name}\" are: #{ids}."
player.send_message(message)
end
@@ -35,7 +37,8 @@ on :command, :iteminfo, RIGHTS_ADMIN do |player, command|
definition = ItemDefinition.lookup(id)
members = definition.is_members_only ? 'members' : 'not members'
player.send_message("Item #{id} is called #{definition.name}, is #{members} only, and has a team of #{definition.team}.")
player.send_message("Item #{id} is called #{definition.name}, is #{members} only, and has a "\
"team of #{definition.team}.")
player.send_message("Its description is \"#{definition.description}\".")
end
@@ -46,7 +49,8 @@ on :command, :npcinfo, RIGHTS_ADMIN do |player, command|
id = args[0].to_i
definition = NpcDefinition.lookup(id)
is_combative = definition.has_combat_level ? "has a combat level of #{definition.combat_level}" : "does not have a combat level"
is_combative = definition.has_combat_level ? "has a combat level of #{definition.combat_level}" :
'does not have a combat level'
player.send_message("Npc #{id} is called #{definition.name} and #{is_combative}.")
player.send_message("Its description is \"#{definition.description}\".")
@@ -59,6 +63,7 @@ on :command, :objectinfo, RIGHTS_ADMIN do |player, command|
id = args[0].to_i
definition = ObjectDefinition.lookup(id)
player.send_message("Object #{id} is called #{definition.name} and its description is \"#{definition.description}\".")
player.send_message("Object #{id} is called #{definition.name} and its description is "\
"\"#{definition.description}\".")
player.send_message("Its width is #{definition.width} and its length is #{definition.length}.")
end
end
+4 -3
View File
@@ -5,7 +5,8 @@ java_import 'org.apollo.game.model.entity.Player'
# Adds a command to broadcast a message to every player on the server.
on :command, :broadcast, RIGHTS_ADMIN do |player, command|
message = command.arguments.to_a.join(" ")
message = command.arguments.to_a.join(' ')
broadcast = "[Broadcast] #{player.get_username.capitalize}: #{message}"
$world.player_repository.each { |player| player.send_message(broadcast) }
end
$world.player_repository.each { |other| other.send_message(broadcast) }
end
+3 -2
View File
@@ -1,5 +1,6 @@
require 'java'
on :command, :filter do |player, command|
player.send_message('Your message filter is now ' + (player.toggle_message_filter ? 'enabled.' : 'disabled.'))
end
status = player.toggle_message_filter ? 'enabled' : 'disabled'
player.send_message('Your message filter is now ' + status + '.')
end
+20 -13
View File
@@ -7,11 +7,12 @@ java_import 'org.apollo.game.model.entity.Npc'
# An array of npcs that cannot be spawned.
blacklist = []
# Spawns a non-blacklisted npc in the specified position, or the player's position if both 'x' and 'y' are not supplied.
# Spawns a non-blacklisted npc in the specified position, or the player's position if both 'x' and
# 'y' are not supplied.
on :command, :spawn, RIGHTS_ADMIN do |player, command|
args = command.arguments
unless [1, 3].include?(args.length) and (id = args[0].to_i) > -1
player.send_message('Invalid syntax - ::spawn [npc id] [optional-x] [optional-y]')
unless [1, 3, 4].include?(args.length) && (id = args[0].to_i) > -1
player.send_message('Invalid syntax - ::spawn [npc id] [optional-x] [optional-y] [optional-z]')
return
end
@@ -20,7 +21,12 @@ on :command, :spawn, RIGHTS_ADMIN do |player, command|
return
end
position = args.length == 1 ? player.position : Position.new(args[1].to_i, args[2].to_i, player.position.height)
if args.length == 1
position = player.position
else
height = args.length == 4 ? args[3].to_i : player.position.height
position = Position.new(args[1].to_i, args[2].to_i, height)
end
$world.register(Npc.new(id, position))
end
@@ -28,7 +34,7 @@ end
# Mass spawns npcs around the player.
on :command, :mass, RIGHTS_ADMIN do |player, command|
args = command.arguments
unless args.length == 2 and (id = args[0].to_i) > -1 and (1..5).include?(range = args[1].to_i)
unless args.length == 2 && (id = args[0].to_i) > -1 && (1..5).include?(range = args[1].to_i)
player.send_message('Invalid syntax - ::spawn [npc id] [range (1-5)]')
return
end
@@ -40,22 +46,23 @@ on :command, :mass, RIGHTS_ADMIN do |player, command|
center_position = player.position
minX = center_position.x - range
minY = center_position.y - range
maxX = center_position.x + range
maxY = center_position.y + range
min_x = center_position.x - range
min_y = center_position.y - range
max_x = center_position.x + range
max_y = center_position.y + range
z = center_position.height
for x in minX..maxX do
for y in minY..maxY do
(min_x..max_x).each do |x|
(min_y..max_y).each do |y|
$world.register(Npc.new(id, Position.new(x, y, z)))
end
end
player.send_message("Mass spawning npcs with id #{id}.")
end
# Unregisters all npcs from the world npc repository.
on :command, :clearnpcs, RIGHTS_ADMIN do |player, command|
on :command, :clearnpcs, RIGHTS_ADMIN do |player, _command|
$world.npc_repository.each { |npc| $world.unregister(npc) }
player.send_message('Unregistered all npcs from the world.')
end
end
+11 -8
View File
@@ -3,8 +3,9 @@ java_import 'org.apollo.game.model.entity.SkillSet'
java_import 'org.apollo.game.model.entity.Skill'
# Maximises the player's skill set.
on :command, :max, RIGHTS_ADMIN do |player, command|
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
@@ -13,15 +14,16 @@ end
# Levels the specified skill to the specified level, optionally updating the current level as well.
on :command, :level, RIGHTS_ADMIN do |player, command|
args = command.arguments
unless (2..3).include?(args.length) && (0..20).include?(skill_id = args[0].to_i) && (1..99).include?(level = args[1].to_i)
player.send_message("Invalid syntax - ::level [skill-id] [level]")
unless (2..3).include?(args.length) && (0..20).include?(skill_id = args[0].to_i) &&
(1..99).include?(level = args[1].to_i)
player.send_message('Invalid syntax - ::level [skill-id] [level]')
return
end
experience = SkillSet.experience_for_level(level)
current = level
if args.length == 3 && args[2].to_s == "old"
if args.length == 3 && args[2].to_s == 'old'
skill = player.skill_set.skill(skill_id)
current = skill.current_level
end
@@ -32,10 +34,11 @@ end
# Adds the specified amount of experience to the specified skill.
on :command, :xp, RIGHTS_ADMIN do |player, command|
args = command.arguments
unless args.length == 2 && (0..20).include?(skill_id = args[0].to_i) && (experience = args[1].to_i) >= 0
player.send_message("Invalid syntax - ::xp [skill-id] [experience]")
unless args.length == 2 && (0..20).include?(skill_id = args[0].to_i) &&
(experience = args[1].to_i) >= 0
player.send_message('Invalid syntax - ::xp [skill-id] [experience]')
return
end
player.skill_set.add_experience(skill_id, experience)
end
end
+3 -5
View File
@@ -3,10 +3,8 @@ require 'java'
java_import 'org.apollo.game.model.Position'
# Sends the player's position.
on :command, :pos, RIGHTS_MOD do |player, command|
position = player.position
player.send_message("You are at: #{position}.")
player.send_message("Local coordinates: (#{position.get_local_x}, #{position.get_local_y}).")
on :command, :pos, RIGHTS_MOD do |player, _command|
player.send_message("You are at: #{player.position}.")
end
# Teleports the player to the specified position.
@@ -19,4 +17,4 @@ on :command, :tele, RIGHTS_ADMIN do |player, command|
z = args.length == 3 ? args[2].to_i : player.position.height
player.teleport(Position.new(x, y, z)) if (0..4).include?(z)
end
end
+18 -14
View File
@@ -4,6 +4,7 @@ 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
@@ -16,47 +17,50 @@ module WildernessConstants
end
declare_attribute(:wilderness_level, 0, :transient)
# Determines the wilderness level for the specified player's position
def wilderness_level(player)
return ((player.position.y - 3520) / 8).ceil
((player.position.y - 3520) / 8).ceil
end
area_action :wilderness_level do
on_entry do |player|
on_entry do |player|
player.wilderness_level = wilderness_level(player)
player.interface_set.open_overlay(WildernessConstants::OVERLAY_INTERFACE_ID)
player.send(SetWidgetTextMessage.new(WildernessConstants::LEVEL_STRING_ID, "Level: #{player.wilderness_level}"))
id = WildernessConstants::LEVEL_STRING_ID
player.send(SetWidgetTextMessage.new(id, "Level: #{player.wilderness_level}"))
show_action(player, ATTACK_ACTION)
end
while_in do |player|
current = player.wilderness_level
updated = wilderness_level(player)
if (current != updated)
player.wilderness_level = updated
player.send(SetWidgetTextMessage.new(WildernessConstants::LEVEL_STRING_ID, "Level: #{player.wilderness_level}"))
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|
player.wilderness_level = 0
player.interface_set.close()
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
# 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
self.wilderness_level > 0
wilderness_level > 0
end
end
area :name => :wilderness, :coordinates => [ 2945, 3522, 3390, 3972, 0 ], :actions => :wilderness_level
area name: :wilderness, coordinates: [2945, 3522, 3390, 3972, 0], actions: :wilderness_level
+10 -7
View File
@@ -3,10 +3,11 @@ require 'java'
# A map of item ids to consumables.
CONSUMABLES = {}
# The id of the food consumption animation.
CONSUME_ANIMATION_ID = 829
# An item that can be consumed to produce a skill effect.
class Consumable
class Consumable
attr_reader :name, :id, :sound
def initialize(name, id, sound)
@@ -15,8 +16,8 @@ class Consumable
@sound = sound
end
def consume(player)
# Override to provide specific functionality.
def consume(_player)
# Override to provide specific functionality.
end
end
@@ -26,6 +27,7 @@ def append_consumable(consumable)
CONSUMABLES[consumable.id] = consumable
end
# An Action used for food consumption.
class ConsumeAction < Action
attr_reader :consumable
@@ -36,10 +38,11 @@ class ConsumeAction < Action
@executions = 0
end
def execute()
def execute
if @executions == 0
mob.inventory.reset(@slot)
@consumable.consume(mob)
mob.play_animation(Animation.new(CONSUME_ANIMATION_ID))
@executions += 1
else
@@ -48,9 +51,9 @@ class ConsumeAction < Action
end
def equals(other)
return (mob == other.mob && @consumable.id == other.consumable.id)
mob == other.mob && @consumable.id == other.consumable.id
end
end
# Intercepts the first item option message and consumes the consumable, if necessary.
@@ -61,4 +64,4 @@ on :message, :first_item_option do |player, message|
player.start_action(ConsumeAction.new(player, message.slot, consumable))
message.terminate
end
end
end
+183 -178
View File
@@ -6,10 +6,11 @@ java_import 'org.apollo.game.model.entity.Player'
private
# The id the of the sound made when eating food.
EAT_FOOD_SOUND = 317
# Represents an edible piece of food, such as bread or fish.
# TODO delay eating times
# TODO: delay eating times
class Food < Consumable
def initialize(name, id, restoration, replace)
@@ -21,221 +22,225 @@ class Food < Consumable
# Restore the appropriate amount of hitpoints when consumed.
def consume(player)
hitpoints = player.skill_set.skill(Skill::HITPOINTS)
new_curr = [ hitpoints.current_level + @restoration, hitpoints.maximum_level ].min
new_curr = [hitpoints.current_level + @restoration, hitpoints.maximum_level].min
player.inventory.add(@replace) unless (@replace == -1)
player.inventory.add(@replace) unless @replace == -1
player.send_message("You eat the #{name}.", true)
player.send_message("It heals some health.", true) if new_curr == hitpoints
player.send_message('It heals some health.', true) if new_curr == hitpoints
player.skill_set.set_skill(Skill::HITPOINTS, Skill.new(hitpoints.experience, new_curr, hitpoints.maximum_level))
skill = Skill.new(hitpoints.experience, new_curr, hitpoints.maximum_level)
player.skill_set.set_skill(Skill::HITPOINTS, skill)
end
end
# The default delay before a piece of food is eaten
DEFAULT_DELAY = 3
# Appends a food item to the list of consumables.
def food(hash)
raise 'Hash must contain a name, id, and a restoration value.' unless (hash.has_keys?(:name, :id, :restoration))
name = hash[:name]; id = hash[:id]; restoration = hash[:restoration]; replace = hash[:replace] || -1; @delay = hash[:delay] || 3
unless hash.has_keys?(:name, :id, :restoration)
fail 'Hash must contain a name, id, and a restoration value.'
end
name, id, restoration = hash[:name], hash[:id], hash[:restoration];
replace = hash[:replace] || -1
delay = hash[:delay] || DEFAULT_DELAY # TODO: ??
append_consumable(Food.new(name, id, restoration, replace))
end
# TODO special effects
food :name => :cooked_slimy_eel, :id => 3381, :restoration => 6 # this has a chance to heal 6 to 10 hp
food :name => :thin_snail_meat, :id => 3369, :restoration => 5 # this has a chance to heal 5 to 7 hp
food :name => :fat_snail_meat, :id => 3373, :restoration => 2 # this has a chance to heal 7 to 9 hp
food :name => :watermelon_slice, :id => 5984, :restoration => 0 # this heals 5% of player's life
food :name => :cooked_karambwan, :id => 3146, :restoration => 0 # poisons player(50)
food :name => :spider_on_stick, :id => 6297, :restoration => 7 # heals between 7 and 10
food :name => :spider_on_shaft, :id => 6299, :restoration => 7 # heals between 7 and 10
# TODO: special effects
food name: :cooked_slimy_eel, id: 3381, restoration: 6 # this has a chance to heal 6 to 10 hp
food name: :thin_snail_meat, id: 3369, restoration: 5 # this has a chance to heal 5 to 7 hp
food name: :fat_snail_meat, id: 3373, restoration: 2 # this has a chance to heal 7 to 9 hp
food name: :watermelon_slice, id: 5984, restoration: 0 # this heals 5% of player's life
food name: :cooked_karambwan, id: 3146, restoration: 0 # poisons player(50)
food name: :spider_on_stick, id: 6297, restoration: 7 # heals between 7 and 10
food name: :spider_on_shaft, id: 6299, restoration: 7 # heals between 7 and 10
# Meats/Fish
food :name => :anchovies, :id => 319, :restoration => 1
food :name => :crab_meat, :id => 7521, :restoration => 2, :replace => 7523
food :name => :crab_meat, :id => 7523, :restoration => 2, :replace => 7524
food :name => :crab_meat, :id => 7524, :restoration => 2, :replace => 7525
food :name => :crab_meat, :id => 7525, :restoration => 2, :replace => 7526
food :name => :crab_meat, :id => 7526, :restoration => 2
food :name => :shrimp, :id => 315, :restoration => 3
food :name => :sardine, :id => 325, :restoration => 3
food :name => :cooked_meat, :id => 2142, :restoration => 3
food :name => :cooked_chicken, :id => 2140, :restoration => 3
food :name => :ugthanki_meat, :id => 1861, :restoration => 3
food :name => :karambwanji, :id => 3151, :restoration => 3
food :name => :cooked_rabbit, :id => 3228, :restoration => 5
food :name => :herring, :id => 347, :restoration => 6
food :name => :trout, :id => 333, :restoration => 7
food :name => :cod, :id => 339, :restoration => 7
food :name => :mackeral, :id => 355, :restoration => 7
food :name => :roast_rabbit, :id => 7223, :restoration => 7
food :name => :pike, :id => 351, :restoration => 8
food :name => :lean_snail_meat, :id => 3371, :restoration => 8
food :name => :salmon, :id => 329, :restoration => 9
food :name => :tuna, :id => 361, :restoration => 10
food :name => :lobster, :id => 379, :restoration => 12
food :name => :bass, :id => 365, :restoration => 13
food :name => :swordfish, :id => 373, :restoration => 14
food :name => :cooked_jubbly, :id => 7568, :restoration => 15
food :name => :monkfish, :id => 7946, :restoration => 16
food :name => :cooked_karambwan, :id => 3144, :restoration => 18
food :name => :shark, :id => 385, :restoration => 20
food :name => :sea_turtle, :id => 397, :restoration => 21
food :name => :manta_ray, :id => 391, :restoration => 22
# Meats/Fish
food name: :anchovies, id: 319, restoration: 1
food name: :crab_meat, id: 7521, restoration: 2, replace: 7523
food name: :crab_meat, id: 7523, restoration: 2, replace: 7524
food name: :crab_meat, id: 7524, restoration: 2, replace: 7525
food name: :crab_meat, id: 7525, restoration: 2, replace: 7526
food name: :crab_meat, id: 7526, restoration: 2
food name: :shrimp, id: 315, restoration: 3
food name: :sardine, id: 325, restoration: 3
food name: :cooked_meat, id: 2142, restoration: 3
food name: :cooked_chicken, id: 2140, restoration: 3
food name: :ugthanki_meat, id: 1861, restoration: 3
food name: :karambwanji, id: 3151, restoration: 3
food name: :cooked_rabbit, id: 3228, restoration: 5
food name: :herring, id: 347, restoration: 6
food name: :trout, id: 333, restoration: 7
food name: :cod, id: 339, restoration: 7
food name: :mackeral, id: 355, restoration: 7
food name: :roast_rabbit, id: 7223, restoration: 7
food name: :pike, id: 351, restoration: 8
food name: :lean_snail_meat, id: 3371, restoration: 8
food name: :salmon, id: 329, restoration: 9
food name: :tuna, id: 361, restoration: 10
food name: :lobster, id: 379, restoration: 12
food name: :bass, id: 365, restoration: 13
food name: :swordfish, id: 373, restoration: 14
food name: :cooked_jubbly, id: 7568, restoration: 15
food name: :monkfish, id: 7946, restoration: 16
food name: :cooked_karambwan, id: 3144, restoration: 18
food name: :shark, id: 385, restoration: 20
food name: :sea_turtle, id: 397, restoration: 21
food name: :manta_ray, id: 391, restoration: 22
# Breads/Wraps
food :name => :bread, :id => 2309, :restoration => 5
food :name => :oomlie_wrap, :id => 2343, :restoration => 14
food :name => :ugthanki_kebab, :id => 1883, :restoration => 19
# Breads/Wraps
food name: :bread, id: 2309, restoration: 5
food name: :oomlie_wrap, id: 2343, restoration: 14
food name: :ugthanki_kebab, id: 1883, restoration: 19
# Fruits
food :name => :banana, :id => 1963, :restoration => 2
food :name => :sliced_banana, :id => 3162, :restoration => 2
food :name => :lemon, :id => 2102, :restoration => 2
food :name => :lemon_chunks, :id => 2104, :restoration => 2
food :name => :lemon_slices, :id => 2106, :restoration => 2
food :name => :lime, :id => 2120, :restoration => 2
food :name => :lime_chunks, :id => 2122, :restoration => 2
food :name => :lime_slices, :id => 2124, :restoration => 2
food :name => :strawberry, :id => 5504, :restoration => 5
food :name => :papaya_fruit, :id => 5972, :restoration => 8
food :name => :pineapple_chunks, :id => 2116, :restoration => 2
food :name => :pineapple_ring, :id => 2118, :restoration => 2
food :name => :orange, :id => 2108, :restoration => 2
food :name => :orange_rings, :id => 2110, :restoration => 2
food :name => :orange_slices, :id => 2112, :restoration => 2
# Fruits
food name: :banana, id: 1963, restoration: 2
food name: :sliced_banana, id: 3162, restoration: 2
food name: :lemon, id: 2102, restoration: 2
food name: :lemon_chunks, id: 2104, restoration: 2
food name: :lemon_slices, id: 2106, restoration: 2
food name: :lime, id: 2120, restoration: 2
food name: :lime_chunks, id: 2122, restoration: 2
food name: :lime_slices, id: 2124, restoration: 2
food name: :strawberry, id: 5504, restoration: 5
food name: :papaya_fruit, id: 5972, restoration: 8
food name: :pineapple_chunks, id: 2116, restoration: 2
food name: :pineapple_ring, id: 2118, restoration: 2
food name: :orange, id: 2108, restoration: 2
food name: :orange_rings, id: 2110, restoration: 2
food name: :orange_slices, id: 2112, restoration: 2
# Pies
# TODO: pie special effects (e.g. fish pie raises fishing level)
food name: :redberry_pie, id: 2325, restoration: 5, replace: 2333, delay: 1
food name: :redberry_pie, id: 2333, restoration: 5, delay: 1
# Pies
#TODO Special Effects on pies (i.e.fish pie raises fishing level)
food :name => :redberry_pie, :id => 2325, :restoration => 5, :replace => 2333, :delay => 1
food :name => :redberry_pie, :id => 2333, :restoration => 5, :delay => 1
food name: :meat_pie, id: 2327, restoration: 6, replace: 2331, delay: 1
food name: :meat_pie, id: 2331, restoration: 6, delay: 1
food :name => :meat_pie, :id => 2327, :restoration => 6, :replace => 2331, :delay => 1
food :name => :meat_pie, :id => 2331, :restoration => 6, :delay => 1
food name: :apple_pie, id: 2323, restoration: 7, replace: 2335, delay: 1
food name: :apple_pie, id: 2335, restoration: 7, delay: 1
food :name => :apple_pie, :id => 2323, :restoration => 7, :replace => 2335, :delay => 1
food :name => :apple_pie, :id => 2335, :restoration => 7, :delay => 1
food name: :fish_pie, id: 7188, restoration: 6, replace: 7190, delay: 1
food name: :fish_pie, id: 7190, restoration: 6, delay: 1
food :name => :fish_pie, :id => 7188, :restoration => 6, :replace => 7190, :delay => 1
food :name => :fish_pie, :id => 7190, :restoration => 6, :delay => 1
food name: :admiral_pie, id: 7198, restoration: 8, replace: 7200, delay: 1
food name: :admiral_pie, id: 7200, restoration: 8, delay: 1
food :name => :admiral_pie, :id => 7198, :restoration => 8, :replace => 7200, :delay => 1
food :name => :admiral_pie, :id => 7200, :restoration => 8, :delay => 1
food name: :wild_pie, id: 7208, restoration: 11, replace: 7210, delay: 1
food name: :wild_pie, id: 7210, restoration: 11, delay: 1
food :name => :wild_pie, :id => 7208, :restoration => 11, :replace => 7210, :delay => 1
food :name => :wild_pie, :id => 7210, :restoration => 11, :delay => 1
food name: :summer_pie, id: 7218, restoration: 11, replace: 7220, delay: 1
food name: :summer_pie, id: 7220, restoration: 11, delay: 1
food :name => :summer_pie, :id => 7218, :restoration => 11, :replace => 7220, :delay => 1
food :name => :summer_pie, :id => 7220, :restoration => 11, :delay => 1
# Stews
food name: :stew, id: 2003, restoration: 11
food name: :banana_stew, id: 4016, restoration: 11
food name: :curry, id: 2011, restoration: 19
# Stews
food :name => :stew, :id => 2003, :restoration => 11
food :name => :banana_stew, :id => 4016, :restoration => 11
food :name => :curry, :id => 2011, :restoration => 19
# Pizzas
food name: :plain_pizza, id: 2289, restoration: 7, replace: 2291
food name: :plain_pizza, id: 2291, restoration: 7
# Pizzas
food :name => :plain_pizza, :id => 2289, :restoration => 7, :replace => 2291
food :name => :plain_pizza, :id => 2291, :restoration => 7
food name: :meat_pizza, id: 2293, restoration: 8, replace: 2295
food name: :meat_pizza, id: 2295, restoration: 8
food :name => :meat_pizza, :id => 2293, :restoration => 8, :replace => 2295
food :name => :meat_pizza, :id => 2295, :restoration => 8
food name: :anchovy_pizza, id: 2297, restoration: 9, replace: 2299
food name: :anchovy_pizza, id: 2299, restoration: 9
food :name => :anchovy_pizza, :id => 2297, :restoration => 9, :replace => 2299
food :name => :anchovy_pizza, :id => 2299, :restoration => 9
food name: :pineapple_pizza, id: 2301, restoration: 11, replace: 2303
food name: :pineapple_pizza, id: 2303, restoration: 11
food :name => :pineapple_pizza, :id => 2301, :restoration => 11, :replace => 2303
food :name => :pineapple_pizza, :id => 2303, :restoration => 11
# Cakes
food name: :fishcake, id: 7530, restoration: 11
# Cakes
food :name => :fishcake, :id => 7530, :restoration => 11
food name: :cake, id: 1891, restoration: 4, replace: 1893
food name: :cake, id: 1893, restoration: 4, replace: 1895
food name: :cake, id: 1895, restoration: 4
food :name => :cake, :id => 1891, :restoration => 4, :replace => 1893
food :name => :cake, :id => 1893, :restoration => 4, :replace => 1895
food :name => :cake, :id => 1895, :restoration => 4
food name: :chocolate_cake, id: 1897, restoration: 5, replace: 1899
food name: :chocolate_cake, id: 1899, restoration: 5, replace: 1901
food name: :chocolate_cake, id: 1901, restoration: 5
food :name => :chocolate_cake, :id => 1897, :restoration => 5, :replace => 1899
food :name => :chocolate_cake, :id => 1899, :restoration => 5, :replace => 1901
food :name => :chocolate_cake, :id => 1901, :restoration => 5
# Wine
# TODO: Add to drinks.rb?
food name: :jug_of_wine, id: 1993, restoration: 11
# Wine
# Add to drinks.rb?
food :name => :jug_of_wine, :id => 1993, :restoration => 11
# Hot Drinks
# TODO: Add to drinks.rb?
food name: :nettle_tea, id: 4239, restoration: 3
food name: :nettle_tea, id: 4240, restoration: 3
# Hot Drinks
# Add to drinks.rb?
food :name => :nettle_tea, :id => 4239, :restoration => 3
food :name => :nettle_tea, :id => 4240, :restoration => 3
# Vegetables
food name: :potato, id: 1942, restoration: 1
food name: :spinach_roll, id: 1969, restoration: 2
food name: :baked_potato, id: 6701, restoration: 4
food name: :sweetcorn, id: 5988, restoration: 10
food name: :sweetcorn_bowl, id: 7088, restoration: 13
food name: :potato_with_butter, id: 6703, restoration: 14
food name: :chili_potato, id: 7054, restoration: 14
food name: :potato_with_cheese, id: 6705, restoration: 16
food name: :egg_potato, id: 7056, restoration: 16
food name: :mushroom_potato, id: 7058, restoration: 20
food name: :tuna_potato, id: 7060, restoration: 22
# Vegetables
food :name => :potato, :id => 1942, :restoration => 1
food :name => :spinach_roll, :id => 1969, :restoration => 2
food :name => :baked_potato, :id => 6701, :restoration => 4
food :name => :sweetcorn, :id => 5988, :restoration => 10
food :name => :sweetcorn_bowl, :id => 7088, :restoration => 13
food :name => :potato_with_butter, :id => 6703, :restoration => 14
food :name => :chili_potato, :id => 7054, :restoration => 14
food :name => :potato_with_cheese, :id => 6705, :restoration => 16
food :name => :egg_potato, :id => 7056, :restoration => 16
food :name => :mushroom_potato, :id => 7058, :restoration => 20
food :name => :tuna_potato, :id => 7060, :restoration => 22
# Dairy
food name: :cheese, id: 1985, restoration: 2
food name: :pot_of_cream, id: 2130, restoration: 1
# Dairy
food :name => :cheese, :id => 1985, :restoration => 2
food :name => :pot_of_cream, :id => 2130, :restoration => 1
# Gnome Food
food name: :toads_legs, id: 2152, restoration: 3
# Gnome Food
food :name => :toads_legs, :id => 2152, :restoration => 3
# Gnome Bowls
food name: :worm_hole, id: 2191, restoration: 12
food name: :worm_hole, id: 2233, restoration: 12
food name: :vegetable_ball, id: 2195, restoration: 12
food name: :vegetable_ball, id: 2235, restoration: 12
food name: :tangled_toads_legs, id: 2187, restoration: 15
food name: :tangled_toads_legs, id: 2231, restoration: 15
food name: :chocolate_bomb, id: 2185, restoration: 15
food name: :chocolate_bomb, id: 2229, restoration: 15
# Gnome Bowls
food :name => :worm_hole, :id => 2191, :restoration => 12
food :name => :worm_hole, :id => 2233, :restoration => 12
food :name => :vegetable_ball, :id => 2195, :restoration => 12
food :name => :vegetable_ball, :id => 2235, :restoration => 12
food :name => :tangled_toads_legs, :id => 2187, :restoration => 15
food :name => :tangled_toads_legs, :id => 2231, :restoration => 15
food :name => :chocolate_bomb, :id => 2185, :restoration => 15
food :name => :chocolate_bomb, :id => 2229, :restoration => 15
# Gnome Crunchies
food :name => :toad_crunchies, :id => 2217, :restoration => 7
food :name => :toad_crunchies, :id => 2243, :restoration => 7
food :name => :spicy_crunchies, :id => 2213, :restoration => 7
food :name => :spicy_crunchies, :id => 2241, :restoration => 7
food :name => :worm_crunchies, :id => 2205, :restoration => 8
food :name => :worm_crunchies, :id => 2237, :restoration => 8
food :name => :chocchip_crunchies, :id => 2209, :restoration => 7
food :name => :chocchip_crunchies, :id => 2239, :restoration => 7
# Gnome Battas
food :name => :fruit_batta, :id => 2225, :restoration => 11
food :name => :fruit_batta, :id => 2277, :restoration => 11
food :name => :toad_batta, :id => 2221, :restoration => 11
food :name => :toad_batta, :id => 2255, :restoration => 11
food :name => :worm_batta, :id => 2219, :restoration => 11
food :name => :worm_batta, :id => 2253, :restoration => 11
food :name => :vegetable_batta, :id => 2227, :restoration => 11
food :name => :vegetable_batta, :id => 2281, :restoration => 11
food :name => :cheese_tom_batta, :id => 2223, :restoration => 11
food :name => :cheese_tom_batta, :id => 2259, :restoration => 11
# Gnome Cocktails
# Make new drink.rb file for drinks? That way it's seperated from food and says You drink, instead of you eat :{name}.
food :name => :fruit_blast, :id => 2034, :restoration => 9
food :name => :fruit_blast, :id => 2084, :restoration => 9
food :name => :pineapple_punch, :id => 2036, :restoration => 9
food :name => :pineapple_punch, :id => 2048, :restoration => 9
food :name => :wizard_blizzard, :id => 2040, :restoration => 5 # -4attack,+5strength also
food :name => :wizard_blizzard, :id => 2054, :restoration => 5 # -4attack,+5strength also
food :name => :short_green_guy, :id => 2038, :restoration => 5 # -4attack,+5strength also
food :name => :short_green_guy, :id => 2080, :restoration => 5 # -4attack,+5strength also
food :name => :drunk_dragon, :id => 2032, :restoration => 5 # -4attack,+6strength also
food :name => :drunk_dragon, :id => 2092, :restoration => 5 # -4attack,+6strength also
food :name => :chocolate_saturday, :id => 2030, :restoration => 7 # -4attack,+6strength also
food :name => :chocolate_saturday, :id => 2074, :restoration => 7 # -4attack,+6strength also
food :name => :blurberry_special, :id => 2028, :restoration => 7 # -4attack,+6strength also
food :name => :blurberry_special, :id => 2064, :restoration => 7 # -4attack,+6strength also
# Misc
# Gnome Crunchies
food name: :toad_crunchies, id: 2217, restoration: 7
food name: :toad_crunchies, id: 2243, restoration: 7
food name: :spicy_crunchies, id: 2213, restoration: 7
food name: :spicy_crunchies, id: 2241, restoration: 7
food name: :worm_crunchies, id: 2205, restoration: 8
food name: :worm_crunchies, id: 2237, restoration: 8
food name: :chocchip_crunchies, id: 2209, restoration: 7
food name: :chocchip_crunchies, id: 2239, restoration: 7
# Gnome Battas
food name: :fruit_batta, id: 2225, restoration: 11
food name: :fruit_batta, id: 2277, restoration: 11
food name: :toad_batta, id: 2221, restoration: 11
food name: :toad_batta, id: 2255, restoration: 11
food name: :worm_batta, id: 2219, restoration: 11
food name: :worm_batta, id: 2253, restoration: 11
food name: :vegetable_batta, id: 2227, restoration: 11
food name: :vegetable_batta, id: 2281, restoration: 11
food name: :cheese_tom_batta, id: 2223, restoration: 11
food name: :cheese_tom_batta, id: 2259, restoration: 11
# Gnome Cocktails
# TODO: seperate from food, should say 'You drink' instead of 'You eat'.
food name: :fruit_blast, id: 2034, restoration: 9
food name: :fruit_blast, id: 2084, restoration: 9
food name: :pineapple_punch, id: 2036, restoration: 9
food name: :pineapple_punch, id: 2048, restoration: 9
food name: :wizard_blizzard, id: 2040, restoration: 5 # -4 attack, +5 strength also
food name: :wizard_blizzard, id: 2054, restoration: 5 # -4 attack, +5 strength also
food name: :short_green_guy, id: 2038, restoration: 5 # -4 attack, +5 strength also
food name: :short_green_guy, id: 2080, restoration: 5 # -4 attack, +5 strength also
food name: :drunk_dragon, id: 2032, restoration: 5 # -4 attack, +6 strength also
food name: :drunk_dragon, id: 2092, restoration: 5 # -4 attack, +6 strength also
food name: :chocolate_saturday, id: 2030, restoration: 7 # -4 attack, +6 strength also
food name: :chocolate_saturday, id: 2074, restoration: 7 # -4 attack, +6 strength also
food name: :blurberry_special, id: 2028, restoration: 7 # -4 attack, +6 strength also
food name: :blurberry_special, id: 2064, restoration: 7 # -4 attack, +6 strength also
+49 -33
View File
@@ -4,9 +4,10 @@ java_import 'org.apollo.game.model.entity.Skill'
private
# Contains potion-related constants.
module Constants
# The sound made when drinking a potion.
# The id of the sound made when drinking a potion.
DRINK_POTION_SOUND = 334
# The id of an empty vial.
@@ -25,10 +26,12 @@ class Potion < Consumable
def consume(player)
index = @doses.find_index(id) + 1
unless index == @doses.length # Consumable removes the previous potion for us, so we don't do it here.
if index != @doses.length # Consumable removes the old potion for us, so don't do it here.
player.inventory.add(@doses[index])
player.send_message("You drink some of your #{name} potion.", true)
player.send_message("You have #{ @doses.length - index } dose#{ "s" unless index == 3 } of potion left.", true)
player.send_message("You drink some of your #{name} potion.", true)
remaining = "You have #{@doses.length - index} dose#{'s' unless index == 3} of potion left."
player.send_message(remaining, true)
else
player.send_message('You drink the last of your potion.', true)
player.inventory.add(Constants::EMPTY_VIAL_ID)
@@ -37,7 +40,7 @@ class Potion < Consumable
drink(player)
end
def drink(player)
def drink(_player)
# Override to provide functionality
end
@@ -48,7 +51,7 @@ class BoostingPotion < Potion
def initialize(id, name, doses, skills, boost)
super(id, name, doses)
@skill_ids = skills.kind_of?(Array) ? skills : [ skills ]
@skill_ids = skills.is_a?(Array) ? skills : [skills]
@boost = boost
end
@@ -56,7 +59,7 @@ class BoostingPotion < Potion
@skill_ids.each do |id|
skill = player.skill_set.skill(id)
max = skill.maximum_level
level = [ skill.current_level, max ].min
level = [skill.current_level, max].min
new_current = @boost.call(max, level).floor
player.skill_set.set_skill(id, Skill.new(skill.experience, new_current, max))
@@ -65,17 +68,18 @@ class BoostingPotion < Potion
end
# Returns the parameters for the potion, as an array. Raises if any of the specified keys do not exist
# Returns the parameters for the potion, as an array. Fails if any of the specified keys do not
# exist.
def get_parameters(hash, keys)
raise "Hash must contain the following keys: #{ keys.join(", ") }." unless hash.has_keys?(*keys)
fail "Hash must contain the following keys: #{keys.join(', ')}." unless hash.has_keys?(*keys)
return keys.map {|key| hash[key] }
keys.map { |key| hash[key] }
end
# Appends a potion to the list of consumables.
def append_potion(hash)
def potion(hash)
class_name = 'Potion'
keys = [ :name, :doses ]
keys = [:name, :doses]
unless (hash.size == 2)
keys << :skills << :boost
@@ -83,36 +87,48 @@ def append_potion(hash)
end
parameters = get_parameters(hash, keys)
hash[:doses].each { |dose| append_consumable(Object.const_get(class_name).new(dose, *parameters)) }
doses = hash[:doses]
doses.each { |dose| append_consumable(Object.const_get(class_name).new(dose, *parameters)) }
end
# Some frequently-used boosts and skills
# Lambda parameters are | maximum_skill_level, current_skill_level |
basic_combat_boost = lambda { |max, level| level * 1.10 + 3 }
super_combat_boost = lambda { |max, level| level * 1.15 + 5 }
non_combat_boost = lambda { |max, level| level + 3 }
basic_combat_boost = ->(_, level) { level * 1.10 + 3 }
super_combat_boost = ->(_, level) { level * 1.15 + 5 }
non_combat_boost = ->(_, level) { level + 3 }
ATTACK, STRENGTH, DEFENCE = Skill::ATTACK, Skill::STRENGTH, Skill::DEFENCE
MAGIC, RANGED, PRAYER = Skill::MAGIC, Skill::RANGED, Skill::PRAYER
all_skills = (Skill::ATTACK..Skill::RUNECRAFT).to_a
combat_skills = [ Skill::ATTACK, Skill::STRENGTH, Skill::DEFENCE, Skill::MAGIC, Skill::RANGED ]
combat_skills = [ATTACK, STRENGTH, DEFENCE, MAGIC, RANGED]
# Boosting potions:
# Note that the order of the elements must be: :name, :doses, :skills, :boost.
append_potion :name => :attack, :doses => [ 2428, 121, 123, 125 ], :skills => Skill::ATTACK, :boost => basic_combat_boost
append_potion :name => :strength, :doses => [ 113, 115, 117, 119 ], :skills => Skill::STRENGTH, :boost => basic_combat_boost
append_potion :name => :defence, :doses => [ 2432, 133, 135, 137 ], :skills => Skill::DEFENCE, :boost => basic_combat_boost
potion name: :attack, doses: [2428, 121, 123, 125], skills: ATTACK, boost: basic_combat_boost
potion name: :strength, doses: [113, 115, 117, 119], skills: STRENGTH, boost: basic_combat_boost
potion name: :defence, doses: [2432, 133, 135, 137], skills: DEFENCE, boost: basic_combat_boost
append_potion :name => :agility, :doses => [ 3032, 3034, 3036, 3038 ], :skills => Skill::AGILITY, :boost => non_combat_boost
append_potion :name => :fishing, :doses => [ 2438, 151, 153, 155 ], :skills => Skill::FISHING, :boost => non_combat_boost
append_potion :name => :prayer, :doses => [ 2434, 139, 141, 143 ], :skills => Skill::PRAYER, :boost => lambda { |max, level| level / 4 + 7 }
potion name: :agility, doses: [3032, 3034, 3036, 3038], skills: Skill::AGILITY,
boost: non_combat_boost
potion name: :fishing, doses: [2438, 151, 153, 155], skills: Skill::FISHING,
boost: non_combat_boost
potion name: :prayer, doses: [2434, 139, 141, 143], skills: Skill::PRAYER,
boost: ->(_, level) { level / 4 + 7 }
append_potion :name => :restore, :doses => [ 2430, 127, 129, 131 ], :skills => combat_skills, :boost => lambda { |max, level| [ level * 1.3 + 10, max ].min }
append_potion :name => :super_restore, :doses => [ 3024, 3026, 3028, 3030 ], :skills => all_skills, :boost => lambda { |max, level| [ level * 1.25 + 8, max ].min }
potion name: :restore, doses: [2430, 127, 129, 131], skills: combat_skills,
boost: ->(_, level) { [level * 1.3 + 10, max].min }
potion name: :super_restore, doses: [3024, 3026, 3028, 3030], skills: all_skills,
boost: ->(_, level) { [level * 1.25 + 8, max].min }
append_potion :name => :super_attack, :doses => [ 2436, 145, 147, 149 ], :skills => Skill::ATTACK, :boost => super_combat_boost
append_potion :name => :super_strength, :doses => [ 2440, 157, 159, 161 ], :skills => Skill::STRENGTH, :boost => super_combat_boost
append_potion :name => :super_defence, :doses => [ 2442, 163, 165, 167 ], :skills => Skill::DEFENCE, :boost => super_combat_boost
append_potion :name => :ranging, :doses => [ 2444, 169, 171, 173 ], :skills => Skill::RANGED, :boost => lambda { |max, level| level * 1.10 + 4 }
append_potion :name => :magic, :doses => [ 3040, 3042, 3044, 3046 ], :skills => Skill::MAGIC, :boost => lambda { |max, level| level + 4 }
potion name: :super_attack, doses: [2436, 145, 147, 149], skills: ATTACK, boost: super_combat_boost
potion name: :super_strength, doses: [2440, 157, 159, 161], skills: STRENGTH,
boost: super_combat_boost
potion name: :super_defence, doses: [2442, 163, 165, 167], skills: DEFENCE,
boost: super_combat_boost
potion name: :ranging, doses: [2444, 169, 171, 173], skills: RANGED,
boost: ->(_, level) { level * 1.10 + 4 }
potion name: :magic, doses: [3040, 3042, 3044, 3046], skills: MAGIC,
boost: ->(_, level) { level + 4 }
+10 -9
View File
@@ -10,6 +10,7 @@ ANIMATION_PULSES = 0
LEVEL_THRESHOLD = 8
EXP_PER_HIT = 5
# A DistancedAction for attacking a training dummy.
class DummyAction < DistancedAction
attr_reader :position
@@ -21,13 +22,7 @@ class DummyAction < DistancedAction
end
def executeAction
unless @started
@started = true
mob.send_message('You hit the dummy.', true)
mob.turn_to(position)
mob.play_animation(PUNCH_ANIMATION)
else
if @started
skills = mob.skill_set
if (skills.skill(ATTACK_SKILL_ID).maximum_level >= LEVEL_THRESHOLD)
@@ -37,14 +32,20 @@ class DummyAction < DistancedAction
end
stop
else
@started = true
mob.send_message('You hit the dummy.', true)
mob.turn_to(position)
mob.play_animation(PUNCH_ANIMATION)
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
get_class == other.get_class && @position == other.position
end
end
on :message, :second_object_action do |player, message|
player.start_action(DummyAction.new(player, message.position)) if message.id == DUMMY_ID
end
end
-21
View File
@@ -1,21 +0,0 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
ANIMATIONS = {
162 => Animation::THINKING, 6503 => Animation::CLIMB_ROPE, 169 => Animation::NO, 164 => Animation::BOW, 13384 => Animation::GOBLIN_DANCE,
161 => Animation::CRY, 170 => Animation::LAUGH, 171 => Animation::CHEER, 163 => Animation::WAVE, 167 => Animation::BECKON,
3362 => Animation::PANIC, 172 => Animation::CLAP, 166 => Animation::DANCE, 13363 => Animation::JIG, 13364 => Animation::SPIN,
13365 => Animation::HEAD_BANG, 6506 => Animation::LEAN, 165 => Animation::ANGRY, 13368 => Animation::YAWN, 13366 => Animation::JOY_JUMP,
667 => Animation::GLASS_BOX, 13367 => Animation::RASPBERRY, 13369 => Animation::SALUTE, 13370 => Animation::SHRUG, 11100 => Animation::BLOW_KISS,
666 => Animation::GLASS_WALL, 168 => Animation::YES, 13383 => Animation::GOBLIN_BOW
}
# Intercept the button message.
on :message, :button do |player, message|
anim = ANIMATIONS[message.widget_id]
unless anim == nil
player.play_animation(anim)
message.terminate
end
end
+26
View File
@@ -0,0 +1,26 @@
require 'java'
java_import 'org.apollo.game.model.Animation'
ANIMATIONS = {
162 => Animation::THINKING, 6_503 => Animation::CLIMB_ROPE, 169 => Animation::NO,
164 => Animation::BOW, 13_384 => Animation::GOBLIN_DANCE, 161 => Animation::CRY,
170 => Animation::LAUGH, 171 => Animation::CHEER, 163 => Animation::WAVE,
167 => Animation::BECKON, 3_362 => Animation::PANIC, 172 => Animation::CLAP,
166 => Animation::DANCE, 13_363 => Animation::JIG, 13_364 => Animation::SPIN,
13_365 => Animation::HEAD_BANG, 6_506 => Animation::LEAN, 165 => Animation::ANGRY,
13_368 => Animation::YAWN, 13_366 => Animation::JOY_JUMP, 667 => Animation::GLASS_BOX,
13_367 => Animation::RASPBERRY, 13_369 => Animation::SALUTE, 13_370 => Animation::SHRUG,
11_100 => Animation::BLOW_KISS, 666 => Animation::GLASS_WALL, 168 => Animation::YES,
13_383 => Animation::GOBLIN_BOW
}
# Intercept the button message.
on :message, :button do |player, message|
anim = ANIMATIONS[message.widget_id]
unless anim.nil?
player.play_animation(anim)
message.terminate
end
end
+2 -2
View File
@@ -8,7 +8,7 @@
<author>Major</author>
</authors>
<scripts>
<script>emote-tab.rb</script>
<script>emote_tab.rb</script>
</scripts>
<dependencies />
</plugin>
</plugin>
+21 -18
View File
@@ -12,47 +12,48 @@ java_import 'org.apollo.game.model.entity.attr.BooleanAttribute'
java_import 'org.apollo.game.model.entity.attr.NumericalAttribute'
java_import 'org.apollo.game.model.entity.attr.StringAttribute'
# Declares an attribute and adds its definition.
def declare_attribute(name, default, persistence=:transient)
raise "Attribute #{name} clashes with an existing variable." if (Player.method_defined?(name) || Mob.method_defined?(name) || Npc.method_defined?(name))
AttributeMap::define(name.to_s, AttributeDefinition.new(default, get_persistence(persistence), get_type(default)))
end
def declare_attribute(name, default, persistence = :transient)
if Player.method_defined?(name) || Mob.method_defined?(name) || Npc.method_defined?(name)
fail "Attribute #{name} clashes with an existing variable."
end
definition = AttributeDefinition.new(default, get_persistence(persistence), get_type(default))
AttributeMap::define(name.to_s, definition)
end
private
# The existing Mob class.
class Mob
# Overrides method_missing to implement the functionality.
def method_missing(symbol, *args)
name = symbol.to_s.strip
if name[-1] == "="
raise "Expected argument count of 1, received #{args.length}" unless args.length == 1
if name[-1] == '='
fail "Expected argument count of 1, received #{args.length}" unless args.length == 1
name = name[0...-1].strip # Drop the equals and trim whitespace.
set_attribute(name, to_attribute(args[0]))
elsif AttributeMap::get_definition(name).nil?
super(symbol, *args)
else
attribute = get_attribute(name)
value = attribute.value
return (attribute.type == AttributeType::SYMBOL) ? value.to_sym : value
value = attribute.value
(attribute.type == AttributeType::SYMBOL) ? value.to_sym : value
end
end
end
# Gets the appropriate attribute for the specified value.
# Gets the appropriate attribute for the specified value.
def to_attribute(value)
case value
when String, Symbol then return StringAttribute.new(value.to_s, value.is_a?(Symbol))
when Integer, Float then return NumericalAttribute.new(value)
when TrueClass, FalseClass then return BooleanAttribute.new(value)
else raise "Undefined attribute type #{value.class}."
else fail "Undefined attribute type #{value.class}."
end
end
@@ -64,13 +65,15 @@ def get_type(value)
when Integer then return AttributeType::LONG
when Float then return AttributeType::DOUBLE
when TrueClass, FalseClass then return AttributeType::BOOLEAN
else raise "Undefined attribute type #{value.class}."
else fail "Undefined attribute type #{value.class}."
end
end
# Gets the Persistence type of the specified value.
def get_persistence(persistence)
raise "Undefined persistence type #{persistence}." unless [ :persistent, :transient ].include?(persistence)
unless [:persistent, :transient].include?(persistence)
fail "Undefined persistence type #{persistence}."
end
return (persistence == :persistent) ? AttributePersistence::PERSISTENT : AttributePersistence::TRANSIENT
end
(persistence == :persistent) ? AttributePersistence::PERSISTENT : AttributePersistence::TRANSIENT
end
+37 -27
View File
@@ -10,22 +10,29 @@ java_import 'org.apollo.game.model.entity.Npc'
# Information about npc spawning
#
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol. Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id after the name (e.g. :woman_4)
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol.
# Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id
# after the name (e.g. :woman_4)
# :x - the x coordinate where the npc will spawn.
# :y - the y coordinate where the npc will spawn.
# Optional arguments are as follows:
# :face - the direction the npc should face when it spawns. Supported options are :north, :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate, top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :face - the direction the npc should face when it spawns. Supported options are :north,
# :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is
# [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate,
# top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from
# the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :spawn_animation - the animation that will be played when the npc spawns.
# :spawn_graphic - the graphic that will be played when the npc spawns.
# Spawns an npc with the properties specified in the hash.
def spawn_npc(hash)
raise 'A name (or id), x coordinate, and y coordinate must be specified to spawn an npc.' unless (hash.has_key?(:name) || hash.has_key?(:id)) && hash.has_keys?(:x, :y)
unless (hash.key?(:name) || hash.key?(:id)) && hash.has_keys?(:x, :y)
fail 'A name (or id), x coordinate, and y coordinate must be specified to spawn an npc.'
end
npc = get_npc(hash)
spawn(npc, hash)
npc
@@ -46,8 +53,8 @@ def get_npc(hash)
id = lookup_npc(hash.delete(:name))
z = hash.delete(:z)
position = Position.new(hash.delete(:x), hash.delete(:y), z == nil ? 0 : z)
return Npc.new($world, id, position)
position = Position.new(hash.delete(:x), hash.delete(:y), z.nil? ? 0 : z)
Npc.new($world, id, position)
end
# Applies a decoded hash (one aquired using parse_hash) to the specified npc.
@@ -58,7 +65,7 @@ def apply_decoded_hash(npc, hash)
when :boundary then npc.boundaries = value
when :spawn_animation then npc.play_animation(Animation.new(value))
when :spawn_graphic then npc.play_graphic(Graphic.new(value))
else raise "Unrecognised key #{key} - value #{value}."
else fail "Unrecognised key #{key} - value #{value}."
end
end
end
@@ -72,27 +79,27 @@ def decode_hash(position, hash)
when :face
decoded[:face] = direction_to_position(value, position)
when :delta_bounds
raise ':delta_bounds must have two values.' unless value.length == 2
fail ':delta_bounds must have two values.' unless value.length == 2
dx, dy, x, y, z = value[0], value[1], position.x, position.y, position.height
raise 'Delta values cannot be less than 0.' if (dx < 0 || dy < 0)
fail 'Delta values cannot be less than 0.' if dx < 0 || dy < 0
decoded[:boundary] = [ Position.new(x - dx, y - dy, z), Position.new(x + dx, y + dy, z) ]
decoded[:boundary] = [Position.new(x - dx, y - dy, z), Position.new(x + dx, y + dy, z)]
when :bounds
raise ':bounds must have four values.' unless value.length == 4
fail ':bounds must have four values.' unless value.length == 4
min_x, min_y, max_x, max_y = value[0], value[1], value[2], value[3]
decoded[:boundary] = [ Position.new(min_x, min_y), Position.new(max_x, max_y) ]
decoded[:boundary] = [Position.new(min_x, min_y), Position.new(max_x, max_y)]
when :spawn_animation then decoded[:spawn_animation] = Animation.new(value)
when :spawn_graphic then decoded[:spawn_graphic ] = Graphic.new(value)
else raise "Unrecognised key #{key} - value #{value}."
when :spawn_graphic then decoded[:spawn_graphic] = Graphic.new(value)
else fail "Unrecognised key #{key} - value #{value}."
end
end
return decoded
decoded
end
# Returns a position that an entity at the specified position should be facing towards if they are looking in the specified direction.
# Returns a position that an entity at the specified position should be facing towards if they are
# looking in the specified direction.
def direction_to_position(direction, position)
x, y, z = position.x, position.y, position.height
@@ -121,13 +128,14 @@ class TemporaryNpcAction < Action
end
def execute
if executions == 0
if @executions == 0
spawn(mob, @hash)
execute_spawn_action
else
execute_action
end
executions += 1
@executions += 1
end
def execute_action
@@ -168,20 +176,22 @@ RANDOM_EVENTS = []
# Spawns a random event for the specified player.
def send_random_event(player)
position = player.position
npc_position = Position.new(position.x + 1, position.y, position.height) # TODO Find an unoccupied tile instead of the assumption that (x + 1) is traversable!!
npc_position = Position.new(position.x + 1, position.y, position.height)
# TODO: Find an unoccupied tile instead of the assumption that (x + 1) is traversable!!
spawn_random_event(npc_position, false)
end
# Spawns a random event in the specified position.
# If 'combat' is false, only non-combat events will be spawned.
def spawn_random_event(position, combat)
def spawn_random_event(_position, _combat)
event = RANDOM_EVENTS[rand(RANDOM_EVENTS.size)]
attempts = 0
while (event.combative && attempts < 5)
while event.combative && attempts < 5
event = RANDOM_EVENTS[rand(RANDOM_EVENTS.size)]
attempts += 1
end
event.execute unless attempts == 5 # 5 iterations is plenty, just give up at this point
end
end
+39 -50
View File
@@ -1,66 +1,55 @@
# Information about npc spawning
#
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol. Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id after the name (e.g. :woman_4)
# :x - the x coordinate where the npc will spawn.
# :y - the y coordinate where the npc will spawn.
# Optional arguments are as follows:
# :face - the direction the npc should face when it spawns. Supported options are :north, :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate, top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :spawn_animation - the animation that will be played when the npc spawns.
# :spawn_graphic - the graphic that will be played when the npc spawns.
# Generic npcs
spawn_npc :name => :man, :x => 3276, :y => 3186
spawn_npc name: :man, x: 3276, y: 3186
# Palace guards
spawn_npc :name => "Al-Kharid warrior", :x => 3283, :y => 3161 # String must be used here because the actual npc name is 'Al-Kharid warrior', and symbols don't support hyphens.
spawn_npc :name => "Al-Kharid warrior", :x => 3285, :y => 3174
spawn_npc :name => "Al-Kharid warrior", :x => 3286, :y => 3164
spawn_npc :name => "Al-Kharid warrior", :x => 3287, :y => 3168
spawn_npc :name => "Al-Kharid warrior", :x => 3288, :y => 3169
spawn_npc :name => "Al-Kharid warrior", :x => 3290, :y => 3162
spawn_npc :name => "Al-Kharid warrior", :x => 3295, :y => 3162
spawn_npc :name => "Al-Kharid warrior", :x => 3295, :y => 3170
spawn_npc :name => "Al-Kharid warrior", :x => 3297, :y => 3175
spawn_npc :name => "Al-Kharid warrior", :x => 3300, :y => 3171
spawn_npc :name => "Al-Kharid warrior", :x => 3301, :y => 3164
spawn_npc :name => "Al-Kharid warrior", :x => 3301, :y => 3168
spawn_npc name: 'Al-Kharid warrior', x: 3283, y: 3161
spawn_npc name: 'Al-Kharid warrior', x: 3285, y: 3174
spawn_npc name: 'Al-Kharid warrior', x: 3286, y: 3164
spawn_npc name: 'Al-Kharid warrior', x: 3287, y: 3168
spawn_npc name: 'Al-Kharid warrior', x: 3288, y: 3169
spawn_npc name: 'Al-Kharid warrior', x: 3290, y: 3162
spawn_npc name: 'Al-Kharid warrior', x: 3295, y: 3162
spawn_npc name: 'Al-Kharid warrior', x: 3295, y: 3170
spawn_npc name: 'Al-Kharid warrior', x: 3297, y: 3175
spawn_npc name: 'Al-Kharid warrior', x: 3300, y: 3171
spawn_npc name: 'Al-Kharid warrior', x: 3301, y: 3164
spawn_npc name: 'Al-Kharid warrior', x: 3301, y: 3168
spawn_npc :name => :shantay_guard_838, :x => 3301, :y => 3120
spawn_npc :name => :shantay_guard, :x => 3304, :y => 3119
spawn_npc :name => :shantay_guard_838, :x => 3307, :y => 3122
spawn_npc name: :shantay_guard_838, x: 3301, y: 3120
spawn_npc name: :shantay_guard, x: 3304, y: 3119
spawn_npc name: :shantay_guard_838, x: 3307, y: 3122
# Mine
spawn_npc :name => :scorpion, :x => 3296, :y => 3294
spawn_npc :name => :scorpion, :x => 3298, :y => 3280
spawn_npc :name => :scorpion, :x => 3299, :y => 3299
spawn_npc :name => :scorpion, :x => 3299, :y => 3309
spawn_npc :name => :scorpion, :x => 3300, :y => 3287
spawn_npc :name => :scorpion, :x => 3301, :y => 3305
spawn_npc name: :scorpion, x: 3296, y: 3294
spawn_npc name: :scorpion, x: 3298, y: 3280
spawn_npc name: :scorpion, x: 3299, y: 3299
spawn_npc name: :scorpion, x: 3299, y: 3309
spawn_npc name: :scorpion, x: 3300, y: 3287
spawn_npc name: :scorpion, x: 3301, y: 3305
# Functional npcs
spawn_npc :name => :gnome_pilot, :x => 3279, :y => 3213
spawn_npc name: :gnome_pilot, x: 3279, y: 3213
spawn_npc :name => :banker_496, :x => 3267, :y => 3164, :face => :east # TODO are these the correct banker ids?
spawn_npc :name => :banker_497, :x => 3267, :y => 3166, :face => :east
spawn_npc :name => :banker_496, :x => 3267, :y => 3167, :face => :east
spawn_npc :name => :banker_497, :x => 3267, :y => 3168, :face => :east
spawn_npc :name => :banker_496, :x => 3267, :y => 3169, :face => :east
# TODO: are these the correct banker ids?
spawn_npc name: :banker_496, x: 3267, y: 3164, face: :east
spawn_npc name: :banker_497, x: 3267, y: 3166, face: :east
spawn_npc name: :banker_496, x: 3267, y: 3167, face: :east
spawn_npc name: :banker_497, x: 3267, y: 3168, face: :east
spawn_npc name: :banker_496, x: 3267, y: 3169, face: :east
spawn_npc :name => :gem_trader, :x => 3287, :y => 3210
spawn_npc :name => :zeke, :x => 3289, :y => 3189
spawn_npc :name => :shantay, :x => 3304, :y => 3124
spawn_npc name: :gem_trader, x: 3287, y: 3210
spawn_npc name: :zeke, x: 3289, y: 3189
spawn_npc name: :shantay, x: 3304, y: 3124
spawn_npc :name => :rug_merchant_2296, :x => 3311, :y => 3109, :face => :west
spawn_npc :name => :ranael, :x => 3315, :y => 3163, :face => :north
spawn_npc :name => :shop_assistant_525, :x => 3315, :y => 3178, :face => :north # TODO are these the correct shop staff ids?
spawn_npc :name => :shop_keeper_524, :x => 3315, :y => 3180, :face => :west
spawn_npc :name => :louie_legs, :x => 3316, :y => 3175, :face => :west
spawn_npc name: :rug_merchant_2296, x: 3311, y: 3109, face: :west
spawn_npc name: :ranael, x: 3315, y: 3163, face: :north
# TODO: are these the correct shop staff ids?
spawn_npc name: :shop_assistant_525, x: 3315, y: 3178, face: :north
spawn_npc name: :shop_keeper_524, x: 3315, y: 3180, face: :west
spawn_npc name: :louie_legs, x: 3316, y: 3175, face: :west
+30 -44
View File
@@ -1,53 +1,39 @@
# Information about npc spawning
#
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol. Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id after the name (e.g. :woman_4)
# :x - the x coordinate where the npc will spawn.
# :y - the y coordinate where the npc will spawn.
# Optional arguments are as follows:
# :face - the direction the npc should face when it spawns. Supported options are :north, :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate, top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :spawn_animation - the animation that will be played when the npc spawns.
# :spawn_graphic - the graphic that will be played when the npc spawns.
# Generic npcs
spawn_npc :name => :man, :x => 3095, :y => 3508
spawn_npc :name => :man, :x => 3095, :y => 3511
spawn_npc :name => :man, :x => 3098, :y => 3509
spawn_npc name: :man, x: 3095, y: 3508
spawn_npc name: :man, x: 3095, y: 3511
spawn_npc name: :man, x: 3098, y: 3509
spawn_npc :name => :guard, :x => 3108, :y => 3514
spawn_npc :name => :guard, :x => 3110, :y => 3514
spawn_npc :name => :guard, :x => 3113, :y => 3514
spawn_npc :name => :guard, :x => 3113, :y => 3516
spawn_npc name: :guard, x: 3108, y: 3514
spawn_npc name: :guard, x: 3110, y: 3514
spawn_npc name: :guard, x: 3113, y: 3514
spawn_npc name: :guard, x: 3113, y: 3516
spawn_npc :name => :sheep_43, :x => 3053, :y => 3514
spawn_npc :name => :sheep_43, :x => 3053, :y => 3517
spawn_npc :name => :sheep_43, :x => 3053, :y => 3518
spawn_npc :name => :sheep_43, :x => 3056, :y => 3517
spawn_npc name: :sheep_43, x: 3053, y: 3514
spawn_npc name: :sheep_43, x: 3053, y: 3517
spawn_npc name: :sheep_43, x: 3053, y: 3518
spawn_npc name: :sheep_43, x: 3056, y: 3517
spawn_npc :name => :mugger, :x => 3076, :y => 3504
spawn_npc :name => :monk, :x => 3044, :y => 3491
spawn_npc :name => :monk, :x => 3045, :y => 3483
spawn_npc :name => :monk, :x => 3045, :y => 3497
spawn_npc :name => :monk, :x => 3050, :y => 3490
spawn_npc :name => :monk, :x => 3054, :y => 3490
spawn_npc :name => :monk, :x => 3058, :y => 3497
spawn_npc name: :mugger, x: 3076, y: 3504
spawn_npc name: :monk, x: 3044, y: 3491
spawn_npc name: :monk, x: 3045, y: 3483
spawn_npc name: :monk, x: 3045, y: 3497
spawn_npc name: :monk, x: 3050, y: 3490
spawn_npc name: :monk, x: 3054, y: 3490
spawn_npc name: :monk, x: 3058, y: 3497
# Functional npcs
spawn_npc :name => :brother_jered, :x => 3045, :y => 3488
spawn_npc :name => :brother_althric, :x => 3054, :y => 3504
spawn_npc :name => :abbot_langley, :x => 3059, :y => 3484
spawn_npc :name => :oziach, :x => 3067, :y => 3518, :face => :east
spawn_npc :name => :shop_assistant, :x => 3079, :y => 3509
spawn_npc :name => :shop_keeper, :x => 3082, :y => 3513
spawn_npc :name => :banker, :x => 3096, :y => 3489, :face => :west # TODO probably not all the same bankers.
spawn_npc :name => :banker, :x => 3096, :y => 3491, :face => :west
spawn_npc :name => :banker, :x => 3096, :y => 3492, :face => :north
spawn_npc :name => :banker, :x => 3098, :y => 3492, :face => :north
spawn_npc :name => :mage_of_zamorak, :x => 3106, :y => 3560
spawn_npc name: :brother_jered, x: 3045, y: 3488
spawn_npc name: :brother_althric, x: 3054, y: 3504
spawn_npc name: :abbot_langley, x: 3059, y: 3484
spawn_npc name: :oziach, x: 3067, y: 3518, face: :east
spawn_npc name: :shop_assistant, x: 3079, y: 3509
spawn_npc name: :shop_keeper, x: 3082, y: 3513
# TODO: probably not all the same bankers.
spawn_npc name: :banker, x: 3096, y: 3489, face: :west
spawn_npc name: :banker, x: 3096, y: 3491, face: :west
spawn_npc name: :banker, x: 3096, y: 3492, face: :north
spawn_npc name: :banker, x: 3098, y: 3492, face: :north
spawn_npc name: :mage_of_zamorak, x: 3106, y: 3560
+10 -23
View File
@@ -1,29 +1,16 @@
# Information about npc spawning
#
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol. Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id after the name (e.g. :woman_4)
# :x - the x coordinate where the npc will spawn.
# :y - the y coordinate where the npc will spawn.
# Optional arguments are as follows:
# :face - the direction the npc should face when it spawns. Supported options are :north, :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate, top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :spawn_animation - the animation that will be played when the npc spawns.
# :spawn_graphic - the graphic that will be played when the npc spawns.
# Generic npcs
spawn_npc :name => :woman_4, :x => 3232, :y => 3207 # southernmost house
spawn_npc :name => :man_1, :x => 3231, :y => 3237 # house by willow tree
spawn_npc :name => :man_2, :x => 3224, :y => 3240 # house by willow tree
spawn_npc :name => :woman_5, :x => 3229, :y => 2329 # house by willow tree
spawn_npc name: :woman_4, x: 3232, y: 3207 # southernmost house
spawn_npc name: :man_1, x: 3231, y: 3237 # house by willow tree
spawn_npc name: :man_2, x: 3224, y: 3240 # house by willow tree
spawn_npc name: :woman_5, x: 3229, y: 2329 # house by willow tree
# Functional npcs
spawn_npc :name => :hans, :x => 3221, :y => 3221
spawn_npc :name => :father_aereck, :x => 3243, :y => 3210
spawn_npc :name => :bob, :x => 3231, :y => 3203
spawn_npc :name => :shop_keeper, :x => 3212, :y => 3247
spawn_npc :name => :shop_assistant, :x => 3211, :y => 3245
spawn_npc :name => :lumbridge_guide, :x => 3232, :y => 3229
spawn_npc name: :hans, x: 3221, y: 3221
spawn_npc name: :father_aereck, x: 3243, y: 3210
spawn_npc name: :bob, x: 3231, y: 3203
spawn_npc name: :shop_keeper, x: 3212, y: 3247
spawn_npc name: :shop_assistant, x: 3211, y: 3245
spawn_npc name: :lumbridge_guide, x: 3232, y: 3229
+34 -30
View File
@@ -3,32 +3,33 @@ require 'java'
java_import 'org.apollo.game.message.impl.HintIconMessage'
java_import 'org.apollo.game.message.impl.SwitchTabInterfaceMessage'
private
# The ids of tabs that are displayed when the player has yet to start the tutorial.
INITIAL_TABS = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2449, 904, -1, -1 ]
INITIAL_TABS = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2449, 904, -1, -1]
# The character design interface id.
CHARACTER_DESIGN = 3559
# The Runescape guide Npc
@runescape_guide = spawn_npc :name => :runescape_guide, :x => 3093, :y => 3107
@runescape_guide = spawn_npc name: :runescape_guide, x: 3093, y: 3107
# Sends the appropriate data to the client when the player logs in to the game.
on :login do |event, player|
if player.in_tutorial_island
# TutorialInstructions::show_instruction(player)
# INITIAL_TABS.each_with_index { |tab, index| player.send(SwitchTabInterfaceMessage.new(index, tab)) }
on :login do |_event, player|
if player.in_tutorial_island && player.privilege_level != RIGHTS_ADMIN
TutorialInstructions.show_instruction(player)
if (player.tutorial_island_progress == :not_started)
INITIAL_TABS.each_with_index do |tab, index|
player.send(SwitchTabInterfaceMessage.new(index, tab))
end
if player.tutorial_island_progress == :not_started
show_hint_icon(player)
player.interface_set.open_window(CHARACTER_DESIGN)
end
end
end
# The conversation with the Runescape Guide, when on tutorial island.
conversation :tutorial_runescape_guide do
@@ -36,63 +37,66 @@ conversation :tutorial_runescape_guide do
dialogue :greetings do
type :npc_speech
npc :runescape_guide
precondition { |player| player.tutorial_island_progress == :not_started }
text "Greetings! I see you are a new arrival to this land. My job is to welcome all new visitors. So welcome!"
text 'Greetings! I see you are a new arrival to this land. My job is to welcome all new '\
'visitors. So welcome!'
continue :dialogue => :talk_to_people do |player|
continue dialogue: :talk_to_people do |player|
player.tutorial_island_progress = :talk_to_people
end
end
# The Guide welcomes back the Player if they speak to him after they have already gone through the conversation once.
# The Guide welcomes back the Player if they speak to him after they have already gone through
# the conversation once.
dialogue :welcome_back do
type :npc_speech
npc :runescape_guide
precondition { |player| player.tutorial_island_progress != :not_started }
text "Welcome back."
text 'Welcome back.'
continue :dialogue => :talk_to_people
continue dialogue: :talk_to_people
end
# The Guide tells Players to speak to people in order to succeed.
dialogue :talk_to_people do
type :npc_speech
npc :runescape_guide
text "You have already learned the first thing you need to succeed in this world: talking to people!",
"You will find many inhabitants of this world have useful things to say to you. By clicking on them with your mouse you can talk to them.",
"I would also suggest reading through some of the supporting information on the website. There you can find maps, a bestiary, and much more."
text 'You have already learned the first thing you need to succeed in this world: talking to '\
'people!',
'You will find many inhabitants of this world have useful things to say to you. By '\
'clicking on them with your mouse you can talk to them.',
'I would also suggest reading through some of the supporting information on the website.'\
' There you can find maps, a bestiary, and much more.'
continue :dialogue => :go_through_door
end
continue dialogue: :go_through_door
end
# The Guide tells Players to go through the door, advancing the tutorial progress if this is the first time the Player has heard this.
# The Guide tells Players to go through the door, advancing the tutorial progress if this is the
# first time the Player has heard this.
dialogue :go_through_door do
type :npc_speech
npc :runescape_guide
text "To continue the tutorial go through that door over there, and speak to your first instructor."
text 'To continue the tutorial go through that door over there, and speak to your first '\
'instructor.'
close do |player|
if (player.tutorial_island_progress < :runescape_guide_finished)
if player.tutorial_island_progress < :runescape_guide_finished
reset_hint_icon(player)
# TODO door hint icon
# TODO: door hint icon
player.tutorial_island_progress = :runescape_guide_finished
end
TutorialInstructions.show_instruction(player)
end
end
end
# Enables the hint icon above the Runescape guide.
def show_hint_icon(player)
player.send(HintIconMessage.for_npc(@runescape_guide.index))
@@ -100,5 +104,5 @@ end
# Resets the hint icon.
def reset_hint_icon(player)
player.send(HintIconMessage.reset_npc())
end
player.send(HintIconMessage.reset_npc)
end
@@ -1,5 +1,5 @@
# TODO update the status to :moving_around when the door is opened
# TODO: update the status to :moving_around when the door is opened
# Contains members related to the instructions issues during tutorial island.
module TutorialInstructions
@@ -18,104 +18,115 @@ module TutorialInstructions
when :given_axe then :viewing_items
when :cut_tree then :cut_tree
when :cutting_tree then :please_wait
else raise "No dialogue for current stage #{progress} exists."
else fail 'No dialogue for current stage #{progress} exists.'
end
dialogue = instructions.part(name)
send_dialogue(player, dialogue)
end
# The one-sided 'conversation' of instruction instructions.
conversation :tutorial_island_instructions do
# The initial instruction displayed when the player logs in, before they have spoken to the guide.
# The initial instruction displayed when the player logs in, before they have spoken to the
# guide.
dialogue :getting_started do
type :text
title "Getting started"
text "To start the tutorial, use your left mouse button to click on the Runescape Guide in this room. He is indicated by "\
"a flashing yellow arrow above his head. If you can't see him, use your keyboard's arrow keys to rotate the view."
title 'Getting started'
text 'To start the tutorial, use your left mouse button to click on the Runescape Guide in '\
'this room. He is indicated by a flashing yellow arrow above his head. If you can\'t '\
'see him, use your keyboard\'s arrow keys to rotate the view.'
end
# The instruction displayed after the player has spoken to the Runescape Guide.
dialogue :scenery do
type :text
title "Interacting with scenery"
text "You can interact with many items of the scenery by simply clicking on them. Right clicking will also give more options. "\
"Click on the door indicated with the yellow arrow to go through to the next area and speak with your next instructor."
title 'Interacting with scenery'
text 'You can interact with many items of the scenery by simply clicking on them. Right '\
'clicking will also give more options. Click on the door indicated with the yellow '\
'arrow to go through to the next area and speak with your next instructor.'
end
## TODO !! When we have door support, the player's tutorial island progress needs to be set to :moving_around when they walk through the door !!
# TODO: The player's tutorial island progress needs to be set to :moving_around when they walk
# through the door !!
# The instruction displayed after the player has left the initial building.
dialogue :moving_around do
type :text
title "Moving around"
text "Follow the path to find the next instructor. Clicking on the ground will walk you to that point. Talk to the survival expert "\
"by the pond to continue the tutorial. Remember you can rotate the view by pressing the arrow keys."
title 'Moving around'
text 'Follow the path to find the next instructor. Clicking on the ground will walk you to '\
'that point. Talk to the survival expert by the pond to continue the tutorial. '\
'Remember you can rotate the view by pressing the arrow keys.'
end
# The instruction displayed after the player has been given the tinderbox and bronze axe by the Survival Guide.
# The instruction displayed after the player has been given the tinderbox and bronze axe by the
# Survival Guide.
dialogue :viewing_items do
type :text
title "Viewing the items you were given"
text "Click on the flashing backpack icon to the right side of the main window to view your inventory. Your inventory is a list of "\
"everything you have in your backpack."
end
title 'Viewing the items you were given'
text 'Click on the flashing backpack icon to the right side of the main window to view your '\
'inventory. Your inventory is a list of everything you have in your backpack.'
end
# The instruction displayed before the player has begun to cut the tree.
dialogue :cut_tree do
type :text
# The instruction displayed before the player has begun to cut the tree.
dialogue :cut_tree do
type :text
title "Cut down a tree"
text "You can click on the backpack icon at any time to view the items that you currently have in your inventory. You will see that you "\
"now have an axe in your inventory. Use this to get some logs by clicking on the indicated tree."
end
title 'Cut down a tree'
text 'You can click on the backpack icon at any time to view the items that you currently '\
'have in your inventory. You will see that you now have an axe in your inventory. '\
'Use this to get some logs by clicking on the indicated tree.'
end
# The instruction displayed when the player begins to cut the tree.
dialogue :please_wait do
type :text
# The instruction displayed when the player begins to cut the tree.
dialogue :please_wait do
type :text
title "Please wait..."
text "Your character is now attempting to cut down the tree. Sit back for a moment whilst he does all the hard work." # TODO she instead of he if applicable
end
title 'Please wait...'
text 'Your character is now attempting to cut down the tree. Sit back for a moment whilst '\
'he does all the hard work.' # TODO: she instead of he if applicable
end
# The instruction displayed after the player has successfully cut logs from the tree.
dialogue :make_a_fire do
type :text
# The instruction displayed after the player has successfully cut logs from the tree.
dialogue :make_a_fire do
type :text
title "Making a fire"
text "Well done! You managed to cut some logs from the tree! Next, use the tinderbox in your inventory to light the logs. First click on the "\
"tinderbox to 'use' it. Then click on the logs in your inventory to light them."
end
title 'Making a fire'
text 'Well done! You managed to cut some logs from the tree! Next, use the tinderbox in '\
'your inventory to light the logs. First click on the tinderbox to \'use\' it.'\
'Then click on the logs in your inventory to light them.'
end
# The instruction displayed when the player begins to light the fire.
dialogue :lighting_fire do
type :text
# The instruction displayed when the player begins to light the fire.
dialogue :lighting_fire do
type :text
title "Please wait..."
text "Your character is now attempting to light the logs. Sit back for a moment whilst he does all the hard work." # TODO she instead of he if applicable
end
title 'Please wait...'
# TODO: she instead of he if applicable
text 'Your character is now attempting to light the logs. Sit back for a moment whilst he '\
'does all the hard work.'
end
# The instruction displayed when the has lit the logs.
dialogue :gained_experience do
type :text
# The instruction displayed when the has lit the logs.
dialogue :gained_experience do
type :text
text "You gained some experience."\
"Click on the flashing bar graph icon near the inventory button to see your skill stats."
end
text 'You gained some experience.'\
'Click on the flashing bar graph icon near the inventory button to see your skill '\
'stats.'
end
# The dialogue displayed when the Player has clicked the flashing skill tab icon.
dialogue :skill_stats do
type :text
# The dialogue displayed when the Player has clicked the flashing skill tab icon.
dialogue :skill_stats do
type :text
title "Your skill stats."
text "" # TODO !!
end
title 'Your skill stats.'
text '' # TODO: this !!
end
end
end
end
+25 -37
View File
@@ -1,52 +1,40 @@
# Information about npc spawning
#
# Npcs are passed to spawn npc as a hash. Every key and every non-integer value must be a Symbol. Every hash must implement the following:
# :name - the name of the npc. If this npc shares its name with another, append the specific id after the name (e.g. :woman_4)
# :x - the x coordinate where the npc will spawn.
# :y - the y coordinate where the npc will spawn.
# Optional arguments are as follows:
# :face - the direction the npc should face when it spawns. Supported options are :north, :north_east, :east, :south_east, :south, :south_west, :west, and :north_west
# :bounds - the rectangular bound that the npc can wander about in. Order is [bottom-left x-coordinate, bottom-left y-coordinate, top-right x-coordinate, top-right y-coordinate]
# :delta_bounds - the rectangular bound that the npc can wander about in, as a difference from the spawn point. Order is [x-delta, y-delta]. Should not be used with :bounds.
# :spawn_animation - the animation that will be played when the npc spawns.
# :spawn_graphic - the graphic that will be played when the npc spawns.
# Functional npcs
# 'Above-ground' npcs
spawn_npc :name => :master_chef, :x => 3076, :y => 3085
spawn_npc :name => :quest_guide, :x => 3086, :y => 3122, :face => :north
spawn_npc :name => :financial_advisor, :x => 3127, :y => 3124, :face => :west
spawn_npc :name => :brother_brace, :x => 3124, :y => 3107, :face => :east
spawn_npc :name => :magic_instructor, :x => 3140, :y => 3085
spawn_npc name: :master_chef, x: 3076, y: 3085
spawn_npc name: :quest_guide, x: 3086, y: 3122, face: :north
spawn_npc name: :financial_advisor, x: 3127, y: 3124, face: :west
spawn_npc name: :brother_brace, x: 3124, y: 3107, face: :east
spawn_npc name: :magic_instructor, x: 3140, y: 3085
# 'Below-ground' npcs
# Note: They aren't actually on a different plane, they're just in a different location that pretends to be underground.
# Note: They aren't actually on a different plane, they're just in a different location that
# pretends to be underground.
spawn_npc :name => :mining_instructor, :x => 3081, :y => 9504
spawn_npc :name => :combat_instructor, :x => 3104, :y => 9506
spawn_npc name: :mining_instructor, x: 3081, y: 9504
spawn_npc name: :combat_instructor, x: 3104, y: 9506
# Non-humanoid npcs
spawn_npc :name => :fishing_spot_316, :x => 3102, :y => 3093
spawn_npc :name => :chicken, :x => 3140, :y => 3095
spawn_npc :name => :chicken, :x => 3140, :y => 3093
spawn_npc :name => :chicken, :x => 3138, :y => 3092
spawn_npc :name => :chicken, :x => 3137, :y => 3094
spawn_npc :name => :chicken, :x => 3138, :y => 3095
spawn_npc name: :fishing_spot_316, x: 3102, y: 3093
spawn_npc name: :chicken, x: 3140, y: 3095
spawn_npc name: :chicken, x: 3140, y: 3093
spawn_npc name: :chicken, x: 3138, y: 3092
spawn_npc name: :chicken, x: 3137, y: 3094
spawn_npc name: :chicken, x: 3138, y: 3095
# 'Below-ground' npcs
# Note: They aren't actually on a different plane, they're just in a different location that pretends to be underground.
# Note: They aren't actually on a different plane, they're just in a different location that
# pretends to be underground.
spawn_npc :name => :giant_rat_87, :x => 3105, :y => 9514
spawn_npc :name => :giant_rat_87, :x => 3105, :y => 9517
spawn_npc :name => :giant_rat_87, :x => 3106, :y => 9514
spawn_npc :name => :giant_rat_87, :x => 3104, :y => 9514
spawn_npc :name => :giant_rat_87, :x => 3105, :y => 9519
spawn_npc :name => :giant_rat_87, :x => 3109, :y => 9516
spawn_npc :name => :giant_rat_87, :x => 3108, :y => 9520
spawn_npc :name => :giant_rat_87, :x => 3102, :y => 9517
spawn_npc name: :giant_rat_87, x: 3105, y: 9514
spawn_npc name: :giant_rat_87, x: 3105, y: 9517
spawn_npc name: :giant_rat_87, x: 3106, y: 9514
spawn_npc name: :giant_rat_87, x: 3104, y: 9514
spawn_npc name: :giant_rat_87, x: 3105, y: 9519
spawn_npc name: :giant_rat_87, x: 3109, y: 9516
spawn_npc name: :giant_rat_87, x: 3108, y: 9520
spawn_npc name: :giant_rat_87, x: 3102, y: 9517
@@ -5,11 +5,12 @@ private
STAGES = []
# The stages that are used when interacting with the Runescape Guide.
RUNESCAPE_GUIDE = [ :not_started, :talk_to_people, :go_through_door, :runescape_guide_finished, :moving_around ]
RUNESCAPE_GUIDE = [:not_started, :talk_to_people, :go_through_door, :runescape_guide_finished,
:moving_around]
STAGES.concat(RUNESCAPE_GUIDE)
# The stages that are used when interacting with the Survival Expert.
SURVIVAL_EXPERT = [ :given_axe, :cut_tree, :cutting_tree, ]
SURVIVAL_EXPERT = [:given_axe, :cut_tree, :cutting_tree]
STAGES.concat(SURVIVAL_EXPERT)
quest :tutorial_island, STAGES
quest :tutorial_island, STAGES
@@ -10,7 +10,7 @@ private
module SurvivalConstants
# The Survival Expert Npc.
@survival_expert = spawn_npc :name => :survival_expert, :x => 3104, :y => 3095, :face => :north
@survival_expert = spawn_npc name: :survival_expert, x: 3104, y: 3095, face: :north
# The inventory tab index.
INVENTORY_TAB_INDEX = 3
@@ -29,7 +29,6 @@ module SurvivalConstants
end
# The conversation with the Survival Expert, when on tutorial island.
conversation :tutorial_surivival_expert do
@@ -39,23 +38,23 @@ conversation :tutorial_surivival_expert do
precondition { |player| player.tutorial_island_progress == :moving_around }
text "Hello there, newcomer. My name is Brynna. My job is to teach you a few survival tips and tricks. First off we're "\
"going to start with the most basic survival skill of all: making a fire."
text 'Hello there, newcomer. My name is Brynna. My job is to teach you a few survival tips and'\
' tricks. First off we\'re going to start with the most basic survival skill of all: '\
'making a fire.'
close &:add_survival_items
close(&:add_survival_items)
end
dialogue :hello_again do
type :npc_speech
npc :survival_expert
precondition { |player| player.tutorial_island_progress == :moving_around }
text "Hello again. I'm here to teach you a few survival tips and tricks. First off we're going to start with the most "\
"basic survival skill of all: making a fire."
text 'Hello again. I\'m here to teach you a few survival tips and tricks. First off we\'re '\
'going to start with the most basic survival skill of all: making a fire.'
close &:add_survival_items
close(&:add_survival_items)
end
# The dialogue displayed when the Survival Expert gives the player a bronze axe.
@@ -63,7 +62,7 @@ conversation :tutorial_surivival_expert do
type :message_with_item
item :bronze_axe
text "The Survival Expert gives you a bronze axe!"
text 'The Survival Expert gives you a bronze axe!'
close { |player| TutorialInstructions.show_instruction(player) }
end
@@ -73,23 +72,28 @@ conversation :tutorial_surivival_expert do
type :message_with_item
item :tinderbox
text "The Survival Expert gives you a tinderbox!"
text 'The Survival Expert gives you a tinderbox!'
close { |player| TutorialInstructions.show_instruction(player) }
end
# The dialogue displayed when the Survival Expert gives the player both a bronze axe and a tinderbox.
# The dialogue displayed when the Survival Expert gives the player both a bronze axe and a
# tinderbox.
dialogue :give_axe_and_tinderbox do
type :message_with_item
item :bronze_axe # TODO the tinderbox is also displayed - find this dialogue id. Scale looks like the default http://i.imgur.com/i1abN5X.png
item :bronze_axe
# TODO: the tinderbox is also displayed - find this dialogue id. Scale looks like the default
# http://i.imgur.com/i1abN5X.png
text 'The Survival Expert gives you a tinderbox and a bronze axe!'
text "The Survival Expert gives you a tinderbox and a bronze axe!"
close do |player|
if (player.tutorial_island_progress < :given_axe)
if player.tutorial_island_progress < :given_axe
player.tutorial_island_progress = :given_axe
player.send(SwitchTabInterfaceMessage.new(SurvivalConstants::INVENTORY_TAB_INDEX, SurvivalConstants::INVENTORY_TAB_ID))
player.send(FlashTabInterfaceMessage.new(SurvivalConstants::INVENTORY_TAB_INDEX))
index = SurvivalConstants::INVENTORY_TAB_INDEX
player.send(SwitchTabInterfaceMessage.new(index, SurvivalConstants::INVENTORY_TAB_ID))
player.send(FlashTabInterfaceMessage.new(index))
end
TutorialInstructions.show_instruction(player)
@@ -101,14 +105,14 @@ conversation :tutorial_surivival_expert do
type :message_with_item
item :logs
text "You get some logs."
text 'You get some logs.'
close { |player| TutorialInstructions.show_instruction(player) }
end
end
# Add the survival items (bronze axe and tinderbox) to the inventory of the player, if they do not already have them.
# Add the survival items (bronze axe and tinderbox) to the inventory of the player, if they do not
# already have them.
def add_survival_items(player)
inventory = player.inventory
@@ -125,22 +129,26 @@ def add_survival_items(player)
send_dialogue(player, get_dialogue(:tutorial_surivival_expert, dialogue))
end
# Intercept the FirstObjectActionMessage to send tutorial-only events if the player is chopping down a tree.
# Intercept the FirstObjectActionMessage to send tutorial-only events if the player is chopping
# down a tree.
on :message, :first_object_action do |player, message|
if (player.in_tutorial_island && message.id == SurvivalConstants::TREE_ID)
if player.in_tutorial_island && message.id == SurvivalConstants::TREE_ID
progress = player.tutorial_island_progress
if (progress < :cut_tree)
# TODO display "You cannot cut down this tree; you must first follow the guide's instructions."
elsif (player.tutorial_island_progress == :cut_tree)
player.tutorial_island_progress = :cutting_tree # Don't break the chain, so that the Woodcutting event actually happens.
if progress < :cut_tree
# TODO: 'You cannot cut down this tree; you must first follow the guide's instructions.'
elsif player.tutorial_island_progress == :cut_tree
# Don't break the chain, so that the Woodcutting event actually happens.
player.tutorial_island_progress = :cutting_tree
end
end
end
# Intercept the FlashingTabClickedMessage to update the player's progress, if applicable.
on :message, :flashing_tab_clicked do |player, message|
if (player.in_tutorial_island && message.tab == SurvivalConstants::INVENTORY_TAB_INDEX && player.tutorial_island_progress == :given_axe)
if player.in_tutorial_island && message.tab == SurvivalConstants::INVENTORY_TAB_INDEX &&
player.tutorial_island_progress == :given_axe
player.tutorial_island_progress = :cut_tree
message.terminate
end
end
end
+6 -10
View File
@@ -5,30 +5,26 @@ java_import 'org.apollo.game.model.entity.Player'
# Declare the tutorial island progress attribute.
declare_attribute(:tutorial_island_progress, :not_started, :persistent)
# The existing player class.
class Player
# Returns whether or not this Player is currently on tutorial island.
def in_tutorial_island
x, y = self.position.x, self.position.y
return above_ground(x, y) || below_ground(x, y)
x = position.x
y = position.y
above_ground(x, y) || below_ground(x, y)
end
end
private
# Returns whether or not the specified coordinate pair is above ground on tutorial island.
def above_ground(x, y)
return (x >= 3053 && x <= 3156 && y >= 3056 && y <= 3136)
x >= 3053 && x <= 3156 && y >= 3056 && y <= 3136
end
# Returns whether or not the specified coordinate pair is 'below' ground on tutorial island.
def below_ground(x, y)
return (x >= 3072 && x <= 3118 && y >= 9492 && y <= 9535)
end
x >= 3072 && x <= 3118 && y >= 9492 && y <= 9535
end
+1 -1
View File
@@ -2,4 +2,4 @@ LOGOUT_BUTTON_ID = 2458
on :button, LOGOUT_BUTTON_ID do |player|
player.logout
end
end
+18 -17
View File
@@ -4,6 +4,7 @@ require 'set'
module DoorConstants
# TODO: GameObjectOrientation enumeration in Apollo's core?
# The orientation of a door.
module Orientation
WEST = 0
NORTH = 1
@@ -15,29 +16,29 @@ module DoorConstants
DOOR_SIZE = 1
# Door object ids that have a hinge on the left side.
LEFT_HINGE_DOORS = Set.new [ 1516, 1536, 1533 ]
LEFT_HINGE_DOORS = Set.new [1516, 1536, 1533]
# Door object ids that have a hinge on the right side.
RIGHT_HINGE_DOORS = Set.new [ 1519, 1530, 4465, 4467, 3014, 3017, 3018, 3019 ]
RIGHT_HINGE_DOORS = Set.new [1519, 1530, 4465, 4467, 3014, 3017, 3018, 3019]
# The hash of orientations that a door will translate to when opened.
ORIENTATIONS = {
# Orientations for doors that have a hinge on the left side.
:left_side_hinge => {
Orientation::NORTH => Orientation::WEST,
Orientation::SOUTH => Orientation::EAST,
Orientation::WEST => Orientation::SOUTH,
Orientation::EAST => Orientation::NORTH
},
# Orientations for doors that have a hinge on the left side.
left_side_hinge: {
Orientation::NORTH => Orientation::WEST,
Orientation::SOUTH => Orientation::EAST,
Orientation::WEST => Orientation::SOUTH,
Orientation::EAST => Orientation::NORTH
},
# Orientations for doors that have a hinge on the right side.
:right_side_hinge => {
Orientation::NORTH => Orientation::EAST,
Orientation::SOUTH => Orientation::WEST,
Orientation::WEST => Orientation::NORTH,
Orientation::EAST => Orientation::SOUTH
}
# Orientations for doors that have a hinge on the right side.
right_side_hinge: {
Orientation::NORTH => Orientation::EAST,
Orientation::SOUTH => Orientation::WEST,
Orientation::WEST => Orientation::NORTH,
Orientation::EAST => Orientation::SOUTH
}
}
end
end
+6 -5
View File
@@ -1,3 +1,4 @@
java_import 'org.apollo.game.action.DistancedAction'
# A distanced action which opens a door.
@@ -13,20 +14,20 @@ class OpenDoorAction < DistancedAction
def executeAction
mob.turn_to(@door.position)
DoorUtil::toggle(@door)
DoorUtil.toggle(@door)
stop
end
def equals(other)
return (get_class == other.get_class && @door == other.door)
get_class == other.get_class && @door == other.door
end
end
# MessageListener for opening and closing doors.
on :message, :first_object_action do |player, message|
if DoorUtil::is_door?(message.id)
door = DoorUtil::get_door_object(message.position, message.id)
if DoorUtil.door?(message.id)
door = DoorUtil.get_door_object(message.position, message.id)
player.start_action(OpenDoorAction.new(player, door)) unless door.nil?
end
end
end
+20 -20
View File
@@ -15,20 +15,18 @@ module DoorUtil
# Translates a door's position in the direction of its orientation.
def self.translate_door_position(door)
position = door.position
orientation = door.orientation
case orientation
case door.orientation
when Orientation::WEST
return Position.new(position.x - 1, position.y, position.height)
Position.new(position.x - 1, position.y, position.height)
when Orientation::EAST
return Position.new(position.x + 1, position.y, position.height)
Position.new(position.x + 1, position.y, position.height)
when Orientation::NORTH
return Position.new(position.x, position.y + 1, position.height)
Position.new(position.x, position.y + 1, position.height)
when Orientation::SOUTH
return Position.new(position.x, position.y - 1, position.height)
Position.new(position.x, position.y - 1, position.height)
else fail "Unsupported orientation #{door.orientation}."
end
raise 'Invalid orientation for door!'
end
# Translates the orientation of a door to a toggled position.
@@ -42,13 +40,12 @@ module DoorUtil
return ORIENTATIONS[:left_side_hinge][orientation]
end
raise 'Given object was not registered as a door.'
fail 'Given object was not registered as a door.'
end
# Toggles the given door.
def self.toggle(door)
position = door.position
region = $world.region_repository.from_position(position)
region = $world.region_repository.from_position(door.position)
region.remove_entity(door)
if TOGGLED_DOORS.include?(door)
@@ -57,11 +54,13 @@ module DoorUtil
original_region = $world.region_repository.from_position(original_door.position)
original_region.add_entity(original_door)
else
toggled_position = translate_door_position(door)
toggled_orientation = translate_door_orientation(door)
toggled_door = DynamicGameObject.create_public($world, door.id, toggled_position, door.type, toggled_orientation)
position = translate_door_position(door)
orientation = translate_door_orientation(door)
type = door.type
toggled_region = $world.region_repository.from_position(toggled_position)
toggled_door = DynamicGameObject.create_public($world, door.id, position, type, orientation)
toggled_region = $world.region_repository.from_position(position)
toggled_region.add_entity(toggled_door)
TOGGLED_DOORS[toggled_door] = door
@@ -70,14 +69,15 @@ module DoorUtil
# Gets the door object at the given position, if it exists.
def self.get_door_object(position, object_id)
game_objects = $world.region_repository.from_position(position).get_entities(position, EntityType::DYNAMIC_OBJECT, EntityType::STATIC_OBJECT)
game_objects.each { |game_object| return game_object if game_object.id == object_id }
return nil
region = $world.region_repository.from_position(position)
objects = region.get_entities(position, EntityType::DYNAMIC_OBJECT, EntityType::STATIC_OBJECT)
objects.each { |game_object| return game_object if game_object.id == object_id }
nil
end
# Checks if the given game object id is a door.
def self.is_door?(object_id)
def self.door?(object_id)
RIGHT_HINGE_DOORS.include?(object_id) || LEFT_HINGE_DOORS.include?(object_id)
end
end
end
@@ -3,14 +3,13 @@ require 'java'
java_import 'org.apollo.game.message.impl.SetPlayerActionMessage'
java_import 'org.apollo.game.model.entity.Player'
# A right-click action for a Player.
class PlayerAction
attr_reader :slot, :primary, :name
def initialize(slot, primary, name)
index = [ :first, :second, :third, :fourth, :fifth ].find_index(slot)
raise "Unsupported action slot #{slot}." if index.nil?
index = [:first, :second, :third, :fourth, :fifth].find_index(slot)
fail "Unsupported action slot #{slot}." if index.nil?
@slot = index
@primary = primary
@@ -26,7 +25,7 @@ FOLLOW_ACTION = PlayerAction.new(:fifth, true, 'Follow')
# Shows multiple context menu action for the specified player
def show_actions(player, *actions)
raise 'Must specify at least one action' if actions.nil?
fail 'Must specify at least one action.' if actions.nil?
actions.each do |action|
player.add_action(action)
@@ -44,6 +43,7 @@ def hide_action(player, action)
show_action(player, PlayerAction.new(action.slot, action.primary, 'null'))
end
# Monkey-patch Player to provide action utility methods.
class Player
def actions
@@ -54,8 +54,8 @@ class Player
actions[action.slot] = action.name
end
def has_action(action)
def action?(action)
actions[action.slot] == action.name
end
end
end
+2 -2
View File
@@ -1,6 +1,6 @@
java_import 'org.apollo.game.model.entity.Player'
on :login do |event, player|
on :login do |_event, player|
show_action(player, TRADE_ACTION)
show_action(player, FOLLOW_ACTION)
end
end
+2 -2
View File
@@ -8,8 +8,8 @@
<author>Ryley</author>
</authors>
<scripts>
<script>player-action.rb</script>
<script>action.rb</script>
<script>login.rb</script>
</scripts>
<dependencies />
</plugin>
</plugin>
+25 -26
View File
@@ -1,7 +1,7 @@
# Defines a quest with the specified name.
def quest(name, stage_names)
stages = { }
stages = {}
stage_names.each_with_index { |stage, index| stages[stage] = QuestStage.new(stage, index, name) }
QUESTS[name] = Quest.new(name, stages)
@@ -18,25 +18,26 @@ class Quest
# Creates the Quest.
def initialize(name, stages)
raise "Quest name must be a symbol, received '#{name}'." unless name.kind_of?(Symbol)
fail "Quest name must be a symbol, received '#{name}'." unless name.is_a?(Symbol)
@name = name
@stages = stages
end
# Gets the finishing quest stage (i.e. the stage that indicates the Player has completed the quest).
def final_stage()
# Gets the finishing quest stage (i.e. the stage that indicates the Player has completed the
# quest).
def final_stage
@stages.last
end
# Gets the starting quest stage.
def initial_stage()
def initial_stage
@stages.first
end
# Gets the QuestStage with the specified name.
def stage(name)
stage = @stages[name]
raise "No stage named #{name} exists in #{@name}." if stage.nil?
fail "No stage named #{name} exists in #{@name}." if stage.nil?
stage
end
@@ -47,7 +48,7 @@ class QuestStage
attr_reader :name, :index
# Creates the QuestProgress.
def initialize(name, index, quest, log_text=nil)
def initialize(name, index, quest, log_text = nil)
@name = name
@index = index
@quest = quest
@@ -61,41 +62,40 @@ class QuestStage
# Gets the log text for this stage.
def log_text
raise "Cannot get the log text from an unlogged quest stage." unless logged
fail 'Cannot get the log text from an unlogged quest stage.' unless logged
@log_text
end
# Defines the equality operator.
def ==(name)
@index == index_of(name)
def ==(other)
@index == index_of(other)
end
# Defines the not equal operator.
def !=(name)
@index != index_of(name)
def !=(other)
@index != index_of(other)
end
# Defines the greater than or equal to operator.
def >=(name)
@index >= index_of(name)
def >=(other)
@index >= index_of(other)
end
# Defines the greater than operator.
def >(name)
@index > index_of(name)
def >(other)
@index > index_of(other)
end
# Defines the less than operator.
def <(name)
@index < index_of(name)
def <(other)
@index < index_of(other)
end
# Defines the less than or equal to operator.
def <=(name)
@index <= index_of(name)
def <=(other)
@index <= index_of(other)
end
private
# Gets the index of the QuestStage with the specified name.
@@ -105,7 +105,6 @@ class QuestStage
end
# Define method_missing for player
class Player
@@ -113,16 +112,16 @@ class Player
def method_missing(symbol, *args)
unless args.nil?
arg = args[0]
args[0] = arg.name if arg.kind_of?(QuestStage)
args[0] = arg.name if arg.is_a?(QuestStage)
end
result = super(symbol, *args)
string = symbol.to_s
if (string.end_with?('_progress'))
if string.end_with?('_progress')
name = string[0..-10] # Cut the '_progress' from the end
quest = QUESTS[name.to_sym]
raise "No Quest with the name '#{name}' exists." if quest.nil?
fail "No Quest with the name '#{name}' exists." if quest.nil?
result = quest.stage(result)
end
@@ -130,4 +129,4 @@ class Player
result
end
end
end
+1 -1
View File
@@ -7,4 +7,4 @@ end
on :button, RUN_BUTTON_ID do |player|
player.toggle_running
end
end
+3 -2
View File
@@ -11,7 +11,6 @@ class Fish
@id = id
@level = level
@experience = experience
@name = name_of(:item, id)
end
@@ -19,7 +18,9 @@ end
# Appends a Fish to the hash.
def append_fish(name, hash)
fail 'Hash must contain an id, level, and experience.' unless hash.has_keys?(:id, :level, :experience)
unless hash.has_keys?(:id, :level, :experience)
fail 'Hash must contain an id, level, and experience.'
end
CATCHABLE_FISH[name] = Fish.new(hash[:id], hash[:level], hash[:experience])
end
+14 -15
View File
@@ -16,27 +16,27 @@ class FishingAction < DistancedAction
@tool = spot.tools[option - 1]
@options = (option == 1) ? spot.first_fish : spot.second_fish
@minimum_level = @options.map { |fish| fish.level }.min
@minimum_level = @options.map(&:level).min
end
# Returns whether or not a catch is successful.
def successful_catch(level, requirement)
return [level - requirement + 5, 30].min > rand(40)
[level - requirement + 5, 30].min > rand(40)
end
# Starts the fishing process.
def start_fishing()
def start_fishing
@started = true
mob.send_message(tool.message, true)
end
# Executes the action.
def executeAction()
def executeAction
skills = mob.skill_set
fishing_level = skills.get_skill(Skill::FISHING).current_level
mob.turn_to(position)
if (@minimum_level > fishing_level)
if @minimum_level > fishing_level
mob.send_message("You need a fishing level of #{@minimum_level} to fish at this spot.")
stop
return
@@ -62,12 +62,10 @@ class FishingAction < DistancedAction
return
end
unless @started
start_fishing
else
if @started
options = @options.reject { |fish| fish.level > fishing_level }
# Player may level up mid-action so reject here, not at initialisation.
fish = options.sample # TODO it's a ~70/30 chance, not 50/50
fish = options.sample # TODO: it's a ~70/30 chance, not 50/50
if successful_catch(fishing_level, fish.level)
inventory.remove(bait) unless bait.nil?
@@ -77,12 +75,14 @@ class FishingAction < DistancedAction
mob.send_message("You catch #{name.end_with?('s') ? 'some' : 'a'} #{name.downcase}.", true)
skills.add_experience(Skill::FISHING, fish.experience)
if (find_bait == -1)
if find_bait == -1
mob.send_message("You need more #{name_of(:item, bait).downcase}s to fish at this spot.")
stop
return
end
end
else
start_fishing
end
mob.play_animation(@tool.animation)
@@ -90,14 +90,13 @@ class FishingAction < DistancedAction
# Finds the id of the first piece of bait in the player's inventory, or nil if no bait is
# required, or -1 if the player's inventory does not contain any valid bait.
def find_bait()
def find_bait
baits = @tool.bait
if baits.empty? then nil else baits.find(-1) { |bait| mob.inventory.contains(bait) } end
baits.empty? ? nil : baits.find(-1) { |bait| mob.inventory.contains(bait) }
end
# Stops this action.
def stop()
def stop
super
mob.stop_animation
end
+1 -1
View File
@@ -23,4 +23,4 @@ end
append_spot(309, Spot.new([:fly_fishing_rod, :fishing_rod], [:trout, :salmon], [:pike]))
append_spot(312, Spot.new([:lobster_cage, :harpoon], [:lobster], [:tuna, :swordfish]))
append_spot(313, Spot.new([:big_net, :harpoon], [:mackerel, :cod], [:bass, :shark]))
append_spot(316, Spot.new([:small_net, :fishing_rod], [:shrimp, :anchovy], [:sardine, :herring]))
append_spot(316, Spot.new([:small_net, :fishing_rod], [:shrimp, :anchovy], [:sardine, :herring]))
+31 -18
View File
@@ -7,10 +7,10 @@ FISHING_TOOLS = {}
# A fishing tool.
class Tool
attr_reader :id, :bait, :animation, :message, :name
attr_reader :animation, :bait, :id, :message, :name
# Creates the tool.
def initialize(id, bait=[], animation, message)
def initialize(id, animation, message, bait)
@id = id
@bait = bait
@animation = Animation.new(animation)
@@ -21,27 +21,40 @@ class Tool
end
private
# Appends a tool with the specified name to the hash.
def append_tool(name, tool)
FISHING_TOOLS[name] = tool
def tool(name, hash)
unless hash.has_keys?(:id, :animation, :message)
fail 'Hash must contain an id, animation, and message.'
end
bait = hash[:bait] || []
FISHING_TOOLS[name] = Tool.new(hash[:id], hash[:animation], hash[:message], bait)
end
HARPOON_ANIMATION_ID = 618
CAGE_ANIMATION_ID = 619
NET_ANIMATION_ID = 620
ROD_ANIMATION_ID = 622
# The harpoon fishing animation id.
HARPOON_ANIMATION = 618
# TODO The other feathers that can be used
FISHING_ROD_BAIT = [ 313 ]
FLY_FISHING_ROD_BAIT = [ 314 ]
# The cage fishing animation id.
CAGE_ANIMATION = 619
append_tool(:lobster_cage, Tool.new(301, CAGE_ANIMATION_ID, 'You attempt to catch a lobster...'))
append_tool(:small_net, Tool.new(303, NET_ANIMATION_ID, 'You cast out your net...'))
append_tool(:big_net, Tool.new(305, NET_ANIMATION_ID, 'You cast out your net...'))
append_tool(:harpoon, Tool.new(311, HARPOON_ANIMATION_ID, 'You start harpooning fish...'))
# The net fishing animation id.
NET_ANIMATION = 620
append_tool(:fishing_rod, Tool.new(307, FISHING_ROD_BAIT, ROD_ANIMATION_ID, 'You attempt to catch a fish...'))
append_tool(:fly_fishing_rod, Tool.new(309, FLY_FISHING_ROD_BAIT, ROD_ANIMATION_ID, 'You attempt to catch a fish...'))
# The rod fishing animation id.
ROD_ANIMATION = 622
# TODO: The other feathers that can be used
FISHING_ROD_BAIT = [313]
FLY_FISHING_ROD_BAIT = [314]
tool :lobster_cage, id: 301, animation: CAGE_ANIMATION, message: 'You attempt to catch a lobster...'
tool :small_net, id: 303, animation: NET_ANIMATION, message: 'You cast out your net...'
tool :big_net, id: 305, animation: NET_ANIMATION, message: 'You cast out your net...'
tool :harpoon, id: 311, animation: HARPOON_ANIMATION, message: 'You start harpooning fish...'
tool :fishing_rod, id: 307, animation: ROD_ANIMATION, message: 'You attempt to catch a fish...',
bait: FISHING_ROD_BAIT
tool :fly_fishing_rod, id: 309, animation: ROD_ANIMATION, message: 'You attempt to catch a fish...',
bait: FLY_FISHING_ROD_BAIT
+17 -14
View File
@@ -10,13 +10,13 @@ class Herb < Ingredient
def initialize(item_id, unidentified, level, experience)
super item_id
@unidentified = unidentified
@level = level
@experience = experience
end
def invoke(player, id, slot)
def invoke(player, _id, slot)
item = player.inventory.get(slot)
player.start_action(HerbIdentificationAction.new(player, self, slot, item))
end
@@ -25,51 +25,54 @@ 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")
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)
# TODO: 'as an' in some cases
end
stop
end
def equals(other)
return (get_class == other.get_class and slot == other.slot and herb == other.herb)
get_class == other.get_class && slot == other.slot && herb == other.herb
end
end
# Appends a herb to the InventoryItemMessage interception.
def append_herb(item_id, unidentified, level, experience)
herb = Herb.new(item_id, unidentified, level, experience)
append_herblore_item(herb, unidentified)
return herb
append_herblore_item(herb, unidentified)
herb
end
# Herbs
@@ -87,4 +90,4 @@ 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)
TORSTOL = append_herb(269, 219, 75, 15)
+15 -13
View File
@@ -1,4 +1,4 @@
# Thanks to Sillhouette <http://www.rune-server.org/members/silhouette/> for posting
# 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'
@@ -13,15 +13,14 @@ 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!'
fail 'You cannot instantiate this module!'
end
def invoke(player, primary, secondary)
raise NotImplementedError.new('You must implement the invocation of HerbloreMethod!')
def invoke(_player, _primary, _secondary)
fail 'You must implement the invocation of HerbloreMethod!'
end
end
@@ -76,25 +75,28 @@ def append_herblore_item(method, key, secondary = -1)
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.
# Utility method for checking if a player's inventory has a 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)
!item.nil? && item.id == id && 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}."
# Utility method for checking if a player's Herblore (maximum) level is at the required level. 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.get_skill(Skill::HERBLORE).current_level)
if required > player.skill_set.get_skill(Skill::HERBLORE).current_level
player.send_message("You need a Herblore level of at least #{required} to #{action}.")
return false
end
return true
true
end
# Opens a 'make' dialogue for the specified player, displaying the specified item. Optionally, a listener can be used for the dialogue.
# 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(SetWidgetItemModelMessage.new(1746, item, 170))
player.interface_set.open_dialogue(listener, HERBLORE_DIALOGUE)
end
end
+25 -27
View File
@@ -18,16 +18,15 @@ class Ingredient
@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.
# 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
next if inv_item.nil?
id = inv_item.id
inventory_amount = inv_item.amount
@@ -47,7 +46,7 @@ class Ingredient
return true
end
return false
false
end
end
@@ -59,11 +58,10 @@ class GroundIngredient < Ingredient
def initialize(item_id, raw)
super(item_id)
@raw = raw
end
def invoke(player, pestle_mortar, ingredient)
def invoke(player, _pestle_mortar, _ingredient)
action = GrindingAction.new(player, self)
listener = GrindingDialogueListener.new(player, action)
@@ -71,7 +69,8 @@ class GroundIngredient < Ingredient
end
end
# A DialogueAdapter used for grinding ingredients. It is also used as an EnterAmountListener for the amount of grinding actions.
# A DialogueAdapter used for grinding ingredients. It is also used as an EnterAmountListener for
# the amount of grinding actions.
class GrindingDialogueListener < DialogueAdapter
include EnterAmountListener
@@ -79,7 +78,6 @@ class GrindingDialogueListener < DialogueAdapter
def initialize(player, action)
super()
@player = player
@action = action
end
@@ -103,7 +101,7 @@ class GrindingDialogueListener < DialogueAdapter
# Called when an amount of grinding actions has been entered.
def amountEntered(amount)
if amount <= 0 then return else execute(amount) end
execute(amount) if amount > 0
end
# Called to set the action(s) in motion.
@@ -129,7 +127,7 @@ class GrindingAction < Action
attr_reader :ingredient, :amount, :pulses, :slot, :listener
def initialize(player, ingredient)
super 0, true, player
super(0, true, player)
@ingredient = ingredient
@pulses = 0
@@ -145,7 +143,7 @@ class GrindingAction < Action
if @pulses == 0
mob.play_animation GRINDING_ANIM
elsif @pulses == 1
if not gather_materials
unless gather_materials
stop
return
end
@@ -159,45 +157,45 @@ class GrindingAction < Action
inventory.reset(@slot)
inventory.add(@ingredient.item)
set_delay(1)
elsif @pulses == 2
mob.stop_animation
continue()
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
next if item.nil?
id = item.id
if id == PESTLE_MORTAR and !pst_mrt
if id == PESTLE_MORTAR && !pst_mrt
pst_mrt = true
elsif id == raw and !ingr
elsif id == raw && !ingr
ingr = true
@slot = slot
end
return true if pst_mrt and ingr
return true if pst_mrt && ingr
end
mob.send_message("You do not have any more #{name_of(raw).downcase}s.")
return false
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
@@ -213,11 +211,11 @@ class GrindingAction < Action
def stop
super
mob.inventory.remove_listener(@listener) unless listener == nil
mob.inventory.remove_listener(@listener) unless listener.nil?
end
def equals(other)
return (get_class == other.get_class and @ingredient == other.ingredient)
get_class == other.get_class && @ingredient == other.ingredient
end
end
@@ -225,7 +223,7 @@ end
def append_ground(id, raw)
ground = GroundIngredient.new(id, raw)
append_herblore_item(ground, PESTLE_MORTAR, raw)
return ground
ground
end
# Normal ingredients
@@ -250,4 +248,4 @@ MAGIC_ROOTS = Ingredient.new(6051)
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)
# CRUSHED_NEST = append_ground(6693, 5075) # TODO: only in 377
+83 -78
View File
@@ -13,25 +13,26 @@ 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.
# 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
super(item_id)
@herb = herb
@level = level
end
def invoke(player, primary, secondary)
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.
@@ -51,11 +52,12 @@ class FinishedPotion
action = FinishedMixingAction.new(player, primary, secondary, self)
listener = FinishedMixingDialogueListener.new(player, action)
open_dialogue(player, @item.id, listener)
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.
# A DialogueAdapter used for mixing potions. It is also used as an EnterAmountListener for the
# amount of mixing actions.
class MixingDialogueListener < DialogueAdapter
include EnterAmountListener
@@ -63,7 +65,7 @@ class MixingDialogueListener < DialogueAdapter
def initialize(player, action)
super()
@player = player
@action = action
end
@@ -71,7 +73,7 @@ class MixingDialogueListener < DialogueAdapter
# 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
@@ -85,12 +87,12 @@ class MixingDialogueListener < DialogueAdapter
amount = calculate_maximum if amount == -2
execute(amount)
return true
true
end
# Called when an amount of mixing actions has been entered.
def amountEntered(amount)
if amount <= 0 then return else execute(amount) end
execute(amount) if amount > 0
end
# Called to set the action(s) in motion.
@@ -99,7 +101,7 @@ class MixingDialogueListener < DialogueAdapter
@player.start_action(@action)
end
def calculate_maximum(code)
def calculate_maximum(_code)
# Override for potion-specific amount calculation.
end
@@ -118,18 +120,17 @@ 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
[herbs, amount].min
end
end
# A MixingDialogueListener used for mixing finished potions.
@@ -144,7 +145,7 @@ class FinishedMixingDialogueListener < MixingDialogueListener
amount = item_amount if amount > item_amount
end
return amount
amount
end
end
@@ -170,6 +171,7 @@ class MixingAction < Action
stop
return
end
@started = true
end
@@ -178,15 +180,17 @@ class MixingAction < Action
return
end
end
mob.play_animation(MIXING_ANIM)
execute_action
if (@amount -= 1) > 0 then @pulses = 0 else stop end
@amount -= 1
@amount > 0 ? @pulses = 0 : stop
end
def stop
super()
mob.inventory.remove_listener(@listener) unless @listener == nil
mob.inventory.remove_listener(@listener) unless @listener.nil?
end
def execute_action
@@ -195,7 +199,7 @@ class MixingAction < Action
def gather_materials
# Override for ingredient checking and gathering
return false
false
end
# Sets the amount of actions.
@@ -204,7 +208,7 @@ class MixingAction < Action
end
def equals(other)
return (get_class == other.get_class and @potion == other.potion)
get_class == other.get_class && @potion == other.potion
end
end
@@ -213,7 +217,7 @@ class UnfinishedMixingAction < MixingAction
attr_reader :slots
def initialize(player, potion)
super(player, potion, "use this herb.")
super(player, potion, 'use this herb.')
end
def execute_action
@@ -221,7 +225,9 @@ class UnfinishedMixingAction < MixingAction
player = mob
inventory = player.inventory
player.send_message("You put the #{name} in the water to make an unfinished #{name.sub(/ leaf$/, "")} potion.", true)
created = name.sub(/ leaf$/, '')
message = "You put the #{name} in the water to make an unfinished #{created} potion."
player.send_message(message, true)
@slots.each do |slot, amount|
unless inventory.remove_slot(slot, amount)
@@ -253,23 +259,23 @@ class UnfinishedMixingAction < MixingAction
@slots[vial_slot] = 1
@slots[herb_slot] = 1
return true
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")
super(player, potion, 'mix this potion')
@unfinished = unfinished
@ingredient = ingredient
end
def execute_action
player = mob
def executeAction
player = mob
ingredient = name_of(@ingredient).downcase
name = @potion.item.definition.name.sub('(3)', '')
@@ -277,17 +283,17 @@ class FinishedMixingAction < MixingAction
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)
unless inventory.remove_slot(slot, amount) # TODO: will this remove stuff incorrectly?
stop
return
end
end
inventory.add(@potion.item)
end
def gather_materials
@slots = {}
inventory = mob.inventory
@@ -297,70 +303,69 @@ class FinishedMixingAction < MixingAction
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
true
end
end
# Appends a finished potion to the ItemOnItemMessage handling interception.
def append_finished_potion(item, unfinished, ingredient, level, experience)
potion = FinishedPotion.new(item, [ unfinished, ingredient ], level, experience)
def 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
potion
end
# Appends an unfinished potion to the ItemOnItemMessage handling interception.
def append_unfinished_potion(item, herb, level)
def unfinished_potion(item, herb, level)
potion = UnfinishedPotion.new(item, herb, level)
append_herblore_item(potion, herb.item_id, WATER_VIAL_ID)
return potion
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)
UNF_GUAM = unfinished_potion(91, GUAM_LEAF, 1) # 3
UNF_MARRENTILL = unfinished_potion(93, MARRENTILL, 5)
UNF_TARROMIN = unfinished_potion(95, TARROMIN, 12)
UNF_HARRALANDER = unfinished_potion(97, HARRALANDER, 22)
UNF_RANARR = unfinished_potion(99, RANARR, 30)
UNF_TOADFLAX = unfinished_potion(3002, TOADFLAX, 34)
UNF_IRIT = unfinished_potion(101, IRIT_LEAF, 45)
UNF_AVANTOE = unfinished_potion(103, AVANTOE, 50)
UNF_KWUARM = unfinished_potion(105, KWUARM, 55)
UNF_SNAPDRAGON = unfinished_potion(3004, SNAPDRAGON, 63)
UNF_CADANTINE = unfinished_potion(107, CADANTINE, 66)
UNF_LANTADYME = unfinished_potion(2483, LANTADYME, 69)
UNF_DWARF_WEED = unfinished_potion(109, DWARF_WEED, 72)
UNF_TORSTOL = 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)
ATTACK_POT = finished_potion(121, UNF_GUAM, EYE_NEWT, 1, 25) # 3
ANTIPOISON_POT = finished_potion(175, UNF_MARRENTILL, UNICORN_HORN_DUST, 5, 37.5)
STRENGTH_POT = finished_potion(115, UNF_TARROMIN, LIMPWURT_ROOT, 12, 50)
RESTORE_POT = finished_potion(127, UNF_HARRALANDER, RED_SPIDERS_EGGS, 18, 62.5)
ENERGY_POT = finished_potion(3010, UNF_HARRALANDER, CHOCOLATE_DUST, 26, 67.5)
DEFENCE_POT = finished_potion(133, UNF_RANARR, WHITE_BERRIES, 30, 75)
AGILITY_POT = finished_potion(3034, UNF_TOADFLAX, TOADS_LEGS, 34, 80)
PRAYER_POT = finished_potion(139, UNF_RANARR, SNAPE_GRASS, 38, 87.5)
SUPER_ATTACK_POT = finished_potion(145, UNF_IRIT, EYE_NEWT, 45, 100)
SUPER_ANTIPOISON_POT = finished_potion(181, UNF_IRIT, UNICORN_HORN_DUST, 48, 106.3)
FISHING_POT = finished_potion(151, UNF_AVANTOE, SNAPE_GRASS, 50, 112.5)
SUPER_ENERGY_POT = finished_potion(3018, UNF_AVANTOE, MORT_MYRE_FUNGI, 52, 117.5)
SUPER_STRENGTH_POT = finished_potion(157, UNF_KWUARM, LIMPWURT_ROOT, 55, 125)
WEAPON_POISON = finished_potion(187, UNF_KWUARM, DRAGON_SCALE_DUST, 60, 137.5)
SUPER_RESTORE_POT = finished_potion(3026, UNF_SNAPDRAGON, RED_SPIDERS_EGGS, 63, 142.5)
SUPER_DEFENCE_POT = finished_potion(163, UNF_CADANTINE, WHITE_BERRIES, 66, 150)
ANTIFIRE_POT = finished_potion(2428, UNF_LANTADYME, DRAGON_SCALE_DUST, 69, 157.5)
RANGING_POT = finished_potion(169, UNF_DWARF_WEED, WINE_ZAMORAK, 72, 162.5)
MAGIC_POT = finished_potion(3042, UNF_LANTADYME, POTATO_CACTUS, 76, 172.5)
ZAMORAK_BREW = finished_potion(189, UNF_TORSTOL, JANGERBERRIES, 78, 175)
+44 -29
View File
@@ -2,57 +2,50 @@ require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.entity.Skill'
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 ]
ILLEGAL_ALCH_ITEMS = [995, 6529, 6306, 6307, 6308, 6309, 6310]
# A spell that alchemises an item.
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
attr_reader :animation, :graphic, :multiplier, :experience
def initialize(level, elements, experience, animation, graphic, multiplier)
super(level, elements, experience)
@animation = animation
@graphic = graphic
@multiplier = multiplier
@delay = delay
end
end
# An Action that performs an AlchemySpell.
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)
ILLEGAL_ALCH_ITEMS.include?(@item.id)
end
def execute_action
def executeAction
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)
mob.skill_set.add_experience(Skill::MAGIC, @spell.experience)
set_delay(ALCHEMY_DELAY)
elsif @pulses == 1
mob.stop_animation
mob.stop_graphic
@@ -62,9 +55,31 @@ class AlchemyAction < ItemSpellAction
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)
private
# The delay of an alchemy spell.
ALCHEMY_DELAY = 4
# The height of the graphic.
GRAPHIC_HEIGHT = 100
# Inserts an `AlchemySpell` into the hash of available alchemy spells.
def alchemy(_name, hash)
unless hash.has_keys?(:button, :level, :runes, :animation, :graphic, :multiplier, :experience)
fail 'Hash must have button, level, runes, animation, graphic, multiplier, experience keys.'
end
id, multiplier = hash[:button], hash[:multiplier]
level, runes, experience = hash[:level], hash[:runes], hash[:experience]
animation = Animation.new(hash[:animation])
graphic = Graphic.new(hash[:graphic], 0, GRAPHIC_HEIGHT)
ALCHEMY_SPELLS[id] = AlchemySpell.new(level, runes, experience, animation, graphic, multiplier)
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
alchemy :low_level, button: 1_162, level: 21, runes: { FIRE => 3, NATURE => 1 }, animation: 712,
graphic: 112, multiplier: 0.48, experience: 31
alchemy :high_level, button: 1_178, level: 55, runes: { FIRE => 5, NATURE => 1 }, animation: 713,
graphic: 113, multiplier: 0.72, experience: 65
+24 -22
View File
@@ -3,6 +3,7 @@ require 'java'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.Graphic'
java_import 'org.apollo.game.model.Item'
java_import 'org.apollo.game.model.entity.Skill'
CONVERT_SPELLS = {}
BONES_ID = 526
@@ -10,21 +11,23 @@ BONES_ID = 526
CONVERT_ANIM = Animation.new(722)
CONVERT_GRAPHIC = Graphic.new(141, 0, 100)
# A `Spell` for converting items.
class ConvertSpell < Spell
attr_reader :reward
def initialize(level, elements, experience, reward)
super(level, elements, experience)
super(level, elements, experience)
@reward = Item.new(reward)
end
end
# A `SpellAction` for a `ConvertSpell`.
class ConvertingAction < SpellAction
attr_reader :slots
def initialize(player, spell, slots)
super(player, spell)
super(player, spell)
@slots = slots
end
@@ -32,27 +35,25 @@ class ConvertingAction < SpellAction
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
inventory.stop_firing_events unless firing # In case of many changes, wait with firing events
reward = @spell.reward
@slots.each do |slot|
inventory.set(slot, reward) # Share the instance
end
@slots.each { |slot| inventory.set(slot, reward) }
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)
mob.skill_set.add_experience(Skill::MAGIC, @spell.experience)
set_delay(2)
elsif @pulses == 1
mob.stop_animation
mob.stop_graphic
mob.stop_graphic
stop
end
end
@@ -63,24 +64,25 @@ 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)
slots << slot if !item.nil? && item.id == BONES_ID
counter += 1
end
return slots
slots
end
def append_convert(button, level, elements, experience, reward)
def 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
convert 1159, 15, { EARTH => 2, WATER => 2, NATURE => 1 }, 25, 1963 # Bones to bananas
# convert 15877, 60, { NATURE => 2, WATER => 4, EARTH => 4 }, 35.5, 6883 # Bones to peaches
+35 -40
View File
@@ -29,36 +29,35 @@ MUD_RUNE = 4698
STEAM_RUNE = 4694
LAVA_RUNE = 4699
# An element of a spell.
class Element
attr_reader :runes, :staffs, :name
def initialize(runes, staffs, name="Null")
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
unless @staffs.nil? || weapon.nil?
@staffs.each { |staff| return true if weapon.id == staff }
end
inventory = player.inventory
found = {}
counter = 0
inventory.items.each do |item|
break unless counter < amount
next if item == nil
next if item.nil?
amt = item.amount
@runes.each do |rune|
break unless counter < amount
id = item.id
if id == rune
if amt >= amount
@@ -71,42 +70,38 @@ class Element
end
end
end
if counter >= amount
if remove
found.each do |id, amt|
inventory.remove(id, amt)
end
end
found.each { |id, amt| inventory.remove(id, amt) } if remove
return true
end
return false
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_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_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")
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")
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")
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')
+29 -31
View File
@@ -8,7 +8,7 @@ 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...
RING_ANIM = Animation.new(713) # TODO: an alchemy animation for enchanting?
LOW_NECK_GFX = Graphic.new(114, 0, 100)
LOW_NECK_ANIM = Animation.new(719)
@@ -21,11 +21,12 @@ HIGH_NECK_ANIM = Animation.new(721)
ONYX_NECK_GFX = Graphic.new(452, 0, 100)
# A `Spell` for enchanting an item.
class EnchantSpell < Spell
attr_reader :button, :animation, :graphic, :delay
def initialize(button, level, elements, animation, graphic, delay, experience)
super(level, elements, experience)
super(level, elements, experience)
@button = button
@animation = animation
@graphic = graphic
@@ -34,38 +35,39 @@ class EnchantSpell < Spell
end
# A `SpellAction` for an `EnchantSpell`.
class EnchantAction < ItemSpellAction
attr_reader :reward
def initialize(player, enchant, slot, item, reward)
super(player, enchant, slot, item)
super(player, enchant, slot, item)
@reward = Item.new(reward)
end
def illegal_item?
return ENCHANT_ITEMS[@item.id] == nil
ENCHANT_ITEMS[@item.id].nil?
end
def execute_action
def executeAction
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
mob.stop_graphic
stop
end
end
end
def append_enchant(button, level, elements, item, animation, graphic, delay, experience, reward)
def 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
@@ -79,31 +81,27 @@ 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
enchant 1155, 7, SAPPHIRE_ELEMENTS, 1637, RING_ANIM, RING_GFX, 2, 17.5, 2550 # Ring
enchant 1155, 7, SAPPHIRE_ELEMENTS, 1656, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 17.5, 3853 # Necklace
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
enchant 1165, 27, EMERALD_ELEMENTS, 1639, RING_ANIM, RING_GFX, 2, 37, 2552 # Ring
enchant 1165, 27, EMERALD_ELEMENTS, 1658, LOW_NECK_ANIM, LOW_NECK_GFX, 1, 37, 5521 # Necklace
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
enchant 1176, 49, RUBY_ELEMENTS, 1641, RING_ANIM, RING_GFX, 2, 59, 2568 # Ring
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
enchant 1180, 57, DIAMOND_ELEMENTS, 1643, RING_ANIM, RING_GFX, 2, 67, 2570 # Ring
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
enchant 1187, 68, DSTONE_ELEMENTS, 1645, RING_ANIM, RING_GFX, 2, 78, 2572 # Ring
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
enchant 6003, 87, ONYX_ELEMENTS, 6575, RING_ANIM, RING_GFX, 2, 97, 6583 # Ring
enchant 6003, 87, ONYX_ELEMENTS, 6581, HIGH_NECK_ANIM, ONYX_NECK_GFX, 2, 97, 6585 # Amulet
+38 -29
View File
@@ -5,11 +5,13 @@ java_import 'org.apollo.game.message.impl.DisplayTabInterfaceMessage'
java_import 'org.apollo.game.model.entity.EquipmentConstants'
java_import 'org.apollo.game.model.entity.Skill'
# A `Message` to display the magic spellbook.
DISPLAY_SPELLBOOK = DisplayTabInterfaceMessage.new(6)
# A spell that can be cast.
class Spell
attr_reader :level, :elements, :experience
def initialize(level, elements, experience)
@level = level
@elements = elements
@@ -18,71 +20,72 @@ class Spell
end
# An `Action` for casting a `Spell`.
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)
unless check_skill && 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(Skill::MAGIC).maximum_level
mob.send_message("You need a Magic level of at least #{required} to cast this spell.")
return false
end
return true
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 { |element, amount| element.check_remove(mob, amount, true) }
return true
true
end
def equals(other)
return (get_class == other.get_class and @spell == other.spell)
get_class == other.get_class && @spell == other.spell
end
end
# A `SpellAction` that verifies an input `Item` is legal.
class ItemSpellAction < SpellAction
attr_reader :slot, :item
def initialize(mob, spell, slot, item)
super(mob, spell)
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
@@ -91,9 +94,9 @@ class ItemSpellAction < SpellAction
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|
@@ -106,13 +109,13 @@ class ItemSpellAction < SpellAction
end
end
super
end
def illegal_item?
# Override this method if necessary
return false
false
end
end
@@ -120,7 +123,7 @@ end
# Intercepts the magic on item message.
on :message, :magic_on_item do |player, message|
spell = message.spell_id
alch = ALCHEMY_SPELLS[spell]
unless alch.nil?
slot = message.slot
@@ -129,9 +132,9 @@ on :message, :magic_on_item do |player, message|
message.terminate
return
end
ench = ENCHANT_SPELLS[message.id]
if !ench.nil? and ench.button == spell
if !ench.nil? && ench.button == spell
slot = message.slot
item = player.inventory.get(slot)
player.start_action(EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id]))
@@ -149,12 +152,18 @@ on :message, :button do |player, message|
message.terminate
return
end
conv = CONVERT_SPELLS[button]
unless conv.nil?
slots = bone_slots player
slots = bone_slots(player)
if slots.length == 0
player.send_message("You can't convert these bones!")
else
player.start_action(ConvertingAction.new(player, conv, slots))
end
if slots.length == 0 then player.send_message("You can't convert these bones!") else player.start_action(ConvertingAction.new(player, conv, slots)) end
message.terminate
end
end
end
+38 -28
View File
@@ -1,10 +1,12 @@
# Thanks to phl0w <http://www.rune-server.org/members/phl0w/> for providing
# 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'
java_import 'org.apollo.game.model.entity.Skill'
TELEPORT_SPELLS = {}
@@ -16,9 +18,10 @@ ANCIENT_TELE_END_GRAPHIC = Graphic.new(455)
ANCIENT_TELE_ANIM = Animation.new(1979)
ANCIENT_TELE_GRAPHIC = Graphic.new(392)
# A `Spell` that teleports a `Player` to another `Position`.
class TeleportSpell < Spell
attr_reader :ancient, :destination, :experience, :name
def initialize(ancient, level, elements, destination, experience, name)
super(level, elements, experience)
@ancient = ancient
@@ -28,67 +31,74 @@ class TeleportSpell < Spell
end
# A `SpellAction` for a `TeleportSpell`.
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
set_delay(1)
elsif @pulses == 2
mob.stop_graphic
mob.play_animation(MODERN_TELE_END_ANIM)
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
set_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)
mob.skill_set.add_experience(Skill::MAGIC, @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)
def tele(ancient = false, button, level, elements, x, y, experience, name)
position = Position.new(x, y)
TELEPORT_SPELLS[button] = TeleportSpell.new(ancient, level, elements, position, experience, name)
end
def ancient_tele(*args)
tele(true, *args)
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")
tele 1_164, 25, { FIRE => 1, AIR => 3, LAW => 1 }, 3213, 3424, 35, 'Varrock'
tele 1_167, 31, { EARTH => 1, AIR => 3, LAW => 1 }, 3222, 3219, 41, 'Lumbridge'
tele 1_170, 37, { WATER => 1, AIR => 3, LAW => 1 }, 2965, 3379, 47, 'Falador'
tele 1_174, 45, { AIR => 5, LAW => 1 }, 2757, 3478, 55.5, 'Camelot'
tele 1_540, 51, { WATER => 2, LAW => 2 }, 2662, 3306, 61, 'Ardougne'
tele 1_541, 58, { EARTH => 2, LAW => 2 }, 2549, 3114, 68, 'the Watchtower'
tele 7_455, 61, { FIRE => 2, LAW => 2 }, 2871, 3590, 68, 'Trollheim'
tele 18_470, 64, { FIRE => 2, WATER => 2, LAW => 2, Element.new([1963], nil, 'Banana') => 1 },
2_754, 2_785, 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")
ancient_tele 13_035, 54, { LAW => 2, FIRE => 1, AIR => 1 }, 3098, 9882, 64, 'Paddewwa'
ancient_tele 13_045, 60, { LAW => 2, SOUL => 2 }, 3320, 3338, 70, 'Senntisten'
ancient_tele 13_053, 66, { LAW => 2, BLOOD => 1 }, 3493, 3472, 76, 'Kharyll'
ancient_tele 13_061, 72, { LAW => 2, WATER => 4 }, 3003, 3470, 82, 'Lassar'
ancient_tele 13_069, 78, { LAW => 2, FIRE => 3, AIR => 2 }, 2966, 3_696, 88, 'Dareeyak'
ancient_tele 13_079, 84, { LAW => 2, SOUL => 2 }, 3163, 3664, 94, 'Carrallangar'
ancient_tele 13_087, 90, { LAW => 2, BLOOD => 2 }, 3287, 3883, 100, 'Annakarl'
ancient_tele 13_095, 96, { LAW => 2, WATER => 8 }, 2972, 3873, 106, 'Ghorrock'
+6 -5
View File
@@ -1,5 +1,6 @@
GEMSTONES = {}
# A gemstone that can be received when mining.
class Gemstone
attr_reader :id, :chance
@@ -9,11 +10,11 @@ class Gemstone
end
end
def append_gem(gem)
def 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
gem(Gemstone.new(1623, 0)) # uncut sapphire
gem(Gemstone.new(1605, 0)) # uncut emerald
gem(Gemstone.new(1619, 0)) # uncut ruby
gem(Gemstone.new(1617, 0)) # uncut diamond
+25 -21
View File
@@ -8,6 +8,7 @@ PROSPECT_PULSES = 3
ORE_SIZE = 1
# TODO: finish implementing this
# A `DistancedAction` for mining ore.
class MiningAction < DistancedAction
attr_reader :position, :ore, :counter, :started
@@ -21,9 +22,11 @@ class MiningAction < DistancedAction
def find_pickaxe
weapon = mob.equipment.get(EquipmentConstants::WEAPON)
PICKAXE_IDS.each { |id| return PICKAXES[id] if (!weapon.nil? && weapon.id == id) || mob.inventory.contains(id) }
PICKAXE_IDS.each do |id|
return PICKAXES[id] if (!weapon.nil? && weapon.id == id) || mob.inventory.contains(id)
end
return nil
nil
end
# starts the mining animation, sets counters/flags and turns the mob to
@@ -42,7 +45,7 @@ class MiningAction < DistancedAction
mob.turn_to(@position)
# verify the mob can mine with their pickaxe
unless (!pickaxe.nil? and level >= pickaxe.level)
if pickaxe.nil? || level < pickaxe.level
mob.send_message('You do not have a pickaxe for which you have the level to use.')
stop
return
@@ -56,9 +59,7 @@ class MiningAction < DistancedAction
end
# check if we need to kick start things
unless @started
start_mine(pickaxe)
else
if @started
# 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
@@ -73,16 +74,20 @@ class MiningAction < DistancedAction
stop
end
@counter -= 1
end
@counter -= 1
else
start_mine(pickaxe)
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position and @ore == other.ore)
get_class == other.get_class && @position == other.position && @ore == other.ore
end
end
# A `DistancedAction` for a rock with no available ore.
class ExpiredProspectingAction < DistancedAction
attr_reader :position
@@ -96,11 +101,12 @@ class ExpiredProspectingAction < DistancedAction
end
def equals(other)
return (get_class == other.get_class and @position == other.position)
get_class == other.get_class && @position == other.position
end
end
# A `DistancedAction` for prospecting a rock.
class ProspectingAction < DistancedAction
attr_reader :position, :ore
@@ -112,22 +118,22 @@ class ProspectingAction < DistancedAction
end
def executeAction
unless @started
@started = true
mob.send_message('You examine the rock for ores...')
mob.turn_to(@position)
else
if @started
ore_def = ItemDefinition.lookup(@ore.id)
name = ore_def.name.sub(/ ore$/, '').downcase
mob.send_message("This rock contains #{name}.")
stop
else
@started = true
mob.send_message('You examine the rock for ores...')
mob.turn_to(@position)
end
end
def equals(other)
return (get_class == other.get_class and @position == other.position and @ore == other.ore)
get_class == other.get_class && @position == other.position && @ore == other.ore
end
end
@@ -135,9 +141,7 @@ end
on :message, :first_object_action do |mob, message|
ore = ORES[message.id]
unless ore.nil?
mob.start_action(MiningAction.new(mob, message.position, ore))
end
mob.start_action(MiningAction.new(mob, message.position, ore)) unless ore.nil?
end
on :message, :second_object_action do |mob, message|
@@ -148,4 +152,4 @@ on :message, :second_object_action do |mob, message|
elsif !EXPIRED_ORES[message.id].nil?
mob.start_action(ExpiredProspectingAction.new(mob, message.position))
end
end
end
+35 -36
View File
@@ -7,6 +7,7 @@
ORES = {}
EXPIRED_ORES = {}
# An ore that can be mined.
class Ore
attr_reader :id, :objects, :level, :exp, :respawn
@@ -27,70 +28,68 @@ def append_ore(ore)
end
CLAY_OBJECTS = {
2180 => 450 , 2109 => 451 , 14904 => 14896, 14905 => 14897
2180 => 450, 2109 => 451, 14_904 => 14_896, 14_905 => 14_897
}
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
11_960 => 11_555, 11_961 => 11_556, 11_962 => 11_557, 11_936 => 11_552,
11_937 => 11_553, 11_938 => 11_554, 2090 => 450, 2091 => 451,
14_906 => 14_898, 14_907 => 14_899, 14_856 => 14_832, 14_857 => 14_833,
14_858 => 14_834
}
TIN_OBJECTS = {
11597 => 11555, 11958 => 11556, 11959 => 11557, 11933 => 11552,
11934 => 11553, 11935 => 11554, 2094 => 450 , 2095 => 451 ,
14092 => 14894, 14903 => 14895
11_597 => 11_555, 11_958 => 11_556, 11_959 => 11_557, 11_933 => 11_552,
11_934 => 11_553, 11_935 => 11_554, 2094 => 450, 2095 => 451,
14_092 => 14_894, 14_903 => 14_895
}
IRON_OBJECTS = {
11954 => 11555, 11955 => 11556, 11956 => 11557, 2092 => 450 ,
2093 => 451 , 14900 => 14892, 14901 => 14893, 14913 => 14915,
14914 => 14916
11_954 => 11_555, 11_955 => 11_556, 11_956 => 11_557, 2092 => 450,
2093 => 451, 14_900 => 14_892, 14_901 => 14_893, 14_913 => 14_915,
14_914 => 14_916
}
COAL_OBJECTS = {
11963 => 11555, 11964 => 11556, 11965 => 11557, 11930 => 11552,
11931 => 11553, 11932 => 11554, 2096 => 450 , 2097 => 451 ,
14850 => 14832, 14851 => 14833, 14852 => 14834
11_963 => 11_555, 11_964 => 11_556, 11_965 => 11_557, 11_930 => 11_552,
11_931 => 11_553, 11_932 => 11_554, 2096 => 450, 2097 => 451,
14_850 => 14_832, 14_851 => 14_833, 14_852 => 14_834
}
SILVER_OBJECTS = {
11948 => 11555, 11949 => 11556, 11950 => 11557, 2100 => 450 ,
2101 => 451
11_948 => 11_555, 11_949 => 11_556, 11_950 => 11_557, 2100 => 450, 2101 => 451
}
GOLD_OBJECTS = {
11951 => 11555, 11952 => 11556, 11953 => 11557, 2098 => 450 ,
2099 => 451
11_951 => 11_555, 11_952 => 11_556, 11_953 => 11_557, 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
11_945 => 11_555, 11_946 => 11_556, 11_947 => 11_557, 11_942 => 11_552,
11_943 => 11_553, 11_944 => 11_554, 2102 => 450, 2103 => 451,
14_853 => 14_832, 14_854 => 14_833, 14_855 => 14_834
}
ADAMANT_OBJECTS = {
11939 => 11552, 11940 => 11553, 11941 => 11554, 2104 => 450 ,
2105 => 451 , 14862 => 14832, 14863 => 14833, 14864 => 14834
11_939 => 11_552, 11_940 => 11_553, 11_941 => 11_554, 2104 => 450,
2105 => 451, 14_862 => 14_832, 14_863 => 14_833, 14_864 => 14_834
}
RUNITE_OBJECTS = {
2106 => 450 , 2107 => 451 , 14859 => 14832, 14860 => 14833,
14861 => 14834
2106 => 450, 2107 => 451, 14_859 => 14_832, 14_860 => 14_833,
14_861 => 14_834
}
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
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
# level 1, exp 5, rune ess = 1436, pure ess = 7936
+2 -1
View File
@@ -5,6 +5,7 @@ java_import 'org.apollo.game.model.Animation'
PICKAXES = {}
PICKAXE_IDS = []
# A pickaxe that can be mined with.
class Pickaxe
attr_reader :id, :level, :animation, :pulses
@@ -29,4 +30,4 @@ 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!
PICKAXE_IDS.reverse!
+1 -1
View File
@@ -13,4 +13,4 @@
# pulses down where appropriate.
def respawn_pulses(base, players)
base - players * base / ($world.player_repository.size * 2)
end
end
+32 -29
View File
@@ -4,12 +4,12 @@ java_import 'org.apollo.game.action.Action'
java_import 'org.apollo.game.model.Animation'
java_import 'org.apollo.game.model.entity.Skill'
BURY_BONE_ANIMATION = 827
BURY_BONE_ANIMATION = Animation.new(827)
BONES = {}
# A bone with an id and experience value.
class Bone
attr_reader :id, :experience
attr_reader :id, :experience
def initialize(id, experience)
@id = id
@@ -18,42 +18,45 @@ class Bone
end
# An action where a bone in a player's inventory is buried.
class BuryBoneAction < Action
attr_reader :slot, :bone
def initialize(mob, slot, bone)
super(1, true, mob)
@slot = slot
@bone = bone
@executions = 0
end
def execute
if @executions == 0
mob.send_message('You dig a hole in the ground...')
@executions += 1
elsif @executions == 1
if mob.inventory.get(@slot).id == @bone.id
mob.play_animation(Animation.new(BURY_BONE_ANIMATION))
mob.play_animation(BURY_BONE_ANIMATION)
mob.send_message('You bury the bones.')
mob.inventory.reset(@slot)
mob.skill_set.add_experience(Skill::PRAYER, @bone.experience)
end
stop
end
end
def equals(other)
return (get_class == other.get_class and @bone == other.bone)
get_class == other.get_class && @bone == other.bone
end
end
# Intercepts the first item option message.
on :message, :first_item_option do |player, message|
bone = BONES[message.id]
unless bone == nil
unless bone.nil?
player.start_action(BuryBoneAction.new(player, message.slot, bone))
message.terminate
end
@@ -61,28 +64,28 @@ 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)
fail 'Hash must contain an id and an experience value.' unless hash.has_keys?(:id, :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
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
+53 -54
View File
@@ -4,86 +4,85 @@ java_import 'org.apollo.game.message.impl.ConfigMessage'
# Declares the active prayer attribute.
declare_attribute(:active_prayer, -1, :persistent)
# The hash of button ids to prayers.
PRAYERS = {}
# Intercept the ButtonMessage to toggle a prayer.
on :message, :button do |player, message|
button = message.widget_id
prayer = PRAYERS[button]
button = message.widget_id
prayer = PRAYERS[button]
unless prayer.nil?
if (prayer.level > player.skill_set.get_maximum_level(Skill::PRAYER))
update_setting(player, prayer, :off)
next
end
player.send_message("after level check")
previous = player.active_prayer
unless previous == -1
update_setting(player, PRAYERS[previous], :off)
end
if previous != button
player.send_message("Previous: #{previous}, new: #{button}.")
update_setting(player, prayer, :on)
player.active_prayer = button
end
unless prayer.nil?
if prayer.level > player.skill_set.get_maximum_level(Skill::PRAYER)
update_setting(player, prayer, :off)
next
end
player.send_message('after level check')
previous = player.active_prayer
update_setting(player, PRAYERS[previous], :off) unless previous == -1
if previous != button
player.send_message("Previous: #{previous}, new: #{button}.")
update_setting(player, prayer, :on)
player.active_prayer = button
end
end
end
private
# A Prayer that can be activated by a player.
class Prayer
attr_reader :name, :level, :button, :setting, :drain
attr_reader :name, :level, :button, :setting, :drain
def initialize(name, level, button, setting, drain)
@name = name
@level = level
@button = button
@setting = setting
@drain = drain
end
def initialize(name, level, button, setting, drain)
@name = name
@level = level
@button = button
@setting = setting
@drain = drain
end
end
def update_setting(player, prayer, state)
value = (state == :on) ? 1 : 0
player.send_message("Toggling prayer #{prayer.name}, state: #{state}.")
player.send(ConfigMessage.new(prayer.setting, value))
value = (state == :on) ? 1 : 0
player.send_message("Toggling prayer #{prayer.name}, state: #{state}.")
player.send(ConfigMessage.new(prayer.setting, value))
end
# Appends a Prayer to the hash.
def append_prayer(properties)
raise 'Error: prayer properties hash must contain a name, level, button, setting, and drain.' unless properties.has_keys?(:name, :level, :button, :setting, :drain)
def append_prayer(name, hash)
unless hash.has_keys?(:level, :button, :setting, :drain)
fail 'Error: prayer hash hash must contain a level, button, setting, and drain.'
end
button = properties[:button]
PRAYERS[button] = Prayer.new(properties[:name], properties[:level], button, properties[:setting], properties[:drain])
button = hash[:button]
PRAYERS[button] = Prayer.new(name, hash[:level], button, hash[:setting], hash[:drain])
end
# Don't deal with the actual effect here to avoid mess (TODO do it, but with attributes?).
append_prayer name: :thick_skin, level: 1, button: 5609, setting: 83, drain: 0.01
append_prayer name: :burst_of_strength, level: 4, button: 5610, setting: 84, drain: 0.01
append_prayer name: :clarity_of_thought, level: 7, button: 5611, setting: 85, drain: 0.01
append_prayer name: :rock_skin, level: 10, button: 5612, setting: 86, drain: 0.04
append_prayer name: :superhuman_strength, level: 13, button: 5613, setting: 87, drain: 0.04
append_prayer name: :improved_reflexes, level: 16, button: 5614, setting: 88, drain: 0.04
append_prayer :thick_skin, level: 1, button: 5609, setting: 83, drain: 0.01
append_prayer :burst_of_strength, level: 4, button: 5610, setting: 84, drain: 0.01
append_prayer :clarity_of_thought, level: 7, button: 5611, setting: 85, drain: 0.01
append_prayer :rock_skin, level: 10, button: 5612, setting: 86, drain: 0.04
append_prayer :superhuman_strength, level: 13, button: 5613, setting: 87, drain: 0.04
append_prayer :improved_reflexes, level: 16, button: 5614, setting: 88, drain: 0.04
append_prayer name: :rapid_restore, level: 19, button: 5615, setting: 89, drain: 0.01
append_prayer name: :rapid_heal, level: 22, button: 5615, setting: 90, drain: 0.01
append_prayer name: :protect_item, level: 25, button: 5617, setting: 91, drain: 0.01
append_prayer :rapid_restore, level: 19, button: 5615, setting: 89, drain: 0.01
append_prayer :rapid_heal, level: 22, button: 5615, setting: 90, drain: 0.01
append_prayer :protect_item, level: 25, button: 5617, setting: 91, drain: 0.01
append_prayer name: :steel_skin, level: 28, button: 5618, setting: 92, drain: 0.1
append_prayer name: :ultimate_strength, level: 31, button: 5619, setting: 93, drain: 0.1
append_prayer name: :incredible_reflexes, level: 34, button: 5620, setting: 94, drain: 0.1
append_prayer :steel_skin, level: 28, button: 5618, setting: 92, drain: 0.1
append_prayer :ultimate_strength, level: 31, button: 5619, setting: 93, drain: 0.1
append_prayer :incredible_reflexes, level: 34, button: 5620, setting: 94, drain: 0.1
append_prayer name: :protect_from_magic, level: 37, button: 5621, setting: 95, drain: 0.15
append_prayer name: :protect_from_missiles, level: 40, button: 5622, setting: 96, drain: 0.15
append_prayer name: :protect_from_melee, level: 43, button: 5633, setting: 97, drain: 0.15
append_prayer :protect_from_magic, level: 37, button: 5621, setting: 95, drain: 0.15
append_prayer :protect_from_missiles, level: 40, button: 5622, setting: 96, drain: 0.15
append_prayer :protect_from_melee, level: 43, button: 5633, setting: 97, drain: 0.15
append_prayer name: :retribution, level: 46, button: 683, setting: 98, drain: 0.15
append_prayer name: :redemption, level: 49, button: 684, setting: 99, drain: 0.15
append_prayer name: :smite, level: 52, button: 685, setting: 100, drain: 0.2
append_prayer :retribution, level: 46, button: 683, setting: 98, drain: 0.15
append_prayer :redemption, level: 49, button: 684, setting: 99, drain: 0.15
append_prayer :smite, level: 52, button: 685, setting: 100, drain: 0.2
+68 -30
View File
@@ -9,11 +9,12 @@ CRAFTING_ALTARS = {}
# Represents a runecrafting altar.
class Altar
attr_reader :entrance_altar, :crafting_altar, :portal_id, :entrance_position, :exit_position, :crafting_centre
attr_reader :entrance_altar, :crafting, :portal_id, :entrance, :exit, :crafting_centre
def initialize(entrance_altar, crafting_altar, portal_id, entrance_position, exit_position,crafting_centre)
def initialize(entrance_altar, crafting, portal_id, entrance_position, exit_position,
crafting_centre)
@entrance_altar = entrance_altar
@altar = crafting_altar
@altar = crafting
@portal_id = portal_id
@entrance_position = entrance_position
@exit_position = exit_position
@@ -22,11 +23,12 @@ class Altar
end
# Intercepts the item on object message.
on :message, :item_on_object do |player, message|
talisman = TALISMANS[message.id]; altar = ENTRANCE_ALTARS[message.object_id]
unless (talisman.nil? || altar.nil?)
talisman = TALISMANS[message.id]
altar = ENTRANCE_ALTARS[message.object_id]
unless talisman.nil? || altar.nil?
player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position))
message.terminate
end
@@ -34,22 +36,27 @@ end
# Intercepts the first object action message.
on :message, :object_action do |player, message|
if (message.option == 1)
if message.option == 1
object_id = message.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))
if PORTALS.key?(object_id)
altar = PORTALS[object_id]
entrance = altar.entrance_position
player.start_action(TeleportAction.new(player, entrance, 1, altar.exit_position))
message.terminate
elsif (rune = RUNES[object_id]) != nil # Get the rune associated with this altar.
elsif RUNES.key?(object_id)
rune = RUNES[object_id]
altar = CRAFTING_ALTARS[object_id]
player.start_action(RunecraftingAction.new(player, rune, altar.crafting_centre))
message.terminate
end
end
end
# An action that causes a mob to teleport when it comes within the specified distance of a specified position.
# 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
@@ -64,28 +71,59 @@ class TeleportAction < DistancedAction
end
def equals(other)
return (get_class == other.get_class && mob == other.mob && @teleport_position == other.teleport_position)
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]
def altar(name, hash)
unless hash.has_keys?(:entrance_altar, :crafting, :portal, :entrance, :exit, :altar_centre)
fail "#{name} is missing one of: entrance altar id, crafting altar id, entrance portal position, "\
"and altar centre position."
end
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))
entrance_altar, crafting = hash[:entrance_altar], hash[:crafting]
portal_id = hash[:portal]
entrance = Position.new(*hash[:entrance])
exit_position = Position.new(*hash[:exit])
centre = Position.new(*hash[:altar_centre])
altar = Altar.new(entrance_altar, crafting, portal_id, entrance, exit_position, centre)
PORTALS[portal_id] = ENTRANCE_ALTARS[entrance_altar] = CRAFTING_ALTARS[crafting] = altar
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 ]
altar :air, entrance_altar: 2452, crafting: 2478, portal: 2465,
entrance: [2841, 4829], exit: [2983, 3292], altar_centre: [2844, 4834]
altar :mind, entrance_altar: 2453, crafting: 2479, portal: 2466,
entrance: [2793, 4828], exit: [2980, 3514], altar_centre: [2786, 4841]
altar :water, entrance_altar: 2454, crafting: 2480, portal: 2467,
entrance: [2726, 4832], exit: [3187, 3166], altar_centre: [2716, 4836]
altar :earth, entrance_altar: 2455, crafting: 2481, portal: 2468,
entrance: [2655, 4830], exit: [3304, 3474], altar_centre: [2658, 4841]
altar :fire, entrance_altar: 2456, crafting: 2482, portal: 2469,
entrance: [2574, 4849], exit: [3311, 3256], altar_centre: [2585, 4838]
altar :body, entrance_altar: 2457, crafting: 2483, portal: 2470,
entrance: [2524, 4825], exit: [3051, 3445], altar_centre: [2525, 4832]
altar :cosmic, entrance_altar: 2458, crafting: 2484, portal: 2471,
entrance: [2142, 4813], exit: [2408, 4379], altar_centre: [2142, 4833]
altar :law, entrance_altar: 2459, crafting: 2485, portal: 2472,
entrance: [2464, 4818], exit: [2858, 3379], altar_centre: [2464, 4832]
altar :nature, entrance_altar: 2460, crafting: 2486, portal: 2473,
entrance: [2400, 4835], exit: [2867, 3019], altar_centre: [2400, 4841]
altar :chaos, entrance_altar: 2461, crafting: 2487, portal: 2474,
entrance: [2268, 4842], exit: [3058, 3591], altar_centre: [2271, 4842]
altar :death, entrance_altar: 2462, crafting: 2488, portal: 2475,
entrance: [2208, 4830], exit: [3222, 3222], altar_centre: [2205, 4836]
+27 -21
View File
@@ -6,7 +6,7 @@ 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 = name_of(:item, id)
@@ -15,32 +15,38 @@ class Rune
@multiplier = multiplier
end
def multiplier(level)
return @multiplier.call(level)
def equals(other)
get_class == other.get_class && id == other.id
end
def equals(other)
return (get_class == other.get_class && id == other.id)
def multiplier(level)
@multiplier.call(level)
end
end
# Appends a rune to the list.
def append_rune(hash)
raise 'Hash must contain an id, level, experience, and multiplier.' unless hash.has_keys?(:id, :level, :experience, :multiplier)
id = hash[:id]; altar = hash[:altar]; level = hash[:level]; experience = hash[:experience]; multiplier = hash[:multiplier]
RUNES[altar] = Rune.new(id, level, experience, multiplier)
def rune(name, hash)
unless hash.has_keys?(:altar, :id, :level, :reward)
fail "#{name} is missing one of id, altar, level, or reward."
end
id, altar, level, experience = hash[:id], hash[:altar], hash[:level], hash[:reward]
bonus = hash[:bonus] || ->(_) { 1 }
RUNES[altar] = Rune.new(id, level, experience, bonus)
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 })
rune :air, altar: 2478, id: 556, level: 1, reward: 5, bonus: ->(level) { (level / 11).floor + 1 }
rune :mind, altar: 2479, id: 558, level: 1, reward: 5.5, bonus: ->(level) { (level / 14).floor + 1 }
rune :water, altar: 2480, id: 555, level: 5, reward: 6, bonus: ->(level) { (level / 19).floor + 1 }
rune :earth, altar: 2481, id: 557, level: 9, reward: 6.5,
bonus: ->(level) { (level / 26).floor + 1 }
rune :fire, altar: 2482, id: 554, level: 14, reward: 7, bonus: ->(level) { (level / 35).floor + 1 }
rune :body, altar: 2483, id: 559, level: 20, reward: 7.5,
bonus: ->(level) { (level / 46).floor + 1 }
rune :cosmic, altar: 2484, id: 564, level: 27, reward: 8, bonus: ->(level) { level >= 59 ? 2 : 1 }
rune :chaos, altar: 2487, id: 562, level: 35, reward: 8.5, bonus: ->(level) { level >= 74 ? 2 : 1 }
rune :nature, altar: 2486, id: 561, level: 44, reward: 9, bonus: ->(level) { level >= 91 ? 2 : 1 }
rune :law, altar: 2485, id: 563, level: 54, reward: 9.5
rune :death, altar: 2488, id: 560, level: 65, reward: 10
+12 -8
View File
@@ -25,11 +25,11 @@ class RunecraftingAction < DistancedAction
def executeAction
runecrafting_level = @player.skill_set.get_skill(Skill::RUNECRAFT).current_level
if (runecrafting_level < @rune.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.')
@player.send_message('You need rune essence to craft runes.')
stop
elsif @executions == 0
@player.turn_to(@position)
@@ -37,18 +37,22 @@ class RunecraftingAction < DistancedAction
@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)
inventory = @player.inventory
removed = inventory.remove(RUNE_ESSENCE_ID, inventory.get_amount(RUNE_ESSENCE_ID))
added = removed * @rune.multiplier(runecrafting_level)
inventory.add(@rune.id, added)
name = added > 1 ? 'some ' + @rune.name + 's' : 'an ' + @rune.name
@player.send_message("Your craft the rune essence into #{name}.", true)
@player.send_message("Your craft the rune essence into #{added > 1 ? 'some ' + @rune.name + 's' : 'an ' + @rune.name}.", true)
@player.skill_set.add_experience(Skill::RUNECRAFT, removed * @rune.experience)
stop
end
end
def equals(other)
return (get_class == other.get_class && @player == other.player && @rune == other.rune)
get_class == other.get_class && @player == other.player && @rune == other.rune
end
end
end
+27 -25
View File
@@ -12,41 +12,43 @@ class Talisman
@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)
def get_message(position)
return 'Your talisman glows brightly.' if 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}."
direction = (position.y > @locate_position.y ? 'North' : 'South') + '-'
direction += (position.x > @locate_position.x ? 'East' : 'West')
"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 message.
on :message, :fourth_item_option do |player, message|
talisman = TALISMANS[message.id]
if (talisman != nil)
unless talisman.nil?
player.send_message(talisman.get_message(player.position))
message.terminate
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 ]
# Appends a talisman to the list.
def talisman(name, hash)
fail 'Hash must contain an id and an altar position.' unless hash.has_keys?(:id, :altar)
id, altar_position = hash[:id], Position.new(*hash[:altar])
TALISMANS[id] = Talisman.new(altar_position)
end
talisman :air_talisman, id: 1438, altar: [2985, 3292]
talisman :earth_talisman, id: 1440, altar: [3306, 3474]
talisman :fire_talisman, id: 1442, altar: [3313, 3255]
talisman :water_talisman, id: 1444, altar: [3185, 3165]
talisman :body_talisman, id: 1446, altar: [3053, 3445]
talisman :mind_talisman, id: 1448, altar: [2982, 3514]
talisman :chaos_talisman, id: 1452, altar: [3059, 3590]
talisman :cosmic_talisman, id: 1454, altar: [2408, 4377]
talisman :death_talisman, id: 1456, altar: [0, 0]
talisman :law_talisman, id: 1458, altar: [2858, 3381]
talisman :nature_talisman, id: 1462, altar: [2869, 3019]
+52 -44
View File
@@ -4,27 +4,27 @@ java_import 'org.apollo.game.message.impl.ConfigMessage'
java_import 'org.apollo.game.model.entity.EquipmentConstants'
java_import 'org.apollo.game.action.DistancedAction'
# The list of tiaras.
# The hash of tiaras.
TIARAS_BY_ALTAR = {}
TIARAS_BY_ID = {}
TIARAS_BY_TALISMAN = {}
# A tiara will make an altar accessible with 1 click
# A tiara will make an altar accessible with a single click.
class Tiara
attr_reader :altar, :bitshift, :tiara_id, :experience, :talisman
def initialize(tiara_id, altar, talisman, bitshift, experience)
@tiara_id = tiara_id
@name = name_of(:item, tiara_id)
@altar = altar
@talisman = talisman
@bitshift = bitshift
@experience = experience
@tiara_id = tiara_id
@name = name_of(:item, tiara_id)
@altar = altar
@talisman = talisman
@bitshift = bitshift
@experience = experience
end
# Sends a config message to change the altar object.
def send_config(player)
player.send(ConfigMessage.new(CHANGE_ALTAR_OBJECT_CONFIG, 1 << @bitshift))
player.send(ConfigMessage.new(CHANGE_ALTAR_OBJECT_CONFIG, 1 << @bitshift))
end
end
@@ -42,26 +42,18 @@ def send_empty_config(player)
player.send(ConfigMessage.new(CHANGE_ALTAR_OBJECT_CONFIG, 0))
end
# Appends a tiara to the list.
def append_tiara(hash)
raise 'Hash must contain a tiara id, altar id, talisman id, a bitshift number, and experience.' unless hash.has_keys?(:altar, :bitshift, :experience, :talisman, :tiara_id)
tiara_id = hash[:tiara_id]; altar = hash[:altar]; talisman = hash[:talisman]; bitshift = hash[:bitshift]; experience = hash[:experience]
TIARAS_BY_TALISMAN[talisman] = TIARAS_BY_ID[tiara_id] = TIARAS_BY_ALTAR[altar] = Tiara.new(tiara_id, altar, talisman, bitshift, experience)
end
# Sets the correct config upon login, if the player is wearing a tiara.
on :login do |event, player|
player = event.player
on :login do |_event, player|
hat = player.equipment.get(EquipmentConstants::HAT)
unless hat.nil?
tiara = TIARAS_BY_ID[hat]
if tiara.nil? then send_empty_config(player) else tiara.send_config end
tiara.nil? ? send_empty_config(player) : tiara.send_config
end
end
# Intercepts the SecondObjectAction message to support left-click access to the altar when wielding the correct tiara.
# Intercepts the SecondObjectAction message to support left-click access to the altar when wielding
# the correct tiara.
on :message, :second_object_action do |player, message|
object_id = message.id
tiara = TIARAS_BY_ALTAR[object_id]
@@ -69,11 +61,13 @@ on :message, :second_object_action do |player, message|
hat = player.equipment.get(EquipmentConstants::HAT)
if (!hat.nil? && hat.id == tiara.tiara_id)
if !hat.nil? && hat.id == tiara.tiara_id
altar = ENTRANCE_ALTARS[tiara.altar]
player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position)) unless altar.nil?
message.terminate
unless altar.nil?
player.start_action(TeleportAction.new(player, message.position, 2, altar.entrance_position))
end
end
end
@@ -99,14 +93,15 @@ end
# Intercepts the ItemOnObject message to create the tiara.
on :message, :item_on_object do |player, message|
tiara= TIARAS_BY_TALISMAN[message.id]; altar = CRAFTING_ALTARS[message.object_id]
return if (tiara.nil? || altar.nil?)
tiara, altar = TIARAS_BY_TALISMAN[message.id], CRAFTING_ALTARS[message.object_id]
return if tiara.nil? || altar.nil?
player.start_action(CreateTiaraAction.new(player, message.position, tiara, altar))
message.terminate
end
# An action lets the player create a tiara when it comes within the specified distance of a specified position.
# An action lets the player create a tiara when it comes within the specified distance of a
# specified position.
# noinspection JRubyImplementInterfaceInspection
class CreateTiaraAction < DistancedAction
@@ -122,7 +117,7 @@ class CreateTiaraAction < DistancedAction
inventory = @player.inventory
if inventory.contains_all(TIARA_ITEM_ID, @tiara.talisman)
if (@tiara.altar == @altar.entrance_altar)
if @tiara.altar == @altar.entrance_altar
inventory.remove(@tiara.talisman, TIARA_ITEM_ID)
inventory.add(@tiara.tiara_id)
@@ -130,30 +125,43 @@ class CreateTiaraAction < DistancedAction
@player.play_animation(RUNECRAFTING_ANIMATION)
@player.play_graphic(RUNECRAFTING_GRAPHIC)
else
@player.send_message("You can't use that talisman on this altar.")
@player.send_message('You can\'t use that talisman on this altar.')
end
else
@player.send_message("You need to have a talisman and blank tiara to enchant a tiara.")
@player.send_message('You need to have a talisman and blank tiara to enchant a tiara.')
end
stop
end
def equals(other)
return (get_class == other.get_class && @player == other.player && @tiara == other.tiara)
get_class == other.get_class && @player == other.player && @tiara == other.tiara
end
end
append_tiara :name => :air_tiara, :tiara_id => 5527, :altar => 2452, :talisman => 1438, :bitshift => 0, :experience => 25
append_tiara :name => :mind_tiara, :tiara_id => 5529, :altar => 2453, :talisman => 1448, :bitshift => 1, :experience => 27.5
append_tiara :name => :water_tiara, :tiara_id => 5531, :altar => 2454, :talisman => 1444, :bitshift => 2, :experience => 30
append_tiara :name => :body_tiara, :tiara_id => 5533, :altar => 2457, :talisman => 1446, :bitshift => 5, :experience => 37.5
append_tiara :name => :earth_tiara, :tiara_id => 5535, :altar => 2455, :talisman => 1440, :bitshift => 3, :experience => 32.5
append_tiara :name => :fire_tiara, :tiara_id => 5537, :altar => 2456, :talisman => 1442, :bitshift => 4, :experience => 35
append_tiara :name => :cosmic_tiara, :tiara_id => 5539, :altar => 2458, :talisman => 1454, :bitshift => 6, :experience => 40
append_tiara :name => :nature_tiara, :tiara_id => 5541, :altar => 2460, :talisman => 1462, :bitshift => 8, :experience => 45
append_tiara :name => :chaos_tiara, :tiara_id => 5543, :altar => 2461, :talisman => 1452, :bitshift => 9, :experience => 42.5
append_tiara :name => :law_tiara, :tiara_id => 5545, :altar => 2459, :talisman => 1458, :bitshift => 7, :experience => 47.5
append_tiara :name => :death_tiara, :tiara_id => 5548, :altar => 2462, :talisman => 1456, :bitshift => 10, :experience => 50
# TODO there are 2 other altars, which probably just aren't spawned on the map
# Appends a tiara to the list.
def tiara(_name, hash)
unless hash.has_keys?(:altar, :bitshift, :experience, :talisman, :tiara_id)
fail 'Hash must contain a tiara id, altar id, talisman id, a bitshift number, and experience.'
end
tiara_id, altar, talisman = hash[:tiara_id], hash[:altar], hash[:talisman]
bitshift, experience = hash[:bitshift], hash[:experience]
tiara = Tiara.new(tiara_id, altar, talisman, bitshift, experience)
TIARAS_BY_TALISMAN[talisman] = TIARAS_BY_ID[tiara_id] = TIARAS_BY_ALTAR[altar] = tiara
end
tiara :air_tiara, tiara_id: 5527, altar: 2452, talisman: 1438, bitshift: 0, experience: 25
tiara :mind_tiara, tiara_id: 5529, altar: 2453, talisman: 1448, bitshift: 1, experience: 27.5
tiara :water_tiara, tiara_id: 5531, altar: 2454, talisman: 1444, bitshift: 2, experience: 30
tiara :body_tiara, tiara_id: 5533, altar: 2457, talisman: 1446, bitshift: 5, experience: 37.5
tiara :earth_tiara, tiara_id: 5535, altar: 2455, talisman: 1440, bitshift: 3, experience: 32.5
tiara :fire_tiara, tiara_id: 5537, altar: 2456, talisman: 1442, bitshift: 4, experience: 35
tiara :cosmic_tiara, tiara_id: 5539, altar: 2458, talisman: 1454, bitshift: 6, experience: 40
tiara :nature_tiara, tiara_id: 5541, altar: 2460, talisman: 1462, bitshift: 8, experience: 45
tiara :chaos_tiara, tiara_id: 5543, altar: 2461, talisman: 1452, bitshift: 9, experience: 42.5
tiara :law_tiara, tiara_id: 5545, altar: 2459, talisman: 1458, bitshift: 7, experience: 47.5
tiara :death_tiara, tiara_id: 5548, altar: 2462, talisman: 1456, bitshift: 10, experience: 50
# TODO: there are 2 other altars, which probably just aren't spawned on the map
+18 -17
View File
@@ -4,40 +4,41 @@ java_import 'org.apollo.cache.def.ItemDefinition'
java_import 'org.apollo.cache.def.NpcDefinition'
java_import 'org.apollo.cache.def.ObjectDefinition'
# Checks whether the amount of arguments provided is correct, sending the player the specified message if not.
# Checks whether the amount of arguments provided is correct, sending the player the specified
# message if not.
def valid_arg_length(args, length, player, message)
valid = length.kind_of?(Range) ? length.include?(args.length) : length == args.length
valid = length.is_a?(Range) ? length.include?(args.length) : length == args.length
player.send_message(message) if !valid
return valid
player.send_message(message) unless valid
valid
end
# Returns the name of the Object, Npc, or Item with the specified id.
def name_of(type, id)
types = [ :object, :item, :npc ]
types = [:object, :item, :npc]
unless types.include?(type)
raise "Invalid type of #{type} specified, must be one of #{types}"
fail "Invalid type of #{type} specified, must be one of #{types}"
end
return Kernel.const_get("#{type.capitalize}Definition").lookup(id).name.to_s
Kernel.const_get("#{type.capitalize}Definition").lookup(id).name.to_s
end
# Add a has_keys? method to hash
# Monkey-patches Hash to add a has_keys? method.
class Hash
def has_keys?(*keys)
keys.each { |key| return false unless has_key?(key) }
return true
keys.all? { |key| self.key?(key) }
end
end
# Monkey-patches Player to add a hash_level? method.
class Player
# Returns whether or not the player's current level is greater than or equal to the specified level.
def has_level(skill, level)
return skill_set.get_skill(skill).current_level >= level
# Returns whether or not the player's current level is greater than or equal to the specified
# level.
def level?(skill, level)
skill_set.get_skill(skill).current_level >= level
end
end
end
-27
View File
@@ -1,27 +0,0 @@
# Essentially a wrapper for specific message types to make them easier to use. Only supports the interception of a message type once (for good reason - this is supposed to
# be a utility, not a chain of interceptors inside the existing chain).
#
# Plugins that wish to expand the list of available message types (you probably don't) should use the add_interception method - see the item-on-item script for example usage.
#
# If you only wish to intercept a message, use the intercept method, e.g.
#
# intercept :item_on_item, used_id, target_id, :irreversible do |player, message|
# # code here
# end
# Calls the registered interception(s), if applicable.
def intercept(message, *args, &block)
raise 'Error - interceptions must provide a block.' unless block_given?
interception = INTERCEPTIONS[message]
if interception == nil then raise "No interception for message #{message}" else interception.call(*args, block) end
end
# Adds an interception.
def add_interception(message, &block)
INTERCEPTIONS[message] = block
end
private
INTERCEPTIONS = {}
@@ -1,46 +0,0 @@
# Adds an interception for the ItemOnItem message
add_interception :item_on_item do |used, target, reversible, block|
interception = ItemOnItemPair.new(used, target)
ITEM_PAIRS[interception] = block
ITEM_PAIRS[interception.reverse] = block if reversible == :reversible
end
private
# A hash of ItemOnItemPairs to blocks.
ITEM_PAIRS = {}
# A pair of items that will cause a block to be executed if one (the 'used' item) is used on the other (the 'target' item).
class ItemOnItemPair
attr_reader :used, :target
def initialize(used, target)
@used = used
@target = target
end
# Returns a new ItemOnItemPair that is the reverse of this.
def reverse
return ItemOnItemPair.new(@target, @used)
end
def eql?(other)
return (other.kind_of?(ItemOnItemPair) && @used == other.used && @target == other.target)
end
def hash
return @used << 16 | @target
end
end
# Adds a message listener to the item on item message.
on :message, :item_on_item do |player, message|
used, target = message.id, message.target_id
pair = ItemOnItemPair.new(used, target)
block = ITEM_PAIRS[pair]
block.call(player, message) unless block == nil
end
@@ -2,48 +2,49 @@ require 'java'
# Looks up the id of the npc with the specified name.
def lookup_npc(name)
return lookup_entity(:npc, name)
lookup_entity(:npc, name)
end
# Looks up the id of the item with the specified name.
def lookup_item(name)
return lookup_entity(:item, name)
lookup_entity(:item, name)
end
# Looks up the id of the object with the specified name.
def lookup_object(name)
return lookup_entity(:object, name)
lookup_entity(:object, name)
end
# Looks up the id of an entity of the specified type (either :npc, :item, or :object)
def lookup_entity(type, name)
type = type.to_s
name = name.to_s.gsub('_', ' ')
cached = NAME_CACHE[type + name]
return cached unless cached.nil?
id = name[name.rindex(' ') + 1, name.length - 1].to_i if name.include?(' ')
id = find_entities(type, name, 1).first if (id.nil? || id.zero?)
raise "The #{type} called #{name} could not be identified." if id.nil?
id = find_entities(type, name, 1).first if id.nil? || id.zero?
fail "The #{type} called #{name} could not be identified." if id.nil?
NAME_CACHE[type + name] = id
return id
id
end
# Finds entities with the specified type (e.g. npc) and name, returning possible ids as an array.
def find_entities(type, name, limit=5)
def find_entities(type, name, limit = 5)
ids = []
name.downcase!
Kernel.const_get("#{type.capitalize}Definition").definitions.each do |definition|
break if (ids.length == limit)
ids << definition.id.to_i if (definition.name.to_s.downcase == name)
ids << definition.id.to_i if definition.name.to_s.downcase == name
end
return ids
ids
end
private
NAME_CACHE = {} # Primitive, caching all may not be desirable.
NAME_CACHE = {} # Primitive, caching all may not be desirable.
+2 -4
View File
@@ -9,9 +9,7 @@
</authors>
<scripts>
<script>command.rb</script>
<script>intercept.rb</script>
<script>item-on-item-intercept.rb</script>
<script>name-lookup.rb</script>
<script>name_lookup.rb</script>
</scripts>
<dependencies /> <!-- This plugin should _NOT_ depend on anything. -->
</plugin>
</plugin>