Jump to content

Search the Community

Showing results for tags 'development'.

More search options

  • Search By Tags

    Type tags separated by commas. These are keywords which should describe the item of content.
  • Search By Author

Content Type


  • Cities: Skylines
    • Cities: Skylines General Discussion
    • Cities: Skylines Modding - Open Discussion
    • Cities: Skylines Showcase
    • Cities: Skylines City Journals
    • Cities: Skylines Technical Help Q&A
  • SimCity (2013)
    • SimCity (2013) General Discussion
    • SimCity (2013) Modding - Open Discussion
    • SimCity (2013) Region Games
    • SimCity (2013) Showcase
    • SimCity (2013) Technical Help Q&A
  • SimCity 4 Players Forum
    • SimCity 4 General Discussion
    • SC4 Showcase
    • SC4 City Journals
    • SC4 Mac Users
    • SC4 Bugs & Technical Issues
  • SimCity 4 Builders Forum
    • SC4 - Custom Content
    • SC4 BAT - Open Discussion
    • SC4 Modding - Open Discussion
  • Simtropolis Social Forum
    • New Members Information
    • Simtropolis Related
    • General Off-Topic
    • Current Events
    • Architecture & Urban Planning
  • Gamer Topics
    • SimCity 3000
    • City-Building Games
    • Gaming Talk
    • Indie Projects
  • Trixies Forum
    • Trixie Awards - Community Discussion
  • Simtropolis Challenges
    • ST Challenges - Info and Discussion
  • Friends of Dirktator's Club Discussion
  • Simtropolis en Español's Plaza Mayor
  • Simtropolis en Español's Soporte Técnico
  • Simtropolis en Español's Parque Industrial
  • Infrastructure Club's Topics
  • SimCampus Students's Topics
  • The Transit and Aviation Geeks Club's Topics
  • Arden County City Council's Topics
  • Alliance of Independent Nations on Simtropolis's Discussion
  • The Major Club's Topics
  • Project Rich Water's Topics
  • Guardians of the Galaxy's Topics
  • New Washington's Topics


  • SimCity 4
    • SC4 Reference
    • SC4 Tutorials
    • BAT & Lot Editor Tutorials
    • Modding Information
    • Mapping & Terraforming
  • Other Games
  • Simtropolis Articles
    • Interviews


  • News
  • News
  • News


  • Challenge Uploads
  • SimCity 4 Buildings
    • Lots
    • Mods & Tools
    • Maps
    • Props
    • Textures
    • 3ds Models
  • PLEX (Main Files)
    • Custom Lots & Mods
    • CDK - Coastal Development Kit
    • MTP - Mountain Theme Pack
    • SPAM - SimPeg Agricultural Mods
    • PEG Utopian Series
  • Cities: Skylines Buildings
    • Maps
    • Roads & Traffic
    • Vehicle Assets
    • Game Mods
    • Props
    • Programs & Tools
  • SimCity (2013) Buildings
    • Game Mods
    • Roads & Traffic
    • Vehicles
    • Programs & Tools
    • User Interface
  • SimCity 3000 Files
    • SC3K Maxis Files
    • Cities & Maps
  • CitiesXL Buildings
    • Mods & Tools
    • Maps
    • Textures & Props
    • Lots
    • 3d Models
  • Simtropolis en Español's Descargas
  • Friends of Dirktator's Dirk's Files
  • Infrastructure Club's Files
  • The Major Club's Files
  • Project Rich Water's Files
  • Guardians of the Galaxy's Files
  • New Washington's Files

City Journals

There are no results to display.

There are no results to display.


  • Weekly Challenge
  • Extended Challenge
  • Monthly Challenge
  • Content Challenge
  • Voting Period
  • Alliance of Independent Nations on Simtropolis's Alliance Calendar
  • Friends of Dirktator's Events
  • Infrastructure Club's Events
  • SimCampus Students's Events
  • SimCampus Students's Noggin Thinkers Dates
  • Arden County City Council's Events
  • The Major Club's Events
  • Project Rich Water's Events
  • Guardians of the Galaxy's Events
  • New Washington's Events




City-building game(s)

