Book/Library Scene
Authors: ForeverZer0
Version: 1.2
Type: Misc Add-on
Key Term: Misc Add-on
IntroductionCalls a scene that will allow the player to read/view books they have collected.
Features
- Easy to configure, text is read from an external text document
- Text is automatically sized for each page
ScreenshotsNone.
Demohttp://www.mediafire.com/?yvgzdoa32uahh7n
Script
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
# Book/Library Scene
# Author: ForeverZer0
# Version: 1.2
# Date: 9.1.2010
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
#
# Version History:
# v. 1.0 9.1.2010
# - Original version
# v. 1.1 9.3.2010
# - Added option for full-screen text
# - Made the page number window slightly wider
# v. 1.2 9.25.2010
# - Added option to simply call scene with the book ID argument and have
# that book already displayed.
#
# Introduction:
# Calls a scene that will allow player to read through books that they have
# collected.
#
# Features:
# - Easy to configure, text is read from an external text document
# - Text will automatically fit itself into the proper size for the window
# width and pages, regardless of font or font size.
#
# Instructions:
# 1. Fill in the configuration below.
# 2. Create a new folder within the "Data" folder, and name it "Books".
# 3. Within this folder, create simple text documents (.txt).
# 4. Name them EXACTLY as you did for its respective title (below).
# 5. Turn word-wrap OFF.
# 6. Create as large as document as you would like, but only break to a new
# line in between paragraphs, not when the text reaches the edge of the
# window. Every time a new line is started, it guarantees that the current
# line will start on a new line in the scene, regardless of the font size.
#
# Use the following Script Calls:
# Books.unlock(BOOK_ID)
# - Unlocks the book with BOOK_ID
# $scene = Scene_Book.new
# - Calls the Book scene.
# $scene = Scene_Book.new(BOOK_ID)
# - Calls the book scene. The book with BOOK_ID will already be displayed.
# This will also disable the book list feature. The book does not have
# to be unlocked to call this way.
#
# Credits/Thanks:
# ForeverZer0, for the script
# Blizzard, for the "slice_text" method
#=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
module Books
#===============================================================================
# BEGIN CONFIGURATION
#===============================================================================
RETURN_SCENE = Scene_Map
# Class of the scene that the game return to after you exit the book scene.
SORT_BY_ID = true
# If true, the books will be listed in order of their Book ID, else they will
# be listed in the order they were aquired.
PAGE_TURN_SE = ['046-Book01', 80, 100]
# Set to the name of the SE that will be played when a player turns a page.
# Set to nil to disable this feature. [FILENAME, VOLUME, PITCH]
FULLSCREEN_TEXT = false
# If true, the text window will extend over the book list and take up the
# entire screen (minus the header).
def self.title(book_id)
# Here is where you define the labels used for the books. The titles will
# be used as the filename to be loaded as well.
# when BOOK_ID then 'TITLE'
return case book_id
when 0 then 'Genesis'
when 1 then 'Exodus'
when 2 then 'Leviticus'
when 3 then 'Numbers'
when 4 then 'Deuteronomy'
end
end
#===============================================================================
# END CONFIGURATION
#===============================================================================
def self.unlock(book_id)
# Adds the Book ID to the array.
unless $game_system.books.include?(book_id)
$game_system.books.push(book_id)
# Sorts the array by the Book IDs if so configured.
if SORT_BY_ID
$game_system.books.sort!
end
end
end
def self.get_text(book_id)
# Opens a text document, makes an array whose elements consist of the lines
# of the document, and returns it.
filename = 'Data/Books/' + title(book_id) + '.txt'
begin
file = File.open(filename, 'r')
rescue
raise("Error occured while attempting to open the following file:\n\n" +
"\t#{filename}\n\n" +
"Please make sure that the file exist before you continue.")
end
book = []
file.each_line {|line| book.push(line)}
file.close
return book
end
end
#===============================================================================
# ** Game_System
#===============================================================================
class Game_System
attr_accessor :books # Array: Stores the IDs of all unlocked books.
alias zer0_book_init initialize
def initialize
zer0_book_init
@books = []
end
end
#===============================================================================
# ** Scene_Book
#===============================================================================
class Scene_Book
def initialize(book_id = nil)
@book_id = book_id
@no_list = @book_id != nil
end
def main
# Create a variable that is set to the window width (depending on config)
@window_width = Books::FULLSCREEN_TEXT ? 640 : 512
@window_width = 640 if @no_list
# Create a blank dummy window.
@dummy_window = Window_Base.new(128, 64, 512, 416)
# Create Help_Window to display the book titles.
@help_window = Window_Base.new(0, 0, 448, 64)
@help_window.contents = Bitmap.new(416, 32)
# Create the page number window
@page_window = Window_Base.new(448, 0, 192, 64)
@page_window.contents = Bitmap.new(160, 32)
# Create the window that text will be displayed on.
x = @window_width == 640 ? 0 : 128
@text_window = Window_Base.new(x, 64, @window_width, 416)
@text_window.contents = Bitmap.new(@window_width - 32, 384)
@text_window.z = @help_window.z + 20
@text_window.visible = false
# Make a copy of the Books array.
@books = $game_system.books.clone
# Create instance variable for updating the text window.
@update_text = false
# Make list of all books, if possible, else make list empty.
if @books.empty?
help_string = 'No books are currently available.'
@command_window = Window_Base.new(0, 64, 128, 416)
else
help_string = 'Whick book would you like to read?'
@titles = []
@books.each {|book_id| @titles.push(Books.title(book_id))}
@command_window = Window_Command.new(128, @titles)
@command_window.height, @command_window.y = 416, 64
end
# Display text on the help screen
@help_window.contents.draw_text(0, 0, 416, 32, help_string, 1)
# Create array that holds all the windows
@windows = [@dummy_window, @help_window, @text_window,
@command_window, @page_window]
if @no_list
@page_number = 1
$game_system.se_play($data_system.decision_se)
@help_window.contents.clear
@help_window.contents.draw_text(0, 0, 416, 32, Books.title(@book_id), 1)
@command_window.active, @update_text = false, true
compile_text
@text_window.visible = true
end
Graphics.transition
# Main loop
loop {Graphics.update; Input.update; update; break if $scene != self}
Graphics.freeze
@windows.each {|window| window.dispose}
end
def update
# Update windows.
@windows.each {|window| window.update}
if @command_window.is_a?(Window_Command) && @command_window.active
update_command_window
return
elsif @update_text
update_text_window
return
end
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Books::RETURN_SCENE.new
end
end
def update_command_window
if Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
$scene = Books::RETURN_SCENE.new
elsif Input.trigger?(Input::C)
@page_number = 1
$game_system.se_play($data_system.decision_se)
@book_id = @books[@command_window.index]
@help_window.contents.clear
@help_window.contents.draw_text(0, 0, 416, 32, Books.title(@book_id), 1)
@command_window.active, @update_text = false, true
compile_text
@text_window.visible = true
end
end
def update_text_window
if Input.trigger?(Input::LEFT) || Input.trigger?(Input::RIGHT)
old_page = @page_number
@page_number += Input.trigger?(Input::LEFT) ? -1 : 1
@page_number = [[@page_number, @pages.size].min, 1].max
# Play SE if configured as such.
if old_page != @page_number && Books::PAGE_TURN_SE != nil
se = Books::PAGE_TURN_SE
audio = RPG::AudioFile.new(se[0], se[1], se[2])
$game_system.se_play(audio)
end
# Refresh the window
refresh_text
elsif Input.trigger?(Input::B)
$game_system.se_play($data_system.cancel_se)
if @no_list
$scene = Books::RETURN_SCENE.new
else
@update_text, @command_window.active = false, true
@text_window.visible = false
end
end
end
def compile_text
# Gets an array whose elements are the lines of the text document.
text = Books.get_text(@book_id)
# Iterate over each line of the text. Break each line up into segments that
# will fit into the window, then add them all together.
@pages, lines = [], []
text.each {|paragraph|
segment = @text_window.contents.slice_text(paragraph, @window_width - 32)
segment.each {|line| lines.push(line)}
}
# Organizes the lines (12 per page) into pages.
page_numbers = (lines.size / 12) + 1
(0...page_numbers).each {|i| @pages[i] = lines[i*12, 12]}
refresh_text
end
def refresh_text
[@text_window.contents, @page_window.contents].each {|bitmap| bitmap.clear}
# Displays the lines of the current page onto the window.
page = @pages[@page_number - 1]
page.each_index {|i|
@text_window.contents.draw_text(0, i*32, @window_width - 32, 32, page[i])}
# Set the proper text to the page screen.
string = "Page #{@page_number}/#{@pages.size}"
@page_window.contents.draw_text(0, 0, 160, 32, string, 1)
end
end
class Bitmap
# The slice_text method was created by Blizzard. I take no credit for it.
def slice_text(text, width)
words = text.split(' ')
return words if words.size == 1
result, current_text = [], words.shift
words.each_index {|i|
if self.text_size("#{current_text} #{words[i]}").width > width
result.push(current_text)
current_text = words[i]
else
current_text = "#{current_text} #{words[i]}"
end
result.push(current_text) if i >= words.size - 1}
return result
end
end
InstructionsSee script.
CompatibilityNo known issues.
Credits and Thanks
- ForeverZer0, for the script
- Blizzard, for the "slice_text" method
- Taiine , for requesting it
Author's NotesPlease let me know if any bug/issues are found.
Enjoy!
Oh my god this is fantastic! <3 No mess, no hassle, so easy to use! Best of no NO ANNOYING FORMATTING OF THE TEXT FILES! <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3 <3
One little little extra request? An added option to select a book to read, with out the little side menu? Like find a book, pick it up and you read, with just the title, pages, and the text? Then can have it as it currently is as a list to go back to reread past books you already found.
Oh and.. is the text size thing really part of it? :P I made the mistake of going SIZE 6 and like holy molly that's tinny, and changing all the game text. It was very much so silly XD
I can make a quick mod for you to change the display.
As for the text size thing, that was just to show how the page will format to whatever the font and size are. I wouldn't use size 6 either. This will make it so that the text always is formatted correctly, even if the player has control of the font and font size. The only drawback is that the text cannot be pre-formatted and stored, which causes that half a second of lag when you first select a book and it needs to open the text document, etc.
A bit off topic, but Zer0, you should make all the list of scripts in your signature actual links to said scripts.
Dats convenient.
I think all scripters should have that! (cept maybe Blizzard, cuz he's got...a LOT.)
:^_^':
http://www.chaos-project.com/index.php?option=com_scriptdatabase&view=scriptdatabase&Itemid=29
Good idea about the sig. I think it needs updated anyway. ;)
That mod will be swell. :3
So fare I have seen no bugs even when tossed in my script computability testing game, it works fine with everything I use.
* Updates to Version 1.1 *
Okay try that out. It now has the option of how you want the text window to be displayed.
Nice once again! However don't think you fully grasped what I asked. :^_^':
Like to be able to read a book with out going through the list. Like going to a library, picking a book and instantly going to the book text and reading. Then (for me anyway) the list could be of books you've already read to reread again... or not use the list scene at all and go back to each book in game to reread it.
Any progress on this?
I think this was forgotten about. :hm:
Quote from: Taiine on September 20, 2010, 01:04:10 pm
I think this was forgotten about. :hm:
Patience, grasshopper. This is not on my list of high priorities.
Very, very nice one! Thanks! Maybe port it to VX too? There's no book scripts for VX if I'm not mistaken, and I sure could use one..
(Why do I use VX? Long story... :/ )
Okay, I updated to 1.2
You can now just call the scene with an argument that will have the desired book all ready to go, without having any book list. The other option is still there,
Use this to call the scene:
$scene - Scene_Book.new(BOOK_INDEX)
Or just ignore the argument and it will open with the list displayed.
Hey, this is a really epic script!
But, I was wondering if there was something in the script I could edit to make a picture display at the bottom of the page, that varies from each book, any ideas?
It should be simple I think :)
something like:
if 0 then $game_screen.pictures[3].show(1, 1, 1, 1, 1, 1, 1, 1)
But I dunno...
Hey FZ0, Can I make a small added request with this?
I'd like to be able to change the font color of the text as well as the font used. I tried it myself, but each time I try it throws back an error.
Rather with
@text_window.font.color
@self.contents.font.color
same with font type.
yet
@text_window.windowskin
worked just fine to change the window skin O.o;;;
The correct syntax would be :
@text_window.contents.font.name = 'FONTNAME'
@text_window.contents.font.size = SIZE
@text_window.contents.font.color = Color.new(R, G, B, ALPHA)
The window is a sprite, which has no methods for font, but "contents" refers the sprite's bitmap, which does.
oh look, more lazy mods :V
I just went through the script section and found more than 10 script topics that haven't been moved. O_o
they are all topics that don't have the template applied I take it? because I couldn't find these topics.
Zer0, I'm sorry were gonna hijack your thread and discuses moderation of the RGSS section now :V:
LMAO!
Actually only 2 of them. The rest had a proper template applied. There were even a couple of F0's topics. xD
Hijack away. I'm easy going and don't mind.
Hello,
Thanks for creating this script, spent quite a bit of time looking for such a script before stumbling onto this one. Just got a few questions.
A couple of my book titles are pretty long and such the text becomes pretty scrunched up, I've thought of 2 possible solutions but seeing how I'm pretty new at scripting haven't been able to incorporate them.
Method 1: If the book name is longer then X characters then a "..." is added.
Method 2: Creating a similar function as FULLSCREEN_ENTRY but for the book names.
In a future version could you add the ability to include chapters? Where when you click the desired book a sub-menu opens allowing you to select which chapter? Also if your able to name the chapters that would be great as well.
Again, thanks for the script.
Yes, thank you ForeverZer0 for this awesome script. I agree with Elemental Crisis about the chapters addition with the ability to name chapters. I may try to tweak this script (I am still learning RGSS lol) to add that function for my own use. Thanks again!