Devlog #44 - City Enum - scriptable Object , ***Game System Update*** - City Growth fixed , InverseLerp for productUnlock ( changes from previous logs)

******City Enum, introduction to fixed system of city names and values (tiers) , which caps the unlocking products to the difference between the base population and next tier/enum for other product unlocks*****


Lets start from the begining and why this matters so much. 

Idea 1 :  

The city has proportional growth based on the base population, tier 1 to tier 2 would mean that the city grows by 100%. so in essence to reach tier 2 it has to double in population. if(cityPop >= baseCityPop *2) 

The productUnlock System was based upon the percentage of difference between the currentPopulation / basePopulation. 

For example: first 2 products unlock at the ratio 1.0 , means that when the game starts the pop/basePop = 1, so 2 products opet, but other 2 products unlock at 1.4 and 1.7 ratio of the currentPop. in essence:

float popRatio = currentPop / basePop; 

and then we say, product a - unlocks at 1.4. ratio, and product b -  unlocks at 1.7 ratio.

Problems with this long term: 

-First, the Tier2 is not universal, its reather proportional to the original base population, which means, a city that starts at 3k, 6k is alreay tier2, while, the city that starts with 6k needs 12k to be tier 2.. so its not balanced and makes not much sense in reality. 

-Second, the products unlocks then would have to always increment, 2.4, 2.7, then 3.4.3.7 or if there is more products its always the same principle. One mistake, grave mistake.. hahah


_______________________________________________________________________


Idea 2 :  

We introduce Enum for city, but this time we dont use Database, but rather just a condition for City size.
For example:


So now, instead of using proportions we are using Enum as set values, so we say, 

//pseudo
static void UpdateCityTier
{
    city.cityTier = city.Population switch 
    
  < 5000 => cityTier.Village 
   < 10000  = > cityTier.Town

 etc
}

So , we run this each turn, and it updates, so if the city grows over 5000, becomes Town, if not stays Village. Which worked! But.. of course it wouldn't be that easy. 

Problem? - We cant use percentage for the purpose of unlocking more products on the way to the tier 2. - (Welcome to one of the most frustrating stuff that i have had in this game, because of mixed enums) , Anyhow:) 


So I had somehow to bring back the values for different cityTiers(5000,10000), but they couldnt be coded within the switch. -So either give up idea on unlocking more products or calculate it from the current pop and 0, and artificially keep the ratio somehow,but again, same issue, the city with 3k is not the same as with 6k.. and now the CityTiers are set.


____________________________________________________________________________________


Idea 3: solution .................. 👀💬

Introduce another array, with actualy population limits for each tier so it can be used for calculating popRatio. In essence we take currentTier and nextTier, and calculate the difference inbetween with inverseLerp, so we get the ratio....

For example, we put it paralel we say

CityTier Enum { village, town, city...    }
Threshold int[] { 5000,10000,150000...}

(that was the most frustration ever) anyhow,


Now we can combine both and use the values instead of switch to actually use the values from the array threshold. 

so we say,

if(city.Pop < threshold(int)city.CityTier  // here we take the value from the array but choose the same value as the cityTier , value i mean int) ;


This way, we can get the same result, and but still use the values for the later popRatio, and also we have the edge case if thepopulation is bigger then the array 5(6) , it will never pass through the for(int i) . Goes through all 6 and its all wrong, 

Thats why we added and said before for , calculatedTierIndex = 5; 5 is actually cityTier that is actually 6, because enums start at 0,1,2,3,4,5.


So then, we also changed the way ratio is calculated, now we have to calculate the currentTier (for example 5000 on 0 place) and also nextTier is 10000, place

we define currentTier = (int)city.cityTier 

then nextTier = (int)cityTier +1 


so we say popRatio = InverseLerp(threshold[currentTier],threshold[nextTier],city.Pop) -so in essence, we now calculate the ratio inbetween the tier 1 and tier2 (town's windonw) to get when the 2 second products will be activated. 

Makes sense? 

This way we say calculate between 5000 and 10000  ratio with population that is for example 7500 at the moment, so  Mathf.InverseLerp(5000,10000,7500) = 0.5; 

so its working! now we just change for each product instead of 1.4, 1.7 to 0.4 and 0.7. and set the minimum tier is tier 2. (1 by enum value)


What this also changed, is that each new product that will be unlocked on tier3 for example, will actually just have set 0.4 or if there are 3 we can say, first 0.3, second 0.6, third 0.9... 

So with this we solved the CityTier, we solved the ratio for each cityTier separately to again show the percentage until its unlocked which was very important for visual reference. And we set up the system much better and more predictable and logical then it was with using basePopulation and proportion for calculating city tier's. Now the structure is much more stable and logical. Each city has the same chance. 



Addapting it to our existing structure, and improving the code .  -update


So in order to improve and later be able to better adjust or change elements without searching through the code and changing values, I added the same as i had for other systems as well. Introduced scriptable object, that contains 6 values, which is 6 enums, but also has values for threshold. So we can just call from the database, compare and get the result, and not rely upon using spaghetti code in a way. Same logic all the same only we dont use int[] array but rather scriptable object combined with enum. For example:

[System.Serializable]
public class CityTierData
{
public string listLabel;

public CityTier cityTier;

// public CityTier cityType;

public int threshold;



}

So we can give the cityTier and as well set the threshold value.

So instead of doing for,  we do like this:

foreach (CityTier tier in Enum.GetValues(typeof(CityTier)))
{

int threshold = WorldManager.Instance.cityTierDatabase.GetThreshold(tier);


and then we simply compare city.pop < threshold 


   calculatedTierIndex = (int)tier;

and GetThreshold(tier) is actually a public int method, that returns the value of threshold.

Simply said, foreach CityTierData data in allCityTiers
                                if(data.cityTier ==tier ){return tier.threshold

Hope that makes sense!!

It can probably be better,but for now this is not as easy for me hah.

Thank you!!!














Comments

Popular posts from this blog

Devlog #47 - TaxSystem/FinanceSystem ,Update-FIx -LoanFixes-- TruckSystem Update - Upgrade/BuyNEwTruck - Costs Prices introduced / OfficeSystem CreateNewOffice, upgrade office - other Fixes

Devlog #46 - HubSystem - CreatNewHub added, HubBuild Ui + INdustrySystem Update - -INdustryTierData to be combined with the IndustryData and IndustryState struct -

Devlog #49-50 - Asset System-NEW system, *Game Design* -construction costs update - LoanSystem- fix-redesign-upgrade,Bug fixes-storeSystem,AutoAdvance Day, Market system, Truck System cost redesign, refactored, Ui bug fixes