Skip to content

Commit

Permalink
Support a barebones "city screen" view
Browse files Browse the repository at this point in the history
This is triggered when building a city and when clicking "zoom to city"

For now I've just added the "exit" button, but hope to add tile yields soon.

I also fixed an issue with the advisor and input handling - previously if you exited the advisor via escape the game would ask if you wanted to exit. Now it works properly.
  • Loading branch information
TomWerner committed Jan 29, 2025
1 parent 077be11 commit df4eeec
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 27 deletions.
15 changes: 14 additions & 1 deletion C7/C7Game.tscn
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
[ext_resource type="Script" path="res://UIElements/Popups/PopupOverlay.cs" id="9"]
[ext_resource type="Theme" uid="uid://c1jpmssnhvodi" path="res://C7Theme.tres" id="10"]
[ext_resource type="Script" path="res://UIElements/UnitButtons/UnitButtons.cs" id="12"]
[ext_resource type="Script" path="res://UIElements/CityScreen/CityScreen.cs" id="13"]

[sub_resource type="Animation" id="2"]
length = 0.001
Expand Down Expand Up @@ -58,12 +59,14 @@ _data = {
"SlideOutAnimation": SubResource("1")
}

[node name="C7Game" type="Node2D" node_paths=PackedStringArray("Toolbar", "popupOverlay", "slider", "animationPlayer")]
[node name="C7Game" type="Node2D" node_paths=PackedStringArray("Toolbar", "popupOverlay", "slider", "animationPlayer", "cityScreen", "advisor")]
script = ExtResource("1")
Toolbar = NodePath("CanvasLayer/Control/ToolBar/MarginContainer/HBoxContainer")
popupOverlay = NodePath("CanvasLayer/PopupOverlay")
slider = NodePath("CanvasLayer/Control/SlideOutBar/VBoxContainer/Zoom")
animationPlayer = NodePath("CanvasLayer/Control/SlideOutBar/AnimationPlayer")
cityScreen = NodePath("CanvasLayer/CityScreen")
advisor = NodePath("CanvasLayer/Advisor")

[node name="CanvasLayer" type="CanvasLayer" parent="."]

Expand Down Expand Up @@ -252,11 +255,21 @@ grow_vertical = 2
theme = ExtResource("10")
script = ExtResource("3")

[node name="CityScreen" type="CenterContainer" parent="CanvasLayer"]
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme = ExtResource("10")
script = ExtResource("13")

