#include "BaseBattle.h" #include #include #include #include #include "Builder.h" namespace kurator { namespace battles { int total_teams_in(const Scenario& scenario); BaseBattle::BaseBattle(const Scenario& scenario) : _registry {}, spawner {total_teams_in(scenario), 2.5, 0.1} { const auto repo = universe::load_sample(); Builder build {_registry, spawner}; for (const auto& ship : scenario.ships) { const auto entity = build(repo->ship_type(ship.type), ship.team); for (const auto& turret_type : ship.turrets) build(repo->turret_type(turret_type), entity); manager.add(ship.team, entity); // registry supports on construction events } } entt::registry& BaseBattle::registry() { return _registry; } void BaseBattle::update(const float dt) { pick_random_targets(); keep_at_range(); floating_movement(dt); turrets(dt); kill_off_dead(); manager.clear(_registry); // registry supports on destructions events } void BaseBattle::pick_random_targets() { auto view = _registry.view(); for (auto&& [entity, team, ai] : view.each()) { if (!_registry.valid(ai.target)) ai.target = manager.random((team.id + 1) % 2); // FIXME } } void BaseBattle::keep_at_range() { auto view = _registry.view(); for (auto&& [entity, self, ai] : view.each()) { if (!_registry.valid(ai.target)) continue; const auto target = _registry.get(ai.target); const Point offset = target.position - self.position; ai.destination = target.position - offset.normalized(); } } void BaseBattle::floating_movement(const float dt) { auto view = _registry.view(); for (auto&& [entity, self, movement, ai] : view.each()) { const double speed = movement.speed * dt; const Point offset = ai.destination - self.position; if (offset.magnitude() > speed) { const Point move = offset.normalized().scale(speed); self.position.x += move.x; self.position.y += move.y; } } } void BaseBattle::turrets(const float dt) { auto view = _registry.view(); for (auto&& [entity, control, def] : view.each()) { if (!_registry.valid(control.owner)) { _registry.destroy(entity); continue; } const auto& [state, transform] = _registry.get(control.owner); // no checks if (!_registry.valid(state.target)) continue; if (control.reload > 0.0) control.reload -= dt; if (control.reload <= 0.0) { auto& target_points = _registry.get(state.target); const auto& target = _registry.get(state.target); const auto distance = transform.position - target.position; if (def.range > distance.magnitude()) target_points.health -= def.base_damage; control.reload = def.rate_of_fire; } } } void BaseBattle::kill_off_dead() { auto view = _registry.view(); for (auto&& [entity, points] : view.each()) { if (points.health <= 0.0) _registry.destroy(entity); } } int total_teams_in(const Scenario& scenario) { int last_team = 0; for (const auto& ship : scenario.ships) { if (ship.team > last_team) last_team = ship.team; } return last_team + 1; } } // namespace battles } // namespace kurator