Passing a list parameter to a screen

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
AWizardWithWords
Newbie
Posts: 1
Joined: Fri Apr 19, 2024 4:56 pm
Tumblr: AWizardWithWords
Deviantart: AWizardWithWords
Github: AWizardWithWords
Skype: AWizardWithWords
Soundcloud: AWizardWithWords
itch: AWizardWithWords
Contact:

Passing a list parameter to a screen

#1 Post by AWizardWithWords »

I'm trying to pass a list a parameter for my code here, and that normally wouldn't be an issue, but I'm trying to retain some other functionality as well:

As a base, I need to be able to have a button that can both show a screen and a new button, and then that new button will hide itself, and hide the screen. Essentially, a button leads to a screen, and has a button that leads back. I've done this previously in my code with no issues:

Code: Select all

screen quest_button():
    if quest_button_visible:
        frame:
            xalign 1.0
            yalign 0.0015
            xsize 445
            ysize 60
            textbutton "View Quest List" xalign 0.5 action [Show("quest_screen"), Hide("quest_button")]

# Define Ren'Py screens to display quest information
screen quest_screen():
    frame:
        text "Quest List:"
        xalign 0.0  # Center the entire frame horizontally
        yalign 0.0  # Center the entire frame vertically
        xsize 1920  # Set the width of the entire frame to cover the screen
        ysize 1080  # Set the height of the entire frame to cover the screen
        background Color("#000000")  # Set the border color to black
        vbox:
            xalign -0.008  # Center the entire frame horizontally
            yalign 0.04  # Center the entire frame vertically
            # Display buttons for each quest title
            for quest_id, quest in quests.items():
                if quest.current_step > 0:
                    textbutton quest.title action [Show("QuestDetails", quest_id=quest_id)]
        frame:
            xalign 1.0
            yalign 0.0
            xsize 445
            ysize 60
            textbutton "Return" xalign 0.5 yalign 0.5 action [Show("quest_button"), Hide("quest_screen")]

This displays a constant button unless I tell it not to, and on press, it leads to the screen where it also shows another button leading back. I tried recreating this exact syntax for my squad_screen, but it tells me I am missing a required argument, 'squad_NPCs'. Here's the full function:

Probably not an important part, but I'll include it for clarity:

Code: Select all

    squad_NPCs = []
    # Create an instance of the Derek character
    derek_Instance = Derek("Derek", "Martial", level=1, health_offset=0, power_offset=0, spell_slots_offset=0, ability_offsets=None, strength=4, constitution=4, dexterity=4, intelligence=4, wisdom=4, charisma=4)
    # Append the Bandit instance to specific_NPCs list
    squad_NPCs.append(derek_Instance)


This is essentially taking information from a massive NPC class, and then making an instance of an NPC I created. This is the base example for testing the squad information screen I am making. Here's the more relevant passage:

Code: Select all

screen squad_screen_button:
    frame:
        xalign 1.0
        yalign 0.195
        xsize 445
        ysize 60
        textbutton "View Squad Screen" xalign 0.5 action [Show("squad_screen", squad_NPCs=squad_NPCs)]

screen squad_screen(squad_NPCs):
    frame:
        background Color("#C0C0C0")  # Grey Background
        frame:
            xalign 1.0
            yalign 0.14
            xsize 445
            ysize 60
            textbutton "Close Squad Screen" xalign 0.5 action [Show("squad_screen_button"), Hide("squad_screen")]

    tag menu

    # Use a grid to layout the NPC boxes and the Player box
    grid 0 0:
        spacing 5

        # First column for NPCs
        grid 0 0:
            spacing 5
            
            # First column for NPCs
            for i, npc in enumerate(squad_NPCs):
                if i % 2 == 0: # If it's an even index, put it in the first column
                    vbox:
                        text "[npc.name]"
                        hbox:
                            text "Str: [npc.strength] Dex: [npc.dexterity] Con: [npc.constitution]"
                        hbox:
                            text "Wis: [npc.wisdom] Int: [npc.intelligence] Cha: [npc.charisma]"
                        hbox:
                            # Health bar
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Health / float(npc.total_Health)]" # The bar fill ratio
                                text "[npc.current_Health]/[npc.total_Health]" at center
                                
                            # Spell Slots
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Slots / float(npc.total_Slots)]"
                                text "[npc.current_Slots]/[npc.total_Slots]" at center

                            # Power Slots
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Power / float(npc.total_Power)]"
                                text "[npc.current_Power]/[npc.total_Power]" at center

        # Second column for NPCs
        grid 1 0:
            spacing 5
        
            # Second column for NPCs
            for i, npc in enumerate(squad_NPCs):
                if i % 2 != 0: # If it's an odd index, put it in the second column
                    vbox:
                        text "[npc.name]"
                        hbox:
                            text "Str: [npc.strength] Dex: [npc.dexterity] Con: [npc.constitution]"
                        hbox:
                            text "Wis: [npc.wisdom] Int: [npc.intelligence] Cha: [npc.charisma]"
                        hbox:
                            # Health bar
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Health / float(npc.total_Health)]" # The bar fill ratio
                                text "[npc.current_Health]/[npc.total_Health]" at center
                                
                            # Spell Slots
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Slots / float(npc.total_Slots)]"
                                text "[npc.current_Slots]/[npc.total_Slots]" at center

                            # Power Slots
                            frame:
                                # background "bar_background.png"
                                bar value "[npc.current_Power / float(npc.total_Power)]"
                                text "[npc.current_Power]/[npc.total_Power]" at center

    # Player box at the bottom outside the grid of NPC boxes
    vbox:
        align (.5, 1.0) # This will center align the player box at the bottom
        text "[player.name]"
        hbox:
            text "Str: [player.characterStrength] Dex: [player.characterDexterity] Con: [player.characterConstitution]"
        hbox:
            text "Wis: [player.characterWisdom] Int: [player.characterIntelligence] Cha: [player.characterCharisma]"
        hbox:
            # Health bar for Player
            frame:
                # background "bar_background.png"
                bar value "[player.currentHealth / float(player.totalhealth)]"
                text "[player.currentHealth]/[player.totalhealth]" at center
                
            # Spell Slots for Player
            frame:
                # background "bar_background.png"
                bar value "[player.currentSpellSlots / float(player.totalSpellSlots)]"
                text "[player.currentSpellSlots]/[player.totalSpellSlots]" at center

            # Power Slots for Player
            frame:
                # background "bar_background.png"
                bar value "[player.currentPowerSlots / float(player.totalPowerSlots)]"
                text "[player.currentPowerSlots]/[player.totalPowerSlots]" at center
