Character affinity levels

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
Rhapsy
Newbie
Posts: 20
Joined: Fri Mar 01, 2024 3:45 pm
itch: Rhapsy
Contact:

Character affinity levels

#1 Post by Rhapsy »

Hi again.

I'm working on the character affinity system.
I've seen some games implement affinity levels on the character list screen. And when one of them has the maximum affinity and the player passes a special event or mission, they level up (Changing that number on their screen).

Example:
1_ You started the game and see that the affinity level number of all the characters on your list is "0".
2_ After spending too much time with "cat". You managed to reach the maximum affinity with her.
3_ A mission or special event is turned on to raise her level.
4_ You overcame that event. Now you see that in your character list the number of "cat" has changed to "1".

I would like to be able to add this to my project, but I'm having trouble creating a command to add and replace my custom level number images (lv0.png, lv1.png....) when a character in my menu increases her affinity level.

Code: Select all

########################### CHARACTER LIST SCREEN ##############################

screen button:
    vbox xalign 0.95 yalign 0.05:
        textbutton "List" action ui.callsinnewcontext("char_list")

define ID = 0

default characters = [
    {ID: "cat", "name": "Kitty", "desc": "Kitty is an independent and quiet cat.", "points": 5, "quest": "Feed the cat.", "show": False},
    {ID: "dog", "name": "Doggy", "desc": "Doggy is a brave and curious boy.", "points": 10, "quest": "Help him find his brother to take revenge.", "show": True},
    {ID: "owl", "name": "Owl", "desc": "Owl is a retired professor, an avid knitter.", "points": 15, "quest": "a lot of teeeeeeext{p}teeeext", "show": True},
    {ID: "man", "name": "The Man", "desc": 'As The Man likes to say, "Oh boy!"', "points": 1, "quest": "teeeeext{p}text", "show": True},
    ]

init python:
    def char(char_id):
        for n in range(0, len(characters)):
            if characters[n][ID] == char_id:
                return characters[n]

    def insert_before(char_id, new_char):
        for n in range(0, len(characters)):
            if characters[n][ID] == char_id:
                break
        store.characters.insert(n, new_char)

screen char_list(char_n=0):
    $ char = ch_filtered[char_n]

    frame:
        background "screens/screenlist_bg.png"
        xfill True
        yfill True
        add f"screens/{char[ID]}.png" pos (806,200) #Name
        add f"screens/photos/{char[ID]}.png" pos (50,40) #char photo with frame
        

        if char_n > 0:
            imagebutton auto "screens/prev_%s.png" pos (796,464) action Return(char_n - 1)

        if char_n < len(ch_filtered) - 1:
            imagebutton auto "screens/next_%s.png" pos (1696,464) action Return(char_n + 1)

        button:
            imagebutton auto "screens/back_%s.png" pos (1223,757) action Return(True)

    frame:
        background None
        pos (959, 80)
        xysize (720, 680)
        text f'{char["desc"]}' text_align 0.5:
            align (0.5, 0.5)

    frame:
        background None
        pos (960, 675)
        xysize (720, 380)
        text f'{char["quest"]}' text_align 0.5:
            align (0.5, 0,5)


    bar:
        value StaticValue(ch_filtered[char_n]["points"], 20)
        #thumb
        xysize (665,120)
        xalign 0.785
        yalign 0.55
        left_bar Frame("bar/baempty.png")
        right_bar Frame("bar/bafull.png")
        
    add "bar/bframe.png" xysize (720, 180) pos (957, 495)


label char_list:
    play music "audio/Dream.mp3"
    $ _return = 0
    $ ch_filtered = [x for x in characters if x["show"]]
label char_list_call:
    call screen char_list(_return)
    if type(_return) is bool:
        # "Back" button was pressed
        return
    # "Previous" or "Next" button was pressed:
    jump char_list_call

########################### END - CHARACTER LIST SCREEN ##############################



define r = Character("Rhapsy")
define k = Character("Kitty")
define p = Character("Porky")

label start:
    scene bgg
    show screen button # List button in the game

    "Look at your character list. Porky's not there."
    "..."
    r "Hello?"
    
    if not renpy.seen_image("img2"):
        show img2
        hide img2
        $ renpy.notify("  New\nGallery\nImage")

    p "Hello! My name is Porky."

    $ insert_before("man", {ID: "pig", "name": "Porky", "desc": "Its a pet, not ham.","quest": "teeeeext{p}text", "points": 4, "show": True})
    $ renpy.notify("Porky unlocked!")

    "Look at the list. Porky is already there."
    "But where is Kitty?"
    k "Meooow"
    
    if not renpy.seen_image("img1"):
        show img1
        hide img1
        $ renpy.notify("  New\nGallery\nImage")

    $ char("cat")["show"] = True
    $ renpy.notify("Kitty unlocked!")

    "Kitty came home! Look at your list. You must feed Kitty."
    "..."
    r "My cat kitty is hungry."
    p "ohh...{p}Bye bye!"
    "The little pig left."
    "You give your cat snacks."

    $ char ("cat")["points"] += 5
    $ renpy.notify("+5 Kitty's afinnity.")
    $ char("cat")["quest"] = "Play with Kitty."

    "Kitty's quest is done. Look at the list.{p}New quest available."
    k "Meooow."
    "Kitty is bored."
    "PAY ATTENTION TO KITTY'S AFFINITY BAR IN EVERY DECISION.{p}THERE WILL BE 2 DIFFERENT ENDINGS IF THE AFFINITY REACHES THE MAXIMUM OR ZERO."

