KInfoMenu XP
by Kyonides
Introduction
The script allows you to create some sort of tutorial menu with lots of options using a GUI similar to my other script FancyChoices XP.
As the

Nope, this is NOT a Plug & Play script at all, guys! 

If you want to customize it, you will have to edit several CONSTANTS in the KInfoMenu module first.
All texts will be shown on top of the option boxes or on a typical message window. This also means that your typical note tags like \n[1] or \c[2] will work normally.

The pictures will be shown on the center of the screen right when its corresponding text message gets displayed there.
Understanding the Options Feature
There are 3 different levels of options, namely the Main Choices plus the first and second subcategories. Those subcategories depend on Hashes to let you customize its contents.
Option labels are simple to understand, they are just a list of texts:
Code:
SUB_CAT1["Combat"] = ["Allies", "Enemies", "FF Menu", "Section 4", "Section 5", "Section 6", "Section 7"]
"Combat" is a key that can be found in the Main Choices list:
Code:
MAIN_CHOICES = ["Combat", "Controls", "Concepts"]
So both subcategories should use keys that already exist on the previous subcategory or the main choices list.
The text hashes sport 3 keys and their respective values. Those keys are :text, :se and :pic and that's it.

You can leave the :pic and :se hashes empty if you need to, but you can add custom pictures or SFX at any given time. Just follow this example:
Code:
SUB_CAT1_TEXTS["Enemies"] = {
:se => { 1 => "Battle1", 2 => "Battle2" },
:pic => { 1 => "093-Monster07", 2 => "099-Monster13" },
:text => [
"You're not given a chance to think twice.",
"All mobs definitely hate you.",
"They'll sweep the floor with your death body",
"while laughing maniacally.",
"Please don't challenge them unless you know",
"very well what you're doing.",
"You've been warned!",
] }
So you need to pick a CONSTANT, then call its option key, and make it contain a { Hash }.
The :se and :pic keys use page indexes as their hash keys, but you can skip pages at will.
The :text hash has a very interesting feature that you should know about from the very beginning. If you plan to display less than 4 lines of text on a given


A Friendly Reminder
If a key like "Section 4" does not exist either in SUB_CAT1_TEXTS or SUB_CAT2_TEXTS, the script will skip the whole enchilada to prevent it from crashing.
NOTES
The comments include an explanation that claims that calling the custom scene is optional.


I don't care if there are other ways to achieve the same goal. I just wanted to create this special menu, and that's it!

