From 4fa5f46575e545437ab774c97f9dc88ec304251d Mon Sep 17 00:00:00 2001 From: Paweł Redman Date: Wed, 25 Apr 2018 17:52:18 +0200 Subject: Remake rockets into grenades. --- src/game/assets.cpp | 4 +- src/game/game.cpp | 31 ++++---------- src/game/game.hpp | 26 ++++++++---- src/game/grenade.cpp | 103 ++++++++++++++++++++++++++++++++++++++++++++++ src/game/rocket.cpp | 84 ------------------------------------- src/game/unit_soldier.cpp | 16 +++++++ 6 files changed, 150 insertions(+), 114 deletions(-) create mode 100644 src/game/grenade.cpp delete mode 100644 src/game/rocket.cpp (limited to 'src') diff --git a/src/game/assets.cpp b/src/game/assets.cpp index 99ef734..d9f9740 100644 --- a/src/game/assets.cpp +++ b/src/game/assets.cpp @@ -43,7 +43,7 @@ void load(void) soldier.legs_walking.load("assets/units/soldier/legs_walking", 2, 2); soldier.dead.load("assets/units/soldier/dead_", 1); soldier.gibbing.load("assets/units/soldier/gibbing_", 3); - soldier.rocket.load("assets/units/soldier/rocket_", 4); + soldier.grenade.load("assets/units/soldier/grenade_", 1); soldier.avatar.load("assets/units/soldier/avatar_", 1); soldier.fire.load("assets/units/soldier/fire.ogg"); @@ -51,6 +51,8 @@ void load(void) soldier.pain.load("assets/units/soldier/pain.ogg"); soldier.death.load("assets/units/soldier/death1.ogg"); soldier.death.load("assets/units/soldier/death2.ogg"); + soldier.grenade_bounce.load("assets/fx/grenade_bounce1.ogg"); + soldier.grenade_bounce.load("assets/fx/grenade_bounce2.ogg"); soldier.step_stone.load("assets/units/soldier/step_stone_1.ogg"); soldier.step_stone.load("assets/units/soldier/step_stone_2.ogg"); diff --git a/src/game/game.cpp b/src/game/game.cpp index f6fa420..2ad7f05 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -180,7 +180,7 @@ void state_t::select(rectf_t rect, int type) enum { COMMAND_MOVE, COMMAND_FIRE, - COMMAND_FIRE_ROCKET, + COMMAND_THROW_GRENADE, COMMAND_STOP, COMMAND_REPL_SOLDIER, @@ -195,7 +195,7 @@ enum { bool state_t::populate_pie_menu(std::vector &items) { - bool soldiers = false, repls = false, rockets = false, + bool soldiers = false, repls = false, grenades = false, scientists = false, builders = false; items.clear(); @@ -210,8 +210,8 @@ bool state_t::populate_pie_menu(std::vector &items) switch (unit->type) { case unit_t::UNIT_SOLDIER: soldiers = true; - if (!dynamic_cast(unit)->rocket_fired) - rockets = true; + if (unit->storage.grenades) + grenades = true; break; case unit_t::UNIT_SCIENTIST: @@ -237,8 +237,8 @@ bool state_t::populate_pie_menu(std::vector &items) if (soldiers) { items.push_back((interface::pie_item_t){"Fire", COMMAND_FIRE}); - if (rockets) - items.push_back((interface::pie_item_t){"Fire a rocket", COMMAND_FIRE_ROCKET}); + if (grenades) + items.push_back((interface::pie_item_t){"Throw a grenade", COMMAND_THROW_GRENADE}); } if (scientists) @@ -283,22 +283,9 @@ static void command_soldier(unit_soldier_t *soldier, v2f_t x, int number) soldier->say("Feuer!", false); break; - case COMMAND_FIRE_ROCKET: - { - v2f_t from, v; - rocket_t *rocket; - - if (soldier->rocket_fired) { - soldier->say("Keine Raketen!"); - break; - } - - soldier->rocket_fired = true; - - from = soldier->x + v2f_t(0, -0.5); - rocket = new rocket_t(soldier->game, from, x, soldier); - rocket->place(&soldier->game->world, from); - } + case COMMAND_THROW_GRENADE: + soldier->command_throw_grenade(x); + break; } } diff --git a/src/game/game.hpp b/src/game/game.hpp index 31001f7..50f903b 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -199,10 +199,12 @@ namespace game { render::oriented_sprite_4M_t body_aiming, body_firing; render::oriented_sprite_4M2_t legs_idle, legs_walking; render::animated_texture_t dead, gibbing; - render::animated_texture_t rocket; render::animated_texture_t avatar; audio::sound_t fire, step_stone, step_dirt, pain, death; + + render::animated_texture_t grenade; + audio::sound_t grenade_bounce; } soldier_assets_t; typedef struct { @@ -301,6 +303,10 @@ namespace game { unit_t *find_target(world::world_t *world, v2f_t x, float r, bool friendly); + typedef struct { + size_t grenades, max_grenades = 0; + } storage_t; + class unit_t : public entity_t { protected: double next_targetting = -INFINITY; @@ -362,6 +368,8 @@ namespace game { bool have_target = false; + storage_t storage; + std::string say_text; double say_time = -INFINITY; void say(std::string str, bool on_interface=true); @@ -383,8 +391,6 @@ namespace game { bool manual_firing = false; v2f_t manual_firing_target; - bool rocket_fired = false; - void check_area(void); void shoot(v2f_t from, v2f_t at, int damage); void fire_shotgun(v2f_t aim); @@ -402,6 +408,8 @@ namespace game { void on_wake(void) {}; void on_damage(unit_t *attacker); void on_death(void); + + void command_throw_grenade(v2f_t at); }; class unit_scientist_t : public unit_t { @@ -638,13 +646,17 @@ namespace game { void damage(int points, unit_t *attacker); }; - class rocket_t : public game::entity_t { + class grenade_t : public game::entity_t { unit_t *shooter; - v2f_t target, v; - std::unique_ptr aim_marker; + v2f_t v; + float z, v_z; + + ntime_t explosion_time; + + void compute_bounds(void); public: - rocket_t(game::state_t *game, v2f_t x_, v2f_t target_, unit_t *shooter_); + grenade_t(game::state_t *game, v2f_t x_, v2f_t target, unit_t *shooter_); void render_to(render::state_t *render); void render_late_to(render::state_t *render) {}; diff --git a/src/game/grenade.cpp b/src/game/grenade.cpp new file mode 100644 index 0000000..e6a44c9 --- /dev/null +++ b/src/game/grenade.cpp @@ -0,0 +1,103 @@ +/* +This file is part of Minitrem. + +Minitrem is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +Minitrem is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Minitrem. If not, see . +*/ + +#include "game.hpp" + +namespace game { + +void grenade_t::compute_bounds(void) +{ + v2f_t x_p3d; + + x_p3d = x + v2f_t(0.0f, -0.3f * z); + cmodel.bounds[0] = x_p3d - size[0]; + cmodel.bounds[1] = x_p3d - size[1]; + render_bounds[0] = x_p3d - render_size[0]; + render_bounds[1] = x_p3d - render_size[1]; +} + +grenade_t::grenade_t(game::state_t *game, v2f_t x_, v2f_t target, unit_t *shooter_) : entity_t(game, ET_ROCKET) +{ + x = x_; + v = (target - x) * 1.5f; + + z = 0.7f; + v_z = 5.0f; + + size = rectf_t(v2f_t(-0.1f, -0.1f), v2f_t(0.1f, 0.1f)); + render_size = size; + cmodel.cflags = CF_BACKGROUND; + + explosion_time = game->time + SEC(3); + + wake(); +} + +void grenade_t::on_spawn(void) +{ +} + +void grenade_t::on_think(void) +{ + v2f_t end; + world::trace_t trace; + + if (game->time >= explosion_time) { + cmodel.ignore = true; + game->explosion(x); + delete this; + return; + } + + if (z + pow(v_z, 2) < 0.01f) + return; + + end = x + v * game->dt; + + trace = world->ray_v_all(x, end, CF_SOLID, shooter); + x = trace.end; + + v_z += -10.0f * game->dt; + z += v_z * game->dt; + if (z < 0.0f) { + trace = world->ray_v_tiles(x, x, CF_WATER); + if (trace.hit) { + fx_bullet_miss_t *bullet_miss; + + bullet_miss = new fx_bullet_miss_t(game, trace.end, true); + bullet_miss->place(world); + + delete this; + return; + } + + z *= -1.0f; + v_z *= -0.4f; + + assets::soldier.grenade_bounce.play_3d(x); + } + + compute_bounds(); + place(world); +} + +void grenade_t::render_to(render::state_t *render) +{ + render->render(game->now, &assets::soldier.grenade, render_bounds); +} + +} \ No newline at end of file diff --git a/src/game/rocket.cpp b/src/game/rocket.cpp deleted file mode 100644 index ccdc788..0000000 --- a/src/game/rocket.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -This file is part of Minitrem. - -Minitrem is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) any later version. - -Minitrem is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Minitrem. If not, see . -*/ - -#include "game.hpp" - -namespace game { - -const v2f_t rocket_radius(1.0f, 1.0f); - -rocket_t::rocket_t(game::state_t *game, v2f_t x_, v2f_t target_, unit_t *shooter_) : entity_t(game, ET_ROCKET) -{ - x = x_; - target = target_; - v = (target - x).norm() * 10.0f; - shooter = shooter_; - - size = rectf_t(v2f_t(-0.1f, -0.1f), v2f_t(0.1f, 0.1f)); - render_size = size; - cmodel.cflags = CF_BACKGROUND; - - wake(); -} - -void rocket_t::on_spawn(void) -{ - aim_marker = std::make_unique(game, target); -} - -void rocket_t::on_think(void) -{ - float Ds, ds; - v2f_t end; - world::trace_t trace; - - Ds = (target - x) * v.norm(); - ds = v.len() * game->dt; - - if (Ds > ds) { - end = x + v * game->dt; - trace = world->ray_v_all(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, shooter); - } else { - end = target; - trace = world->ray_v_all_p3d(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, -1, this); - } - - if (trace.hit) { - if (trace.tile && trace.tile->type == TILE_WATER) { - fx_bullet_miss_t *bullet_miss; - - bullet_miss = new fx_bullet_miss_t(game, trace.end, true); - bullet_miss->place(world); - } else { - cmodel.ignore = true; - game->explosion(trace.end); - } - - delete this; - return; - } - - x = trace.end; - place(world, x); -} - -void rocket_t::render_to(render::state_t *render) -{ - render->render(game->now, &assets::soldier.rocket, render_bounds); -} - -} \ No newline at end of file diff --git a/src/game/unit_soldier.cpp b/src/game/unit_soldier.cpp index c8e46d0..1e34d7c 100644 --- a/src/game/unit_soldier.cpp +++ b/src/game/unit_soldier.cpp @@ -57,6 +57,7 @@ unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER) controllable = true; health = max_health = 28; + storage.grenades = 3; } static v2f_t spread_aim(v2f_t x, v2f_t aim, float cof, procgen::prng_t *prng) @@ -225,6 +226,21 @@ void unit_soldier_t::on_death(void) aim_marker.reset(); } +void unit_soldier_t::command_throw_grenade(v2f_t at) +{ + grenade_t *grenade; + + if (!storage.grenades) { + say("Keine Granaten!"); + return; + } + + storage.grenades--; + + grenade = new grenade_t(game, x, at, this); + grenade->place(&game->world); +} + void unit_soldier_t::render_to(render::state_t *render) { sf::Color selection_color; -- cgit