namespace rogue_unlike { /** a helper structure to mass to powerfun */ struct data { int keystate; double d; ld modv; ld moda; int dx; struct power *p; }; using powerfun = hr::function; struct power { int key; string name; string desc; string glyph; color_t color; powerfun pf; int id_status; int qty_filled; int qty_owned; flagtype flags; void init(); hr::function act, paused_act; hr::function get_name; hr::function get_desc; hr::function get_glyph; hr::function get_color; hr::function picked_up; power& is_starting(); power& be_weapon(); power& be_resource(string plural); power& while_paused(); power& identified_name(string, string); }; extern vector powers; struct bbox { int minx, miny, maxx, maxy; bool operator != (bbox& a) { return minx != a.minx || miny != a.miny || maxx != a.maxx || maxy != a.maxy; } }; bool intersect(bbox a, bbox b); struct room { // texture::texture_data *room_texture; string roomname; renderbuffer *rbuf; cell *where; short block_at[room_y][room_x]; bool fov[room_y][room_x]; bool which_map_rendered; bool infile, need_rerender; vector> entities; eWall at(int x, int y) { return eWall(block_at[y][x] >> 3); } void clear() { for(int y=0; ymaster->distance; if(ylev <= 0) for(int y=room_y-6; y struct statarray : array { statarray() {}; T& operator [] (stat s) { return array::operator[] ((int) s); }; const T& operator [] (stat s) const { return array::operator[] ((int) s); }; }; struct entity { virtual xy siz() = 0; xy where, vel; bool existing; xy dsiz() { return get_scale() * siz(); } xy gwhere, gvel; xy zero_vel; /* relative to the platform */ virtual struct moving_platform* as_platform() { return nullptr; } int hp; int invinc_end; virtual int max_hp() { return 100; } virtual bool visible(room *r); void clearg() { gwhere = where; gvel = vel; } entity() { where = xy(screen_x / 2., screen_y / 2.); vel = xy(0, 0); existing = true; destroyed = false; invinc_end = -1; clearg(); }; void postfix() { hp = max_hp(); } data get_dat(); struct bbox get_pixel_bbox_at(xy); struct bbox get_pixel_bbox() { return get_pixel_bbox_at(where); } virtual double grav() { return 0.1; } bool on_floor, fallthru, on_ice, wallhug, on_bounce; bool destroyed; void kino(); void apply_vel(); void apply_walls(); void apply_walls_reflect(); void apply_grav(); void apply_portal_grav(); virtual void act() { kino(); } double get_scale() { return get_scale_at(where.y); } virtual bool freezing() { return false; } virtual void hit_wall() {}; virtual void draw(); virtual void attacked(int s) {} virtual string glyph() = 0; virtual color_t color() = 0; virtual bool hurt_by_spikes() { return false; } bool visible_inv() { return (invinc_end < gframeid || (invinc_end - gframeid) % 50 < 25); } virtual bool have_help() { return true; } virtual string get_name() { return "unnamed"; } virtual void on_kill() { existing = false; } virtual bool reduce_hp(int x) { if(gframeid < invinc_end) return false; hp -= x; if(hp < 0) on_kill(); invinc_end = gframeid + 150; return true; } virtual string get_help() { return "No help about this."; } }; struct man : public entity { int facing; int attack_facing; int attack_when; int on_floor_when; int jump_control, next_jump_control; int coyote_time, next_coyote_time; int last_action; int experience; statarray base_stats, current_stats, next_stats; virtual int max_hp() { return 10 * current_stats[stat::con]; } man() { facing = 1; attack_facing = 1; for(auto s: allstats) base_stats[s] = 10; next_stats = base_stats; current_stats = base_stats; postfix(); } xy siz() override { return {12, 12}; } string glyph() override { return hallucinating ? "f" : "@"; } color_t color() override { return hallucinating ? 0x808080FF : 0xFF8080FF; } void act() override; void draw() override; virtual bool hurt_by_spikes() { return true; } string get_name() override { return "alchemist"; } string get_help() override { return "This is you."; } }; extern man m; struct moving_platform : public entity { xy ctr; ld radius, shift; xy siz() override { return {36, 12}; } string glyph() override { return "#"; } color_t color() override { return 0xFFFFFFFF; } virtual xy location_at(ld t) = 0; void draw() override; void act() override; virtual moving_platform* as_platform() { return this; } string get_name() override { return "moving platform"; } string get_help() override { return "Moving platforms move."; } }; struct ferris_platform : public moving_platform { xy location_at(ld t) override; string get_name() override { return "Ferris platform"; } string get_help() override { return "Ferris wheel platforms, powered by some ancient mechanism. They always go in perfect circles, with constant velocity."; } }; struct pendulum_platform : public moving_platform { xy a, b; ld period, shift; xy location_at(ld t) override; string get_name() override { return "pendulum platform"; } string get_help() override { return "These pendulum platforms go back and forth between two locations, taking the shortest path possible."; } }; struct npc : public entity { string sglyph, name; color_t col; string text; int talk_on; xy siz() override { return {12, 12}; } string glyph() override { return sglyph; } color_t color() override { return col; } void act() override; string get_name() override { return name; } string get_help() override { return "Stay awhile and listen."; } }; struct enemy : public entity { xy respawn; int num_kills; void on_kill() override { entity::on_kill(); num_kills++; } enemy() { num_kills = 0; postfix(); } }; struct boar : public enemy { xy siz() override { return {18, 18}; } string glyph() override { return "B"; } color_t color() override { return 0x804000FF; } void act() override; void attacked(int s) override; string get_name() override { return "giant boar"; } string get_help() override { return "Beware their tusks."; } }; struct snake : public enemy { int dir; xy siz() override { return {18, 8}; } string glyph() override { return "S"; } color_t color() override { return 0x20D020FF; } void act() override; void attacked(int s) override; string get_name() override { return "snake"; } string get_help() override { return "A nasty dungeon snake."; } }; struct kestrel : public enemy { xy siz() override { return {10, 10}; } string glyph() override { return "K"; } color_t color() override { return 0xD0A0A0FF; } void act() override; void attacked(int s) override; string get_name() override { return "kestrel"; } string get_help() override { return "A standard dungeon kestrel."; } }; struct bat : public enemy { int next_change; xy siz() override { return {6, 6}; } string glyph() override { return "B"; } color_t color() override { return 0xD0A0A0FF; } void act() override; void attacked(int s) override; string get_name() override { return "bat"; } string get_help() override { return "A cave bat."; } }; struct hint : public entity { string hint_text; int state; xy size; xy siz() override { return size; } string glyph() override { return " "; } color_t color() override { return 0; } void act() override; bool have_help() { return false; } }; struct item : public entity { int id, qty; string pickup_message; xy siz() override { return {12, 12}; } string glyph() override { return powers[id].get_glyph(); } color_t color() override { return powers[id].get_color(); } void act() override { kino(); if(intersect(get_pixel_bbox(), m.get_pixel_bbox())) { addMessage(pickup_message); powers[id].picked_up(qty); existing = false; } } string get_name() override { return powers[id].name; } string get_help() override { return powers[id].get_desc(); } }; struct missile : public entity { missile() { destroyed = false; } xy siz() override { return {4, 4}; } string glyph() override { return "*"; } color_t color() override { return 0x8080FFFF; } void act() override; bool freezing() override { return true; } void hit_wall() override { destroyed = true; } }; }