mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-03 08:39:11 +00:00
Fix bugs in the magic skill plugin.
This commit is contained in:
@@ -7,7 +7,7 @@ end
|
||||
|
||||
on :command, :tele, RIGHTS_ADMIN do |player, command|
|
||||
args = command.arguments
|
||||
unless (2..3).include? args.length
|
||||
unless (2..3).include?(args.length)
|
||||
player.send_message("Invalid syntax - ::tele [x] [y] [optional-z]")
|
||||
return
|
||||
end
|
||||
@@ -16,5 +16,5 @@ on :command, :tele, RIGHTS_ADMIN do |player, command|
|
||||
y = args[1].to_i
|
||||
z = args.length == 3 ? args[2].to_i : player.position.height
|
||||
|
||||
player.teleport Position.new(x, y, z)
|
||||
player.teleport Position.new(x, y, z) if (0..4).include?(z)
|
||||
end
|
||||
@@ -5,67 +5,66 @@ java_import 'org.apollo.game.model.Graphic'
|
||||
|
||||
ALCHEMY_SPELLS = {}
|
||||
|
||||
LOW_ALC_ANIM = Animation.new(712)
|
||||
LOW_ALC_GFX = Graphic.new(112, 0, 100)
|
||||
LOW_ALC_MULTIPLIER = 0.4
|
||||
LOW_ALCH_ANIM = Animation.new(712)
|
||||
LOW_ALCH_GRAPHIC = Graphic.new(112, 0, 100)
|
||||
LOW_ALCH_MULTIPLIER = 0.4
|
||||
|
||||
HIGH_ALC_ANIM = Animation.new(713)
|
||||
HIGH_ALC_GFX = Graphic.new(113, 0, 100)
|
||||
HIGH_ALC_MULTIPLIER = 0.6
|
||||
HIGH_ALCH_ANIM = Animation.new(713)
|
||||
HIGH_ALCH_GRAPHIC = Graphic.new(113, 0, 100)
|
||||
HIGH_ALCH_MULTIPLIER = 0.6
|
||||
|
||||
ILLEGAL_ALC_ITEMS = [ 995, 6529, 6306, 6307, 6308, 6309, 6310 ]
|
||||
ILLEGAL_ALCH_ITEMS = [ 995, 6529, 6306, 6307, 6308, 6309, 6310 ]
|
||||
|
||||
class AlchemySpell < Spell
|
||||
attr_reader :high, :animation, :graphic, :multiplier, :experience, :delay
|
||||
|
||||
def initialize(level, elements, high, animation, graphic, multiplier, experience, delay)
|
||||
super level, elements, experience
|
||||
|
||||
super(level, elements, experience)
|
||||
@high = high
|
||||
@animation = animation
|
||||
@graphic = graphic
|
||||
@multiplier = multiplier
|
||||
@delay = delay
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class AlchemyAction < ItemSpellAction
|
||||
|
||||
def initialize(player, alchemy, slot, item)
|
||||
super player, alchemy, slot, item
|
||||
super(player, alchemy, slot, item)
|
||||
end
|
||||
|
||||
def illegal_item?
|
||||
return ILLEGAL_ALC_ITEMS.include? @item.id
|
||||
return ILLEGAL_ALCH_ITEMS.include?(@item.id)
|
||||
end
|
||||
|
||||
def execute_action
|
||||
player = character
|
||||
if @pulses == 0
|
||||
player.play_animation(@spell.animation)
|
||||
player.play_graphic(@spell.graphic)
|
||||
player.send(DISPLAY_SPELLBOOK)
|
||||
mob.play_animation(@spell.animation)
|
||||
mob.play_graphic(@spell.graphic)
|
||||
mob.send(DISPLAY_SPELLBOOK)
|
||||
|
||||
inventory = player.inventory
|
||||
gold = (item.definition.value * @spell.multiplier)
|
||||
inventory = mob.inventory
|
||||
gold = (item.definition.value * @spell.multiplier) + 1
|
||||
|
||||
inventory.remove(inventory.get(@slot).id, 1)
|
||||
inventory.add(995, gold)
|
||||
|
||||
player.skill_set.add_experience(MAGIC_ID, @spell.experience)
|
||||
|
||||
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
|
||||
set_delay(@spell.delay)
|
||||
elsif @pulses == 1
|
||||
player.stop_animation
|
||||
player.stop_graphic
|
||||
mob.stop_animation
|
||||
mob.stop_graphic
|
||||
stop
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def append_alchemy(button, level, elements, high, animation, graphic, multiplier, experience, delay)
|
||||
ALCHEMY_SPELLS[button] = AlchemySpell.new(level, elements, high, animation, graphic, multiplier, experience, delay)
|
||||
end
|
||||
|
||||
append_alchemy(1162, 21, { FIRE => 3, NATURE => 1 }, false, LOW_ALC_ANIM, LOW_ALC_GFX, 0.48, 31, 1) # Low level alchemy
|
||||
append_alchemy(1178, 55, { FIRE => 5, NATURE => 1 }, true, HIGH_ALC_ANIM, HIGH_ALC_GFX, 0.72, 65, 4) # High level alchemy
|
||||
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
|
||||
@@ -8,34 +8,32 @@ CONVERT_SPELLS = {}
|
||||
BONES_ID = 526
|
||||
|
||||
CONVERT_ANIM = Animation.new(722)
|
||||
CONVERT_GFX = Graphic.new(141, 0, 100)
|
||||
CONVERT_GRAPHIC = Graphic.new(141, 0, 100)
|
||||
|
||||
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
|
||||
|
||||
class ConvertingAction < SpellAction
|
||||
attr_reader :slots
|
||||
|
||||
def initialize(player, spell, slots)
|
||||
super(player, spell)
|
||||
|
||||
super(player, spell)
|
||||
@slots = slots
|
||||
end
|
||||
|
||||
def execute_action
|
||||
player = character
|
||||
if @pulses == 0
|
||||
player.play_animation CONVERT_ANIM
|
||||
player.play_graphic CONVERT_GFX
|
||||
mob.play_animation(CONVERT_ANIM)
|
||||
mob.play_graphic(CONVERT_GRAPHIC)
|
||||
|
||||
inventory = player.inventory
|
||||
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
|
||||
@@ -50,16 +48,15 @@ class ConvertingAction < SpellAction
|
||||
inventory.force_refresh
|
||||
end
|
||||
|
||||
player.skill_set.add_experience MAGIC_ID, @spell.experience
|
||||
|
||||
set_delay 2
|
||||
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
|
||||
set_delay(2)
|
||||
elsif @pulses == 1
|
||||
player.stop_animation
|
||||
player.stop_graphic
|
||||
|
||||
mob.stop_animation
|
||||
mob.stop_graphic
|
||||
stop
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def bone_slots(player)
|
||||
@@ -73,9 +70,7 @@ def bone_slots(player)
|
||||
break unless counter <= size
|
||||
|
||||
item = items[slot]
|
||||
if item != nil and item.id == BONES_ID
|
||||
slots << slot
|
||||
end
|
||||
slots << slot if (item != nil and item.id == BONES_ID)
|
||||
|
||||
counter += 1
|
||||
end
|
||||
@@ -84,9 +79,8 @@ def bone_slots(player)
|
||||
end
|
||||
|
||||
def append_convert(button, level, elements, experience, reward)
|
||||
convert = ConvertSpell.new(level, elements, experience, reward)
|
||||
CONVERT_SPELLS[button] = convert
|
||||
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 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
|
||||
@@ -83,29 +83,30 @@ class Element
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
AIR_RUNES = [ 556, 4695, 4696, 4697 ]
|
||||
WATER_RUNES = [ 555, 4695, 4698, 4694 ]
|
||||
EARTH_RUNES = [ 557, 4696, 4697, 4698 ]
|
||||
FIRE_RUNES = [ 554, 4697, 4694, 4699 ]
|
||||
WATER_RUNES = [ 555, 4695, 4698, 4694 ]
|
||||
EARTH_RUNES = [ 557, 4696, 4697, 4698 ]
|
||||
FIRE_RUNES = [ 554, 4697, 4694, 4699 ]
|
||||
|
||||
AIR_STAFFS = [ 1381, 1397, 1405 ]
|
||||
AIR_STAFFS = [ 1381, 1397, 1405 ]
|
||||
WATER_STAFFS = [ 1383, 1395, 1403 ]
|
||||
EARTH_STAFFS = [ 1385, 1399, 1407, 3053, 3054 ]
|
||||
FIRE_STAFFS = [ 1387, 1393, 1401, 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")
|
||||
|
||||
@@ -25,21 +25,20 @@ 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
|
||||
@delay = delay
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
@@ -48,20 +47,18 @@ class EnchantAction < ItemSpellAction
|
||||
end
|
||||
|
||||
def execute_action
|
||||
player = character
|
||||
if @pulses == 0
|
||||
player.play_animation @spell.animation
|
||||
player.play_graphic @spell.graphic
|
||||
player.send DISPLAY_SPELLBOOK
|
||||
mob.play_animation(@spell.animation)
|
||||
mob.play_graphic(@spell.graphic)
|
||||
mob.send(DISPLAY_SPELLBOOK)
|
||||
|
||||
player.inventory.set @slot, @reward
|
||||
player.skill_set.add_experience MAGIC_ID, @spell.experience
|
||||
mob.inventory.set(@slot, @reward)
|
||||
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
|
||||
|
||||
set_delay @spell.delay
|
||||
set_delay(@spell.delay)
|
||||
elsif @pulses == 1
|
||||
player.stop_animation
|
||||
player.stop_graphic
|
||||
|
||||
mob.stop_animation
|
||||
mob.stop_graphic
|
||||
stop
|
||||
end
|
||||
end
|
||||
@@ -75,11 +72,11 @@ def append_enchant(button, level, elements, item, animation, graphic, delay, exp
|
||||
end
|
||||
|
||||
SAPPHIRE_ELEMENTS = { WATER => 1, COSMIC => 1 }
|
||||
EMERALD_ELEMENTS = { AIR => 1, COSMIC => 1 }
|
||||
RUBY_ELEMENTS = { FIRE => 5, COSMIC => 1 }
|
||||
DIAMOND_ELEMENTS = { EARTH => 10, COSMIC => 1 }
|
||||
DSTONE_ELEMENTS = { WATER => 15, EARTH => 15, COSMIC => 1 }
|
||||
ONYX_ELEMENTS = { EARTH => 20, FIRE => 20, COSMIC => 1 }
|
||||
EMERALD_ELEMENTS = { AIR => 1, COSMIC => 1 }
|
||||
RUBY_ELEMENTS = { FIRE => 5, COSMIC => 1 }
|
||||
DIAMOND_ELEMENTS = { EARTH => 10, COSMIC => 1 }
|
||||
DSTONE_ELEMENTS = { WATER => 15, EARTH => 15, COSMIC => 1 }
|
||||
ONYX_ELEMENTS = { EARTH => 20, FIRE => 20, COSMIC => 1 }
|
||||
|
||||
# Sapphire
|
||||
append_enchant 1155, 7, SAPPHIRE_ELEMENTS, 1637, RING_ANIM, RING_GFX, 2, 17.5, 2550 # Ring
|
||||
|
||||
@@ -5,8 +5,7 @@ java_import 'org.apollo.game.event.impl.DisplayTabInterfaceEvent'
|
||||
java_import 'org.apollo.game.model.EquipmentConstants'
|
||||
java_import 'org.apollo.game.model.Skill'
|
||||
|
||||
MAGIC_ID = Skill::MAGIC
|
||||
DISPLAY_SPELLBOOK = DisplayTabInterfaceEvent.new 6
|
||||
DISPLAY_SPELLBOOK = DisplayTabInterfaceEvent.new(6)
|
||||
|
||||
class Spell
|
||||
attr_reader :level, :elements, :experience
|
||||
@@ -16,6 +15,7 @@ class Spell
|
||||
@elements = elements
|
||||
@experience = experience
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class SpellAction < Action
|
||||
@@ -45,8 +45,8 @@ class SpellAction < Action
|
||||
|
||||
def check_skill
|
||||
required = @spell.level
|
||||
if required > mob.skill_set.skill(MAGIC_ID).maximum_level
|
||||
mob.send_message "You need a Magic level of at least #{required} to cast this spell."
|
||||
if required > mob.skill_set.skill(MAGIC_SKILL_ID).maximum_level
|
||||
mob.send_message("You need a Magic level of at least #{required} to cast this spell.")
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -58,7 +58,7 @@ class SpellAction < Action
|
||||
|
||||
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."
|
||||
mob.send_message("You do not have enough #{element.name}s to cast this spell.")
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -73,14 +73,14 @@ class SpellAction < Action
|
||||
def equals(other)
|
||||
return (get_class == other.get_class and @spell == other.spell)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ItemSpellAction < SpellAction
|
||||
attr_reader :slot, :item
|
||||
|
||||
def initialize(mob, spell, slot, item)
|
||||
super(mob, spell)
|
||||
|
||||
super(mob, spell)
|
||||
@slot = slot
|
||||
@item = item
|
||||
end
|
||||
@@ -89,9 +89,9 @@ class ItemSpellAction < SpellAction
|
||||
def execute
|
||||
if @pulses == 0
|
||||
if illegal_item?
|
||||
mob.send_message "You cannot use that spell on this item!"
|
||||
mob.send_message('You cannot use that spell on this item!')
|
||||
stop
|
||||
return
|
||||
next
|
||||
end
|
||||
|
||||
id = @item.id
|
||||
@@ -100,9 +100,9 @@ class ItemSpellAction < SpellAction
|
||||
@spell.elements.each do |element, amount|
|
||||
element.runes.each do |rune|
|
||||
if id == rune && !element.check_remove(mob, amount + 1, false)
|
||||
mob.send_message("You do not have enough " + element.name + "s to cast this spell.")
|
||||
mob.send_message("You do not have enough #{element.name}s to cast this spell.")
|
||||
stop
|
||||
return
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -116,17 +116,18 @@ class ItemSpellAction < SpellAction
|
||||
# Override this method if necessary
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# MagicOnItemEvent handling
|
||||
# Intercepts the magic on item event.
|
||||
on :event, :magic_on_item do |ctx, player, event|
|
||||
spell = event.spell_id
|
||||
|
||||
alch = ALCHEMY_SPELLS[spell]
|
||||
if alch != nil
|
||||
slot = event.slot
|
||||
item = player.inventory.get slot
|
||||
player.start_action AlchemyAction.new(player, alch, slot, item)
|
||||
item = player.inventory.get(slot)
|
||||
player.start_action(AlchemyAction.new(player, alch, slot, item))
|
||||
ctx.break_handler_chain
|
||||
return
|
||||
end
|
||||
@@ -134,19 +135,19 @@ on :event, :magic_on_item do |ctx, player, event|
|
||||
ench = ENCHANT_SPELLS[event.id]
|
||||
if ench != nil and ench.button == spell
|
||||
slot = event.slot
|
||||
item = player.inventory.get slot
|
||||
player.start_action EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id])
|
||||
item = player.inventory.get(slot)
|
||||
player.start_action(EnchantAction.new(player, ench, slot, item, ENCHANT_ITEMS[item.id]))
|
||||
ctx.break_handler_chain
|
||||
end
|
||||
end
|
||||
|
||||
# ButtonEvent handling
|
||||
# Intercepts the button event
|
||||
on :event, :button do |ctx, player, event|
|
||||
button = event.widget_id
|
||||
|
||||
tele = TELEPORT_SPELLS[button]
|
||||
if tele != nil
|
||||
player.start_action TeleportingAction.new(player, tele)
|
||||
player.start_action(TeleportingAction.new(player, tele))
|
||||
ctx.break_handler_chain
|
||||
return
|
||||
end
|
||||
|
||||
@@ -10,11 +10,11 @@ TELEPORT_SPELLS = {}
|
||||
|
||||
MODERN_TELE_ANIM = Animation.new(714)
|
||||
MODERN_TELE_END_ANIM = Animation.new(715)
|
||||
MODERN_TELE_GFX = Graphic.new(308, 15, 100)
|
||||
MODERN_TELE_GRAPHIC = Graphic.new(308, 15, 100)
|
||||
|
||||
ANCIENT_TELE_END_GFX = Graphic.new(455)
|
||||
ANCIENT_TELE_END_GRAPHIC = Graphic.new(455)
|
||||
ANCIENT_TELE_ANIM = Animation.new(1979)
|
||||
ANCIENT_TELE_GFX = Graphic.new(392)
|
||||
ANCIENT_TELE_GRAPHIC = Graphic.new(392)
|
||||
|
||||
class TeleportSpell < Spell
|
||||
attr_reader :ancient, :destination, :experience, :name
|
||||
@@ -25,6 +25,7 @@ class TeleportSpell < Spell
|
||||
@destination = destination
|
||||
@name = name
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class TeleportingAction < SpellAction
|
||||
@@ -38,37 +39,34 @@ class TeleportingAction < SpellAction
|
||||
end
|
||||
|
||||
def execute_modern
|
||||
player = mob
|
||||
if @pulses == 0
|
||||
player.play_animation(MODERN_TELE_ANIM)
|
||||
mob.play_animation(MODERN_TELE_ANIM)
|
||||
elsif @pulses == 1
|
||||
player.play_graphic(MODERN_TELE_GFX)
|
||||
mob.play_graphic(MODERN_TELE_GRAPHIC)
|
||||
delay = 1
|
||||
elsif @pulses == 2
|
||||
player.stop_graphic
|
||||
player.play_animation(MODERN_TELE_END_ANIM)
|
||||
|
||||
destination = @spell.destination
|
||||
player.teleport(destination)
|
||||
player.skill_set.add_experience(MAGIC_ID, @spell.experience)
|
||||
mob.stop_graphic
|
||||
mob.play_animation(MODERN_TELE_END_ANIM)
|
||||
mob.teleport(@spell.destination)
|
||||
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
|
||||
stop
|
||||
end
|
||||
end
|
||||
|
||||
def execute_ancient
|
||||
player = mob
|
||||
if @pulses == 0
|
||||
player.play_graphic(ANCIENT_TELE_GFX)
|
||||
player.play_animation(ANCIENT_TELE_ANIM)
|
||||
mob.play_graphic(ANCIENT_TELE_GRAPHIC)
|
||||
mob.play_animation(ANCIENT_TELE_ANIM)
|
||||
delay = 2
|
||||
elsif @pulses == 1
|
||||
player.stop_graphic
|
||||
player.stop_animation
|
||||
player.teleport(@spell.destination)
|
||||
player.skill_set.add_experience(MAGIC_ID, @spell.experience)
|
||||
mob.stop_graphic
|
||||
mob.stop_animation
|
||||
mob.teleport(@spell.destination)
|
||||
mob.skill_set.add_experience(MAGIC_SKILL_ID, @spell.experience)
|
||||
stop
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def append_tele(ancient, button, level, elements, x, y, experience, name)
|
||||
|
||||
Reference in New Issue
Block a user