Could anyone help with coding? Need quest/hints, portrait and stats screen for my games...and I'm garbage at it.

ArchieGold

Newbie
Game Developer
Dec 17, 2021
61
203
Hi,
I am trying to build a user interface that shows character's pictures, 2 stats, and a quest or hint system for each person. Coding is my biggest handicap to making games and it is honestly frustrating. I would really appreciate if someone could just help me make something simple that I could use, and that my players could be satisfied with and hopefully I can just use that for as long as I'm in this hobby.

I am comfortable with the basics of renpy but this is definitely a point of knowledge gap and the learning curve appears steep and I'm hitting fatigue at trying to figure things out independently.

I have being looking through old scripts and I think that I found one that could work for the hint/quest system:

init python:
class Quest( renpy.python.RevertableObject ):

def __init__( self, char ):
self._char = char
self._stages = []
self._iterationsLeft = []
self._actualStage = 0

property
def showStage( self ):
# Let /isFinished/ deal with this, it's better.
if self.isFinished() is True: return "The quest is finished."
return self._stages[self._actualStage][0]

property
def actualStage( self ):
return self._actualStage + 1

property
def iterationLeft( self ):
# Let /isFinished/ deal with this, it's better.
if self.isFinished() is True: return 0
return self._iterationsLeft[self._actualStage]

def addStage( self, task, iteration=1 ):
self._stages.append( ( task, iteration ) )
self._iterationsLeft.append( iteration )

def nextStage( self ):
if self.isFinished() is True: return
self._iterationsLeft[self._actualStage] -= 1
if self._iterationsLeft[self._actualStage] == 0:
self._actualStage += 1

def reset( self ):
self._actualStage = 0
self._iterationsLeft = []
for s in self._stages:
self._iterationsLeft.append( s[1] )

def numberStages( self ):
return len( self._stages )

def updateStage( self, stage, task, iteration=1 ):
if len( self._stages ) <= stage : return
if stage < 0: return
iterationDone = self._stages[stage][1] - self._iterationsLeft[stage]
self._stages[stage] = ( task, iteration )
self._iterationsLeft[stage] = iteration - iterationDone
if self._iterationsLeft[stage] < 1: self._iterationsLeft[stage] = 1

def updateLastStage( self, task, iteration=1 ):
self.updateStage( len( self._stages - 1 ), task, iterarion )

def isFinished( self ):
# Still at least a stage, so it can't be ended.
if self._actualStage + 1 < len( self._stages ): return False
# Above the last stage, so obviously finished.
if self._actualStage + 1 > len( self._stages ): return True
# Else, it will depend if there's still an iteration to do or not.
return self._iterationsLeft[self._actualStage] == 0

I have a few questions related to this above. I just want to make sure I know how to work this.

1. If I had a character quest and wanted to add it, would this be appropriate code during the actual script?
define a = "charA name"
$ charAQuest = Quest( "charA name" )
or
$ aquest = Quest( "charA name" )

2. If I wanted to add another stage, would this be appropriate?
$ charAQuest.addStage( "Assemble in the main hall" )
or
$ a.addstage( "Assemble in the main hall" )

3. How would I get to "Is Finished", like what code would I need to put into the script?

If I could get the above to work, that should be sufficient to walkthrough my game, on top of the other changes I already plan to make to simplify everything including doing away with maps, and just using jump events.

Another area where I would love help, if possible would be including a stats screen which has a portrait and 2 stats from the game. My games have a lot of characters, and if there is a way to simplify this I would greatly appreciate any help. The two stats I'd like to showcase for all characters are Bond and Lust. But rather than using the actual number values, I'd like to just use a string such as below...what could I do to show this?

default CharacterBond = 0
default CharacterBondValue = Null
default CharacterDesire = 0
default CharacterDesireValue = Null

if CharacterBond == 0:
$ CharacterBondValue = "Neutral"
if CharacterBond >= 3:
$ CharacterBondValue = "Devoted"
if CharacterBond >= 2:
$ CharacterBondValue = "Close"
if CharacterBond >= 1:
$ CharacterBondValue = "Friendly"
if CharacterBond <= -1:
$CharacterBondValue = "Distant"
if CharacterBond <= -2:
$ CharacterBondValue = "Rival"
if CharacterBond <= -3:
$ CharacterBondValue = "Enemy"


