summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAki <please@ignore.pl>2023-04-23 12:54:14 +0200
committerAki <please@ignore.pl>2024-04-05 19:41:19 +0200
commit975339d07aeb193564221adff31b55a913d92a1e (patch)
tree957b37e922e494780874bbc8e495a1a5e412fb76
parentbdfb27ba04528f213dcadc00afdcf1f35a61f6fc (diff)
downloadkurator-975339d07aeb193564221adff31b55a913d92a1e.zip
kurator-975339d07aeb193564221adff31b55a913d92a1e.tar.gz
kurator-975339d07aeb193564221adff31b55a913d92a1e.tar.bz2
Separated Turret from AI, shuffled their units
-rw-r--r--kurator/src/inspect.cpp57
-rw-r--r--sim/CMakeLists.txt3
-rw-r--r--sim/include/kurator/sim/TurretControl.h25
-rw-r--r--sim/include/kurator/sim/ai.h23
-rw-r--r--sim/include/kurator/sim/components.h8
-rw-r--r--sim/include/kurator/sim/weapons.h31
-rw-r--r--sim/src/BaseSimulation.cpp7
-rw-r--r--sim/src/Builder.cpp8
-rw-r--r--sim/src/FloatingMovement.cpp3
-rw-r--r--sim/src/TurretControl.cpp72
-rw-r--r--sim/src/ai.cpp60
-rw-r--r--sim/src/ai.h21
-rw-r--r--sim/src/sim.cpp4
-rw-r--r--sim/src/systems.cpp25
-rw-r--r--sim/src/systems.h2
-rw-r--r--sim/src/weapons.cpp81
16 files changed, 261 insertions, 169 deletions
diff --git a/kurator/src/inspect.cpp b/kurator/src/inspect.cpp
index ea70baf..38f5394 100644
--- a/kurator/src/inspect.cpp
+++ b/kurator/src/inspect.cpp
@@ -6,12 +6,12 @@
#include <imgui.h>
#include <raylib.h>
+#include <kurator/sim/ai.h>
#include <kurator/sim/components.h>
#include <kurator/sim/FloatingMovement.h>
#include <kurator/sim/HitPoints.h>
-#include <kurator/sim/TurretControl.h>
+#include <kurator/sim/weapons.h>
#include <kurator/universe/ShipType.h>
-#include <kurator/universe/TurretType.h>
#include <kurator/universe/UniqueIdentifier.h>
#include "Controller.h"
@@ -51,10 +51,10 @@ InspectionWindow::show()
ImGui::PushID(it - selected.begin());
inspect<universe::UniqueIdentifier>(*it);
inspect<universe::ShipType>(*it);
- inspect<universe::TurretType>(*it);
inspect<sim::FloatingMovement>(*it);
inspect<sim::HitPoints>(*it);
- inspect<sim::AIState>(*it);
+ inspect<sim::AIShip>(*it);
+ inspect<sim::Turret>(*it);
inspect<TurretVisuals>(*it);
inspect<AIVisuals>(*it);
it = std::next(it);
@@ -76,7 +76,7 @@ InspectionWindow::select(entt::handle entity)
return;
entity.get<Selectable>().active = true;
auto* registry = entity.registry();
- auto turrets = registry->view<sim::TurretControl>();
+ auto turrets = registry->view<sim::Turret>();
entity.emplace<AIVisuals>();
selected.push_back(std::move(entity));
for (auto&& [entity_, turret] : turrets.each()) {
@@ -131,21 +131,26 @@ slider_double(const char* label, double* value, double minimum, double maximum,
template <>
void
-inspect(entt::handle&, universe::TurretType& type)
-{
- ImGui::Text("Turret: %s", type.name.c_str());
- ImGui::Text("DPS: %.1f", type.damage_per_second());
- ImGui::Text("Eff. Range: %.1f", type.effective_range());
- ImGui::SliderInt("Rounds", &type.rounds, 0, 50);
- slider_double("Base Damage", &type.base_damage, 0, 1000.0, "%.1f");
- slider_double("Rate of Fire", &type.rate_of_fire, 0, 60.0, "%.3f");
- slider_double("Reload", &type.reload, 0, 60.0, "%.3f");
- slider_double("Optimal Range", &type.optimal_range, 0, 30000.0, "%.1f");
- slider_double("Falloff Modifier", &type.falloff_modifier, 0, 5.0, "%.3f");
- slider_double("Falloff Intensity", &type.falloff_intensity, 0, 1.0, "%.3f");
- slider_double("Tracking", &type.tracking, 0, 1000.0, "%.1f");
- slider_double("Tracking Factor", &type.tracking_factor, 0, 10.0, "%.3f");
- slider_double("Tracking Exponent", &type.tracking_exponent, 0, 2.0, "%.3f");
+inspect(entt::handle&, sim::Turret& turret)
+{
+ ImGui::Text("Turret: %s", turret.type.name.c_str());
+ ImGui::Text("DPS: %.1f", turret.type.damage_per_second());
+ ImGui::Text("Eff. Range: %.1f", turret.type.effective_range());
+ ImGui::Text("Current");
+ ImGui::SliderInt("Rounds##current", &turret.rounds, 0, turret.type.rounds);
+ slider_double("Delay", &turret.delay, 0, turret.type.rate_of_fire, "%.3f");
+ slider_double("Reload##current", &turret.reload, 0, turret.type.reload, "%.3f");
+ ImGui::Text("Base");
+ ImGui::SliderInt("Rounds##base", &turret.type.rounds, 0, 50);
+ slider_double("Base Damage", &turret.type.base_damage, 0, 1000.0, "%.1f");
+ slider_double("Rate of Fire", &turret.type.rate_of_fire, 0, 60.0, "%.3f");
+ slider_double("Reload##base", &turret.type.reload, 0, 60.0, "%.3f");
+ slider_double("Optimal Range", &turret.type.optimal_range, 0, 30000.0, "%.1f");
+ slider_double("Falloff Modifier", &turret.type.falloff_modifier, 0, 5.0, "%.3f");
+ slider_double("Falloff Intensity", &turret.type.falloff_intensity, 0, 1.0, "%.3f");
+ slider_double("Tracking", &turret.type.tracking, 0, 1000.0, "%.1f");
+ slider_double("Tracking Factor", &turret.type.tracking_factor, 0, 10.0, "%.3f");
+ slider_double("Tracking Exponent", &turret.type.tracking_exponent, 0, 2.0, "%.3f");
}
@@ -171,7 +176,7 @@ inspect(entt::handle&, sim::HitPoints& points)
template <>
void
-inspect(entt::handle&, sim::AIState& ai)
+inspect(entt::handle&, sim::AIShip& ai)
{
ImGui::InputDouble("Keep At Range", &ai.keep_at_range, 0, 0, "%.1f");
}
@@ -201,14 +206,14 @@ static constexpr Color EFFECTIVE {0x77, 0x50, 0x22, 0xff};
void
draw_turret_visuals(const sim::State& ctx)
{
- const auto helpers = ctx.registry.view<TurretVisuals, universe::TurretType, sim::TurretControl>();
- for (const auto& [entity, visuals, type, turret] : helpers.each()) {
+ const auto helpers = ctx.registry.view<TurretVisuals, sim::Turret>();
+ for (const auto& [entity, visuals, turret] : helpers.each()) {
if (!visuals.visible || !ctx.registry.valid(turret.owner))
continue;
const auto& transform = ctx.registry.get<sim::Transform>(turret.owner);
const auto center = ctx.camera.to_screen(transform.position);
- const auto optimal = type.optimal_range * ctx.camera.scale;
- const auto effective = type.effective_range() * ctx.camera.scale;
+ const auto optimal = turret.type.optimal_range * ctx.camera.scale;
+ const auto effective = turret.type.effective_range() * ctx.camera.scale;
DrawCircleLines(center.x, center.y, optimal, OPTIMAL);
DrawCircleLines(center.x, center.y, effective, EFFECTIVE);
}
@@ -222,7 +227,7 @@ static constexpr Color TARGET {0x44, 0x22, 0x66, 0xff};
void
draw_ai_visuals(const sim::State& ctx)
{
- const auto visuals = ctx.registry.view<AIVisuals, sim::AIState, sim::Transform>();
+ const auto visuals = ctx.registry.view<AIVisuals, sim::AIShip, sim::Transform>();
for (const auto& [entity, visuals, ai, transform] : visuals.each()) {
const auto start = ctx.camera.to_screen(transform.position);
if (visuals.show_target && ctx.registry.valid(ai.target)) {
diff --git a/sim/CMakeLists.txt b/sim/CMakeLists.txt
index 9713d96..f5af416 100644
--- a/sim/CMakeLists.txt
+++ b/sim/CMakeLists.txt
@@ -1,6 +1,7 @@
project(sim)
add_library(
${PROJECT_NAME} STATIC
+ src/ai.cpp
src/BaseSimulation.cpp
src/Builder.cpp
src/FloatingMovement.cpp
@@ -9,7 +10,7 @@ add_library(
src/sim.cpp
src/systems.cpp
src/TeamManager.cpp
- src/TurretControl.cpp
+ src/weapons.cpp
)
target_include_directories(
${PROJECT_NAME}
diff --git a/sim/include/kurator/sim/TurretControl.h b/sim/include/kurator/sim/TurretControl.h
deleted file mode 100644
index ecafb90..0000000
--- a/sim/include/kurator/sim/TurretControl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#pragma once
-
-#include <entt/entt.hpp>
-
-#include "State.h"
-
-
-namespace kurator
-{
-namespace sim
-{
-
-
-struct TurretControl
-{
- double delay;
- double reload;
- int rounds;
- entt::entity owner;
- static void update(State& ctx);
-};
-
-
-} // namespace sim
-} // namespace kurator
diff --git a/sim/include/kurator/sim/ai.h b/sim/include/kurator/sim/ai.h
new file mode 100644
index 0000000..f9899d6
--- /dev/null
+++ b/sim/include/kurator/sim/ai.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <entt/entt.hpp>
+
+#include <kurator/engine/Point.h>
+
+
+namespace kurator
+{
+namespace sim
+{
+
+
+struct AIShip
+{
+ double keep_at_range;
+ engine::Point destination;
+ entt::entity target = entt::null;
+};
+
+
+} // namespace sim
+} // namespace kurator
diff --git a/sim/include/kurator/sim/components.h b/sim/include/kurator/sim/components.h
index f329c0e..c4d8abc 100644
--- a/sim/include/kurator/sim/components.h
+++ b/sim/include/kurator/sim/components.h
@@ -25,13 +25,5 @@ struct Team
};
-struct AIState
-{
- double keep_at_range;
- engine::Point destination;
- entt::entity target = entt::null;
-};
-
-
} // namespace sim
} // namespace kurator
diff --git a/sim/include/kurator/sim/weapons.h b/sim/include/kurator/sim/weapons.h
new file mode 100644
index 0000000..7dd5b3b
--- /dev/null
+++ b/sim/include/kurator/sim/weapons.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <entt/entt.hpp>
+
+#include <kurator/universe/TurretType.h>
+
+#include "State.h"
+
+
+namespace kurator
+{
+namespace sim
+{
+
+
+struct Turret
+{
+ entt::entity owner;
+ universe::TurretType type;
+ double delay = 0.0;
+ double reload = 0.0;
+ int rounds = type.rounds;
+ void shoot_at(State& ctx, const entt::entity& target, double distance);
+};
+
+
+void update_turrets(State& ctx);
+
+
+} // namespace sim
+} // namespace kurator
diff --git a/sim/src/BaseSimulation.cpp b/sim/src/BaseSimulation.cpp
index 545e9ce..b1add54 100644
--- a/sim/src/BaseSimulation.cpp
+++ b/sim/src/BaseSimulation.cpp
@@ -2,10 +2,10 @@
#include <kurator/sim/State.h>
#include <kurator/sim/FloatingMovement.h>
-#include <kurator/sim/TurretControl.h>
+#include <kurator/sim/weapons.h>
+#include "ai.h"
#include "systems.h"
-#include "TeamManager.h"
namespace kurator
@@ -26,7 +26,8 @@ BaseSimulation::operator()(State& ctx)
pick_random_targets(ctx, manager);
keep_at_range(ctx);
FloatingMovement::update(ctx);
- TurretControl::update(ctx);
+ update_turrets(ctx);
+ shoot_at_targets(ctx);
kill_off_dead(ctx);
manager.update(ctx);
}
diff --git a/sim/src/Builder.cpp b/sim/src/Builder.cpp
index af19974..4cf0bc6 100644
--- a/sim/src/Builder.cpp
+++ b/sim/src/Builder.cpp
@@ -3,10 +3,11 @@
#include <entt/entt.hpp>
#include <kurator/engine/Point.h>
+#include <kurator/sim/ai.h>
#include <kurator/sim/components.h>
#include <kurator/sim/FloatingMovement.h>
#include <kurator/sim/HitPoints.h>
-#include <kurator/sim/TurretControl.h>
+#include <kurator/sim/weapons.h>
#include <kurator/universe/ShipType.h>
#include <kurator/universe/TurretType.h>
@@ -41,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<AIState>(entity, 15000.0, Point{0.0, 0.0});
+ registry.emplace<AIShip>(entity, 15000.0, Point{0.0, 0.0});
registry.emplace<HitPoints>(entity, ship_type);
return entity;
}
@@ -51,8 +52,7 @@ entt::entity
Builder::operator()(const universe::TurretType& turret_type, const entt::entity& owner) const
{
const auto entity = registry.create();
- registry.emplace<universe::TurretType>(entity, turret_type);
- registry.emplace<TurretControl>(entity, 0.0, 0.0, turret_type.rounds, owner);
+ registry.emplace<Turret>(entity, owner, turret_type);
registry.emplace<Transform>(entity, Point{0.0, 0.0}, 0.0, owner);
return entity;
}
diff --git a/sim/src/FloatingMovement.cpp b/sim/src/FloatingMovement.cpp
index 39ec17c..4aebb9b 100644
--- a/sim/src/FloatingMovement.cpp
+++ b/sim/src/FloatingMovement.cpp
@@ -1,5 +1,6 @@
#include <kurator/sim/FloatingMovement.h>
+#include <kurator/sim/ai.h>
#include <kurator/sim/components.h>
#include <kurator/sim/State.h>
@@ -13,7 +14,7 @@ namespace sim
void
FloatingMovement::update(State& ctx)
{
- auto view = ctx.registry.view<Transform, FloatingMovement, AIState>();
+ auto view = ctx.registry.view<Transform, FloatingMovement, AIShip>();
for (auto&& [entity, transform, movement, ai] : view.each()) {
const auto offset = ai.destination - transform.position;
const auto at_destination = offset.magnitude() > movement.destination_boundary;
diff --git a/sim/src/TurretControl.cpp b/sim/src/TurretControl.cpp
deleted file mode 100644
index 51f2a46..0000000
--- a/sim/src/TurretControl.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include <kurator/sim/TurretControl.h>
-
-#include <kurator/sim/components.h>
-#include <kurator/sim/FloatingMovement.h>
-#include <kurator/sim/HitPoints.h>
-#include <kurator/sim/events.h>
-#include <kurator/sim/State.h>
-#include <kurator/universe/TurretType.h>
-
-
-namespace kurator
-{
-namespace sim
-{
-
-
-bool consume(float& dt, double& target);
-
-
-void
-TurretControl::update(State& ctx)
-{
- auto view = ctx.registry.view<TurretControl, universe::TurretType>();
- for (auto&& [entity, control, def] : view.each()) {
- if (!ctx.registry.valid(control.owner)) {
- ctx.registry.destroy(entity);
- continue;
- }
- if (!ctx.registry.all_of<AIState, Transform>(control.owner))
- continue;
- const auto& [state, transform] = ctx.registry.get<AIState, Transform>(control.owner);
- if (!ctx.registry.valid(state.target))
- continue;
- const auto& target = ctx.registry.get<Transform>(state.target);
- const auto distance = transform.position.distance(target.position);
- if (distance > def.effective_range())
- continue;
- auto remaining_dt = ctx.clock.dt;
- while (remaining_dt > 0.0) {
- if (control.rounds < 1 && consume(remaining_dt, control.reload))
- control.rounds = def.rounds;
- if (control.rounds > 0 && consume(remaining_dt, control.delay)) {
- auto& target_points = ctx.registry.get<HitPoints>(state.target);
- const auto& movement = ctx.registry.get<FloatingMovement>(state.target);
- auto damage = def.effective_damage(distance, movement.speed.magnitude());
- if (damage > 0.0) {
- damage = target_points.deal(damage);
- ctx.dispatcher.trigger(Hit{damage, control.owner, state.target});
- }
- control.delay = def.rate_of_fire;
- if (--control.rounds < 1)
- control.reload = def.reload;
- }
- }
- }
-}
-
-
-bool
-consume(float& dt, double& target)
-{
- if (target <= 0.0)
- return true;
- const auto _dt = dt;
- dt -= target;
- target -= _dt;
- return target <= 0.0;
-}
-
-
-} // namespace sim
-} // namespace kurator
diff --git a/sim/src/ai.cpp b/sim/src/ai.cpp
new file mode 100644
index 0000000..1f2a4ec
--- /dev/null
+++ b/sim/src/ai.cpp
@@ -0,0 +1,60 @@
+#include "ai.h"
+
+#include <kurator/sim/components.h>
+#include <kurator/sim/State.h>
+#include <kurator/sim/weapons.h>
+
+#include "TeamManager.h"
+
+
+namespace kurator
+{
+namespace sim
+{
+
+
+void
+pick_random_targets(State& ctx, TeamManager& manager)
+{
+ auto view = ctx.registry.view<Team, AIShip>();
+ for (auto&& [entity, team, ai] : view.each()) {
+ if (!ctx.registry.valid(ai.target))
+ ai.target = manager.random(team.id);
+ }
+}
+
+
+void
+keep_at_range(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);
+ }
+}
+
+
+void
+shoot_at_targets(State& ctx)
+{
+ auto view = ctx.registry.view<Turret>();
+ for (auto&& [entity, turret] : view.each()) {
+ if (!ctx.registry.all_of<AIShip, Transform>(turret.owner))
+ continue;
+ const auto& [state, transform] = ctx.registry.get<AIShip, Transform>(turret.owner);
+ if (!ctx.registry.valid(state.target))
+ continue;
+ const auto& target = ctx.registry.get<Transform>(state.target);
+ const auto distance = transform.position.distance(target.position);
+ if (distance <= turret.type.effective_range())
+ turret.shoot_at(ctx, state.target, distance); // passing distance here is wrong
+ }
+}
+
+
+} // namespace sim
+} // namespace kurator
diff --git a/sim/src/ai.h b/sim/src/ai.h
new file mode 100644
index 0000000..9173891
--- /dev/null
+++ b/sim/src/ai.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <kurator/sim/ai.h> // Propagate public header to users since both are sim/ai.h
+#include <kurator/sim/State.h>
+
+#include "TeamManager.h"
+
+
+namespace kurator
+{
+namespace sim
+{
+
+
+void pick_random_targets(State& ctx, TeamManager& manager);
+void keep_at_range(State& ctx);
+void shoot_at_targets(State& ctx);
+
+
+} // namespace sim
+} // namespace kurator
diff --git a/sim/src/sim.cpp b/sim/src/sim.cpp
index 4cb7467..740e6af 100644
--- a/sim/src/sim.cpp
+++ b/sim/src/sim.cpp
@@ -1,7 +1,7 @@
#include <kurator/sim.h>
#include <kurator/campaign/Scenario.h>
-#include <kurator/sim/components.h>
+#include <kurator/sim/ai.h>
#include <kurator/sim/State.h>
#include <kurator/sim/System.h>
#include <kurator/universe/UniqueIdentifier.h>
@@ -26,7 +26,7 @@ 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<AIState>(entity);
+ auto& state = ctx.registry.get<AIShip>(entity);
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);
diff --git a/sim/src/systems.cpp b/sim/src/systems.cpp
index c6f997a..ce4a6b4 100644
--- a/sim/src/systems.cpp
+++ b/sim/src/systems.cpp
@@ -15,31 +15,6 @@ namespace sim
void
-pick_random_targets(State& ctx, TeamManager& manager)
-{
- auto view = ctx.registry.view<Team, AIState>();
- for (auto&& [entity, team, ai] : view.each()) {
- if (!ctx.registry.valid(ai.target))
- ai.target = manager.random(team.id);
- }
-}
-
-
-void
-keep_at_range(State& ctx)
-{
- auto view = ctx.registry.view<Transform, AIState>();
- 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);
- }
-}
-
-
-void
kill_off_dead(State& ctx)
{
auto view = ctx.registry.view<HitPoints>();
diff --git a/sim/src/systems.h b/sim/src/systems.h
index 396ebb2..2ec9ba4 100644
--- a/sim/src/systems.h
+++ b/sim/src/systems.h
@@ -11,8 +11,6 @@ namespace sim
{
-void pick_random_targets(State& ctx, TeamManager& manager);
-void keep_at_range(State& ctx);
void kill_off_dead(State& ctx);
diff --git a/sim/src/weapons.cpp b/sim/src/weapons.cpp
new file mode 100644
index 0000000..bd130dc
--- /dev/null
+++ b/sim/src/weapons.cpp
@@ -0,0 +1,81 @@
+#include <kurator/sim/weapons.h>
+
+#include <entt/entt.hpp>
+
+#include <kurator/sim/events.h>
+#include <kurator/sim/FloatingMovement.h>
+#include <kurator/sim/HitPoints.h>
+#include <kurator/sim/State.h>
+#include <kurator/universe/TurretType.h>
+
+
+namespace kurator
+{
+namespace sim
+{
+
+
+static bool consume(float& dt, double& target);
+static bool reload_(float& dt, Turret& turret);
+
+
+void
+Turret::shoot_at(State& ctx, const entt::entity& target, const double distance)
+{
+ float remaining_dt = ctx.clock.dt;
+ while (reload_(remaining_dt, *this)) {
+ auto& target_points = ctx.registry.get<HitPoints>(target);
+ const auto& movement = ctx.registry.get<FloatingMovement>(target);
+ auto damage = type.effective_damage(distance, movement.speed.magnitude());
+ if (damage > 0.0) {
+ damage = target_points.deal(damage);
+ ctx.dispatcher.trigger(Hit{damage, owner, target});
+ }
+ delay = type.rate_of_fire;
+ if (--rounds < 1)
+ reload = type.reload;
+ }
+}
+
+
+void
+update_turrets(State& ctx)
+{
+ auto turrets = ctx.registry.view<Turret>();
+ for (auto&& [entity, turret] : turrets.each()) {
+ if (!ctx.registry.valid(turret.owner)) {
+ ctx.registry.destroy(entity);
+ continue;
+ }
+ float remaining_dt = ctx.clock.dt;
+ while (remaining_dt > 0.0) {
+ if (reload_(remaining_dt, turret))
+ break;
+ }
+ }
+}
+
+
+bool
+consume(float& dt, double& target)
+{
+ if (target <= 0.0)
+ return true;
+ const auto _dt = dt;
+ dt -= target;
+ target -= _dt;
+ return target <= 0.0;
+}
+
+
+bool
+reload_(float& dt, Turret& turret) // at this point move it to the class?
+{
+ if (turret.rounds < 1 && consume(dt, turret.reload))
+ turret.rounds = turret.type.rounds;
+ return turret.rounds > 0 && consume(dt, turret.delay);
+}
+
+
+} // namespace sim
+} // namespace kurator