Merge branch 'main' into session/builder-roads
This commit is contained in:
@@ -59,6 +59,7 @@ public:
|
|||||||
|
|
||||||
std::vector<std::pair<int, int>> territory; // Owned hex coordinates
|
std::vector<std::pair<int, int>> territory; // Owned hex coordinates
|
||||||
std::map<std::pair<int, int>, QString> workedTiles; // (x, y) -> resource name
|
std::map<std::pair<int, int>, QString> workedTiles; // (x, y) -> resource name
|
||||||
|
std::map<std::pair<int, int>, QString> tilePreferredResources; // (x, y) -> user chosen resource
|
||||||
|
|
||||||
City(int cId, int pId, const QString &cName, int tx, int ty, const QVector3D &pos,
|
City(int cId, int pId, const QString &cName, int tx, int ty, const QVector3D &pos,
|
||||||
int initInhabitants = 1000, int initInhabitantsPerPop = 100000, int initRadius = 1);
|
int initInhabitants = 1000, int initInhabitantsPerPop = 100000, int initRadius = 1);
|
||||||
@@ -127,8 +128,24 @@ public:
|
|||||||
return it != workedTiles.end() ? it->second : "";
|
return it != workedTiles.end() ? it->second : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString getEffectiveResource(int tx, int ty, const QString &defaultBestRes) const {
|
||||||
|
auto itW = workedTiles.find({tx, ty});
|
||||||
|
if (itW != workedTiles.end()) return itW->second;
|
||||||
|
auto itP = tilePreferredResources.find({tx, ty});
|
||||||
|
if (itP != tilePreferredResources.end()) return itP->second;
|
||||||
|
return defaultBestRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTilePreferredResource(int tx, int ty, const QString &resource) {
|
||||||
|
tilePreferredResources[{tx, ty}] = resource;
|
||||||
|
if (isTileWorked(tx, ty)) {
|
||||||
|
workedTiles[{tx, ty}] = resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool assignWorker(int tx, int ty, const QString &resource) {
|
bool assignWorker(int tx, int ty, const QString &resource) {
|
||||||
if (!ownsTile(tx, ty)) return false;
|
if (!ownsTile(tx, ty)) return false;
|
||||||
|
tilePreferredResources[{tx, ty}] = resource;
|
||||||
if (isTileWorked(tx, ty)) {
|
if (isTileWorked(tx, ty)) {
|
||||||
workedTiles[{tx, ty}] = resource;
|
workedTiles[{tx, ty}] = resource;
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,3 +30,15 @@ initial_national_resources:
|
|||||||
kennis: 0
|
kennis: 0
|
||||||
geloof: 0
|
geloof: 0
|
||||||
goud: 0
|
goud: 0
|
||||||
|
|
||||||
|
# Slot long press duration in milliseconds to open resource selection popup
|
||||||
|
slot_long_press_duration_ms: 400
|
||||||
|
|
||||||
|
# Priority order for resources (used for tie-breaking when yields are equal and display order)
|
||||||
|
resource_priority:
|
||||||
|
- "voedsel"
|
||||||
|
- "arbeid"
|
||||||
|
- "goud"
|
||||||
|
- "kennis"
|
||||||
|
- "cultuur"
|
||||||
|
- "geloof"
|
||||||
|
|||||||
+19
-1
@@ -55,6 +55,11 @@ ui:
|
|||||||
farm_completed: "Farm completed!"
|
farm_completed: "Farm completed!"
|
||||||
farm_completed_consumed: "Farm completed! (Builder consumed)"
|
farm_completed_consumed: "Farm completed! (Builder consumed)"
|
||||||
farm_completed_charges: "Farm completed! (%1 %2 remaining)"
|
farm_completed_charges: "Farm completed! (%1 %2 remaining)"
|
||||||
|
road_queued: "Build Road queued on arrival"
|
||||||
|
road_started: "Constructing %1... (%2 ticks)"
|
||||||
|
road_completed: "%1 completed!"
|
||||||
|
road_already_here: "Tile already has a road!"
|
||||||
|
cannot_build_road_water: "Roads cannot be built on water!"
|
||||||
city_queued: "Found City queued on arrival"
|
city_queued: "Found City queued on arrival"
|
||||||
city_founded: "%1 founded!"
|
city_founded: "%1 founded!"
|
||||||
already_building: "Already busy building!"
|
already_building: "Already busy building!"
|
||||||
@@ -119,7 +124,7 @@ ui:
|
|||||||
close_btn: "[X] Close"
|
close_btn: "[X] Close"
|
||||||
local_info: "Local: Population: %L1 (%2 Pop: %3 working, %4 free) | Labor: %L5"
|
local_info: "Local: Population: %L1 (%2 Pop: %3 working, %4 free) | Labor: %L5"
|
||||||
national_info: "National: Culture: %L1 | Science: %L2 | Gold: %L3 | Faith: %L4"
|
national_info: "National: Culture: %L1 | Science: %L2 | Gold: %L3 | Faith: %L4"
|
||||||
help_text: "Click a tile to assign 1 Pop | Click an unowned tile to buy with Culture."
|
help_text: "Click a slot to assign/free Pop | Hold a slot to choose resource | Buy tile with Culture."
|
||||||
current_production: "CURRENT PRODUCTION"
|
current_production: "CURRENT PRODUCTION"
|
||||||
no_project: "No active project"
|
no_project: "No active project"
|
||||||
select_prompt: "Select a unit or building to construct"
|
select_prompt: "Select a unit or building to construct"
|
||||||
@@ -147,3 +152,16 @@ ui:
|
|||||||
no_free_pop: "No free Pop!"
|
no_free_pop: "No free Pop!"
|
||||||
buy_tile: "BUY"
|
buy_tile: "BUY"
|
||||||
occupied: "OCCUPIED"
|
occupied: "OCCUPIED"
|
||||||
|
select_resource: "SELECT RESOURCE"
|
||||||
|
best_yield: "BEST"
|
||||||
|
resource_switched: "Producing %1 (+%2)"
|
||||||
|
worker_assigned_res: "+1 Pop: %1 (+%2)"
|
||||||
|
resource_preferred: "Slot set to %1 (+%2)"
|
||||||
|
|
||||||
|
resources:
|
||||||
|
voedsel: "Food"
|
||||||
|
arbeid: "Production"
|
||||||
|
goud: "Gold"
|
||||||
|
kennis: "Science"
|
||||||
|
cultuur: "Culture"
|
||||||
|
geloof: "Faith"
|
||||||
|
|||||||
+67
-25
@@ -76,10 +76,8 @@ void GameManager::init(const QString &baseDir, Matrix2D<TerrainPoint> *mapPoints
|
|||||||
City initialCity(cId, 1, "Roma", 35, 17, QVector3D(w.x(), w.y(), gz),
|
City initialCity(cId, 1, "Roma", 35, 17, QVector3D(w.x(), w.y(), gz),
|
||||||
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
||||||
|
|
||||||
// Assign initial 1 pop to work the city center tile
|
// Assign initial 1 pop to work the city center tile with best yield resource
|
||||||
QString tType = TerrainYieldManager::instance().getTerrainType(35, 17, mapPoints, numPoints05);
|
QString defRes = getBestTileResource(35, 17, mapPoints, numPoints05);
|
||||||
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
|
||||||
QString defRes = yCfg ? yCfg->primaryResource : "voedsel";
|
|
||||||
initialCity.assignWorker(35, 17, defRes);
|
initialCity.assignWorker(35, 17, defRes);
|
||||||
|
|
||||||
m_cities.push_back(initialCity);
|
m_cities.push_back(initialCity);
|
||||||
@@ -251,6 +249,67 @@ void GameManager::exitCityView()
|
|||||||
m_activeCityViewId = -1;
|
m_activeCityViewId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QMap<QString, int> GameManager::getTileYields(int tx, int ty, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const
|
||||||
|
{
|
||||||
|
QMap<QString, int> yields;
|
||||||
|
const CityConfig &cCfg = TerrainYieldManager::instance().getCityConfig();
|
||||||
|
QStringList resources = cCfg.resourcePriority;
|
||||||
|
if (resources.isEmpty()) {
|
||||||
|
resources = {"voedsel", "arbeid", "goud", "kennis", "cultuur", "geloof"};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, mapPoints, numPoints05);
|
||||||
|
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
||||||
|
const TileImprovement *imp = getImprovementAt(tx, ty);
|
||||||
|
const ImprovementConfig *iCfg = imp ? TerrainYieldManager::instance().getImprovementConfig(imp->improvementId) : nullptr;
|
||||||
|
|
||||||
|
for (const QString &res : resources) {
|
||||||
|
int amount = yCfg ? yCfg->getYield(res) : 0;
|
||||||
|
if (iCfg && iCfg->yieldBonus.contains(res)) {
|
||||||
|
amount += iCfg->yieldBonus.value(res, 0);
|
||||||
|
}
|
||||||
|
yields[res] = amount;
|
||||||
|
}
|
||||||
|
return yields;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GameManager::getTileYield(int tx, int ty, const QString &res, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const
|
||||||
|
{
|
||||||
|
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, mapPoints, numPoints05);
|
||||||
|
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
||||||
|
int amount = yCfg ? yCfg->getYield(res) : 0;
|
||||||
|
const TileImprovement *imp = getImprovementAt(tx, ty);
|
||||||
|
if (imp) {
|
||||||
|
const ImprovementConfig *iCfg = TerrainYieldManager::instance().getImprovementConfig(imp->improvementId);
|
||||||
|
if (iCfg && iCfg->yieldBonus.contains(res)) {
|
||||||
|
amount += iCfg->yieldBonus.value(res, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GameManager::getBestTileResource(int tx, int ty, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const
|
||||||
|
{
|
||||||
|
const CityConfig &cCfg = TerrainYieldManager::instance().getCityConfig();
|
||||||
|
QStringList priority = cCfg.resourcePriority;
|
||||||
|
if (priority.isEmpty()) {
|
||||||
|
priority = {"voedsel", "arbeid", "goud", "kennis", "cultuur", "geloof"};
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, int> yields = getTileYields(tx, ty, mapPoints, numPoints05);
|
||||||
|
QString bestRes = priority.first();
|
||||||
|
int maxYield = -1;
|
||||||
|
|
||||||
|
for (const QString &res : priority) {
|
||||||
|
int y = yields.value(res, 0);
|
||||||
|
if (y > maxYield) {
|
||||||
|
maxYield = y;
|
||||||
|
bestRes = res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bestRes;
|
||||||
|
}
|
||||||
|
|
||||||
CityYieldSummary GameManager::calculateCityYields(const City &city, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const
|
CityYieldSummary GameManager::calculateCityYields(const City &city, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const
|
||||||
{
|
{
|
||||||
CityYieldSummary summary;
|
CityYieldSummary summary;
|
||||||
@@ -270,20 +329,7 @@ CityYieldSummary GameManager::calculateCityYields(const City &city, Matrix2D<Ter
|
|||||||
int ty = pair.first.second;
|
int ty = pair.first.second;
|
||||||
QString assignedRes = pair.second;
|
QString assignedRes = pair.second;
|
||||||
|
|
||||||
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, mapPoints, numPoints05);
|
int amount = getTileYield(tx, ty, assignedRes, mapPoints, numPoints05);
|
||||||
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
|
||||||
if (!yCfg) continue;
|
|
||||||
|
|
||||||
int amount = yCfg->getYield(assignedRes);
|
|
||||||
|
|
||||||
// Add bonus from tile improvements (e.g. farm bonus)
|
|
||||||
const TileImprovement *imp = getImprovementAt(tx, ty);
|
|
||||||
if (imp) {
|
|
||||||
const ImprovementConfig *iCfg = TerrainYieldManager::instance().getImprovementConfig(imp->improvementId);
|
|
||||||
if (iCfg && iCfg->yieldBonus.contains(assignedRes)) {
|
|
||||||
amount += iCfg->yieldBonus.value(assignedRes, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (assignedRes == "voedsel") summary.food += amount;
|
if (assignedRes == "voedsel") summary.food += amount;
|
||||||
else if (assignedRes == "arbeid") summary.labor += amount;
|
else if (assignedRes == "arbeid") summary.labor += amount;
|
||||||
@@ -636,10 +682,8 @@ void GameManager::commandBuildCitySelected(Matrix2D<TerrainPoint> *mapPoints, in
|
|||||||
QVector3D(w.x(), w.y(), gz),
|
QVector3D(w.x(), w.y(), gz),
|
||||||
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
||||||
|
|
||||||
// Assign initial worker to center tile
|
// Assign initial worker to center tile with best yield resource
|
||||||
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, mapPoints, numPoints05);
|
QString defRes = getBestTileResource(tx, ty, mapPoints, numPoints05);
|
||||||
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
|
||||||
QString defRes = yCfg ? yCfg->primaryResource : "voedsel";
|
|
||||||
newCity.assignWorker(tx, ty, defRes);
|
newCity.assignWorker(tx, ty, defRes);
|
||||||
|
|
||||||
m_cities.push_back(newCity);
|
m_cities.push_back(newCity);
|
||||||
@@ -1084,9 +1128,7 @@ void GameManager::processUnitActionQueue(Unit &unit, Matrix2D<TerrainPoint> *map
|
|||||||
QVector3D(w.x(), w.y(), gz),
|
QVector3D(w.x(), w.y(), gz),
|
||||||
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
cCfg.initialInhabitants, cCfg.inhabitantsPerPop, cCfg.initialBorderRadius);
|
||||||
|
|
||||||
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, mapPoints, numPoints05);
|
QString defRes = getBestTileResource(tx, ty, mapPoints, numPoints05);
|
||||||
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
|
||||||
QString defRes = yCfg ? yCfg->primaryResource : "voedsel";
|
|
||||||
newCity.assignWorker(tx, ty, defRes);
|
newCity.assignWorker(tx, ty, defRes);
|
||||||
|
|
||||||
m_cities.push_back(newCity);
|
m_cities.push_back(newCity);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "player.h"
|
#include "player.h"
|
||||||
#include "unitconfig.h"
|
#include "unitconfig.h"
|
||||||
#include "buildingconfig.h"
|
#include "buildingconfig.h"
|
||||||
|
#include "roadconfig.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "city.h"
|
#include "city.h"
|
||||||
#include "matrix2d.h"
|
#include "matrix2d.h"
|
||||||
@@ -48,6 +49,15 @@ struct TileImprovement {
|
|||||||
QVector3D worldPos;
|
QVector3D worldPos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TileRoad {
|
||||||
|
QString roadTypeId = "dirt";
|
||||||
|
int tileX = 0;
|
||||||
|
int tileY = 0;
|
||||||
|
int playerId = 1;
|
||||||
|
QVector3D worldPos;
|
||||||
|
unsigned char connectionMask = 0; // bit e (0..5) indicates connected across edge e
|
||||||
|
};
|
||||||
|
|
||||||
struct FloatingText {
|
struct FloatingText {
|
||||||
QString text;
|
QString text;
|
||||||
QVector3D worldPos;
|
QVector3D worldPos;
|
||||||
@@ -100,6 +110,10 @@ public:
|
|||||||
CityYieldSummary calculateCityYields(const City &city, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const;
|
CityYieldSummary calculateCityYields(const City &city, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const;
|
||||||
void processTickYields(Matrix2D<TerrainPoint> *mapPoints, int numPoints05);
|
void processTickYields(Matrix2D<TerrainPoint> *mapPoints, int numPoints05);
|
||||||
|
|
||||||
|
QMap<QString, int> getTileYields(int tx, int ty, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const;
|
||||||
|
int getTileYield(int tx, int ty, const QString &res, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const;
|
||||||
|
QString getBestTileResource(int tx, int ty, Matrix2D<TerrainPoint> *mapPoints, int numPoints05) const;
|
||||||
|
|
||||||
bool isTileOwned(int tx, int ty, int *outOwnerCityId = nullptr) const;
|
bool isTileOwned(int tx, int ty, int *outOwnerCityId = nullptr) const;
|
||||||
bool buyTileForCity(int cityId, int tx, int ty);
|
bool buyTileForCity(int cityId, int tx, int ty);
|
||||||
|
|
||||||
|
|||||||
+316
-24
@@ -72,6 +72,12 @@ QSceneRenderer::QSceneRenderer(QWidget* parent): QOpenGLWidget(parent)
|
|||||||
QTimer *animTimer = new QTimer(this);
|
QTimer *animTimer = new QTimer(this);
|
||||||
connect(animTimer, &QTimer::timeout, this, QOverload<>::of(&QSceneRenderer::update));
|
connect(animTimer, &QTimer::timeout, this, QOverload<>::of(&QSceneRenderer::update));
|
||||||
animTimer->start(16);
|
animTimer->start(16);
|
||||||
|
|
||||||
|
m_slotLongPressTimer = new QTimer(this);
|
||||||
|
m_slotLongPressTimer->setSingleShot(true);
|
||||||
|
connect(m_slotLongPressTimer, &QTimer::timeout, this, [this]() {
|
||||||
|
onSlotLongPressTimeout();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSceneRenderer::loadCameraConfig()
|
void QSceneRenderer::loadCameraConfig()
|
||||||
@@ -1354,15 +1360,10 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
|||||||
if (yCfg && yCfg->workable) {
|
if (yCfg && yCfg->workable) {
|
||||||
// Tile has 1 slot!
|
// Tile has 1 slot!
|
||||||
bool isWorked = city->isTileWorked(hx, hy);
|
bool isWorked = city->isTileWorked(hx, hy);
|
||||||
QString res = isWorked ? city->getWorkedResource(hx, hy) : yCfg->primaryResource;
|
QString bestRes = GameManager::instance().getBestTileResource(hx, hy, m_point, m_numPoints05);
|
||||||
int amount = yCfg->getYield(res);
|
QString res = city->getEffectiveResource(hx, hy, bestRes);
|
||||||
|
int amount = GameManager::instance().getTileYield(hx, hy, res, m_point, m_numPoints05);
|
||||||
const TileImprovement *imp = GameManager::instance().getImprovementAt(hx, hy);
|
const TileImprovement *imp = GameManager::instance().getImprovementAt(hx, hy);
|
||||||
if (imp) {
|
|
||||||
const ImprovementConfig *iCfg = TerrainYieldManager::instance().getImprovementConfig(imp->improvementId);
|
|
||||||
if (iCfg && iCfg->yieldBonus.contains(res)) {
|
|
||||||
amount += iCfg->yieldBonus.value(res, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float slotR = 15.0f;
|
float slotR = 15.0f;
|
||||||
QRect slotRect((int)(sCenter.x() - slotR), (int)(sCenter.y() - slotR), (int)(slotR * 2), (int)(slotR * 2));
|
QRect slotRect((int)(sCenter.x() - slotR), (int)(sCenter.y() - slotR), (int)(slotR * 2), (int)(slotR * 2));
|
||||||
@@ -1373,6 +1374,24 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
|||||||
painter.setPen(QPen(isWorked ? QColor(80, 240, 120) : QColor(140, 175, 215), isWorked ? 2.2 : 1.2));
|
painter.setPen(QPen(isWorked ? QColor(80, 240, 120) : QColor(140, 175, 215), isWorked ? 2.2 : 1.2));
|
||||||
painter.drawEllipse(sCenter, slotR, slotR);
|
painter.drawEllipse(sCenter, slotR, slotR);
|
||||||
|
|
||||||
|
// Long-press charging progress ring on the active held slot
|
||||||
|
if (m_slotPressPending && m_pressedSlotTx == hx && m_pressedSlotTy == hy) {
|
||||||
|
int dur = TerrainYieldManager::instance().getCityConfig().slotLongPressDurationMs;
|
||||||
|
float charge = std::min(1.0f, (float)m_slotPressElapsed.elapsed() / (float)std::max(1, dur));
|
||||||
|
QRectF chargeRect(sCenter.x() - (slotR + 3.0f), sCenter.y() - (slotR + 3.0f), (slotR + 3.0f) * 2, (slotR + 3.0f) * 2);
|
||||||
|
painter.setPen(QPen(QColor(255, 220, 80, 230), 2.5));
|
||||||
|
painter.setBrush(Qt::NoBrush);
|
||||||
|
painter.drawArc(chargeRect, 90 * 16, -(int)(charge * 360 * 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active menu highlight ring
|
||||||
|
if (m_resourceMenuOpen && m_resourceMenuTx == hx && m_resourceMenuTy == hy) {
|
||||||
|
QRectF activeMenuRect(sCenter.x() - (slotR + 3.0f), sCenter.y() - (slotR + 3.0f), (slotR + 3.0f) * 2, (slotR + 3.0f) * 2);
|
||||||
|
painter.setPen(QPen(QColor(80, 200, 255, 240), 2.0));
|
||||||
|
painter.setBrush(Qt::NoBrush);
|
||||||
|
painter.drawEllipse(activeMenuRect);
|
||||||
|
}
|
||||||
|
|
||||||
// Resource icon
|
// Resource icon
|
||||||
QImage rIcon = getTintedIcon("images/resources/" + res + ".png", isWorked ? QColor(80, 255, 120) : QColor(180, 210, 245));
|
QImage rIcon = getTintedIcon("images/resources/" + res + ".png", isWorked ? QColor(80, 255, 120) : QColor(180, 210, 245));
|
||||||
painter.drawImage(QRectF(sCenter.x() - 8.5, sCenter.y() - 8.5, 17, 17), rIcon);
|
painter.drawImage(QRectF(sCenter.x() - 8.5, sCenter.y() - 8.5, 17, 17), rIcon);
|
||||||
@@ -1876,6 +1895,188 @@ void QSceneRenderer::drawCityViewOverlay(QPainter &painter, const QMatrix4x4 &vM
|
|||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Resource Selection Popup Menu (if open)
|
||||||
|
if (m_resourceMenuOpen) {
|
||||||
|
drawCityResourceMenu(painter, vMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSceneRenderer::onSlotLongPressTimeout()
|
||||||
|
{
|
||||||
|
if (m_slotPressPending && GameManager::instance().isInCityView()) {
|
||||||
|
m_slotLongPressTriggered = true;
|
||||||
|
m_slotPressPending = false;
|
||||||
|
m_resourceMenuOpen = true;
|
||||||
|
m_resourceMenuTx = m_pressedSlotTx;
|
||||||
|
m_resourceMenuTy = m_pressedSlotTy;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QSceneRenderer::drawCityResourceMenu(QPainter &painter, const QMatrix4x4 &vMatrix)
|
||||||
|
{
|
||||||
|
m_cityResourceChoiceHits.clear();
|
||||||
|
m_resourceMenuCloseBtnRect = QRect();
|
||||||
|
m_resourceMenuRect = QRect();
|
||||||
|
|
||||||
|
City *city = GameManager::instance().getActiveCityView();
|
||||||
|
if (!city) {
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tx = m_resourceMenuTx;
|
||||||
|
int ty = m_resourceMenuTy;
|
||||||
|
if (!city->ownsTile(tx, ty)) {
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector2D center = Pathfinder::hexToWorld(tx, ty);
|
||||||
|
float gz = Unit::getTerrainHeight(center.x(), center.y(), m_point, m_numPoints05);
|
||||||
|
bool inFront = false;
|
||||||
|
QPointF sCenter = UnitRenderer::projectToScreen(QVector3D(center.x(), center.y(), gz + 0.05f), Projection, vMatrix, width(), height(), inFront);
|
||||||
|
if (!inFront) return;
|
||||||
|
|
||||||
|
QString tType = TerrainYieldManager::instance().getTerrainType(tx, ty, m_point, m_numPoints05);
|
||||||
|
const TerrainYieldConfig *yCfg = TerrainYieldManager::instance().getYieldConfig(tType);
|
||||||
|
QString tName = yCfg ? yCfg->name : tType;
|
||||||
|
const TileImprovement *imp = GameManager::instance().getImprovementAt(tx, ty);
|
||||||
|
if (imp) {
|
||||||
|
const ImprovementConfig *iCfg = TerrainYieldManager::instance().getImprovementConfig(imp->improvementId);
|
||||||
|
if (iCfg) {
|
||||||
|
tName += QString(" (%1)").arg(iCfg->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CityConfig &cCfg = TerrainYieldManager::instance().getCityConfig();
|
||||||
|
QStringList resources = cCfg.resourcePriority;
|
||||||
|
if (resources.isEmpty()) {
|
||||||
|
resources = {"voedsel", "arbeid", "goud", "kennis", "cultuur", "geloof"};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString bestRes = GameManager::instance().getBestTileResource(tx, ty, m_point, m_numPoints05);
|
||||||
|
QString activeRes = city->getEffectiveResource(tx, ty, bestRes);
|
||||||
|
|
||||||
|
int menuW = 240;
|
||||||
|
int rowH = 32;
|
||||||
|
int headerH = 46;
|
||||||
|
int footerH = 10;
|
||||||
|
int menuH = headerH + (resources.size() * rowH) + footerH;
|
||||||
|
|
||||||
|
// Anchor menu near sCenter
|
||||||
|
int menuX = (int)sCenter.x() + 24;
|
||||||
|
int menuY = (int)sCenter.y() - menuH / 2;
|
||||||
|
if (menuX + menuW > width() - 15) {
|
||||||
|
menuX = (int)sCenter.x() - menuW - 24;
|
||||||
|
}
|
||||||
|
if (menuX < 15) menuX = 15;
|
||||||
|
if (menuY + menuH > height() - 15) {
|
||||||
|
menuY = height() - 15 - menuH;
|
||||||
|
}
|
||||||
|
if (menuY < 15) menuY = 15;
|
||||||
|
|
||||||
|
m_resourceMenuRect = QRect(menuX, menuY, menuW, menuH);
|
||||||
|
|
||||||
|
// Connecting line from slot to menu card
|
||||||
|
painter.setPen(QPen(QColor(80, 200, 255, 120), 1.5, Qt::DashLine));
|
||||||
|
painter.drawLine(sCenter, QPointF(menuX < sCenter.x() ? menuX + menuW : menuX, menuY + menuH / 2));
|
||||||
|
|
||||||
|
// Drop shadow
|
||||||
|
painter.setBrush(QColor(0, 0, 0, 160));
|
||||||
|
painter.setPen(Qt::NoPen);
|
||||||
|
painter.drawRoundedRect(m_resourceMenuRect.adjusted(4, 4, 4, 4), 8, 8);
|
||||||
|
|
||||||
|
// Card background
|
||||||
|
painter.setBrush(QColor(16, 22, 32, 250));
|
||||||
|
painter.setPen(QPen(QColor(80, 180, 240), 1.6));
|
||||||
|
painter.drawRoundedRect(m_resourceMenuRect, 8, 8);
|
||||||
|
|
||||||
|
// Header Title
|
||||||
|
painter.setFont(QFont("sans-serif", 9, QFont::Bold));
|
||||||
|
painter.setPen(QColor(240, 248, 255));
|
||||||
|
QString title = Localization::instance().get("ui.city.select_resource", "SELECT RESOURCE");
|
||||||
|
painter.drawText(QRect(menuX + 12, menuY + 6, menuW - 40, 18), Qt::AlignLeft | Qt::AlignVCenter, title);
|
||||||
|
|
||||||
|
// Close button [X]
|
||||||
|
m_resourceMenuCloseBtnRect = QRect(menuX + menuW - 26, menuY + 6, 20, 18);
|
||||||
|
painter.setFont(QFont("sans-serif", 9, QFont::Bold));
|
||||||
|
painter.setPen(QColor(180, 190, 205));
|
||||||
|
painter.drawText(m_resourceMenuCloseBtnRect, Qt::AlignCenter, "×");
|
||||||
|
|
||||||
|
// Subtitle (tile info)
|
||||||
|
painter.setFont(QFont("sans-serif", 7));
|
||||||
|
painter.setPen(QColor(140, 170, 200));
|
||||||
|
painter.drawText(QRect(menuX + 12, menuY + 24, menuW - 24, 16), Qt::AlignLeft | Qt::AlignVCenter, tName);
|
||||||
|
|
||||||
|
// Divider line
|
||||||
|
painter.setPen(QPen(QColor(50, 75, 105), 1.0));
|
||||||
|
painter.drawLine(menuX + 10, menuY + 44, menuX + menuW - 10, menuY + 44);
|
||||||
|
|
||||||
|
// Rows
|
||||||
|
int currY = menuY + headerH;
|
||||||
|
for (const QString &res : resources) {
|
||||||
|
int yieldVal = GameManager::instance().getTileYield(tx, ty, res, m_point, m_numPoints05);
|
||||||
|
bool isActive = (res == activeRes);
|
||||||
|
bool isBest = (res == bestRes);
|
||||||
|
|
||||||
|
QRect rowRect(menuX + 8, currY, menuW - 16, rowH - 4);
|
||||||
|
m_cityResourceChoiceHits.push_back({rowRect, res, yieldVal});
|
||||||
|
|
||||||
|
bool isHovered = rowRect.contains(m_mouseCurrentPos);
|
||||||
|
|
||||||
|
// Row background
|
||||||
|
if (isActive) {
|
||||||
|
painter.setBrush(QColor(30, 65, 45, 240));
|
||||||
|
painter.setPen(QPen(QColor(80, 240, 120), 1.4));
|
||||||
|
} else if (isHovered) {
|
||||||
|
painter.setBrush(QColor(40, 60, 85, 230));
|
||||||
|
painter.setPen(QPen(QColor(100, 190, 255), 1.2));
|
||||||
|
} else {
|
||||||
|
painter.setBrush(QColor(22, 30, 42, 210));
|
||||||
|
painter.setPen(QPen(QColor(45, 60, 80), 1.0));
|
||||||
|
}
|
||||||
|
painter.drawRoundedRect(rowRect, 5, 5);
|
||||||
|
|
||||||
|
// Resource icon
|
||||||
|
QColor iconColor;
|
||||||
|
if (res == "voedsel") iconColor = QColor(90, 255, 130);
|
||||||
|
else if (res == "arbeid") iconColor = QColor(255, 160, 60);
|
||||||
|
else if (res == "goud") iconColor = QColor(255, 215, 60);
|
||||||
|
else if (res == "kennis") iconColor = QColor(80, 180, 255);
|
||||||
|
else if (res == "cultuur") iconColor = QColor(225, 110, 255);
|
||||||
|
else if (res == "geloof") iconColor = QColor(220, 230, 255);
|
||||||
|
else iconColor = QColor(200, 220, 240);
|
||||||
|
|
||||||
|
QImage resIcon = getTintedIcon("images/resources/" + res + ".png", iconColor);
|
||||||
|
painter.drawImage(QRect(rowRect.left() + 6, rowRect.top() + (rowRect.height() - 18) / 2, 18, 18), resIcon);
|
||||||
|
|
||||||
|
// Resource Name
|
||||||
|
QString resName = Localization::instance().get(QString("ui.resources.%1").arg(res), res);
|
||||||
|
painter.setFont(QFont("sans-serif", 8, isHovered || isActive ? QFont::Bold : QFont::Normal));
|
||||||
|
painter.setPen(isActive ? QColor(100, 255, 150) : (isHovered ? QColor(255, 255, 255) : QColor(200, 215, 230)));
|
||||||
|
painter.drawText(QRect(rowRect.left() + 28, rowRect.top(), 80, rowRect.height()), Qt::AlignLeft | Qt::AlignVCenter, resName);
|
||||||
|
|
||||||
|
// Best tag
|
||||||
|
if (isBest) {
|
||||||
|
QRect bestRect(rowRect.left() + 110, rowRect.top() + (rowRect.height() - 14) / 2, 34, 14);
|
||||||
|
painter.setBrush(QColor(80, 65, 20, 220));
|
||||||
|
painter.setPen(QPen(QColor(255, 205, 50), 1.0));
|
||||||
|
painter.drawRoundedRect(bestRect, 3, 3);
|
||||||
|
painter.setFont(QFont("sans-serif", 6, QFont::Bold));
|
||||||
|
painter.setPen(QColor(255, 220, 80));
|
||||||
|
painter.drawText(bestRect, Qt::AlignCenter, Localization::instance().get("ui.city.best_yield", "BEST"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active indicator or yield amount
|
||||||
|
painter.setFont(QFont("sans-serif", 8, QFont::Bold));
|
||||||
|
painter.setPen(isActive ? QColor(80, 255, 120) : (yieldVal > 0 ? QColor(160, 230, 255) : QColor(130, 145, 160)));
|
||||||
|
QString yieldText = QString("+%L1").arg(yieldVal);
|
||||||
|
painter.drawText(QRect(rowRect.right() - 70, rowRect.top(), 64, rowRect.height()), Qt::AlignRight | Qt::AlignVCenter, yieldText);
|
||||||
|
|
||||||
|
currY += rowH;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
||||||
@@ -1884,7 +2085,55 @@ void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
|||||||
if (GameManager::instance().isInCityView()) {
|
if (GameManager::instance().isInCityView()) {
|
||||||
City *city = GameManager::instance().getActiveCityView();
|
City *city = GameManager::instance().getActiveCityView();
|
||||||
|
|
||||||
|
// 0a. Handle Resource Selection Menu clicks (if open)
|
||||||
|
if (m_resourceMenuOpen) {
|
||||||
|
if (m_resourceMenuCloseBtnRect.contains(event->pos())) {
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &choice : m_cityResourceChoiceHits) {
|
||||||
|
if (choice.rect.contains(event->pos())) {
|
||||||
|
if (city) {
|
||||||
|
int tx = m_resourceMenuTx;
|
||||||
|
int ty = m_resourceMenuTy;
|
||||||
|
city->setTilePreferredResource(tx, ty, choice.res);
|
||||||
|
|
||||||
|
QVector2D w = Pathfinder::hexToWorld(tx, ty);
|
||||||
|
float gz = Unit::getTerrainHeight(w.x(), w.y(), m_point, m_numPoints05);
|
||||||
|
QString resName = Localization::instance().get(QString("ui.resources.%1").arg(choice.res), choice.res);
|
||||||
|
|
||||||
|
if (city->isTileWorked(tx, ty)) {
|
||||||
|
// Already working: switch active producing resource
|
||||||
|
QString msg = Localization::instance().get("ui.city.resource_switched", "Producing %1 (+%2)").arg(resName).arg(choice.amount);
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
||||||
|
} else {
|
||||||
|
if (city->getAvailablePop() > 0) {
|
||||||
|
city->assignWorker(tx, ty, choice.res);
|
||||||
|
QString msg = Localization::instance().get("ui.city.worker_assigned_res", "+1 Pop: %1 (+%2)").arg(resName).arg(choice.amount);
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
||||||
|
} else {
|
||||||
|
QString msg = Localization::instance().get("ui.city.resource_preferred", "Slot set to %1 (+%2)").arg(resName).arg(choice.amount);
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 220, 80));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clicked outside resource menu: dismiss popup
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_closeCityViewBtnRect.contains(event->pos())) {
|
if (m_closeCityViewBtnRect.contains(event->pos())) {
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
m_slotPressPending = false;
|
||||||
cameraPosition = m_savedCamPos;
|
cameraPosition = m_savedCamPos;
|
||||||
m_zoom = m_savedZoom;
|
m_zoom = m_savedZoom;
|
||||||
zRot = m_savedZRot;
|
zRot = m_savedZRot;
|
||||||
@@ -1923,25 +2172,18 @@ void QSceneRenderer::mousePressEvent(QMouseEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Slot pressed: initiate long press timer for hold-to-change resource
|
||||||
for (const auto &slot : m_citySlotHits) {
|
for (const auto &slot : m_citySlotHits) {
|
||||||
if (slot.rect.contains(event->pos())) {
|
if (slot.rect.contains(event->pos())) {
|
||||||
if (city) {
|
if (city) {
|
||||||
QVector2D w = Pathfinder::hexToWorld(slot.tx, slot.ty);
|
m_slotPressPending = true;
|
||||||
float gz = Unit::getTerrainHeight(w.x(), w.y(), m_point, m_numPoints05);
|
m_slotLongPressTriggered = false;
|
||||||
if (city->isTileWorked(slot.tx, slot.ty)) {
|
m_pressedSlotTx = slot.tx;
|
||||||
city->unassignWorker(slot.tx, slot.ty);
|
m_pressedSlotTy = slot.ty;
|
||||||
QString msg = Localization::instance().get("ui.city.worker_freed", "Pop worker freed");
|
m_slotPressPos = event->pos();
|
||||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 220, 80));
|
m_slotPressElapsed.start();
|
||||||
} else {
|
int dur = TerrainYieldManager::instance().getCityConfig().slotLongPressDurationMs;
|
||||||
if (city->getAvailablePop() > 0) {
|
m_slotLongPressTimer->start(std::max(100, dur));
|
||||||
city->assignWorker(slot.tx, slot.ty, slot.defaultRes);
|
|
||||||
QString msg = Localization::instance().get("ui.city.worker_assigned", "+1 Pop working");
|
|
||||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
|
||||||
} else {
|
|
||||||
QString msg = Localization::instance().get("ui.city.no_free_pop", "No free Pop!");
|
|
||||||
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 80, 80));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2144,6 +2386,14 @@ void QSceneRenderer::mouseMoveEvent(QMouseEvent *event)
|
|||||||
|
|
||||||
// Disable panning, rotation and minimap drag in City View
|
// Disable panning, rotation and minimap drag in City View
|
||||||
if (GameManager::instance().isInCityView()) {
|
if (GameManager::instance().isInCityView()) {
|
||||||
|
if (m_slotPressPending) {
|
||||||
|
if ((event->pos() - m_slotPressPos).manhattanLength() > 8) {
|
||||||
|
if (m_slotLongPressTimer && m_slotLongPressTimer->isActive()) {
|
||||||
|
m_slotLongPressTimer->stop();
|
||||||
|
}
|
||||||
|
m_slotPressPending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
update();
|
update();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2171,6 +2421,42 @@ void QSceneRenderer::mouseReleaseEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
Q_UNUSED(event);
|
Q_UNUSED(event);
|
||||||
m_draggingMinimap = false;
|
m_draggingMinimap = false;
|
||||||
|
|
||||||
|
if (m_slotLongPressTimer && m_slotLongPressTimer->isActive()) {
|
||||||
|
m_slotLongPressTimer->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_slotPressPending && !m_slotLongPressTriggered) {
|
||||||
|
// Short click on slot! Toggle worker assignment.
|
||||||
|
if (GameManager::instance().isInCityView()) {
|
||||||
|
City *city = GameManager::instance().getActiveCityView();
|
||||||
|
if (city) {
|
||||||
|
int tx = m_pressedSlotTx;
|
||||||
|
int ty = m_pressedSlotTy;
|
||||||
|
QVector2D w = Pathfinder::hexToWorld(tx, ty);
|
||||||
|
float gz = Unit::getTerrainHeight(w.x(), w.y(), m_point, m_numPoints05);
|
||||||
|
if (city->isTileWorked(tx, ty)) {
|
||||||
|
city->unassignWorker(tx, ty);
|
||||||
|
QString msg = Localization::instance().get("ui.city.worker_freed", "Pop worker freed");
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 220, 80));
|
||||||
|
} else {
|
||||||
|
if (city->getAvailablePop() > 0) {
|
||||||
|
QString bestRes = GameManager::instance().getBestTileResource(tx, ty, m_point, m_numPoints05);
|
||||||
|
QString res = city->getEffectiveResource(tx, ty, bestRes);
|
||||||
|
city->assignWorker(tx, ty, res);
|
||||||
|
QString msg = Localization::instance().get("ui.city.worker_assigned", "+1 Pop working");
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(80, 255, 120));
|
||||||
|
} else {
|
||||||
|
QString msg = Localization::instance().get("ui.city.no_free_pop", "No free Pop!");
|
||||||
|
GameManager::instance().addFloatingText(msg, QVector3D(w.x(), w.y(), gz + 0.8f), QColor(255, 80, 80));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_slotPressPending = false;
|
||||||
|
m_slotLongPressTriggered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QSceneRenderer::keyPressEvent(QKeyEvent *e)
|
void QSceneRenderer::keyPressEvent(QKeyEvent *e)
|
||||||
@@ -2178,6 +2464,12 @@ void QSceneRenderer::keyPressEvent(QKeyEvent *e)
|
|||||||
// In City View: disable WASD panning and Q/E rotation; only allow Escape to exit
|
// In City View: disable WASD panning and Q/E rotation; only allow Escape to exit
|
||||||
if (GameManager::instance().isInCityView()) {
|
if (GameManager::instance().isInCityView()) {
|
||||||
if (e->key() == Qt::Key_Escape) {
|
if (e->key() == Qt::Key_Escape) {
|
||||||
|
if (m_resourceMenuOpen) {
|
||||||
|
m_resourceMenuOpen = false;
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_slotPressPending = false;
|
||||||
cameraPosition = m_savedCamPos;
|
cameraPosition = m_savedCamPos;
|
||||||
m_zoom = m_savedZoom;
|
m_zoom = m_savedZoom;
|
||||||
zRot = m_savedZRot;
|
zRot = m_savedZRot;
|
||||||
|
|||||||
@@ -147,6 +147,31 @@ protected:
|
|||||||
int m_cityProjectTab = 0; // 0 = Buildings, 1 = Units
|
int m_cityProjectTab = 0; // 0 = Buildings, 1 = Units
|
||||||
QRect m_tabBuildingsRect;
|
QRect m_tabBuildingsRect;
|
||||||
QRect m_tabUnitsRect;
|
QRect m_tabUnitsRect;
|
||||||
|
|
||||||
|
void drawCityResourceMenu(QPainter &painter, const QMatrix4x4 &vMatrix);
|
||||||
|
void onSlotLongPressTimeout();
|
||||||
|
|
||||||
|
// Slot Long Press & Resource Selection Menu State
|
||||||
|
bool m_slotPressPending = false;
|
||||||
|
bool m_slotLongPressTriggered = false;
|
||||||
|
int m_pressedSlotTx = -1;
|
||||||
|
int m_pressedSlotTy = -1;
|
||||||
|
QPoint m_slotPressPos;
|
||||||
|
QElapsedTimer m_slotPressElapsed;
|
||||||
|
QTimer *m_slotLongPressTimer = nullptr;
|
||||||
|
|
||||||
|
bool m_resourceMenuOpen = false;
|
||||||
|
int m_resourceMenuTx = -1;
|
||||||
|
int m_resourceMenuTy = -1;
|
||||||
|
QRect m_resourceMenuRect;
|
||||||
|
QRect m_resourceMenuCloseBtnRect;
|
||||||
|
|
||||||
|
struct CityResourceChoiceHit {
|
||||||
|
QRect rect;
|
||||||
|
QString res;
|
||||||
|
int amount;
|
||||||
|
};
|
||||||
|
std::vector<CityResourceChoiceHit> m_cityResourceChoiceHits;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QSCENERENDERER_H
|
#endif // QSCENERENDERER_H
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ bool TerrainYieldManager::loadConfigs(const QString &baseDir)
|
|||||||
m_cityConfig.initialNationalResources[it.key()] = it.value().asInt(0);
|
m_cityConfig.initialNationalResources[it.key()] = it.value().asInt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_cityConfig.slotLongPressDurationMs = cityRoot["slot_long_press_duration_ms"].asInt(400);
|
||||||
|
|
||||||
|
if (cityRoot.hasChild("resource_priority") && !cityRoot["resource_priority"].listValues.isEmpty()) {
|
||||||
|
m_cityConfig.resourcePriority = cityRoot["resource_priority"].listValues;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Load terrain_yields.yaml
|
// 2. Load terrain_yields.yaml
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ struct CityConfig {
|
|||||||
int tileCultureCost;
|
int tileCultureCost;
|
||||||
float foodToInhabitantsRatio;
|
float foodToInhabitantsRatio;
|
||||||
|
|
||||||
|
int slotLongPressDurationMs;
|
||||||
|
QStringList resourcePriority;
|
||||||
|
|
||||||
QMap<QString, int> baseYields;
|
QMap<QString, int> baseYields;
|
||||||
QMap<QString, int> initialNationalResources;
|
QMap<QString, int> initialNationalResources;
|
||||||
|
|
||||||
@@ -43,7 +46,9 @@ struct CityConfig {
|
|||||||
initialBorderRadius(1), maxWorkableRadius(3), defaultTileSlots(1),
|
initialBorderRadius(1), maxWorkableRadius(3), defaultTileSlots(1),
|
||||||
cityViewZoom(4.8f),
|
cityViewZoom(4.8f),
|
||||||
baseResourceYieldPerTick(500), tileCultureCost(10000),
|
baseResourceYieldPerTick(500), tileCultureCost(10000),
|
||||||
foodToInhabitantsRatio(1.0f)
|
foodToInhabitantsRatio(1.0f),
|
||||||
|
slotLongPressDurationMs(400),
|
||||||
|
resourcePriority({"voedsel", "arbeid", "goud", "kennis", "cultuur", "geloof"})
|
||||||
{
|
{
|
||||||
baseYields["voedsel"] = 500;
|
baseYields["voedsel"] = 500;
|
||||||
baseYields["arbeid"] = 500;
|
baseYields["arbeid"] = 500;
|
||||||
|
|||||||
Reference in New Issue
Block a user