Quest updates with the use of lists

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
FrandollScarlet
Newbie
Posts: 8
Joined: Mon Jan 11, 2021 12:03 pm
Contact:

Quest updates with the use of lists

#1 Post by FrandollScarlet » Wed Aug 10, 2022 9:50 am

Hello!
I have quests in my game and I want the player to progress through them step by step. All information about the current step is written in the protagonist's notebook.
I have been playing around with it for a few days now so probably there is some useless code that I left when I came up with new ideas. I thought some of the old code could become useful later. Feel free to erase anything useless.

This is what it looks like now:

Class and list:

Code: Select all

init python:
    import renpy.store as store
    import renpy.exports as renpy

    class QuestC(object):
        def __init__(self, ID, name, description, update, active = False, completed = False):
            self.ID = ID
            self.name = name
            self.description = description
            self.update = update
            self.active = active
            self.completed = completed
        def StartQuest(self):
            if self.active == False:
                self.active = True
        def UpdateQuest(self):
            self.update += 1


    Steps = []
    Quest = []
    q = 0
    u = 0
    while q < 100:
        Quest.append(QuestC(q, "none", "none", u))
        q += 1
List of quests:

Code: Select all

label quest_list:
    $ Quest[0] = QuestC(0, "Apple Hunter", "This stranger asked me to buy him an apple.", 0, False, False)

    $ Steps0 = ["I should find a store where they sell apples.", "An apple costs 5 coins. Hopefully, I have enough.", "I bought an apple. Now it is time to deliver it to the stranger."]

    return
Screen that is displayed in the notebook:

Code: Select all

screen quest_info():
    $ info_quest_name = Quest[index].name
    $ info_quest_description = Quest[index].description
    $ info_quest_steps = Quest[index].update

    vbox:
        hbox:
            xalign 0.5
            text "{size=+12}[info_quest_name]{/size}"
        hbox:
            text "[info_quest_description]":
                justify True
        hbox:
            text "[info_quest_steps]":
                justify True
Script: (It is way longer in my code so I shortened it only to the relevant part).

Code: Select all

label start:
    call quest_list
    "Hey, you! Buy me an apple!"
    $ Quest[0].StartQuest()
#    The protagonist finds and enters the store. He sees the price of an apple.
    $ Quest[0].UpdateQuest()
#    The protagonist buys an apple.
    $ Quest[0].UpdateQuest()
After that, the next update will make the quest go from Active quests to Finished. I didn't consider how it will look like because for now, I want to finish this part.
So now with this code, the numbers of progression from self.update += 1 appear in the notebook. Instead of the numbers, I want the text from the list Steps0 to appear. I feel that it is simple to write but I still lack knowledge about lists and classes so I struggle a bit. Could you help me?

User avatar
enaielei
Regular
Posts: 114
Joined: Fri Sep 17, 2021 2:09 am
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: Quest updates with the use of lists

#2 Post by enaielei » Wed Aug 10, 2022 10:27 am

Try making Steps0 a property of the class QuestC also.

Code: Select all

class QuestC(object):
        def __init__(self, ID, name, description, steps, active = False, completed = False):
            self.ID = ID
            self.name = name
            self.description = description
            self.active = active
            self.completed = completed

            self.steps = steps
            self.update = 0
            self.finished = False
        def StartQuest(self):
            if self.active == False:
                self.active = True
        def UpdateQuest(self):
            if not self.active or self.update >= len(self.steps): return
            self.update += 1
            if self.update >= len(self.steps):
              self.active = False
              self.finished = True
        def GetStep(self):
            if not self.steps or self.update < 0 or self.update >= len(self.steps): return
            return self.steps[self.update]
Declare it like this then...

Code: Select all

label quest_list:
    $ Steps0 = ["I should find a store where they sell apples.", "An apple costs 5 coins. Hopefully, I have enough.", "I bought an apple. Now it is time to deliver it to the stranger."]
    $ Quest[0] = QuestC(0, "Apple Hunter", "This stranger asked me to buy him an apple.", Steps0, False, False)

    return
And in your screen...

Code: Select all

screen quest_info():
    $ quest = Quest[index]

    vbox:
        hbox:
            xalign 0.5
            text "{size=+12}[quest.name]{/size}"
        hbox:
            text "[quest.description]":
                justify True
        hbox:
            for step in quest.steps:
              text "[step]":
                justify True
Also you need to make some adjustments in your variable definitions. "default" the variable if you want to participate it in Rollback. "define" if the variable is a constant. You also need to remove the loop, use append in Quest to avoid errors.

Code: Select all

default Quest = []

label start:
  $ Quest.append(QuestC(...))
  $ quest = Quest[0]
  "[quest.name]"

FrandollScarlet
Newbie
Posts: 8
Joined: Mon Jan 11, 2021 12:03 pm
Contact:

Re: Quest updates with the use of lists

#3 Post by FrandollScarlet » Wed Aug 10, 2022 12:47 pm

Thank you! I might be a bit tired looking at all this coding, but I don't understand what do you mean by making a Steps0 property. I think it may look something like this:

Code: Select all

@property
        def Steps0(self):
but I don't know what to put in there.

