summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--assets/units/soldier/rocket_0.pngbin0 -> 403 bytes
-rw-r--r--assets/units/soldier/rocket_1.pngbin0 -> 528 bytes
-rw-r--r--assets/units/soldier/rocket_2.pngbin0 -> 565 bytes
-rw-r--r--assets/units/soldier/rocket_3.pngbin0 -> 607 bytes
-rw-r--r--src/game/assets.cpp1
-rw-r--r--src/game/game.cpp22
-rw-r--r--src/game/game.hpp26
-rw-r--r--src/game/rocket.cpp76
-rw-r--r--src/game/text.cpp6
-rw-r--r--src/game/units.cpp20
11 files changed, 145 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index 09f4725..b86f8dc 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,7 @@ SRC := src/game/assets.cpp \
src/game/effects.cpp \
src/game/game.cpp \
src/game/interface.cpp \
+ src/game/rocket.cpp \
src/game/text.cpp \
src/game/units.cpp \
src/game/unit_nest.cpp \
diff --git a/assets/units/soldier/rocket_0.png b/assets/units/soldier/rocket_0.png
new file mode 100644
index 0000000..2417aef
--- /dev/null
+++ b/assets/units/soldier/rocket_0.png
Binary files differ
diff --git a/assets/units/soldier/rocket_1.png b/assets/units/soldier/rocket_1.png
new file mode 100644
index 0000000..ec62482
--- /dev/null
+++ b/assets/units/soldier/rocket_1.png
Binary files differ
diff --git a/assets/units/soldier/rocket_2.png b/assets/units/soldier/rocket_2.png
new file mode 100644
index 0000000..7dc21cd
--- /dev/null
+++ b/assets/units/soldier/rocket_2.png
Binary files differ
diff --git a/assets/units/soldier/rocket_3.png b/assets/units/soldier/rocket_3.png
new file mode 100644
index 0000000..0415136
--- /dev/null
+++ b/assets/units/soldier/rocket_3.png
Binary files differ
diff --git a/src/game/assets.cpp b/src/game/assets.cpp
index 31c4427..f3b4cd3 100644
--- a/src/game/assets.cpp
+++ b/src/game/assets.cpp
@@ -41,6 +41,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.fire.load("assets/units/soldier/fire.ogg");
soldier.fire.volume = 4.0f;
diff --git a/src/game/game.cpp b/src/game/game.cpp
index 6e73811..03033fb 100644
--- a/src/game/game.cpp
+++ b/src/game/game.cpp
@@ -164,6 +164,7 @@ void state_t::select(rectf_t rect, int type)
enum {
COMMAND_MOVE,
COMMAND_FIRE,
+ COMMAND_FIRE_ROCKET,
COMMAND_STOP,
COMMAND_REPL,
@@ -197,6 +198,7 @@ bool state_t::populate_pie_menu(std::vector<interface::pie_item_t> &items)
if (soldiers) {
items.push_back((interface::pie_item_t){"Move", COMMAND_MOVE});
items.push_back((interface::pie_item_t){"Fire", COMMAND_FIRE});
+ items.push_back((interface::pie_item_t){"Fire a rocket", COMMAND_FIRE_ROCKET});
items.push_back((interface::pie_item_t){"Stop", COMMAND_STOP});
}
@@ -231,6 +233,26 @@ static void command_soldier(unit_soldier_t *soldier, v2f_t x, int number)
soldier->manual_firing_target = x;
soldier->say(text::get(text::SAY_FIRING));
break;
+
+ case COMMAND_FIRE_ROCKET:
+ {
+ v2f_t from, v;
+ rocket_t *rocket;
+
+ if (soldier->rocket_fired) {
+ soldier->say(text::get(text::SAY_NO_ROCKETS));
+ break;
+ }
+
+ soldier->rocket_fired = true;
+
+ from = soldier->x + v2f_t(0, -0.5);
+ v = x - from;
+ v *= 1.0f / v.len() * 10.0f;
+
+ rocket = new rocket_t(soldier->game, from, v, soldier);
+ rocket->place(&soldier->game->world, from);
+ }
}
}
diff --git a/src/game/game.hpp b/src/game/game.hpp
index a173b7e..20b2b41 100644
--- a/src/game/game.hpp
+++ b/src/game/game.hpp
@@ -21,7 +21,8 @@ namespace game {
enum {
ET_UNIT,
ET_EFFECT,
- ET_DECO
+ ET_DECO,
+ ET_ROCKET
};
enum {
@@ -61,6 +62,7 @@ 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;
audio::sound_t fire, step_stone, step_dirt, pain, death, gib_sound;
} soldier_assets_t;
@@ -125,11 +127,13 @@ namespace game {
SAY_MOVING,
SAY_STOPPING,
SAY_FIRING,
+ SAY_NO_ROCKETS,
UNIT_NAME_SPIDER,
UNIT_NAME_SOLDIER,
UNIT_NAME_NEST,
UNIT_NAME_REPL,
- UNIT_DEATH
+ UNIT_DEATH,
+ UNIT_DESTRUCTION
} index_t;
std::string get(index_t index);
@@ -244,11 +248,12 @@ namespace game {
bool manual_firing = false;
v2f_t manual_firing_target;
+ bool rocket_fired = false;
+
void check_area(void);
void shoot(v2f_t aim);
void target_and_attack(void);
-
unit_soldier_t(game::state_t *game_);
~unit_soldier_t(void) {};
void render_to(render::state_t *render);
@@ -414,4 +419,19 @@ namespace game {
void on_wake(void) {};
void damage(int points, unit_t *attacker);
};
+
+ class rocket_t : public game::entity_t {
+ unit_t *shooter;
+ v2f_t v;
+
+ public:
+ rocket_t(game::state_t *game, v2f_t x_, v2f_t v_, unit_t *shooter_);
+ void render_to(render::state_t *render);
+ void render_late_to(render::state_t *render) {};
+
+ void on_think(void);
+ void on_spawn(void) {};
+ void on_wake(void) {};
+ void damage(int points, unit_t *attacker) {};
+ };
};
diff --git a/src/game/rocket.cpp b/src/game/rocket.cpp
new file mode 100644
index 0000000..e88f599
--- /dev/null
+++ b/src/game/rocket.cpp
@@ -0,0 +1,76 @@
+/*
+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 {
+
+/*
+ class rocket_t : public game::entity_t {
+ unit_t *shooter;
+ v2f_t v;
+
+ public:
+ rocket_t(game::state_t *game, v2f_t x, v2f_t v, unit_t *shooter_);
+ void render_to(render::state_t *render);
+ void render_late_to(render::state_t *render) {};
+
+ void on_think(void);
+ void on_spawn(void) {};
+ void on_wake(void) {};
+ void damage(int points, unit_t *attacker) {};
+ }
+*/
+
+const v2f_t rocket_radius(1.0f, 1.0f);
+
+rocket_t::rocket_t(game::state_t *game, v2f_t x_, v2f_t v_, unit_t *shooter_) : entity_t(game, ET_ROCKET)
+{
+ x = x_;
+ v = v_;
+ 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_think(void)
+{
+ v2f_t end;
+ world::trace_t trace;
+
+ end = x + v * game->dt;
+ trace = world->ray_v_all(x, end, CF_SOLID|CF_BODY|CF_BODY_SMALL, shooter);
+ if (trace.frac < 1.0f) {
+ game->explosion(x);
+ 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/text.cpp b/src/game/text.cpp
index 9b5503b..28addc9 100644
--- a/src/game/text.cpp
+++ b/src/game/text.cpp
@@ -55,6 +55,9 @@ static std::string get_english(index_t index)
case SAY_FIRING:
return "Firing!";
+ case SAY_NO_ROCKETS:
+ return "Out of rockets.";
+
case UNIT_NAME_SPIDER:
return "Spider";
@@ -70,6 +73,9 @@ static std::string get_english(index_t index)
case UNIT_DEATH:
return "died";
+ case UNIT_DESTRUCTION:
+ return "was destroyed";
+
default:
abort();
}
diff --git a/src/game/units.cpp b/src/game/units.cpp
index e7263c0..43e6878 100644
--- a/src/game/units.cpp
+++ b/src/game/units.cpp
@@ -217,7 +217,16 @@ void unit_t::damage(int points, unit_t *attacker)
void unit_t::die(unit_t *killer)
{
- game->interface->print(name + " " + text::get(text::UNIT_DEATH) + ".");
+ switch (type) {
+ case UNIT_SOLDIER:
+ case UNIT_SPIDER:
+ game->interface->print(name + " " + text::get(text::UNIT_DEATH) + ".");
+ break;
+
+ default:
+ game->interface->print(name + " " + text::get(text::UNIT_DESTRUCTION) + ".");
+ break;
+ }
dead = true;
death_time = game->now;
@@ -300,13 +309,16 @@ void hivemind_attack(unit_t *source, v2f_t target)
if (unit->type != unit_t::UNIT_SPIDER)
continue;
- if ((unit->x - target).len() > 25.0f)
- continue;
-
if (unit->have_target)
continue;
unit->wake();
+
+ // Move towards the target if it's close, otherwise walk
+ // randomly to avoid fire.
+ if ((unit->x - target).len() > 25.0f)
+ continue;
+
unit->start_moving(target);
}
}