I tried a few other solutions too. Trying to make it a global variable, to see if it was a scope problem. I tried to create what I like to call a "stopgap" label, to pass information to a label, and then pass that to a screen, and I tried even passing parameters to that "stopgap", to no avail:

Code: Select all

# Making it a global variable:

init python:
    global squad_NPCs
    squad_NPCs = []
screen squad_screen(squad_NPCs):
    ...
    for i, npc in enumerate(globals["squad_NPCs"]):

# Calling a "stopgap" label:

    textbutton "View Squad Screen" xalign 0.5 action [call show_squad_screen]

label show_squad_screen():
    $ renpy.hide("squad_screen_button")
    $ renpy.call_screen("squad_screen")

label hide_squad_screen():
    $ renpy.hide("squad_screen")
    $ renpy.show("squad_screen_button")

# Passing parameters to the stopgap:

label show_squad_screen(squad_NPCs):
    $ renpy.hide("squad_screen_button")
    $ renpy.call_screen("squad_screen", squad_NPCs=squad_NPCs)

label show_squad_screen():
    $ renpy.hide("squad_screen_button")
    $ renpy.call_screen("squad_screen", squad_NPCs=squad_NPCs)

All return the same error. Somehow, I am missing an argument somewhere: 'squad_NPCs'. Though that makes no sense. There is only one area where I call it:

Code: Select all

screen squad_screen(squad_NPCs):
I suppose I call it here too:

Code: Select all

for i, npc in enumerate(squad_NPCs):
But that is within the screen. I never get that far. I get a crash on trying to show the screen. No matter what additions, or corrections I make, the error never changes.

Somehow I feel like this is a really simple solution, but it is evading me. I think it might have to do with the syntax of passing a list as a parameter to a screen, but regardless of what I've tried, this is the error it returns:

I'm sorry, but an uncaught exception occurred.

While running game code:
File "game/script.rpy", line 12, in script
menu:
TypeError: missing a required argument: 'squad_NPCs'

-- Full Traceback ------------------------------------------------------------

Full traceback:
File "game/script.rpy", line 12, in script
menu:
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\ast.py", line 1618, in execute
choice = renpy.exports.menu(choices, self.set, args, kwargs, item_arguments)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\exports.py", line 1109, in menu
rv = renpy.store.menu(new_items)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\exports.py", line 1364, in display_menu
rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\ui.py", line 301, in interact
rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\core.py", line 2165, in interact
repeat, rv = self.interact_core(preloads=preloads, trans_pause=trans_pause, pause=pause, pause_start=pause_start, pause_modal=pause_modal, **kwargs) # type: ignore
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\core.py", line 2687, in interact_core
root_widget.visit_all(lambda d : d.per_interact())
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\displayable.py", line 431, in visit_all
d.visit_all(callback, seen)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\displayable.py", line 431, in visit_all
d.visit_all(callback, seen)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\displayable.py", line 431, in visit_all
d.visit_all(callback, seen)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\screen.py", line 480, in visit_all
callback(self)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\core.py", line 2687, in <lambda>
root_widget.visit_all(lambda d : d.per_interact())
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\screen.py", line 491, in per_interact
self.update()
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\display\screen.py", line 697, in update
self.screen.function(**self.scope)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\parameter.py", line 429, in apply_arguments
return parameters.apply(args or (), kwargs or {}, ignore_errors)
File "C:\Users\6ft5r\Desktop\Ren'py\renpy-8.2.1-sdk\renpy\parameter.py", line 283, in apply
raise TypeError(msg) # from None
TypeError: missing a required argument: 'squad_NPCs'
```

Ignore the part about the script.rpy and the menu, that's just referring to where the crash occurs. Its a debugging statement I use to test a lot of different functionalities. I've looked through and commented everything out, or removed elements. Nothing seems to cause this error on that screen. It just crashes on trying to call squad_screen.

Any help anyone could render would be greatly appreciated. Thank you!

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

Re: Passing a list parameter to a screen

#2 Post by m_from_space »

AWizardWithWords wrote: Fri Apr 19, 2024 5:32 pm Any help anyone could render would be greatly appreciated. Thank you!
Just make SquadNPCs a global variable the right way and then do not use any screen arguments anymore. I mean why pass it around like this, if it will always be this list? Arguments are useful if they change.

Do NOT create variables inside python blocks, Renpy treats them as constants!

Code: Select all

default derek_Instance = Derek("Derek", "Martial", level=1, health_offset=0, power_offset=0, spell_slots_offset=0, ability_offsets=None, strength=4, constitution=4, dexterity=4, intelligence=4, wisdom=4, charisma=4)

default squad_NPCs = [derek_Instance]

screen squad_screen():
    ...
    for i, npc in enumerate(squad_NPCs):
        ...

Post Reply

Who is online

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