Also, could you explain what this part means? What does "len" refer to?
enaielei wrote:
Wed Aug 10, 2022 10:27 am

Code: Select all

        def UpdateQuest(self):
            if not self.active or self.update >= len(self.steps): return
            self.update += 1
            if self.update >= len(self.steps):
              self.active = False
              self.finished = True
        def GetStep(self):
            if not self.steps or self.update < 0 or self.update >= len(self.steps): return
            return self.steps[self.update]
An interesting thing is that

Code: Select all

	$ quest = Quest[0]
	"[quest.name]"
in label start displays the name of the quest correctly, but when I open the notebook, no quest is listed in Active quests despite it also calling

Code: Select all

screen quest_info():
    $ quest = Quest[index]

    vbox:
        hbox:
            xalign 0.5
            text "{size=+12}[quest.name]{/size}"
(I also put 0 instead of index to see whether it sees the index at all or something but it doesn't display the name even if there is 0 so that's not it).
Why is that?

User avatar
enaielei
Regular
Posts: 114
Joined: Fri Sep 17, 2021 2:09 am
Tumblr: enaielei
Deviantart: enaielei
Github: enaielei
Skype: enaielei
Soundcloud: enaielei
itch: enaielei
Discord: enaielei#7487
Contact:

Re: Quest updates with the use of lists

#4 Post by enaielei » Wed Aug 10, 2022 1:31 pm

Thank you! I might be a bit tired looking at all this coding, but I don't understand what do you mean by making a Steps0 property. I think it may look something like this:
I wrongly phrased that.
What I mean is that make the "steps" a property of the class "QuestC" since as far as I understood the steps vary depending on the quest?
If so then making it a property would be convenient, hence the "steps" parameter in the "__init__" method.
@property
def Steps0(self):
This would also work, but unnecessary.
A simple storing of the steps inside "self.steps" would work.
Also, could you explain what this part means? What does "len" refer to?
It's just a python thing, a built-in function. "len" just basically returns the length of the passed object.
In the code, I'm using "len" to get the number of elements in the "steps" property.
This documentation explains that as well, also you can find here additional built-in functions that you might wanna learn or try.
An interesting thing is that
in label start displays the name of the quest correctly, but when I open the notebook, no quest is listed in Active quests despite it also calling
This is one of the reasons why you need to determine when to "default" or "define" your variables. I provided an example earlier regarding that.

For your reference, this is the complete working code that should work for you. I removed the unnecessary lines that I stated earlier.
I also removed the "finished" variable since I missed that you already have the "completed" variable so I used that instead.
And also I removed "GetStep" and replaced it with an actual property since you're familiar with the "@property" wrapper.

Code: Select all

init python:
  class QuestC(object):
    # returns the current step for the quest
    @property
    def step(self):
      if not self.steps or self.update < 0 or self.update >= len(self.steps): return
      return self.steps[self.update]

    def __init__(self, ID, name, description, steps, active = False, completed = False):
      self.ID = ID
      self.name = name
      self.description = description
      self.active = active
      self.completed = completed

      self.steps = steps
      self.update = 0
    def StartQuest(self):
      if self.active == False:
          self.active = True
    def UpdateQuest(self):
      if not self.active or self.update >= len(self.steps): return
      self.update += 1
      if self.update >= len(self.steps):
        self.active = False
        self.completed = True

# default the variables quests and index since you'll be changing contents
# of these variables from time to time.
# defaulting also makes the variable compatible with rollbacks
default quests = []
default index = 0

screen quest_info():
    $ quest = quests[index]

    vbox:
        hbox:
            xalign 0.5
            text "{size=+12}[quest.name]{/size}"
        hbox:
            text "[quest.description]":
                justify True
        hbox:
            spacing 20
            for step in quest.steps:
              text "[step]":
                justify True
                size 14

        text "Current Step: [quest.step]"

label start:
  python:
    # append first quest
    quests.append(QuestC(
      0,
      "Apple Hunter",
      "This stranger asked me to buy him an apple.",
      [
        "I should find a store where they sell apples.",
        "An apple costs 5 coins. Hopefully, I have enough.",
        "I bought an apple. Now it is time to deliver it to the stranger."
      ],
      False, False
    ))

    # access first quest
    quest = quests[index]
  
  $ quest.StartQuest()
  show screen quest_info
  "Show Quest"
  $ quest.UpdateQuest()
  "First Update"
  $ quest.UpdateQuest()
  "Second Update"
  $ quest.UpdateQuest()
  "Third Update"
For trying out this code, just literally copy and paste it first then test things out.
I suggest having a blank renpy project to test things out before integrating it into your actual game.
If its working then that's the time you tinker with the code and make adjustments.

FrandollScarlet
Newbie
Posts: 8
Joined: Mon Jan 11, 2021 12:03 pm
Contact:

Re: Quest updates with the use of lists

#5 Post by FrandollScarlet » Fri Aug 12, 2022 9:37 am

Sorry for the late response!
After a few adjustments, I managed to get it to work with the protagonist's notebook.

Thank you so much, enaielei, you are amazing!

Post Reply

Who is online

Users browsing this forum: Bing [Bot]