if CharacterDesire == 0:
$ CharacterDesireValue = "None"
if CharacterDesire >= 2:
$ CharacterDesireValue = "Interested"
if CharacterDesire >= 4:
$ CharacterDesireValue = "Eager"
if CharacterDesire >= 6:
$ CharacterDesireValue = "Obsessed"
if CharacterDesire >= 8:
$CharacterDesireValue = "Desperate"
if CharacterDesire >= 10:
$CharacterDesireValue = "Uninhibited"

So, ideally, I could have a screen that shows a character's picture, these two stats, and a tiny hint/quest line for every character. I would appreciate any help, including even something much simpler or different from this. I just want to make games but I still want to retain some element of complexity and depth to the logic of them...this is so frustrating.
 

ArchieGold

Newbie
Game Developer
Dec 17, 2021
61
203
init python:
class People:

def __init__(self,name, picture, bond, desire, mission):
self.name=name
self.picture=picture
self.bond=bond
self.desire=desire
self.mission=mission

property
def bond_change(self, change):
self.bond += change
if change > 0:
direction = "increased"
else:
direction = "decreased"
renpy.notify("Bond with " + str(self.name) + " " + direction + " by " + str(abs(change)))

property
def desire_change(self, change):
self.desire += change
if change > 0:
direction = "increased"
else:
direction = "decreased"
renpy.notify("Desire of " + str(self.name) + " " + direction + " by " + str(abs(change)))

property
def mission_update(self, update):
self.mission = append.mission

property
def desire_status(self):
if self.desire < 2:
status = str("None")
if self.desire >= 2:
status = str("Interested")
if self.desire >= 4:
status = str("Eager")
if self.desire >= 6:
status = str("Obsessed")
if self.desire >= 8:
status = str("Desperate")
if self.desire >= 10:
status = str("Uninhibited")

property
def bond_rank(self):
if self.bond <= -3:
rank = str("Enemy")
if self.bond <= -2:
rank = str("Rival")
if self.bond <= -1:
rank = str("Distant")
if self.bond == 0:
rank = str("Neutral")
if self.bond >= 1:
rank = str("Friendly")
if self.bond >= 2:
rank = str("Close")
if self.bond >= 3:
rank = str("Devoted")

$ k.bond += 1
$ k.mission = "Go to the main hall"
$ k.desire += 3

default allpeople = ["k"]
default k = People("Kate","kate_icon",0,0,"Null")

Sorry, so I still have a question. I can get the Bond/Desire working fine....when it comes to showing bond rank and desire status I get stuck with only the initial value. It's not dynamic...is there someway to code it to recalculate every time the base variable (Bond OR desire) increases?

Currently it shows
Bond 1 Desire 3
"Go to the Main Hall"
Status "None" Rank "None"

"None" wasn't even an option for bond rank...

property
def desire_status(self, desire_change):
if self.desire + k.desire_change < 2:
status = str("None")
if self.desire + k.desire_change >= 2:
status = str("Interested")
if self.desire + k.desire_change >= 4:
status = str("Eager")
if self.desire + k.desire_change >= 6:
status = str("Obsessed")
if self.desire + k.desire_change >= 8:
status = str("Desperate")
if self.desire + k.desire_change >= 10:
status = str("Uninhibited")

The only other thought I had was adding the desire change directly into the calculation but I still don't have it . Would appreciate any assistance.
 

mickydoo

Fudged it again.
Game Developer
Jan 5, 2018
2,446
3,548
I am trying to build a user interface that shows character's pictures, 2 stats, and a quest or hint system for each person. Coding is my biggest handicap to making games and it is honestly frustrating. I would really appreciate if someone could just help me make something simple that I could use, and that my players could be satisfied with and hopefully I can just use that for as long as I'm in this hobby.
When you write your post, up the top of this box is a little flag, to its right is three dots with a arrow. if you click on the little arrow you will see among other things, insert code, clicking on that you will then see a list of codes to insert, select python, your code will look like this then.

Python:
label see_more:
    "Of what you are doing"
Can't help with the rest, I am coding simpleton. But you will get more help inserting the code properly as ppl can see what is happening and why things are not working.
 
  • Like
