Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Flowchart Plug-In for Ren'Py

Framework for implementing in-game flowcharts for easier navigation · By Devil Spiδεr

KeyError: "

A topic by Laddinger created 84 days ago Views: 70 Replies: 4
Viewing posts 1 to 5
(1 edit)

Hello, I'm getting the following error when I try to access the flowchart screen in my game:

[code]

I'm sorry, but an uncaught exception occurred.

While running game code:

  File "game/text files/flowchart.rpy", line 103, in execute

    screen flowchart():

  File "game/text files/flowchart.rpy", line 103, in execute

    screen flowchart():

  File "game/text files/flowchart.rpy", line 108, in execute

    use game_menu(_("Flowchart"), scroll="viewport"):

  File "game/text files/screens.rpy", line 510, in execute

    screen game_menu(title, scroll=None, yinitial=0.0):

  File "game/text files/screens.rpy", line 510, in execute

    screen game_menu(title, scroll=None, yinitial=0.0):

  File "game/text files/screens.rpy", line 519, in execute

    frame:

  File "game/text files/screens.rpy", line 522, in execute

    hbox:

  File "game/text files/screens.rpy", line 528, in execute

    frame:

  File "game/text files/screens.rpy", line 531, in execute

    if scroll == "viewport":

  File "game/text files/screens.rpy", line 533, in execute

    viewport:

  File "game/text files/screens.rpy", line 542, in execute

    vbox:

  File "game/text files/screens.rpy", line 543, in execute

    transclude

  File "game/text files/flowchart.rpy", line 108, in execute

    use game_menu(_("Flowchart"), scroll="viewport"):

  File "game/text files/flowchart.rpy", line 109, in execute

    vbox:

  File "game/text files/flowchart.rpy", line 111, in execute

    viewport:

  File "game/text files/flowchart.rpy", line 134, in execute

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

  File "game/text files/flowchart.rpy", line 134, in keywords

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

  File "game/text files/flowchart.rpy", line 134, in <module>

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

KeyError: ''

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

Full traceback:

  File "renpy/common/_layout/screen_load_save.rpym", line 35, in script

    $ ui.interact()

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\ast.py", line 1138, in execute

    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\python.py", line 1122, in py_exec_bytecode

    exec(bytecode, globals, locals)

  File "renpy/common/_layout/screen_load_save.rpym", line 35, in <module>

    $ ui.interact()

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\ui.py", line 299, in interact

    rv = renpy.game.interface.interact(roll_forward=roll_forward, **kwargs)

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 3579, 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\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 4052, in interact_core

    root_widget.visit_all(lambda d : d.per_interact())

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 681, in visit_all

    d.visit_all(callback, seen)

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 681, in visit_all

    d.visit_all(callback, seen)

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 681, in visit_all

    d.visit_all(callback, seen)

  [Previous line repeated 1 more time]

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\screen.py", line 476, in visit_all

    callback(self)

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\core.py", line 4052, in <lambda>

    root_widget.visit_all(lambda d : d.per_interact())

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\screen.py", line 487, in per_interact

    self.update()

  File "C:\Users\ladil\OneDrive\Desktop\Games\Renpy\renpy-8.0.3-sdk\renpy\display\screen.py", line 680, in update

    self.screen.function(**self.scope)

  File "game/text files/flowchart.rpy", line 103, in execute

    screen flowchart():

  File "game/text files/flowchart.rpy", line 103, in execute

    screen flowchart():

  File "game/text files/flowchart.rpy", line 108, in execute

    use game_menu(_("Flowchart"), scroll="viewport"):

  File "game/text files/screens.rpy", line 510, in execute

    screen game_menu(title, scroll=None, yinitial=0.0):

  File "game/text files/screens.rpy", line 510, in execute

    screen game_menu(title, scroll=None, yinitial=0.0):

  File "game/text files/screens.rpy", line 519, in execute

    frame:

  File "game/text files/screens.rpy", line 522, in execute

    hbox:

  File "game/text files/screens.rpy", line 528, in execute

    frame:

  File "game/text files/screens.rpy", line 531, in execute

    if scroll == "viewport":

  File "game/text files/screens.rpy", line 533, in execute

    viewport:

  File "game/text files/screens.rpy", line 542, in execute

    vbox:

  File "game/text files/screens.rpy", line 543, in execute

    transclude

  File "game/text files/flowchart.rpy", line 108, in execute

    use game_menu(_("Flowchart"), scroll="viewport"):

  File "game/text files/flowchart.rpy", line 109, in execute

    vbox:

  File "game/text files/flowchart.rpy", line 111, in execute

    viewport:

  File "game/text files/flowchart.rpy", line 134, in execute

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

  File "game/text files/flowchart.rpy", line 134, in keywords

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

  File "game/text files/flowchart.rpy", line 134, in <module>

    add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

KeyError: ''

Windows-10-10.0.26100 AMD64

Ren'Py 8.1.1.23060707

EveBloom 2.0

Thu Mar 27 08:47:38 2025

[/code]

This is how I formatted the screen:

