#ifndef UNIT_H #define UNIT_H #include #include #include #include #include #include "unitconfig.h" #include "terrain.h" #include "matrix2d.h" enum class UnitState { Idle, Moving, Attacking, Building }; enum class UnitActionType { None, Move, BuildImprovement, BuildCity, BuildRoad, Attack }; struct UnitAction { UnitActionType type = UnitActionType::None; int targetX = -1; int targetY = -1; int targetUnitId = -1; QString extraData = ""; // e.g. improvementId ("farm") UnitAction() = default; UnitAction(UnitActionType t) : type(t) {} UnitAction(UnitActionType t, int x, int y, const QString &data = "") : type(t), targetX(x), targetY(y), extraData(data) {} UnitAction(UnitActionType t, int targetId) : type(t), targetUnitId(targetId) {} bool isValid() const { return type != UnitActionType::None; } }; class Unit { public: Unit(int uId, int pId, const UnitConfig &cfg, int startX, int startY, float groundZ); int id; int playerId; UnitConfig config; int tileX; int tileY; QVector3D worldPos; float health; float maxHealth; int buildCharges; UnitState state; // Movement Path std::vector> path; size_t pathIndex; float moveProgress; // 0.0 to 1.0 between hexes int targetTileX; int targetTileY; // Action Queue std::deque actionQueue; int maxQueueSize = 5; // Road Construction Route (tile-by-tile road paving) std::vector> roadRoute; size_t roadRouteIndex = 0; bool hasRoadRoute() const { return !roadRoute.empty() && roadRouteIndex < roadRoute.size(); } void startRoadRoute(const std::vector> &route) { roadRoute = route; roadRouteIndex = 0; } void clearRoadRoute() { roadRoute.clear(); roadRouteIndex = 0; } void advanceRoadRouteStep() { if (!roadRoute.empty()) { roadRouteIndex++; } } bool queueAction(const UnitAction &action); void clearActionQueue(); bool hasQueuedAction() const { return !actionQueue.empty(); } bool hasQueuedActionType(UnitActionType type) const; void removeQueuedActionsOfType(UnitActionType type); UnitAction popNextQueuedAction(); const UnitAction* peekNextQueuedAction() const; QString getQueuedActionSummary() const; // Attack cooldown / flash float attackFlashTimer; // Building State float buildProgress; // 0.0 to 1.0 float buildDuration; QString buildingImprovementId; void update(float deltaTime, float tickDuration, float simSpeedMultiplier, Matrix2D *mapPoints, int numPoints05); void setPath(const std::vector> &newPath); void stopMovement(); void startBuilding(const QString &impId, float duration); void cancelBuilding(); bool isBuilding() const { return state == UnitState::Building; } bool isBusy() const { return state == UnitState::Building; } bool canAttack(const Unit &other) const; void performAttack(Unit &target); void takeDamage(float damage); bool isDead() const { return health <= 0.001f; } bool isNaval() const { return config.isNaval(); } bool isLand() const { return config.isLand(); } static float getTerrainHeight(float worldX, float worldY, Matrix2D *mapPoints, int numPoints05); }; #endif // UNIT_H