Not so long ago I decided to create a sandbox-VN game, inspired by games like Corrupted Kingdoms, Hero's Harem Guild or Harem Hotel. I wanted to implement quests and automatically show scenes (I will call VN blocks scenes to separate them from events that I'm using in programming sense) whenever player fulfilled conditions.
Let's look at some example scenario: When player goes to Kitchen at night, a scene should start playing.
The simplest and most common way (at least from what I've seen and read) is to create if statement in location:
For single scene it works and there's no problem, but what if we have more scenes that starts in the Kitchen location, or more conditions, or maybe the scene can be triggered in kitchen and dining room. All of those things will eventually lead to the "if hell" as I call it. 10+ if statements called every time player enters a location even if the scenes were played and will never trigger again. It may not cause performance issues but it's probably gonna cause some headaches in case something goes wrong or the dev changes his mind about something.
The solution I found is to mimic the C# events in python and use them to trigger whatever we want.
For our scenario I created a VNScene class in python.
Then we create object from our class.
Now, let's create our events.
iadd and isub methods allow us to use += and -= operators
Now lets go back to our VNScene class, add two new method and modify start_scene method.
Now whenever we want that scene to be available for player, we call
After scene has been played, we unregister events, so we no longer track them.
Now to use events we use them as methods.
I hope this tutorial was in any way helpful.
Let's look at some example scenario: When player goes to Kitchen at night, a scene should start playing.
The simplest and most common way (at least from what I've seen and read) is to create if statement in location:
Python:
label Kitchen:
#some location code
if time == "night":
jump some_scene
#some location code
The solution I found is to mimic the C# events in python and use them to trigger whatever we want.
For our scenario I created a VNScene class in python.
Python:
init python:
class VNScene(store.object):
def __init__(self, label_name, conditions):
self.label_name = label_name #name of the label with the scene we want to play
self.conditions = conditions #list of conditions to trigger scene, remember that it should be dictionary
def check_conditions(self):
if all(eval(c) for c in self.conditions.values()):
self.start_scene()
def start_scene(self):
renpy.jump(self.label_name)
Python:
define conditions = {
"location": "location == \"Kitchen\"",
"time": "time == \"night\""
}
default scene_obj = VNScene("some_scene", conditions)
Python:
init python:
class Event(store.object):
def __init__(self): #constructor
self.__event_handlers = []
def __iadd__(self, handler):
if all(not id(handler) == id(h) for h in self.__event_handlers):
self.__event_handlers.append(handler)
return self
def __isub__(self, handler):
self.__event_handlers.remove(handler)
return self
def __call__(self, *args, **keywargs):
for event_handler in self.__event_handlers:
event_handler(*args, **keywargs)
default on_location_change = Event()
default on_time_change = Event()
Now lets go back to our VNScene class, add two new method and modify start_scene method.
Python:
init python:
class VNScene(store.object):
def __init__(self, label_name, conditions):
self.label_name = label_name #name of the label with the scene we want to play
self.conditions = conditions #list of conditions to trigger scene, remember that it should be dictionary
def check_conditions(self):
if all(eval(c) for c in self.conditions.values()):
self.start_scene()
def start_scene(self):
self.unregister()
renpy.jump(self.label_name
def register(self):
for c in self.conditions:
if c == "location":
store.on_location_change += self.check_conditions
if c == "time":
store.on_time_change += self.check_conditions
def unregister(self):
for c in self.conditions:
if c == "location":
store.on_location_change -= self.check_conditions
if c == "time":
store.on_time_change -= self.check_conditions
Python:
scene_obj.register()
Now to use events we use them as methods.
Python:
store.on_location_change() #whenever we change location
store.on_time_change() #whenever time changes