[connection signal="NewAutoselectedUnit" from="." to="CanvasLayer/Control/GameStatus" method="OnNewUnitSelected"]
[connection signal="NewAutoselectedUnit" from="." to="CanvasLayer/Control/UnitButtons" method="OnNewUnitSelected"]
[connection signal="NoMoreAutoselectableUnits" from="." to="CanvasLayer/Control/GameStatus" method="OnNoMoreAutoselectableUnits"]
[connection signal="NoMoreAutoselectableUnits" from="." to="CanvasLayer/Control/UnitButtons" method="OnNoMoreAutoselectableUnits"]
[connection signal="ShowSpecificAdvisor" from="." to="CanvasLayer/Advisor" method="OnShowSpecificAdvisor"]
[connection signal="ShowCityScreen" from="." to="CanvasLayer/CityScreen" method="OnShowCityScreen"]
[connection signal="TurnEnded" from="." to="CanvasLayer/Control/GameStatus" method="OnTurnEnded"]
[connection signal="TurnStarted" from="." to="CanvasLayer/Control/GameStatus" method="OnTurnStarted"]
[connection signal="UpdateTechProgress" from="." to="CanvasLayer/Control/GameStatus" method="OnUpdateTechProgress"]
Expand Down
33 changes: 31 additions & 2 deletions C7/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public partial class Game : Node2D {
[Signal] public delegate void NewAutoselectedUnitEventHandler();
[Signal] public delegate void NoMoreAutoselectableUnitsEventHandler();
[Signal] public delegate void UpdateTechProgressEventHandler();
[Signal] public delegate void ShowCityScreenEventHandler();

private ILogger log = LogManager.ForContext<Game>();

Expand Down Expand Up @@ -61,6 +62,10 @@ public class GotoInfo {
[Export]
private PopupOverlay popupOverlay;
[Export]
private CityScreen cityScreen;
[Export]
private Advisors advisor;
[Export]
private VSlider slider;
[Export]
private AnimationPlayer animationPlayer;
Expand Down Expand Up @@ -183,6 +188,9 @@ public void processEngineMessages(GameData gameData) {
case MsgStartTurn mST:
OnPlayerStartTurn();
break;
case MsgCityCreated mCC:
ShowCityScreenForCity(mCC.city);
break;
case MsgCityDestroyed mCD:
mapView.cityLayer.UpdateAfterCityDestruction(mCD.city);

Expand Down Expand Up @@ -551,8 +559,18 @@ private void ProcessAction(string currentAction) {
return;
}

if (currentAction == C7Action.Escape && cityScreen.Visible) {
cityScreen.Hide();
return;
}

if (currentAction == C7Action.Escape && advisor.Visible) {
advisor.Hide();
return;
}

// never poll for actions if UI elements are visible
if (popupOverlay.Visible) {
if (popupOverlay.Visible || cityScreen.Visible || advisor.Visible) {
return;
}

Expand Down Expand Up @@ -691,6 +709,17 @@ private void OnQuitTheGame() {
}

private void OnBuildCity(string name) {
new ActionToEngineMsg(() => CurrentlySelectedUnit?.buildCity(name)).send();
new ActionToEngineMsg(() => {
// Create the city and then let the ui know, so we can show the city
// screen.
City city = CurrentlySelectedUnit?.buildCity(name);
if (city != null) {
new MsgCityCreated(city).send();
}
}).send();
}

public void ShowCityScreenForCity(City city) {
EmitSignal(SignalName.ShowCityScreen, new ParameterWrapper<City>(city));
}
}
19 changes: 0 additions & 19 deletions C7/UIElements/Advisors/Advisors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,23 +67,4 @@ private void OnShowSpecificAdvisor(string advisorType) {
this.Show();
}
}

public override void _UnhandledInput(InputEvent @event) {
if (this.Visible) {
if (@event is InputEventKey eventKey) {
//As I've added more shortcuts, I've realized checking all of them here could be irksome.
//For now, I'm thinking it would make more sense to process or allow through the ones that should go through,
//as most of the global ones should *not* go through here.
if (eventKey.Pressed) {
if (eventKey.Keycode == Godot.Key.Escape) {
this.Hide();
GetViewport().SetInputAsHandled();
} else {
log.Debug("Advisor received a key press; stopping propagation.");
GetViewport().SetInputAsHandled();
}
}
}
}
}
}
35 changes: 35 additions & 0 deletions C7/UIElements/CityScreen/CityScreen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Godot;
using System;
using Serilog;
using System.Collections.Generic;
using C7GameData;


// 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>();

// Called when the node enters the scene tree for the first time.
public override void _Ready() {
TextureRect background = new() {
Texture = Util.LoadTextureFromPCX("Art/city screen/background.pcx")
};
AddChild(background);

TextureButton close = new() {
TextureNormal = Util.LoadTextureFromPCX("Art/city screen/cityMgmtButtons.pcx", 155, 1, 32, 48),
TextureHover = Util.LoadTextureFromPCX("Art/city screen/cityMgmtButtons.pcx", 155, 50, 32, 48),
TexturePressed = Util.LoadTextureFromPCX("Art/city screen/cityMgmtButtons.pcx", 155, 99, 32, 48)
};
close.SetPosition(new Vector2(950, 20));
close.Pressed += () => { this.Hide(); };
background.AddChild(close);

this.Hide();
}

private void OnShowCityScreen(ParameterWrapper<City> city) {
this.Show();
}
}
9 changes: 9 additions & 0 deletions C7/UIElements/RightClickMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Godot;
using C7GameData;
using C7Engine;
using System;

