Skip to content

Commit

Permalink
Allow modifying tile assignments in the city screen
Browse files Browse the repository at this point in the history
This currently only allows moving the "worst" citizen as well as resetting tile assignments by clicking on the city center, but it's a good start. Implementing entertainers (which is necessary to support fancier moves) will be a separate PR.

#541
  • Loading branch information
TomWerner committed Feb 15, 2025
1 parent 02307f8 commit 3586d0b
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 1 deletion.
3 changes: 2 additions & 1 deletion C7/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ public override void _Ready() {
}

// Allow the city screen to control whether tile assignments
// are visible.
// are visible and map UI locations back to map locations.
cityScreen.tileAssignmentLayer = mapView.tileAssignmentLayer;
cityScreen.mapView = mapView;
}

//TODO: What was this supposed to do? It throws errors and occasinally causes crashes now, because _OnViewportSizeChanged doesn't exist
Expand Down
89 changes: 89 additions & 0 deletions C7/UIElements/CityScreen/CityScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
using System.Collections.Generic;
using C7GameData;
using C7.Map;
using C7Engine;
using C7Engine.AI;


// Handles the city screen, where citizens can be assigned and other details of
// the city can bee seen.
public partial class CityScreen : CenterContainer {
private ILogger log = LogManager.ForContext<CityScreen>();
public TileAssignmentLayer tileAssignmentLayer;
public MapView mapView;

// Called when the node enters the scene tree for the first time.
public override void _Ready() {
Expand All @@ -31,6 +34,92 @@ public override void _Ready() {
this.Hide();
}

public override void _UnhandledInput(InputEvent @event) {
// Only capture mouse events if we're visible.
if (!this.Visible) {
return;
}

// If we left clicked on a tile, handle reassigning a citizen accordingly.
if (@event is InputEventMouseButton eventMouseButton) {
if (eventMouseButton.ButtonIndex == MouseButton.Left) {
GetViewport().SetInputAsHandled();
if (eventMouseButton.IsPressed()) {
using (UIGameDataAccess gameDataAccess = new()) {
Tile tile = mapView.tileOnScreenAt(gameDataAccess.gameData.map, eventMouseButton.Position);
if (tile != null) {
HandleReassignment(tile);
}
}
}
}
}
}

private void HandleReassignment(Tile tile) {
City city = tileAssignmentLayer.city;

// We can't assign citizens to other cities.
if (tile.cityAtTile != null && tile.cityAtTile != city) {
return;
}

// We can't assign citizens to tiles worked by other cities.
if (tile.personWorkingTile != null && tile.personWorkingTile.city != city) {
return;
}

// If we're already working a tile and click on it, turn the citizen
// into an entertainer.
if (tile.personWorkingTile != null && tile.personWorkingTile.city == city) {
// TODO: implement entertainers.
return;
}

// We've clicked on an unworked tile, move the "worst" citizen to that
// tile.
//
// TODO: only allow this within the city's borders/BFC.
if (tile.cityAtTile == null) {
int worstYield = int.MaxValue;
CityResident worst = null;

foreach (CityResident cr in city.residents) {
int tileYield = cr.tileWorked.foodYield(city.owner) +
cr.tileWorked.productionYield(city.owner) +
cr.tileWorked.commerceYield(city.owner);
if (tileYield < worstYield) {
worstYield = tileYield;
worst = cr;
}
}

// Move the worst citizen to our new tile, being sure to update
// backpointers from the tile.
worst.tileWorked.personWorkingTile = null;
worst.tileWorked = tile;
tile.personWorkingTile = worst;
return;
}

// If we've clicked the city center, re-assign all the citizens using
// the basic AI.
//
// TODO: This throws away existing nationalities, fix that.
if (tile.cityAtTile == city) {
int numResidents = city.residents.Count;
city.RemoveAllCitizens();

for (int i = 0; i < numResidents; ++i) {
CityResident newResident = new() {
nationality = city.owner.civilization,
city = city
};
CityTileAssignmentAI.AssignNewCitizenToTile(newResident);
}
}
}

public void HideScreen() {
this.Hide();
tileAssignmentLayer.city = null;
Expand Down

0 comments on commit 3586d0b

Please sign in to comment.