[Tutorial] Making a Separate Content Patch

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
User avatar
Belgerum
Regular
Posts: 110
Joined: Thu Nov 06, 2014 12:24 am
Skype: belgerum09
Soundcloud: Belgerum
itch: Belgerum
Contact:

[Tutorial] Making a Separate Content Patch

#1 Post by Belgerum »

Not sure if this will be of use to anyone really important, but since I programmed this myself for the sake of a project, I thought I'd share a simple, easy way to make a Ren'Py game with a separately-distributable content patch. This allows you to add, remove, or change content in a game based on whether a patch file is present.

This might be used to make DLC patches that add routes, characters, or other content to a base game, but are distributed or sold separately.

It also might be used to make "mature" game patches that uncensor images and add sex or gore scenes to the game script, while leaving that content out of the base game.


Step 1: Set up the directory for the patch

Image

First, you should create a new folder in your game directory. This is where we will put all of the content we want to include in the patch, but not the base game. Make sure that your game can run smoothly even without anything you put in there, since the patch will be detachable from the game later.

Image

Inside the patch folder, make an RPY file. We will use this file to control how the patch functions. Also, put any images, music, or files that will be patched into the game inside the patch folder. By putting them here, we can make it so these files are included with the patch, and don't take up extra file space in the base game.

Step 2: Make the patch change a persistent variable on game startup, and define patch assets.

Now, we're going to set a persistent variable. First, we put this code in the regular script.rpy, above the start label:

Code: Select all

init -3 python:
    persistent.patch_installed = False
init -1 python:
    if persistent.patch_installed and not persistent.patch_first_time:
        persistent.patch_enabled = True
        persistent.patch_first_time = True
    elif not persistent.patch_installed:
        persistent.patch_first_time = False
        persistent.patch_enabled = False
Then, in the patch RPY file in the new folder you just created, put this:

Code: Select all

init -2:
    $ persistent.patch_installed = True
By placing this code, the game will, when starting the game, set "persistent.patch_installed" to be False. Then, if the patch RPY file is present, it will set it back to being True. Thus, the variable will always be True if the patch is present in the game directory, and False if it is not.

To go a step further, the game will then set a variable "persistent.patch_enabled," which will determine if the patch has been turned on/off by the player if you put an option in the settings menu to turn the patch off without leaving the game.

Next, in the patch RPY file, define all of the new assets that will only be used in the patch, and are contained in the folder. Do this the exact same way as you would at the top of script.rpy.

For example, if you want to make a content patch that adds Lucy to the game, the patch RPY file might look something like this:

Code: Select all

### This file can be used to define content in the patch, and enable the persistent variable if the patch exists.

### Initial Variable Setup:
init -2:
    $ persistent.patch_installed = True

### Declare characters used in the patched content.
define l = Character("Lucy", who_color="#ffcccc")

### Declare images used in the patched content.
image lucy happy = "patch/images/lucy_happy.png"
image lucy mad = "patch/images/lucy_mad.png"

### Declare music and sounds used in the patched content.
define audio.track2 = "patch/audio/track2.ogg"
define audio.punch = "patch/audio/punch.wav"
Step 3: Add prompts to your script which change the game based on the persistent variable.

Now for the fun part. Throughout your game, you can test the "persistent.patch_enabled" variable to see if the patch is enabled or not. For example:

Code: Select all

if persistent.patch_enabled:
    jump patch_scene
If the patch is enabled, the game will jump to the new label here. You can put the label and new scene in the patch RPY file, if you don't want to include it in the base game.

Code: Select all

if persistent.patch_enabled:
    show uncensored image
else:
    show censored image

Code: Select all

if persistent.patch_enabled:
    "I film her in the party."
else:
    "I f*** her in the p****."
You can use this to have images and dialogue alternate depending on whether the patch is enabled or not like above.

Code: Select all

menu:
    "I love Eileen":
        jump eileen_romance
    "I love Lucy":
        jump lucy_romance
    "I love both girls" if persistent.patch_enabled:
        jump harem_route
You can also add additional choices to menus if the patch is enabled like the example above. The persistent variable switch can be used to alternate content and add new parts to the game in a large number of ways.

You can also place ConditionSwitch on images, if you want the patch to change how certain characters look without altering tons of code. This might be useful for patches that just add cat ears to characters, or swap some images for others. Here's an example:

Code: Select all

image eileen pose = ConditionSwitch(
    "persistent.patch_enabled", "patch/images/eileen_pose_cat_ears.png",
    "not persistent.patch_enabled", "images/eileen_pose.png"
    )
Optional Step: Make changes to the GUI

For those who want some added functionality out of the patch, and have some added knowledge of screens and customization, you can do the same thing above with Repy's GUI as you can with the script.

For starters, you can add some text to the main menu in screens.rpy if you like, so the player can rest assured that they installed the patch correctly.

Code: Select all

        textbutton _("Start Game") action Start()
        textbutton _("Load Game") action ShowMenu("load")
        textbutton _("Preferences") action ShowMenu("preferences")
        textbutton _("Help") action Help()
        textbutton _("Quit") action Quit(confirm=False)
        
    if persistent.patch_enabled:
        text "Patch applied!" xalign 0.0 yalign 1.0
You can also let the player toggle the patch in the preferences menu by adding a binary switch to the screen:

Code: Select all

if persistent.patch_installed:
    frame:
        style_group "pref"
        has vbox

        label _("Patch")
        textbutton _("On") action [SetField(persistent, "patch_enabled", True), SelectedIf(persistent.patch_enabled)]
        textbutton _("Off") action [SetField(persistent, "patch_enabled", False), SelectedIf(not persistent.patch_enabled)]
