QuestManager for Ren'PY
A downloadable tool
About
QuestManager is a framework specialized in managing quests and events for Ren'Py. Create and manage quests for your game with powerful tools that limit the amount of code for your project. The framework is easily customizable and suitable for novice programmers.
You can use it for:
- Create quests and events (with a name and ID).
- Classify these quests and events into categories (make a To Do list).
- Group the categories into chapters allowing you to divide your game into different chapters (like a book or a movie by Q. Tarantino )
- Assign a "status" to each quest (hidden, unlocked, in progress, completed, done, cancelled, failed)
- You can trigger events depending on the progress of a certain quest (start a dialog if a quest is completed, start a dialog if all quests of a category are completed, move to another chapter if all quests of the chapter are completed, etc.)
- Included are many functions to sort and organize your quests within your game.
- A 100% customizable diary interface.
- Free and OPenSource!
OS: Window, Mac Linux, Android
How to install the framework in your game
Adding the framework in your game
- Download the framework with the download button at the end of this page.
- Unzip the QuestManager.zip file to your home.
- Go to the QuestManager file and copy the questmanager folder
- Past it into game folder of your project
Activating the framework in your script
To use the framework you must initialize it in your game code !
Open the main script of your game where the start label is located. Usually this label is located in the script.rpy file
- In your script.rpy file add the following line before label start:
default quest = Manager()
Displaying the diary screen
You can display the log at any time by adding the following code anywhere between your dialogs:
show screen diary
Example:
show screen diary_open_btn
You can customize the button by creating new background image or in the questmanager/gui.rpy file.
Getting Started
Create a new quest
To create a new quest you must follow the following syntax:
Quest("id", "title", "category", "state")
or if you allow the Ren'Py translation
Quest("id", _("title"), _("category"), "state")
- The id is a string not displayed in the game. It allows the algorithm to find a quest in the chapter. It must be unique for each quest.
- The title of the quest is displayed in game. It is only meant to be displayed in the game. The algorithm does not use the title. The title must be contained between _() to allow renpy to do translations (don't forget the underscore before the parenthesis)
- The category is also displayed in-game and is also used by the algorithm to rank the quests. It is also a string contained between _() for the translation
- The state is a string not displayed in game. The default state is "pending" but you can optionally add it if you want another default state.
By default when you create a new quest, it will be in the "pending" state and hidden with ??? in the diary. You can modify this default state by adding a new state in string form
List of all the states
"pending" | Default state! The quest is posted in the diary but the text is hidden by ??? |
"unlocked" | The quest is displayed in the diary. |
"in progress" | The player is doing the quest. |
"completed" | The player has completed the quest but must return to the Non-Player Character to validate it. |
"done" | The quest is over. |
"canceled" | The quest is cancelled and the player cannot start it again (it is removed from the chapter). |
"failed" | The player has failed to complete his quest. |
You can customize state display in the questmanager/gui.rpy file
Exemple:
Create a new chapter
Chapters are arrays that contain all the quests that the player must complete. You can create a single chapter for your entire game. But if your game is very long, we recommend you to create several chapters like in a book, so that the player can better find his way through the game.
All chapters must be declared after the default quest = Manager() line and before the start label !
your_chapter = (your_quest1, your_quest2, your_quest3)
/!\ Don't forget the commas between the quests
Example:
chapter01 = ( Quest("id01", _("Introduction"), _("General")), Quest("id02", _("First dialog"), _("General")), Quest("id03", _("New category"), _("Category 1")), )
Functions to manage your quests
The following functions allow you to manipulate your quests. You can test their status, whether they are completed or not, trigger actions and dialogs depending on the player's progress in their quests, etc.
You can add them directly after your characters' dialogues. Don't forget to add the $ sign before each function.
Loading and deleting chapter into the manager
- Load the chapter into the manager memory.
$ quest.load(chapter_name)
- Delete the chapter from the manager memory.
$ quest.free()
Functions to do some tests
These different functions allow you to perform actions according to the progress of the quests. They are useful to start a dialogue or an action when the player talks to a npc.
- Return True if the category exists in the chapter
$ quest.exists("quest_id")
- Return the category
$ quest.is_in("quest_id")
- Return True if the ID has the right state
$ quest.is_state("quest_id", " quest_state")
- Return True if all the events of a category are done
$ quest.is_category_over("your_category")
- Return True if all the events from all the categories into the chapter are done
$ quest.is_chapter_over()
Some functions to change the state of quests
The following functions allow you to manipulate the status of quests. For example, when the player has completed a quest, you can use these functions to validate the current quest and unlock the next quests.
- Check if the event has the right state, otherwise it is updated
$ quest.check("quest_id", "quest_state")
Example
The quest.update() function is a little bit tricky to use !
The update function allows you to manage several quests at the same time. It is very powerful but can be quite complicated to use for beginners.
Its syntax is as follows:
$ quest.update(id="", state="", unchanged = [], category="")
Yes, it looks terrible, but I will explain how it works ;)
Imagine you have a category with 10 quests. You can handle these quests in different ways.
- changing all the quest state from the first quest to the target id
## example $ quest.update("quest07", "unlocked")
>> All the quest from quest01 to quest07 are unlocked
- Changing the state from a quest to another
## example $ quest.update(("quest02", "quest05"), "unlocked" )
>> All the quests from the number 2 to the 5 are unlocked
- Changing the state from a quest to another but the last one has a different state than the previous one.
## example $ quest.update(("quest02", "quest05"), ("completed", "unlocked"))
>> All the quests from the number 2 to the number 4 are completed and the number 5 is unlocked
- Changing the state from a quest to another but you can exclude one state.
## example $ quest.update(("quest02", "quest05"), ("completed", "unlocked") , ["failed"])
>> All the quests from the number 2 to the number 4 are completed and the number 5 is unlocked but if a quest is failed it is not updated.
- Changing the state from a quest to another but you can exclude several states.
## example $ quest.update(("quest02", "quest05"), ("completed", "unlocked"), ["failed", "completed"])
==> All the quests from the number 2 to the number 4 are completed and the number 5 is unlocked but if a quest is failed or completed it is not updated.
- Update all quests in a category but exclude those with a certain state.
## example $ quest.update(category="my_category" , state="completed", unchanged= ["failed", "completed"])
>> All the quests in the category my_category are updated to competed but if a quest is failed or completed it is not updated.
Adding or removing categories from the chapter
You can add or remove categories or quests during the game. But when a chapter is freed it returns to its original state.
- Adding a new category into the chapter during the game (The added categories will not be stored when the chapter is freed)
$ quest.add(your_new_quest)
- Adding multiple quests
$ quest.add([your_quest01, your_quest02, your_quest03])
example:
$ quest.add([ Quest("intro01", _("Add an event 1"), _("Introduction")), Quest("intro02", _("Add an event 2"), _("Category")), ])
- Removing a category from the chapter
$ quest.remove("your_category_name")
Customize
You can easily customize the diary interface. Open the questmanager/gui.rpy file.
The code is commented to allow you to easily modify it. You can set the number of categories and quests that should be displayed on the left page and on the right page. You can change the fonts, text size, style of each state, etc.
Lastly...
If you have any question, feel free to ask me in comments ;)
Status | In development |
Category | Tool |
Rating | Rated 5.0 out of 5 stars (6 total ratings) |
Author | NerdChickenGames |
Tags | framework, Management, Ren'Py |
Development log
- Rename exist() by exists() with a "S" at the endMar 31, 2022
- QuestManager-0.1.1Aug 28, 2021
Comments
Log in with itch.io to leave a comment.
Thx it works amazing. If I want to add two more sub-classes, such as description and requirement, where else do I need to change in the screens?
I only have 2 missions so far, this is what I have:
Hi, how can I add more categories on the left page? I have put this in the gui file, defines left_page = {( ("General"),("Categoria1"),)} but it appears on the right page
Wondering this myself...
By which I mean it appears on both the left and right when I do it
Hello everyone,
how can I change the path of the questmanager folder?
I tried that code below but it doesn't work.
Code:
from myfolder.questmanager.engine.classes import Quest
Old path: game/questmanager
New path: game/myfolder/questmanager
Has anyone solved this before?
Thank you 🙏
Hello there! I hope you are doing excellent, and let me tell you that I absolutely love this framework!
I have a quick question. Is there a way to completely hide quests if they are in a specific state? I've modified the screen to not show any quests under "pending" status, however as you can see in my screenshot they are still kinda there, but they are just a blank space, and if you scroll down most of it would be just blank spaces. My guess is that it has to do with how the Quest and Manager classes work, but I'm no Python expert so I'm completely lost here. Any help would be really appreciated!
This is really well done! Thank you! I had a quick question though. I try to manage my .rpy files with referencing or calls so I can manage the pieces a little better, especially if I need to change a quest later. I don't have to search through a HUGE file of codes to find the one I need. I was wondering if you could help me figure out why mine isn't working? I've tried to leave the default quest = Manager() in the script file and then use a call to load the quests in a different file as well as putting the default quest = Manager() in the referenced file and using a call quest_load in my script but it isn't recognizing Quest at that point. It gives me a NameError Quest is not defined when I do that. The only way I've gotten it to work is to load it into my script file first. Am I stuck with having it that way or is there something I'm missing that I need to add to be able to do this? Thank you in advance for your help!
Hi. Thank you for making this awesome Manager.
I got a question while customizing QuestManager, and this is it: Can you tell me how to subtract the prefix '~' and suffix '~' from screen evs_block? I'd like to remove the wave mark on ~General~ and ~Introduction~.
I found this in the screen evs_block under \questmanager\engine\screens. The code block looks like this:
screen evs_block(cat, evlist, prefix=" {b}-{/b} ", completed_suffix="{image=completed}", progress_suffix="{image=in_progress}", unknown=_("? ? ?")):
text " "+__(cat)+" ":
style "category_style"
the text ""+__(cat)+"": is where the ~ should be in your block. I just removed mine but left the category area in case I wanted to change it around later. I hope this helps!
Hi thanks for your comment :) You can remove the prefix by modifying the code. Go to the screens folder from questmanager folder and look for the diary.rpy file. At line 73 replace the line
by
and it should work !
File "game/houselocations.rpy", line 15, in script
if quest.is_state("mom2", "unlocked"):
File "game/houselocations.rpy", line 15, in <module>
if quest.is_state("mom2", "unlocked"):
File "game/questmanager/engine/classes.rpy", line 89, in is_state
if self._search(id, category).state == state:
AttributeError: 'NoneType' object has no attribute 'state'
This error mean that the name of the quest "mom2" doesn't exist. Is the quest "mom2" declared into the chapter ???
yes but i solved it differently i changed the classes.rpy a little bit.
how can I write two or 3 values in § quest.is_state?
do you have discord for a few questions?
Did you solve it?
Hi, this error mean that the name of the quest "qnicolas01" doesn't exist. Is the quest "qnicolas01" declared into the chapter ???
Hey, there. I have a bug where I just drag and dropped your folder into my project with no edits and its throwing this error Exception: Screen diary_open_btn is not known. Is there a way the screens are supposed to be setup?
I actually have not. I moved on to a different part of the code with a plan of returning. Mind sharing what you did to solve this?
u need to write this into file screens.rpy
There is code
This is awesome and I'm so thankful, that you have given us this amazing tool! I have one question, that is probably, already answered, but im just not finding it.
How can I activate events, depending on the status of a Quest?
Example: If quest with Id "007" is unlocked jump to this label, elif quest with id "008" is unlocked jump to... and so on.
So basically what would be the code for having jumps depending on the Quests?
Probably a simple If script line, but I rather ask an expert like you, before I do something wrong.
Thank you <3
Hi thank for your nice comment !
You can easily activate events depending on the status with the quest.is_state() function. This is an example:
# Define the chapter
define test = (
Quest("test01", _("Test01"), _("Introduction"), "completed"),
Quest("test02", _("Test02"), _("Introduction"), "in progress"),
)
label start:
#Load the chapter into the game
$ quest.load(test)
#Add the conditional state
if quest.is_state("test01", " completed"):
jump choice01
else:
jump choice02
label choice01:
c "First"
label choice02:
c "Two"
Thank you so much. I understood this. I'm amazed by myself. :3 Thank you. This explanation was clear and straight to the point. Thank you so much :)
Thanks :)
This is awesome, mate! Thanks for your hard work :D
Your welcome :)