diff --git a/DensityMod.csproj b/DensityMod.csproj
new file mode 100644
index 0000000..82eab11
--- /dev/null
+++ b/DensityMod.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net6.0
+ DensityMod
+ A mod by Nova to allow you to set the range of density allowed when generating a city
+ 1.4.0
+ true
+ latest
+
+ https://api.nuget.org/v3/index.json;
+ https://nuget.bepinex.dev/v3/index.json;
+ https://nuget.samboy.dev/v3/index.json
+
+ DensityMod
+
+
+
+
+
+
+
+
+
+ C:\Users\Nova\AppData\Roaming\Thunderstore Mod Manager\DataFolder\ShadowsofDoubt\profiles\Default\BepInEx
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Hook.cs b/Hook.cs
new file mode 100644
index 0000000..7466946
--- /dev/null
+++ b/Hook.cs
@@ -0,0 +1,246 @@
+using HarmonyLib;
+using System;
+using Il2CppSystem.Collections.Generic;
+using UnityEngine;
+using Il2CppSystem;
+using UnityEngine.Events;
+using UnityEngine.UI;
+using System.Globalization;
+using System.Text.RegularExpressions;
+
+namespace DensityMod
+{
+ internal class DensityModHook{
+
+ static public GameObject dropdownDenLow;
+ static public GameObject dropdownDenHigh;
+ static public GameObject dropdownValueLow;
+ static public GameObject dropdownValueHigh;
+ static public GameObject densityMenu;
+ static public GameObject menuContainer;
+ static public GameObject GenerateCityMenu;
+ static public GameObject DensityModBtn;
+
+ //This is to convert the Density enum to a clean looking string
+ static public string EnumToString(T e) where T : System.Enum{
+ var s = e.ToString();
+ s = Regex.Replace(s, "(\\B[A-Z])", " $1");
+ s = new CultureInfo("en-US",false).TextInfo.ToTitleCase(s);
+ return s;
+ }
+
+ //Converts string into the Density Enum
+ static public T StringToEnum(string s) where T : System.Enum{
+ s = s.Substring(0,1).ToLower() + s.Substring(1).Replace(" ", ""); //Makes the first letter lowercase(Used in the case of veryHigh, as well as removing the space)
+ return (T)System.Enum.Parse(typeof(T), s);
+ }
+
+ //Update the city generation with the desired density values
+ [HarmonyPatch(typeof(CityConstructor), "Update")]
+ public class Citydata_PopulationMultiplier{
+ public static void Postfix(){
+ CityTile[] cityTile = Resources.FindObjectsOfTypeAll();
+ CityConstructor cityConstructor = Resources.FindObjectsOfTypeAll()[0];
+ //Gets the values from the config file and stores them in a Vector 2, because two ints would be too easy... and messy
+ var DensityRange = new Vector2(
+ (int)System.Enum.Parse(typeof(BuildingPreset.Density), DensityMod.DensityMinConfig.Value),
+ (int)System.Enum.Parse(typeof(BuildingPreset.Density), DensityMod.DensityMaxConfig.Value));
+
+ var ValueRange = new Vector2(
+ (int)System.Enum.Parse(typeof(BuildingPreset.LandValue), DensityMod.LandValueMinConfig.Value),
+ (int)System.Enum.Parse(typeof(BuildingPreset.LandValue), DensityMod.LandValueMaxConfig.Value));
+
+ //Uses the valueRange and clamps the allowed density. This is done by treating the Enum as an int, since the values range from 0 - 3.
+ if (cityConstructor.generateNew){
+ foreach(CityTile tile in cityTile){
+ if (tile.name == "CityTile") return;//This was used, because there seems to be a CityTile manager or something, so I didn't want to edit it(Also caused issues before)
+ var d = (int)tile.density;
+ d = (int)System.Math.Clamp(d,DensityRange.x, DensityRange.y);
+
+ var v = (int)tile.landValue;
+ v = (int)System.Math.Clamp(v,ValueRange.x, ValueRange.y);
+
+ //Density Update
+ tile.density = (BuildingPreset.Density)d;
+ DensityMod.Logger.LogDebug($"{tile.name} density = {tile.density}");
+
+ //Land Value update
+ tile.landValue = (BuildingPreset.LandValue)v;
+ DensityMod.Logger.LogDebug($"{tile.name} landValue = {tile.landValue}");
+ }
+ }
+ }
+ }
+
+ //Simple function to close the Density menu
+ static void CloseDensityMenu(){
+ densityMenu.SetActive(false);
+ GenerateCityMenu.SetActive(true);
+ }
+
+ //Simple function to open the Density menu(duh)
+ static void OpenDensityMenu(){
+ densityMenu.SetActive(true);
+ GenerateCityMenu.SetActive(false);
+ }
+
+ //Creates the menu objects
+ [HarmonyPatch(typeof(MainMenuController), "Start")]
+ public class MainMenuController_Start{
+
+ public static void Postfix(){
+ var inputTemplate = GameObject.Find("MenuCanvas").transform.Find("MainMenu/GenerateCityPanel/GenerateNewCityComponents/SizeDropdown").gameObject;
+ GenerateCityMenu = GameObject.Find("MenuCanvas").transform.Find("MainMenu/GenerateCityPanel/").gameObject;
+
+ //Dropdown list of options.
+ List DensityOptions = new List();
+ DensityOptions.Add("Low");
+ DensityOptions.Add("Medium");
+ DensityOptions.Add("High");
+ DensityOptions.Add("Very High");
+
+ List ValueOptions = new List();
+ ValueOptions.Add("Very Low");
+ ValueOptions.Add("Low");
+ ValueOptions.Add("Medium");
+ ValueOptions.Add("High");
+ ValueOptions.Add("Very High");
+
+ if (GenerateCityMenu != null){
+ //Generate a density menu, based on the Generate City menu already present
+ densityMenu = GameObject.Instantiate(GenerateCityMenu.gameObject);
+ densityMenu.name = "Density Menu";
+ densityMenu.transform.parent = GenerateCityMenu.transform.parent;
+ densityMenu.transform.localPosition = new Vector3(0, -42, 0);//Set the localPosition to this, because when cloned it starts in an odd position.
+
+ //Finds the gameobject that holds the dropdowns
+ menuContainer = densityMenu.transform.FindChild("GenerateNewCityComponents").gameObject;
+ menuContainer.name = "DensitySettingsComponents";
+
+ //Removes all elements currently present
+ //Note: it was done in this way, because a while and foreach loop would fail. It seems when this is created, the data is static,
+ // so when you remove Child(0), Child(1) does not become the new Child(0) as you would expect in Unity.
+ for(int i = 0; i < menuContainer.transform.GetChildCount(); i++){
+ GameObject.Destroy(menuContainer.transform.GetChild(i).gameObject);
+ }
+
+ //Removes one of the buttons from the menu, then changes the remaining one to be the done button
+ GameObject.Destroy(densityMenu.transform.FindChild("ButtonArea").GetChild(0).gameObject);
+ var doneButton = densityMenu.transform.FindChild("ButtonArea").GetChild(1).gameObject;
+ doneButton.transform.parent = densityMenu.transform.FindChild("ButtonArea").transform;
+ doneButton.GetComponent