-
Announcement
-
Simtropolis Returns! 05/26/2026
See here for details about our site recovery efforts.
-
Search the Community
Showing results for tags 'example'.
Found 2 results
-
A small example how to replace the AI of a custom building asset on startup: In this example the AI extends from PlayerBuildingAI, that means it has basic stats like a construction cost, it can catch fire etc. But of course you can also extend from any other AI (BuildingAI or CommonBuildingAI if you want to start from scratch). The AI in this example displays a counter value in the building info window. The counter is increased after SimulationStep is called 16 times (SimulationStep is called about once every second on normal speed). The mod expects a local building asset with the file name "thing" and asset name "Thing". The AI is replaced before the prefab is initialized. That means there should be no bad side effects. The mod requires Harmony. Just place 0Harmony.dll in the same folder as the mod dll. It is not compatible with Loading Screen Mod. If you want to support LSM and LSM Test, take a look at the source code of Custom Animation Loader. using ColossalFramework.Packaging; using Harmony; using ICities; using UnityEngine; namespace AiReplace { public class AiReplaceMod : IUserMod { private const string HarmonyId = "boformer.AiReplace"; private HarmonyInstance _harmony; public string Name => "AI Replace"; public string Description => "Replaces AI"; public void OnEnabled() { if (_harmony != null) return; Debug.Log("AiReplace Patching..."); _harmony = HarmonyInstance.Create(HarmonyId); _harmony.PatchAll(GetType().Assembly); } public void OnDisabled() { _harmony.UnpatchAll(HarmonyId); _harmony = null; Debug.Log("AiReplace Reverted..."); } } public class MyBuildingAI : PlayerBuildingAI { public override string GetLocalizedStats(ushort buildingID, ref Building data) { var counter = data.m_customBuffer1; return $"Counter: {counter}"; } public override void SimulationStep(ushort buildingID, ref Building data) { Debug.Log("SimulationStep!"); if ((SimulationManager.instance.m_currentFrameIndex & 0xFFF) >= 0xF00) { Debug.Log("SimulationStep was called 16 times!"); data.m_customBuffer1++; } base.SimulationStep(buildingID, ref data); } } // Vanilla Asset Loader [HarmonyPatch(typeof(PackageDeserializer), "DeserializeGameObject")] public static class PackageAssetPatch { public static void Postfix(Package package, GameObject __result) { var prefab = __result.GetComponent<BuildingInfo>(); if (prefab == null) return; Debug.Log($"Instantiate {package.packageName} {prefab.name}"); // packageName is file name of the .crp file (for local .crp files) // prefab name is the "Asset Name" you set in Asset Editor + "_Data" if (package.packageName == "thing" && prefab.name == "Thing_Data") { var oldAi = prefab.gameObject.GetComponent<BuildingAI>(); UnityEngine.Object.DestroyImmediate(oldAi); var newAi = prefab.gameObject.AddComponent<MyBuildingAI>(); Debug.Log($"AI replaced!"); } } } }
-
Lately we've had considerable new members who are somewhat at sea on getting a city going. Here is one I started a couple of days ago as part of my new region. It is in the black, but it has no services other than power and water (the pond in the lower centre). Admittedly, there is a lot of custom content here. The farms are SPAM and the pond is also from Pegasus. Many of the 2 x 1 buildings are from Paeng (thanks, Paeng.) The game is yelling at me for not watering all the buildings. I'll do that when I open this city again. I've always considered the best way to get a city off the ground without cheats is to start the way cities usually do either with something riparian, or a farm group and a little rail junction. This one is the latter. Later on, you can think of the nice, big farms in terms of new subdivisions. Here's the image. Enjoy. Oh, and notice that this baby is only four Sim-months old, exactly.