public partial class RightClickMenu : VBoxContainer {
protected Game game;
Expand Down Expand Up @@ -151,6 +152,10 @@ public void ResetItems(Tile tile, Dictionary<ID, bool> uiUpdatedUnitStates = nul
this.CloseAndDelete();
new RightClickChooseProductionMenu(game, tile.cityAtTile).Open(this.position);
});
AddItem("Zoom to city", () => {
this.CloseAndDelete();
game.ShowCityScreenForCity(tile.cityAtTile);
});
}

// If we're looking at an enemy tile, then the behavior depends on whether the units
Expand Down Expand Up @@ -224,6 +229,10 @@ public void ResetItems(Tile tile) {
this.CloseAndDelete();
new RightClickChooseProductionMenu(game, tile.cityAtTile).Open(this.position);
});
AddItem("Zoom to city", () => {
this.CloseAndDelete();
game.ShowCityScreenForCity(tile.cityAtTile);
});
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion C7Engine/EntryPoints/CityInteractions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace C7Engine {
using C7GameData;

public class CityInteractions {
public static void BuildCity(int x, int y, ID playerID, string name) {
public static City BuildCity(int x, int y, ID playerID, string name) {
GameData gameData = EngineStorage.gameData;
Player owner = gameData.GetPlayer(playerID);
Tile tileWithNewCity = gameData.map.tileAt(x, y);
Expand All @@ -24,8 +24,10 @@ public static void BuildCity(int x, int y, ID playerID, string name) {
// a city is build on a mine, the mine should be removed.
tileWithNewCity.overlays.road = true;
tileWithNewCity.overlays.mine = false;
tileWithNewCity.overlays.irrigation = false;

gameData.UpdateTileOwners();
return newCity;
}

public static void DestroyCity(int x, int y) {
Expand Down
7 changes: 7 additions & 0 deletions C7Engine/EntryPoints/MessageToUI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,11 @@ public MsgCityDestroyed(City city) {
}
}

public class MsgCityCreated : MessageToUI {
public City city;

public MsgCityCreated(City city) {
this.city = city;
}
}
}
10 changes: 6 additions & 4 deletions C7Engine/MapUnitExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -420,21 +420,23 @@ public static bool canBuildCity(this MapUnit unit) {
return unit.location.neighbors.Values.All(tile => !tile.HasCity);
}

public static void buildCity(this MapUnit unit, string cityName) {
public static City buildCity(this MapUnit unit, string cityName) {
if (!unit.canBuildCity()) {
log.Warning($"can't build city at {unit.location}");
return;
return null;
}

unit.animate(MapUnit.AnimatedAction.BUILD, true);

// TODO: Need to check somewhere that this unit is allowed to build a city on its current tile. Either do that here or in every caller
// (probably best to just do it here).
CityInteractions.BuildCity(unit.location.xCoordinate, unit.location.yCoordinate, unit.owner.id, cityName);
City city = CityInteractions.BuildCity(unit.location.xCoordinate, unit.location.yCoordinate, unit.owner.id, cityName);

// TODO: Should directly delete the unit instead of disbanding it. Disbanding in a city will eventually award shields, which we
// obviously don't want to do here.
unit.disband();

return city;
}

public static bool canBuildRoad(this MapUnit unit) {
Expand Down Expand Up @@ -485,7 +487,7 @@ public static bool canIrrigate(this MapUnit unit) {
unit.location.overlays.mine ||
unit.location.overlays.irrigation ||
unit.location.cityAtTile != null) {
return false;
return false;
}

// If a tile borders a river, it has fresh water access.
Expand Down

0 comments on commit df4eeec

Please sign in to comment.