Reactions: ArchieGold

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,398
15,311
I have being looking through old scripts and I think that I found one that could work for the hint/quest system:

Code:
            # Let /isFinished/ deal with this, it's better.
            if self.isFinished() is True: return "The quest is finished."
Oh yeah, a good quest system. I have absolutely no memories of this but, I'm sure the code works fine :whistle:
So, writing style is really a fucking good fingerprint...

This being said, if I hadn't concern at this time, I have some now regarding the reliability for a Ren'Py game. The system can have quest added at anytime, but correcting errors in previously defined quests is not part of the code and would be problematic.


1. If I had a character quest and wanted to add it, would this be appropriate code during the actual script?
define a = "charA name"
$ charAQuest = Quest( "charA name" )
or
$ aquest = Quest( "charA name" )
Neither, because the leading $ imply that you are doing this on a label.
It should be :
default charAQuest = Quest( "charA name" )
or
default aquest = Quest( "charA name" )
The name of the variable is totally up to you and your preferences.


2. If I wanted to add another stage, would this be appropriate?
$ charAQuest.addStage( "Assemble in the main hall" )
or
$ a.addstage( "Assemble in the main hall" )
Well, all depend on the name you decided to use. And, of course, can mess with the save compatibility if you put this on the wrong place.


3. How would I get to "Is Finished", like what code would I need to put into the script?
nameOfTheQuest.nextStage() each time a stage is finished.


If I could get the above to work, that should be sufficient to walkthrough my game,
Feel an overkill for that, or I haven't understood what you meant (what is possible).



Another area where I would love help, if possible would be including a stats screen which has a portrait and 2 stats from the game. My games have a lot of characters, and if there is a way to simplify this I would greatly appreciate any help.
Python:
# List of all the girls names.
# MUST match the number of entry in the /grid/ below, fill with /None/ for this.
define allGirls = [ "anna", "sarah", "chris", "whatever", "girl1", "girl2", None, None ]

screen stats( girlName="anna" ):

    vbox:
       # Buttons to access the girl page.
       # Display this properly.
       # I used 2 lines of 4 rows as example, but you can perfectly have had 1 line of 8 rows
       # or even 1 line of 6 since there's 6 girls in my example
       grid 2 4:
           for name in allGirls:
               if name is None:
                   null width 1
               else:
                   textbutton "[name]":
                       # I have a doubt, can possibly be /SetScreenVariable/ instead
                       action SetLocaleVariable( "girlName", name )

       null height 50

       hbox:
          #  Assuming that you've an image "anna_profile.png", "sarah_profile.png" and so on
          # and they are located in "images/stats/"
          add ( "images/stats/{}_profile.png".format( girlName ) )
          vbox:
              hbox:
                  text "Bond"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Bond" ) )
              hbox:
                  text "Desire"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Desire" ) )

      textbutton "Close":
          xalign 0.5
          action Return()

label whatever:
    # Display the screen starting with the first girl
    call screen stats()

label whateverelse:
    # open the screen starting with a particular girl
    call screen stats( "sarah" )


Code:
            if self.desire < 2:
                status = str("None")
            if self.desire >= 2:
                status = str("Interested")
            if self.desire >= 4:
                status = str("Eager")
            if self.desire >= 6:
                status = str("Obsessed")
            if self.desire >= 8:
                status = str("Desperate")
            if self.desire >= 10:
                status = str("Uninhibited")
This is wrong, should be:
Code:
            if self.desire < 2:
                status = str("None")
            elif self.desire >= 10:
                status = str("Uninhibited")
            elif self.desire >= 8:
                status = str("Desperate")
            elif self.desire >= 6:
                status = str("Obsessed")
            elif self.desire >= 4:
                status = str("Eager")
            elif self.desire >= 2:
                status = str("Interested")
There's no need to proceed all the test and change the value many times.

The use of str is also totally useless, you are asking for a string to be transformed into a string.
 
  • Like
Reactions: ArchieGold

ArchieGold

Newbie
Game Developer
Dec 17, 2021
61
203
Oh yeah, a good quest system. I have absolutely no memories of this but, I'm sure the code works fine :whistle:
So, writing style is really a fucking good fingerprint...

This being said, if I hadn't concern at this time, I have some now regarding the reliability for a Ren'Py game. The system can have quest added at anytime, but correcting errors in previously defined quests is not part of the code and would be problematic.