label Kitty:
menu:
    r "What should I do?"
    "Play with Kitty":
        $ char ("cat")["points"] += 5
        $ renpy.notify("+5 Kitty's afinnity.")
        "Kitty is happy"
        if char ("cat")["points"] >= 20:
            jump continue1
        else:
            jump Kitty

        
    "Ignore":
        $ char ("cat")["points"] -= 5
        $ renpy.notify("-5 Kitty's afinnity.")
        "Kitty is angry"
        if char ("cat")["points"] <= 0:
            jump Badend
        else:
            jump Kitty

label Badend:
    k "MEOOOW!!!"
    "Kitty scratched you."
    r "Why? :("
    "BAD END{p}Next time spend more time with your pet."
    return

label continue1:
    
    $ char ("cat")["points"] = 0  #reset cat's bar/points
    #You raised the affinity level with "cat" to 1
    
    $ char("cat")["quest"] = "No events available in this version.{p}Wait for updates."
    "Kitty's quest is done. Look at the list."
    "..."
    "Thank you and See you later!"
    
    return

User avatar
m_from_space
Miko-Class Veteran
Posts: 975
Joined: Sun Feb 21, 2021 3:36 am
Contact:

Re: Character affinity levels

#2 Post by m_from_space »

Rhapsy wrote: Thu Mar 14, 2024 12:40 pm I would like to be able to add this to my project, but I'm having trouble creating a command to add and replace my custom level number images (lv0.png, lv1.png....) when a character in my menu increases her affinity level.
So just to be clear, it looks like you store the "affinity" inside the characters list and you call it "points" (alright, why not call it "affinity"?)...

And you change it for example here:

Code: Select all

    $ char ("cat")["points"] += 5
It took me a while to realize what you're doing, and it's a bit weird. Calling a function with an id that then returns the object that was found in the list. It's very inefficient, because you could just create a dictionary in the first place and use the dictionary instead of the function. It takes Python very little time to look that one up, instead of looping through that list all the time:

Code: Select all

default chars = {
    "cat": 
        {"name": "Kitty", "desc": "Kitty is an independent and quiet cat.", "points": 5, "quest": "Feed the cat.", "show": False},
    "dog":
        {"name": "Doggy", "desc": "Doggy is a brave and curious boy.", "points": 10, "quest": "Help him find his brother to take revenge.", "show": True},
    # ...
}

...
    # no function necessary
    $ chars["cat"]["points"] += 5
Of course you could also just create a dict for each character and then put them in the list, much easier to handle I think.

Code: Select all

default cat = {"name": "Kitty", "desc": "Kitty is an independent and quiet cat.", "points": 5, "quest": "Feed the cat.", "show": False}
default dog = {"name": "Doggy", "desc": "Doggy is a brave and curious boy.", "points": 10, "quest": "Help him find his brother to take revenge.", "show": True}

default chars = [cat, dog]

...
    $ cat["points"] += 5
Also, you are creating a variable called "char" inside one of your screens. But that's odd, because you already have a function with that same name. That's bad practice, in the worst case you're overwriting your function if you're not sure it's a local variable... Do not use the same names twice! (On a sidenote, better not call your screen "button", because that is a reserved Renpy keyword.) You also have both a screen and a label that is called "char_list". Are you not confusing yourself doing this?

So you say you want to update a level image based on the affinity level. So where do you store the affinity level to begin with? Is it just one level every 10 points or what? Nevertheless, showing your images is quite easy, I guess you know that. Assuming you have the pictures "lv1.png" and "lv2.png" etc. in your images folder and the affinity_level is 1, 2 etc...

Code: Select all

    add f"lv{affinity_level}"
If you want the affinity level based on the points, you could just calculate it with integer division.

Code: Select all

    # one level every 10 points
    $ affinity_level = cat["points"] // 10

Rhapsy
Newbie
Posts: 20
Joined: Fri Mar 01, 2024 3:45 pm
itch: Rhapsy
Contact:

Re: Character affinity levels

#3 Post by Rhapsy »

HI and thanks for helping me, I received some help here to create this command, I'm still reading the python files.
I plan to increase the affinity level after reaching the maximum, which is currently 20 points. Or the way to change the character's level number after completing an event.

I think this last option is better, so I can start an event when a character reaches maximum affinity points. I think it would be created like this:
Following the document I shared at the beginning. I hope I'm not wrong here. lol

Code: Select all

if char ("cat")["points"] >= 20:
            jump affinity_level_up_event

label affinity_level_up_event:
	"text....."
	
	#Event completed. (Here should be the command to change the character level number in the character list.)

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Google [Bot]