I've recently had some headaches with Ren'py overwriting functions when passing keywords to labels.
For example, I have a JRPG-esque battle engine. I define a function to start a battle within Ren'py.
Code: Select all
# File: tern_functions.rpy
# This functions are used only in the renpy script.
init -19 python:
def conflict(participants):
"""
Creates a conflict and moves the player to the conflict label.
"""
Conflict(participants)
An instance of
Conflict stores the data for the current battle, and deals with some battle logic.
Code: Select all
# File: conflict.py
# This is imported to Renpy
class Conflict(object):
def __init__(self, actors, player_start=True):
# Some init code...
def begin_conflict(self):
"""
Begins the conflict and send us to the conflict screens.
:return: None
"""
self.step()
menus.jump('conflict_start', conflict=self)
The
menus.jump is essentially Ren'py's call function in disguise. The conflict_start label looks like
Code: Select all
label conflict_start(conflict):
"Hoi!"
python:
menus.s_choice("The conflict starts!")
conflict.step()
player.participant.is_in_conflict = True
jump('conflict_action_phase', actor=conflict.next_actor(), conflict=conflict)
However, once the code reaches this label conflict, instead of becoming the function in tern_functions.rpy, becomes a object of
Conflict once the text "Hoi" displays. It should stay as the function.
If I call the conflict parameter 'con' instead of 'conflict' then the conflict function is not overwritten.
I've tried to mimic this in pure python but couldn't, so I figure
label conflict_start(conflict): is somehow setting the conflict function equal to the conflict object I pass into the label.
It's easy enough to avoid this by renaming the conflict function or the conflict keyword in the label. It's just annoying because I must avoid passing labels names that are used as functions. I have a decent amount of functions and a decent amount of parameters to pass into labels. The code reads clearer when I do not have to abbreviate variables to avoid overwriting functions with the same name. Mostly though, I do not expect this to happen and I worry that this will cause people bugs.
(Below is the custom jump code. I doubt it has anything to do with the problem, but I'm putting it here just in case.)
Code: Select all
# File: promenus.py
import renpy.exports as renpy
class ProMenus(object):
#init some stuff...
def jump(self, label, clear_stack=True, add_to_stack=True, *args, **kwargs):
"""
Jumps to the label.
:param label: String of the label we are jumping to.
:param clear_stack: Boolean. If true, clear the stack.
:param add_to_stack: If true, add the label to the stack. This is done after clearing the stack.
:param container: If not none, then go the that container's menu.
:param user: Actor that is doing something. Used with containers
:return: Label we jumped to. (Return for testing purposes.)
"""
# Update entire game state.
self.step()
# Decide if we clear the menu stack
if clear_stack:
self.stack.clear()
# Add label to stack.
if add_to_stack:
self.stack.push(label)
# Have Ren'py jump to the label. We cannot pass it empty kwargs or args,
# so we go through many cases.
if kwargs and args:
self.renpy.call(label, *args, **kwargs)
if kwargs:
self.renpy.call(label, **kwargs)
if args:
self.renpy.call(label, *args)
else:
self.renpy.call(label)