This time I chose to use a book-like format, because it fits better with my new menu-in-the-works than the scroll thing does. The code's a lot cleaner, the quests are easier to manage and organize, and you have -complete- control over the placement of everything in the description.
Features
- Organize your quests into categories!
- Faster loading!
- Less save-bloating!
- Easier quest data organization!
- Multi-page descriptions!
- Quest-specific variables!
- Ability to change font size, color, and name!
- Ability to use icons and pictures in descriptions!
- Greater control over objectives!
- Message codes for displaying various data in your description!
- HOLY CRAP MORE CUSTOMIZATION THAN YOU'LL EVER NEED FOR ANYTHING EVER
- Probably some other stuff that I forgot!
- wakka wakka wakka
- I am a SALAD BOAT
- VROOM VROOOM
- pinecone
Changelog v.2.1.3
Woops.
Bugfixes:
-Fixed a bug causing the quest display to refresh itself more than neccessary.
-Fixed a bug where the category title would be drawn based on all categories in the list instead of based on only active categories.
-Fixed several other bugs caused by the above problem.
v.2.1.2
Bugfixes:
-Fixed a bug where the draw text instruction types would default to the window's default font/size/color instead of the category list's default font/size/color
New stuff:
-Added support for spaces in quest variable names and in the \\s message code
-Confirm button now closes quest window when called directly to a quest (So books and stuff will behave more like a message box)
-Updated demo
Scripts
Quest Data
Code:
class Game_System
def load_quest_data
$data_quests = {}
#$data_quests["hash key"] = Quest_Data.new(
# "name", [description code], [objective code], {initial quest variables(optional)})
$data_quests["fishtalk"] = Quest_Data.new("Talk with Fish",
[[0, [0, [4, 4], "Cat wants me to ask Fish if"]], [0, [0, [4, 24], "it's ok to eat him."]]],
[[0, 1, [0, [4, 44], ["I need to get Fish's response.", "Fish said no."]]]])
$data_quests["cat quest 2"] = Quest_Data.new("Cat's Query",
[[0, [0, [4, 4], "Cat wants to know how Fish is"]], [0, [0, [4, 24], "breathing outside of water."]],
[0, [0, [4, 60], "Being a cat, Cat is too damn lazy"]], [0, [0, [4, 80], "to ask Fish himself."]]],
[])
$data_quests["cat quest done"] = Quest_Data.new("Lazy Cat",
[[0, [0, [4, 4], "Cat can ask his own stupid"]], [0, [0, [4, 24], "questions from now on."]]],
[])
$data_quests["trees"] = Quest_Data.new("Oh, nuts",
[[0, [0, [4, 4], "This tree wants me to find"]], [0, [0, [4, 24], "its missing acorns."]],
[2, [0, [290, 4], [1, 1]]], [0, [0, [310, 260], "A nice enough sort.", nil, 15]],
[0, [0, [4, 100], "I have found \\qv[nuts found]/5 acorns."]]],
[[0, 0, [0, [4, 120], ["I should return these to that tree."]]]], {"nuts found" => 0})
$data_quests["trees done"] = Quest_Data.new("Oh, nuts",
[[1, [0, [-80, 4], [1, "hat2"]]], [0, [0, [4, 232], "That tree gave me its"]],
[0, [0, [4, 252], "old 'brocap'."]], [0, [0, [4, 270], "I think I look smashing in it."]]],
[])
$data_quests["sign1"] = Quest_Data.new("",
[[0, [0, [4, 4], "You can call the script directly to a quest,"]],
[0, [0, [4, 24], "like this sign does. This lets you create"]],
[0, [0, [4, 44], "books and other media for your game..."]],
[0, [0, [4, 74], "...such as this sign."]], [0, [0, [4, 120], "You can also skip the category list and"]],
[0, [0, [4, 140], "jump directly to a category, if you wanted to."]]], [])
end
def initialize(quest_id)
@data = $data_quests[quest_id].data
@stages = []
for obj in $data_quests[quest_id].objectives
@stages.push(obj[1])
end
@id = quest_id
end
def name
return $data_quests[@id].name
end
def description
return $data_quests[@id].description
end
def objectives
return $data_quests[@id].objectives
end
def initialize
@quests = {}
@order = {}
@lists = {}
@settings = [1, 2] # Default inventory, default battlers
@lists['wat'] = Category_List.new
@lists['wat'].windowskin = "001-Blue01"
@lists['wat'].categories = [["Not Finished", "list1"], ["Not Not Finished", "Finished"]]
@lists["signboard"] = Category_List.new
@lists["signboard"].windowskin = "001-Blue01"
@lists["signboard"].background = ["terriblesign", -16, -24] # Remember that there's a 16x16 buffer on windows
end
def has_quest?(quest_id)
return @quests.include?(quest_id)
end
def add(quest_id, list_name)
return if $data_quests[quest_id].nil?
if @order[list_name].nil?
@order[list_name] = []
end
return if @order[list_name].include?(quest_id)
@order[list_name].push(quest_id)
add_quest(quest_id)
end
def remove(quest_id, list_name)
return if $data_quests[quest_id].nil?
return if @order[list_name].nil?
return if @order[list_name].empty?
return unless @order[list_name].include?(quest_id)
@order[list_name].delete(quest_id)
end
def add_quest(quest_id)
return if $data_quests[quest_id].nil?
return if @quests.include?(quest_id)
@quests[quest_id] = Quest_List_Data.new(quest_id)
end
def remove_quest(quest_id, erase = false)
@quests.delete(quest_id) if erase
for list in @order.keys
@order[list].delete(quest_id)
end
end
def reset_quest(quest_id, create = true)
return unless @quests.include?(quest_id) if create == false
@quests.delete(quest_id)
add_quest(quest_id)
end
def replace(new_quest, rep_quest, list_name)
return if new_quest == rep_quest # EASIEST REPLACEMENT EVER
return if $data_quests[new_quest].nil? or $data_quests[rep_quest].nil?
return if @order[list_name].nil?
return if @order[list_name].empty?
return if @order[list_name].include?(new_quest)
return unless @order[list_name].include?(rep_quest)
@order[list_name][@order[list_name].index(rep_quest)] = new_quest
add_quest(new_quest)
end
def erase_list(list_name)
@order.delete(list_name)
end
def create_list(list_name)
return unless @order[list_name].nil?
@order[list_name] = []
end
def initialize
# These are the defaults. You have to set them for the category list itself
# if you want it to be different.
@title = "Table of Contents"
# Font [[Title Font, Size, Color], [Category Font, Size, Color]]
@font = [[Font.default_name, 24, Color.new(0, 0, 0)], [Font.default_name, 20, Color.new(0, 0, 0)]]
# Background [filename, x offset, y offset]
@background = ["BookBack2.png", 5, 8]
@windowskin = "Pengu Speech 1.png"
# Items per page. Will require adjusting of @formatting if you change it.
@ipp = 11
# Animation ID (defined in script)
@animation = -1
# Text to display when there are no valid categories
@empty_text = ""
# Audio
@audio = [["Audio/SE/046-Book01", 100, 100], ["Audio/SE/046-Book01", 100, 100],
["Audio/SE/046-Book01", 100, 90], ["Audio/SE/046-Book01", 100, 90],
["Audio/SE/" + $data_system.cursor_se.name, $data_system.cursor_se.volume, $data_system.cursor_se.pitch],
["Audio/SE/046-Book01", 100, 100]]
# Formatting: [Distance from one page to the next, distance between list items, width of page, offset from top, cursor margin]
@formatting = [261, 26, 235, 12, 8]
# Page Graphics: [prevpage, nextpage]
@page_graphics = ["prevpage.png", "nextpage.png"]
# Same as before
@categories = []
end
def update_loop
loop do
Graphics.update
Input.update
update
break if @close_book
end
dispose
Input.update
end
def check_mode
se = @list.audio[2]
Audio.se_play(se[0], se[1], se[2])
case @mode[0]
when 1 # Directly to category [1, category key, header text]
@phase = 1
setup_category_cursor
when 2 # Directly to quest [2, quest key]
@phase = 2
end
end
def dispose
@background.dispose
super
end
def setup_toc
@toc = [[]]
@pagemax = []
@indexmax = [-1, 0]
i = 0
count = 1
val = -1
for catg in @list.categories
val += 1
next if $game_party.quests.order[catg[1]].nil?
next if $game_party.quests.order[catg[1]].empty?
if count > @list.ipp * 2
count = 0
i += 1
@toc.push([])
end
@toc[i].push(catg)
count += 1
@indexmax[0] += 1
end
if @indexmax[0] == -1
@phase = -1
@toc[0].push([@list.empty_text])
end
@pagemax[0] = i
end
def update
if [-1, 0].include?(@phase)
indexnum = 0
elsif @phase == 1
indexnum = 1
elsif @phase == 2
indexnum = 2
end
if Input.repeat?(Input::DOWN)
if [0, 1].include?(@phase)
temp = @index[indexnum] / @list.ipp
@index[indexnum] += 1
if @index[indexnum] > @indexmax[indexnum]
@index[indexnum] -= (@indexmax[indexnum] + 1) % @list.ipp
elsif @index[indexnum] / @list.ipp != temp
@index[indexnum] -= @list.ipp
end
end
end
if Input.repeat?(Input::UP)
if [0, 1].include?(@phase)
temp = @index[indexnum] / @list.ipp
@index[indexnum] -= 1
if @index[indexnum] < 0 or @index[indexnum] / @list.ipp != temp
@index[indexnum] = [(@index[indexnum] + @list.ipp), @indexmax[indexnum]].min
end
end
end
if Input.repeat?(Input::RIGHT)
if [0, 1].include?(@phase)
if @index[indexnum] == @indexmax[indexnum]
@index[indexnum] = 0
else
@index[indexnum] += @list.ipp
@index[indexnum] = @indexmax[indexnum] if @index[indexnum] > @indexmax[indexnum]
end
elsif @phase == 2
@page[2] += 1
@page[2] = 0 if @page[2] > @pagemax[2]
end
end
if Input.repeat?(Input::LEFT)
if [0, 1].include?(@phase)
if @index[indexnum] == 0
@index[indexnum] = @indexmax[indexnum]
else
@index[indexnum] -= @list.ipp
@index[indexnum] = 0 if @index[indexnum] < 0
end
elsif @phase == 2
@page[2] -= 1
@page[2] = @pagemax[2] if @page[2] < 0
end
end
if [-1, 0, 1].include?(@phase)
@page[indexnum] = (@index[indexnum] / (@list.ipp * 2))
end
if Input.trigger?(Input::C)
if @phase == 0
@phase = 1
setup_questlist
setup_category_cursor
@last_index = -1
@last_page = - 1
se = @list.audio[0]
Audio.se_play(se[0], se[1], se[2])
return
elsif @phase == 1
@phase = 2
@last_index = -1
@last_page = - 1
se = @list.audio[1]
Audio.se_play(se[0], se[1], se[2])
return
elsif @phase == 2 and @mode[0] == 2
@close_book = true
se = @list.audio[2]
Audio.se_play(se[0], se[1], se[2])
return
end
end
if Input.trigger?(Input::B)
if [-1, 0].include?(@phase) or (@phase == 1 and @mode[0] == 1) or
(@phase == 2 and @mode[0] == 2)
@close_book = true
se = @list.audio[2]
Audio.se_play(se[0], se[1], se[2])
return
elsif [1, 2].include?(@phase)
@index[1] = 0 if @phase == 1
@phase -= 1
@last_index = -1
@last_page = - 1
@page[2] = 0
se = @list.audio[3]
Audio.se_play(se[0], se[1], se[2])
return
end
end
if [0, 1].include?(@phase)
if @index[indexnum] != @last_index
unless @page[indexnum] != @last_page or @last_index == -2
se = @list.audio[4]
Audio.se_play(se[0], se[1], se[2])
end
@last_index = @index[indexnum]
self.cursor_rect.set(@cursor_coord[indexnum][@index[indexnum]][0], @cursor_coord[indexnum][@index[indexnum]][1], @cursor_coord[indexnum][@index[indexnum]][2],30)
end
end
if @page[indexnum] != @last_page
unless @last_page == - 1
se = @list.audio[5]
Audio.se_play(se[0], se[1], se[2])
if @page[indexnum] < @last_page
if @page[indexnum] + 1 < @last_page
page_left_many
else
page_left
end
else
if @page[indexnum] - 1 > @last_page
page_right_many
else
page_right
end
end
end
@last_page = @page[indexnum]
refresh
end
end
def refresh
self.contents.clear
if [-1, 0, 1].include?(@phase)
if [-1, 0].include?(@phase)
pagenum = 0
pagemaxnum = 0
headertext = @list.title
loopvals = @toc[@page[0]]
else
pagenum = 1
@pagemax[1] = 0
pagemaxnum = 1
if @mode[0] == 1
headertext = @mode[2]
loopvals = $game_party.quests.order[@mode[1]]
else
headertext = @toc[@page[1]][@index[0]][0]
loopvals = $game_party.quests.order[@toc[@page[1]][@index[0]][1]]
end
end
offset = @list.formatting[3]
if @page[pagenum] == 0
self.contents.font.name = @list.font[0][0]
self.contents.font.size = @list.font[0][1]
self.contents.font.color = @list.font[0][2]
text = headertext.dup
fontcheck = check_title_codes(text)
self.contents.font.name = fontcheck[0] unless fontcheck[0].nil?
self.contents.font.size = fontcheck[1] + 5 unless fontcheck[1].nil?
self.contents.font.color = fontcheck[2] unless fontcheck[2].nil?
self.contents.draw_text(0, 0, @list.formatting[2], 32, text, 1)
end
y = 0
x = 0
for asdf in loopvals
self.contents.font.name = @list.font[1][0]
self.contents.font.size = @list.font[1][1]
self.contents.font.color = @list.font[1][2]
if @phase == 1
name = $game_party.quests.quests[asdf].name.dup
else
name = asdf[0].dup
end
fontcheck = check_title_codes(name)
self.contents.font.name = fontcheck[0] unless fontcheck[0].nil?
self.contents.font.size = fontcheck[1] unless fontcheck[1].nil?
self.contents.font.color = fontcheck[2] unless fontcheck[2].nil?
y += 1
if y > @list.ipp
y = 1
x += 1
end
break if x >= 2
self.contents.draw_text(x * @list.formatting[0], offset + (y * @list.formatting[1]), @list.formatting[2], 32, name, 1)
end
if @page[pagenum] + 1 <= @pagemax[pagemaxnum]
bitmap = RPG::Cache.picture(@list.page_graphics[1])
self.contents.blt(self.contents.width - bitmap.width, self.contents.height - bitmap.height, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
end
if @page[pagenum] > 0
bitmap = RPG::Cache.picture(@list.page_graphics[0])
self.contents.blt(0, self.contents.height - bitmap.height, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
end
elsif @phase == 2
self.cursor_rect.empty
draw_description
end
end
def setup_toc_cursor
duck = 0
@cursor_coord[0] = []
for cat in @toc
x = 0
y = 0
for dog in cat
y += 1
if y > @list.ipp
y = 1
x += 1
end
if x >= 2
x = 0
end
self.contents.font.name = @list.font[1][0]
self.contents.font.size = @list.font[1][1]
self.contents.font.color = @list.font[1][2]
zebra = dog[0].dup
fontcheck = check_title_codes(zebra)
self.contents.font.name = fontcheck[0] unless fontcheck[0].nil?
self.contents.font.size = fontcheck[1] unless fontcheck[1].nil?
self.contents.font.color = fontcheck[2] unless fontcheck[2].nil?
@cursor_coord[0][duck] = [x * @list.formatting[0] + (@list.formatting[2] / 2) - @list.formatting[4] - (self.contents.text_size(zebra).width / 2), @list.formatting[3] + (y * @list.formatting[1]), self.contents.text_size(zebra).width + (@list.formatting[4] * 2)]
duck += 1
end
end
end
def setup_category_cursor
x = 0
y = 0
moose = 0
@cursor_coord[1] = []
if @mode[0] == 1
loopvals = $game_party.quests.order[@mode[1]]
else
loopvals = $game_party.quests.order[@toc[@page[0]][@index[0]][1]]
end
for cow in loopvals
badger = $game_party.quests.quests[cow].name
y += 1
if y > @list.ipp
y = 1
x += 1
end
if x >= 2
x = 0
end
self.contents.font.name = @list.font[1][0]
self.contents.font.size = @list.font[1][1]
self.contents.font.color = @list.font[1][2]
mushroom = badger.dup
fontcheck = check_title_codes(mushroom)
self.contents.font.name = fontcheck[0] unless fontcheck[0].nil?
self.contents.font.size = fontcheck[1] unless fontcheck[1].nil?
self.contents.font.color = fontcheck[2] unless fontcheck[2].nil?
@cursor_coord[1][moose] = [x * @list.formatting[0] + (@list.formatting[2] / 2) - @list.formatting[4] - (self.contents.text_size(mushroom).width / 2), @list.formatting[3] + (y * @list.formatting[1]), self.contents.text_size(mushroom).width + (@list.formatting[4] * 2)]
moose += 1
end
end
def check_title_codes(text)
fn = nil
fs = nil
fc = nil
text.gsub!(/\\[Ff][Nn]\[([0-9]+)\]/) do
fn = title_fonts($1.to_i)
""
end
text.gsub!(/\\[Ff][Ss]\[([0-9]+)\]/) do
fs = $1.to_i
""
end
text.gsub!(/\\[Ff][Cc]\[([0-9]+),([0-9]+),([0-9]+)\]/) do
fc = Color.new($1.to_i, $2.to_i, $3.to_i)
""
end
return [fn, fs, fc]
end
def page_left
end
def page_right
end
def page_left_many
end
def page_right_many
end
def title_fonts(type)
case type
when 0
return Font.default_name
when 1
return "Verdana"
end
end
end
Message Codes and Instruction Types
Code:
class Quest_Window < Window_Base
def draw_description
case @mode[0]
when 0
@index[2] = $game_party.quests.order[@list.categories[@indexvals[@index[0]]][1]][@index[1]]
when 1
@index[2] = $game_party.quests.order[@mode[1]][@index[1]]
when 2
@index[2] = @mode[1]
end
quest = $game_party.quests.quests[@index[2]]
pages = []
page_graphics = @list.page_graphics.dup
for line in quest.description
pages.push(line[1][0])
next unless @page[2] == line[1][0]
case line[0]
when 0 # Draw Text
x = line[1][1][0]
y = line[1][1][1]
t1 = line[1][2].dup
fc = line[1][3]
fs = line[1][4]
ft = line[1][5]
fc = @list.font[1][2] if fc.nil?
fs = @list.font[1][1] if fs.nil?
ft = @list.font[1][0] if ft.nil?
self.contents.font.color = fc
self.contents.font.size = fs
self.contents.font.name = ft
t = check_codes(t1)
h = self.contents.text_size(t).height
self.contents.draw_text(x, y, 1000, h, t)
when 1 # Draw Graphic
x = line[1][1][0]
y = line[1][1][1]
w = line[1][1][2]
h = line[1][1][3]
o = line[1][1][4]
w = 1.0 if w.nil?
h = 1.0 if h.nil?
o = 255 if o.nil?
gt = line[1][2][0]
gn = line[1][2][1]
if gt == 0
bitmap = RPG::Cache.icon(gn)
elsif gt == 1
bitmap = RPG::Cache.picture(gn)
end
self.contents.stretch_blt(Rect.new(x, y, bitmap.width * w, bitmap.height * h), bitmap, Rect.new(0, 0, bitmap.width, bitmap.height), o)
when 2 # Draw battler
x = line[1][1][0]
y = line[1][1][1]
o = line[1][1][2]
o = 255 if o.nil?
if line[1][2][0] == 0
actor = $game_actors[line[1][2][1]]
elsif line[1][2][0] == 1
actor = $data_enemies[line[1][2][1]]
end
case $game_party.quests.settings[1]
when 0 # Jaber's animation system [page, [x, y, opacity], [actor/enemy, id], pose, frame]
graphic = actor.battle_graphic + actor.stance + line[1][3]
bitmap = RPG::Cache.battler(graphic, 0)
self.contents.blt(x - ((bitmap.width / $game_temp.pose_frames(graphic)) / 2), y - bitmap.height, bitmap,
Rect.new(((bitmap.width / $game_temp.pose_frames(graphic)) * line[1][4]), 0, bitmap.width / $game_temp.pose_frames(graphic), bitmap.height), o)
if line[1][2][0] == 0
equip_graphics = []
eqind = -1
for equip in actor.slot_data
eqind += 1
equip_data = $game_temp.get_data(actor.equipment[eqind])
next if equip_data == nil or equip_data.battle_graphic == nil
hand = eqind == 0 ? "_R" : eqind == 1 ? "_L" : "_"
equip_pic = actor.battle_graphic + actor.stance + hand + equip_data.battle_graphic + line[1][3]
equip_graphics.push([equip_data.priority, equip_pic])
end
equip_graphics.sort!
for equip in equip_graphics
bitmap = RPG::Cache.battler(equip[1], 0)
if bitmap.nil?
p equip[1]
next
end
self.contents.blt(x - ((bitmap.width / $game_temp.pose_frames(graphic)) / 2), y - bitmap.height, bitmap,
Rect.new(((bitmap.width / $game_temp.pose_frames(graphic)) * line[1][4]), 0, bitmap.width / $game_temp.pose_frames(graphic), bitmap.height), o)
end
end
when 1 # Minkoff's animation system [page, [x, y], [actor/enemy, id], pose#, frame#]
if line[1][2][0] == 0
bitmap = RPG::Cache.battlers(actor.battler_name, actor.battler_hue)
o = MNK_TRANSLUCENCY if MNK_TRANSLUCENT_ACTOR.include?(actor.id)
if DEFAULT_ACTOR or DEFAULT_ACTOR_ID.include?(actor.id)
x_div = 1
y_div = 1
pose = 0
frame = 0
else
x_div = MNK_FRAMES
y_div = MNK_POSES
if MNK_FRAMES_ACTOR != nil and MNK_FRAMES_ACTOR[actor.id] != nil
x_div = MNK_FRAMES_ACTOR[actor.id]
end
if MNK_POSES_ACTOR != nil and MNK_POSES_ACTOR[actor.id] != nil
y_div = MNK_POSES_ACTOR[actor.id]
end
# WHY COULDN'T YOU MAKE THE POSE CRAP EASIER DVV D:
pose = line[1][3]
frame = line[1][4]
case line[1][3]
when 0
pose = MNK_APOSE1[actor.id] if MNK_APOSE1[actor.id] != nil
when 1
pose = MNK_APOSE2[actor.id] if MNK_APOSE2[actor.id] != nil
when 2
pose = MNK_APOSE3[actor.id] if MNK_APOSE3[actor.id] != nil
when 3
pose = MNK_APOSE4[actor.id] if MNK_APOSE4[actor.id] != nil
when 4
pose = MNK_APOSE5[actor.id] if MNK_APOSE5[actor.id] != nil
when 5
pose = MNK_APOSE6[actor.id] if MNK_APOSE6[actor.id] != nil
when 6
pose = MNK_APOSE7[actor.id] if MNK_APOSE7[actor.id] != nil
when 7
pose = MNK_APOSE8[actor.id] if MNK_APOSE8[actor.id] != nil
when 8
pose = MNK_APOSE9[actor.id] if MNK_APOSE9[actor.id] != nil
when 9
pose = MNK_APOSE10[actor.id] if MNK_APOSE10[actor.id] != nil
when 10
pose = MNK_APOSE11[actor.id] if MNK_APOSE11[actor.id] != nil
end
if MNK_FRAMES_PER_POSE[pose] != nil
x_div = MNK_FRAMES_PER_POSE[pose]
end
# I DON'T KNOW HOW THE MNK_POSES_FR_ THING WORKS SORRY
end
elsif line[1][2][0] == 1
bitmap = RPG::Cache.battlers(actor.battler_name, actor.battler_hue)
o = MNK_TRANSLUCENCY if MNK_TRANSLUCENT_ENEMY.include?(actor.id)
if DEFAULT_ENEMY or DEFAULT_ENEMY_ID.include?(actor.id)
x_div = 1
y_div = 1
pose = 0
frame = 0
else
x_div = MNK_FRAMES
y_div = MNK_POSES
if MNK_FRAMES_ENEMY != nil and MNK_FRAMES_ENEMY[actor.id] != nil
x_div = MNK_FRAMES_ENEMY[actor.id]
end
if MNK_POSES_ENEMY != nil and MNK_POSES_ENEMY[actor.id] != nil
y_div = MNK_POSES_ENEMY[actor.id]
end
pose = line[1][3]
frame = line[1][4]
case line[1][3]
when 0
pose = MNK_EPOSE1[actor.id] if MNK_EPOSE1[actor.id] != nil
when 1
pose = MNK_EPOSE2[actor.id] if MNK_EPOSE2[actor.id] != nil
when 2
pose = MNK_EPOSE3[actor.id] if MNK_EPOSE3[actor.id] != nil
when 3
pose = MNK_EPOSE4[actor.id] if MNK_EPOSE4[actor.id] != nil
when 4
pose = MNK_EPOSE5[actor.id] if MNK_EPOSE5[actor.id] != nil
when 5
pose = MNK_EPOSE6[actor.id] if MNK_EPOSE6[actor.id] != nil
when 6
pose = MNK_EPOSE7[actor.id] if MNK_EPOSE7[actor.id] != nil
when 7
pose = MNK_EPOSE8[actor.id] if MNK_EPOSE8[actor.id] != nil
when 8
pose = MNK_EPOSE9[actor.id] if MNK_EPOSE9[actor.id] != nil
when 9
pose = MNK_EPOSE10[actor.id] if MNK_EPOSE10[actor.id] != nil
when 10
pose = MNK_EPOSE11[actor.id] if MNK_EPOSE11[actor.id] != nil
end
end
end
self.contents.blt(x, y, bitmap, Rect.new((bitmap.width / x_div) * frame, (bitmap.height / y_div) * pose, bitmap.width / x_div, bitmap.height / y_div), o)
when 2 # Default battlers [page, [x, y, opacity], [actor/enemy, id]]
bitmap = RPG::Cache.battler(actor.battler_name, actor.battler_hue)
self.contents.blt(x, y, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height), o)
end
when 3 # Draw Characterset [page, [x, y, opacity], [type, data], [#frames, #directions, facing, frame]]
case line[1][2][0] # For type:
when 0 # Use actor ID, [0, actor id]
cn = $game_actors[line[1][2][1]].character_name
ch = $game_actors[line[1][2][1]].character_hue
when 1 # Use filename, [1, filename, hue number]
cn = line[1][2][1]
ch = line[1][2][2]
end
x = line[1][1][0]
y = line[1][1][1]
o = line[1][1][2]
o = 255 if o.nil?
w = line[3][0]
h = line[3][1]
d = line[3][2]
f = line[3][3]
bitmap = RPG::Cache.character(cn, ch)
self.contents.blt(x, y, bitmap, Rect.new(x + ((bitmap.width / w) * f), y + ((bitmap.height / h) * d),
bitmap.width / w, bitmap.height / h), o)
#
end
end
count = -1
for line in quest.objectives
count += 1
obj = quest.stages[count]
next if obj == 0
pages.push(line[2][0])
next unless @page[2] == line[2][0]
case line[0]
when 0 # Draw Text
x = line[2][1][0]
y = line[2][1][1]
t1 = line[2][2][obj-1].dup
fc = line[2][3]
fs = line[2][4]
ft = line[2][5]
fc = @list.font[1][2] if fc.nil?
fs = @list.font[1][1] if fs.nil?
ft = @list.font[1][0] if ft.nil?
self.contents.font.color = fc
self.contents.font.size = fs
self.contents.font.name = ft
t = check_codes(t1)
h = self.contents.text_size(t).height
self.contents.draw_text(x, y, 1000, h, t)
when 1 # Draw Graphic
x = line[2][1][0]
y = line[2][1][1]
w = line[2][1][2]
h = line[2][1][3]
o = line[2][1][4]
w = 1.0 if w.nil?
h = 1.0 if h.nil?
o = 255 if o.nil?
gt = line[2][2][obj-1][0]
gn = line[2][2][obj-1][1]
if gt == 0
bitmap = RPG::Cache.icon(gn)
elsif gt == 1
bitmap = RPG::Cache.picture(gn)
end
self.contents.stretch_blt(Rect.new(x, y, bitmap.width * w, bitmap.height * h), bitmap, Rect.new(0, 0, bitmap.width, bitmap.height), o)
when 2 # Draw battler
x = line[2][1][0]
y = line[2][1][1]
o = line[1][1][2]
o = 255 if o.nil?
if line[2][2][obj-1][0] == 0
actor = $game_actors[line[2][2][obj-1][1]]
elsif line[2][2][obj-1][0] == 1
actor = $data_enemies[line[2][2][obj-1][1]]
end
case $game_party.quests.settings[1]
when 0 # Jaber's animation system
graphic = actor.battle_graphic + actor.stance + line[2][3][obj-1]
bitmap = RPG::Cache.battler(graphic, 0)
self.contents.blt(x - ((bitmap.width / $game_temp.pose_frames(graphic)) / 2), y - bitmap.height, bitmap,
Rect.new(((bitmap.width / $game_temp.pose_frames(graphic)) * line[2][4][obj-1]), 0, bitmap.width / $game_temp.pose_frames(graphic), bitmap.height), o)
if line[1][1][obj-1][0] == 0
equip_graphics = []
eqind = -1
for equip in actor.slot_data
eqind += 1
equip_data = $game_temp.get_data(actor.equipment[eqind])
next if equip_data == nil or equip_data.battle_graphic == nil
hand = eqind == 0 ? "_R" : eqind == 1 ? "_L" : "_"
equip_pic = actor.battle_graphic + actor.stance + hand + equip_data.battle_graphic + line[2][3][obj-1]
equip_graphics.push([equip_data.priority, equip_pic])
end
equip_graphics.sort!
for equip in equip_graphics
bitmap = RPG::Cache.battler(equip[1], 0)
if bitmap.nil?
p equip[1]
next
end
self.contents.blt(x - ((bitmap.width / $game_temp.pose_frames(graphic)) / 2), y - bitmap.height, bitmap,
Rect.new(((bitmap.width / $game_temp.pose_frames(graphic)) * line[2][4][obj-1]), 0, bitmap.width / $game_temp.pose_frames(graphic), bitmap.height), o)
end
end
when 1 # Minkoff's animation system [page, [x, y], [actor/enemy, id], pose#, frame#]
if line[1][2][obj-1][0] == 0
bitmap = RPG::Cache.battlers(actor.battler_name, actor.battler_hue)
o = MNK_TRANSLUCENCY if MNK_TRANSLUCENT_ACTOR.include?(actor.id)
if DEFAULT_ACTOR or DEFAULT_ACTOR_ID.include?(actor.id)
x_div = 1
y_div = 1
pose = 0
frame = 0
else
x_div = MNK_FRAMES
y_div = MNK_POSES
if MNK_FRAMES_ACTOR != nil and MNK_FRAMES_ACTOR[actor.id] != nil
x_div = MNK_FRAMES_ACTOR[actor.id]
end
if MNK_POSES_ACTOR != nil and MNK_POSES_ACTOR[actor.id] != nil
y_div = MNK_POSES_ACTOR[actor.id]
end
pose = line[1][3][obj-1]
frame = line[1][4][obj-1]
case line[1][3]
when 0
pose = MNK_APOSE1[actor.id] if MNK_APOSE1[actor.id] != nil
when 1
pose = MNK_APOSE2[actor.id] if MNK_APOSE2[actor.id] != nil
when 2
pose = MNK_APOSE3[actor.id] if MNK_APOSE3[actor.id] != nil
when 3
pose = MNK_APOSE4[actor.id] if MNK_APOSE4[actor.id] != nil
when 4
pose = MNK_APOSE5[actor.id] if MNK_APOSE5[actor.id] != nil
when 5
pose = MNK_APOSE6[actor.id] if MNK_APOSE6[actor.id] != nil
when 6
pose = MNK_APOSE7[actor.id] if MNK_APOSE7[actor.id] != nil
when 7
pose = MNK_APOSE8[actor.id] if MNK_APOSE8[actor.id] != nil
when 8
pose = MNK_APOSE9[actor.id] if MNK_APOSE9[actor.id] != nil
when 9
pose = MNK_APOSE10[actor.id] if MNK_APOSE10[actor.id] != nil
when 10
pose = MNK_APOSE11[actor.id] if MNK_APOSE11[actor.id] != nil
end
if MNK_FRAMES_PER_POSE[pose] != nil
x_div = MNK_FRAMES_PER_POSE[pose]
end
end
elsif line[1][2][obj-1][0] == 1
bitmap = RPG::Cache.battlers(actor.battler_name, actor.battler_hue)
o = MNK_TRANSLUCENCY if MNK_TRANSLUCENT_ENEMY.include?(actor.id)
if DEFAULT_ENEMY or DEFAULT_ENEMY_ID.include?(actor.id)
x_div = 1
y_div = 1
pose = 0
frame = 0
else
x_div = MNK_FRAMES
y_div = MNK_POSES
if MNK_FRAMES_ENEMY != nil and MNK_FRAMES_ENEMY[actor.id] != nil
x_div = MNK_FRAMES_ENEMY[actor.id]
end
if MNK_POSES_ENEMY != nil and MNK_POSES_ENEMY[actor.id] != nil
y_div = MNK_POSES_ENEMY[actor.id]
end
pose = line[1][3][obj-1]
frame = line[1][4][obj-1]
case line[1][3][obj-1]
when 0
pose = MNK_EPOSE1[actor.id] if MNK_EPOSE1[actor.id] != nil
when 1
pose = MNK_EPOSE2[actor.id] if MNK_EPOSE2[actor.id] != nil
when 2
pose = MNK_EPOSE3[actor.id] if MNK_EPOSE3[actor.id] != nil
when 3
pose = MNK_EPOSE4[actor.id] if MNK_EPOSE4[actor.id] != nil
when 4
pose = MNK_EPOSE5[actor.id] if MNK_EPOSE5[actor.id] != nil
when 5
pose = MNK_EPOSE6[actor.id] if MNK_EPOSE6[actor.id] != nil
when 6
pose = MNK_EPOSE7[actor.id] if MNK_EPOSE7[actor.id] != nil
when 7
pose = MNK_EPOSE8[actor.id] if MNK_EPOSE8[actor.id] != nil
when 8
pose = MNK_EPOSE9[actor.id] if MNK_EPOSE9[actor.id] != nil
when 9
pose = MNK_EPOSE10[actor.id] if MNK_EPOSE10[actor.id] != nil
when 10
pose = MNK_EPOSE11[actor.id] if MNK_EPOSE11[actor.id] != nil
end
end
end
self.contents.blt(x, y, bitmap, Rect.new((bitmap.width / x_div) * frame, (bitmap.height / y_div) * pose, bitmap.width / x_div, bitmap.height / y_div), o)
when 2 # Default battlers
bitmap = RPG::Cache.battler(actor.battler_name, actor.battler_hue)
self.contents.blt(x, y, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height), o)
end
when 3 # Draw Characterset
case line[1][2][obj-1][0]
when 0 # Use actor ID
cn = $game_actors[line[1][2][obj-1][1]].character_name
ch = $game_actors[line[1][2][obj-1][1]].character_hue
when 1 # Use filename
cn = line[1][2][obj-1][1]
ch = line[1][2][obj-1][2]
end
x = line[1][1][0]
y = line[1][1][1]
o = line[1][1][2]
o = 255 if o.nil?
w = line[3][0][obj-1]
h = line[3][1][obj-1]
d = line[3][2][obj-1]
f = line[3][3][obj-1]
bitmap = RPG::Cache.character(cn, ch)
self.contents.blt(x, y, bitmap, Rect.new(x + ((bitmap.width / w) * f), y + ((bitmap.height / h) * d),
bitmap.width / w, bitmap.height / h), o)
#
end
end
@pagemax[2] = pages.max
if @page[2] + 1 <= @pagemax[2]
bitmap = RPG::Cache.picture(page_graphics[1])
self.contents.blt(self.contents.width - bitmap.width, self.contents.height - bitmap.height, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
end
if @page[2] > 0
bitmap = RPG::Cache.picture(page_graphics[0])
self.contents.blt(0, self.contents.height - bitmap.height, bitmap, Rect.new(0, 0, bitmap.width, bitmap.height))
end
end
def check_codes(text)
text.gsub!(/\\[Vv]\[([0-9]+)\]/) { $game_variables[$1.to_i] }
text.gsub!(/\\[Ss]\[([0-9]+),([\w\s]*),([\w\s]*)\]/) { $game_switches[$1.to_i] == true ? $2 : $3 }
text.gsub!(/\\[Gg]/) { $game_party.gold }
text.gsub!(/\\[Qq][Vv]\[([\w\s]*)\]/) { $game_party.quests.quests[@index[2]].data[$1] }
text.gsub!(/\\[Ii][Tt][Ee][Mm]\[([0-9]+)\]/) { $data_items[$1.to_i].name }
text.gsub!(/\\[Ww][Ee][Aa][Pp][Oo][Nn]\[([0-9]+)\]/) { $data_weapons[$1.to_i].name }
text.gsub!(/\\[Aa][Rr][Mm][Oo][Rr]\[([0-9]+)\]/) { $data_armors[$1.to_i].name }
text.gsub!(/\\[Ss][Kk][Ii][Ll][Ll]\[([0-9]+)\]/) { $data_skills[$1.to_i].name }
text.gsub!(/\\[Aa][Cc][Tt][Oo][Rr]\[([0-9]+)\]/) { $data_actors[$1.to_i].name }
text.gsub!(/\\[Ee][Nn][Ee][Mm][Yy]\[([0-9]+)\]/) { $data_enemies[$1.to_i].name }
text.gsub!(/\\[Cc][Ll][Aa][Ss][Ss]\[([0-9]+)\]/) { $data_classes[$1.to_i].name }
text.gsub!(/\\[Aa][Cc][Ll][Aa][Ss][Ss]\[([0-9]+)\]/) { $data_classes[$game_actors[$1.to_i].class_id].name }
case $game_party.quests.settings[0]
when 0 # For my inventory grid [mode, bag index, type, id]
text.gsub!(/\\[Hh][Ee][Ll][Dd]\[([01]),([0-9]+),([0-9]+),([0-9]+)\]/) do
if $1.to_i == 0 # Use $game_party
case $2.to_i
when 0 # Party item bag
$game_party.item_bag.item_amount([$3.to_i, $4.to_i]).to_s
else
$game_party.actors[$2.to_i].item_bag.item_amount([$3.to_i, $4.to_i]).to_s
end
elsif $1.to_i == 1 # Use $game_actors
$game_actors[$2.to_i].item_bag.item_amount([$3.to_i, $4.to_i]).to_s
end
end
when 1 # For everyone else's less insane inventory systems [type, id]
text.gsub!(/\\[Ii][Hh][Ee][Ll][Dd]\[([012]),([0-9]+)\]/) do
case $1.to_i
when 0 # Items
$game_party.item_number($2.to_i).to_s
when 1 # Weapons
$game_party.weapon_number($2.to_i).to_s
when 2 # Armor
$game_party.armor_number($2.to_i).to_s
end
end
end
text.gsub!(/\\[Ss][Tt][Aa][Tt]\[([012]),([0-9]+),(\w*)\]/) do
case $1.to_i
when 0
chara = $game_party.actors[$2.to_i]
when 1
chara = $game_actors[$2.to_i]
when 2
chara = $data_enemies[$2.to_i]
end
case $3
when "hp"
chara.hp.to_s
when "maxhp"
chara.maxhp.to_s
when "sp"
chara.sp.to_s
when "maxsp"
chara.maxsp.to_s
when "bmaxhp"
chara.base_maxhp.to_s
when "bmaxsp"
chara.base_maxsp.to_s
when "atk"
chara.base_atk.to_s
when "str"
chara.base_str.to_s
when "int"
chara.base_int.to_s
when "dex"
chara.base_dex.to_s
when "agi"
chara.base_agi.to_s
when "pdef"
chara.base_pdef.to_s
when "mdef"
chara.base_mdef.to_s
when "eva"
chara.base_eva.to_s
# Don't use any of the following or your game will asplode.
when "tp"
chara.tp.to_s
when "atk0"
chara.base_atk(0).to_s
when "atk1"
chara.base_atk(1).to_s
when "dmg0"
chara.basedmg(0).to_s
when "dmg1"
chara.basedmg(1).to_s
when "mdmg0"
chara.magdmg(0).to_s
when "mdmg1"
chara.magdmg(1).to_s
when "acc"
chara.base_acc.to_s
when "altdmg0"
chara.altbasedmg(0).to_s
when "altdmg1"
chara.altbasedmg(1).to_s
when "delay"
chara.delay.to_s
when "matk0"
chara.base_matk(0).to_s
when "matk1"
chara.base_matk(1).to_s
when "macc"
chara.base_macc.to_s
else
""
end
end
And here's some crappy next/previous page pictures:
Alright, onto the setup.
In Scene_Title, locate the following line:
$game_system = Game_System.new
In the default title, it should be on line 32.
Add this line right below it:
$game_system.load_quest_data
Next, stick the following anywhere below Game_Party:
Code:
class Game_Party
attr_accessor :quests
alias eveningguvnr initialize
def initialize
eveningguvnr
@quests = Quest_List.new
end
end
To call the quest window, simply use
Quest_Window.new(x, y, z, list key, selfupdate, mode)
x, y, and z are the coordinates, obviously.
Don't know what a list key is? Read the instructions below.
selfupdate and mode are optional.
If selfupdate is set to true, the window will function as it's own scene of sorts, meaning you could, say, call it from an event on the map without interrupting Scene_Map. If you don't know what that means, you'll probably want to have this set to true all the time.
mode is an array that lets you... 'skip' sections of the quest window.
Here's the various settings for it:
[0]
This is the default setting for the mode. It'll open up to the specified list.
[1, category key, headertext]
This will skip the category list and open up a category directly. 'headertext' is what will be displayed at the top of the first page. You still need to specify a list key, as it'll use that for formatting. Useful if you, say... don't want to use the category seperation feature. You'd be able to use a category as the entire quest log, if you wanted.
[2, quest key]
This will skip everything and jump right to a quest. Usefor for things like books or notes laying around.
Instructions
And this is the part where your head explodes. There's a whole crapload of stuff you can do with this, so I'll just go over the features and how to use them.
Creating Quests
This is done in the Quest Data script. You can see an example of what the data for a quest will look like. You have complete control over everything displayed on the page when the quest is opened. It doesn't even need to be a quest, you could make some text for books, or put together a wanted poster on a wall, or really anything you can think of.
First, to create your quest, you need to pick out a unique key for it. The example quest uses "test quest". No other quest can have the same key, and you can name it whatever you want so it's more intuitive than just giving them numbers. For this example, let's use "wumpus" as the quest key. You'd start by adding the following line to the load_quest_data method:
$data_quests["wumpus"] = Quest_Data.new()
Now you can begin entering the data for your quest. The first thing to enter is the quest's name. This is what will be displayed ingame. We'll call this quest "Hunt the Wumpus":
$data_quests["wumpus"] = Quest_Data.new("Hunt the Wumpus",
The next two things to enter will be instructions for how the quest will look. See the "Instruction Types" section for detailed info.
The first of the two is the description section. The second of the two is the objective section. You don't need to put description only in the description section, and the objective section doesn't need to be used for objectives. Essentially, the two sections are identical, with one difference: The objective section has a 'stage' variable that you can change in-game to hide the objective or change what it does.
For our wumpus quest, we'll keep it simple and just use the first instruction type to write some text, and leave the objectives section blank:
$data_quests["wumpus"] = Quest_Data.new("Hunt the Wumpus", [[0, [0, [4, 4], "YOU MUST KILL THE WUMPUS"]]], []
The next part is for the quest variables. They don't need to be set up here, and you don't even need add this part. This section exists only to set what variables will start at when the quest is started. We'll leave it blank:
$data_quests["wumpus"] = Quest_Data.new("Hunt the Wumpus", [[0, [0, [4, 4], "YOU MUST KILL THE WUMPUS"]]], [])
And there you go, you've got the data for a simple wumpus-hunting quest set up. Or maybe it's just a note, or a flyer, who knows? You can use this for pretty much any kind of visual media in your game, whether you use the quest log functions or not.
Category Lists
Quests are added to categories, and categories are added to category lists. You call the quest window and tell it what list to use, and it will display any categories in that list that have quests in them.
Even if you decide not to use the quest log functions, you'll still need to set up a list. They contain all the formatting information required by the script.
Here's how to set one up:
First, go to the quest handling script, and scroll down to the Quest_List class. See the '@lists[0] = Category_List.new' line? That's how you make a category list. There's more to it than that, though. That 0 is the list key. Like the quest key, it's a unique identifier for this particular list.
Now you have a number of different things you can customize for the list, the first of which being the categories it contains.
@lists[0].categories.push(["Category Name", category key])
Will add a category to the list. Category name would, of course, be the name of the category. Category key, just like the quest and list keys, is a unique identifier for a category. However, the categories themselves are not created just by adding them to a list. The list.categories just points towards the categories themselves. Don't worry too much about it, though, because the categories themselves are created automatically when quests are added to them. Any categories without quests in them won't show up, so add whatever categories you'll want to use in the future.
Onto the actual customization portion:
All of the following are accessed the same way, with @lists[key].xxxxxxx, where xxxxx would be the name of the option. So if you wanted to change the title of the list '0' above, you'd use @lists[0].title = ______. Let's begin. title
This is what shows up at the top of the page where "Table of Contents" is in the screenshots. It's just a string.
font
This contains the default fonts, sizes, and colors for the list. It's set up as
[[Title Font, Size, Color], [List Font, Size, Color]]
background
An array holding the filename of the picture to use, and the x/y offsets for positioning it relative to the text. It's set up as
[filename, x offset, y offset]
windowskin
This is what windowskin the list will use. This pretty much just affects what the cursor will look like. It's just a string.
ipp
This is how many items will appear on each page of the list. If you muck with this, you'll likely have to change the formatting part below. It's an integer.
animation
This will control the page turning animations whenever I get around to making them. Currently it does nothing.
empty_text
This is what will be displayed if you have no categories with quests on the list. It's just a string.
audio
This is an array containing arrays containing the data on what sound effects to play for various things like flipping pages and moving the cursor. I forget how it's set up, but each element of the array is set up as ["Audio/SE/Filename", volume, pitch].
I know audio[2] is for the opening and closing of the list, but I forget the rest. Experiment with it a bit, you'll figure it out.
formatting
This controls the positioning and spacing of the items on the list. It's set up as
[distance between pages, distance between list items, width of one page, offset from top of page, cursor margin]
page_graphics
This is an array holding the filenames of the little arrows in the corner. It's set up as [filename for left arrow, filename for right arrow]
You can check the Category_List class if you need help with how it should be set up. Changing the settings in the actual class will change them for all lists that don't have the options set individually. In other words, they're the defaults.
Basic Use
Alright, you've got some quests set up and a category list set up. So how do you start adding quests and all that stuff?
It's really rather easy once you get the hang of it.
First, I'll explain how the data is handled.
The entries in $data_quests don't contain the actual quest data, they're basically just cookie cutters that display the quest. When you add a quest to a category, it creates an actual data entry for the quest in $game_party.quests.quests. This is where the objective stages and quest variables are stored. You can access them any time in-game by using $game_party.quests.quests[quest key].stages[objective index]
and
$game_party.quests.quests[quest key].data[variable key]
You're probably confused at this point, but it's important to understand that before a quest has an entry in $game_party.quests.quests, it essentially does not exist in your saved data, which means you can't do anything with its objective stages or quest variables until it's been added. There's two ways to do this: You can use the 'add' method to add it to a category, or the 'add_quest' function to create just the quest data. More on that later.
Other than objectives and variables, you won't be able to view any quest that doesn't have an entry in $game_party.quests.quests. If you try to open the quest window directly to such a quest, it will explode.
While you're here, there is one more thing you need to do. See that '@settings = [0, 0]' line? That controls the settings for the message codes and instruction types. Specifically, for the drawing of battlers and the displaying of item quantities.
The first number is for item quantities. 0 is for my item grid system. You'll need to set this to 1 so it'll use the default inventory system. Otherwise, youre game will explode.
The second number is for the type of battlers you're using. 0 is for my animation system, and will make your game explode. Set this to 1 for minkoff's animated battlers, or 2 for the default battlers. Currently there is no code for the display of minkoff battlers, so don't be alarmed if it doesn't do anything yet. It'll be added in the next update.
Back to objectives and variables...
The 'objective index' above points to an objective. 0 would be the first objective, 1 would be the second, and so on.
The variable key is, like all the other keys, an identifier for a variable of the quest. You can only use alphanumeric characters for variable keys. If you use anything else, you won't be able to show the variable in the quest description using the message codes. These variables can be whatever you want, you could have say... a "cats ridden" variable that tracks how many cats you've ridden, for example.
It's really simple once you get the hang of it. Not so simple to explain. You'll get the hang of it. Probably.
Anyways, with that out of the way, let's go back to the basics: how to control the quests. There's a number of commands I've made to make it easier, and they handle a lot of the checks and data creation for you.
All are accessed with $game_party.quests._________
Let's begin: has_quest(quest key)
This will return true if the quest has a data entry. You can use this to check if a quest has been accepted, or to prevent the aforementioned explosion from trying to view a quest with no data entry.
add(quest key, category key)
This will add a quest to a category. It will also create a data entry for the quest if it doesn't already have one. The quest will be viewable from any lists that have the category key in their categories setting.
add_quest(quest key)
This will create a data entry for a quest if it doesn't already have one.
remove(quest key, category key)
This will remove a quest from a category. It will not remove the quest's data entry.
remove_quest(quest key, erase)
This will remove a quest from ALL categories. It will not remove the quest's data entry unless 'erase' is set to true. 'erase' is entirely optional, and not including it is the same as setting it to false.
reset_quest(quest key, create)
This will blank out a quest's variables and objectives, returning them to the default values. It will not remove it from any categories. If 'create' is set to true, this command will create a data entry if called on a quest that doesn't have one. 'create' is optional, and not including it is the same as calling it as true.
replace(new quest, old quest, category key)
This will replace one quest with another on a category. It will take the old quest's spot on the list, so the order will stay the same. It does not touch the quest data at all. Useful for when a quest requires a large update, and you want it to look like the same quest.
erase_list(category key)
This will erase a category. It will not erase any quest data for the quests within. Almost entirely useless, you can use this to veeeeery slightly lower the size of your savefiles by erasing lists that are no longer needed.
create_list(category key)
This will create a category. Entirely useless since this is done automatically whenever it's needed.
Instruction Types
For quest layout, that is. Descriptions and objectives use a list of these to put together the quest. For the most part, they're pretty much the same for descriptions and objectives. Objectives just have an added stage variable and a some parts are turned into arrays.
The basic layout for an instruction is as follows:
[type, [data]]
For objectives, there's an added stage variable:
[type, stage, [data]]
'stage' would be whatever you want the stage to start at. 0 is hidden, 1 displays the first entry, 2 displays the second, and so on. Objectives can have as many stages as you want.
And with that, here's the type numbers and data format:
Any options marked with a * are optional.
'page' refers to the pair of pages it will appear on, i.e. 1 would refer to page 3 and 4. This means you can have thigns spanning multiple pages, so you could use it for books and whatnot. Type 0 - Draw Text
This draws text, obviously.
Descriptions:
[0, [page, [x, y], text, alignment*, color*, size*, font*]]
Objectives:
[0, stage, [page, [x, y], [stage1 text, stage2 text, etc.], alignment*, color*, size*, font*]]
Pretty self-explanatory. The text can make use of message codes, detailed in the 'message codes' section.
Type 1 - Graphic
This displays either an icon or a picture.
Descriptions:
[1, [page, [x, y, zoom_x*, zoom_y*, opacity*], [type, filename]]]
Objectives:
[1, stage, [page, [x, y, zoom_x*, zoom_y*, opacity*], [[stage1 type, stage1 filename], [stage2 type, stage2 filename], [etc., etc.]]]]
'type' is either 0 or 1. 0 will load an icon, 1 will load a picture. zoom_x and zoom_y are multipliers, i.e. a zoom_x of 1.2 will make the image 20% wider.
Type 2 - Draw Battler
This will draw an actor's battler.
For default battlers:
Descriptions:
[2, [page, [x, y, opacity*], [type, id]]]
Objectives:
[2, stage, [page, [x, y, opacity*], [[stage1 type, stage1 id], [stage2 type, stage2 id], etc.]]]
'type' is either 0 or 1. 0 will load actors, 1 will load enemies. ID is the database id.
For Minkoff battlers:
Descriptions:
[2, [page, [x, y, opacity*], [type, id], pose#, frame]]
Objectives:
[2, stage, [page, [x, y, opacity*], [[stage1 type, stage1 id], [stage2 type, stage2 id], etc.], [stage1 pose#, stage2 pose#, etc.], [stage1 frame, stage2 frame, etc.]]]
'type' is either 0 or 1. 0 will load actors, 1 will load enemies. ID is the database id.
If the battler is set up to use a default battler, pose and frame can be skipped.
You can enter an opacity to use, but if the battler is added to MNK_TRANSLUCENT_WHATEVER, then it'll use the MNK_TRANSLUCENCY thingy setting.
Type 3 - Draw Characterset
This will draw a specified character, or an actor's characterset.
Descriptions:
[3, [page, [x, y, opacity*], [type, data], [frames, directions, facing, frame#]]]
Objectives:
[3, stage, [page, [x, y, opacity*], [[stage1 type, stage1 data], [stage2 type, stage2 data], [etc., etc.]], [[stage1 frames, directions, facing, frame#], [stage 2 frames, directions, facing, frame#], etc.]]]
'type' is either 0 or 1. 'data' depends on which type you use:
For type 0, it will use an actor's characterset, formatted like so: [0, actor id]
For type 1, it will use the specified characterset, formatted like so: [1, "filename", hue number]
frames is how many animation frames the characterset has (typically 4)
directions is how many directions the characterset has (typically 4 or 8)
facing is which direction will be displayed. It does not correspond to the actual directions, but to how far down the characterset it is, i.e. on a default 4dir characterset (dirs = [2, 4, 6, 8]), you'd enter 0 for down, 1 for left, 2 for right, and 3 for up.
frame# is what frame of the walking animation will be displayed.
Message Codes
There's three codes for use in quest and category names, and a bunch others for description and objective text. All you do is include the code in the text, and it'll replace it with various things or change various settings.
Quest/Category Name Codes
These control the font for quest and category names. They'll be used in place of the list's default settings. You can use this to, say, use a handwriting-ish font to make it look like a note was scrawled in, or something.
\\fn[number]
This will change the font. You'll have to set up what number goes with what font in the 'title_fonts' method at the very bottom of the Quest Window script.
\\fs[number]
This will change the size of the font.
\\fc[r,g,b]
This will change the color of the font. r, g, b corresponds to red, green, and blue levels.
Description/Objective Codes
These can be used to display a wide variety of data.
\\v[n]
This will display $game_variables[n]
\\s[n,on,off]
This will display the state of $game_switches[n].
If the switch is true, it will display the 'on' text. Otherwise, it will display the 'off' text.
Example: "The gate is \\s[3,open,closed]."
Alphanumerics only, by the way.
\\g
This will display the amount of gold the party has.
\\qv[key]
This will display one of the quest's variables. 'key' would be the variable key, obviously. This is why I suggested only using alphanumerics in the variable keys, as you won't be able to display any that use other characters.
\\item[n]
\\weapon[n]
\\armor[n]
\\skill[n]
\\actor[n]
\\enemy[n]
\\class[n]
These will display the item/skill/class/etc. names. n would be the id.
\\aclass[id]
This will display the name of $game_actor[id]'s class.
\\held[type,id]
This will display the quantity of an item/weapon/armor.
type is 0 for items, 1 for weapons, and 2 for armors. id is, of course, the id.
\\stat[type,id,stat]
This will display an actor/enemy's stats.
For type, enter one of the following:
0: Will use $game_party.actors[id]
1: Will use $game_actors[id]
2: Will use $data_enemies[id]
For id, enter the party index (if you're using type 0), or the database ID.
For stat, you can use any of the following:
hp, maxhp, sp, maxsp, bmaxhp, bmaxsp, atk, str, int, dex, agi, pdef, mdef, eva
It's typed in exactly like that.
For example, \\stat[1,2,bmaxhp] would display Basil's base max hp.
If you look at the code, you'll notice a whole bunch more stats listed. Don't use them or your game will explode.
Also, hp, maxhp, sp, and maxsp will likely not work with enemies.
WELL THAT ONLY TOOK THREE HOURS TO WRITE
...
It's really easy to use, but really hard to understand at first.
If anyone feels like writing a better set of instructions, go for it.
Screenshots
Category List
Quest List
Yeah, with 1 quest.
Quest Description
I was testing various things, okay?
v2.1.0 New Features
Battlers, item quantities, and ability to be called from any scene.
Terms of Use
You can use it or repost it wherever you want, just make sure to credit me.
If you complain about the images, I will punch you in the face.
If you refuse to try it because you don't like the images and don't feel like making your own, I will punch you again, only harder.
Lastly, I would love to see the kinds of ideas people come up with for this.
Special thanks to DerVVulfman for support, suggestions, and encouraging me to make something that runs outside of Ninja Penguin.
1. Quest Handling ->
# Formatting: [Distance from one page to the next, distance between list items, width of page, offset from top, cursor margin]
@formatting = [261, 26, 235, 12, 8]
this is it I think, just play around with the values. If it's not working, I have no clue ^^
---------------------------------------------------------
2. This is just a window so you have to open the quest window on map to show the map in the background I think
---------------------------------------------------------
3. Don't know what you mean, I think this could be done by events, but correct me if I'm wrong
Just make another list, label it as 'available', and add quests to it as they become available <.<
I dunno what you mean by an NPC tracker. You could just write the location of the NPC yourself. If it's something that's not static, i.e. the NPC moves around different maps, you could use a quest variable.
Anyways, if you have an idea for a new feature, and it's not impossible/impractical/etc., I'll add it in o_o/