Step 4: Build a distribution with Renpy, and separate the files.

Now that you've programmed your game and told it what to do if the patch is enabled or disabled, it's time to build the game distribution and share it with the world! Hit that button on the Renpy Launcher that says "Build Distributions." If you are prompted to add build information to the end of options.rpy, say "yes."

Now that you're sure you have the build information on the bottom of options.rpy, open it up and take a look. You can modify the archive settings if you like, but the most important part is that you archive the patch folder to a separate file.

Code: Select all

    build.archive("Patch", "all")
    build.classify('game/patch/**.**', 'Patch')
This makes Renpy label all files and subfolders in the "patch" folder we created earlier to be compressed into a single RPA file when you build a game distribution.

After you've finished modifying the code, go back to the Renpy Launcher and finish building the distributions. Extract the ZIP file that is created, and you should find that the patch folder is gone, replaced by a Patch.rpa file.

Image

This is your completed game version, already patched! The distribution will run as if the patch was installed as long as the Patch.rpa stays in the game folder. To make the game run without the patched material, simply move or delete the Patch.rpa file. You can also feel free to rename the Patch.rpa file to whatever you like, as long as it remains a RPA file, and is in the correct directory.

A sample game is attached below, to show an example of how this works. When the patch is installed and enabled, a different ending will occur. Let me know if you have questions.
Attachments
Unpatched Build.zip
The distribution build from Renpy, with the patch file removed.
(30.61 MiB) Downloaded 173 times
Patch.zip
The patch, taken from the distribution build's game folder.
(1.07 MiB) Downloaded 212 times
Source Files.zip
Source files for the project before building the distribution.
(6.45 MiB) Downloaded 185 times
Last edited by Belgerum on Sun Mar 03, 2024 3:11 am, edited 7 times in total.

Hesyisytehray
Newbie
Posts: 6
Joined: Tue Dec 12, 2017 6:53 am
Projects: Your Life Is A Failure Simulator
Organization: S.H.Y.
IRC Nick: Hesyisytehray
Tumblr: hesyisytehray
Deviantart: Hesyisytewithhray
Github: hesyisytehray
Skype: Hesyisytehray
Soundcloud: Hesyisytehray
itch: hesyisytehray
Location: SEA
Contact:

Re: [Tutorial] Making a Separate Content Patch

#2 Post by Hesyisytehray »

Nice, actually it will come in handy as long as people finds no better way to replace patches.

Good job!

User avatar
Milkymalk
Miko-Class Veteran
Posts: 753
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: [Tutorial] Making a Separate Content Patch

#3 Post by Milkymalk »

Good to see this in action, nice tutorial. However, I still wonder how I can actually CHANGE stuff with a patch - I mean stuff that was present before I even thought of the patch. Like, overwrite screens, functions and labels.
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

User avatar
Belgerum
Regular
Posts: 110
Joined: Thu Nov 06, 2014 12:24 am
Skype: belgerum09
Soundcloud: Belgerum
itch: Belgerum
Contact:

Re: [Tutorial] Making a Separate Content Patch

#4 Post by Belgerum »

Milkymalk wrote: Fri Dec 15, 2017 12:13 pm Good to see this in action, nice tutorial. However, I still wonder how I can actually CHANGE stuff with a patch - I mean stuff that was present before I even thought of the patch. Like, overwrite screens, functions and labels.
Using this method, you won't be able to directly overwrite anything in a base game. This only works from the perspective of a developer who wants to make a patch for their game, and who can update the base game to allow for the patch's functions.

User avatar
Milkymalk
Miko-Class Veteran
Posts: 753
Joined: Wed Nov 23, 2011 5:30 pm
Completed: Don't Look (AGS game)
Projects: KANPEKI! ★Perfect Play★
Organization: Crappy White Wings
Location: Germany
Contact:

Re: [Tutorial] Making a Separate Content Patch

#5 Post by Milkymalk »

Yes, but sometimes a developer also wants to change something in order to make the patch work: Update a game menu, add an option in a choice menu for additional branching etc.
Crappy White Wings (currently quite inactive)
Working on: KANPEKI!
(On Hold: New Eden, Imperial Sea, Pure Light)

User avatar
Belgerum
Regular
Posts: 110
Joined: Thu Nov 06, 2014 12:24 am
Skype: belgerum09
Soundcloud: Belgerum
itch: Belgerum
Contact:

Re: [Tutorial] Making a Separate Content Patch

#6 Post by Belgerum »

A developer that wants to patch updates or fixes to a single base game would best find a solution that's simpler and more direct, like replacing the script or archive file(s) in the game directory with a newer version, or just uploading a new build entirely.

I can't predict what situations every developer might face, but in this case, I'm assuming that the developer has control over the base game build, whether it be by patching updates, or because the game is still in development and unreleased.

Either way, that's a problem that would be very situational.

kamti
Regular
Posts: 31
Joined: Sun Apr 12, 2015 1:50 am
Completed: The Book of Bondmaids
Contact:

Re: [Tutorial] Making a Separate Content Patch

#7 Post by kamti »

Thanks for a nice guide!

Work fine for me.
Fits a lot to my current need.

Stampaw
Newbie
Posts: 1
Joined: Sat Mar 02, 2024 10:32 pm
Contact:

Re: [Tutorial] Making a Separate Content Patch

#8 Post by Stampaw »

Hi, the bug I found is when your access "Pref" button in game (bottom bar shortcut) The toggle for Patch Version is disappear and except you quit and re enter the game, you won't be able to see the toggle at all. You know how to fix this error?

Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot]