Mod Map Masks - ilikegoodfood/CommunityLib GitHub Wiki
Background
Map Masks in Shadows of Forbidden Gods are defined as an Enum in MapMaskManager.maskType.
An enum is a compiled structure that maps a string name to a simpler underlying value. For example, the MapMaskManager.maskType.NONE has a string name "NONE" and an integer value "0". They are primarily used for fixed sets of options that a developer has to type out and compare repeatedly. Typing strings can lead to hidden errors when a typo is made, and comparing string is much more computationally expensive than comparing ints.
Unfortunately for mods however, Enums are defined at compile time, and cannot be extended.
While not strictly correct, you can think of an Enum as a class with each item being a field, and the field having both a value and a name strored in it.
Fortunately for mods, the runtime code doesn't actually pass around the Enum, but only the value.
This means that all of the methods that expect a MapMaskManager.maskType.[SOME_TYPE] actually expect an int. This allows mods to use integer values for their own map masks, as long as they are not used by the base game or any other mod. This is how the Community Library is able to fascilitate modded map masks. Unfortunately, if two or more mods picked the same int value, then they would be fighting over the true outcome.
To solve this, the Community Library requires the use of a registration function, so that it can internally track which values are in use, and what information is associated with it.
The Community Library also hooks various UI elements directly into this data provided during map mask registration, to make up for required mod kernel hooks not having been implemented in the vanilla code. Modded Map Masks will not work without the Community Library, unless a modder implements their own soluton, and ensures that it does not conflict with the Community Library's solution.
Registration
The first step of making a Modded Map Mask is registering it to the Community Library. This must be done for each hook in the beforeMapGen and afterLoading hooks, after the getModKernels method described in Integration > Finding a Mod.
The registration method:
public int tryRegisterMapMask(ModKernel maskingMod, string title, string buttonLabel, string description, bool needsSimplifiedTerrain)
The registration method must receive the following elements:
- The
ModKernelinstance that is registering the map mask. This is required to help identify the mask, and prevent conflicts. - The string title of the Map Mask. This is what will be displayed in the top-centre of the screen while the map mask is active.
- The string label of the button for the map mask. This is what will be listed on the map mask button in the map masks list, which is expaned by clicking on the magnifying glass in the bottom right.
- The string description of the map mask. This is the tgext that will appear at the top of the threats panel to explain what the map mask shows.
- A boolean (true/false) indicating whether the terrian sprites should be replaced with a uniform grey while the map mask is active.
The registration function returns the integer value that the Community Library has assigned that map mask to. It is neccessary to identify the map mask as active, and to gain access to the map masks' data. Store it in a class field in your ModKernel.
Here is the registration of the Potential Vendetta map mask within the Community Library's ModKernel:
// inside the ModKernel class:
public int potentialVendettaMaskID = -1;
// inside the map mask setup method that is called in both `beforeMapGen` and `afterLoading`:
potentialVendettaMaskID = tryRegisterMapMask(Get(), "Potential Vendettas", "Potential Vendettas", "Shows mourners that can be exploited to create a blood feud between houses, grouped by source and target houses.", false);