Page 1 of 7

Encyclopaedia / Bestiary Framework

Posted: Tue Feb 11, 2014 8:37 pm
by Human Bolt Diary
Update: 11/25/2017

In response to a lot of the difficulties people were having, I've been working on a version 2 of the Encyclopaedia Framework. I've kept most of the core concepts similar, but this is a hard break for quite a bit of the behaviour. Overall, it should be much more user-friendly and easier to customize.

The beta for v2 is available at:
https://github.com/jsfehler/renpy-encyc ... a/releases

and documentation at:
http://renpy-encyclopaedia.readthedocs. ... index.html

Getting v2 out of beta is going to take a lot more manual testing (I've tested it a lot, but I'm sure there's things I've missed.), more work on the documentation, and more unit tests.

The information below is outdated, but kept for archival purposes:

The following is a prototype for an Encyclopaedia and/or Bestiary. I've done my best to split up the data management and screens, but using and customizing this will still require a tiny bit of python knowledge. My knowledge of screen language isn't that advanced, but nothing in the layout outright explodes.

While I've tried to be rigorous in finding outright bugs, a lot of the logic I've used to get everything working may not ultimately be the best way to go about it, or just simply sort of clunky. I hope that posting it here will invite people to try it out, break it apart, and report on their results.

That said, everything's working fine on my end and I hope it works on yours.

Features:
-Sorting entries by Entry Number, A to Z, Z to A, or by Subject
-Entries can have multiple pages
-An Image can be displayed next to an entry, or not
-Lock entries, then Unlock them over the course of the game
-Unread Entries are tagged.
-Locked entries can be displayed as "???" or outright hidden
-Access from the main menu or during gameplay

Update 10/26/2014:
-Major code refactoring under the hood.
-Flags for status can be generated dynamically.

Update 3/13/2014:
-Bug Fix: Can now start an Encyclopaedia in Z to A sorting
-Screens simplified and rearranged a bit
-An Entry/Sub-Entry's Text can now be single string or list of strings. (Useful to make paragraphs.)
-Tweaks in how entry_text variable is processed to support paragraphs
-Encyclopaedia "showLocked" variable renamed "showLockedButtons"
-Encyclopaedia "showLockedEntry" variable added. Determines if locked entry pages can be viewed or not.
(showLockedButtons and showLockedEntry are independent and compatible, but personally, the user experience will be weird if showLockedEntry but not showLockedButtons)
-Viewable Locked entry page shows generic name and text. Can be modified (Default is "???" in both cases)
-Viewable Locked entry page shows tinted image. Tint amount can be changed or the locked image can be an entirely different image.
-Demo project and attached files below updated

Update 2/20/2014:
-Multiple encyclopaedias can now be created in the same project
-Refactored code, fixed notes, should be more user friendly now
-Fixed bug involving sub-page number not resetting
-Fixed bug involving entries not sorting into the correct subject when hiding locked entries
-"new!" status is restored when an entry gets a new sub-entry
-Added show/hide locked entries button
-Percentage of the Encyclopaedia unlocked can be displayed now
-Demo project and attached files below updated

I've included a demo game to show everything in action. The user experience suffers a bit to show off everything, but this also helps ensure no feature bugs out another when used. The Encyclopaedia can be accessed from the Main Menu or via button in-game.

To use the Encyclopaedia in your project, drop encyclopaedia.rpy into your project's game folder. Refer to the included enc_data.rpy and script.rpy to see how entries and the screens are created.

Limitations:
-The Encyclopaedia uses Persistent Data to save the Unread and Locked flags. Regardless of save game, once it's open and read, that's it.
-Read entries only save their status after exiting the Encyclopaedia. If the program is closed before exiting, the Unread status returns.
-Exiting the Encyclopaedia sets the sorting to by number. This is necessary to make sure the Unread flags save correctly.

Basic Usage example:

Code: Select all

init python:
 e = Encyclopaedia()
 e.addSubjects("Subject 1", "Subject 2", "Etc")
 
 entry1 = EncEntry (number=1, name="Title", text="Entry Text", subject="Subject 1", status=False, locked=False, image= "directory/image.jpg")

 e.addEntry(entry1)
