Skip to content

Harmony patches

algernon-A edited this page Nov 29, 2021 · 27 revisions

Ploppable RICO Revisited currently uses Harmony 2.0 (via boformer's CitiesHarmony) to deploy the following patches (note that all of these patches are applied whenever the mod is active):

BuildingInfo

BuildingInfo.InitializePrefab

Thee patches are applied to this method: a Prefix, a Transpiler, and a Postfix.

The Prefix patch has high priority and never preempts the original method (it always returns true from the Prefix method). This patch handles the setup of Ploppable RICO prefabs (including assigning of correct AIs and ItemClasses prior to initialisaton) and is critical to the operation of the mod.

It should generally be allowed to run before any other Prefix patches in order to ensure that Ploppable RICO prefabs are correctly set up before being manipulated by other mods; otherwise, actions by other mods may be overridden, and/or mods may not correctly identify which prefabs they should apply to (especially where prefab AIs and ItemClasses are changed by this mod, which is quite common).

The Transpiler patch has standard priority and removes two conditional checks from the base method which would otherwise block Ploppable RICO buildings from being initialised; these are the checks for "Private building cannot have manual placement style" and "Private building cannot include roads or other net types".

Obviously, all Ploppable RICO buildings with non-Dummy AI are assigned private building AIs, and so can't be initialised with these checks in place.

These checks are still performed for all non-Ploppable RICO prefabs by the Prefix patch (a 1:1 replacement for the checks removed by the Transpiler); buildings failing those checks will still throw the relevant PrefabException.

The Postfix patch simply checks that the prefab has successfully completed initialisation (e.g. a PrefabException hasn't been thrown due to a bad asset or a missing dependency). Prefabs that don't successfully complete are removed from Ploppable RICO Revisited's prefab lists upon completion of level loading.

BuildingTool

BuildingTool.CreateBuilding

ref BuildingInfo info, Vector3 position, float angle, int relocating, bool needMoney, bool fixedHeight

This is a Postfix patch with standard priority. This patch implements the Instantly plop growable buildings (no construction) and the Make all plopped growables historical functions.

BuildingTool.IsImportantBuilding

BuildingInfo info, ref Building building

This is a Prefix patch with standard priority, that may or may not preempt the original method (can return either true or false from the Prefix method).

  • The original method is preempted (the Prefix returns false with the original result set to true) if info.m_buildingAI is a Ploppable RICO AI.
  • Otherwise, the Prefix returns true (and excution flow continues on to the original method).

This patch ensures that Ploppable RICO buildings aren't 'trivially' destroyed or replaced (auto-demolished, auto-bulldozed, upgraded, etc.).

CommercialBuildingAI

CommercialBuildingAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces the following code with a call to a custom method:

buildingData.m_flags |= Building.Flags.Demolishing;
instance.m_currentBuildIndex++;

The custom method implements the Growable buildings can survive without required district specializations functionality.

CommonBuildingAI

CommonBuildingAI.CollapseBuilding

ushort buildingID, ref Building data, InstanceManager.Group group, bool testOnly, bool demolish, int burnAmount

This is a Prefix patch with standard priority, that may or may not preempt the original method (can return either true or false from the Prefix method).

  • The original method is preempted (the Prefix returns false with the original result set to false) if info.m_buildingAI is a Ploppable RICO AI and the mod is set to prevent Ploppable RICO buildings from collapsing.
  • Otherwise, the Prefix returns true (and excution flow continues on to the original method).

This patch ensures that Ploppable RICO buildings aren't collapsed by disasters (unless the player has changed that option).

EconomyManager

EconomyManager.OnAddResource

EconomyManager.Resource resource, ref int amount, ItemClass.Service service, ItemClass.SubService subService, ItemClass.Level level

This is a Postfix patch that checks if amount is negative, and if so, inverts it (makes it positive). This is to fix a game bug where private building income (tax revenue) can sometimes be negative for buildings with large numbers of households.

IndustrialBuildingAI

IndustrialBuildingAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces the following code with a call to a custom method:

buildingData.m_flags |= Building.Flags.Demolishing;
instance.m_currentBuildIndex++;

The custom method implements the Growable buildings can survive without required district specializations functionality.

IndustrialExtractorAI

IndustrialExtractorAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces the following code with a call to a custom method:

buildingData.m_flags |= Building.Flags.Demolishing;
instance.m_currentBuildIndex++;

The custom method implements the Growable buildings can survive without required district specializations functionality.

LevelUpWrapper

LevelUpWrapper.OnCalculateCommercialLevelUp

This is a Postfix patch to implement the 'low land value' complaint suppression option for commercial buildings.

LevelUpWrapper.OnCalculateIndustrialLevelUp

This is a Postfix patch to implement the 'too few services' complaint suppression option for industrial buildings.

LevelUpWrapper.OnCalculateOfficeLevelUp

This is a Postfix patch to implement the 'too few services' complaint suppression option for office buildings.

LevelUpWrapper.OnCalculateResidentialLevelUp

This is a Postfix patch to implement the 'low land value' complaint suppression option for residential buildings.

OfficeBuildingAI

OfficeBuildingAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces the following code with a call to a custom method:

buildingData.m_flags |= Building.Flags.Demolishing;
instance.m_currentBuildIndex++;

The custom method implements the Growable buildings can survive without required district specializations functionality.

PrivateBuildingAI

PrivateBuildingAI.BuildingLoaded

ushort buildingID, ref Building data, uint version

There are two patches applied to this method: A Prefix and a Postfix. Both have standard priority.

The Prefix patch may or may not preempt the original method (can return either true or false from the Prefix method).

  • The original method is preempted (the Prefix returns false) if this building's prefab has an active Ploppable RICO Revisited setting, in which case the mod handles the post-loading setup for that building (in place of the original method).
  • Otherwise, the Prefix returns true (and excution flow continues on to the original method).

This patch ensures that the building level, household counts, visit counts, and workplace counts of all existing building intances match the current RICO settings for that prefab, and all existing problem notifications are cleared.

This is necessary to ensure that all buildings function correctly when RICO (and hence prefab) settings are changed after buildings have been placed (this can include service and subservice changes as well - other modders should not assume that buildings governed by this mod will always retain the same m_class).

The Postfix patch checks to make sure that at least one CitizenUnit has been assigned to a residential building. If the building doesn't have any CitizenUnits, it will make a second attempt at allocation by manually calling the Prefix directly. This is an attempt to address a (non-reproduceable, so far) issue where some users were reporting that some buildings were being loaded without any CitizenUnits.

PrivateBuildingAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces calls to CheckZoning with calls to a custom method; the custom method implements the Growable buildings can survive outside of the correct zone functionality.

If the building in question isn't covered by the relevant options setting, the custom method will then call the original CheckZoning method.

It's done this way (changing calls with a Transpiler instead of simply using a Prefix patch on CheckZoning itself) for compatibility with the 81 Tiles Mod, which uses cope's detours(!) to detour Building.CheckZoning, preventing execution of direct Harmony patches.

ResidentialBuildingAI

ResidentialBuildingAI.SimulationStep

ushort buildingID, ref Building buildingData, ref Building.Frame frameData

This is a Transpiler patch that replaces the following code with a call to a custom method:

buildingData.m_flags |= Building.Flags.Demolishing;
instance.m_currentBuildIndex++;

The custom method implements the Growable buildings can survive without required district specializations functionality.

UnlockingPanel

UnlockingPanel.RefreshMonumentsPanel

This is a Prefix patch with standard priority that preempts the original method (returns false from the Prefix method); however, it calls the (unaltered) original method directly from within the patch.

This patch simply calls the original method within an exception catcher, in order to prevent the game crash (hang) that occurs when no valid monument buildings are found during game load (either because they've been converted to RICO buildings with this mod, skipped via the Loading Screen Mod's prefab skipping feature, or both).

Clone this wiki locally