#include "game.hpp" namespace game { size_t selection_cookie = 1; entity_t::entity_t(game::state_t *game_, int type_) : world::entity_t(type_) { game = game_; } entity_t::~entity_t(void) { } void entity_t::destroy(void) { unlink(); game->awake_entities.erase(this); delete this; } void entity_t::place(world::world_t *world_) { bool do_spawn = false; if (!world) do_spawn = true; link(world_); if (do_spawn) on_spawn(); if (!ignore_waking) wake(); } void entity_t::place(world::world_t *world, v2f_t x_) { x = x_; cmodel.bounds = size + x; render_bounds = render_size + x; place(world); } void entity_t::wake(void) { awake = true; wake_time = game->now; game->awake_entities.insert(this); if (!ignore_waking) on_wake(); } void entity_t::sleep(void) { awake = false; game->awake_entities.erase(this); } void state_t::start(void) { unit_soldier_t *soldier; world.generator = worldgen; world.generator_data = (void*)this; soldier = new unit_soldier_t(this); soldier->place(&world, v2f_t(0.5, 0.5)); soldier = new unit_soldier_t(this); soldier->place(&world, v2f_t(1.5, 0.5)); soldier = new unit_soldier_t(this); soldier->place(&world, v2f_t(2.5, 0.5)); } void state_t::stop(void) { } void state_t::select(rectf_t x) { size_t old_cookie = selection_cookie; selection_cookie++; selected_units.clear(); for (world::entity_t *ent : world.get_render_entities(x)) { unit_t *unit; if (ent->type != ET_UNIT) continue; unit = (unit_t*)ent; if (!unit->controllable) continue; if (!unit->dead && unit->selected != old_cookie) unit->say(text::get(text::SAY_READY)); unit->selected = selection_cookie; selected_units.insert(unit); } } void state_t::command(v2f_t x) { v2f_t snap; snap[0] = std::round(x[0] - 0.5f) + 0.5f; snap[1] = std::round(x[1] - 0.5f) + 0.5f; for (unit_t *unit : selected_units) { if (unit->dead) continue; if (!unit->start_moving(snap, CF_SOLID | CF_WATER)) unit->say(text::get(text::SAY_NO_PATH)); else unit->say(text::get(text::SAY_MOVING)); } } void state_t::tick(double now_, double dt_) { union { double d; uint32_t i; } u; if (paused) return; dt = dt_; now += dt; // FIXME: Is this non-deterministic enough? u.d = now; dice_prng.seed(dice_prng.next() ^ u.i); u.d = dt; dice_prng.seed(dice_prng.next() ^ u.i); // NOTE: on_think can erase the entity from awake_entities. for (auto i = awake_entities.begin(); i != awake_entities.end(); ) { auto next = i; next++; (*i)->on_think(); i = next; } } void state_t::wake_everything(v2f_t x, float range) { rectf_t wake_range; wake_range[0] = x - v2f_t(range, range); wake_range[1] = x + v2f_t(range, range); for (world::entity_t *went : world.get_entities(wake_range, -1)) { auto ent = dynamic_cast(went); // WTF? if (!ent) continue; if (ent->ignore_waking) continue; ent->wake_time = now; if (ent->awake) continue; ent->wake(); } } die_t::die_t(size_t sides_) { sides = sides_; } die_t::die_t(size_t count_, size_t sides_) { count = count_; sides = sides_; } die_t::die_t(size_t count_, size_t sides_, size_t bonus_) { count = count_; sides = sides_; bonus = bonus_; } size_t state_t::roll(die_t die) { size_t total = 0; for (size_t i = 0; i < die.count; i++) total += dice_prng.next() % die.sides + 1; return total + die.bonus; } bool load_assets(void) { assets::load(); return true; } } //namespace game