diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.hpp | 14 | ||||
-rw-r--r-- | src/game/game.cpp | 39 | ||||
-rw-r--r-- | src/game/game.hpp | 24 | ||||
-rw-r--r-- | src/game/units.cpp | 75 |
4 files changed, 104 insertions, 48 deletions
diff --git a/src/common.hpp b/src/common.hpp index 54f9804..d4cebf5 100644 --- a/src/common.hpp +++ b/src/common.hpp @@ -187,11 +187,23 @@ namespace game { class unit_t; + class roll_params_t { + public: + size_t count = 1, sides = 20, bonus = 0; + + roll_params_t(void) = default; + roll_params_t(size_t sides_); + roll_params_t(size_t count_, size_t sides_); + roll_params_t(size_t count_, size_t sides_, size_t bonus_); + }; + class state_t { std::unordered_set<unit_t*> units; std::unordered_set<unit_t*> selected_units; std::unordered_set<unit_t*> awake_units; + procgen::prng_t dice_prng; + public: world::world_t world; interface::state_t *interface; @@ -204,6 +216,8 @@ namespace game { // These are called by the interface. void select(rectf_t rect); void command(v2f_t x); + + size_t roll(roll_params_t *P); }; } diff --git a/src/game/game.cpp b/src/game/game.cpp index 5067df7..96f76d3 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -84,9 +84,20 @@ void state_t::command(v2f_t x) void state_t::tick(double now_, double dt_) { + union { + double d; + uint32_t i; + } u; + now = now_; dt = dt_; + // FIXME: Is this non-deterministic enough? + u.d = now; + dice_prng.seed(dice_prng.next() ^ u.i); + u.d = dt; + dice_prng.seed(dice_prng.next() ^ u.i); + for (unit_t *unit : units) { rectf_t wake_range; @@ -136,6 +147,34 @@ void state_t::tick(double now_, double dt_) } } +roll_params_t::roll_params_t(size_t sides_) +{ + sides = sides_; +} + +roll_params_t::roll_params_t(size_t count_, size_t sides_) +{ + count = count_; + sides = sides_; +} + +roll_params_t::roll_params_t(size_t count_, size_t sides_, size_t bonus_) +{ + count = count_; + sides = sides_; + bonus = bonus_; +} + +size_t state_t::roll(roll_params_t *P) +{ + size_t total = 0; + + for (size_t i = 0; i < P->count; i++) + total += dice_prng.next() % P->sides + 1; + + return total + P->bonus; +} + bool load_assets(void) { assets::load(); diff --git a/src/game/game.hpp b/src/game/game.hpp index d4aed5d..57dbb07 100644 --- a/src/game/game.hpp +++ b/src/game/game.hpp @@ -49,6 +49,9 @@ namespace game { world::cmodel_t make_cmodel(v2f_t at); void compute_bounds(); + double next_targetting = -INFINITY; + double last_attack = -INFINITY; + public: v2f_t x; rectf_t size, render_size; @@ -88,6 +91,12 @@ namespace game { virtual void wake(unit_t *by_whom) = 0; virtual void sleep(void) = 0; + struct { + size_t armor_class; + roll_params_t hit_roll; + roll_params_t damage_roll; + } cs; + bool dead = false; double death_time = -INFINITY; int health = 1, max_health = 1; @@ -99,15 +108,14 @@ namespace game { double say_time = -INFINITY; void say(std::string str); + void render_to(render::state_t *render); }; class human_t : public unit_t { - double next_targetting = -INFINITY; double last_target_time = -INFINITY; v2f_t last_target_x; - double last_attack = -INFINITY; public: human_t(game::state_t *game); @@ -121,9 +129,7 @@ namespace game { class alien_t : public unit_t { double next_targetting = -INFINITY; - double next_attack = -INFINITY; - void attack(unit_t *target, float range); public: alien_t(game::state_t *game); void render_to(render::state_t *render); @@ -133,14 +139,4 @@ namespace game { void think(void); void die(void); }; - - static inline size_t roll(size_t count, size_t sides) - { - size_t total = 0; - - for (size_t i = 0; i < count; i++) - total += rand() % sides + 1; - - return total; - } }; diff --git a/src/game/units.cpp b/src/game/units.cpp index 2eb5dbe..d1648d7 100644 --- a/src/game/units.cpp +++ b/src/game/units.cpp @@ -103,7 +103,9 @@ bool unit_t::keep_moving(double speed) next = *move.path.begin(); delta = next - x; - move.angle = delta.angle(); + + if (delta.len() != 0.0f) + move.angle = delta.angle(); if (delta.len() >= time) { x_new = x + delta * time / delta.len(); @@ -182,15 +184,15 @@ void unit_t::damage(int points, unit_t *attacker) void unit_t::try_attack(unit_t *target) { std::stringstream ss; - int hit_roll, hit_dc = 10 /* FIXME */; - int dmg_roll, dmg_bonus, dmg_total; + size_t hit_roll; + size_t dmg_roll; ss << name << " " << text::get(text::UNIT_ATTACK) << " " << target->name << ": "; - hit_roll = roll(1, 20); - ss << hit_roll << " vs " << hit_dc; + hit_roll = game->roll(&cs.hit_roll); + ss << hit_roll << " vs " << target->cs.armor_class; - if (hit_roll == 1 || hit_roll < hit_dc) { + if (hit_roll == 1 || hit_roll < target->cs.armor_class) { ss << " (" << text::get((hit_roll == 1 ? text::UNIT_CRITICAL_MISS : text::UNIT_MISS)) << ")"; game->interface->print(ss.str()); return; @@ -199,16 +201,14 @@ void unit_t::try_attack(unit_t *target) ss << " (" << text::get((hit_roll == 20 ? text::UNIT_CRITICAL_HIT : text::UNIT_HIT)) << ")"; game->interface->print(ss.str()); - dmg_roll = roll(2, 6); - dmg_bonus = 2; - dmg_total = dmg_roll + dmg_bonus; + dmg_roll = game->roll(&cs.damage_roll); ss.str(std::string()); ss << name << " " << text::get(text::UNIT_DAMAGE) << " " << target->name << ": "; - ss << dmg_roll << " + " << dmg_bonus << " = " << dmg_total; + ss << dmg_roll - cs.damage_roll.bonus << " + " << cs.damage_roll.bonus << " = " << dmg_roll; game->interface->print(ss.str()); - target->damage(dmg_total, this); + target->damage(dmg_roll, this); } static unit_t *find_target(world::world_t *world, v2f_t x, float r, @@ -255,6 +255,10 @@ human_t::human_t(game::state_t *game) : unit_t(game, UNIT_HUMAN) render_size[0] = v2f_t(-0.5f, -1.0f); render_size[1] = v2f_t(+0.5f, +0.5f); name = text::get(text::UNIT_HUMAN); + + cs.armor_class = 10; + cs.hit_roll = roll_params_t(20); + cs.damage_roll = roll_params_t(4); } void human_t::wake(unit_t *by_whom) @@ -275,9 +279,14 @@ void human_t::think(void) last_target_time = game->now; last_target_x = target->x; - if (last_attack + 0.5 < game->now) { - last_attack = game->now; - try_attack(target); + if (last_attack + 1.5 < game->now) { + world::trace_t trace; + + trace = world->trace(x, target->x, CF_SOLID); + if (!trace.hit) { + last_attack = game->now; + try_attack(target); + } } //start_moving(target->x, CF_SOLID); @@ -326,7 +335,7 @@ void human_t::render_to(render::state_t *render) render->render(legs, render_bounds, move.angle); render->render(body, render_bounds, body_angle); - render->render(&assets::human.head_idle, render_bounds, move.angle); + render->render(&assets::human.head_idle, render_bounds, body_angle); } else render->render(&assets::human.dead, render_bounds); @@ -353,12 +362,16 @@ alien_t::alien_t(game::state_t *game) : unit_t(game, UNIT_ALIEN) render_size[0] = v2f_t(-0.3f, -0.3f); render_size[1] = v2f_t(+0.3f, +0.3f); name = text::get(text::UNIT_ALIEN); + + cs.armor_class = 5; + cs.hit_roll = roll_params_t(20); + cs.damage_roll = roll_params_t(3, 6, 1); } void alien_t::wake(unit_t *by_whom) { start_moving(by_whom->x, CF_SOLID); - next_targetting = game->now + 0.4; + next_targetting = game->now + 0.2; } void alien_t::sleep(void) @@ -370,23 +383,6 @@ void alien_t::die(void) render_layer = -1; } -void alien_t::attack(unit_t *target, float range) -{ - world::trace_t trace; - - if (game->now < next_attack) - return; - - if ((x - target->x).len() > range) - return; - - trace = world->trace(x, target->x, CF_SOLID); - if (!trace.hit) - try_attack(target); - - next_attack = game->now + 1.0; -} - void alien_t::think(void) { if (game->now > next_targetting) { @@ -394,7 +390,18 @@ void alien_t::think(void) target = find_target(world, x, 10.0f, UNIT_HUMAN); if (target) { - attack(target, 1.0f); + if (last_attack + 0.5 < game->now) { + world::trace_t trace; + + if ((x - target->x).len() < 1.0f) { + trace = world->trace(x, target->x, CF_SOLID); + if (!trace.hit) + try_attack(target); + + last_attack = game->now; + } + } + start_moving(target->x, CF_SOLID); } |