Classes:
Encyclopaedia(sortingMode = "Number", showLockedButtons=False, showLockedEntry=False)
Holds entry objects and organizes how they're displayed.
sortingMode - Determines which type of sorting is used when an Encyclopaedia is first opened. Can be "Number", "A to Z", "Z to A", "Subject".
showLockedButtons - If True, the buttons for locked entries will be visible in the entry list.
showLockedEntry - if True, locked entries will be viewable. Locked entries, even when viewed, hide data from the player.

EncEntry(number=0, name="Entry Name", text="Entry Text", subject=None, status=None, locked=False, image=None, locked_image=None)
Holds the data for an individual entry.
number - The entry's number in an Encyclopaedia's list. Used for sorting.
name - The title of an entry. Must be a string.
text - The text of an entry. Can be a string or a list of strings.
subject - An entry's subject. Used for sorting by subject.
status - If None or False, Entry is considered to have not been viewed. If viewed/unviewed status is shown to player, must be persistent variable that is a Boolean or status will reset every time the project is started.
locked - If not False, must be a persistent variable that is a Boolean or else entry will lock every time the project is started.
image - Image associated with entry.
locked_image - Image to be displayed if entry is locked and locked entries are viewable. If None, will be a tinted version of image.

Re: Encyclopaedia / Bestiary Framework (Functional Prototype

Posted: Mon Mar 03, 2014 6:00 am
by Coyotl
Thanks for working on this! It's something I was putting off until much later in development. I'm sure this will help tremendously, and I'll be following your work closely.

Re: Encyclopaedia / Bestiary Framework

Posted: Fri Mar 14, 2014 1:30 pm
by Human Bolt Diary
Coyotl wrote:Thanks for working on this! It's something I was putting off until much later in development. I'm sure this will help tremendously, and I'll be following your work closely.
Thanks, I hope you find it useful.

The latest version is "feature complete" since I can't think of much more to add, but if there's any options not included that you're interested in I can look into adding it.

Re: Encyclopaedia / Bestiary Framework

Posted: Sun Oct 26, 2014 6:21 pm
by Human Bolt Diary
I've updated the files to a new version. The code's been rewritten a bit but should retain full compatibility with the older versions. It's mostly just cleaning up based on my increased Python knowledge. The biggest change is that the flags for the "New!" status can be generated dynamically.

The older version used a pretty gross way to make those flags:

Code: Select all

try:
  persistent.enc00_new = persistent.new_dict["new_00"]
  persistent.enc01_new = persistent.new_dict["new_01"]
  persistent.enc02_new = persistent.new_dict["new_02"]
  persistent.enc03_new = persistent.new_dict["new_03"]
  persistent.enc04_new = persistent.new_dict["new_04"]
  persistent.enc05_new = persistent.new_dict["new_05"]
  persistent.enc06_new = persistent.new_dict["new_06"]
  persistent.enc07_new = persistent.new_dict["new_07"]
 except TypeError:
  pass
 
 #The keys must all have a prefix+number. "new_0" and "number" in this case.
 persistent.new_dict = {
 "new_00" : persistent.enc00_new,
 "new_01" : persistent.enc01_new,
 "new_02" : persistent.enc02_new,
 "new_03" : persistent.enc03_new,
 "new_04" : persistent.enc04_new,
 "new_05" : persistent.enc05_new,
 "new_06" : persistent.enc06_new,
 "new_07" : persistent.enc07_new
 }
Exploiting persistent data is still the way it works, but having to declare each flag is going to be painful if an Encyclopaedia has dozens or hundreds of entries. Now, that's all been stuck under the hood. All you need to do is state how many entries there will be:

Code: Select all

encyclopaedia.setPersistentStatus(entries_total=7, master_key="new", name="new")

Re: Encyclopaedia / Bestiary Framework

Posted: Mon Oct 27, 2014 3:56 pm
by yon
I just checked out the new .rpy file, and wow. You really reworked this whole thing. I'll probably need a little while to re-familiarize myself with it, but I've got a good feeling about this update.

Re: Encyclopaedia / Bestiary Framework

Posted: Sun Nov 02, 2014 6:49 pm
by yon
Could you post a zip file with the whole thing, actually? I remember there being one before, for 1.3 and 1.4, but I don't seen anything like that now. Am I missing something?
I tried to make a copy of one of the previous projects and overwrite the old files with the new attachments, but it doesn't seem to work if I try that.

Re: Encyclopaedia / Bestiary Framework

Posted: Tue Feb 10, 2015 2:11 pm
by Meinos Kaen
Oh my god, thank you thank you thank you for this. Not only does it work wonderfully and can add more dept to games rich of lore, but it also solved another unrelated problem for me.

Re: Encyclopaedia / Bestiary Framework

Posted: Wed Feb 18, 2015 7:56 am
by Luxliev
That's great piece of code thanks for it. Please keep it updated I also have one question can you update already read entries? fe.

entry one = You met this guy at park.

later in game you get update

entry one (updated) = This guy name is John I met him at park first.

Re: Encyclopaedia / Bestiary Framework

Posted: Sat Apr 18, 2015 12:40 pm
by Laiska
Luxliev wrote:That's great piece of code thanks for it. Please keep it updated I also have one question can you update already read entries? fe.

entry one = You met this guy at park.

later in game you get update

entry one (updated) = This guy name is John I met him at park first.
I'm curious about this as well - anyone?

Also the demo script doesn't run properly because it doesn't include the images =P

Re: Encyclopaedia / Bestiary Framework

Posted: Tue Apr 21, 2015 10:08 pm
by Human Bolt Diary
Off the top of my head, if you create the entry data in an init block, it'll get set each time the game starts. If you create the entry data outside, it should save if you update it. So you could do something like:

Code: Select all


a_entry = "Blah blah blah"

a "Hamburgers? Love 'em."

python:
    a_entry = "Blah blah blah. Loves hamburgers."


However, creating the entry data outside an init block may cause bugs if you want to be able to open the encyclopaedia from the main menu. Now that I think about it, I haven't tested what happens if you try to open an Encyclopaedia that has zero entries. If it crashes, I could probably fix it over a weekend.
Laiska wrote:
Luxliev wrote:That's great piece of code thanks for it. Please keep it updated I also have one question can you update already read entries? fe.

entry one = You met this guy at park.

later in game you get update

entry one (updated) = This guy name is John I met him at park first.
I'm curious about this as well - anyone?

Also the demo script doesn't run properly because it doesn't include the images =P

Re: Encyclopaedia / Bestiary Framework

Posted: Wed May 11, 2016 6:28 pm
by LabaroDD
Hello there!
I have a question about using this awesome encyclopaedia - how can I customize it? I'm pretty newbie in coding and I just can't get how I should to change the text style, I mean, size, color, etc. I tried to use init python to create a style of encyclopaedia_list, but there were no changes. Sorry, I'm so stupid ><
I really, really need help.

Re: Encyclopaedia / Bestiary Framework

Posted: Thu Jun 16, 2016 12:27 pm
by Otoke_Neko
LabaroDD wrote:Hello there!
I have a question about using this awesome encyclopaedia - how can I customize it? I'm pretty newbie in coding and I just can't get how I should to change the text style, I mean, size, color, etc. I tried to use init python to create a style of encyclopaedia_list, but there were no changes. Sorry, I'm so stupid ><
I really, really need help.
Try doing this: "{color=hexcode} text {/color}
Of course, I didn't use the encyclopedia in this topic, but it'll probably still work.

Re: Encyclopaedia / Bestiary Framework

Posted: Fri Sep 02, 2016 3:48 pm
by tictactofu
This is exactly what I was looking for - thank you!

Is there a way to make dialogue function as a button to pull up the encyclopaedia? Like, to make it so that if a character says "Hi, my name is John," you can press John to open his entry. Been fussing with it for a while, but I know nothing and have gotten nowhere :?

Re: Encyclopaedia / Bestiary Framework

Posted: Fri Jan 27, 2017 4:58 am
by noeinan
tictactofu wrote:This is exactly what I was looking for - thank you!

Is there a way to make dialogue function as a button to pull up the encyclopaedia? Like, to make it so that if a character says "Hi, my name is John," you can press John to open his entry. Been fussing with it for a while, but I know nothing and have gotten nowhere :?
I do not know much about this, but I would guess maybe making a post in the main questions section of the forum, and ask like... "how to turn a word in dialogue into a button"

On a separate note, I really appreciate this code and have been keeping a copy in my resources file in case I ever needed it. Recently, I started making a game where I have need of an encyclopedia, but I wanted to make it so that sub-entries could have a slightly different picture.

I am having a really hard time finding in the code why the image doesn't change when you click to the next sub-entry page. I added an image to where I've defined the sub-entry:

Code: Select all

    #When creating sub-entries, the main entry is considered page 1, always start at 2
    en1_2 = EncEntry(2,"Crown Flower",lorem2,"Herb Identification", locked=False, image=en1_2_image)
But when you click for the next page, the image stays the same. I haven't been able to figure out how to make it change. I can find where the image appears on the screen:

Code: Select all

if encyclopaedia.getEntryData()[1].hasImage: #If the entry or sub-entry has an image, add it to the screen  
But the image changes for regular entries and not sub-entries. I tried copying parts of the ChangeEntryAction into the ChangePageAction, but even if I changed the variable names to match sub-entry, all that did is make the Next Page button change the entry instead...

Code: Select all

    class ChangeEntryAction(EncyclopaediaEntryAction):
        """  
        Scroll through the current entry being viewed. 
        Used by Encyclopaedia's PreviousEntry and NextEntry functions
        """    
        def __init__(self, encyclopaedia, direction, block,*args,**kwargs):  
            self.enc = encyclopaedia
            self.block = block #If the button is active or not
            self.dir = direction  #Determines if it's going to the previous or next entry 
  
        def __call__(self):
            if self.block == False:
                self.enc.setEntryData(self.enc.current_position+self.dir)
 
                if self.enc.showLockedEntry == False:
                    self.enc.unlocked_entries[self.enc.current_position+self.dir][1].status = True 
                    given_text = self.enc.unlocked_entries[self.enc.current_position + self.dir][1].getText()
    
                else: 
                    self.enc.all_entries[self.enc.current_position+self.dir][1].status = True   
                    given_text = self.enc.all_entries[self.enc.current_position + self.dir][1].getText()
 
                self.enc.entry_text = self.string_to_list(given_text)
    
                self.enc.current_position += self.dir
      
                self.enc.sub_current_position = 1 #When changing an entry, the sub-entry page number is set back to 1
                renpy.restart_interaction()
    
        def get_sensitive(self):
            if self.block:
                return False
            return True 
 

    class ChangePageAction(ChangeEntryAction):
        """Change the current sub-entry being viewed."""        
        def __init__(self, encyclopaedia, direction, direction2, block,*args,**kwargs):
            super(ChangePageAction,self).__init__(encyclopaedia, direction, block,*args,**kwargs)

            self.dir1 = direction
            self.dir2 = direction2

        def __call__(self):
            if self.block == False: 
                given_text = self.enc.getUnlockedEntry(self.enc.current_position).getSubEntry(self.enc.sub_current_position + self.dir1)
   
                self.enc.entry_text = self.string_to_list(given_text)
                
                self.enc.sub_current_position += self.dir2
    
                renpy.restart_interaction()
As far as I can tell, both entries and sub-entries fall under the class EncEntry, so there shouldn't be any difference between how they are displayed/which ones show a picture and which don't. Or at least I can't find the code that controls this. Any advice on this would be much appreciated!

Re: Encyclopaedia / Bestiary Framework

Posted: Sun Jan 29, 2017 7:34 pm
by LabaroDD
Here is the way to disable sorting?

UPD
Ah, I found it myself! ^^"