Found 43 results

  1. I decided to set up a page here to compliment my main Discount House of Lots page on Simpeg.com (Jul 15 - Simpeg is no longer online, link removed). There are two main reasons for this, firstly so that more people can get support for my content here as well and secondly because here I can attach those little things that I wouldn't bother to upload on the exchange, but that some people might find useful. Probably a good idea to explain that I'm both RSC204 here and MGB204 on SC4Devotion, MGB was not available to me here if I remember correctly but is my preferred handle. MGB - LHD-NWM-Tuleps Center-tile fix.zip: I'm not sure why, but my LHD install of NAM 32 doesn't have a blank NWM TULEP Center-tile. Being picky, I started out to make a single blank piece, but then I decided I didn't like the mismatch of textures, so I fixed those as well. Note this is for Euro textures and LHD ONLY, this needs to load after your z___NAM folder, but ideally in the last folder that loads to ensure no problems. Just to be clear, any attached files will not be subject to support in the way released mods would be, I will try to help with any problems though. Feel free to make requests, but bear in mind I am free also to decline. I plan on doing a lot of work for LHD stuff in the future, mostly just correcting stoplines, but I generally try to improve anything I find that I dislike on the way too.
  2. In this tutorial, we will create a simple mod that removes some of the ugly vanilla billboard props. You will learn how to work with loading hooks, prefab collections and the ModTools scene explorer. Step 1: Project Setup Create a new project named "CityBeautifier" in VS2017, following Method 2 in Tutorial 0 (working with a text editor is still possible in this tutorial, but not recommended) Your IUserMod implementation should look like this: using ICities; namespace CityBeautifier { public class CityBeautifierMod : IUserMod { public string Name => "City Beautifier"; public string Description => "Removes some ugly props"; } } Tip: The arrow syntax (=>) is a shorthand for the property syntax (get { return ...; }) used in the 0. tutorial. Both are equivalent. Step 2: Loading Hook The Mod API of Cities: Skylines contains various extension interfaces. You can create classes implementing these interfaces to hook into the game. The most important interface is ILoadingExtension. A class implementing this interface will get notified when the loading process begins and when it completes, and when a save is unloaded. Create a new file called CityBeautifierLoading.cs in the Solution Explorer. Add the following content to the file: using ColossalFramework.UI; using ICities; namespace CityBeautifier { public class CityBeautifierLoading : ILoadingExtension { // called when level loading begins public void OnCreated(ILoading loading) { } // called when level is loaded public void OnLevelLoaded(LoadMode mode) { // create dialog panel ExceptionPanel panel = UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel"); // display a message for the user in the panel panel.SetMessage("City Beautifier", "The level is loaded!", false); } // called when unloading begins public void OnLevelUnloading() { } // called when unloading finished public void OnReleased() { } } } Tip: You can also extend the class LoadingExtensionBase. It allows you to override a single loading method instead of implementing all methods Now compile the mod (F6). If there are any compilation errors, use the error list in VS2017 to locate and fix the error (View > Error List) When the compilation was successful, run the game. Enable the mod in content manager (if your mod does not show up, you probably forgot to setup the post build script). Now create or load a city. You will see the dialog panel as soon as the loading screen disappears: Close the game (UI development requires a complete restart after every change) Step 3: Working with the Prefab Collection Our goal is the removal of various props which are attached to buildings. To do that, we have to access the collection of loaded buildings, more specifically building prefabs. Prefabs vs. Instances: Building prefabs are templates for building instances. That means when a building instance is spawned, it uses the properties, textures and models defined in the building prefab. Modifying the building prefab usually causes all building instances to change. There are also prefabs for trees, props, vehicles and networks. Prefab classes of the game always end with Info (e.g. BuildingInfo, PropInfo, ...). All building prefabs can be found in the PrefabCollection<BuildingInfo>. We will now learn how to cycle through all buildings in this collection. Replace the OnLevelLoadedMethod with this code, then compile the mod and run the game: public void OnLevelLoaded(LoadMode mode) { // total number of loaded building assets int buildingPrefabCount = PrefabCollection<BuildingInfo>.LoadedCount(); // create a message string for the user string message = "Number of building assets: " + buildingPrefabCount; // create dialog panel ExceptionPanel panel = UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel"); // display the message in the panel panel.SetMessage("City Beautifier", message, false); } This will output the total number of loaded building prefabs: Now we will create a list of all building names, using a simple for loop. The LoadedCount() method returns the total number of prefabs. We can use the GetLoaded(uint) method to get the prefab objects, using a number in range 0 <= index < buildingPrefabCount: public void OnLevelLoaded(LoadMode mode) { int buildingPrefabCount = PrefabCollection<BuildingInfo>.LoadedCount(); string message = "Number of building assets: " + buildingPrefabCount; // append a list of building names to the message for(uint index = 0; index < buildingPrefabCount; index++) { // get the building asset with the given index from the collection BuildingInfo prefab = PrefabCollection<BuildingInfo>.GetLoaded(index); // append a separator and the name of the asset to the message message += ", "; message += prefab.name; } ExceptionPanel panel = UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel"); panel.SetMessage("City Beautifier", message, false); } The output looks like this: We learned how to access the building prefabs. In the next step, we will use ModTools to dive deeper into the structure of BuildingInfo objects. Step 4: Exploring and modifying building prefabs with the ModTools scene explorer Subscribe to ModTools and enable the mod in content manager. Create or load a city and click on a building you want to inspect. Then use the "Find in Scene Explorer" button. I picked one of the commercial buildings that is decorated with ugly billboards: The properties displayed in the scene explorer belong to the building instance. Props are defined in the building prefab. Luckily the prefab can be found right at the top (expand the "Info" property). Scroll down and expand the "m_props" property. You will see a list of prop items: Expand the items of the list to find out more about the props. Here you can change properties like position, probability and angle. Find the prop you want to remove and set the probability to 0: The prop will disappear instantly. Repeat the step for all props you want remove. Create a list of all prop names, like this: Billboard_big_variation_02 Billboard_big_variation_04 neon-yakisoba-noodles neon-burned-bean-coffee neon-morellos Billboard_big_variation Billboard_big_variation_01 Problem: The changes you applied to the prefabs are not permanent because prefabs are loaded from game/.crp files when you load your city. In the next step, we will change the probability values programmatically, in the loading class of our mod. Step 5: Modify building props programmatically We will remove the panel/message used in Step 3. Instead, we will add another nested for loop to cycle through all prop items of every building prefab: public void OnLevelLoaded(LoadMode mode) { for(uint index = 0; index < PrefabCollection<BuildingInfo>.LoadedCount(); index++) { // get the building prefab with the given index from the collection BuildingInfo prefab = PrefabCollection<BuildingInfo>.GetLoaded(index); // skip prefabs without props if(prefab == null || prefab.m_props == null) continue; for (int propIndex = 0; propIndex < prefab.m_props.Length; propIndex++) { // get the prop item BuildingInfo.Prop propItem = prefab.m_props[propIndex]; // skip trees/undefined props etc. if (propItem.m_prop == null) continue; string propName = propItem.m_prop.name; // check if the prop name equals one of the banned props if (propName == "Billboard_big_variation" || propName == "Billboard_big_variation_01" || propName == "Billboard_big_variation_02" || propName == "Billboard_big_variation_04" || propName == "neon-yakisoba-noodles" || propName == "neon-burned-bean-coffee" || propName == "neon-morellos") { // set the probability to zero to hide the props propItem.m_probability = 0; } } } } The continue keyword is a control statement of the for loop. It skips the execution of the current iteration and moves along to the next iteration of the loop. Tip: Instead of using the equals operator (==), you can use the Contains method to detect all prop names containing a certain string: if (propName.Contains("Billboard_big") || propName.Contains("neon-")) { propItem.m_probability = 0; } The result (before-after): You can see that the mod removes the billboards from all buildings. We reached our goal! Happy Coding! Tip: You can also remove trees with the same technique: if (propItem.m_tree == null) continue; string treeName = propItem.m_tree.name; Tip: You can limit the replacement to buildings with a certain name, or buildings of certain zone type: for(uint index = 0; index < PrefabCollection<BuildingInfo>.LoadedCount(); index++) { BuildingInfo prefab = PrefabCollection<BuildingInfo>.GetLoaded(index); if(prefab == null || prefab.m_props == null) continue; // filter by name if(!prefab.name.Contains("Blockhouse")) continue; // filter by building/service type if (prefab.m_class.m_service != ItemClass.Service.Industrial) continue; // ... } Next part:
  3. Hey guys, I've experienced a strange behavior of 2 of my cities: both cities (each built on the biggest segments of the "New York" landscape) have reached a high population of about 480.000 and 390.000 sims. Most r/c buildings are $$/$$$ and the (little) industry consists of 95% high tech. Then suddenly things became weird. Instead of growing the cities remained static and then even started losing inhabitants, got more and more unemployment, buildings decayed and nothing seemed to be able to stop this progress. I built new avenues/highways to connect the areas and/or expanded the public transport with underground/monorail which didn't help much. I demolished whole neighborhoods (loosing 50.000 sims each) and focused on enhancing the remaining ones. But here's what makes me really wonder: now even new designated zones with perfect conditions (nearby parks/plazas, avenues, stations, mixed r/c zones) aren't getting inhabited at all or just very very slowly. In fact I have to wait 1-2 in-game years on the fastest tempo until something develops even on low-density areas. And even then, I often get only poor $-buildings with little customers or residential buildings that decay some minutes later because of too long commute time. At the same time the need for $/$$ r/c is very high ($$$ jumps around 0), the mayor rating, too (70+). I've got plenty of parks, plazas and landscape/bonus buildings. So at the moments it seems that I just can get rid of buildings and sims but without the chance of getting anything new. Luckily the smaller city is stable now (but can't grow anymore) but the bigger one keeps "bleeding" … I also experimented with new traffic concepts, tried low and high density zones, fast-forwarded for 10 years and so on but that didn't work. I've not experienced this anytime before and the cities in the neighborhoods (pop. 30.000/120.000/130.00/190.000) seem to run normal and they all are built in a similar way (much public transport, very "green", fully developed education and health systems and so on). The whole region has about 1,4 Mio sims. All cities are connected via highways and public transport and have at least one neighbor deal running (trading power or waste). I usually don't touch taxes. I'm not quite sure, if this might be more a technical problem due to my laptop specs (i5 2,5GHz, 4GB RAM, AMD Radeon 7470M, Samsung Evo SSD, Win7) and the cities became just too big or if this a mistake of my gameplay. That's why I also tried some technical tips (cpu-core: 1, adding my GPU to the graphics card list, switching between hardware/software mode and AMD GPU/built-in Intel HD, low settings etc.) but non of those could fix my issue. And of course I'm playing with NAM (v35). So, any comments or recommendations?
  4. In this tutorial, we will replicate the functionality of the "Make Historical" checkbox in SimCity 4 (stop building from leveling up). The mod will utilize the same interfaces as the Control Building Level Up mod. You will learn how to inspect and modify user interfaces with ModTools, how the info panels of the game work, how to add a checkbox to the UI, how to control building level up with the official API, how to get notified when a building is added/removed and how to serialize custom data in the savegame. Once again, we will use the loading and threading hooks provided by the API. Step 1: Project Setup Create a new project named "MakeHistorical" in VS2017, following Method 2 in Tutorial 0 (working with a text editor is still possible in this tutorial, but not recommended) Your IUserMod implementation should look like this: using ICities; namespace MakeHistorical { public class MakeHistoricalMod : IUserMod { public string Name => "Make Historical"; public string Description => "Prevents the level up of buildings"; } } Step 2: Data Storage with Serialization Hook Data Structure We will store the ids (ushort) of the historical building instances in the savegame. Like in Tutorial 2 Step 4, we will create a data class that holds our data: using System.Collections.Generic; namespace MakeHistorical { public class MakeHistoricalData { public List<ushort> HistoricalBuildingIds { get; set; } = new List<ushort>(); } } The game requires additional savegame data to be in byte[] (byte array) format (basically zeros and ones, very low level). Luckily, Colossal Order provides a few useful tools to convert data classes to byte arrays (package ColossalFramework.IO). To use these tools, our data class must implement the IDataContainer interface. Extend the class like this: using System.Collections.Generic; using System.Linq; using ColossalFramework.IO; namespace MakeHistorical { public class MakeHistoricalData : IDataContainer { // The key for our data in the savegame public const string DataId = "MakeHistorical"; // Version of data save format // This is important when you add new fields to MakeHistoricalData public const int DataVersion = 0; public List<ushort> HistoricalBuildingIds { get; set; } = new List<ushort>(); // This serializes the object (to bytes) public void Serialize(DataSerializer s) { // convert ushort list to int array int[] ids = HistoricalBuildingIds.Select(id => (int)id).ToArray(); s.WriteInt32Array(ids); } // This reads the object (from bytes) public void Deserialize(DataSerializer s) { int[] ids = s.ReadInt32Array(); // convert int array to ushort list HistoricalBuildingIds = ids.Select(id => (ushort)id).ToList(); } // Validates that all building ids are active public void AfterDeserialize(DataSerializer s) { if (!BuildingManager.exists) return; List<ushort> validatedBuildingIds = new List<ushort>(); Building[] buildingInstances = BuildingManager.instance.m_buildings.m_buffer; // itertate through all building ids, filter active ids foreach (ushort buildingId in HistoricalBuildingIds) { if (buildingInstances[buildingId].m_flags != Building.Flags.None) { validatedBuildingIds.Add(buildingId); } } HistoricalBuildingIds = validatedBuildingIds; } } } What happened? We added the constants DataId and DataVersion. We will use these in the next step We implemented the Serialize method: In this method, we convert our list of ushort numbers to an integer array (the serializer does not support ushort) and pass it to a DataSerializer, which converts our array to bytes. We implemented the Deserialize method, which does the opposite of Serialize We implemented AfterDeserialize, which validates that all deserialized building ids belong to buildings (important when the mod was disabled for some time, to keep the data clean) Serialization System Colossal Order provides a serialization hook for mods (ISerializableDataExtension/SerializableDataExtensionBase). This hook is invoked when the savegame data is loaded, and when the user presses the save button. The game also provides a storage interface (ISerializableData) that allows us to write byte arrays to savegame and read byte arrays from savegame. Combined with the data class and the byte array conversion tools provided by Colossal Order, we will use this hook to save our data. Add a new MakeHistoricalDataManager class: using ColossalFramework.IO; using ICities; using System.IO; using UnityEngine; namespace MakeHistorical { public class MakeHistoricalDataManager : SerializableDataExtensionBase { // The data object of our mod private MakeHistoricalData _data; public override void OnLoadData() { // Get bytes from savegame byte[] bytes = serializableDataManager.LoadData(MakeHistoricalData.DataId); if (bytes != null) { // Convert the bytes to MakeHistoricalData object using (var stream = new MemoryStream(bytes)) { _data = DataSerializer.Deserialize<MakeHistoricalData>(stream, DataSerializer.Mode.Memory); } Debug.LogFormat("Data loaded (Size in bytes: {0})", bytes.Length); } else { _data = new MakeHistoricalData(); Debug.Log("Data created"); } } public override void OnSaveData() { byte[] bytes; // Convert the MakeHistoricalData object to bytes using (var stream = new MemoryStream()) { DataSerializer.Serialize(stream, DataSerializer.Mode.Memory, MakeHistoricalData.DataVersion, _data); bytes = stream.ToArray(); } // Save bytes in savegame serializableDataManager.SaveData(MakeHistoricalData.DataId, bytes); Debug.LogFormat("Data saved (Size in bytes: {0})", bytes.Length); } } } What happens here? The _data property stores our mod data The OnLoadData method attempts to read the saved byte array from the savegame. If the array was found, it converts the bytes to a MakeHistoricalData object (our data structure). If no array was found, it creates a new MakeHistoricalData object (new city or mod enabled for the first time). The OnSaveData method converts the MakeHistoricalData object to bytes, then saves the bytes in the savegame. Tip: To understand how data versioning works, look at this example data manager. Singleton To make the data readable from other classes, we will make MakeHistoricalDataManager implement a simple singleton pattern. We willl also add a few methods to lookup, add and remove building ids: // Singleton getter public static MakeHistoricalDataManager Instance { get; private set; } public bool IsHistorical(ushort buildingId) { return _data.HistoricalBuildingIds.Contains(buildingId); } public void AddBuildingId(ushort buildingId) { if (_data.HistoricalBuildingIds.Contains(buildingId)) return; _data.HistoricalBuildingIds.Add(buildingId); Debug.Log($"Historical Building {buildingId} added"); } public void RemoveBuildingId(ushort buildingId) { if (!_data.HistoricalBuildingIds.Contains(buildingId)) return; _data.HistoricalBuildingIds.Remove(buildingId); Debug.Log($"Historical Building {buildingId} removed"); } public override void OnCreated(ISerializableData serializedData) { base.OnCreated(serializedData); Instance = this; // initialize singleton } public override void OnReleased() { Instance = null; // reset singleton } Now we can use a simple statement to check if a building is historical: bool h = MakeHistoricalDataManager.Instance.IsHistorical(1234); Final code of the MakeHistoricalDataManager class. Step 3: Removing destroyed buildings from the list We have to remove buildings from the list when they are buldozed. Luckily CO added a hook just for that (not documented in the wiki): using ICities; using UnityEngine; namespace MakeHistorical { public class MakeHistoricalBuildingMonitor : BuildingExtensionBase { public override void OnBuildingReleased(ushort id) { if (MakeHistoricalDataManager.Instance.IsHistorical(id)) { // Remove demolished/destroyed buildings from the list of historical buildings MakeHistoricalDataManager.Instance.RemoveBuildingId(id); } } } } Tip: With the IBuildingExtension/BuildingExtensionBase hook, you can also manipulate which buildings are spawned, and there are hooks for building creation and relocation. Step 4: Inspecting And Manipulating User Interfaces with ModTools and ILSpy Like in SimCity 4, we will add a "Make Historical" checkbox to the building info window: To do that, we have to find out how to access the info window programmatically. ModTools supports us with its "debug view". You can toggle it with CTRL + R. Then move your mouse over the info panel (so that the tint of the panel changes to green) and press CTRL + F: The UI window component is now displayed in the ModTools scene explorer. The class name of the element is ZonedBuildingWorldInfoPanel. In the scene explorer, we can change properties like the colour, size and position of the window. We can also look at the child UI elements (buttons, text labels). The position of the child elements is determined by the relativeLayout property. Noted values: Height: 321 Left Padding: 14 (based on the child element positions) Bottom Padding: 27 (based on the child element positions) Now that we know the class name, we can locate the class in ILSpy to find out how to access it programmatically: ZonedBuildingWorldInfoPanel is a subclass of WorldInfoPanel, which contains a static Show<>() method: // WorldInfoPanel (taken from ILSpy) public static void Show<TPanel>(Vector3 worldMousePosition, InstanceID instanceID) where TPanel : WorldInfoPanel { TPanel tPanel = UIView.library.Show<TPanel>(typeof(TPanel).Name, false); tPanel.SetTarget(worldMousePosition, instanceID); tPanel.component.opacity = 1f; } After further investigation (use ILSpy's "Analyze" feature), you will find a Get<>() method in UIView.library which returns the ZonedBuildingWorldInfoPanel instance: var panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); Note: There is only one panel instance, which is just filled with the data of the currently selected building. The panel even exists when no building is selected, it's just hidden. Step 5: Adding a Checkbox to the Info Panel Finding the right property values for user interfaces is a finicky task, especially when you have to restart the game after every little change. Using the ModTools console, we can add and modify our checkbox while the game is running. Run this script in the ModTools console (F7): var panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); var checkBox = panel.component.AddUIComponent<UICheckBox>(); checkBox.width = panel.component.width; checkBox.height = 20f; checkBox.clipChildren = true; UISprite sprite = checkBox.AddUIComponent<UISprite>(); sprite.spriteName = "ToggleBase"; sprite.size = new Vector2(16f, 16f); sprite.relativePosition = Vector3.zero; checkBox.checkedBoxObject = sprite.AddUIComponent<UISprite>(); ((UISprite)checkBox.checkedBoxObject).spriteName = "ToggleBaseFocused"; checkBox.checkedBoxObject.size = new Vector2(16f, 16f); checkBox.checkedBoxObject.relativePosition = Vector3.zero; checkBox.label = checkBox.AddUIComponent<UILabel>(); checkBox.label.text = " "; checkBox.label.textScale = 0.9f; checkBox.label.relativePosition = new Vector3(22f, 2f); checkBox.name = "MakeHistorical"; checkBox.text = "Make Historical"; This will add everything that is required for a checkbox, giving it the name "MakeHistorical". It is still in the wrong position: Tip: SamsamTS created a very useful utility class that allows you to create various UI elements. The code above was copied from that class. With ModTools, we can experiment with the position without restarting the game. Execute this code in the ModTools console: var panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); var checkBox = panel.component.Find<UICheckBox>("MakeHistorical"); checkBox.relativePosition = new Vector3(14f, 164f + 130f + 5f); Result: Now we just have to increase the height of the window a little bit. Execute this code in the ModTools console: var panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); panel.component.height = 321f + 5f + 20f; Result: Now, we will put the code we just executed with the console into the loading hook of our mod: using ColossalFramework.UI; using ICities; using UnityEngine; namespace MakeHistorical { public class MakeHistoricalLoading : LoadingExtensionBase { private UICheckBox _makeHistoricalCheckBox; public override void OnLevelLoaded(LoadMode mode) { if (_makeHistoricalCheckBox != null) return; ZonedBuildingWorldInfoPanel panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); UICheckBox checkBox = panel.component.AddUIComponent<UICheckBox>(); checkBox.width = panel.component.width; checkBox.height = 20f; checkBox.clipChildren = true; UISprite sprite = checkBox.AddUIComponent<UISprite>(); sprite.spriteName = "ToggleBase"; sprite.size = new Vector2(16f, 16f); sprite.relativePosition = Vector3.zero; checkBox.checkedBoxObject = sprite.AddUIComponent<UISprite>(); ((UISprite)checkBox.checkedBoxObject).spriteName = "ToggleBaseFocused"; checkBox.checkedBoxObject.size = new Vector2(16f, 16f); checkBox.checkedBoxObject.relativePosition = Vector3.zero; checkBox.label = checkBox.AddUIComponent<UILabel>(); checkBox.label.text = " "; checkBox.label.textScale = 0.9f; checkBox.label.relativePosition = new Vector3(22f, 2f); checkBox.name = "MakeHistorical"; checkBox.text = "Make Historical"; checkBox.relativePosition = new Vector3(14f, 164f + 130f + 5f); panel.component.height = 321f + 5f + 16f; _makeHistoricalCheckBox = checkBox; } } } Compile the mod (F6). If there are any compilation errors, use the error list in VS2017 to locate and fix the error (View > Error List) When the compilation was successful, run the game. Enable the mod in content manager (if your mod does not show up, you probably forgot to setup the post build script). Now create or load a city, open the building info window for a growable building. Et voila: Step 6: Processing Checkbox Events To process checkbox events, we will add a delegate to the CheckedChange event: public override void OnLevelLoaded(LoadMode mode) { ... checkBox.eventCheckChanged += (component, check) => { ushort buildingId = WorldInfoPanel.GetCurrentInstanceID().Building; if (check) { MakeHistoricalDataManager.Instance.AddBuildingId(buildingId); } else { MakeHistoricalDataManager.Instance.RemoveBuildingId(buildingId); } }; } Clicking the checkbox now triggers the data manager: Step 7: Monitoring the ZonedBuildingWorldInfoPanel with a Threading Hook There is another problem: The checkbox is not updated when you select a building. We will use a threading hook to update the checkbox: using ColossalFramework.UI; using ICities; namespace MakeHistorical { public class MakeHistoricalPanelMonitor : ThreadingExtensionBase { private ZonedBuildingWorldInfoPanel _panel; private UICheckBox _makeHistoricalCheckBox; private ushort _lastBuildingId = 0; // called every frame public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) { if (!FindComponents()) return; if (_panel.component.isVisible) { ushort buildingId = WorldInfoPanel.GetCurrentInstanceID().Building; if (_lastBuildingId != buildingId) { // display the right checkbox state _makeHistoricalCheckBox.isChecked = MakeHistoricalDataManager.Instance.IsHistorical(buildingId); _lastBuildingId = buildingId; } } else { _lastBuildingId = 0; } } private bool FindComponents() { if (_panel != null && _makeHistoricalCheckBox != null) return true; _panel = UIView.library.Get<ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); if (_panel == null) return false; _makeHistoricalCheckBox = _panel.component.Find<UICheckBox>("MakeHistorical"); return _makeHistoricalCheckBox != null; } } } Step 8: Controlling Building Level Up It took quite some time to get to this point (UI and serialization are always very time consuming). The last missing piece is the ILevelUpExtension/LevelUpExtensionBase hook, which monitors and manipulates the level up behaviour of buildings. Probably the least complicated part of the mod: using ICities; namespace MakeHistorical { public class MakeHistoricalLevelUpMonitor : LevelUpExtensionBase { public override ResidentialLevelUp OnCalculateResidentialLevelUp(ResidentialLevelUp levelUp, int averageEducation, int landValue, ushort buildingID, Service service, SubService subService, Level currentLevel) { if (MakeHistoricalDataManager.Instance.IsHistorical(buildingID)) { levelUp.targetLevel = currentLevel; } return levelUp; } public override CommercialLevelUp OnCalculateCommercialLevelUp(CommercialLevelUp levelUp, int averageWealth, int landValue, ushort buildingID, Service service, SubService subService, Level currentLevel) { if (MakeHistoricalDataManager.Instance.IsHistorical(buildingID)) { levelUp.targetLevel = currentLevel; } return levelUp; } public override IndustrialLevelUp OnCalculateIndustrialLevelUp(IndustrialLevelUp levelUp, int averageEducation, int serviceScore, ushort buildingID, Service service, SubService subService, Level currentLevel) { if (MakeHistoricalDataManager.Instance.IsHistorical(buildingID)) { levelUp.targetLevel = currentLevel; } return levelUp; } public override OfficeLevelUp OnCalculateOfficeLevelUp(OfficeLevelUp levelUp, int averageEducation, int serviceScore, ushort buildingID, Service service, SubService subService, Level currentLevel) { if (MakeHistoricalDataManager.Instance.IsHistorical(buildingID)) { levelUp.targetLevel = currentLevel; } return levelUp; } } } The logic is very simple: When the building is historical, the target level is set to the current building level. And we are done! Buildings with the "Make Historical" checkbox enabled will no longer level up. The list of historical buildings is stored in the savegame. Happy Coding! Download Source
  5. Southern winter vacations had arrived, and with them, free time to experiment with the game. After years of playing and roaming the site, a simple test on using a sidewalk mod overflowed on the creation of my own sidewalk mod, all thanks to the high tech advancements by Rivit and MGB (a.k.a. rsc204). Well, in fact it begun a little before: in March I uploaded a fictional map, and surprisingly, people is using it! So, to take advantage of the momentum already gained, I'm opening this thread, to give support on this couple of humble custom content I've done, but also to try creating something more. By now, I let you with what is already done: Ciudad del Lago (map) A 24x24 km square region with lots of hills and natural canals, and plenty of pre-terraformed plains to build Veredas Santiaguinas (sidewalk mod) A Santiago de Chile inspired SD sidewalk mod for Maxis networks, lots and NAM networks, made with MGB's Automated Sidewalk Mod. Now it also includes SCILT support! Basaltic Sands (sand and beach texture mod) Blackish SD sand textures for basaltic beaches, from Polynesia to Iceland Basalt Column Tiles (sidewalk mod) A SD sidewalk mod made of sliced basalt columns, for your hotspot-placed cities <-- working on this Basalt Columns (cliff texture mod) A SD cliff texture that mimics basalt columns, with different hues for various locations: Iceland, Spain, Yellowstone, New Zeland, Taiwan, etc. <-- researching m93 KOSC SuperSHK+ retexture for Veredas Santiaguinas and Sudden Valley (override of SuperSHK textures) What it says on the title
  6. In this tutorial, we will create a basic mod in two different ways: With a simple text editor, and with the Visual Studio IDE. Cities: Skylines uses the Unity Engine, which is based on Mono, an open source implementation of the .NET framework that runs on Windows, Mac and Linux. That means the same code can be used on all of these platforms. The .NET framework is comparable to Java. It's basically a set of libraries and a virtual machine that runs your .NET applications. C# is the most common programming language that can be used to create .NET applications and libraries. It's very similar to Java (just better!). After writing your mod in C#, you have to compile it to create machine readable code. Cities: Skylines comes with an integrated compiler. It works like this: [.cs files containing raw C# code] → [COMPILER] → [compiled .dll file] The .dll file is your compiled mod (what you usually download from the Workshop). Alternatively, your can use an external compiler like the one provided by Visual Studio (see Method 2). Method 1: Using Notepad, let the game compile First we will create a mod with the tools provided by the game. The game searches for mod source folders in the directory C:\Users\<YourName>\AppData\Local\Colossal Order\Cities_Skylines\Addons\Mods. In this folder, create a new directory named "FirstMod". Inside of the new directory, create another folder named "Source". That's the directory for the .cs files Open Notepad (or your favourite text editor) and enter this code: // Makes UnityEngine and Cities: Skylines API classes available for use using ICities; using UnityEngine; // the namespace makes the names of your classes unique. // Naming: You can just use the name of your mod, it doesn't really matter. Spaces are not allowed. namespace Tutorial { // This defines a class that implements IUserMod. // The class defines the name and description displayed in the content manager. // The game searches for these classes. Every working mod must contain one class implementing IUserMod. // Naming: Just append "Mod" to the name of your mod, like "NetworkSkins" -> "NetworkSkinsMod". Spaces are not allowed. public class MyFirstMod : IUserMod { // this defines the title of your mod displayed in content manager public string Name { get { return "My First Mod"; } } // this defines the description of your mod displayed in content manager public string Description { get { return "Hello World, this is my first mod!"; } } } } (Lines starting with "//" are comments. You can add your own or remove them without affecting anything.) Save the file in the "Source" directory. Name it FirstMod.cs (in the file type dropdown, select "All Files"). Now just start your game. The game compiles your mod on start up. You will find it in the content manager: You will also notice a new .dll file in your mod directory. That's your compiled mod: So far we didn't add functionality to the mod. It only spawns the item in content manager. The big problem of Notepad and the game compiler is that it is hard to find errors in your code. You will have to restart your game many times. That's where Visual Studio comes into play... Method 2: Using Visual Studio (recommended) Visual Studio is a specialized IDE for C#/.NET development. It helps you to find errors in your code, and it autocompletes code statements for you, and it compiles your mod much faster than the game. It is also a requirement for advanced modding techniques like detours. The following tutorials will be based on Visual Studio. First of all, download and install Visual Studio Community 2017 for free. Make sure that the .NET desktop development feature is checked. Also enable the individual component .NET Framework 3.5 development tools. Step 1: Project Setup Create a new project in VS2017: Select File > New > Project On the left, select Templates > Visual C# > Windows Classic Desktop Select "Class Library (.NET Framework)" In the top, select ".NET Framework 3.5" in the dropdown menu (Important!) In the bottom, enter "SecondMod" as the name and solution name. and choose a location for your project files (e.g. your desktop) Press OK Visual Studio will create a project that looks like this: On the right, you can see the Solution Explorer with a list of .cs files. Visual Studio created a file named Class1.cs to get us started. If you want, you can rename the .cs file to match your mod name (Right click in solution explorer > Rename). Step 2: Dependencies Before we continue, we have to set up two things in the project. You always have to do it when you create a new mod project: First, we will add the modding API (ICities), UnityEngine, ColossalFramework and the game assembly (Assembly-CSharp) as dependencies. In the solution explorer, right click the "References" item and select "Add reference..."). Now use the "Browse..." button in the bottom to select the following .dll files. The files are located in the folder: Steam\steamapps\common\Cities_Skylines\Cities_Data\Managed Step 3: Post Build Script Secondly, we will add a so-called post build script: It automatically puts the compiled dll file into the C:SL mod directory when you compile with Visual Studio: Right-click your project in the Solution Explorer and choose Properties Select Build Events on the left hand side of the property sheet Paste the following in the Post-build event command line: mkdir "%LOCALAPPDATA%\Colossal Order\Cities_Skylines\Addons\Mods\$(SolutionName)" del "%LOCALAPPDATA%\Colossal Order\Cities_Skylines\Addons\Mods\$(SolutionName)\$(TargetFileName)" xcopy /y "$(TargetPath)" "%LOCALAPPDATA%\Colossal Order\Cities_Skylines\Addons\Mods\$(SolutionName)" Step 4: Writing the Mod Now we are finally ready for the creation of the actual mod. Replace the contents of Class1.cs with this code: using ICities; using UnityEngine; namespace Tutorial { public class MySecondMod : IUserMod { public string Name { get { return "My Second Mod"; } } public string Description { get { return "I made this with VS2017"; } } } } Step 5: Compilation Press F6 (or Build > Build Solution) to compile the mod. The mod should appear in your mod directory. Now start the game and enjoy the listing of your useless mod in content manager Happy Coding! Next part:
  7. In this tutorial, we will create a simple mod that globally replaces vanilla road trees with custom trees made by MrMaison. Like in Tutorial 1, we will use a loading hook, prefab collections and the ModTools scene explorer. You will also learn how to add settings to your mod. Step 1: Exploring and modifying network and tree prefabs with the ModTools scene explorer Before writing the actual mod, we will apply the replacement with the ModTools scene explorer. Just like buildings, networks and trees are defined as prefabs (NetInfo and TreeInfo, see Tutorial 1 Step 3). There are various way to find these prefabs in the ModTools scene explorer. The easiest way that works for vanilla and workshop assets is the ToolsController. "Tools" in Cities: Skylines allow you to interact with the game world. The most obvious tool is the bulldozer, but there are also tools for the placement of objects, zoning, transport line creation and camera control. For this tutorial, we will access the TreeTool and the NetTool, which hold a reference to the tree/network prefab you are placing. Select a tree you in the Landscaping panel. I chose the Royal Palm made by MrMaison. While the placement mode is enabled, open the ModTools scene explorer (CTRL + E). On the left, select Tool Controller > TreeTool. You will see the properties of the TreeTool on the right. The currently selected tree prefab is stored in the m_prefab property. Press the "Copy" button to copy the reference of the tree prefab to the ModTools clipboard (it does not copy the actual data, just the memory address of the prefab). Tip: For every prefab (prop, building, network, ...) there is also a "Preview" button that displays a model viewer, and more importantly, a "Plop" button that allows you to plop the asset. With this button, you can place assets which are not available in the panels of the game, like props or sub-buildings. Now, select a road with trees in the Roads panel. I chose the "Large Avenue with Grass" that was added by the MT update. Open the scene explorer and select Tool Controller > NetTool. On the right, expand the m_prefab property (the currently selected network prefab). You can now see the properties of the network prefab. The structure of a network prefab looks like this: NetInfo: Network Prefab ├ m_nodes[]: Array of objects defining meshes/textures for intersections ├ m_segments[]: Array of objects defining meshes/textures for segments ├ m_lanes[]: Array of NetInfo.Lane objects │ └ NetInfo.Lane: Defines a lane used by vehicles or pedestrians + prop/tree decoration │ ├ m_laneProps │ │ └ m_props[]: Array of prop items │ │ └ NetLaneProps.Prop: Like BuildingInfo.Prop, defines the position a prop/tree │ │ ├ m_prop/m_finalProp: The prop prefab │ │ ├ m_tree/m_finalTree: The tree prefab │ │ ├ m_probability: Probability that the prop/tree spawns │ │ ├ m_repeatDistance: Distance between two props/trees │ │ └ ... │ └ ... └ ... Expand the m_lanes array and search for the lane that contains the tree prop items you want to replace. In case of the "Large Avenue with Grass", navigate to m_lanes > m_lanes.[0] > m_laneProps > m_props > m_props.[4]: Click the "Paste" button on the right for the properties m_finalTree and m_tree. This will assign the custom tree prefab we copied earlier to the prop item: You will instantly see the result: The trees of all avenues in the city have been replaced. In the next steps, we will create a mod that automates the replacement. Step 2: Project Setup Create a new project named "RoadTreeReplacer" in VS2017, following Method 2 in Tutorial 0 (working with a text editor is still possible in this tutorial, but not recommended) Your IUserMod implementation should look like this: using ICities; namespace RoadTreeReplacer { public class RoadTreeReplacerMod : IUserMod { public string Name => "Road Tree Replacer"; public string Description => "Replaces the boring Oak roadside trees with MrMaison's creations"; } } Step 3: Loading Hook & Tree Replacement Logic Create a new file called RoadTreeReplacerLoading.cs in the Solution Explorer. This file will contain our ILoadingExtension implementation that is invoked by the game when a save is loaded (See Tutorial 1 Step 2). Like in the last tutorial, we will use the static PrefabCollection class to find our network and tree prefab. Add the following contents to the file: using UnityEngine; using ICities; namespace RoadTreeReplacer { public class RoadTreeReplacerLoading : LoadingExtensionBase { public override void OnLevelLoaded(LoadMode mode) { // Find the network NetInfo netPrefab = PrefabCollection<NetInfo>.FindLoaded("Avenue Large With Grass"); // Find the tree we want to use as a replacement TreeInfo treePrefab = PrefabCollection<TreeInfo>.FindLoaded("909448182.Royal Palm_Data"); // Check if both prefabs are loaded, cancel if not if (netPrefab == null) { Debug.LogError("RTR: The network could not be found"); return; } if (treePrefab == null) { Debug.LogError("RTR: The replacement tree could not be found"); return; } // cancel if lanes array is null (networks without lanes) if (netPrefab.m_lanes == null) return; // iterate through all lanes foreach (NetInfo.Lane lane in netPrefab.m_lanes) { // cancel if lane props array is null (networks without lanes) if (lane?.m_laneProps?.m_props == null) continue; // iterate through all lane props of that lane foreach (NetLaneProps.Prop laneProp in lane.m_laneProps.m_props) { if (laneProp == null) continue; // if the tree/finalTree field is set, replace it with our tree prefab if (laneProp.m_tree != null) { laneProp.m_tree = treePrefab; } if (laneProp.m_finalTree != null) { laneProp.m_finalTree = treePrefab; } } } Debug.Log("RTR: Replacement successful!"); } } } Tip: You can use the Debug.Log(...) method to add log entries to the output_log.txt. The log entries are also displayed in the ModTools console, which can be used for debugging your mod. Now compile the mod (F6). If there are any compilation errors, use the error list in VS2017 to locate and fix the error (View > Error List) When the compilation was successful, run the game. Enable the mod in content manager (if your mod does not show up, you probably forgot to setup the post build script). Now create or load a city. The tree replacement is now automated. You will also see the success message in the ModTools console: Before we proceed with the next step, we will move our replacement code to a separate ReplaceNetTrees method. We can call this method multiple times with a single line of code: using UnityEngine; using ICities; namespace RoadTreeReplacer { public class RoadTreeReplacerLoading : LoadingExtensionBase { public override void OnLevelLoaded(LoadMode mode) { ReplaceNetTrees("Avenue Large With Grass", "909448182.Royal Palm_Data"); ReplaceNetTrees("Medium Road Decoration Trees", "909448182.Royal Palm_Data"); } private void ReplaceNetTrees(string netName, string treeName) { NetInfo netPrefab = PrefabCollection<NetInfo>.FindLoaded(netName); TreeInfo treePrefab = PrefabCollection<TreeInfo>.FindLoaded(treeName); if (netPrefab == null) { Debug.LogError($"RTR: The network {netName} could not be found"); return; } if (treePrefab == null) { Debug.LogError($"RTR: The replacement tree {treeName} could not be found"); return; } if (netPrefab.m_lanes == null) return; foreach (NetInfo.Lane lane in netPrefab.m_lanes) { if (lane?.m_laneProps?.m_props == null) continue; foreach (NetLaneProps.Prop laneProp in lane.m_laneProps.m_props) { if (laneProp == null) continue; if (laneProp.m_tree != null) laneProp.m_tree = treePrefab; if (laneProp.m_finalTree != null) laneProp.m_finalTree = treePrefab; } } Debug.Log($"RTR: Replacement of tree in network {netName} successful!"); } } } Step 4: Adding Mod Settings Right now the functionality of the mod is fixed, there is no way to configure which trees are replaced. Adding settings to a mod is a difficult task. It will require 3 components: User interface with checkboxes or dropdown menus (using the settings API provided by CO, or a custom window) Data structure for the settings data (usually a C# class, or a set of key-value pairs) Serialization System (to .xml file, or save game) To keep it simple, we will only add a simple settings page with 3 dropdown options (Small Road Tree, Medium Road Tree, Large Road Tree), with a fixed number of trees to choose from (Default, Royal Palm, Weeping Silver Birch, River Red Gum Small). The settings will saved in a .xml file in the Cities: Skylines installation directory. The settings are global, that means the mod applies the same settings to all cities (in one of the next tutorials, I will show you how to save additional data in the save game). Serialization System Add a new file called Configuration.cs and paste this code. It is a very minimalistic serialization library that I've written some time ago. It does all the heavy lifting for you (loading and saving of .xml files, transformation from/to C# objects). It is not important to understand what happens internally, you just have to understand how to use it. The library provides a method to load your configuration data: YourConfiguration config = Configuration<YourConfiguration>.Load(); And to save it: Configuration<YourConfiguration>.Save(); You only have to provide the data class that defines the structure of the .xml file. Data Structure Add a new class named RoadTreeReplacerConfiguration. This data class contains the string options we want to save: namespace RoadTreeReplacer { [ConfigurationPath("RoadTreeReplacer.xml")] public class RoadTreeReplacerConfiguration { public string SmallRoadTree { get; set; } = "909448182.Royal Palm_Data"; public string MediumRoadTree { get; set; } = "909448182.Royal Palm_Data"; public string LargeRoadTree { get; set; } = "909448182.Royal Palm_Data"; } } The [ConfigurationPath] attribute is read by the serialization library. The strings on the right are the default values used when a new configuration is created. User Interface Some time ago, CO added a simple settings API that allows you to create simple setting menus with a few lines of code. To use it, add a new method called OnSettingsUI to your IUserMod implementation: using System; using System.Collections.Generic; using ICities; namespace RoadTreeReplacer { public class RoadTreeReplacerMod : IUserMod { public string Name => "Road Tree Replacer"; public string Description => "Replaces the boring Oak roadside trees with MrMaison's creations"; // The strings displayed in the dropdown private static readonly string[] OptionLabels = { "Default", "Royal Palm", "Weeping Silver Birch", "River Red Gum" }; // The corresponding prefab names private static readonly string[] OptionValues = { "Tree2Variant", "909448182.Royal Palm_Data", "765126845.Weeping Silver Birch_Data", "742114726.River Red Gum small_Data" }; // Sets up a settings user interface public void OnSettingsUI(UIHelperBase helper) { // Load the configuration RoadTreeReplacerConfiguration config = Configuration<RoadTreeReplacerConfiguration>.Load(); // Small Roads int smallSelectedIndex = GetSelectedOptionIndex(config.SmallRoadTree); helper.AddDropdown("Small Road Tree", OptionLabels, smallSelectedIndex, sel => { // Change config value and save config config.SmallRoadTree = OptionValues[sel]; Configuration<RoadTreeReplacerConfiguration>.Save(); }); // Medium Roads int mediumSelectedIndex = GetSelectedOptionIndex(config.MediumRoadTree); helper.AddDropdown("Medium Road Tree", OptionLabels, mediumSelectedIndex, sel => { // Change config value and save config config.MediumRoadTree = OptionValues[sel]; Configuration<RoadTreeReplacerConfiguration>.Save(); }); // Large Roads int largeSelectedIndex = GetSelectedOptionIndex(config.LargeRoadTree); helper.AddDropdown("Large Road Tree", OptionLabels, largeSelectedIndex, sel => { // Change config value and save config config.LargeRoadTree = OptionValues[sel]; Configuration<RoadTreeReplacerConfiguration>.Save(); }); } // Returns the index number of the option that is currently selected private int GetSelectedOptionIndex(string value) { int index = Array.IndexOf(OptionValues, value); if (index < 0) index = 0; return index; } } } What happens here? Load the config data with the Load method provided by the library Get the index of the dropdown option that should be selected at first Add a dropdown option with label, options, selected index and a callback (called when selection is changed) (Repeat 2. and 3. for medium and large roads) The OptionLabels array contains the strings displayed in the dropdown menus. The other array, OptionValues, contains the internal names of the prefabs. The callback is a lamda function that takes the selected index (0-3). It saves the value that corresponds to the selected index in the configuration file. The game automatically creates a settings page for mods which are implementing the OnSettingsUI method. No further steps are needed. Tip: Other methods for UI element generation: AddButton(), AddCheckbox(), AddGroup(), AddSlider(), AddSpace(), AddTextfield() Step 5: Using the configuration values in our loading hook In the RoadTreeReplacerLoading class, replace the OnLevelLoaded method: public override void OnLevelLoaded(LoadMode mode) { // Load the configuration RoadTreeReplacerConfiguration config = Configuration<RoadTreeReplacerConfiguration>.Load(); ReplaceNetTrees("Basic Road Decoration Trees", config.SmallRoadTree); ReplaceNetTrees("Oneway Road Decoration Trees", config.SmallRoadTree); ReplaceNetTrees("Medium Road Decoration Trees", config.MediumRoadTree); ReplaceNetTrees("Avenue Large With Grass", config.MediumRoadTree); ReplaceNetTrees("Avenue Large With Buslanes Grass", config.MediumRoadTree); ReplaceNetTrees("Large Road Decoration Trees", config.LargeRoadTree); ReplaceNetTrees("Large Oneway Decoration Trees", config.LargeRoadTree); } This will replace the trees of all vanilla roads with the trees selected in the settings. And we are done! After changing the options for the first time, the settings are saved to .xml: Note: To apply the changed settings, you have to reload your city. Happy Coding! Download Source Next part:
  8. Version 1.0.0


    Source Code of the Make Historical Mod Tutorial for Cities: Skylines. Created with Visual Studio 2017
  9. In this tutorial, we will replicate the functionality of the Show Limits mod. Like in Tutorial 1, we will use the default alert window to display the limits. You will learn how to use ILSpy for reverse engineering, how to access singleton manager objects, how to work with building/tree instances and how to listen to keyboard shortcuts. Step 1: Exploring the game source code in ILSpy Download the latest version of ILSpy (select "Download Binaries"). ILSpy is an open source decompiler that allows you to take a look at the source code of the game and other mods. It's basically the opposite of a compiler: [compiled .dll file] → [DECOMPILER] → [.cs files containing raw C# code] The restored source code is not exactly the same as the original code. Names of variables defined in methods are lost, which makes the code harder to read. Some parts of the loading code are not readable (enumerators), but that won't bother us. Open the Assembly-CSharp.dll file in ILSpy (C:\Program Files (x86)\Steam\steamapps\common\Cities_Skylines\Cities_Data\Managed). On the left, expand the source tree: The tree contains all classes and structs of the game. Select one of them to view the source code. There are different types of classes, here are the most common ones: ...Info: Prefabs or other assets (see Tutorial 1 and 2) Building, Citizen, District, NetLane, NetNode, NetSegment, PropInstance, TransportLine, TreeInstance, Vehicle, ZoneBlock (structs): Instances of objects, managed by a simulation system. There is a limit how many instances of a certain type can exist. ...AI: AI behaviour attached to prefabs, calculating the behavior of object instances. ...Manager: A simulation system, responsible for rendering, simulation and creation/deletion of instances ...Tool: Tool for interacting with the city ...Collection: A collection of prefabs or assets ...Properties: Properties for simulation systems, like colors, shaders and constants ...Panel: UI elements ...Wrapper: Implementation of the official modding API The various manager classes are the key components of the game. Managers extend the Singleton<> class. The singleton pattern is a software design pattern that ensures that only one instance of a class exists. You can easily access a singleton in Cities: Skylines with the static instance field: string cityName = SimulationManager.instance.m_metaData.m_CityName; Debug.Log("Name of the city: " + cityName); Alternatively: Singleton<SimulationManager>.instance Tip: You can run these code snippets with the ModTools console (F7) Today we will take a look at the TreeManager and BuildingManager to display the number of trees and buildings. Tree Manager Select the TreeManager in ILSpy. After scrolling down a few lines in the source code, you will find the constant MAX_TREE_COUNT and the integer field m_treeCount: Outputting these numbers will lead to the desired result. We will go a step further and check how the m_treeCount field is calculated. Right click the m_treeCount item in the left sidebar and select "Analyze": The panel at the bottom displays which methods are reading the field, and which methods are assigning values to the field. For example, the AssetEditorChirpPanel and EditorChirpPanel are reading the field to display the number of trees in the asset/map editor. The field is modified by 3 methods of the TreeManager: CreateTree: When a new tree instance is placed, increment the value by 1. ReleaseTreeImplementation: When a tree instance is deleted, decrement the value by 1 Data.AfterDeserialize: After a save game is loaded, recalculate the tree count The last method is particularly interesting. Double click it to view the source code of the method: The method calls TreeManager.instance.m_trees.ItemCount() to calculate the number of trees. m_trees is a special kind of array list (Array16<TreeInstance>) that is used by the game to manage instances of trees, props, buildings etc. The list contains a fixed number of TreeInstance structs (262144 in case of trees). When a new tree is created, one of the unused items from the listt is activated and used to describe the state, position and type of a tree. A few lines above you can see how the game iterates through the list to modify the active items. Tip: You can also use the "Analyze" feature on methods and classes. It will help you to understand how the different components of the game are connected. Building Manager Now, select the BuildingManager on the left. You will notice that the BuildingManager contains the same kind of fields: const int MAX_BUILDING_COUNT: The max number of building instances int m_buildingCount: The current number of building instances Array16<Building> m_buildings: The array list containing the building instances Step 2: Outputting the limits with ModTools Before writing our mod, we will create a ModTools script to see if everything works: int treeCount = TreeManager.instance.m_treeCount; int maxTreeCount = TreeManager.MAX_TREE_COUNT; Debug.Log("Number of trees: " + treeCount + " of " + maxTreeCount); int buildingCount = BuildingManager.instance.m_buildingCount; int maxBuildingCount = BuildingManager.MAX_BUILDING_COUNT; Debug.Log("Number of buildings: " + buildingCount + " of " + maxBuildingCount); Load or create a city and open the ModTools console (F7). In the bottom of the console, paste the script and press the "Run" button: Step 3: Project Setup Create a new project named "ShowLimits" in VS2017, following Method 2 in Tutorial 0 (working with a text editor is still possible in this tutorial, but not recommended) Your IUserMod implementation should look like this: using ICities; namespace ShowLimits { public class ShowLimitsMod : IUserMod { public string Name => "Show Limits"; public string Description => "Displays the number of buildings and trees in your city (Hotkey CTRL + I)"; } } Step 4: Threading Hook & Hotkeys The IThreadingExtension/ThreadingExtensionBase is another hook provided by the official modding API. Classes implementing IThreadingExtension are invoked before, during and after every simulation tick (many times per second). It is important that the contained code is very light-weight (no IO operations, like reading configuration files, no object construction...). We will use the hook to check if the player is pressing they keyboard shortcut (CTRL + I). Create a new class called ShowLimitsThreading: using ColossalFramework.UI; using ICities; using UnityEngine; namespace ShowLimits { public class ShowLimitsThreading : ThreadingExtensionBase { private bool _processed = false; public override void OnUpdate(float realTimeDelta, float simulationTimeDelta) { if ((Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl)) && Input.GetKey(KeyCode.I)) { // cancel if they key input was already processed in a previous frame if (_processed) return; _processed = true; // compose message int treeCount = TreeManager.instance.m_treeCount; int maxTreeCount = TreeManager.MAX_TREE_COUNT; int buildingCount = BuildingManager.instance.m_buildingCount; int maxBuildingCount = BuildingManager.MAX_BUILDING_COUNT; string message = $"Trees: {treeCount} of {maxTreeCount}\nBuildings: {buildingCount} of {maxBuildingCount}"; // display message ExceptionPanel panel = UIView.library.ShowModal<ExceptionPanel>("ExceptionPanel"); panel.SetMessage("Show Limits", message, false); } else { // not both keys pressed: Reset processed state _processed = false; } } } } Now compile the mod (F6). If there are any compilation errors, use the error list in VS2017 to locate and fix the error (View > Error List) When the compilation was successful, run the game. Enable the mod in content manager (if your mod does not show up, you probably forgot to setup the post build script). Now create or load a city. Press Ctrl + I: Happy Coding! Download Source Next Part:
  10. Version 1.0.0


    Source Code of the Show Limits Mod Tutorial for Cities: Skylines. Created with Visual Studio 2017
  11. Version 1.0.0


    Source Code of the Road Tree Replacer Mod Tutorial for Cities: Skylines. Created with Visual Studio 2017
  12. Urbanism: Traffic Oriented Development

    Hello, welcome to another entry from my CJ. Today I'm going to explain a little trick for adding some realism that I use in Bellingham, the Traffic Oriented Development, the SimCity 4 cousin of the Transit Oriented Development - Why the names are different? Because the concept is a little different. Mixed zone is the appropriate, not the mandatory to apply in this system; My system allow use of big avenues if they're the commanding way of the neighborhood, TOD means sharp roads; For TOD, Public Transport Traffic is good and Road Traffic is bad; In my system, traffic is just traffic and the hibrid use is oriented, and you can have things like this: A walkable historic city center that can be accessed by avenues and transit stations. There's two stations in this image, can you spot it? Neighborhood walking to a Traffic Oriented Development; The Subway station will complete the process - Why use this type of development? * The scale in SC4 is monumental. So sometimes we will not repair in the pedestrian props, or they will even exist at all. So a Vibrant city can be done by cars and people in the same environment, using car for long distances and walking the short ones. *Flowing: it's a challenge and a compromise. There's flowing for cars passing thru, with the expressway. There's organized flowing for people and the cars of the neighborhood, with aligned viaducts, what permits that the desired flowing pass thru without difficult over and under the expressway. There's flowing with the buildings, the major part of the image keeps the same average size. -Traffic Oriented? Real life example; The Tallest buildings faces the biggest avenues. Where the roads are sharper, the buildings are smaller. Open That image: You will see the same phenomenon! See? There's a backbone. - But what about that Sears Tower and the super high buildings in that block? They have a subway station, so no need for big avenues. -OK, you have my attention, show me how to do this You need to know few things to do this: -Traffic Capacity and Urban Planning Plan ahead and plan first. No, squarish-squaring-square is not a good plan. It lead you to side streets crossing major avenues and transit signals everywhere. This system leads also to traffic jams and transit collapse faster than any rational system. lay down a road system that leads to the follow: side streets>side roads>neighborhood arterial road>city arterial road(or Highway if it's the case)>Highway (optional if there's none) Networks capacities in different levels RHW capacity chart NWM capacity chart This capacity chart and your previous plan will define what type of development you will have in that particular area. Take from example the green corridor in last image. It's two RHW-6S (50000) side to side with an avenue (8000); What give us a notion of what I've been waiting from that develop. But the important part of it is: The Capacity of the corridor is equal to the sum of the capacity of all it's members. 28000 sims capacity corridor Should I stay or should I go? Your road will attend traffic that is going or they will stay in the way? This will define if there will be full controlled access (highways and expressways), semi-controlled access (Bigger avenues with few intersections and interchanges with other big avenues or highways) or no controlled access (roads, minor avenues and side streets). If they will attend both, you'll need bigger avenues, to attend both traffics (I Like OWR-4 Corridors in that cases) - Zoning and development You'll need CAM for... WAIT, WAIT! I DON'T WANT GIGANTIC SKYSCRAPERS IN MY REGION, THAT'S A NO, NO! C'mon man, we're in 2017, as @A Nonny Moose said, Read the Famous Manual. CAM is not a mod-pack to add buildings to the game. If you need more information about Colossus Add-on Mod, read the text on @Tarkus blog but the important part for us in that text is: "The centerpiece of the mod is that it adds new growth stages for each type of zone. The notion of a growth stage is roughly equivalent to the concept of density. A Stage 2 residential will have more residents in it than a Stage 1 residential. A Stage 4 commercial office will have fewer jobs than a Stage 5. The default game settings include 8 growth stages for Residential and Commercial, and 3 growth stages for Industrial. The CAM ups the number of Residential and Commercial growth stages to 15, and the number of Industrial growth stages to 10, excluding Agriculture, which has 7 growth stages with the CAM. The reason for these new stages is to better distribute population and job density. The default settings end up introducing a pretty wide variance at the upper stages (especially Stages 7 and 8). The CAM smooths out this variance." In a text that the central part is the relations between densities and road capacities, CAM has to be your first thought. and we will explore that variance smooth pretty much. Can you see? all buildings has the same average size. this is a CO$$8 that I'm developing and will appear in the next entries of the CJ. It still has no name, and there will be some parks in it. Diagonal buildings are wanted. But I still miss some transit stations in that avenue, maybe a BRT Project would help Real spoiler: The use of the same stage growth buildings creates a sensation of flow and the different types of size creates the sensation of filling. The avenue don't seem clogged too, because there's a relation between the OWRs and the buildings. see the buildings making shadows in the other side of the OWRs. This is what I've been waiting for. I expect to have 40000 sims here per peak. the ones that I expect 60% will stay in that commercial center. the rest will follow to the intersection and to the city center. The zoning also lead us the possibility of creating that flow, using the same type and average size of zoning. (Even that Maxis Bigger school fits nicely in the zoning, wow) This will create a ton of buildings related to each other, but nothing impede you that if you don't like that building (or doesn't fit in the style of the other buildings), click B in your keyboard and bulldoze it. That's It for now. I hope that you enjoyed it.
  13. So Entry II. Since Wednesday I've made considerable progress on I-10 heading south, pretty much reaching the outer expanse of the city. Further to this, I began small amounts of zoning near the Mini'stack interchange which I developed slightly but have yet to complete. Anyway, pictures! I'll start with the zoning development I have begun just North-West of the airport, between I-10 and 16th Street. The image at the top is just some generic industry just off the I-10, sandwiched between E Washington St and E Jefferson St. Looking closer now at the map, each one is in fact one-way so I will likely revisit this later and alter accordingly. The next image is of the residential area that has developed to the north of the industry. I have tried to 'overlap' the industry and residential as much as possible, so many of the areas to the south are a mixture of residential streets and industrial roads, as seen in the second image. Just on the north side of E Washington St I managed to achieve a nice mix of commercial and residential, along with a short woodland path as a divider. Finally, an overview of the current development on that tile, cornered in by I-10 and the Mini-stack. The overview really shows the extent of the industry mixing with the residential. Moving south, I have now fully developed the UPS Car Park to the south west of Runway 08. It really fills in the gap between 24th St and I-10. That covers the extent of construction throughout the city so far, so now on to the progress I made on I-10 heading south out of the city. The progress covers three tiles, so the images below will simply be highlights of the better interchanges. This first interchange is the junction between I-10 and Route 143 (seen at the top) and the junction of I-10 with W Broadway Rd. There are some slight modifications due to proportions but overall I think it turned out quite nicely. Finally, here is the interchanges between I-10 and Route 60, which I am very pleased with. Although it is not an exact replica, it comes pretty close to it and it is possibly the most satisfying junction I have built with the RHW. The junction with S Priest Dr can also be seen at the bottom of the image. As per usual I will wrap up this entry with an overview of the progress made so far. We have currently established 5 tiles, covering the area between the Mini-stack interchange and going right down to Chandler Blvd and the area where the city ends. As always, thanks for reading. Be sure to comment any opinions or criticisms you may have, I'll try my best to address them.
  14. Introduction

    I'm starting a new city: Hartford. I'm using a map of Boston, so there'll be some similarities, though unlike my previous city journal Alexandria (which you can see here) there's no location or history as it relates to the whole country. I'll also be using some of the same names as Alexandria, because they're good names, Brent. In this city journal, I'll be focusing on making Hartford a realistic city, rather than the best city possible, meaning sometimes I'll make a decision I wouldn't normally do. Currently Hartford's at about 28,000 people. Here's some pictures of the initial construction of the city.
  15. I recently installed the Less Abandonment modd which raises the higher wealth development requirements so that they are not at the same level as what causes sims to abandon them. So far I it seems to work, but it still does not solve the problem of redevelopment. In the game sometimes a medium or high wealth building will depreciate and become occupied by lower wealth level jobs or sims. Also sometimes you have abandonment issues due to transport or water issues, and if you don't realize it and save the game, then you have to hopefully find those buildings yourself and demolish them. I believe both of these ideas brings some realism to the game. What is unrealistic is that the game does not ever redevelop the depreciated buildings to a lower wealth building type, or reoccupy or redevelop the abandoned buildings for transport or water issues if the issues have been resolved and there is a demand for that building type. Does anyone know of a modd that provides a mechanism for the game to redevelop to lower wealth buildings, or reoccupy or redevelop abandoned buildings? If such a modd does not exist, then would it be possible for someone to write a modd that would give a reoccupied at a lower wealth level or abandoned building a 5% chance each month to redevelop to a lower wealth occupancy or for abandoned buildings to reoccupy provided desirability requirements are met and there is a demand for that building type? I believe such a modd would bring greater realism to the game.
  16. SparkleCity Dev Entries

    Well it's here! With only 55 days to go, i thought i would bring a development update. Below is dev update 1. Beta 1 If you want to call it that. All dev updates will go here, and the final release will be in the actual City Journal Menu. (Between STEX and Gallery) Without further ado, SparkleCity Beta 1 In fall of 1995, the population of Prowersville stood at only 32,000. This was already quick growth, since the city was founded as a US territory in 1994. By the kingdom's independence in October 2006, the population reached over 1.5 Million. Eventually, ten years after that, the population stands at 2.4 Million. (2015 Census: 2,476,375) Below are three pics of the major centers of the city. Each dev update will contain three pics. Part of Downtown Prowersville, A lot of companies have built large complexes consisting of the same building. Several buildings are even copy-pasted all over the place. A large high school: Station Square High School located in downtown. It places the highest on the Sparkle Kingdom College Placement Exams (SKCPE) with a 2270/2500 (91%) Average Score on the exams. Most of the highest placing students go to the University of Prowersville. The Miles Prower Mall, located in the Jasmine Falls township. Since it is 10PM, the mall is closed to anyone under the age of 21. (21 is the legal adult age in the SK) The mall contains a massive 374 stores, and is over 20 million square feet. Any minors caught in the mall after 8:30 PM can be sentenced to up to 2 years in the Juvenile detention center. (With hard labor)
  17. Holt: One Year Later

    Welcome to Holt District! Holt District is my brand-new CJ and is also my second one. In this journal we will follow the Region of Holt District through developments - both good and bad - and the pains on motorists as roads are widened and residents + businesses as utilities are tinkered with the allow for new developments. We will see developments go from the planning phases, through construction all the way to the end process. Likewise, those of you who know of Windemere & Taschereau also know I like road construction. That, too will be part of this CJ as when an area grows, so to do the demands on its road/transit network. Holt District will vary from Windemere & Taschereau in that instead of me adding "new" cities throughout the course of the CJ, the cities I start with are it. Any new cities that come up will be result of new developments, and the bureaucratic mess that goes with it. As mentioned, we will see developments go from a plan to finished product. While this is not true for all developments - that would get boring pretty quick we will see some major developments through the entire process, and on a variety of styles. (Suburban sprawl, urban skyscrapers, business parks, etc.) Holt District has been in development for several months, since about later March/early April. It has been a long road to this point, and those who have been following my Innocent Posts will (hopefully) be excited to be here, just as I am. Now, before I begin today's update (Yay update 1!) I will go into a bit about the CJ website, map and twitter feed. For information about the region of Holt District itself, check out the CJ website! Additional Media: Additional media will play a very large roll in Holt District. Holt District (the CJ) has a website (holtdistrict.weebly.com - link at the bottom of this post) which has some information about the region and general news that you won't generally get in an update. Sometimes a special post will be made to highlight something on the website, with feedback and discussion more than welcome here in the Holt District topic. Generally development proposals will be posted on the site, with discussion about them taking place here. The process of watching it go from plan to finished product will also take place here. It is only the "application", if you will, that is posted on the website. Also, Holt District will have a streetmap. To be located at maps.holtdistrict.host22.com, it will be a streetmap (i.e. the elevated rail lines won't be on it.) This may change in the future as my abilities in this area improve. When this feature launches (it is currently only a welcome page) there will also be a regional transportation view available for more detail in other areas of transit - including EL-RAIL. Lastly, Holt District Has twitter! Twitter will be used to let you know when updates will be coming out, random teasers and general "What I'm working on in the region today is..." So with that... let's get onto the update. Again, welcome - to Holt District! INTRODUCTION + RETAIL 'DILEMMA' 1.1 \ Shorecoast Shopping Centre is at the cross-roads of 2 major arterial roads in Manatee. Having grown over time with 2 additions and several renovations, the mall is now home to Hecht's, Sears, JCPenney and a large multiplex movie theatre. The mall is a major draw for residents of not only Manatee, but the entire region as it is the only enclosed shopping centre in the region. 1.2 \ Over time, the owner of the mall, Centurion Properties, Inc., developed portions of the massive parking lot into large office buildings. Several office building and even a department store exist on what was once pavement. When confronted with these proposals (over time) the city's council easily approved the developments, saying "It helps break up the pavement monster which is the Shorecoast parking lot, all while brining jobs to the area." Indeed, this building alone employs over 2 000 people. 1.3 \ Although the mall has a diverse clientele, and wise base where it draws customers from - its biggest return visitors and spenders are those who live right around the mall. This is one of the older sections of Manatee. 1.4 \ The food court benefits from a high school which is about a 10 minute walk away. The food court suring any of the lunches is packed - if you are a non-high school student you need to pick and choose when you go for lunch or a snack. 1.5 \ However, not all retail is booming. This Kmart store, which has been in this location for 35 years - and expanded several times - has been loosing business to the mall since it has opened. The mid-range department stores in the mall have stolen business away from Kmart, while an out-of-town Walmart has put the nail in the coffin. Rumours of its closing have been swirling for years, though no official confirmation from the company. 1.6 \ The only saving grace for this location is it is across the street from this minor league stadium, home to various local sports teams and the soccer and foorball teams from the highschool just down the street. Often, people will purchase snacks from Kmart, and on cool nights sales of blankets soar. 1.7 \ Another source of customers is the casino resort, Holt Casino & Resort. It is inevitable that travellers forget something, and with Kmart in walking distance several tourists enter the store each week. While this is not a steady source of income for the store, it is better than nothing. 1.8 \ However, Kmart's demise may now be more real than ever. Rumours are swirling that Walmart is in the process of purchasing the property from the land owner. The fact Kmart's lease is up in 11 months is doing nothing to help squash the rumour. Walmart previously tried to enter Manatee, 10 years ago, but their plan was rejected. Since this is already a retail site, chances any changes they make to the building would be approved. When their plan was rejected 10 years ago, they located 2 highway exits to the south in another town. 1.9 \ It is becoming increasingly likely that the residents of the luscious suburbs in and around Kmart could soon be faced with the sound of construction vehicles for months. That is all for today, the first update of Holt District! I hope for those who have been following its development it is everything you have been looking forward to. I am super excited about the prospects of this new CJ, and I hope you will stay for the journey as things develop! Next Update: We will be looking at some more of suburban Manatee and may just venture into its downtown core...
  18. Cities / Alternative History

    Really interesting article - some really excellent pictures too, the City of London that could have been, if various designs had been approved. Almost all of them are better than the 'Walkie Talkie' http://www.theguardian.com/artanddesign/gallery/2015/nov/03/london-might-have-been-designs-alternative-architecture-pictures
  19. A Growing Capital

    Welcome back. In this update we will be taking a closer look at how Bandar Sabah is growing, and what you can expect to see built in the next little while. Also, I have re-done the history on the first page take a look HERE Bandar Sabah has experienced rapid growth in the last few years. With new government policies bringing in money and jobs, that growth is only expected to increase. You saw a few of the projects currently in the works in the last update, but we will look at a few more today. Here is a GIF to demonstrate the growth the capital has had. I am not really sure where we will go in the next update. Maybe a new city? IDK- we shall see REPLIES 111222333444: Thanks, I wish I could go top the Philippines escilnavia: Thank you, yes it is custom there is a tutorial here on how to do it. http://sc4devotion.com/forums/index.php?topic=2443.0 Evillions: Thanks very much, my friend panthersimcity4: Thanks a bunch panther. IL: Thank you for the nice comment. If you mean the house sets, I made those, but a release could happens soon. FaisalZulkarnaen: wow, thanks, I have taken inspiration from malaysia- good to know it's paying off spursrule14: Whoot! THanks for that, and thanks to those who supported me
  20. I have been looking over posts about marking things historical. Am I correct that this will freeze development of a lot and that is its only function?
  21. I've made some (painfully slow) progress on implementing the core simulation code for my Since I'm finally giving the economic simulation some concrete attention, I am curious about what the community might think of a particular feature that is currently part of that core. The general feature in mind is that the cost, speed, and quality of various player-initiated activities can be affected by the current state of the economic simulation. (Such activities include stuff like road construction or the routine operation of city services.) For example, cities with a strong steel industry might allow the player to build bridges more cheaply, rather than having to import more expensive steel. But cities with a weak construction industry might experience slower construction times and higher construction costs due to the need to import construction labor from out of town. Similarly, the prevalence of a well educated work force and a large high-tech equipment manufacturing sector could make it cheaper to operate a hospital, but lack of a well educated work force could cause schools to be more expensive to run or have less educational effect due to not being able to easily hire good teachers. In addition to the player being affected by the economic simulation, the economy could conversely be affected by player-initiated city activities. If the player goes through a few years of building a lot of stuff, the local construction industry might boom. But if the player quits building and zoning for a while, then the construction industry might experience a contraction if the city were a major source of construction work. In all these cases, I envision the behavior arising simply because the player is essentially just another participant in the economic simulation, not because the specific behaviors are pre-designed and hard-coded into the game. I realize that getting the desired kinds of emergent behavior out of a simulation can be tricky, but for now I'm hopeful on that front. On the other hand, if I can achieve such emergent behavior, I'm still not sure about what impact such behavior would have on the sense of fun that players would experience. Here are some hopes and worries: Speculated Pros The city will feel move "alive" and reactive, and the player will have more "interesting decisions" available. The player will feel like their decisions have more meaning to the evolution of the city. The player will feel like their decisions are influenced more strongly and obviously by the current circumstances of the city. It sets the stage for an interesting variety of designed scenarios or challenges, rather than faking such scenarios using superficial or blunt mechanics. Speculated Cons Changing prices might be more frustrating than fun. Relevant economic data might be hard for the player to quickly find, evaluate, understand, and respond to. The quantity of relevant data and the potentially complex consequences of player decisions might inhibit more casual play. (I don't want to "dumb down" gameplay, but I don't want the gameplay to turn into a tedious desk job either! ) I have some ideas to mitigate con #1, but even with those ideas, prices for the player will still change, just not very rapidly. For con #2, I imagine this will just require the proper effort to design high quality charts and maps. Once I have a simulation producing lots of this relevant data, I'll be able to more easily evaluate what it takes to understand it, and solicit feedback and insight from others about how best to present it visually. For con #3, the balance that I'll be attempting to achieve is for the player to be capable of mostly ignoring the details and still being able to build a reasonable city without dooming it all to failure. But for the players that want to dig deeper, I want the economic simulation to provide that meaningful depth. And I want interesting tidbits of those details to be poking up near the surface, easy to find if you're looking for them. Ultimately, I envision the economic simulation as a major source of story telling elements that the players will use to build narratives for their city. Do you share any of these hopes or worries? Have any additional hopes, worries, or general ideas to add to the mix?
  22. Who says you have to be in a big city? Low cost of living, low cost of doing business, magnificent surroundings.
  23. Introduction: Hi Simtropolis! I'm Andy Gainey, founder of the newly formed independent game dev company Experilous. For my first major project, I'm seriously considering working on a city builder. I have been contemplating city builder designs for a long time, have accumulated many ideas (as we all have, no doubt ), and have recently been putting together a pretty strong vision for many aspects of this project. Nonetheless, there are plenty of major design decisions that I haven't made yet, and so I seek the aid of the city builder community during these early design stages. In the upcoming weeks, I'll be posting questions and topics of discussion on issues that I know are important but that I have not yet made any strong decisions about. I'm curious about the features and styles of gameplay that are important to each of you, and to what degree. In addition, there are numerous technical and design challenges a city builder project is likely to face, and I'm eager to explore the vast landscape of potential solutions to those problems with you. I'll keep a record of those topics in this post. As a preview of where I'm likely to go first: Discussions: Detailed agent behavior versus statistical approximations (not yet posted) Plenty more... In addition to the above discussions, we can use this thread for talking about what topics you think are most worthy of discussion, especially during the initial stages of design and development. I am also open to any general questions you might have about the project and my plans for it. I know I don't have a lot to offer yet in the way of functioning systems or screenshots, but hope to begin working on prototypes soon. What systems would you be most interested in seeing prototyped first? Current Vision: Obviously, there are a lot of big decisions that I have not yet made. So what does my vision consist of? Here are a few of the important attributes I seek to achieve: Modern Large Cities: Every time I run numbers to estimate the technical feasibility of a design based on CPU, GPU, memory, and bandwidth concerns, I'm working with upper limit numbers such as 10 million residents, 1 active vehicles, or 400 square miles (~1000 square kilometers). I've had to reject some ideas because they simply wouldn't get even close to functioning given those numbers. I want large cities to be an option for players, and I don't think I'm alone in this desire. Super-Efficient Engine: The core simulation engine needs to be optimized for modern computers. That means things like 64-bit support, broad parallelization to fully take advantage of multicore CPUs and maybe even GPGPUs, and cache-friendly processing to be able to churn through large amounts of data. If I want to provide the large numbers while minimizing the amount of statistical approximations I depend upon, an efficient engine design will be absolutely critical. Thorough Mod Support: Modding communities can do great things, even when it isn't made particularly easy. I want to go out of my way to encourage modding. In the ideal case, I'd like to provide in-game editors for certain types of mods (such as by making a building architect tool an integrated component of ordinary gameplay). A system for handling dependencies, versioning, and other technical mod issues has also been on my mind for a while. High Degrees of Customization: Sandbox games are ultimately about the player's vision, and I want to enable as much city customization as possible, both functional (such as highway interchanges) and aesthetic (such as park layouts or street surfaces). Feel free to follow my activites on my website experilous.com, or through my Twitter handle @AndyGainey. I look forward to interacting with this community during my pursuit of building a worthy game!
  24. As described my I'm in the early stages of designing a city builder and seeking community input on a variety of topics. The first topic I want to tackle: Multiplayer. Some people have no interest in multiplayer, and I similarly feel that a city builder should be single player at its core. But there's clearly a large demand to share in-game experiences with one's friends even within the city builder genre, and I'd love to develop a game that is designed to optionally accommodate that shared experience as fully as possible. Or at least as fully as is relevant, which raises the question: How much multiplayer are people interested in? The "MMO route" taken by Cities XL and SimCity 2013 isolate each city, and thus each player, quite a bit. The system is easier to implement on top of an otherwise single player experience, but does it do a good job of capturing the social aspect that people seek? How much more satisfying would it be if multiple players could be actively working within a single city at once? Greatly? Marginally? Would it matter if, for technical reasons, only one player at a time could be modifying a specific area in the city? Or more severely, only one player at a time modifying anything in the whole city at all? Would it actually be a welcome feature to be able to limit certain players to certain areas or activities, especially if hosting a public server with strangers joining cities? In short, what, if anything, excites you about the possibility of multiplayer? What type of experience would you most want to share with your friends? Is a save file and/or screenshots enough (e.g., city journals)? Or having multiple cities interact with a shared regional economy? Or do you want to collaboratively build a city together? What activities, what details, would be the most engaging in a multiplayer city builder? If you want to let your imagination run free for a moment, by all means, be my guest; I'm fascinated with the untold possibilities of where everyone's imaginations might end up.
  25. Continuing on with I'd like to discuss traffic simulation this time. I've spent the past couple weeks working on a prototype simulator to get a feel for what is technically achievable. (I'll have some preliminary results posted later this week; you can read about of my few early bugs on my blog.) But more important than technical feasibility would be practical value: How much (and what kind of) detail would actually maximize entertainment, in the face of certain tradeoffs? I would classify the tradeoffs into three broad categories: Performance, Interface, and Mechanics. On the performance side, naturally the more detailed a simulation gets, the slower it will run when attempting to run as fast as possible. For interface, it's sort of a tradeoff between ease-of-use and and creative power. And for mechanics, it's largely a matter of feedback from the game to the player: Can a player understand what's happening in the simulation, why it is working well or poorly, and what one could try in order to improve traffic problems? Running at max speed, how long would you be willing to wait for the simulation to process one in-game year? (What counts as an in-game year can be fuzzy, but you can loosely base it on other city builders you've played.) Would you be more forgiving if it were a large city? For example, what if a city of 100,000 people could simulate a year in 1 minute, but a city of 10 million, while playable, would take nearly 2 hours? Or would you prefer the SimCity 4 style where you could focus on just one segment of the city at a time, and thus get more predictable performance regardless of how large the overall city were? The tradeoff would be that the simulation for most areas of the city would be frozen or vastly simplified during that time. Regarding interface, I'm not sure I have any specific questions at this early stage. The ideal is obviously to achieve both ease-of-use and creative power simultaneously. I am optimistic that with effort, and with a lot of feedback and ideas from players, the ideal can be accomplished. But for now I think that just having an idea of priorities would be helpful to me. Judging from past discussions and player activity, it seems clear that a capable interface for designing highway interchanges, rail yards, bus/subway routes, and similar complex structures would be very welcome. What type of transit-related structures would you most like to see have a well designed interface? Finally, I have a concern that if the game mechanics contain too much complexity, even if the computer is able to process all the details, and even if the interface allows easy creation of complex transit networks, the result will be an incomprehensible mess of data, and an overwhelming array of options available to the player. But I also suspect that different types of players will judge this point of excess quite differently: Aesthetic builders would love to have a myriad of options. Functional tinkerers on the other hand would probably do better with just enough options to provide proper control over the behavior of the simulation. So from this suggested distinction, which transit network features would you like to have mostly for aesthetic purposes, and which are desired primarily for behavioral control? Which ones are important for both reasons? (For example, I suspect highway interchanges would be.) Other features to consider might include rail yards, lane count, intersection styles, road surface styles, specialized lane use (bus lanes, no trucks, et cetera), pedestrian routes, and I'm sure many more.

volume5_md.pngPlease help us reach our September Goal!

Your contribution helps keep Simtropolis up and running!

Please consider a donation today.

We need to continue to raise enough money each month to pay for expenses which includes hardware, bandwidth, software licenses, support licenses and other necessary 3rd party costs.

By way of a "Thank You" gift, we'd like to send you our STEX Collector's DVD. It's some of the best buildings, lots, maps and mods collected for you over the years. Check out the STEX Collections for more info.

Each donation goes to help us keep the site running free.

Enjoy the site!

OK - See STEX Collections