Custom Museum Framework
Essential Data
In order to create a custom museum, you will first want to do an edit targeting Spiderbuttons.CMF/Museums
to add a new museum entry. The model is described below with an example Content Patcher edit further down. This documentation will not explain the process of adding the location itself, as it is no different from adding any other location. It will also not explain the map making process in detail, however there is important map-related documentation you will need to read on the Museum Maps page of this documentation.
Table of Contents
- MuseumData Model
- Completion Requirements
- Museum Ownership
- Donation Requirements
- Pedestal Interactions
- Museum Rewards
- Museum Strings
- Item Retrieval
- Invalid Donations
- Complete Example
MuseumData Model
Your museum data must exist when a save is loaded. You may not conditionally patch in a custom museum. You may edit your museum data whenever you would like afterwards, but it must exist in some form in Spiderbuttons.CMF/Museums
by the time the player goes to load a save, as this is when Custom Museum Framework will connect your data to the matching in-game location (which must also be present when a save is loaded and never conditionally appear or disappear from Data/Locations
).
Spiderbuttons.CMF/Museums
consists of a string to MuseumData
dictionary,? where MuseumData
is a model with the following fields:
FIELD | PURPOSE |
---|---|
Id | The string Id of your museum. This must match both the key you used for this entry and the ID of the location you want to use as a museum. This should also be globally unique, so using the {{ModId}} Content Patcher token is highly recommended. |
Owner | (Optional) An OwnerData object describing who runs your museum and what their "working zone" is. See Museum Ownership.Default null |
Bounds | (Optional) A Rectangle in the form of { "X": 0, "Y": 0, "Width": 0, "Height": 0} that encompasses all (or at least most) of the valid item pedestal locations in your museum.[1] |
Donation | A list of DonationRequirement objects that define the criteria an item must meet in order to be donated to your museum. If an item meets any requirement in this list, it will be considered a valid donation item. See Donation Requirements. |
Completion | (Optional) An int that determines at what number of donations should your museum be considered complete. If set to null , this number will be set to the number of items in the game that are valid donation items. See Completion Requirements.Default null |
CountInvalid | (Optional) A bool that determines whether or not to count items that are not valid donation items, but are currently present in your museum nevertheless, in various features that check donation counts. See Invalid Donations. |
Allow | (Optional) A bool for whether or not players can remove items from your museum after they have been donated. Items that have been removed will affect museum completion but may be re-donated again later. The player will not receive infinite rewards for removing and re-donating items. See Item Retrieval to understand the implications of this. Default false |
Show | (Optional) A bool for whether or not items that can be donated to your museum will have a hint added to their description ala "Gunther can tell you more about this..." Default true |
Override | (Optional) A bool for whether or not your museum will completely override the description of items that can be donated to it and only show the hint. Does nothing if ShowDonationHint is false .Default false |
Pedestal | (Optional) An InteractionData object defining what should occur when a player interacts with a donated item on its item pedestal. See Pedestal Interactions. |
Rewards | (Optional) A list of CustomMuseumReward objects describing what rewards the player can earn for donating items. See Museum Rewards. |
Milestones | (Optional) A list of integers. When a milestone number of items have been donated to your museum, a customizable message will be displayed in chat. |
Strings | (Optional) A string to string dictionary for you to override the default strings that are shown when certain events occur. See Museum Strings.[2] |
[1] This area is where the game will look for item pedestals when donating an item via trigger action actions or when a menu is force-closed and it needs to safely place an item down. While this field is optional, you should really fill it in!
[2] Many of the default strings are set to use lines found in the vanilla game, and therefore will be written with Gunther in mind. It is highly recommended to fill out all of the string overrides for this reason.
Completion Requirements
By default, Custom Museum Framework will use the total number of valid donation items in the game as the target number for museum completion. If there are 50 items in the game that meet your requirements, for example, then your museum will be considered complete once 50 items are donated. However, by altering your CompletionNumber
, you can change when your museum will be considered complete. Continuing our previous example, if there were 50 items possible to donate, but you set your CompletionNumber
to 20, then your museum will be complete once there are 20 items in your museum; the other 30 items will be ignored.
Once your museum is complete, the player will no longer be able to donate any items. Donation hints will no longer be shown for your museum on items that have not been donated. If there are any museum rewards that require an item to be donated that has not been earned yet, they will become unavailable as long as the museum remains complete. Quests may become impossible to finish while the museum remains completed if the required quest items have not yet been donated.
It is possible for your museum to become incomplete again after it has been completed once. You can remove donations with an action, via the item retrieval menu, or with a console command. If an item is removed from your completed museum, then it will no longer be considered complete. Pre-completion museum strings may be shown again. Donation hints will also be shown on qualifying items again. The player will be allowed to donate items again as long as the museum remains incomplete. Unclaimed museum rewards that required all items to be donated will become unclaimable, but they can be earned again once the museum is completed again.
However, some things are irreversible. The mail flag earned for museum completion will not be removed. The OnCompletion
museum string will not be shown more than once per save file. Milestones will also only be reached once per save file. Claimed rewards that required museum completion will of course not be revoked nor will any of their mail flags be removed.
See also: Invalid Donations.
Museum Ownership
While the vanilla museum has an owner, your custom museum does not need to have one. It can be a location with nobody in it while still allowing the player to donate items. If you do not wish for your museum to be run by any NPC in particular, you would set the entire Owner
field to null
in your JSON.
However, if you do wish to have an NPC running your museum, then an OwnerData
object consists of the following fields:
FIELD | PURPOSE |
---|---|
Name | The internal name of the NPC that runs your museum. |
Required | (Optional) A bool for whether or not the owner must be present and "clocked in" for the player to be allowed to donate items. Default false |
Area | (Optional) A Rectangle in the form of { "X": 0, "Y": 0, "Width": 0, "Height": 0} that defines the area in which the owner must be standing in order to be considered "clocked in" and for the player to be allowed to donate items. If no area is set, then the owner only must be present anywhere in your museum to be considered clocked in. This field only affects donating if RequiredForDonation is true , however it may still matter for your museum strings.Default null |
Donation Requirements
If you do not set any donation requirements for your museum, then your museum will accept no items at all, and will hardly be worthy of being called a museum. In order to determine what items the player can donate to your museum, you must provide the DonationRequirements
field of your MuseumData
with a list of DonationRequirement
objects. Each DonationRequirement
object consists of the following fields:
FIELD | PURPOSE |
---|---|
Id | The string Id of this entry in your DonationRequirements list. While this does not need to be globally unique, it must be unique across all of the requirements in your museum. |
Categories | (Optional) A list of integers where each integer corresponds to a category of items. You may add any number of categories to this list and, if an item matches any of them, it will meet this category requirement. Default null |
ContextTags | (Optional) A list of context tags. You may add any number of context tags to this list and, if an item has any of them, it will meet this context tag requirement. Default null |
ItemIds | (Optional) A list of qualified item Ids. You may add any number of item IDs to this list and, if an items qualified item ID matches any of them, it will meet this item ID requirement. Default null |
MatchType | (Optional) Determines whether an item must meet every filled out requirement or any filled out requirement in order to be considered a valid donation. Allowed values are All and Any respectively. See below for further explanation.Default Any |
As you can see, all three of Categories
, ContextTags
, and ItemIds
are optional. However, you must fill out at least one of them for it to be a valid requirement, otherwise it will be skipped. As long as at least one of those fields is filled out, then any requirement type that is not filled out will be ignored when checking whether an item is a valid donation. For example, if you provide a list of categories, but leave the context tag and item Ids null or do not include them, then Custom Museum Framework will only check whether a potential donation has any of the categories in your list. Similarly, if you provide a list of categories and a list of item IDs, then Custom Museum Framework will check the category and item ID of a potential donation in order to see if it's valid, but it will not look at the context tags of the item.
MatchType All vs. Any
The MatchType
comes into play when you fill out two or more of the requirement types. If MatchType
is set to All
, then an item must pass every listed requirement in order to be donated. For example, if you gave it a list of categories and a list of item Ids, then an item must have one of those item Ids and have one of the listed categories at the same time in order to be donated. If MatchType
is set to Any
, then the item only needs to pass at least one of the requirements. Using the same example, if the item had one of the listed item IDs but did not match any category, it would still be a valid donation, and vice versa if it had one of the listed categories but did not match any listed item ID. This MatchType
behaviour applies if you fill out all three of the requirement types as well.
Remember, DonationRequirements
is a list. Feel free to add as many different requirements as you'd like. However, be aware that the MatchType
behaviour described above will only apply on a per DonationRequirement
basis and will not apply any restrictions or freedoms to other DonationRequirement
objects in your list. If an item passes at least one of the DonationRequirement
objects in your list, it will be considered a valid donation item.
Pedestal Interactions
In the vanilla museum, when you interact with an item that has been donated to the museum, you get a little pop-up message on your screen with the name of the item and its description. In Custom Museum Framework, you are able to customize this interaction behaviour for your items. An InteractionData
object consists of the following fields:
FIELD | PURPOSE |
---|---|
Id | The string Id of this InteractionData object. |
Interaction | (Optional) The type of interaction that should occur when the player clicks on an item in a pedestal. Allowed values are Default , Sign , Message , Letter , Custom , or None . A value of Default in the context of item pedestal interactions is equivalent to Sign , which is the same behaviour as the vanilla museum. Message and Letter perform identically to their respective map actions. Custom will tell Custom Museum Framework to do whatever action you wrote in the Action field (described below) instead of displaying a message. A value of None means nothing will happen at all when the player clicks on an item pedestal.Default Default |
Text | (Optional) The text that will be displayed when showing a Default , Sign , Message , or Letter interaction. This field is ignored if InteractionType is set to Custom or None . This field will apply text substitutions, meaning that if you write {0} , {1} , {2} , or {3} inside your text, those bits will be replaced with the item display name, item description, museum display name, and item qualified ID respectively. This field also supports tokenizable strings which will be parsed after the aforementioned substitutions.Default - {0} - ^{1} ![]() Substitutions will replace numbers within braces. For example, |
Action | (Optional) An action string that will be run when the player interacts with an item pedestal. This field will get the same substitutions described in the Text field above applied in the same order.Default null |
In addition to PedestalAction
, which is applied globally to every donatable item, you can also choose to use a custom interaction on a per-item basis by adding some data to that items CustomFields
section in its Data/Objects
entry. You must add a new CustomFields
entry with the key Spiderbuttons.CMF/PedestalAction
and a value that is an action string that you would like to run when that item is interacted with on a museum pedestal. You may also add another custom field with the key Spiderbuttons.CMF/PedestalOverride
and a value of either true
or false
. If you set this entry to false
, then both the global PedestalAction
and your action described in CustomFields
will both run, with your CustomFields
action running first. If you set this override value to true
or omit it entirely (since true
is the default), then only the action string defined in your Spiderbuttons.CMF/PedestalAction
entry will run, skipping the global PedestalAction
entirely.
Like with the global PedestalAction
, an action string defined in an objects CustomFields
dictionary will also receive the same substitutions described in the table above. An example is shown below:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
Museum Rewards
The reward system for your custom museum works the same way that the reward system does for the vanilla museum, however the fields you will need to fill out are slightly different, both to account for the more flexible donation criteria that Custom Museum Framework allows and to allow more possibilities for the rewards themselves. A CustomMuseumReward
object consists of the following fields:
FIELD | PURPOSE |
---|---|
Id | The string ID of this entry in your Rewards list. While this does not need to be globally unique, it must be unique across all of the rewards in your museum. |
Requirements | A list of CountableDonationRequirement objects defining what items must be donated to your museum in order to earn this reward. These CountableDonationRequirement objects contain the same fields as a DonationRequirement object as well as the following additional field:
ItemIds , ContextTags , and Categories as null . If you do, then Custom Museum Framework will only check if there are Count items of any kind donated to your museum.
Every requirement in this list of requirements must be met in order for the player to earn this reward. |
RewardItems | A list of generic item spawn objects. Every item in this list will be given as a reward when the requirement is met.[3] |
Action[4] | (Optional) An action string that will be run when the player collects the reward (not when it is earned). Default null |
Actions[4] | (Optional) A list of action strings that will be run when the player collects the reward (not when it is earned). Default null |
Reward | (Optional) A bool for whether or not the items from this reward should be marked "special." Special items cannot be trashed or lost on death. In the context of a museum, it also means that any item gained from this reward can only ever be gained the one time, even if another reward contains an identical item. This "special" check is also done in some other miscellaneous places in the vanilla game. Unless you're sure of what this does, you should probably just leave this false. Default false |
FlagOn | (Optional) A bool for whether or not the game should set a mail flag when the player collects the reward (not when it is earned). See Mail Flags. Default true ![]() This is used to track whether or not the player has collected the reward and should almost always be true. If both this and |
[3] If you are using an item query that involves choosing a random item, be aware that the RNG is seeded based on the reward Id, generic item spawn Id, and save file Id. This means that, all else being equal, the reward will not change depending on when the player earns or collects it.
[4] You may fill out both the Action
field and the Actions
field if you'd like, though you should probably just choose one for simplicity. The former will run first.
Rewards are checked after the player manually donates an item directly to your museum and not when the donation is the result of a trigger action. If the player earns a reward with their latest donation, sparkly text will appear on screen to let them know, just like the vanilla museum. In order for the player to collect the reward, they must interact with the MuseumMenu tile in your museum map to access the reward collection option. The museum owner (should they exist) does not need to be present for the player to be able to collect their rewards.
Museum Strings
Custom Museum Framework lets you customize nearly any text related to your museum that might be displayed to the player at some point. Any string that you do not choose to customize will display a default message instead, which you can check by looking in the i18n
folder of the Custom Museum Framework mod itself.[5] You can choose to customize all of these strings or none of these strings or anything in between, therefore all of these fields can be considered optional. All of these strings support tokenizable strings, but only some will receive text substitutions, which will be documented where applicable.
These are the strings that you are able to customize:
FIELD | PURPOSE |
---|---|
OnDonation | The message shown in chat when a player donates an item to your museum. The text substitutions are {0} for the player name, {1} for the item display name, and {2} for the museum display name. If you specifically set this to null , then no message will be shown in chat at all. |
OnMilestone | The message shown in chat when the player(s) reaches a milestone of donated items. The text substitutions are {0} for the farm name, {1} for the number of items donated, and {2} for your museum's display name. If you specifically set this to null , then no message will be shown in chat at all. |
OnCompletion | The message shown in chat when the player(s) completes your museum collection. The text substitutions are {0} for the farm name and {1} for the museum display name. If you specifically set this to null , then no message will be shown in chat at all. |
MenuDonate | The text for the dialogue choice that opens the donation menu from the MuseumMenu tile interaction. |
MenuCollect | The text for the dialogue choice that opens the reward collection menu from the MuseumMenu tile interaction. |
Menu | The text for the dialogue choice that opens the rearrangement menu from the Rearrange tile interaction. |
MenuRetrieve | The text for the dialogue choice that opens the item retrieval menu from the Rearrange tile interaction. This is only shown if AllowRetrieval is true . |
ClockedOut | The message shown when the player tries to interact with the MuseumMenu tile when the owner is not clocked in. This is only shown if the owner is required to be present. |
Busy_ | The message shown when your museum's owner is busy and cannot interact with the player. This is only shown when an owner exists and is currently clocked in. This string supports the standard NPC dialogue format.[6] |
Busy_ | The message shown when your museum is busy and a player cannot interact with it. This is only shown when an owner does not exist or is currently clocked out. |
Museum | The message shown when the player interacts with the MuseumMenu tile after your museum is completed. This is only shown when an owner exists and is currently clocked in. This string supports the standard NPC dialogue format.[6] |
Museum | The message shown when the player interacts with the MuseumMenu tile after your museum is completed. This is only shown when an owner does not exist or is currently clocked out. |
NothingTo | The message shown when the player interacts with the MuseumMenu tile but has nothing to donate and no rewards to collect. This is only shown when an owner exists and is currently clocked in. This string supports the standard NPC dialogue format.[6] |
NothingTo | The message shown when the player interacts with the MuseumMenu tile but has nothing to donate and no rewards to collect. This is only shown when an owner does not exist or is currently clocked out. |
NoDonations_ | The message shown when the player interacts with the MuseumMenu tile but has nothing to donate and there are no donations in your museum yet. This is only shown when an owner exists and is currently clocked in. This string supports the standard NPC dialogue format.[6] |
NoDonations_ | The message shown when the player interacts with the MuseumMenu tile but has nothing to donate and there are no donations in your museum yet. This is only shown when an owner does not exist or is currently clocked out. |
CanBeDonated | The hint shown in an item description to let the player know that the item can be donated to your museum. This string is only shown if ShowDonationHint is true . |
[5] Some of the default strings have text substitutions in them that are not documented here. These text substitutions are unnecessary if you have complete control over the string when customizing them and may be subject to changing or being removed completely in future Custom Museum Framework versions. Therefore, you should not rely on any undocumented text substitutions when customizing your strings.
[6] While you can use the standard NPC dialogue format here, be aware that any dialogue that requires the player to interact with the NPC again to finish the rest of the dialogue will not be shown. Once the dialogue box is closed, the interaction is over.
Item Retrieval
In vanilla, once you donate an item to the museum, there is no way to get that item back. By default, this is the case with your custom museum as well, however you have the option to change that if you wish by setting the AllowRetrieval
property in your museum data to true
. Whether or not you actually would want to is entirely up to you, but you should carefully consider it if your museum accepts items that the player may not want to lose, even if they can get them back via other means. For example, if your museum accepts tools, the player would probably be unhappy if they accidentally donated their pickaxe or hoe and had no option to get it back. On the other hand, if your museum only accepts custom items that you've created whose sole purpose is to be donated to your museum, then the player probably doesn't need to retrieve them again in the future.
If you do allow item retrieval, then the player will have an extra option available to them when interacting with your museum tiles (see the Museum Maps documentation). Once the player selects the option to retrieve items from your museum, a chest menu will open on their screen containing every item currently in your museum (though it will only display up to whatever the maximum size of a normal chest is). As long as this chest remains open, the player can freely take items out. They can also freely place items back in as long as the item in question was taken out of this chest menu during this interaction. Once an item is removed from this chest, it is removed from the museum. Any relevant mail flags will not be removed, however unclaimed rewards requiring that item may disappear if the player no longer meets the reward requirements, in which case the reward can be re-earned once the item is donated again.
If your museum only accepts items that a player should be fine with losing permanently, then you are safe to disallow item retrieval entirely. However, be aware that the player may still retrieve items from your museum if they use the included console commands to do so, which will always allow item retrieval in case of a bug or other reason that a player may need to force item retrieval.
Invalid Donations
It is possible to end up with items donated to your museum that do not actually meet any of your donation requirements and thus don't actually belong in your museum according to its data. This may or may not be intentional or desired. By default, these invalid donations do not count towards museum progress in any regard. They will not count towards museum completion or milestones, they will not count for certain[7] museum rewards, they will not count for certain[7] museum quests, and they will not count for the MUSEUM_DONATIONS
or IS_ITEM_DONATED
game state queries.[8] They will remain in your museum and the player can still interact with them, but the museum will ignore them otherwise.
However, if you set your CountInvalidDonations field to true
instead, then invalid donations will be counted for all of those things. Your museum will no longer care whether or not the item belongs, it will only care about the fact that the item is donated and count it alongside the valid donations. If any of your quests or rewards rely on invalid donations being counted in order for the player to earn or complete them, you will probably want to set CountInvalidDonations to true
.
[7] Rewards and quests that only require a certain number of items donated without any other requirement will not count invalid donations by default. However, if the reward or quest specifies other requirements, then invalid donations will be counted no matter what so long as they meet those requirements.
[8] Invalid donations will still be checked when using the MUSEUM_HAS_ITEM
game state query.
Complete Example
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |