diff --git a/C7/UIElements/CityScreen/CityScreen.cs b/C7/UIElements/CityScreen/CityScreen.cs index 21b9edcb..3073e123 100644 --- a/C7/UIElements/CityScreen/CityScreen.cs +++ b/C7/UIElements/CityScreen/CityScreen.cs @@ -20,6 +20,15 @@ public partial class CityScreen : CenterContainer { private Label culturePerTurn; private Label totalCulture; + Theme yieldDetailsFontTheme = new(); + FontFile yieldDetailsFont = new(); + + private Label foodDetails; + private Label productionDetails; + private Label commerceTaxesDetails; + private Label commerceScienceDetails; + private Label commerceHappinessDetails; + // Called when the node enters the scene tree for the first time. public override void _Ready() { background = new() { @@ -42,6 +51,53 @@ public override void _Ready() { OffsetTop = 4 }); + + // Load the font we'll use for the details. + // + // We skip the cache so that we can change the size without affecting other + // code using the same font. + yieldDetailsFont = ResourceLoader.Load("res://Fonts/NotoSans-Regular.ttf", null, ResourceLoader.CacheMode.Ignore); + yieldDetailsFont.FixedSize = 20; + + yieldDetailsFontTheme.DefaultFont = yieldDetailsFont; + yieldDetailsFontTheme.SetColor("font_color", "Label", Colors.Black); + yieldDetailsFontTheme.SetFontSize("font_size", "Label", 20); + + foodDetails = new Label() { + OffsetLeft = 290, + OffsetTop = 567, + Theme = yieldDetailsFontTheme, + }; + background.AddChild(foodDetails); + + productionDetails = new Label() { + OffsetLeft = 290, + OffsetTop = 520, + Theme = yieldDetailsFontTheme, + }; + background.AddChild(productionDetails); + + commerceTaxesDetails = new Label() { + OffsetLeft = 290, + OffsetTop = 620, + Theme = yieldDetailsFontTheme, + }; + background.AddChild(commerceTaxesDetails); + + commerceScienceDetails = new Label() { + OffsetLeft = 290, + OffsetTop = 653, + Theme = yieldDetailsFontTheme, + }; + background.AddChild(commerceScienceDetails); + + commerceHappinessDetails = new Label() { + OffsetLeft = 290, + OffsetTop = 685, + Theme = yieldDetailsFontTheme, + }; + background.AddChild(commerceHappinessDetails); + this.Hide(); } @@ -61,6 +117,9 @@ public override void _UnhandledInput(InputEvent @event) { if (tile != null) { HandleReassignment(tile); RenderPopHeads(tileAssignmentLayer.city); + RenderFoodDetails(tileAssignmentLayer.city); + RenderCommerceDetails(tileAssignmentLayer.city); + RenderProductionDetails(tileAssignmentLayer.city); } } } @@ -160,6 +219,24 @@ private void OnShowCityScreen(ParameterWrapper city) { tileAssignmentLayer.city = city.Value; RenderPopHeads(city.Value); RenderCulture(city.Value); + RenderFoodDetails(city.Value); + RenderCommerceDetails(city.Value); + RenderProductionDetails(city.Value); + } + + private void RenderFoodDetails(City city) { + foodDetails.Text = $"{city.CurrentFoodYield()} food/turn, {city.FoodGrowthPerTurn()} surplus. {city.foodStored} stored. Growth in {city.TurnsUntilGrowth()} turns."; + } + + private void RenderCommerceDetails(City city) { + CommerceBreakdown breakdown = city.CurrentCommerceYield(); + commerceTaxesDetails.Text = $"{breakdown.taxes} gold/turn to taxes (0 corrupt)"; + commerceScienceDetails.Text = $"{breakdown.beakers} gold/turn to science (0 corrupt)"; + commerceHappinessDetails.Text = $"{breakdown.happiness} gold/turn to happiness (0 corrupt)"; + } + + private void RenderProductionDetails(City city) { + productionDetails.Text = $"{city.CurrentProductionYield()} shields/turn (0 corrupt). {city.shieldsStored} of {city.itemBeingProduced.shieldCost} stored. {city.TurnsUntilProductionFinished()} turns left."; } private void RenderCulture(City city) { diff --git a/C7Engine/EntryPoints/TurnHandling.cs b/C7Engine/EntryPoints/TurnHandling.cs index b9dc4fa0..7f61df6c 100644 --- a/C7Engine/EntryPoints/TurnHandling.cs +++ b/C7Engine/EntryPoints/TurnHandling.cs @@ -185,8 +185,8 @@ private static void HandleCityResults(GameData gameData) { city.SetItemBeingProduced(CityProductionAI.GetNextItemToBeProduced(city, producedItem)); } - city.owner.gold += (int)Math.Floor(city.CurrentCommerceYield() * city.owner.taxRate / 10.0); - city.owner.beakers += (int)Math.Floor(city.CurrentCommerceYield() * city.owner.scienceRate / 10.0); + city.owner.gold += city.CurrentCommerceYield().taxes; + city.owner.beakers += city.CurrentCommerceYield().beakers; } } diff --git a/C7GameData/City.cs b/C7GameData/City.cs index e2de1e67..9efef31b 100644 --- a/C7GameData/City.cs +++ b/C7GameData/City.cs @@ -4,6 +4,12 @@ using Serilog; namespace C7GameData { + public struct CommerceBreakdown { + public int taxes; + public int beakers; + public int happiness; + } + public class City { public ID id { get; set; } public Tile location { get; internal set; } @@ -80,7 +86,7 @@ public int TurnsUntilProductionFinished() { } public void ComputeCityGrowth() { - foodStored += CurrentFoodYield() - size * 2; + foodStored += FoodGrowthPerTurn(); if (foodStored >= foodNeededToGrow) { size++; foodStored = 0; @@ -123,17 +129,21 @@ public int CurrentProductionYield() { return yield; } - public int CurrentCommerceYield() { - // TODO: Split this into science, entertainment, etc. - + public CommerceBreakdown CurrentCommerceYield() { int yield = location.commerceYield(owner); foreach (CityResident r in residents) { yield += r.tileWorked.commerceYield(owner); } - return yield; + + CommerceBreakdown result = new CommerceBreakdown(); + result.beakers = (int)Math.Floor(yield * owner.scienceRate / 10.0); + result.happiness = (int)Math.Floor(yield * owner.luxuryRate / 10.0); + result.taxes = yield - result.beakers - result.happiness; + + return result; } - private int FoodGrowthPerTurn() { + public int FoodGrowthPerTurn() { return CurrentFoodYield() - size * 2; } diff --git a/C7GameData/Player.cs b/C7GameData/Player.cs index c462265f..21cee5f6 100644 --- a/C7GameData/Player.cs +++ b/C7GameData/Player.cs @@ -136,7 +136,7 @@ public int EstimateTurnsToResearch(Tech tech) { // TODO: See this this whole equation can be configurable int beakersPerTurn = 0; foreach (City city in cities) { - beakersPerTurn += (int)Math.Floor(city.CurrentCommerceYield() * city.owner.scienceRate / 10.0); + beakersPerTurn += city.CurrentCommerceYield().beakers; } if (beakersPerTurn == 0) {