summaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
Diffstat (limited to 'sim')
-rw-r--r--sim/include/kurator/sim/ai.h9
-rw-r--r--sim/src/BaseSimulation.cpp2
-rw-r--r--sim/src/Builder.cpp2
-rw-r--r--sim/src/ai.cpp69
-rw-r--r--sim/src/ai.h2
-rw-r--r--sim/src/sim.cpp6
6 files changed, 73 insertions, 17 deletions
diff --git a/sim/include/kurator/sim/ai.h b/sim/include/kurator/sim/ai.h
index f9899d6..0ffa1cc 100644
--- a/sim/include/kurator/sim/ai.h
+++ b/sim/include/kurator/sim/ai.h
@@ -1,9 +1,13 @@
#pragma once
+#include <functional>
+
#include <entt/entt.hpp>
#include <kurator/engine/Point.h>
+#include "State.h"
+
namespace kurator
{
@@ -11,9 +15,12 @@ namespace sim
{
+using Action = std::function<void()>;
+
+
struct AIShip
{
- double keep_at_range;
+ Action action;
engine::Point destination;
entt::entity target = entt::null;
};
diff --git a/sim/src/BaseSimulation.cpp b/sim/src/BaseSimulation.cpp
index b1add54..2731c67 100644
--- a/sim/src/BaseSimulation.cpp
+++ b/sim/src/BaseSimulation.cpp
@@ -24,7 +24,7 @@ void
BaseSimulation::operator()(State& ctx)
{
pick_random_targets(ctx, manager);
- keep_at_range(ctx);
+ take_actions(ctx);
FloatingMovement::update(ctx);
update_turrets(ctx);
shoot_at_targets(ctx);
diff --git a/sim/src/Builder.cpp b/sim/src/Builder.cpp
index 4cf0bc6..2b2bd24 100644
--- a/sim/src/Builder.cpp
+++ b/sim/src/Builder.cpp
@@ -42,7 +42,7 @@ Builder::operator()(const universe::ShipType& ship_type, const int team) const
ship_type.max_speed,
ship_type.max_speed * 2.0,
ship_type.max_speed * 3.0);
- registry.emplace<AIShip>(entity, 15000.0, Point{0.0, 0.0});
+ registry.emplace<AIShip>(entity);
registry.emplace<HitPoints>(entity, ship_type);
return entity;
}
diff --git a/sim/src/ai.cpp b/sim/src/ai.cpp
index 1f2a4ec..7a0f637 100644
--- a/sim/src/ai.cpp
+++ b/sim/src/ai.cpp
@@ -1,5 +1,10 @@
#include "ai.h"
+#include <algorithm>
+#include <utility>
+
+#include <entt/entt.hpp>
+
#include <kurator/sim/components.h>
#include <kurator/sim/State.h>
#include <kurator/sim/weapons.h>
@@ -13,6 +18,42 @@ namespace sim
{
+static double find_worst_range(State& ctx, entt::entity ship);
+
+
+class KeepAtRange
+{
+public:
+ KeepAtRange(State& ctx_, AIShip& ai_, entt::entity self_, entt::entity target_, double distance_) :
+ ctx {ctx_},
+ ai {ai_},
+ self {std::move(self_)},
+ target {std::move(target_)},
+ distance {distance_}
+ {
+ }
+
+ void operator()()
+ {
+ if (!ctx.registry.valid(target)) {
+ if (ctx.registry.valid(ai.target))
+ ai.action = KeepAtRange(ctx, ai, self, ai.target, distance);
+ return;
+ }
+ const auto here = ctx.registry.get<Transform>(self).position;
+ const auto there = ctx.registry.get<Transform>(target).position;
+ const auto offset = there - here;
+ ai.destination = there - offset.normalized().scale(distance);
+ }
+private:
+ State& ctx;
+ AIShip& ai;
+ entt::entity self;
+ entt::entity target;
+ double distance;
+};
+
+
void
pick_random_targets(State& ctx, TeamManager& manager)
{
@@ -20,20 +61,19 @@ pick_random_targets(State& ctx, TeamManager& manager)
for (auto&& [entity, team, ai] : view.each()) {
if (!ctx.registry.valid(ai.target))
ai.target = manager.random(team.id);
+ if (!ai.action)
+ ai.action = KeepAtRange(ctx, ai, entity, ai.target, find_worst_range(ctx, entity));
}
}
void
-keep_at_range(State& ctx)
+take_actions(State& ctx)
{
- auto view = ctx.registry.view<Transform, AIShip>();
- for (auto&& [entity, self, ai] : view.each()) {
- if (!ctx.registry.valid(ai.target))
- continue;
- const auto target = ctx.registry.get<Transform>(ai.target);
- const auto offset = target.position - self.position;
- ai.destination = target.position - offset.normalized().scale(ai.keep_at_range);
+ auto view = ctx.registry.view<AIShip>();
+ for (auto&& [_, ai] : view.each()) {
+ if (ai.action)
+ ai.action();
}
}
@@ -56,5 +96,18 @@ shoot_at_targets(State& ctx)
}
+double
+find_worst_range(State& ctx, entt::entity ship)
+{
+ double range = 20000.0;
+ auto turrets = ctx.registry.view<Turret>();
+ for (const auto& [_, turret] : turrets.each()) {
+ if (turret.owner == ship)
+ range = std::min(range, turret.type.optimal_range);
+ }
+ return range;
+}
+
+
} // namespace sim
} // namespace kurator
diff --git a/sim/src/ai.h b/sim/src/ai.h
index 9173891..d1e9c29 100644
--- a/sim/src/ai.h
+++ b/sim/src/ai.h
@@ -13,7 +13,7 @@ namespace sim
void pick_random_targets(State& ctx, TeamManager& manager);
-void keep_at_range(State& ctx);
+void take_actions(State& ctx);
void shoot_at_targets(State& ctx);
diff --git a/sim/src/sim.cpp b/sim/src/sim.cpp
index 740e6af..879f7fb 100644
--- a/sim/src/sim.cpp
+++ b/sim/src/sim.cpp
@@ -1,7 +1,6 @@
#include <kurator/sim.h>
#include <kurator/campaign/Scenario.h>
-#include <kurator/sim/ai.h>
#include <kurator/sim/State.h>
#include <kurator/sim/System.h>
#include <kurator/universe/UniqueIdentifier.h>
@@ -26,11 +25,8 @@ load_scenario(const campaign::Scenario& scenario)
for (const auto& ship : scenario.ships) {
const auto entity = build(ship.loadout.type, ship.team);
ctx.registry.emplace<universe::UniqueIdentifier>(entity, ship.identifier);
- auto& state = ctx.registry.get<AIShip>(entity);
- for (const auto& turret_type : ship.loadout.turrets) {
+ for (const auto& turret_type : ship.loadout.turrets)
build(turret_type, entity);
- state.keep_at_range = std::min(state.keep_at_range, turret_type.optimal_range);
- }
}
return ctx;
}