Posibility to check certain conditions before player can add points?

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
User avatar
lordelpresidente
Newbie
Posts: 3
Joined: Mon Oct 03, 2022 2:57 pm
Location: Indonesia
Discord: El Presidente of Tropico#4323
Contact:

Posibility to check certain conditions before player can add points?

#1 Post by lordelpresidente » Tue Oct 04, 2022 5:17 am

Hello there! :)
This is my first qustion in the forum

I am trying to create a progressive affection system which you need to gain the status of "Best Friend" before you can add points to Romance.

My code so far looks like so:
(NB: I rewrite the code on another project to specifically test this so if there's lines that sometimes out of the ordinary, chances are that line is copy-pasted from my main game)

Code: Select all


default plname = "Andrew"

define pl = Character("Advisor [plname]")
define pre = Character("President Rosellini")

define bestfriendstatus = False

I put this part outside any labels

Code: Select all

label start:

    # scores
    scene bg2

    #president's 
    #affinity point to player
    $presaffpts = 5
    $presaffstate = ""
    #romance point to player
    $preslovpts = 0
    $preslovstate = ""
    #points tracking presidents popularity
    $prespoppts = 0
    $prespoppts = ""


    #function for points
    init python:
        #function to determine president points limit
        #affinity

        def limit_pres_aff(presaffpts, minpts=0, maxpts=100):
            return max(min(presaffpts, maxpts), minpts)

        def pres_aff_calc():
            if presaffpts < 9:
                presaffstate = "Stranger"
            if ((presaffpts >= 10)and(presaffpts < 25)):
                presaffstate = "Acquaintance"
            if ((presaffpts >=25 )and(presaffpts < 50)):
                presaffstate = "Friend"
            if((presaffpts >=50)and (presaffpts < 80)):
                presaffstate = "Close Friend"
            if ((presaffpts >=85 )and(presaffpts < 101)):
                presaffstate = "Best Friend"
            return presaffstate

        #status check for continuing 
        def pres_aff_check():
            if presaffstate == "Best Friend":
                bestfriendstatus = True
            else:
                bestfriendstatus = False
            return bestfriendstatus
	
	#love
	#TBD NEED TO FIGURE OUT
I put this on in game start label to determine variables, functions to limit the values of the points so it doesn't overflow, function to define written level of affection (from Stranger to Best Friend) and another function to check whether or not the Best Friend Status is true or not.

My question is:

Is there a good way for me to create a similar structure of functions for the Romance points that requires the game to check first whether the Best Friend Status is marked true or not before the player can add Romance Points? (e.g: The game need to see if you're a best friend or not, if not, Romance points cannot be added, if true it can)
Should I rework the code to a better way?

I can't for the love of myself figure out how to properly do it

Thank you beforehand and I would really appreciate any suggestion or help

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: Posibility to check certain conditions before player can add points?

#2 Post by enaielei » Tue Oct 04, 2022 7:15 am

I'm guessing you're using the function this way?

Code: Select all

label start:
    $ bestfriendstatus = pres_aff_check()
Then why not...

Code: Select all

init python:
    def limit_pres_aff(presaffpts, minpts=0, maxpts=100):
        ...

    def pres_aff_calc():
        ...

    def pres_aff_check():
        ...

    def add_rom(amount=0):
        if not bestfriendstatus: return preslovpts
        return preslovpts + amount

label start:
    $ bestfriendstatus = pres_aff_check()
    $ preslovpts = add_rom(10)
Note that I moved your functions outside the label, that's the right way to do it.
Also just like your bestfriendstatus, default the other variables instead of declaring them inside the label.
And of course, there's always a better way to do this. Using classes would definitely help.

User avatar
Ocelot
Eileen-Class Veteran
Posts: 1882
Joined: Tue Aug 23, 2016 10:35 am
Github: MiiNiPaa
Discord: MiiNiPaa#4384
Contact:

Re: Posibility to check certain conditions before player can add points?

#3 Post by Ocelot » Tue Oct 04, 2022 7:49 am

I prefer to wrap data which should be handled in a specific way in classes, so it simply couldn't accidentally be handled wrong. I cannot forget to update or clamp value, because everything is done automatically:

Code: Select all

init python:
    class Attribute:
        def __init__(self, titles, attribute_min=0, attribute_max=100, value=0):
            """Attribute class constructor. 
                attribute_min and attribute_max set the range value would be clamped to.
                value sets starting attribute value
                titles is a list of tuples consisting of attribute level name, and maximum attrubute value for this level. 
                This list is sorted and level with the least maximum level still higher than vale is selected"""
            self.att_min = attribute_min
            self.att_max = attribute_max
            self.title = sorted(titles, key=lambda entry: entry[1])
            self.__value = value

        @property
        def value(self):
            return self.__value

        @value.setter
            def value(self, new_value):
                self._value = max(self.att_min, min(new_value, self.att_max))

        @property
        def title(self):
            for name, level in self.titles:
                if self.value < level:
                    return name
            return _("Unknown")

    class Relationships:
        """"Relationship class both exposes attributes directly and provides a way to add points to corresponding attribute. 
            Attempting to add points to romance through helper function will not change romance value unless friendship is high enough
            The can_romance property can be used in conditions""""
        def __init__(self):
            self.friendship = Attribute(titles=[
                (_("Stranger"), 10), (_("Acquaintance"), 25), (_("Friend"), 50), (_("Close Friend"), 80), (_("Best Friend"), 1000),
            ])    
            self.romance = Attribute(max_attribute=10, titles=[
                (_("None"), 1), (_("Interest"), 6), (_("Crush"), 10), (_("Love"), 1000)
            ])

        @property
        def can_romance(self):
            return self.friendship >= 80

        def add_friendship(self, amount):
            self.friendship.value += amount
            return self.friendship.value

        def add_romance(self, amount):
            if self.can_romance():
                    self.romance.value += amount
            return self.romance.value

# usage:
default relationships = Relationships()

label start:
    # 0 , Stranger , None
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
    menu:
        "Go on a date" if relationships.can_romance: # Won't be avaliable now
            $ relationships.romance += 1 # Here I am accessing romance value directly, since we checked if romance is possible earlier
        "Sleep":
           pass
    $ relationships.friendship += 1000 # add a lot of points directly
    $ relationship.add_romance(1) # try to add romance if possible. Needed here if we only want to add romance points in best friend status.
    # 100 , Best Friend , None
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
        menu:
        "Go on a date" if relationships.can_romance: # Now avaliable
            $ relationships.romance += 1
        "Sleep":
           pass
    # 100 , Best Friend , Interest
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
    return
< < insert Rick Cook quote here > >

User avatar
lordelpresidente
Newbie
Posts: 3
Joined: Mon Oct 03, 2022 2:57 pm
Location: Indonesia
Discord: El Presidente of Tropico#4323
Contact:

Re: Posibility to check certain conditions before player can add points?

#4 Post by lordelpresidente » Thu Oct 06, 2022 9:50 am

enaielei wrote:
Tue Oct 04, 2022 7:15 am
I'm guessing you're using the function this way?

Code: Select all

label start:
    $ bestfriendstatus = pres_aff_check()
Then why not...

Code: Select all

init python:
    def limit_pres_aff(presaffpts, minpts=0, maxpts=100):
        ...

    def pres_aff_calc():
        ...

    def pres_aff_check():
        ...

    def add_rom(amount=0):
        if not bestfriendstatus: return preslovpts
        return preslovpts + amount

label start:
    $ bestfriendstatus = pres_aff_check()
    $ preslovpts = add_rom(10)
Note that I moved your functions outside the label, that's the right way to do it.
Also just like your bestfriendstatus, default the other variables instead of declaring them inside the label.
And of course, there's always a better way to do this. Using classes would definitely help.
Aha, so it should be fine for me to put them outside of labels... noted.

Thank you! this should be it, I'll test it should I can
Is there any notable difference between putting variables inside and outside of labels? I guess it's just keep it from being a clutter? Or is it to prevent the game from recording the variables to a specific label, reducing mess as I write further?
Pretty new on using this

User avatar
lordelpresidente
Newbie
Posts: 3
Joined: Mon Oct 03, 2022 2:57 pm
Location: Indonesia
Discord: El Presidente of Tropico#4323
Contact:

Re: Posibility to check certain conditions before player can add points?

#5 Post by lordelpresidente » Thu Oct 06, 2022 9:55 am

Ocelot wrote:
Tue Oct 04, 2022 7:49 am
I prefer to wrap data which should be handled in a specific way in classes, so it simply couldn't accidentally be handled wrong. I cannot forget to update or clamp value, because everything is done automatically:

Code: Select all

init python:
    class Attribute:
        def __init__(self, titles, attribute_min=0, attribute_max=100, value=0):
            """Attribute class constructor. 
                attribute_min and attribute_max set the range value would be clamped to.
                value sets starting attribute value
                titles is a list of tuples consisting of attribute level name, and maximum attrubute value for this level. 
                This list is sorted and level with the least maximum level still higher than vale is selected"""
            self.att_min = attribute_min
            self.att_max = attribute_max
            self.title = sorted(titles, key=lambda entry: entry[1])
            self.__value = value

        @property
        def value(self):
            return self.__value

        @value.setter
            def value(self, new_value):
                self._value = max(self.att_min, min(new_value, self.att_max))

        @property
        def title(self):
            for name, level in self.titles:
                if self.value < level:
                    return name
            return _("Unknown")

    class Relationships:
        """"Relationship class both exposes attributes directly and provides a way to add points to corresponding attribute. 
            Attempting to add points to romance through helper function will not change romance value unless friendship is high enough
            The can_romance property can be used in conditions""""
        def __init__(self):
            self.friendship = Attribute(titles=[
                (_("Stranger"), 10), (_("Acquaintance"), 25), (_("Friend"), 50), (_("Close Friend"), 80), (_("Best Friend"), 1000),
            ])    
            self.romance = Attribute(max_attribute=10, titles=[
                (_("None"), 1), (_("Interest"), 6), (_("Crush"), 10), (_("Love"), 1000)
            ])

        @property
        def can_romance(self):
            return self.friendship >= 80

        def add_friendship(self, amount):
            self.friendship.value += amount
            return self.friendship.value

        def add_romance(self, amount):
            if self.can_romance():
                    self.romance.value += amount
            return self.romance.value

# usage:
default relationships = Relationships()

label start:
    # 0 , Stranger , None
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
    menu:
        "Go on a date" if relationships.can_romance: # Won't be avaliable now
            $ relationships.romance += 1 # Here I am accessing romance value directly, since we checked if romance is possible earlier
        "Sleep":
           pass
    $ relationships.friendship += 1000 # add a lot of points directly
    $ relationship.add_romance(1) # try to add romance if possible. Needed here if we only want to add romance points in best friend status.
    # 100 , Best Friend , None
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
        menu:
        "Go on a date" if relationships.can_romance: # Now avaliable
            $ relationships.romance += 1
        "Sleep":
           pass
    # 100 , Best Friend , Interest
    "Current friendship value is [relationships.friendship.value]\nFriendship level is [relationships.friendship.title]\nRomance level is [relationships.romance.title]"
    return
    


I probably should have started using classes, but I wasn't familiar since this is my first time using RenPy. I was wondering why would my values wasn't updating when I tried to put them on a display so I just decided to call the function everytime the calculation is made...

Thank you! I'll just put most of my variables in a class for now

Post Reply

Who is online

Users browsing this forum: Google [Bot], Majestic-12 [Bot]