Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions C7/Text/c7-static-map-save-standalone.json
Original file line number Diff line number Diff line change
Expand Up @@ -70924,7 +70924,10 @@
"contentFacesInCity": 0,
"combatDefenseBonus": 0,
"maintenanceCost": 0,
"iconRowIndex": 59
"iconRowIndex": 59,
"flags": [
"treasuryEarnsInterest"
]
},
{
"name": "Apollo Program",
Expand Down Expand Up @@ -73494,7 +73497,9 @@
"scoutUnitType": "Scout",
"maxRankOfWorkableTiles": 2,
"maxRankOfBarbarianCampTiles": 2,
"defaultDealDuration": 20
"defaultDealDuration": 20,
"treasuryInterestRate": 0.05,
"maxInterest": 50
},
"techs": [
{
Expand Down
9 changes: 7 additions & 2 deletions C7/Text/c7-static-map-save.json
Original file line number Diff line number Diff line change
Expand Up @@ -73497,7 +73497,10 @@
"contentFacesInCity": 0,
"combatDefenseBonus": 0,
"maintenanceCost": 0,
"iconRowIndex": 59
"iconRowIndex": 59,
"flags": [
"treasuryEarnsInterest"
]
},
{
"name": "Apollo Program",
Expand Down Expand Up @@ -76067,7 +76070,9 @@
"scoutUnitType": "Scout",
"maxRankOfWorkableTiles": 2,
"maxRankOfBarbarianCampTiles": 2,
"defaultDealDuration": 20
"defaultDealDuration": 20,
"treasuryInterestRate": 0.05,
"maxInterest": 50
},
"techs": [
{
Expand Down
14 changes: 6 additions & 8 deletions C7/UIElements/Advisors/DomesticAdvisor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,10 @@ public void ShowAdvisor() {

EngineStorage.ReadGameData((GameData gameData) => {
Player player = gameData.GetFirstHumanPlayer();
PlayerCommerceBreakdown totalIncome = player.AggregateFlows();

int scienceRate = player.scienceRate;
int luxuryRate = player.luxuryRate;
int maintenanceCosts = player.MaintenanceCosts();
(_, _, int unitSupportCost) = player.TotalUnitsAllowedUnitsAndSupportCost();

scienceSliderIcon.SetPosition(new Vector2(CalculateSliderXPos(scienceRate), scienceSliderY));
luxurySliderIcon.SetPosition(new Vector2(CalculateSliderXPos(luxuryRate), luxurySliderY));
Expand All @@ -159,15 +158,14 @@ public void ShowAdvisor() {
scienceStatus.Text = player.SummarizeScience(gameData);
treasury.Text = $"Treasury: {player.gold}";

// TODO: fill these in.
incomeDetails.Text = "From cities: +??\nFrom taxmen: +??\nFrom other civs: +??\nFrom interest: +??";
expenseDetails.Text = $"-??: Science\n-??: Entertainment\n-??: Corruption\n-{maintenanceCosts}: Maintenance\n-{unitSupportCost}: Unit costs\n-??: To other civs";
incomeSummary.Text = "??";
expenseSummary.Text = "??";
incomeDetails.Text = $"From cities: +{totalIncome.CityInflows()}\nFrom taxmen: +{totalIncome.taxmenTaxes}\nFrom other civs: +{totalIncome.fromOtherCivs}\nFrom interest: +{totalIncome.interest}";
expenseDetails.Text = $"-{totalIncome.beakers}: Science\n-{totalIncome.happiness}: Entertainment\n-{totalIncome.corrupted}: Corruption\n-{totalIncome.maintenance}: Maintenance\n-{totalIncome.unitSupport}: Unit costs\n-{totalIncome.toOtherCivs}: To other civs";
incomeSummary.Text = $"Income: {totalIncome.Inflows()}";
expenseSummary.Text = $"Expenses: {totalIncome.Outflows()}";

int goldPerTurn = player.CalculateGoldPerTurn();
if (goldPerTurn > 0) {
sumSummary.Text = $"Net gain: {goldPerTurn}";
sumSummary.Text = $"Net gain: +{goldPerTurn}";
growth.Text = "Growing!";
} else if (goldPerTurn < 0) {
sumSummary.Text = $"Net loss: {goldPerTurn}";
Expand Down
2 changes: 2 additions & 0 deletions C7Engine/C7GameData/Building.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class GreatWonderProperties {
public bool onlyUsefulInTowns;
public StrengthBonus? combatDefenseBonus;
public bool providesVeteranGroundUnits;
public bool treasuryEarnsInterest;

public int culturePerTurn = 0;
public int maintenanceCost = 0;
Expand Down Expand Up @@ -93,6 +94,7 @@ public Building(SaveBuilding building, GameData gameData) {
providesWalls = building.flags.Contains(SaveBuilding.Flag.ProvidesWalls);
onlyUsefulInTowns = building.flags.Contains(SaveBuilding.Flag.CanOnlyBeBuiltInTowns);
providesVeteranGroundUnits = building.flags.Contains(SaveBuilding.Flag.VeteranGroundUnits);
treasuryEarnsInterest = building.flags.Contains(SaveBuilding.Flag.TreasuryEarnsInterest);

if (building.greatWonderProperties != null) {
greatWonderProperties = new();
Expand Down
1 change: 1 addition & 0 deletions C7Engine/C7GameData/City.cs
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ public CommerceBreakdown CurrentCommerceYield(bool respectCivilDisorder = true)
commerce.corrupt = uncorruptedCommerce;
}

// TODO: Science/Luxury commerce doesn't seem to be tabulating correctly, can be negative in some cases with specialists, might be ImportCiv3 issue?
CommerceBreakdown result = new();
result.corrupted = commerce.corrupt;
result.beakers = (int)Math.Floor(commerce.useful * owner.scienceRate / 10.0);
Expand Down
1 change: 1 addition & 0 deletions C7Engine/C7GameData/ImportCiv3.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,7 @@ private void ImportBuildings() {
(bldg.AllowsCitySize2, SaveBuilding.Flag.AllowsCitySize2),
(bldg.AllowsCitySize3, SaveBuilding.Flag.AllowsCitySize3),
(bldg.DoublesCityGrowthRate, SaveBuilding.Flag.DoublesCityGrowthRate),
(bldg.TreasuryEarnsInterest, SaveBuilding.Flag.TreasuryEarnsInterest),
}
.Where(t => t.Item1)
.Select(t => t.Item2);
Expand Down
97 changes: 86 additions & 11 deletions C7Engine/C7GameData/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,35 @@
using static C7GameData.EraUtils;

namespace C7GameData {

public struct PlayerCommerceBreakdown {
public int corrupted; // Amount of commerce lost directly to corruption
public int taxes; // Amount of treasury income from REGULAR citizens working tiles
public int taxmenTaxes; // Amount of treasury income from tax collector specialists
public int beakers; // Amount of commerce going to science
public int happiness; // Amount of commerce going to entertainment
public int fromOtherCivs; // Income from other Civ GPT deals
public int toOtherCivs; // Expenses paid to other Civ GPT deals
public int interest; // Interest income from Wall Street-flag small wonder
public int maintenance; // Expenses due to aggregate building maintenance
public int unitSupport; // Expenses due to unit support costs

public int Inflows() {
return corrupted + taxes + taxmenTaxes + beakers + happiness + fromOtherCivs + interest;
}

public int Outflows() {
return corrupted + beakers + happiness + toOtherCivs + maintenance + unitSupport;
}

public int Netflows() {
return Inflows() - Outflows();
}

public int CityInflows() {
return corrupted + taxes + beakers + happiness;
}
}
public class Player {
private static ILogger log = Log.ForContext<Player>();

Expand Down Expand Up @@ -324,6 +353,61 @@ public override string ToString() {
return "";
}

public PlayerCommerceBreakdown AggregateFlows() {
var result = new PlayerCommerceBreakdown
{
corrupted = 0,
taxes = 0,
taxmenTaxes = 0,
beakers = 0,
happiness = 0,
fromOtherCivs = 0,
toOtherCivs = 0,
interest = 0,
maintenance = 0,
unitSupport = 0
};

// If player has no cities, apply no expenses or income.
// This is how this behaves in regular Civ 3 as well (if you're not defeated, e.g. you still have a King unit or settler)
if (cities.Count == 0) return result;

// Assume player has no buildings that generate interest income until we check
int interestBuildings = 0;

foreach (City city in cities) {
CommerceBreakdown cityCommerce = city.CurrentCommerceYield();
result.corrupted += cityCommerce.corrupted;
result.taxes += cityCommerce.taxes;
result.beakers += cityCommerce.beakers;
result.happiness += cityCommerce.happiness;
result.maintenance += city.MaintenanceCosts();

interestBuildings += city.constructed_buildings.Count(cb => cb.building.treasuryEarnsInterest);

foreach (CityResident cr in city.residents) {
// Split city income into "regular citizen" and "tax collector" buckets
result.taxes -= cr.citizenType.Taxes;
result.taxmenTaxes += cr.citizenType.Taxes;
}
}

foreach (var pr in playerRelationships.Values) {
foreach (var mtd in pr.multiTurnDeals) {
if (mtd.dealSubType == DealSubType.GoldPerTurn) {
if (mtd.dealDetails == DealDetails.Inbound) result.fromOtherCivs += mtd.goldPerTurn;
else if (mtd.dealDetails == DealDetails.Outbound) result.toOtherCivs += mtd.goldPerTurn;
}
}
}

result.unitSupport = TotalUnitsAllowedUnitsAndSupportCost().Item3;

if (interestBuildings > 0) result.interest = interestBuildings * Math.Min((int)(gold * rules.TreasuryInterestRate), rules.MaxInterest);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@esbudylin That's what cought my eye, and saw some similarities with the lua files


return result;
}

public int MaintenanceCosts() {
int result = 0;
foreach (City c in cities) {
Expand All @@ -332,18 +416,9 @@ public int MaintenanceCosts() {
return result;
}

// TODO: Add interest and GPT deals
public int CalculateGoldPerTurn() {
int result = 0;
foreach (City city in cities) {
result += city.CurrentCommerceYield().taxes;
result -= city.MaintenanceCosts();
}

// Subtract unit support costs, if any.
var (_, _, unitSupportCost) = TotalUnitsAllowedUnitsAndSupportCost();
result -= unitSupportCost;

return result;
return AggregateFlows().Netflows();
}

public bool WouldAcceptDealFrom(GameData gameData, Player other, TradeOffer theirOffer, TradeOffer ourOffer) {
Expand Down
2 changes: 2 additions & 0 deletions C7Engine/C7GameData/Rules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public class Rules {
public int MaxRankOfWorkableTiles;
public int MaxRankOfBarbarianCampTiles;
public int DefaultDealDuration;
public float TreasuryInterestRate = .05f;
public int MaxInterest = 50;
}
}
1 change: 1 addition & 0 deletions C7Engine/C7GameData/Save/SaveBuilding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public enum Flag {
DoublesCityGrowthRate,
ProvidesWalls,
CanOnlyBeBuiltInTowns,
TreasuryEarnsInterest,
}

public class GreatWonderProperties {
Expand Down