-
Notifications
You must be signed in to change notification settings - Fork 0
Customize your Custom Campaign
This section covers a few more topics that may help you customize your custom campaign. These are not required but may be helpful for you.
To fit your theme better, you may want to change more than just the campaign parts.
Please note, although these options exist, I highly recommend using modifiers instead.
So after you have understood the basics of making changes to your custom campaign, I would highly recommend checking out
the modifiers section at the bottom of this page.
First, let's see how to modify the campaign days and the desktop date.
Here is an example to show different types of days when loading into the main game. These will show up on their corresponding day based on the order. The first item in the list corresponds to the first day, the second item to the second day, etc.
"custom_campaign_days_names": ["First Day", "Second Day", "Third Day", "Fourth Day", "Last Day"]It is best to have one element for each day to avoid any non-fitting days.
Now, you might also be interested in how to change the day on the desktop. To do so, provide the following:
"start_year": 1987
"start_month": 11
"start_day": 15With these 3 options, you can set the start date to any preferred day. Please note, due to how the game is coded, that the first day is 1 day after the start day. So if you wish for your game to start on the 15th, provide your start day as the 14th instead.
Some may have noticed that the date format is from the United States. So if you prefer the European date format instead, you can use the following option:
"use_europe_date_format": trueAfter using these options, you may get a result similar to:
You can also provide options to change the desktop loading screen. \
"custom_campaign_loading_desktop_text1": ["First Text loading", "First Text loading.", "First Text loading..", "First Text loading..."],
"custom_campaign_loading_desktop_text2": ["Second Text loading", "Second Text loading\nSecond Text loading 2"]
The loading screen will loop through the first list.
In this example, I added three dots to simulate it loading.
The second option contains the second part of the loading screen, showing the computer startup and login.
In this case, I only provided a dummy text.
Note: Any text in the game you can provide uses Rich Text Markup,
so if you wish to customize it even further, use it at your heart's content!
A simpler option is the username on the desktop screen:
"desktop_username_text": "Different_Username"
As the name suggests, it just changes the username to a different one. Fancy.
Now for a "more" fun part. How to modify the desktop background. The background is split into two parts: first, the logo shown on top, and the actual background. I will first show how to change the background first.
The background in the main game is changed every day and even has a custom one for finishing the game. You can provide the different backgrounds for each day with:
"custom_campaign_desktop_backgrounds": ["1stDayBackground.png", "2ndDayBackground.png", "last3rdDayBackground.png"],
"custom_campaign_desktop_game_finished_background": "IWONTHEGAMEimage.jpg",
"disable_green_color_on_desktop": trueSimilar to how we provided options on how to change the different day names.
Each image in the list corresponds to its corresponding day.
If you wish to have a background for multiple days, just provide the same image.
The second option, as the name suggests, is the background shown after beating your campaign.
Now for the third option. It is used to disable the green color filter over your image. If you wish to show your image in its pure color, use this option. But if you wish to keep the green CRT style of coloring, you can leave it on by not providing it.
Let us talk about the logo now. By default, it shows the Home Safety Hotline logo in the middle of your screen. If you don't care about the logo or do not want it, you can simply disable it with:
"disable_desktop_logo": trueIf, however, you do wish to use it and even modify it, you can use the following options:
"custom_desktop_logo_name": "weird_cat.png"
"custom_desktop_logo_transparency": 0.2627The first option custom_desktop_logo_name provides the image for the logo.
The second option custom_desktop_logo_transparency is used to define how transparent the logo is supposed to be.
By default, it is set to 0.2627.
So if you wish it less transparent, provide a higher number, and if you want it more transparent, provide a lower number.
If you set your background and logo to your heart's content, you should see a result similar to this (or not similar):
Now, as you can see in the image, you can also change the main game's logo and text to a different one with:
"rename_main_game_desktop_icon": "John Safety Hotline"
"main_game_desktop_icon_path": "pizza_cat.png"And that covers all the custom campaign options. Next up is how to add custom callers to your custom campaign so that you can finally test and see it work.
Emails in the game appear on certain days or are unlocked by reaching a certain score in the campaign.
Adding custom emails is done the same way as adding a new custom caller. You create a new file and add these required lines first:
{
"email_subject": "Title of the email here",
"email_sender": "Sender of the email",
"email_body": "Text that inside the email using any rich text markup features.",
"email_custom_campaign_name": "Name of the campaign the email belongs to"
}The first three lines define the email's subject, sender, and body.
These terms should be familiar if you have written an email before.
To attach the email to the custom campaign,
one must only add the line email_custom_campaign_name which adds the email to the custom campaign.
Right now the mail is unlocked by default with no unlock condition.
To change that, you can provide the following lines:
"email_unlock_day": 2,
"email_unlock_threshold": 90With the option email_unlock_day you can specify on which day the email gets unlocked.
And if you combine it with the option email_unlock_threshold,
you can specify at what score from the previous day the email gets unlocked.
So if you had a score of 80%, and you set the threshold to 90, you will not unlock the email, and it won't show up.
This is similar to how the coupons are made in the main campaign.
Now, as you know, you can have a single image at the end of the email show up. You can provide an image for the custom email with:
"email_image": "image_at_the_end_of_the_email.png"You can also provide a video instead of an image via:
"email_animated_image": "video_of_dancing_cat.mp4"If you provided everything correctly, you should see an email like the following appear:
Before we had into the complicated things of emails. Here are a few options you might be interested in:
The first one simply states that the email only unlocks after the player has beaten the game:
"unlock_when_game_finished": trueYou are also able to set the image at the end to be clickable and open a link in the browser via:
"email_click_url": "www.google.de"Please be aware, that this shouldn't be used to open up unwanted or even malicious pages.
There are checks in place that attempt to prevent this, but please use this responsibly.
Now that you have created an email. You may be wondering on how to check for than just a simple threshold.
For this, simply head down to the
Advanced Accuracy Checks and Caller Requirements
section.
There you will see how to check for accuracy on specific days and even check if a caller was correctly answered or not
for an email to unlock.
If you already understood the advanced accuracy checks,
here is an example of an email that only unlock if the player got a score
of 100% (1.0) on day 5 and answered the fifth caller (4) correctly and got the tenth (9) caller wrong:
{
"email_subject": "Title of the email here",
"email_sender": "Sender of the email",
"email_body": "Text that inside the email using any rich text markup features.",
"email_custom_campaign_name": "Name of the campaign the email belongs to",
"email_required_accuracy": 1.0,
"email_accuracy_days": 5,
"email_accuracy_check_type": "geq",
"email_caller_requirement_ids": [4, 9],
"email_caller_requirement_should_be_correct": [true, false]
}Now, for those advanced, you can change emails in the main campaign (disabled by default) with the following line:
"email_in_main_campaign": falseAnd that covers the email section. The next and last section will show you how to add videos on the desktop.
Similar to creating a custom email, we must create a new file to define a video for the custom campaign. You need to provide the following lines:
{
"video_desktop_name": "Name of the video file on the desktop",
"video_file_name": "video_name.mp4",
"custom_campaign_attached": "Name of the campaign"
}The first line defines the name of the file as it should appear on the desktop.
You can make it appear as if it were an actual file or name it as you wish.
The second line video_file_name defines the video file name.
You might have already done the same for the custom campaign end cutscenes.
The third line should be understood already, but it defines which campaign to be attached to.
Similar to emails, you may only want your video to appear on a specific day. You can do so with the following line:
"video_unlock_day": 1After creating a video, it should appear on the desktop like so:
You can also set the custom video to unlock after one has beaten the game by adding this line:
"video_unlock_when_game_finished": trueNow, similar to custom emails, you may also want to check for advanced accuracies or for specific callers.
I won't be covering it again, but you can read up on it in the Advanced Accuracy Checks and Caller Requirements section, which shows how to implement it for custom emails.
If you already understood it, here is an example of a custom video and its requirements:
{
"video_desktop_name": "Name of the video file on the desktop",
"video_file_name": "video_name.mp4",
"custom_campaign_attached": "Name of the campaign",
"video_unlock_day": 1,
"video_required_accuracy": [0.5, 1.0],
"video_accuracy_days": [3, 4],
"video_accuracy_check_type": ["leq", "eq"],
"video_caller_requirement_ids": 5,
"video_caller_requirement_should_be_correct": true
}And that should cover how to add a custom video to the custom campaign.
Adding custom music is done the same way as the previous sections:
{
"custom_campaign_attached": "Custom Campaign Name",
"music_audio_clip_name": "MusicClip1.wav",
"unlock_day": 0
}The first 2 lines should be easy to understand. The first line provides the custom campaign to be attached to, and the second line provides the audio clip to be heard.
The third line is a bit more complicated but similarly known. It sets when the music is allowed to play. By default, any music is allowed to play from the first day. If you increase the unlock days to any higher day, it will only play starting from that day, not any time before.
If you don't wish that to happen, you can set the music to only play on unlock day:
"only_play_on_unlock_day": trueSimilar to custom music, you can add intermission music. Intermission music is music that plays between the callers, meaning while we are waiting for the next caller to call.
For this simply create a new file with:
{
"custom_campaign_attached": "Custom Campaign Name",
"music_audio_clip_name": "MusicClip1.wav",
"unlock_day": 0,
"is_intermission_music": true
}The first three lines are the same as in custom music, the new (fourth line) defines the music to be an intermission music.
You can also define a start and end range for the intermission music.
You can either set a static start/end point by providing a single value:
"start_range": 10,
"end_range": 90If you provide at most two values, it will instead choose between the two values:
"start_range": [10, 20],
"end_range": [70, 90]If you provide three or more values, it will instead pick on of the points inside the list:
"start_range": [5, 20, 40, 50],
"end_range": [20, 70, 90]That covers how to create intermission music.
Adding ringtones is also quite simple. For a simple ringtone, you can use the following basic structure:
{
"custom_campaign_attached": "RingtoneCampaign",
"ringtone_audio_clip_name": "testRingtone.mp3",
"unlock_day": 0
}The first line defines the custom campaign this ringtone belongs to.
The second line provides the audio clip to be played, and the last line defines when this ringtone is unlocked.
Please note, if the unlock day is 0 then it will appear on every day.
If it is set to any other number than 0, it will play only on the provided day. You can change that behavior with:
"only_play_on_unlock_day": falseIf set to false, it will make sure the ringtone plays beginning from that day onward and not just that single day.
If you wish to have a random ringtone for each day, you can also set the ringtone to be appended instead:
"is_append_ringtone": trueThis will add the ringtone into a list, where one ringtone is picked randomly at the beginning of the day. If you also wish to have the default ringtone be able to appear, you can set the following option in your custom campaign JSON:
"do_not_account_default_ringtone": falseIf you also wish to replace the "Network Down" ringtone, you can simply use the following option to replace the warped ringtone:
"is_glitched_version": trueSimilar to video files, you can add text files on the desktop:
{
"custom_campaign_attached": "SecretCampaign",
"text_file_desktop_name": "secrets_v2",
"text_file_contents": "This is text inside the text file. You can see it, if you open the text file in-game.",
"text_file_unlock_day": 0
}The first line defines the custom campaign this text file belongs to. The second line is the desktop label name. And the third line contains the contents of the text file.
The last line "text_file_unlock_day" simply defines from which day on ward this text file will appear on the desktop.
Now, similar to accuracy callers (not covered yet) and emails, you can have more control over the unlock behavior of your text file.
One cool feature that you might want is custom themes!
Custom themes are very similar to in-game themes. You can select them in the in-game settings, or you can make them the default theme for your campaign.
Here is a simple theme for your custom campaign. These are, as are all the other features, contained in a separate JSON file:
{
"theme_custom_campaign_attached": "Quiet On Hallows Eve",
"theme_name": "Default Custom Campaign Theme",
"title_bar_color": [0.5, 1, 1],
"menu_color": [0.325, 0.62, 0.263],
"main_window_color": [0.596, 0.263, 0.62, 0.5],
"entry_font_color": [0.62, 0.263, 0.263]
}The first two lines should be easy to understand. These define in which campaign to show your theme and the name of the theme.
The three lines after the first two define the color and are the main part of the theme.
Each element in the list (for example, [0.325, 0.62, 0.263]) represents one color.
We use the format RGBA (Red, Green, Blue, Alpha) (These can either be in 0-1 format (1 = 100% and 0 = 0%).
Or they can be in 0-255 format (255 = 100% and 0 = 0%)).
You can find many color pickers online to describe the color you want.
The alpha value defines the transparency of the color. You don't need to provide the alpha value,
but you can if you wish to use it.
The last color (entry_font_color) defines the color of the font for entries.
This can be helpful so that you can read it better.
To better understand each color, here is a small image describing each:
Let us continue with a few more options that you might find interesting. One of these is "conditional themes". These themes override a certain theme, but only on certain days. For example, it might be appealing to use for turning every menu option red on the last day. You can do so by adding these lines:
"attached_to_theme": "Default Custom Campaign Theme",
"unlock_day": [0, 1]The first option is to state that it should only override the theme called "Default Custom Campaign Theme". This is to allow the user more freedom when choosing a theme and it not being forced upon the user. Though you may not want the user to change the theme, for that you can add the option inside your custom campaign option (not in the theme file):
"disable_theme_dropdown": trueYou can also set which theme is the default theme of your campaign with:
"defaultTheme": "Default Custom Campaign Theme"Now, if you are interested, you can also add your themes to the main campaign. Please note, this will make it only appear in the main campaign!
"theme_in_main_campaign": trueThat is all for custom themes. Let us move to modifiers.
An accuracy caller is a caller that is only allowed to call if they pass certain accuracies. To make a caller an accuracy caller, you can use the following option:
"is_accuracy_caller": trueAfter you have done so, you can now also provide your criteria. Please note, you can pick between having one or multiple criteria. For a single criterion, here is a simple check:
"accuracy_required": 0.3,
"use_total_accuracy": false,
"accuracy_check_type": "geq"The first line defines what accuracy we check against. In this case, 0.3 refers to 30%.
The second line defines if we wish to use the accuracy of the current day
or if we wish to consider the total accuracy of the entire campaign.
The third and most important line defines what type of check we wish to perform.
The following types of checks exist:
-
eq: (Equal) The current accuracy must be equal to the provided (required) accuracy. -
neq: (Not equal) The current accuracy must not be equal to the provided accuracy. -
geq: (Greater than or equal) The current accuracy must be greater than or equal to the provided accuracy. -
leq: (Less than or equal) The current accuracy must be less than or equal to the provided accuracy. -
none: (None) A placeholder check. This check ignores the required accuracy. Used for testing.
It is also possible to have multiple checks. For this, you can simply provide them in a list manner:
"accuracy_required": [0.3, 0.1, 0.9, 0.8],
"use_total_accuracy": true,
"accuracy_check_type": ["geq", "neq", "eq", "eq"]In the above case, we have 4 different checks. The first check will check for greater than or equal to 30%.
The second check will also check if the current accuracy is not equal to 10%. And so on.
Each check must be true for the caller to appear. If any of them fail, then the caller will be skipped.
As you might have noticed, the total accuracy only provided a single true.
If you only provide a single true for "use_total_accuracy",
it means that every single check in the list will use the total accuracy.
If you wish for each single check to have a different accuracy check,
you can also provide them in a list manner, like so:
"accuracy_required": [0.3, 0.1, 0.9, 0.8],
"use_total_accuracy": [true, false, true],
"accuracy_check_type": ["geq", "neq", "eq", "eq"]Please note, the total accuracy is optional. You don't have to provide the total accuracy for all 4.
In the above case, we only provide 3. The 4th check will use the default value (false).
That covers accuracy callers.
More often than we sometimes like, we may wish to check more than just a generic accuracy.
Or we may wish for something to unlock only if we got a certain caller correct.
For this, we can use accuracy checks and caller requirements.
As of writing it is possible to do so for: Custom Emails, Video Files, Text Files, Custom Cutscenes, and Accuracy
Callers.
In this section, we will cover how these work and how to use them.
Please be aware, that this differs for each different type.
So a custom email may use "email_required_accuracy", while a custom text file may use "text_file_required_accuracy".
So let us see how to add more complicated requirements for emails as an example.
Please note, you can pick between having one or multiple criteria.
For a single criterion, here is a simple check:
"email_required_accuracy": 0.3,
"email_accuracy_days": 4,
"email_accuracy_check_type": "geq"The first line defines what accuracy we check against. In this case, 0.3 refers to 30%.
The second line "email_accuracy_days" asks for which day we want to check against.
In other words, we wish for 30% on day 4.
The third and most important line defines what type of check we wish to perform.
Since we may wish to have greater or lesser than the required accuracy.
The following types of checks exist:
-
eq: (Equal) The accuracy of the provided day must be equal to the provided (required) accuracy. -
neq: (Not equal) The accuracy of the provided day must not be equal to the provided accuracy. -
geq: (Greater than or equal) The accuracy of the provided day must be greater than or equal to the provided accuracy. -
leq: (Less than or equal) The accuracy of the provided day must be less than or equal to the provided accuracy. -
none: (None) A placeholder check. This check ignores the required accuracy. Used for testing. (Always true)
It is also possible to have multiple checks. For this, you can simply provide them in a list manner:
"email_required_accuracy": [0.3, 0.1, 0.9, 0.8],
"email_accuracy_days": [4, 7, 8, 9],
"email_accuracy_check_type": ["geq", "neq", "eq", "eq"]In the above case, we have 4 different checks.
The first check will check for greater than or equal to 30% (0.3) for day 4.
The second check will also check if the accuracy of day 7 is not equal to 10%.
The third check, will check if the accuracy on day 8 is equal to 0.9 (i.e. 90%). And so on.
Each check must be true for the email to appear. If any of them fail, the email will not appear and stay hidden.
That covers the required accuracies. Let us now check how to check for specific callers:
"email_caller_requirement_ids": 5,
"email_caller_requirement_should_be_correct": trueYou will only need these two lines.
The first line asks for which caller we should check.
In our example, it will check if the sixth (0-5) caller in the custom campaign was answered correctly.
If we actually wish for the fifth caller to have been answered incorrectly, we simply flip the true to false:
"email_caller_requirement_ids": 5,
"email_caller_requirement_should_be_correct": falseSimilar to the accuracy checks, we can actually check for multiple callers at the same time:
"email_caller_requirement_ids": [3, 4, 1],
"email_caller_requirement_should_be_correct": [true, false, true]Here again, it's 1:1 mapping.
Meaning that the first value in the list (3), meaning the fourth (0-3) caller of the campaign, must have been answered correctly (true).
The second value (4), meaning the fifth (0-4) caller of the campaign, must have been answered incorrectly (false).
And the last value, the third value (1) (0-1), simply asks if the second caller was answered correctly.
And that should be it.
If you wish to learn on how to implement it more than just emails,
please check out the corresponding section or check the documentation for a clean list of all features.
Modifiers allow you to modify certain aspects of the game. They can be applied globally or on certain days only. Please be aware that if you have a modifier that is active on one day, it will override any global modifiers. The simplest modifier you can make is:
{
"modifier_custom_campaign_attached": "Campaign Name without any typos"
}Similar to the campaign options, you can provide most of these options in modifiers. Here are a few options. For all available options, please check the documentation section: Custom Modifier.
{
"desktop_username_text": "Bob",
"desktop_logo_image_name": "test.png",
"desktop_background_color": [0, 0.5, 0.5],
"show_entry_browser_icon_on_desktop": false
}The first line should already be known. It defines the username that is shown on the desktop. The second line defines the logo seen on the desktop over the background picture. The third option (NEW!) allows you to change the color of the background. The last line simply enables/disables the entry browser for that day.
Now, similar to the themes, you can set your modifiers to only appear on certain days. This can be done via:
"unlock_day": [4, 5, 6]Each day in the list means that the modifier will only work on that day. You can have multiple modifiers for each day. Just know that "general" modifiers (modifiers that don't have an unlock day provided) are overwritten by "conditional" modifiers (Modifiers that only appear on certain days). Overlapping modifiers are handled by the last one to be applied, so avoid any conflicts if possible.
Also be aware, I have not listed all options here, but if you go over to the list (next page), you will see that there are many options that you may be interested in.
This small section is meant for more complicated features that may not be needed. So you can skip this section and not miss anything major.
If you haven't seen it yet, you can set the game to skip some loading screens and videos.
You can do so by enabling them in the in-game options.
Simply open your options, scroll down, and enable the first three checkboxes.
You can also find the "in-game reload" button at the very bottom.
This allows you to reload the JSONs from inside the game without needing to restart everything.
You can also enable some of the DEBUG logs if you require.
The debug logs allow seeing what the mod is doing internally to handle some of the more complicated scenarios.
Here below you can find the same instructions but as an image:

If you are running on an older version or something broke, you can set these settings manually. I, however, recommend using the in-game settings to enable these features.
If you navigate from your games folder to UserData, you should be able to see a file named MelonPreferences.cfg:
Inside this file, you should be able to find the line:
[MainModSettings]
SkipComputerScene = falseHere simply change the false to true and now you won't have to watch the initial scene every time.
That wraps up this section.
If you have any other questions, feel free to message me.
If you want every option displayed in a cleaner matter, you can check the
documentation for a list of all used and available features.
In any case, if you want a feature that isn't added yet, don't be afraid to ask! This isn't all there will be.
Anyway, have fun creating your campaigns!
- Home
- Installation
- Your first Entry
- Your first Custom Campaign
-
Customize your Custom Campaign
- Extra campaign customization
- Adding custom emails
- Adding custom videos
- Adding custom music
- Adding intermission music
- Adding custom ringtones
- Adding custom text files
- Adding custom cutscene
- Adding custom themes
- Accuracy Callers
- Advanced Accuracy Checks and Caller Requirements
- Adding custom modifiers
- Advanced Settings
- Documentation