Guide:Ren'Py visual novels on Steam/External patch

From VNDev Wiki
Revision as of 13:53, 19 February 2025 by Ironnori (talk | contribs) (nocat)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Create an Externally-Distributed Nudity Patch This guide is intended to help you with a high-level overview of how to add such content, but it is strongly recommended that you are extremely comfortable with Ren'Py and coding before attempting to add a nudity patch.

The first thing to remember is that the guidelines for Adult Content in Steam are based on all files uploaded to Steam, even if those files are not actually accessible in the game. This means that you cannot simply hide all adult content and lewd images behind a Ren'Py define, and have a patch that enables them again. You must actually have separate versions of images and textual content between the Steam version and the patch.

Before starting this, it is recommended that you are very comfortable both with how define in Ren'Py works, as well as how file archiving works in Ren'Py – particularly in how you set up additional rpa archives and add files to them.

One Define to Rule Them All

The first thing you'll want to do is determine if the game is running in a "lewd" version or not. Somewhere in your base game (such as in options.rpy), add the following lines:

define patch_installed = False
define patch_version = 1
define expected_patch = 1

Handle All Images

For each image that has a lewd and "clean" version, you will need to define a new image for it. For example, let's say Eileen has a naked outfit that is used as part of her layeredimage.

Define a ConditionSwitch for that outfit:

image eileen_outfit_naked = ConditionSwitch("patch_installed", "images/lewd/sprites/eileen_naked_lewd.png", "True", "images/sprites/eileen/naked_clean.png")

In the base game, make sure there's a clean version of the image (maybe she's wearing lingerie) as images/sprites/eileen/naked_clean.png. (It's okay that images/sprites/lewd/eileen_naked_lewd.png does not exist yet.)

You'll need to prepare all images in this way, referencing yet-nonexistent files for the lewd versions

Handle All Text

For each bit of dialogue that can be lewd, you'll need to call a lewd version of the label. Likewise, it's okay if this doesn't exist yet.


label sexy_scene:
    if patch_installed:
        call sexy_scene_lewd
    else:
        call sexy_scene_clean
    "The game continues after the sexy scene."
    ...MORE...

label sexy_scene_clean:
    "You and Eileen go to the ice cream parlor."
    "She gets ice cream everywhere!"
    return

Handle Patch Versioning (Optional)

The versioning variables are useful for when you make future changes that require a net new patch file, such as adding additional images with corresponding lewd versions, or additional lewd scenes.

You can perform checks such as


if patch_installed and patch_version != expected_patch:


in various locations (such as on screen main_menu or label start) to display error messages to the user if their patch file is out of date.

For example:


screen main_menu():
    if patch_installed and patch_version != expected_patch:
        text "Your nudity patch is out of date! Download the newest version!"

Make The Clean Build

You should now have a version of the game that is generally clean and ready for Steam. Make a build normally, play through the game, and ensure that everything generally works, especially the places where you have soon-to-be-lewd images and text.

Make a Lewd Project

Copy the entirety of your base game into a new Ren'Py project, and create a new rpy file (for example, lewd.rpy) that overrides the patch define:


init 10 python:
    patch_installed = True
    expected_patch = 1

You can also include the NSFW versions of scenes in this file (or create new rpy files for them). Write these normally.


label sexy_scene_lewd:
    "You and Eileen go to a special massage parlor."
    "It is {i}very{/i} special."
    "Sex sex sexy sex boner boner uterus."
    return

You'll also want to add the lewd images into this project. It's easier if they're all in a single directory (ex: images/lewd), but you'll need to make sure they're included in the appropriate locations as referenced by your image definitions.

Run this project normally and ensure now that all lewd scenes and images appear as desired in the appropriate places.

Make the Nudity Patch

Update the archive settings in your lewd project to build the appropriate files into a new rpa archive. For example, if you have lewd.rpy and images/lewd, you would use the following archive code:


init python:
    build.archive("nudity", "all")
    build.classify("game/images/lewd/**", "nudity")
    build.classify("game/lewd.rpyc", "nudity")

(You could also put this directly in lewd.rpy if desired. It shouldn't make a difference, but ensure the file where this code lives is lexographically before options.rpy or whatever you've defined your other archiving code.)

Build the game normally (you only need to make one distribution, ex: Windows) and grab the resulting nudity.rpa file out of the resulting ZIP file (under game/).

Test The Patch

Take your basic build of the base game, and then paste the nudity.rpa file into the game/ directory. Run that executable and ensure that the lewd content works properly now.

You can now upload the clean version of your game to Steam, and provide nudity.rpa for separate download to patch the game. (This can even be done as Steam DLC so users don't have to follow patching instructions.)