Screenshots
Several Snapshots
The Script
Code:
# * KInfoMenu XP * #
# Scripter : Kyonides Arkanthes
# v1.2.1 - 2025-09-03
# Not a Plug & Play Script!
# This scriptlet lets you setup a simple tutorial menu.
# NOTES on Message Window's Contents:
# For the message window, empty lines are equally as important as normal ones.
# They are used as fillers, and this matters a lot whenever you're trying to
# display multiple pages on screen. If you ever skip them, you'll soon notice
# that certain lines of text do appear sooner than expected.
# * Optional Script Call * #
# $scene = KInfoMenu::Scene.new
module KInfoMenu
WIDTH = 640
HEIGHT = 480
BACKDROP = "Roman City"
TITLE_FILENAME = "title480"
# BGM Options: "" for no song, "Some Name" for any specific BGM
TUTORIAL_BGM = "062-Slow05"
TEXT_ALIGN_X = :center
CHOICE_ALIGN_X = :center
CHOICE_TOP_Y = 76
CHOICE_MARGIN_Y = 16
CHOICE_ROW_MAX = 6
MAIN_CHOICE_FILE = "box280"
SUB_CHOICE_FILE = "box240"
CHOICE_CURSOR = "cursor_shield"
MAIN_TITLE = "Tutorial Menu"
MAIN_CHOICES = ["Combat", "Controls", "Concepts"]
SHOW_WINDOW_BACK = true # true or false only!
WINDOW_POSITION = 2 # 0, 1 or 2 only!
# - Message Window's Contents - #
INTRO_TEXTS = ["Welcome to the Great Hero's Tutorial!",
"I'm your valorous host \c[2]\n[1]\c[0].",
"Nice to meet you!"]
# - The Don't Touch These Lines Section - #
MAIN_CHO_COLS = 1
SUB_CAT1 = {}
SUB_CAT2 = {}
SUB_CAT1_TEXTS = {}
SUB_CAT2_TEXTS = {}
SUB_CAT1.default = []
SUB_CAT2.default = []
SUB_CAT1_TEXTS.default = {}
SUB_CAT2_TEXTS.default = {}
# - End of Section - #
SUB_CAT1["Combat"] = ["Allies", "Enemies", "FF Menu", "Section 4",
"Section 5", "Section 6", "Section 7"]
SUB_CAT1["Controls"] = ["Decision", "Cancel"]
SUB_CAT1["Concepts"] = ["Concepts 1", "Concepts 2", "Concepts 3"]
SUB_CAT1_TEXTS["Allies"] = {
:se => {},
:pic => {},
:text => [
"Most of the time your allies will be very useless.",
"Just keep them alive to avoid making very large",
"donations to your local priest to heal those",
"reckless companions after every single battle."
] }
SUB_CAT1_TEXTS["Enemies"] = {
:se => { 1 => "Battle1", 2 => "Battle2" },
:pic => { 1 => "093-Monster07", 2 => "099-Monster13" },
:text => [
"You're not given a chance to think twice.",
"All mobs definitely hate you.",
"They'll sweep the floor with your death body",
"while laughing maniacally.",
"Please don't challenge them unless you know",
"very well what you're doing.",
"You've been warned!",
] }
SUB_CAT1_TEXTS["FF Menu"] = {
:se => {},
:pic => { 1 => "FF9_MenuBar old" },
:text => [
"This tutorial uses an old fashioned FF9 menubar.",
"We don't know when it will be replaced by a new",
"one. The game developer has repeatedly refused",
"to address the issue on social media."
] }
SUB_CAT2["Concepts 1"] = ["Concept 1", "Concept 2", "Concept 3"]
SUB_CAT2_TEXTS["Concept 1"] = {
:se => {},
:pic => {},
:text => [
"You've chosen the Proof of Concept #1!",
"Hurray..."
] }
class TextBox
def initialize(pos, total, vp=nil)
@index = pos
@max = total
@row_max = CHOICE_ROW_MAX
@col_max = (@max / @row_max) + 1
@viewport = vp
@backdrop = Sprite.new(vp)
@label = Sprite.new(vp)
@label.z = 50
end
def set_image(filename)
@filename = filename
set_bitmap
set_text_bitmap
reset_alignment
end
def set_bitmap
bitmap = RPG::Cache.picture(@filename)
@width = bitmap.width
@height = bitmap.height
@rect = bitmap.rect
@col_width = 640
@center_x = (@col_width - @width) / 2
@backdrop.bitmap = bitmap
end
def set_align_x
case TEXT_ALIGN_X
when :left
0
when :center
1
when :right
2
else
TEXT_ALIGN_X
end
end
def set_text_bitmap
@align_x = set_align_x
@label.bitmap = Bitmap.new(@width, @height)
end
def set_title_xy
@backdrop.x = @center_x
@backdrop.y = 8
end
def set_align_xy
h = @height + CHOICE_MARGIN_Y
if @max < @row_max
@backdrop.x = @center_x
@backdrop.y = CHOICE_TOP_Y + @index * h
else
n = @index % @col_max
cw = @col_width / 2
@backdrop.x = n * cw + (cw - @width) / 2
@backdrop.y = CHOICE_TOP_Y + @index / @col_max * h
end
end
def reset_alignment
@index ? set_align_xy : set_title_xy
@label.x = @backdrop.x
@label.y = @backdrop.y
end
def x
@backdrop.x
end
def y
@backdrop.y
end
def set_text(text)
@text = text
bit = @label.bitmap
bit.clear
bit.draw_text(@rect, text, @align_x)
end
def dispose
@label.bitmap.dispose
@label.dispose
@backdrop.bitmap.dispose
@backdrop.dispose
end
attr_reader :height, :text
end
class Spriteset
def initialize
create_variables
create_backdrop
create_viewports
create_title
create_picture
create_main_choices
create_cursors
update_box(0)
@sprites = @cursors + [@backdrop, @picture]
end
def create_variables
@index = 0
@section_index = 0
@subsection_index = 0
@sound = RPG::SE.new
@cursors = []
@sections = []
@subsections = []
@main_boxes = []
@section_boxes = []
@subsection_boxes = []
@section_viewports = []
@subsection_viewports = []
end
def create_backdrop
@backdrop = Sprite.new
@backdrop.bitmap = RPG::Cache.title(BACKDROP)
end
def create_viewports
@viewport_rect = [0, 0, WIDTH, HEIGHT]
@main_viewport = Viewport.new(*@viewport_rect)
@picture_viewport = Viewport.new(*@viewport_rect)
@picture_viewport.z = 1000
end
def create_title
@title = TextBox.new(nil, 0, nil)
@title.set_image(TITLE_FILENAME)
@title.set_text(MAIN_TITLE)
end
def create_picture
@picture = Sprite.new(@picture_viewport)
@picture.y = 48
@picture.visible = false
@picture.bitmap = Bitmap.new(WIDTH, HEIGHT - 96)
end
def create_main_choices
filename = MAIN_CHOICE_FILE
total = MAIN_CHOICES.size
MAIN_CHOICES.each_with_index do |choice, n|
box = TextBox.new(n, total, @main_viewport)
box.set_image(filename)
box.set_text(choice)
@main_boxes << box
end
@item_max = @main_boxes.size
end
def create_cursors
box = @main_boxes[@index]
@main_cursor = Sprite.new(@main_viewport)
@main_cursor.z = 100
@main_cursor.bitmap = RPG::Cache.icon(CHOICE_CURSOR)
@main_cursor.x = box.x + 4
@offset_y = (box.height - @main_cursor.bitmap.height) / 2
@main_cursor.y = box.y + @offset_y
@section_cursor = Sprite.new
@section_cursor.visible = false
@section_cursor.z = 100
@section_cursor.bitmap = RPG::Cache.icon(CHOICE_CURSOR)
@subsection_cursor = Sprite.new
@subsection_cursor.visible = false
@subsection_cursor.z = 100
@subsection_cursor.bitmap = RPG::Cache.icon(CHOICE_CURSOR)
@cursors << @main_cursor << @section_cursor << @subsection_cursor
end
def update_main
if Input.trigger?(Input::UP)
$game_system.se_play($data_system.cursor_se)
update_box(-1)
return
elsif Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
update_box(1)
end
end
def update_box(n)
@index = (@index + n) % @item_max
box = @main_boxes[@index]
@section_title = box.text
@main_cursor.x = box.x + 4
@main_cursor.y = box.y + @offset_y
end
def show_main
@title.set_text(MAIN_TITLE)
@main_viewport.visible = true
end
def hide_main
@main_viewport.visible = false
end
def find_section_viewport
@section_viewports[@index] ||= Viewport.new(*@viewport_rect)
end
def find_subsections
@sections[@index] ||= SUB_CAT1[@section_title].dup
end
def find_section_boxes
@section_boxes[@index] ||= []
end
def setup_section
@section_viewport = find_section_viewport
@section_list = find_subsections
@current_boxes = find_section_boxes
create_section if @current_boxes.empty?
reset_section
update_section_box(0)
@title.set_text(@section_title)
@section_viewport.visible = true
end
def create_section
return if @section_list.empty?
filename = SUB_CHOICE_FILE
total = @section_list.size
@section_list.each_with_index do |choice, n|
box = TextBox.new(n, total, @section_viewport)
box.set_image(filename)
box.set_text(choice)
@current_boxes << box
end
end
def reset_section
@section_max = @current_boxes.size
@col_max = (@section_max / CHOICE_ROW_MAX) + 1
@section_index = 0
box = @current_boxes[@section_index]
@section_oy1 = (box.height - @section_cursor.bitmap.height) / 2
@section_cursor.visible = box ? true : false
end
def show_section
@title.set_text(@section_title)
@section_viewport.visible = true
@section_cursor.visible = true
end
def hide_section(clear)
@section_cursor.visible = false
@section_viewport.visible = false
return unless clear
@section_viewport = @current_boxes = nil
@section_index = 0
end
def update_section
if Input.trigger?(Input::UP)
$game_system.se_play($data_system.cursor_se)
update_section_box(-@col_max)
return
elsif Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
update_section_box(@col_max)
return
end
return if @col_max == 1
if Input.trigger?(Input::LEFT)
$game_system.se_play($data_system.cursor_se)
update_section_box(-1)
return
elsif Input.trigger?(Input::RIGHT)
$game_system.se_play($data_system.cursor_se)
update_section_box(1)
end
end
def update_section_box(n)
@section_index = (@section_index + n) % @section_max
box = @current_boxes[@section_index]
@subsection_title1 = box.text
@section_cursor.x = box.x + 4
@section_cursor.y = box.y + @section_oy1
end
def set_pictures(pictures)
@page_index = 1
@pictures = pictures
show_picture
end
def show_picture
picture = @pictures[@page_index]
return unless picture
@picture.bitmap.dispose
@picture.bitmap = bit = RPG::Cache.picture(picture)
@picture.x = (WIDTH - bit.width) / 2
@picture.y = (HEIGHT - bit.height - 128) / 2
@picture.visible = true
end
def set_sfx(sfx)
@sfx = sfx
play_sound
end
def play_sound
@sound.name = @sfx[@page_index] || ""
$game_system.se_play(@sound)
end
def find_subsection_viewport
@subsection_viewports[@section_index] ||= Viewport.new(*@viewport_rect)
end
def find_subsections_lvl2
@subsections[@section_index] ||= SUB_CAT2[@subsection_title1].dup
end
def find_subsection_boxes
@subsection_boxes[@section_index] ||= []
end
def setup_subsection
@subsection_viewport = find_subsection_viewport
@subsection_list = find_subsections_lvl2
@current_subboxes = find_subsection_boxes
create_subsection if @current_subboxes.empty?
reset_subsection
update_subsection_box(0)
box = @current_subboxes[@subsection_index]
@subsection_title2 = box ? box.text : ""
@title.set_text(@subsection_title1)
@subsection_viewport.visible = true
end
def create_subsection
return if @subsection_list.empty?
filename = SUB_CHOICE_FILE
total = @subsection_list.size
@subsection_list.each_with_index do |choice, n|
box = TextBox.new(n, total, @subsection_viewport)
box.set_image(filename)
box.set_text(choice)
@current_subboxes << box
end
end
def reset_subsection
@subsection_max = @current_subboxes.size
@subcol_max = (@subsection_max / CHOICE_ROW_MAX) + 1
@subsection_index = 0
box = @current_subboxes[@subsection_index]
@section_oy2 = (box.height - @subsection_cursor.bitmap.height) / 2
@subsection_cursor.visible = box ? true : false
end
def hide_subsection
@subsection_cursor.visible = false
@subsection_viewport.visible = false
@subsection_viewport = @current_subboxes = nil
@subsection_index = 0
end
def update_subsection
if Input.trigger?(Input::UP)
$game_system.se_play($data_system.cursor_se)
update_subsection_box(-@subcol_max)
return
elsif Input.trigger?(Input::DOWN)
$game_system.se_play($data_system.cursor_se)
update_subsection_box(@subcol_max)
return
end
return if @subcol_max == 1
if Input.trigger?(Input::LEFT)
$game_system.se_play($data_system.cursor_se)
update_subsection_box(-1)
return
elsif Input.trigger?(Input::RIGHT)
$game_system.se_play($data_system.cursor_se)
update_subsection_box(1)
end
end
def update_subsection_box(n)
@subsection_index = (@subsection_index + n) % @subsection_max
box = @current_subboxes[@subsection_index]
@subsection_title2 = box.text
@subsection_cursor.x = box.x + 4
@subsection_cursor.y = box.y + @section_oy2
end
def hide_picture
@picture.bitmap.dispose
@picture.bitmap = Bitmap.new(WIDTH, HEIGHT - 96)
@picture.visible = false
end
def update_extras
return unless $game_temp.new_message_page
$game_temp.new_message_page = nil
@page_index += 1
show_picture
play_sound
end
def dispose
@sprites.each do |sprite|
sprite.bitmap.dispose
sprite.dispose
end
@subsection_boxes.each do |boxes|
next unless boxes
boxes.each {|box| box.dispose }
end
@section_boxes.each do |boxes|
next unless boxes
boxes.each {|box| box.dispose }
end
@main_boxes.each {|box| box.dispose }
@title.dispose
@section_viewports.each {|vp| vp.dispose if vp }
@picture_viewport.dispose
@main_viewport.dispose
@section_boxes.clear
@main_boxes.clear
@section_viewports.clear
end
attr_reader :subsection_title1, :subsection_title2
end
class Scene
def initialize(index=nil)
@main_menu_index = index
@map_bgm = $game_system.playing_bgm || RPG::BGM.new
@bgm = RPG::BGM.new
return if TUTORIAL_BGM.empty?
@bgm.name = TUTORIAL_BGM
$game_system.bgm_play(@bgm)
end
def main
start
Graphics.transition
update_basic while @stage
Graphics.freeze
terminate
end
def start
@stage = :message
@next_stage = :main
@spriteset = Spriteset.new
@message_window = Window_Message.new
$game_system.setup_message
$game_temp.set_tutorial_texts(INTRO_TEXTS)
end
def update_basic
Graphics.update
Input.update
update
end
def close_message
if $game_temp.next_lines
$game_temp.set_next_page
@spriteset.update_extras
else
@message_window.clear_contents
@spriteset.hide_picture
@stage = @next_stage
end
end
def update
case @stage
when :message
update_message
when :main
update_main
when :section
update_section
when :subsection
update_subsection
end
end
def update_message
@message_window.update
while $game_temp.message_window_showing
Graphics.update
Input.update
@message_window.update
end
close_message
end
def update_main
@spriteset.update_main
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
if @main_menu_index
$scene = Scene_Menu.new(@main_menu_index)
else
$scene = Scene_Map.new
end
return @stage = nil
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
@spriteset.hide_main
@spriteset.setup_section
@stage = :section
end
end
def update_section
@spriteset.update_section
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@spriteset.hide_section(true)
@spriteset.show_main
return @stage = :main
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
key = @spriteset.subsection_title1
if SUB_CAT2[key].any?
show_subsection
else
show_section_message(key)
end
end
end
def show_subsection
@spriteset.hide_section(nil)
@spriteset.setup_subsection
@stage = :subsection
end
def show_section_message(key)
data = SUB_CAT1_TEXTS[key].dup
return if data.empty?
message = data[:text]
pictures = data[:pic]
sfx = data[:se]
$game_system.setup_message
$game_temp.set_tutorial_texts(message)
@spriteset.set_pictures(pictures)
@spriteset.set_sfx(sfx)
@next_stage = :section
@stage = :message
end
def update_subsection
@spriteset.update_subsection
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
@spriteset.hide_subsection
@spriteset.show_section
return @stage = :section
elsif Input.trigger?(Input::C)
$game_system.se_play($data_system.decision_se)
key = @spriteset.subsection_title2
data = SUB_CAT2_TEXTS[key]
return if data.empty?
message = data[:text]
pictures = data[:pic]
sfx = data[:se]
$game_system.setup_message
$game_temp.set_tutorial_texts(message)
@spriteset.set_pictures(pictures)
@spriteset.set_sfx(sfx)
@next_stage = :subsection
@stage = :message
end
end
def terminate
@message_window.dispose
@spriteset.dispose
$game_system.reset_message
return if TUTORIAL_BGM.empty?
if $game_map.autoplay_bgm?
$game_map.autoplay
elsif @map_bgm
$game_system.bgm_play(@map_bgm)
end
end
end
end
class Game_Temp
def set_tutorial_texts(texts)
texts = texts.dup
if texts.size > 4
@next_lines = texts[4..-1]
texts = texts[0..3]
else
@next_lines = nil
end
texts = texts.join("\n")
texts.gsub!("\e", "\\c[")
texts.gsub!(/(.)\^/) { "#{$1}\\^" }
texts.gsub!(/([^\\])\|/) { "#{$1}\\|" }
texts.gsub!(/(\-|,|;|:|!)\./) { "#{$1}\\." }
texts.gsub!(/[\b]/i, "\\b")
texts.gsub!(/([^\\])i\[([0-9]+)\]/i) { "#{$1}\\i[#{$2}]" }
texts.gsub!(/\n\[([0-9]+)\]/i) { "\\n[#{$1}]" }
@message_text = texts
end
def set_next_page
@new_message_page = true
set_tutorial_texts(@next_lines)
end
attr_accessor :new_message_page
attr_reader :next_lines
end
class Game_System
def setup_message
@message_position = KInfoMenu::WINDOW_POSITION
@message_frame = KInfoMenu::SHOW_WINDOW_BACK ? 0 : 1
end
def reset_message
@message_position = 2
@message_frame = 0
end
end
class Game_Map
def autoplay_bgm?
@map.autoplay_bgm
end
end
class Window_Message
def clear_contents
@gold_window.close if @gold_window
self.pause = false
self.index = -1
self.visible = false
end
end
Terms & Conditions
Free as in
![[Image: beer.gif]](https://www.save-point.org/images/smilies/ejlol/beer.gif)
![[Image: gamer.gif]](https://www.save-point.org/images/smilies/ejlol/gamer.gif)
Include my nickname in your game credits.
That's it!
![[Image: tongue.gif]](https://www.save-point.org/images/smilies/ejlol/tongue.gif)
"For God has not destined us for wrath, but for obtaining salvation through our Lord Jesus Christ," 1 Thessalonians 5:9
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
![[Image: SP1-Scripter.png]](https://www.save-point.org/images/userbars/SP1-Scripter.png)
![[Image: SP1-Writer.png]](https://www.save-point.org/images/userbars/SP1-Writer.png)
![[Image: SP1-Poet.png]](https://www.save-point.org/images/userbars/SP1-Poet.png)
![[Image: SP1-PixelArtist.png]](https://www.save-point.org/images/userbars/SP1-PixelArtist.png)
![[Image: SP1-Reporter.png]](https://i.postimg.cc/GmxWbHyL/SP1-Reporter.png)
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!
Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE
Maranatha!
The Internet might be either your friend or enemy. It just depends on whether or not she has a bad hair day.
![[Image: SP1-Scripter.png]](https://www.save-point.org/images/userbars/SP1-Scripter.png)
![[Image: SP1-Writer.png]](https://www.save-point.org/images/userbars/SP1-Writer.png)
![[Image: SP1-Poet.png]](https://www.save-point.org/images/userbars/SP1-Poet.png)
![[Image: SP1-PixelArtist.png]](https://www.save-point.org/images/userbars/SP1-PixelArtist.png)
![[Image: SP1-Reporter.png]](https://i.postimg.cc/GmxWbHyL/SP1-Reporter.png)
My Original Stories (available in English and Spanish)
List of Compiled Binary Executables I have published...
HiddenChest & Roole
Give me a free copy of your completed game if you include at least 3 of my scripts!

Just some scripts I've already published on the board...
KyoGemBoost XP VX & ACE, RandomEnkounters XP, KSkillShop XP, Kolloseum States XP, KEvents XP, KScenario XP & Gosu, KyoPrizeShop XP Mangostan, Kuests XP, KyoDiscounts XP VX, ACE & MV, KChest XP VX & ACE 2016, KTelePort XP, KSkillMax XP & VX & ACE, Gem Roulette XP VX & VX Ace, KRespawnPoint XP, VX & VX Ace, GiveAway XP VX & ACE, Klearance XP VX & ACE, KUnits XP VX, ACE & Gosu 2017, KLevel XP, KRumors XP & ACE, KMonsterPals XP VX & ACE, KStatsRefill XP VX & ACE, KLotto XP VX & ACE, KItemDesc XP & VX, KPocket XP & VX, OpenChest XP VX & ACE