- 1,224
- Posts
- 11
- Years
- Omnipresence
- Seen Aug 8, 2023
I always wanted to use Mobius' Quest Journal for my game, but there are some important differences in Essentials that prevent it from working as is. I did just a bit of tweaking, and it seems to work fine.
See the link above for more info about using the script and writing the .txt document (it goes in your /Data folder), as well as a sample project file and a simple program for writing/editing the text document.
Basically, just copy this in above the main.
and then we need to add a couple things so that your updates to your journal are saved and loaded.
this
needs to be added in PokemonLoad a bit under
Same section but under
add
In PokemonSave under
add
Should work fine, let me know if any bugs found.
Only thing I can't figure out how to do is change the windowskin used, it keeps sticking with the default, so let me know if you know how to fix that :)
Important thing to note, once you install these scripts you must start a new game for it to work properly.
No credit to me required, but please give credit to MobiusXVI.
See the link above for more info about using the script and writing the .txt document (it goes in your /Data folder), as well as a sample project file and a simple program for writing/editing the text document.
Basically, just copy this in above the main.
Spoiler:
Code:
#==============================================================================
# ** Window_Base
#------------------------------------------------------------------------------
# This class is for all in-game windows.
#==============================================================================
class Window_Base < Window
#--------------------------------------------------------------------------
# * Object Initialization
# x : window x-coordinate
# y : window y-coordinate
# width : window width
# height : window height
#--------------------------------------------------------------------------
def initialize(x, y, width, height)
super()
$game_system.windowskin_name=("001-Blue01")
@windowskin_name = $game_system.windowskin_name
self.windowskin = RPG::Cache.windowskin(@windowskin_name)
self.x = x
self.y = y
self.width = width
self.height = height
self.z = 100
end
#--------------------------------------------------------------------------
# * Dispose
#--------------------------------------------------------------------------
def dispose
# Dispose if window contents bit map is set
if self.contents != nil
self.contents.dispose
end
super
end
#--------------------------------------------------------------------------
# * Get Text Color
# n : text color number (0-7)
#--------------------------------------------------------------------------
def text_color(n)
case n
when 0
return Color.new(255, 255, 255, 255)
when 1
return Color.new(128, 128, 255, 255)
when 2
return Color.new(255, 128, 128, 255)
when 3
return Color.new(128, 255, 128, 255)
when 4
return Color.new(128, 255, 255, 255)
when 5
return Color.new(255, 128, 255, 255)
when 6
return Color.new(255, 255, 128, 255)
when 7
return Color.new(192, 192, 192, 255)
else
normal_color
end
end
#--------------------------------------------------------------------------
# * Get Normal Text Color
#--------------------------------------------------------------------------
def normal_color
return Color.new(255, 255, 255, 255)
end
#--------------------------------------------------------------------------
# * Get Disabled Text Color
#--------------------------------------------------------------------------
def disabled_color
return Color.new(255, 255, 255, 128)
end
#--------------------------------------------------------------------------
# * Get System Text Color
#--------------------------------------------------------------------------
def system_color
return Color.new(192, 224, 255, 255)
end
#--------------------------------------------------------------------------
# * Get Crisis Text Color
#--------------------------------------------------------------------------
def crisis_color
return Color.new(255, 255, 64, 255)
end
#--------------------------------------------------------------------------
# * Get Knockout Text Color
#--------------------------------------------------------------------------
def knockout_color
return Color.new(255, 64, 0)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# Reset if windowskin was changed
if $game_system.windowskin_name != @windowskin_name
@windowskin_name = $game_system.windowskin_name
self.windowskin = RPG::Cache.windowskin(@windowskin_name)
end
end
end
#==============================================================================
# ** Window_Selectable
#------------------------------------------------------------------------------
# This window class contains cursor movement and scroll functions.
#==============================================================================
class Window_Selectable < Window_Base
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :index # cursor position
attr_reader :help_window # help window
#--------------------------------------------------------------------------
# * Object Initialization
# x : window x-coordinate
# y : window y-coordinate
# width : window width
# height : window height
#--------------------------------------------------------------------------
def initialize(x, y, width, height)
super(x, y, width, height)
@item_max = 1
@column_max = 1
@index = -1
end
#--------------------------------------------------------------------------
# * Set Cursor Position
# index : new cursor position
#--------------------------------------------------------------------------
def index=(index)
@index = index
# Update Help Text (update_help is defined by the subclasses)
if self.active and @help_window != nil
update_help
end
# Update cursor rectangle
update_cursor_rect
end
#--------------------------------------------------------------------------
# * Get Row Count
#--------------------------------------------------------------------------
def row_max
# Compute rows from number of items and columns
return (@item_max + @column_max - 1) / @column_max
end
#--------------------------------------------------------------------------
# * Get Top Row
#--------------------------------------------------------------------------
def top_row
# Divide y-coordinate of window contents transfer origin by 1 row
# height of 32
return self.oy / 32
end
#--------------------------------------------------------------------------
# * Set Top Row
# row : row shown on top
#--------------------------------------------------------------------------
def top_row=(row)
# If row is less than 0, change it to 0
if row < 0
row = 0
end
# If row exceeds row_max - 1, change it to row_max - 1
if row > row_max - 1
row = row_max - 1
end
# Multiply 1 row height by 32 for y-coordinate of window contents
# transfer origin
self.oy = row * 32
end
#--------------------------------------------------------------------------
# * Get Number of Rows Displayable on 1 Page
#--------------------------------------------------------------------------
def page_row_max
# Subtract a frame height of 32 from the window height, and divide it by
# 1 row height of 32
return (self.height - 32) / 32
end
#--------------------------------------------------------------------------
# * Get Number of Items Displayable on 1 Page
#--------------------------------------------------------------------------
def page_item_max
# Multiply row count (page_row_max) times column count (@column_max)
return page_row_max * @column_max
end
#--------------------------------------------------------------------------
# * Set Help Window
# help_window : new help window
#--------------------------------------------------------------------------
def help_window=(help_window)
@help_window = help_window
# Update help text (update_help is defined by the subclasses)
if self.active and @help_window != nil
update_help
end
end
#--------------------------------------------------------------------------
# * Update Cursor Rectangle
#--------------------------------------------------------------------------
def update_cursor_rect
# If cursor position is less than 0
if @index < 0
self.cursor_rect.empty
return
end
# Get current row
row = @index / @column_max
# If current row is before top row
if row < self.top_row
# Scroll so that current row becomes top row
self.top_row = row
end
# If current row is more to back than back row
if row > self.top_row + (self.page_row_max - 1)
# Scroll so that current row becomes back row
self.top_row = row - (self.page_row_max - 1)
end
# Calculate cursor width
cursor_width = self.width / @column_max - 32
# Calculate cursor coordinates
x = @index % @column_max * (cursor_width + 32)
y = @index / @column_max * 32 - self.oy
# Update cursor rectangle
self.cursor_rect.set(x, y, cursor_width, 32)
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
super
# If cursor is movable
if self.active and @item_max > 0 and @index >= 0
# If pressing down on the directional buttons
if Input.repeat?(Input::DOWN)
# If column count is 1 and directional button was pressed down with no
# repeat, or if cursor position is more to the front than
# (item count - column count)
if (@column_max == 1 and Input.trigger?(Input::DOWN)) or
@index < @item_max - @column_max
# Move cursor down
$game_system.se_play($data_system.cursor_se)
@index = (@index + @column_max) % @item_max
end
end
# If the up directional button was pressed
if Input.repeat?(Input::UP)
# If column count is 1 and directional button was pressed up with no
# repeat, or if cursor position is more to the back than column count
if (@column_max == 1 and Input.trigger?(Input::UP)) or
@index >= @column_max
# Move cursor up
$game_system.se_play($data_system.cursor_se)
@index = (@index - @column_max + @item_max) % @item_max
end
end
# If the right directional button was pressed
if Input.repeat?(Input::RIGHT)
# If column count is 2 or more, and cursor position is closer to front
# than (item count -1)
if @column_max >= 2 and @index < @item_max - 1
# Move cursor right
$game_system.se_play($data_system.cursor_se)
@index += 1
end
end
# If the left directional button was pressed
if Input.repeat?(Input::LEFT)
# If column count is 2 or more, and cursor position is more back than 0
if @column_max >= 2 and @index > 0
# Move cursor left
$game_system.se_play($data_system.cursor_se)
@index -= 1
end
end
# If R button was pressed
if Input.repeat?(Input::R)
# If bottom row being displayed is more to front than bottom data row
if self.top_row + (self.page_row_max - 1) < (self.row_max - 1)
# Move cursor 1 page back
$game_system.se_play($data_system.cursor_se)
@index = [@index + self.page_item_max, @item_max - 1].min
self.top_row += self.page_row_max
end
end
# If L button was pressed
if Input.repeat?(Input::L)
# If top row being displayed is more to back than 0
if self.top_row > 0
# Move cursor 1 page forward
$game_system.se_play($data_system.cursor_se)
@index = [@index - self.page_item_max, 0].max
self.top_row -= self.page_row_max
end
end
end
# Update help text (update_help is defined by the subclasses)
if self.active and @help_window != nil
update_help
end
# Update cursor rectangle
update_cursor_rect
end
end
#==============================================================================
# ** Game Quest -- Mobius
#------------------------------------------------------------------------------
# The class that holds quests. Each instance of Game Quest is used to hold
# one quest.
#==============================================================================
class Game_Quest
#--------------------------------------------------------------------------
# * Class Variables
#--------------------------------------------------------------------------
@@total_quests = 0 # Used to track number of quest objects
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_reader :id # ID
attr_reader :name # Name
attr_accessor :phase # Phase
attr_reader :known # Known status (true / false)
attr_reader :completed # Completed status (true / false)
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize(name, info_array)
@id = @@total_quests
@@total_quests += 1
@name = name
@phase = 0
@known = false
@completed = false
# The info array contains text that corresponds to the current phase
# of the quest. So, you simply need to get the info in the i-th position
# of the array for the i-th phase
@info_array = info_array
end
#--------------------------------------------------------------------------
# * Get Current Info
# Returns text info for the current phase
#--------------------------------------------------------------------------
def get_current_info
@info_array[@phase]
end
#--------------------------------------------------------------------------
# * Discover
# Changes quest state known to true
#--------------------------------------------------------------------------
def discover
@known = true
end
#--------------------------------------------------------------------------
# * Complete
# Changes quest state completed to true
#--------------------------------------------------------------------------
def complete
@completed = true
end
#--------------------------------------------------------------------------
# * to_s
# Returns quest object data as string
# Mostly used for debugging purposes
#--------------------------------------------------------------------------
def to_s
"Quest ID: #{@id}\n" +
"Quest Name: #{@name}\n" +
"Quest Info:\n" +
@info_array.join("\n")
end
end
#==============================================================================
# ** Game_Quests
#------------------------------------------------------------------------------
# This class handles the Game Quest arrays. Refer to "$game_quests" for the
# instance of this class.
#==============================================================================
class Game_Quests
#--------------------------------------------------------------------------
# * Class constants
#--------------------------------------------------------------------------
CREATE_ENCRYPTED = false # Determines encrypted file creation
USE_ENCRYPTED = false # Sets use of encrypted file
QUEST_FILENAME = "Data/QuestData.txt" # Sets unencrypted filename
#--------------------------------------------------------------------------
# * Public Instance Variables
#--------------------------------------------------------------------------
attr_accessor :all_quests # Array of all quest objects
attr_accessor :current_quests # Array of all current quest objects
attr_accessor :completed_quests # Array of all completed quest objects
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize
@all_quests = []
@current_quests = []
@completed_quests = []
setup
end
#--------------------------------------------------------------------------
# * Add Quest - adds a quest object to the all_quests array
#--------------------------------------------------------------------------
def add_quest(quest)
@all_quests.push(quest)
end
#--------------------------------------------------------------------------
# * Sort Quests
# Refreshes the current_quests and completed_quests arrays
# Also sorts them as well as the all quests array by ID's
#--------------------------------------------------------------------------
def sort_quests
# Sort the all_quests array by ID
@all_quests.sort {|a,b| a.id <=> b.id }
# Reset the current and completed quest arrays
@current_quests = []
@completed_quests = []
# Push known and completed quests to their appropiate arrays
for quest in @all_quests
if quest.known and quest.completed
@completed_quests.push(quest)
elsif quest.known
@current_quests.push(quest)
end
end
end
#--------------------------------------------------------------------------
# * Discover Quest - uses quest name or id to change state of quest to known
#--------------------------------------------------------------------------
def discover_quest(name_or_id)
# Check if passed value is ID
if name_or_id.is_a?(Integer)
# Set quest to known
@all_quests[name_or_id].discover
else
# Look up quest using name
quest_to_change = @all_quests.find {|quest| quest.name == name_or_id}
# Set quest to known
quest_to_change.discover
end
sort_quests
end
# Create shorthand name for eventing scripts
alias dq discover_quest
#--------------------------------------------------------------------------
# * Set Phase - uses quest name or id to change phase
#--------------------------------------------------------------------------
def set_phase(name_or_id, phase)
# Check if passed value is ID
if name_or_id.is_a?(Integer)
# Set quest to known
@all_quests[name_or_id].phase = phase
else
# Look up quest using name
quest_to_change = @all_quests.find {|quest| quest.name == name_or_id}
# Set quest to known
quest_to_change.phase = phase
end
sort_quests
end
# Create shorthand name for eventing scripts
alias sp set_phase
#--------------------------------------------------------------------------
# * Complete Quest
# Uses quest name or id to change state of quest to complete
#--------------------------------------------------------------------------
def complete_quest(name_or_id)
# Check if passed value is ID
if name_or_id.is_a?(Integer)
# Set quest to known
@all_quests[name_or_id].complete
else
# Look up quest using name
quest_to_change = @all_quests.find {|quest| quest.name == name_or_id}
# Set quest to known
quest_to_change.complete
end
sort_quests
end
# Create shorthand name for eventing scripts
alias cq complete_quest
#--------------------------------------------------------------------------
# * Setup - Performs first time setup of quest data
#--------------------------------------------------------------------------
def setup
# if true
if CREATE_ENCRYPTED
# Load unencrypted data
Game_Quests.normal_setup
# Create encrypted .rxdata
Game_Quests.create_encrypted
# elsif true
elsif USE_ENCRYPTED
# Load encrypted data
Game_Quests.encrypted_setup
else
# Load unencrypted data
Game_Quests.normal_setup
end
# initialize Game_Quest object data from $data_quests array
for quest in $data_quests
self.add_quest(quest)
end
# Set Main Quest to known
discover_quest(0)
end
#--------------------------------------------------------------------------
# * GQs - Normal Setup
# Class method that intializes normal quest data
#--------------------------------------------------------------------------
def Game_Quests.normal_setup
# Create array of quest data from file
quest_array = File.open(QUEST_FILENAME) {|f|
f.readlines("mobius_quest_break\n\n")}
# Initialize $data_quests array
$data_quests = Array.new
# Create Game_Quest objects from data
for quest_data in quest_array
# Split quest data by paragraph
quest_data_array = quest_data.split("\n\n")
# Remove file delimiter "mobius_quest_break\n\n"
quest_data_array.pop
# Set and remove name
name = quest_data_array.shift
# Initialize info array
info_array = []
# Organize phase info into useable line lengths
for quest_data_line in quest_data_array
new_arr = []
# Split phase info into words
temp_arr = quest_data_line.split
temp_str = ""
for word in temp_arr
# Rejoin words together
temp_str.concat(word + " ")
# When line length is useable, push to new_arr
if temp_str.size >= 35
new_arr.push(temp_str.strip)
temp_str = ""
end
end
# Push leftover string
new_arr.push(temp_str.strip) unless temp_str == ""
# Push phase info to info_array
info_array.push(new_arr)
end
# Push new Game_Quest object to $data_quests array
$data_quests.push(Game_Quest.new(name, info_array))
end
end
#--------------------------------------------------------------------------
# * GQs - Encrypted Setup
# Class method that intializes encrypted quest data
#--------------------------------------------------------------------------
def Game_Quests.encrypted_setup
# load encrypted data
$data_quests = load_data("Data/Quests.rxdata")
end
#--------------------------------------------------------------------------
# * GQs - Create Setup
# Class method that creates encrypted quest data
#--------------------------------------------------------------------------
def Game_Quests.create_encrypted
# save encrypted data
save_data($data_quests, "Data/Quests.rxdata")
end
end
#==============================================================================
# ** Window Quest Info
#------------------------------------------------------------------------------
# This window lists the info for the quests
#==============================================================================
class Window_QuestInfo < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize()
super(200, 0, 300, 384)
self.active = false
self.contents = Bitmap.new(width - 32, height - 32)
self.index = -1
refresh([""])
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh(text_array)
self.contents.clear
self.contents.font.color = text_color(2)
self.contents.font.name=MessageConfig.pbDefaultSystemFontName #line to fix Mac problem
for i in 0...text_array.size
line = text_array[i]
self.contents.draw_text(0, i * 22, 300, 22, line)
end
end
end
#==============================================================================
# ** Window Quest List
#------------------------------------------------------------------------------
# This window lists all currently active/completed quests
#==============================================================================
class Window_QuestList < Window_Selectable
#--------------------------------------------------------------------------
# * Object Initialization
#--------------------------------------------------------------------------
def initialize()
super(0, 0, 200, 384)
@current_quests = [] # Array of current quests
@completed_quests = [] # Array of completed quests
@top_half_size = 0 # Number of rows of current quests
@bottom_half_size = 0 # Number of rows of completed quests
self.active = true
self.index = 0
refresh
end
#--------------------------------------------------------------------------
# * Refresh
#--------------------------------------------------------------------------
def refresh
# Determine total number of rows
@item_max = [@top_half_size + @bottom_half_size, 1].max
if self.contents != nil
self.contents.dispose
end
# Draw bitmap
self.contents = Bitmap.new(200 - 32, row_max * 32)
self.contents.font.color = text_color(2)
self.contents.font.name=MessageConfig.pbDefaultSystemFontName #line to fix Mac problem
# Draw current quests
for i in 0...@top_half_size
quest_name = @current_quests[i].name
self.contents.draw_text(8, i * 32, 200, 32, quest_name)
end
self.contents.font.color = disabled_color
self.contents.font.name=MessageConfig.pbDefaultSystemFontName #line to fix Mac problem
# Draw completed quests
for i in 0...@bottom_half_size
quest_name = @completed_quests[i].name
self.contents.draw_text(8, i * 32 + @top_half_size *
32, 200, 32, quest_name)
end
end
#--------------------------------------------------------------------------
# * Set Quests
#--------------------------------------------------------------------------
def set_quests(new_current_quests, new_completed_quests)
if @current_quests != new_current_quests or
@completed_quests != new_completed_quests
#set new quests
@current_quests = new_current_quests
@completed_quests = new_completed_quests
@top_half_size = @current_quests.size
@bottom_half_size = @completed_quests.size
#call update
refresh
end
end
#--------------------------------------------------------------------------
# * Get Index Info
# Returns the text info from which ever quest is currently highlighted
#--------------------------------------------------------------------------
def get_index_info
# Unless there are no quests
unless @current_quests.empty? and @completed_quests.empty?
# Determine cursor location
if self.index < @top_half_size
# Get selected quest info
@current_quests[self.index].get_current_info
else
# Get selected quest info
@completed_quests[self.index - @top_half_size].get_current_info
end
end
end
end
#==============================================================================
# ** Scene_Quest
#------------------------------------------------------------------------------
# This class performs quest screen processing.
#==============================================================================
class Scene_Quest
#--------------------------------------------------------------------------
# * Main Processing
#--------------------------------------------------------------------------
def main
# Make QuestList Window
@quest_list_window = Window_QuestList.new
# Make QuestInfo Window
@quest_info_window = Window_QuestInfo.new
# Update Game Quests
$game_quests.sort_quests
# Refresh QuestList
@quest_list_window.set_quests($game_quests.current_quests,
$game_quests.completed_quests)
# Execute transition
Graphics.transition
# Main loop
loop do
# Update game screen
Graphics.update
# Update input information
Input.update
# Frame update
update
# Abort loop if screen is changed
if $scene != self
break
end
end
# Prepare for transition
Graphics.freeze
# Dispose of windows
@quest_list_window.dispose
@quest_info_window.dispose
end
#--------------------------------------------------------------------------
# * Frame Update
#--------------------------------------------------------------------------
def update
# Update windows
@quest_list_window.update
new_text = @quest_list_window.get_index_info
@quest_info_window.refresh(new_text)
# When cancel
if Input.trigger?(Input::B)
# Play cancel SE
$game_system.se_play($data_system.cancel_se)
$scene = Scene_Map.new
end
end
end
and then we need to add a couple things so that your updates to your journal are saved and loaded.
this
Code:
$game_quests = Marshal.load(f)
Code:
if cmdContinue>=0 && command==cmdContinue
Same section but under
Code:
elsif cmdNewGame>=0 && command==cmdNewGame
Code:
$game_quests = Game_Quests.new
In PokemonSave under
Code:
Marshal.dump($PokemonStorage,f)
Code:
Marshal.dump($game_quests,f)
Should work fine, let me know if any bugs found.
Only thing I can't figure out how to do is change the windowskin used, it keeps sticking with the default, so let me know if you know how to fix that :)
Important thing to note, once you install these scripts you must start a new game for it to work properly.
No credit to me required, but please give credit to MobiusXVI.
Last edited: