From 7fe865d745fede7e2628ecf0c91b38bb15154cb3 Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 25 Apr 2018 12:40:23 +0200 Subject: Building mechanic. --- src/game/assets.cpp | 1 + src/game/game.cpp | 28 +++++++++------ src/game/game.hpp | 35 ++++++++++++------- src/game/unit_builder.cpp | 88 +++++++++++++++++++++++++++++++++++++++++++++-- src/game/unit_repl.cpp | 12 +++++-- 5 files changed, 134 insertions(+), 30 deletions(-) (limited to 'src/game') diff --git a/src/game/assets.cpp b/src/game/assets.cpp index d34f312..99ef734 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -94,6 +94,7 @@ void load(void) nest.death.load("assets/units/nest/death.ogg"); repl.idle.load("assets/units/repl/idle_", 4); + repl.unfinished.load("assets/units/repl/unfinished_", 1); repl.avatar.load("assets/units/repl/avatar_", 1); repl.sound.load("assets/units/repl/sound.ogg"); repl.damage.load("assets/units/repl/damage1.ogg"); diff --git a/src/game/game.cpp b/src/game/game.cpp index a19eecc..f6fa420 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -35,7 +35,9 @@ entity_t::entity_t(game::state_t *game_, int type_) : world::entity_t(type_) entity_t::~entity_t(void) { sleep(); - unlink(); + + if (world) + unlink(); } void entity_t::place(world::world_t *world_) @@ -85,6 +87,8 @@ void state_t::start(void) repl = new unit_repl_t(this); repl->place(&world, v2f_t(5.3, 4.2)); + repl->constructed = true; + repl->health = repl->max_health; select_unit(repl, SELECT_NEW); resume(); @@ -185,7 +189,8 @@ enum { COMMAND_GATHER, - COMMAND_REPAIR + COMMAND_REPAIR, + COMMAND_BUILD_REPL }; bool state_t::populate_pie_menu(std::vector &items) @@ -199,7 +204,7 @@ bool state_t::populate_pie_menu(std::vector &items) return false; for (unit_t *unit : selected_units) { - if (unit->dead || !unit->controllable) + if (unit->dead || !unit->controllable || !unit->constructed) continue; switch (unit->type) { @@ -239,8 +244,10 @@ bool state_t::populate_pie_menu(std::vector &items) if (scientists) items.push_back((interface::pie_item_t){"Gather", COMMAND_GATHER}); - if (builders) + if (builders) { items.push_back((interface::pie_item_t){"Repair", COMMAND_REPAIR}); + items.push_back((interface::pie_item_t){"Build a replicator", COMMAND_BUILD_REPL}); + } if (repls) { items.push_back((interface::pie_item_t){"Spawn a soldier", COMMAND_REPL_SOLDIER}); @@ -335,16 +342,15 @@ static void command_builder(unit_builder_t *builder, v2f_t x, int number) break; case COMMAND_STOP: - builder->stop_moving(); - builder->say("Stop.", false); - builder->repair_marker.reset(); + builder->command_stop(); break; case COMMAND_REPAIR: - builder->repairing = true; - builder->repairing_at = x; - builder->repair_marker = std::make_unique(builder->game, x); - builder->say("Idę naprawiać.", false); + builder->command_repair(x); + break; + + case COMMAND_BUILD_REPL: + builder->command_build(x, unit_t::UNIT_REPL); break; } } diff --git a/src/game/game.hpp b/src/game/game.hpp index dbf1e41..31001f7 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -147,7 +147,8 @@ namespace game { bool populate_pie_menu(std::vector &items); void command(v2f_t x, int number); - size_t crystals = 150; + size_t crystals = 9999; + //size_t crystals = 150; }; enum { @@ -170,12 +171,13 @@ namespace game { enum { CF_SURFACE = 1, - CF_BACKGROUND = 2, - CF_SOLID = 4, - CF_BODY = 8, - CF_BODY_SMALL = 16, - CF_WATER = 32, - CF_DECOS = 64 + CF_SURFACE2 = 2, // entities on the surface (FIXME: the name) + CF_BACKGROUND = 4, + CF_SOLID = 8, + CF_BODY = 16, + CF_BODY_SMALL = 32, + CF_WATER = 64, + CF_DECOS = 128 }; enum { @@ -230,7 +232,7 @@ namespace game { } nest_assets_t; typedef struct { - render::animated_texture_t idle, avatar; + render::animated_texture_t idle, unfinished, avatar; audio::sound_t sound, damage; } repl_assets_t; @@ -352,6 +354,9 @@ namespace game { void try_attack(unit_t *target); void die(unit_t *killer); + // FIXME: move buildings to another class + bool constructed = true; + virtual void on_damage(unit_t *attacker) = 0; virtual void on_death(void) = 0; @@ -426,18 +431,18 @@ namespace game { class unit_builder_t : public unit_t { bool gibbed = false; + + bool repairing = false, building; + v2f_t repairing_at; + void repair(void); ntime_t next_repair = 0, last_repair = 0; + std::unique_ptr repair_marker; public: std::unique_ptr move_marker; - std::unique_ptr repair_marker; sf::Color selection_color; - bool repairing = false, repaired; - v2f_t repairing_at; - void repair(void); - unit_builder_t(game::state_t *game_); ~unit_builder_t(void) {}; void render_to(render::state_t *render); @@ -448,6 +453,10 @@ namespace game { void on_wake(void) {}; void on_damage(unit_t *attacker); void on_death(void); + + void command_repair(v2f_t where); + void command_build(v2f_t where, type_t what); + void command_stop(void); }; class unit_spider_t : public unit_t { diff --git a/src/game/unit_builder.cpp b/src/game/unit_builder.cpp index fcb3b90..1ed7f58 100644 --- a/src/game/unit_builder.cpp +++ b/src/game/unit_builder.cpp @@ -51,6 +51,78 @@ unit_builder_t::unit_builder_t(game::state_t *game) : unit_t(game, UNIT_BUILDER) health = max_health = 45; } +void unit_builder_t::command_stop(void) +{ + stop_moving(); + move_marker.reset(); + + repairing = false; + repair_marker.reset(); + + say("Stop.", false); +} + +void unit_builder_t::command_repair(v2f_t where) +{ + repairing = true; + building = false; + repairing_at = where; + repair_marker = std::make_unique(game, where); + say("Idę naprawiać.", false); +} + +void unit_builder_t::command_build(v2f_t where, type_t what) +{ + world::trace_t trace; + unit_t *built; + size_t price; + world::cmodel_t cmodel; + + if ((x - where).len() > 1.3f) { + say("Tak daleko tego nie postawię!"); + return; + } + + trace = world->ray_v_all(x, where, CF_SOLID|CF_WATER|CF_DECOS, this); + if (trace.hit) { + say("Coś stoi mi na drodze."); + return; + } + + switch (what) { + case UNIT_REPL: + built = new unit_repl_t(game); + price = 250; + break; + + default: + abort(); + } + + if (price > game->crystals) { + game->interface.print("Insufficient crystals; " + std::to_string(price - game->crystals) + " more needed"); + delete built; + return; + } + + cmodel.bounds[0] = where + built->size[0]; + cmodel.bounds[1] = where + built->size[1]; + cmodel.cflags = CF_SOLID|CF_SURFACE2|CF_WATER|CF_DECOS; + + if (world->test_rect(&cmodel, nullptr)) { + say("Nie ma tutaj miejsca."); + delete built; + return; + } + + game->crystals -= price; + built->place(world, where); + + repairing = true; + building = true; + repairing_at = where; +} + void unit_builder_t::repair(void) { rectf_t rect; @@ -66,7 +138,7 @@ void unit_builder_t::repair(void) if (next_repair && next_repair > game->time) return; - trace = game->world.ray_v_all_p3d(x, repairing_at, CF_SOLID, CF_SURFACE, this); + trace = game->world.ray_v_all_p3d(x, repairing_at, CF_SOLID, CF_SURFACE2, this); if (!trace.hit || !trace.ent || trace.ent->type != ET_UNIT) { repairing = false; return; @@ -79,7 +151,11 @@ void unit_builder_t::repair(void) } if (!game->crystals) { - say("Nie mam czym naprawiać!"); + game->interface.print("Insufficient crystals; 1 more needed."); + if (building) + say("Nie mam czym konstruować!", false); + else + say("Nie mam czym naprawiać!", false); return; } @@ -89,7 +165,13 @@ void unit_builder_t::repair(void) if (unit->max_health - unit->health < 3) { repairing = false; unit->health = unit->max_health; - say("Naprawa ukończona."); + unit->constructed = true; + + if (building) + say("Budowa zakończona."); + else + say("Naprawa ukończona."); + } else unit->health += 2; diff --git a/src/game/unit_repl.cpp b/src/game/unit_repl.cpp index ddea8b0..2e0c3fd 100644 --- a/src/game/unit_repl.cpp +++ b/src/game/unit_repl.cpp @@ -25,14 +25,16 @@ unit_repl_t::unit_repl_t(game::state_t *game_) : unit_t(game_, UNIT_REPL) size[1] = {+0.4f, +0.4f}; render_size = size; render_layer = render::LAYER_FLAT; - cmodel.cflags = CF_SURFACE; + cmodel.cflags = CF_SURFACE2; name = "Replicator"; ignore_waking = false; - health = max_health = 35; + max_health = 35; + health = 5; friendly = true; controllable = true; + constructed = false; } void unit_repl_t::on_damage(unit_t *attacker) @@ -48,7 +50,11 @@ void unit_repl_t::on_death(void) void unit_repl_t::render_to(render::state_t *render) { - render->render(game->now, &assets::repl.idle, render_bounds); + if (constructed) + render->render(game->now, &assets::repl.idle, render_bounds); + else + render->render(game->now, &assets::repl.unfinished, render_bounds); + unit_t::render_to(render); } -- cgit