Neither, because the leading $ imply that you are doing this on a label.
It should be :
default charAQuest = Quest( "charA name" )
or
default aquest = Quest( "charA name" )
The name of the variable is totally up to you and your preferences.




Well, all depend on the name you decided to use. And, of course, can mess with the save compatibility if you put this on the wrong place.




nameOfTheQuest.nextStage() each time a stage is finished.




Feel an overkill for that, or I haven't understood what you meant (what is possible).





Python:
# List of all the girls names.
# MUST match the number of entry in the /grid/ below, fill with /None/ for this.
define allGirls = [ "anna", "sarah", "chris", "whatever", "girl1", "girl2", None, None ]

screen stats( girlName="anna" ):

    vbox:
       # Buttons to access the girl page.
       # Display this properly.
       # I used 2 lines of 4 rows as example, but you can perfectly have had 1 line of 8 rows
       # or even 1 line of 6 since there's 6 girls in my example
       grid 2 4:
           for name in allGirls:
               if name is None:
                   null width 1
               else:
                   textbutton "[name]":
                       # I have a doubt, can possibly be /SetScreenVariable/ instead
                       action SetLocaleVariable( "girlName", name )

       null height 50

       hbox:
          #  Assuming that you've an image "anna_profile.png", "sarah_profile.png" and so on
          # and they are located in "images/stats/"
          add ( "images/stats/{}_profile.png".format( girlName ) )
          vbox:
              hbox:
                  text "Bond"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Bond" ) )
              hbox:
                  text "Desire"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Desire" ) )

      textbutton "Close":
          xalign 0.5
          action Return()

label whatever:
    # Display the screen starting with the first girl
    call screen stats()

label whateverelse:
    # open the screen starting with a particular girl
    call screen stats( "sarah" )




This is wrong, should be:
Code:
            if self.desire < 2:
                status = str("None")
            elif self.desire >= 10:
                status = str("Uninhibited")
            elif self.desire >= 8:
                status = str("Desperate")
            elif self.desire >= 6:
                status = str("Obsessed")
            elif self.desire >= 4:
                status = str("Eager")
            elif self.desire >= 2:
                status = str("Interested")
There's no need to proceed all the test and change the value many times.

The use of str is also totally useless, you are asking for a string to be transformed into a string.

Thank you so much for all your help. I have just one issue left it seems and it's probably really simple...I can get it to switch when I can on the names of the different characters. Below, I have defined two of them, and I have included everything I wanted...but it won't let me switch between the two? I am assuming once a click on the name of a girl, that one is supposed to become the default girl on the screen correct?

Code:
define allGirls = [ "Kate", "Valeria", "Airi", "Aisha", "Claudia", "Irina", "Grace", "Maslani", "Nadya", "Samarra", "Titania", None]

default KateBond = 0
default KateDesire = 0
default KateMission = "Go to Main hall"
default ValeriaBond = 0
default ValeriaDesire = 0
default ValeriaMission = "Talk to Valeria"

screen Relationships(girlName="Kate"):

    vbox:
       # Buttons to access the girl page.
       # Display this properly.
       # I used 2 lines of 4 rows as example, but you can perfectly have had 1 line of 8 rows
       # or even 1 line of 6 since there's 6 girls in my example
       grid 2 6:
           for name in allGirls:
               if name is None:
                   null width 1
               else:
                   textbutton "[name]":
                       # I have a doubt, can possibly be /SetScreenVariable/ instead vs SetLocaleVariable
                       action SetScreenVariable( "girlName", name )

       null height 50

       hbox:
          #  Assuming that you've an image "anna_profile.png", "sarah_profile.png" and so on
          # and they are located in "images/stats/"
          add ( "images/{}_icon.png".format( girlName ) )
          vbox:
              hbox:
                  text "Bond"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Bond" ) )
              hbox:
                  text "Desire"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Desire" ) )
              hbox:
                  text "Mission:"
                  null width 30
                  text "{}".format( getattr( store, girlName + "Mission" ) )



screen controlrelationships():
    frame:
        xalign 1.00
        yalign 0.00
        textbutton "Relationships" action If(renpy.get_screen("Relationships"), Hide("Relationships"), Show("Relationships"))