diff --git a/game/territory-autobattler/scenes/game/hex_grid_screen.gd b/game/territory-autobattler/scenes/game/hex_grid_screen.gd index 9cf3791..16d1c4e 100644 --- a/game/territory-autobattler/scenes/game/hex_grid_screen.gd +++ b/game/territory-autobattler/scenes/game/hex_grid_screen.gd @@ -96,6 +96,7 @@ var pending_move_q := 9999 var pending_move_r := 9999 var refresh_prompt_active := false var refresh_request_active := false +var units_reload_queued := false func _ready() -> void: @@ -1112,6 +1113,13 @@ func _refresh_player_state() -> void: _load_units() +func _queue_units_reload() -> void: + if units_request.get_http_client_status() == HTTPClient.STATUS_DISCONNECTED: + _load_units() + else: + units_reload_queued = true + + func _load_resources() -> void: var access_token: String = str(session.get("accessToken", "")) if access_token.is_empty(): @@ -1172,6 +1180,7 @@ func _on_resources_request_completed(result: int, response_code: int, _headers: if gold_tick_anchor_unix <= 0.0: gold_tick_anchor_unix = Time.get_unix_time_from_system() _update_tick_bar() + _queue_units_reload() func _resource_line(resource_name: String, amount: int, capacity: int, rate: int) -> String: @@ -1241,8 +1250,12 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack if typeof(raw_units) == TYPE_ARRAY: unit_instances = raw_units grid_view.set_unit_instances(unit_instances) + _clear_removed_selected_unit() unit_label.text = "Scouts: %d | Peasants: %d | Archers: %d | Queue: %d" % [completed_scout_count, completed_peasant_count, completed_archer_count, training.size()] _update_action_buttons() + if units_reload_queued: + units_reload_queued = false + call_deferred("_load_units") if training.is_empty(): training_started_unix = 0.0 @@ -1263,6 +1276,17 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack _update_training_bar() +func _clear_removed_selected_unit() -> void: + if not grid_view: + return + if selected_scout_count > 0 and grid_view.get_scout_count_at(selected_scout_q, selected_scout_r) <= 0: + _clear_selected_archers() + elif selected_archer_count > 0 and grid_view.get_archer_count_at(selected_archer_q, selected_archer_r) <= 0: + _clear_selected_archers() + elif selected_peasant_count > 0 and grid_view.get_peasant_count_at(selected_peasant_q, selected_peasant_r) <= 0: + _clear_selected_archers() + + func _train_scout() -> void: _request_unit_training("Scout") diff --git a/microservices/LocationsApi/Services/GameSettingsService.cs b/microservices/LocationsApi/Services/GameSettingsService.cs index c8feefd..e549c0a 100644 --- a/microservices/LocationsApi/Services/GameSettingsService.cs +++ b/microservices/LocationsApi/Services/GameSettingsService.cs @@ -27,6 +27,7 @@ public class GameSettingsService public const string ProductionBuildingResourceCapacity = "ProductionBuildingResourceCapacity"; public const string StartingGold = "StartingGold"; public const string HeadquartersGoldPerMinute = "HeadquartersGoldPerMinute"; + public const string TownHallFoodPerMinute = "TownHallFoodPerMinute"; public const string TownHallGoldCapacity = "TownHallGoldCapacity"; public const string TownHallWoodCapacity = "TownHallWoodCapacity"; public const string TownHallOreCapacity = "TownHallOreCapacity"; diff --git a/microservices/LocationsApi/Services/ResourceService.cs b/microservices/LocationsApi/Services/ResourceService.cs index 3f90c5d..4d7adbf 100644 --- a/microservices/LocationsApi/Services/ResourceService.cs +++ b/microservices/LocationsApi/Services/ResourceService.cs @@ -16,6 +16,7 @@ public class ResourceService private readonly GameSettingsService _settings; private readonly int _startingGold; private readonly int _headquartersGoldPerMinute; + private readonly int _townHallFoodPerMinute; private readonly int _townHallGoldCapacity; private readonly int _townHallWoodCapacity; private readonly int _townHallOreCapacity; @@ -38,6 +39,9 @@ public class ResourceService _headquartersGoldPerMinute = int.TryParse(cfg["Resources:HeadquartersGoldPerMinute"], out var goldPerMinute) ? Math.Max(0, goldPerMinute) : 10; + _townHallFoodPerMinute = int.TryParse(cfg["Resources:TownHallFoodPerMinute"], out var townHallFoodPerMinute) + ? Math.Max(0, townHallFoodPerMinute) + : 5; _townHallGoldCapacity = int.TryParse(cfg["Resources:TownHallGoldCapacity"], out var goldCapacity) ? Math.Max(0, goldCapacity) : 500; @@ -231,10 +235,16 @@ public class ResourceService { await EnsureAsync(username); var now = DateTime.UtcNow; + var townHallFoodPerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.TownHallFoodPerMinute, _townHallFoodPerMinute); + var hasTownHall = await _locations.Find(x => + x.OwnerUsername == username && + x.Kind == "Home") + .AnyAsync(); + var totalFoodPerMinute = Math.Max(0, foodPerMinute) + (hasTownHall ? townHallFoodPerMinute : 0); var update = Builders.Update .Set(x => x.WoodPerMinute, Math.Max(0, woodPerMinute)) .Set(x => x.OrePerMinute, Math.Max(0, orePerMinute)) - .Set(x => x.FoodPerMinute, Math.Max(0, foodPerMinute)) + .Set(x => x.FoodPerMinute, totalFoodPerMinute) .Set(x => x.UpdatedAtUtc, now); if (woodPerMinute > 0) @@ -245,7 +255,7 @@ public class ResourceService { update = update.Set(x => x.LastOreGeneratedAtUtc, now); } - if (foodPerMinute > 0) + if (totalFoodPerMinute > 0) { update = update.Set(x => x.LastFoodGeneratedAtUtc, now); } @@ -489,14 +499,19 @@ public class ResourceService private async Task CalculateFoodProductionPerMinuteAsync(string username) { + var townHallFoodPerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.TownHallFoodPerMinute, _townHallFoodPerMinute); var farmFoodPerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.FarmFoodPerMinute, 5); + var hasTownHall = await _locations.Find(x => + x.OwnerUsername == username && + x.Kind == "Home") + .AnyAsync(); var farms = await _locations.CountDocumentsAsync(x => x.OwnerUsername == username && !string.IsNullOrWhiteSpace(x.WorkerUnitId) && (x.BuildingStatus == "Built" || x.BuildingStatus == null || x.BuildingStatus == "") && x.BuildingType == "Farm"); - return checked((int)farms) * farmFoodPerMinute; + return (hasTownHall ? townHallFoodPerMinute : 0) + checked((int)farms) * farmFoodPerMinute; } private async Task CompletePendingWorkerAssignmentsAsync(string username, DateTime now) @@ -686,8 +701,29 @@ public class ResourceService await _units.DeleteManyAsync(x => x.Username == username && instanceIds.Contains(x.Id)); + + await RecalculateWorkerGenerationAsync(username); } } + private async Task RecalculateWorkerGenerationAsync(string username) + { + var logCampWoodPerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.LogCampWoodPerMinute, 5); + var mineOrePerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.MineOrePerMinute, 5); + var farmFoodPerMinute = await _settings.GetNonNegativeIntAsync(GameSettingsService.FarmFoodPerMinute, 5); + var built = await _locations.Find(x => + x.OwnerUsername == username && + !string.IsNullOrWhiteSpace(x.WorkerUnitId) && + (x.BuildingStatus == "Built" || x.BuildingStatus == null || x.BuildingStatus == "") && + (x.BuildingType == "LogCamp" || x.BuildingType == "Mine" || x.BuildingType == "Farm")) + .ToListAsync(); + + await SetBuildingGenerationAsync( + username, + built.Count(x => x.BuildingType == "LogCamp") * logCampWoodPerMinute, + built.Count(x => x.BuildingType == "Mine") * mineOrePerMinute, + built.Count(x => x.BuildingType == "Farm") * farmFoodPerMinute); + } + private sealed record FoodConsumingUnit(string Id, string UnitType, bool IsTrainingRecord); } diff --git a/microservices/LocationsApi/appsettings.json b/microservices/LocationsApi/appsettings.json index 5d27db9..373f8c3 100644 --- a/microservices/LocationsApi/appsettings.json +++ b/microservices/LocationsApi/appsettings.json @@ -22,6 +22,7 @@ "Resources": { "StartingGold": 100, "HeadquartersGoldPerMinute": 10, + "TownHallFoodPerMinute": 5, "TownHallGoldCapacity": 500, "TownHallWoodCapacity": 100, "TownHallOreCapacity": 100, diff --git a/microservices/LocationsApi/k8s/configmap.yaml b/microservices/LocationsApi/k8s/configmap.yaml index c057b00..fcd4255 100644 --- a/microservices/LocationsApi/k8s/configmap.yaml +++ b/microservices/LocationsApi/k8s/configmap.yaml @@ -13,6 +13,7 @@ data: World__VisibilityDepth: "3" Resources__StartingGold: "100" Resources__HeadquartersGoldPerMinute: "10" + Resources__TownHallFoodPerMinute: "5" Resources__TownHallGoldCapacity: "500" Resources__TownHallWoodCapacity: "100" Resources__TownHallOreCapacity: "100"