[code]screen flowchart():

    tag menu

    default select_node = None

    use game_menu(_("Flowchart"), scroll="viewport"):

        vbox:

            align (0.5, 0.5)

            viewport:

                xalign 0.5

                xysize (1025, 625) # Change this to your flowchart's image size + 25 on each axis

                child_size (1000, 600) # Change this to your flowchart's image size

                mousewheel True

                scrollbars "vertical"

                edgescroll (150, 2000) # Optional

                draggable True

                xinitial 0.5

                for img, cnd in extra_lines.items():

                    if eval(cnd):

                        add "game/flowchart/" + img + ".png"

                imagemap:

                    ground "flowchart/ground.png"

                    idle "flowchart/idle.png"

                    hover "flowchart/hover.png"

                    insensitive "flowchart/insensitive.png"

                    selected_idle "flowchart/selected_idle.png"

                    selected_hover "flowchart/selected_hover.png"

                    for i in segments:

                        hotspot nodes[i][0] + gui.flow_hotspot_size:

                            action SetScreenVariable("select_node", i)

                            sensitive eval(nodes[i][3])

                add 'flowchart/crosshair.png' xpos nodes[segment][0][0] ypos nodes[segment][0][1]

            if select_node:

                text nodes[select_node][1]

                text nodes[select_node][2]

                textbutton "Jump" action [SetVariable("segment", select_node), Start(select_node)]

                if flow_choices.get(select_node):

                    text flow_choices[select_node][0]

                    hbox:

                        for t in flow_choices[select_node][1]:

                            textbutton t[0] action eval(t[1])[/code]


Any help would be greatly appreciated, thank you!

Developer (1 edit)

Did you define your flowchart segments, images and any other features as documented in the in-file documentation or did you put the script as it is and ran the game that way?

P.S. If you are in the DevTalk discord server, I’m available there as well.

Thank you for your speedy response, yes I believe I've defined the flowchart segments and I'm using the images provided with the original coding. Please let me know if I mistunderstood anything:

In the script file:

label MarshVisit3:

    $ segment = "Marsh"

    $ new_node("Marsh Start")

    $ unlock_node("Marsh Start")

    $ finished.append("marshv3")

Choice  and branch example:

    menu:

        "That's fine.":

            $ mary_points += 1

            $ finished.append("Consensual Route")

            jump MaryMarshVisit3

        "...I mean.":

            $ story_flags["marsh_route"] = "disrespect"

            $ ann_points += 1

            $ finished.append("Maid Route")

            jump AnnMarshVisit3

    label MaryMarshVisit3:

        $ new_node("That's fine.")

        $ unlock_node("That's fine.")

In the flowchart file:

init python:

    def new_node(n=None):

        global segment, segments

        if segment not in segments:

            segments.append(segment)

        segment = n

    # This is a function that adds a completed ending - usually named after the label it's in - to the endings list. You can call len(endings) to track amount of endings

    def unlock_ending(n=None):

        global endings

        if n not in endings:

            endings.append(n)

    # Use this alongside unlock_ending to make the ending accessible from the flowchart

    def unlock_node(n=None):

        global segments

        if n not in segments:

            segments.append(n)

    ##### STORY NODES #####

    # This is where you fill out information for all nodes in your game

    # The format is: "label": [(x coordinate, y coordinate), "name", "description", "condition"],

    # Coordinates are for the imagemap's buttons to render correctly - they tell the upper-left corner of an imagebutton hotspot

    # condition is a string containing either a Python expression or True - if the expression evaluates to false, the node can't be selected from the menu.

    nodes = {

        "MarshVisit3": [(450, 0), "Marsh Start", "It begins.", "True"],

        "MarshVisit3Return": [(500, 0), "Delayed Marsh Start", "Finally...", "True"],

        "MaryMarshVisit3": [(350, 200), "Consensual Route", "This is enough for me.",],

        "MaryConsentVisit1": [(350, 300), "Consensual Route2", "Better play it safe.", "True"],

        "ConsensualStart": [(350, 400), "Consensual Route3", "Everything's going well...?", "True"],

        "MarshConsentEnd": [(350, 500), "Consensual Route Ending", "Picture perfect.", "story_flags['marsh_route'] == 'consensual'"],

        "AnnMarshVisit3": [(400, 200), "Maid Route", "It would be a waste otherwise... right?", "True"],

        "AnnConsentVisit1": [(400, 300), "Maid Route2", "It should be fine.", "True"],

        "MaidStart": [(400, 400), "Maid Route3", "Well done.", "True"],

        "MarshMaidEnd": [(550, 400), "Maid Routte Ending", "Perfection.", "story_flags['marsh_route'] == 'maid'"],

    }

    gui.flow_hotspot_size = (100, 100) # X and Y size of a node - if your hotspots are sized differently, change this


Developer

From what I understand, your calls of the new_node and unlock_node functions are either referencing the description of the name of the node, when they should be called with the label name.

If you are a DevTalk member, you can also go there where I’m more active.

I tried changing the nodes to the labels they're under but that error is still persisting unfortuantely. And oh, yes I am thank you I'll move to there!