implement sensor range requirements

This commit is contained in:
2026-04-29 21:01:41 +02:00
parent 58b7cda21c
commit b0320ac117
9 changed files with 178 additions and 30 deletions

View File

@@ -397,6 +397,14 @@ ShipsConfig ConfigLoader::loadShips(const std::string& path)
def.movement.speedFormula = requireFormula(mMt["speed_formula"], file, mPath + ".speed_formula");
}
// Sensor
{
const std::string snsPath = elemPath + ".sensor";
const toml::table& snsTable = requireTable(mt["sensor"], file, snsPath);
toml::table& snsMt = const_cast<toml::table&>(snsTable);
def.sensor.sensorRangeFormula = requireFormula(snsMt["sensor_range_formula"], file, snsPath + ".sensor_range_formula");
}
// Loot
{
const std::string lPath = elemPath + ".loot";

View File

@@ -33,6 +33,11 @@ struct ShipMovement
Formula speedFormula; // REQ-SHP-STATS, REQ-SHP-MOVEMENT
};
struct ShipSensor
{
Formula sensorRangeFormula; // REQ-SHP-SENSOR, REQ-SHP-STATS
};
struct ShipCombat
{
Formula damageFormula;
@@ -69,6 +74,7 @@ struct ShipDef
ShipThreat threat;
ShipHealth health;
ShipMovement movement;
ShipSensor sensor;
ShipLoot loot;
// Role-specific sections. A ship is a combat ship if combat is present,

View File

@@ -41,7 +41,6 @@ struct RepairTool
struct ThreatResponse
{
float engagementRange;
std::optional<EntityId> currentTarget;
};
@@ -78,7 +77,8 @@ struct Ship
QVector2D velocity;
float hp;
float maxHp;
float speedPerTick; // pre-evaluated from speedFormula / kTickRateHz
float speedPerTick; // pre-evaluated from speedFormula / kTickRateHz
float sensorRange; // pre-evaluated from sensorRangeFormula (REQ-SHP-SENSOR)
int level;
std::string schematicId;

View File

@@ -47,6 +47,7 @@ EntityId ShipSystem::spawn(const std::string& schematicId, int level, QVector2D
ship.speedPerTick = static_cast<float>(
def->movement.speedFormula.evaluate(x))
/ static_cast<float>(kTickRateHz);
ship.sensorRange = static_cast<float>(def->sensor.sensorRangeFormula.evaluate(x));
ship.level = level;
ship.schematicId = schematicId;
ship.isEnemy = isEnemy;
@@ -61,9 +62,7 @@ EntityId ShipSystem::spawn(const std::string& schematicId, int level, QVector2D
w.cooldownTicks = 0.0f;
ship.weapon = w;
ThreatResponse tr;
tr.engagementRange = w.range;
ship.threatResponse = tr;
ship.threatResponse = ThreatResponse{};
if (!isEnemy)
{
@@ -241,7 +240,7 @@ void ShipSystem::tickThreatResponse(const BuildingSystem& buildings)
continue;
}
const float range = s.threatResponse->engagementRange;
const float range = s.sensorRange;
if (!s.isEnemy)
{
@@ -394,7 +393,6 @@ void ShipSystem::tickThreatResponse(const BuildingSystem& buildings)
void ShipSystem::tickRepairBehavior(BuildingSystem& buildings)
{
const std::vector<Building> allBuildings = buildings.allBuildings();
const float kPatrolRange = 3.0f; // scan radius relative to repair range
for (Ship& s : m_ships)
{
@@ -410,7 +408,7 @@ void ShipSystem::tickRepairBehavior(BuildingSystem& buildings)
for (const Ship& candidate : m_ships)
{
if (candidate.isEnemy
&& (candidate.position - s.position).length() <= repairRange)
&& (candidate.position - s.position).length() <= s.sensorRange)
{
enemyNearby = true;
break;
@@ -450,7 +448,7 @@ void ShipSystem::tickRepairBehavior(BuildingSystem& buildings)
{
s.repairBehavior->currentTarget = std::nullopt;
currentId = kInvalidEntityId;
float bestDist = repairRange * kPatrolRange;
float bestDist = s.sensorRange;
for (const Ship& candidate : m_ships)
{
@@ -640,8 +638,7 @@ void ShipSystem::tickScrapCollector(ScrapSystem& scraps, const BuildingSystem& b
else
{
// Scan for nearest scrap within sensor range.
const float sensorRange = collectRange * 5.0f;
float bestDist = sensorRange;
float bestDist = s.sensorRange;
std::optional<QVector2D> bestPos;
for (const Scrap& sc : scraps.allScraps())
{