summaryrefslogtreecommitdiff
path: root/src/game/units.cpp
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-12-18 17:33:49 +0000
committerPaweł Redman <pawel.redman@gmail.com>2017-12-18 17:33:49 +0000
commitc6489d36f6de7464c555f04d5d4324f50fa6c51f (patch)
treefde3f3d3a0d720a328f8b74ac2d0d14a0d463f02 /src/game/units.cpp
parent41bebb262aa8f346ce6cdaefd854c9077ae84f97 (diff)
Start experimenting with fear.
Diffstat (limited to 'src/game/units.cpp')
-rw-r--r--src/game/units.cpp129
1 files changed, 118 insertions, 11 deletions
diff --git a/src/game/units.cpp b/src/game/units.cpp
index cbc3f1a..24b9567 100644
--- a/src/game/units.cpp
+++ b/src/game/units.cpp
@@ -46,7 +46,7 @@ void unit_t::render_to(render::state_t *render)
float height;
text_pos = render_bounds[0] + v2f_t(render_bounds.dim(0) / 2, -render_bounds.dim(1) * 0.1);
- height = size.dim_min() * 0.20f;
+ height = size.dim_min() * 0.50f;
render->render_text(text_pos, height, say_text,
render::ALIGN_CENTER_BOTTOM,
sf::Color::White);
@@ -65,6 +65,9 @@ void unit_t::render_to(render::state_t *render)
else
ss << "S";
+ if (controllable)
+ ss << "C";
+
text_pos = render_bounds[0] + v2f_t(render_bounds.dim(0) / 2, -render_bounds.dim(1) * 0.1);
height = size.dim_min() * 0.40f;
text_pos[1] -= height;
@@ -119,7 +122,7 @@ bool unit_t::keep_moving(double speed)
}
cmodel_next.bounds = size + x_new;
- cmodel_next.cflags = cmodel.cflags;
+ cmodel_next.cflags = move.cflags;
if (!world->test_rect(&cmodel_next, this)) {
x = x_new;
cmodel = cmodel_next;
@@ -142,7 +145,7 @@ bool unit_t::keep_moving(double speed)
return rv;
}
-bool unit_t::start_moving(v2f_t dst, world::cflags_t cflags)
+bool unit_t::start_moving(v2f_t dst)
{
world::cmodel_t rep;
@@ -154,7 +157,7 @@ bool unit_t::start_moving(v2f_t dst, world::cflags_t cflags)
move.dst = dst;
move.path.clear();
- rep.cflags = cflags;
+ rep.cflags = move.cflags;
rep.bounds = cmodel.bounds;
if (!world->find_path(x, move.dst, &rep, this, &move.path)) {
@@ -270,6 +273,7 @@ unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER)
render_size[0] = v2f_t(-0.5f, -1.0f);
render_size[1] = v2f_t(+0.5f, +0.5f);
cmodel.cflags = CF_BODY;
+ move.cflags = CF_SOLID | CF_BODY | CF_WATER;
name = text::get(text::UNIT_NAME_SOLDIER);
@@ -283,6 +287,51 @@ unit_soldier_t::unit_soldier_t(game::state_t *game) : unit_t(game, UNIT_SOLDIER)
cs.hit_die = die_t(8);
}
+void unit_soldier_t::check_area(void)
+{
+ rectf_t bounds;
+
+ bounds[0] = x - v2f_t(10, 10);
+ bounds[1] = x + v2f_t(10, 10);
+
+ willpower_bonus = 0;
+ fear_dc = 0;
+
+ for (world::entity_t *went : game->world.get_entities(bounds, -1)) {
+ auto ent = dynamic_cast<game::entity_t*>(went);
+ unit_t *unit;
+
+ // WTF?
+ if (!ent)
+ continue;
+
+ // Wake everything around.
+ if (!ent->ignore_waking) {
+ ent->wake_time = game->now;
+
+ if (!ent->awake)
+ ent->wake();
+ }
+
+ if (ent->type != ET_UNIT)
+ continue;
+
+ unit = (unit_t*)ent;
+
+ if (unit->dead)
+ continue;
+
+ if (unit->friendly)
+ willpower_bonus += 3;
+ else {
+ if (unit->type == UNIT_NEST)
+ fear_dc += 4;
+ else
+ fear_dc += 2;
+ }
+ }
+}
+
void unit_soldier_t::target_and_attack(void)
{
unit_t *target;
@@ -317,12 +366,64 @@ void unit_soldier_t::target_and_attack(void)
void unit_soldier_t::on_think(void)
{
- game->wake_everything(x, 10);
+ check_area();
- target_and_attack();
+ if (!panic && fear_dc > 1 && game->now > next_fear_test) {
+ size_t roll;
+ bool success;
+ std::stringstream ss;
+
+ roll = game->roll(die_t(20));
+ success = roll + willpower_bonus >= fear_dc;
+
+ ss << name << " " << text::get(text::UNIT_SAVING_THROW_WILLPOWER);
+ ss << ": " << roll << " + " << willpower_bonus << " = " << roll + willpower_bonus;
+ ss << " vs " << fear_dc << ": ";
+
+ if (success)
+ ss << text::get(text::UNIT_SAVING_THROW_SUCCESS);
+ else
+ ss << text::get(text::UNIT_SAVING_THROW_FAILURE);
+
+ game->interface->print(ss.str());
+
+ if (!success) {
+ say(text::get(text::SAY_PANIC));
+ panic = true;
+ panic_end = game->now + 10;
+ panic_turn = -INFINITY;
+ controllable = false;
+ }
+
+ next_fear_test = game->now + 3;
+ }
+
+ if (panic && game->now > panic_end) {
+ move.moving = false;
+ move.path.clear();
+ panic = false;
+ controllable = true;
+ }
+
+ if (!panic) {
+ target_and_attack();
+
+ if (!keep_moving(4.0))
+ say(text::get(text::SAY_BLOCKED));
+ } else {
+ if (!keep_moving(4.0))
+ panic_turn = -INFINITY;
+
+ if (game->now >= panic_turn) {
+ v2f_t t;
- if (!keep_moving(4.0))
- say(text::get(text::SAY_BLOCKED));
+ t = game->dice_prng.unit_vec2();
+
+ move.path.clear();
+ move.path.push_back(x + t * 10);
+ panic_turn = game->now + 0.5;
+ }
+ }
}
void unit_soldier_t::on_death(void)
@@ -345,7 +446,7 @@ void unit_soldier_t::render_to(render::state_t *render)
else
legs = &assets::soldier.legs_idle;
- if (last_target_time + 3 > game->now) {
+ if (!panic && last_target_time + 3 > game->now) {
if (last_attack + 0.1 > game->now)
body = &assets::soldier.body_firing;
else
@@ -359,7 +460,12 @@ void unit_soldier_t::render_to(render::state_t *render)
}
render->render(game->now * 10, legs, render_bounds, move.angle);
- render->render(game->now * 10, body, render_bounds, body_angle);
+
+ if (panic)
+ render->render(game->now * 10, &assets::soldier.body_panic, render_bounds);
+ else
+ render->render(game->now * 10, body, render_bounds, body_angle);
+
render->render(game->now * 10, &assets::soldier.head_idle, render_bounds, body_angle);
} else
render->render(game->now * 10, &assets::soldier.dead, render_bounds);
@@ -374,6 +480,7 @@ unit_spider_t::unit_spider_t(game::state_t *game) : unit_t(game, UNIT_SPIDER)
render_size[0] = v2f_t(-0.3f, -0.3f);
render_size[1] = v2f_t(+0.3f, +0.3f);
cmodel.cflags = CF_BODY_SMALL;
+ move.cflags = CF_SOLID | CF_WATER;
name = text::get(text::UNIT_NAME_SPIDER);
@@ -394,7 +501,7 @@ void unit_spider_t::target_and_attack(void)
if (!target)
return;
- start_moving(target->x, CF_SOLID | CF_WATER);
+ start_moving(target->x);
next_targetting = game->now + 0.2;
if (last_attack + 0.5 > game->now)