/// <summary>
 /// Harmony Postfix patch to stop historical buildings from abandoning.
 /// </summary>
 /// <param name="__instance">Instance reference</param>
 /// <param name="buildingID">Building instance ID</param
 /// <param name="buildingData">Building instance data reference</param>
 public static void Postfix(PrivateBuildingAI __instance, ushort buildingID, ref Building buildingData)
 {
     // Check to see if we have no abandonement for any building set, or no abandonment historical and this is an historical building.
     if (ModSettings.noAbandonAny || (ModSettings.noAbandonHistorical && __instance.IsHistorical(buildingID, ref buildingData, out bool _)))
     {
         // It is - simply reset the major problem timer to avoid the 'abandonment' timeout.
         buildingData.m_majorProblemTimer = 0;
     }
 }
        /// <summary>
        /// Upgrades/downgrades the selected building to the given level, if possible.
        /// </summary>
        /// <param name="buildingID">Building instance ID</param>
        /// <param name="targetLevel">Level to upgrade/downgrade to</param>
        internal static void ForceLevel(ushort buildingID, byte targetLevel)
        {
            // BuildingInfo to change to, if this building isn't historical.
            BuildingInfo targetInfo = null;

            // References.
            BuildingManager buildingManager = Singleton <BuildingManager> .instance;

            Building[]        buildingBuffer = buildingManager.m_buildings.m_buffer;
            BuildingInfo      buildingInfo   = buildingBuffer[buildingID].Info;
            PrivateBuildingAI buildingAI     = buildingInfo?.GetAI() as PrivateBuildingAI;

            if (buildingInfo == null || buildingAI == null)
            {
                // If something went wrong, abort.
                Logging.Error("couldn't get existing building info");
                return;
            }

            // Check to see if this is historical or not, or is a RICO ploppable.
            bool isHistorical = buildingAI.IsHistorical(buildingID, ref Singleton <BuildingManager> .instance.m_buildings.m_buffer[buildingID], out bool _) || ModUtils.CheckRICOPloppable(buildingInfo);

            // Get target prefab (if needed, i.e. not historical or RICO ploppable).
            if (!isHistorical)
            {
                // Get upgrade/downgrade building target.
                targetInfo = GetTargetInfo(buildingID, targetLevel);
                if (targetInfo == null)
                {
                    // If we failed, don't do anything more.
                    return;
                }
            }

            // If we have a valid upgrade/downgrade target, proceed.
            if (isHistorical || targetInfo != null)
            {
                // Apply target level to our building and cancel all level-up progress.
                buildingBuffer[buildingID].m_level           = targetLevel;
                buildingBuffer[buildingID].m_levelUpProgress = 0;

                // Apply our upgrade/downgrade target if not historical
                if (!isHistorical)
                {
                    buildingManager.UpdateBuildingInfo(buildingID, targetInfo);
                }

                // Post-downgrade processing to update instance values - call game method if new level is equal to or greater than info base level, otherwise use custom method.
                BuildingInfo newInfo = targetInfo ?? buildingInfo;
                if (newInfo.GetAI() is PrivateBuildingAI newAI)
                {
                    if (targetLevel < (byte)newInfo.GetClassLevel())
                    {
                        // New level is less than info base level; call custom method.
                        CustomBuildingUpgraded(newAI, buildingID, ref buildingBuffer[buildingID]);
                    }
                    else
                    {
                        // New level is equal to or greater than info base level; call game method.
                        newAI.BuildingUpgraded(buildingID, ref buildingBuffer[buildingID]);
                    }
                }
            }
        }