summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--LICENSE1
-rw-r--r--Makefile2
-rw-r--r--assets/fx/grenade_bounce1.oggbin0 -> 5468 bytes
-rw-r--r--assets/fx/grenade_bounce2.oggbin0 -> 4774 bytes
-rw-r--r--assets/units/soldier/grenade_0.pngbin0 -> 886 bytes
-rw-r--r--assets/units/soldier/rocket_0.pngbin403 -> 0 bytes
-rw-r--r--assets/units/soldier/rocket_1.pngbin528 -> 0 bytes
-rw-r--r--assets/units/soldier/rocket_2.pngbin565 -> 0 bytes
-rw-r--r--assets/units/soldier/rocket_3.pngbin607 -> 0 bytes
-rw-r--r--src/game/assets.cpp4
-rw-r--r--src/game/game.cpp31
-rw-r--r--src/game/game.hpp26
-rw-r--r--src/game/grenade.cpp103
-rw-r--r--src/game/rocket.cpp84
-rw-r--r--src/game/unit_soldier.cpp16
15 files changed, 152 insertions, 115 deletions
diff --git a/LICENSE b/LICENSE
index 25df008..a67007f 100644
--- a/LICENSE
+++ b/LICENSE
@@ -24,6 +24,7 @@ FILE
assets/ambience/wind.ogg
assets/fx/corpse_hit.ogg
assets/fx/gibbing.ogg
+assets/fx/grenade_bounce*.ogg
assets/fx/ricochet.ogg
assets/units/nest/*.ogg
assets/units/repl/damage*.ogg
diff --git a/Makefile b/Makefile
index 3280034..7eea551 100644
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,7 @@ SRC := src/game/assets.cpp \
src/game/game.cpp \
src/game/interface.cpp \
src/game/pseudostate.cpp \
- src/game/rocket.cpp \
+ src/game/grenade.cpp \
src/game/units.cpp \
src/game/unit_builder.cpp \
src/game/unit_nest.cpp \
diff --git a/assets/fx/grenade_bounce1.ogg b/assets/fx/grenade_bounce1.ogg
new file mode 100644
index 0000000..80006d6
--- /dev/null
+++ b/assets/fx/grenade_bounce1.ogg
Binary files differ
diff --git a/assets/fx/grenade_bounce2.ogg b/assets/fx/grenade_bounce2.ogg
new file mode 100644
index 0000000..aed17f3
--- /dev/null
+++ b/assets/fx/grenade_bounce2.ogg
Binary files differ
diff --git a/assets/units/soldier/grenade_0.png b/assets/units/soldier/grenade_0.png
new file mode 100644
index 0000000..2da4b15
--- /dev/null
+++ b/assets/units/soldier/grenade_0.png
Binary files differ
diff --git a/assets/units/soldier/rocket_0.png b/assets/units/soldier/rocket_0.png
deleted file mode 100644
index 2417aef..0000000
--- a/assets/units/soldier/rocket_0.png
+++ /dev/null
Binary files differ
diff --git a/assets/units/soldier/rocket_1.png b/assets/units/soldier/rocket_1.png
deleted file mode 100644
index ec62482..0000000
--- a/assets/units/soldier/rocket_1.png
+++ /dev/null
Binary files differ
diff --git a/assets/units/soldier/rocket_2.png b/assets/units/soldier/rocket_2.png
deleted file mode 100644
index 7dc21cd..0000000
--- a/assets/units/soldier/rocket_2.png
+++ /dev/null
Binary files differ
diff --git a/assets/units/soldier/rocket_3.png b/assets/units/soldier/rocket_3.png
deleted file mode 100644
index 0415136..0000000
--- a/assets/units/soldier/rocket_3.png
+++ /dev/null
Binary files differ
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<interface::pie_item_t> &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<interface::pie_item_t> &items)
switch (unit->type) {
case unit_t::UNIT_SOLDIER:
soldiers = true;
- if (!dynamic_cast<unit_soldier_t*>(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<interface::pie_item_t> &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<fx_aim_marker_t> 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 <http://www.gnu.org/licenses/>.
+*/
+
+#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 <http://www.gnu.org/licenses/>.
-*/
-
-#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<fx_aim_marker_t>(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;