Implement action-needed queue bar at bottom of screen with oldest-first ordering and dismissal

This commit is contained in:
bart
2026-11-08 22:39:20 +01:00
parent 705aa0f0f0
commit c47673575b
8 changed files with 689 additions and 5 deletions
+99 -2
View File
@@ -58,6 +58,10 @@ void GameManager::init(const QString &baseDir, Matrix2D<TerrainPoint> *mapPoints
QString roadsConfigPath = baseDir + "/config/roads.yaml";
m_roadConfigManager.loadConfigFile(roadsConfigPath);
// Load action needed queue configuration
QString actionNeededConfigPath = baseDir + "/config/action_needed.yaml";
m_actionNeededManager.loadConfigFile(actionNeededConfigPath);
const CityConfig &cCfg = TerrainYieldManager::instance().getCityConfig();
// Initialize player national resources from configuration
@@ -133,8 +137,12 @@ void GameManager::update(float deltaTime, Matrix2D<TerrainPoint> *mapPoints, int
if (u->isBuilding() && u->buildProgress >= 1.0f) {
completeUnitBuilding(*u, mapPoints, numPoints05);
}
if (!u->isDead() && u->state == UnitState::Idle && u->hasQueuedAction()) {
processUnitActionQueue(*u, mapPoints, numPoints05);
if (!u->isDead() && u->state == UnitState::Idle) {
if (u->hasRoadRoute()) {
advanceRoadRoute(*u, mapPoints, numPoints05);
} else if (u->hasQueuedAction()) {
processUnitActionQueue(*u, mapPoints, numPoints05);
}
}
}
}
@@ -162,6 +170,9 @@ void GameManager::update(float deltaTime, Matrix2D<TerrainPoint> *mapPoints, int
++it;
}
}
// Update Action Needed Queue for active human player 1
m_actionNeededManager.update(deltaTime, 1, m_units, m_cities);
}
Unit* GameManager::getSelectedUnit()
@@ -663,6 +674,7 @@ void GameManager::commandMoveSelected(int targetX, int targetY, Matrix2D<Terrain
if (path.size() > 1) {
selected->clearActionQueue();
selected->clearRoadRoute();
selected->setPath(path);
addFloatingText(Localization::instance().get("ui.unit.moving", "Moving"),
selected->worldPos + QVector3D(0, 0, 0.8f), QColor(255, 230, 80));
@@ -1032,6 +1044,86 @@ void GameManager::commandBuildRoadSelected(Matrix2D<TerrainPoint> *mapPoints, in
selected->worldPos + QVector3D(0, 0, 0.8f), QColor(255, 220, 80), 2.0f);
}
void GameManager::commandBuildRoadToTileSelected(int targetX, int targetY, Matrix2D<TerrainPoint> *mapPoints, int numPoints05)
{
Unit *selected = getSelectedUnit();
if (!selected || !selected->config.canBuildRoad()) return;
if (!TerrainMovementManager::instance().isHexPassable(
targetX, targetY, MovementDomain::Land, mapPoints, numPoints05, &selected->config)) {
addFloatingText(Localization::instance().get("ui.unit.cannot_build_road_water", "Roads cannot be built on water!"),
selected->worldPos + QVector3D(0, 0, 0.8f), QColor(255, 80, 80));
return;
}
// Pathfind from current tile to target tile
std::vector<std::pair<int, int>> route = Pathfinder::findPath(
selected->tileX, selected->tileY, targetX, targetY,
MovementDomain::Land, mapPoints, numPoints05, &selected->config
);
if (route.empty()) {
addFloatingText(Localization::instance().get("ui.unit.no_path", "No reachable path!"),
selected->worldPos + QVector3D(0, 0, 0.8f), QColor(255, 90, 90));
return;
}
selected->clearActionQueue();
selected->startRoadRoute(route);
QString defaultType = m_roadConfigManager.defaultRoadType();
const RoadTypeConfig *rCfg = m_roadConfigManager.getRoadType(defaultType);
QString roadName = rCfg ? rCfg->name : "Road";
addFloatingText(Localization::instance().get("ui.unit.road_route_started", "Building road route to (%1, %2)...").arg(targetX).arg(targetY),
selected->worldPos + QVector3D(0, 0, 0.8f), QColor(255, 220, 80), 2.2f);
advanceRoadRoute(*selected, mapPoints, numPoints05);
}
void GameManager::advanceRoadRoute(Unit &unit, Matrix2D<TerrainPoint> *mapPoints, int numPoints05)
{
if (!unit.hasRoadRoute()) return;
while (unit.roadRouteIndex < unit.roadRoute.size()) {
auto nextHex = unit.roadRoute[unit.roadRouteIndex];
int tx = nextHex.first;
int ty = nextHex.second;
// If unit is not on this tile yet, move to it!
if (unit.tileX != tx || unit.tileY != ty) {
unit.setPath({ {unit.tileX, unit.tileY}, {tx, ty} });
unit.state = UnitState::Moving;
return;
}
// Unit is on this tile! Does it already have a road?
if (hasRoadAt(tx, ty)) {
// Already has a road, skip to next tile along route
unit.advanceRoadRouteStep();
continue;
}
// Start building road on this tile
QString defaultType = m_roadConfigManager.defaultRoadType();
const RoadTypeConfig *rCfg = m_roadConfigManager.getRoadType(defaultType);
QString roadName = rCfg ? rCfg->name : "Road";
int ticks = m_roadConfigManager.buildDurationTicks();
float duration = (float)ticks * m_movementTickDuration;
unit.startBuilding(QString("road:%1").arg(defaultType), duration);
addFloatingText(Localization::instance().get("ui.unit.road_started", "Constructing %1... (%2 ticks)").arg(roadName).arg(ticks),
unit.worldPos + QVector3D(0, 0, 0.8f), QColor(255, 220, 80), 2.0f);
return;
}
// Finished entire route!
unit.clearRoadRoute();
QVector2D w = Pathfinder::hexToWorld(unit.tileX, unit.tileY);
float gz = Unit::getTerrainHeight(w.x(), w.y(), mapPoints, numPoints05);
addFloatingText(Localization::instance().get("ui.unit.road_route_completed", "Road route completed!"),
QVector3D(w.x(), w.y(), gz + 1.2f), QColor(100, 255, 140), 3.0f);
}
void GameManager::completeUnitBuilding(Unit &unit, Matrix2D<TerrainPoint> *mapPoints, int numPoints05)
{
int tx = unit.tileX;
@@ -1054,6 +1146,11 @@ void GameManager::completeUnitBuilding(Unit &unit, Matrix2D<TerrainPoint> *mapPo
QString roadName = rCfg ? rCfg->name : "Road";
addFloatingText(Localization::instance().get("ui.unit.road_completed", "%1 completed!").arg(roadName),
QVector3D(w.x(), w.y(), gz + 1.2f), QColor(240, 210, 100), 2.8f);
if (unit.hasRoadRoute()) {
unit.advanceRoadRouteStep();
advanceRoadRoute(unit, mapPoints, numPoints05);
}
return;
}