/* 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 "../common.hpp" namespace game { enum { ET_UNIT, ET_EFFECT, ET_DECO }; enum { TILE_NONE, TILE_DIRT, TILE_DIRT_RED, TILE_STONE, TILE_STONE_RED, TILE_WATER, TILE_GRAVEL }; enum { CF_BACKGROUND = 1, CF_SOLID = 2, CF_BODY = 4, CF_BODY_SMALL = 8, CF_WATER = 16 }; enum { AMBIENT_NEXUS, AMBIENT_CHASM, AMBIENT_WIND, AMBIENT_WATER, AMBIENT_COUNT }; extern size_t selection_cookie; void worldgen(world::world_t *world, world::sector_index_t index, world::sector_t *sector, bool gen_tiles, bool gen_decos, void *data); namespace assets { typedef struct { render::oriented_sprite_4M_t head_idle, body_idle; render::oriented_sprite_4M_t body_aiming, body_firing; render::oriented_sprite_4M2_t legs_idle, legs_walking; render::animated_texture_t dead, gibbing; audio::sound_t fire, step_stone, step_dirt, gib_sound; } soldier_assets_t; typedef struct { render::oriented_sprite_4M_t idle, walking; render::animated_texture_t dead; } spider_assets_t; typedef struct { render::animated_texture_t idle, dead; } nest_assets_t; typedef struct { render::animated_texture_t idle, dead; audio::sound_t sound; } repl_assets_t; typedef struct { render::animated_texture_t blood, flash; } fx_assets_t; typedef struct { render::animated_texture_t stone, eyething; render::animated_texture_t spike, spike_small; render::animated_texture_t wart; } deco_assets_t; extern soldier_assets_t soldier; extern spider_assets_t spider; extern nest_assets_t nest; extern repl_assets_t repl; extern fx_assets_t fx; extern deco_assets_t deco; extern audio::ambient_t ambients[AMBIENT_COUNT]; extern render::animated_texture_t unit_selected; extern render::animated_texture_t unit_selected_halo; extern render::animated_texture_t move_marker, aim_marker; void load(void); } namespace text { typedef enum { LANG_ENGLISH } language_t; extern language_t language; typedef enum { PAUSED, UNPAUSED, FOLLOWING_ON, FOLLOWING_OFF, SAY_NO_PATH, SAY_READY, SAY_MOVING, SAY_STOPPING, SAY_FIRING, UNIT_NAME_SPIDER, UNIT_NAME_SOLDIER, UNIT_NAME_NEST, UNIT_NAME_REPL, UNIT_DEATH } index_t; std::string get(index_t index); } class entity_t : public world::entity_t { public: game::state_t *game = 0; v2f_t x; rectf_t size, render_size; entity_t(game::state_t *game, int type_); virtual ~entity_t(void) = 0; void destroy(void); void place(world::world_t *world); void place(world::world_t *world, v2f_t x_); bool ignore_waking = true; // Most entities won't need this mechanism. bool awake = false; double wake_time = -INFINITY; void wake(void); void sleep(void); virtual void on_think(void) = 0; virtual void on_spawn(void) = 0; virtual void on_wake(void) = 0; }; class fx_move_marker_t; class fx_aim_marker_t; unit_t *find_target(world::world_t *world, v2f_t x, float r, bool friendly); class unit_t : public entity_t { protected: double next_targetting = -INFINITY; double last_attack = -INFINITY; public: size_t selected = 0; typedef enum { UNIT_SOLDIER, UNIT_SPIDER, UNIT_NEST, UNIT_REPL } type_t; game::state_t *game; type_t type; std::string name; unit_t(game::state_t *game_, type_t type_); bool friendly = false; bool controllable = false; struct { world::cflags_t cflags; bool moving = false; v2f_t dst; float angle = 0.0f; std::list path; bool blocked; size_t attempts_left; float next_attempt; v2f_t last_step; ntime_t random_walk_time = 0; } move; bool keep_moving(double speed); bool start_moving(v2f_t dst); void stop_moving(void); void random_walk(void); bool dead = false; double death_time = -INFINITY; int health = 1, max_health = 1; void damage(int points, unit_t *attacker); void try_attack(unit_t *target); void die(unit_t *killer); virtual void on_death() = 0; std::string say_text; double say_time = -INFINITY; void say(std::string str); void render_to(render::state_t *render); }; class unit_soldier_t : public unit_t { public: double last_target_time = -INFINITY; v2f_t last_target_x; std::unique_ptr move_marker; std::unique_ptr aim_marker; sf::Color selection_color; bool manual_firing = false; v2f_t manual_firing_target; 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); void render_late_to(render::state_t *render); void on_think(void); void on_spawn(void) {}; void on_wake(void) {}; void on_death(void); }; class unit_spider_t : public unit_t { public: unit_spider_t(game::state_t *game_); ~unit_spider_t(void) {}; void render_to(render::state_t *render); void render_late_to(render::state_t *render) {}; void target_and_attack(void); void on_think(void); void on_spawn(void) {}; void on_wake(void); void on_death(void); }; class unit_nest_t : public unit_t { double next_spawning = -INFINITY; public: unit_nest_t(game::state_t *game_); ~unit_nest_t(void) {}; 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_death(void); void on_wake(void) {}; }; class unit_repl_t : public unit_t { public: unit_repl_t(game::state_t *game_); ~unit_repl_t(void) {}; 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_death(void); void on_wake(void) {}; void activate(void); }; class effect_t : public game::entity_t { public: double ttl = +INFINITY; effect_t(game::state_t *game_); virtual ~effect_t() {}; void on_think(void); void on_spawn(void) {}; void on_wake(void) {}; void render_late_to(render::state_t *render) {}; }; class fx_tracer_t : public effect_t { v2f_t x0, x1; public: fx_tracer_t(game::state_t *game_, v2f_t x0_, v2f_t x1_); ~fx_tracer_t(void) {}; void render_to(render::state_t *render); }; class fx_flash_t : public effect_t { v2f_t x; float radius; public: fx_flash_t(game::state_t *game_, v2f_t x_, float radius_); ~fx_flash_t(void) {}; void render_to(render::state_t *render); }; class fx_blood_t : public effect_t { bool alien; v2f_t x; public: fx_blood_t(game::state_t *game_, v2f_t x_, bool alien_); ~fx_blood_t(void) {}; void render_to(render::state_t *render); }; class fx_move_marker_t : public effect_t { v2f_t x; public: fx_move_marker_t(game::state_t *game_, v2f_t x_); ~fx_move_marker_t(void); void render_to(render::state_t *render); }; class fx_aim_marker_t : public effect_t { v2f_t x; public: fx_aim_marker_t(game::state_t *game_, v2f_t x_); ~fx_aim_marker_t(void); void render_to(render::state_t *render); }; typedef enum { DECO_STONE, DECO_STONE_SMALL, DECO_EYETHING, DECO_SPIKE, DECO_SPIKE_SMALL, DECO_WART } deco_type_t; class deco_t : public game::entity_t { deco_type_t type; public: double phase_shift; deco_t(game::state_t *game, deco_type_t type_); 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) {}; }; };