1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-05-17 06:34:07 +00:00
hyperrogue/rogueviz/ru/classes.cpp

400 lines
10 KiB
C++

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<void(data&)>;
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<void(data&)> act, paused_act;
hr::function<string()> get_name;
hr::function<string()> get_desc;
hr::function<string()> get_glyph;
hr::function<color_t()> get_color;
hr::function<void(int)> picked_up;
power& is_starting();
power& be_weapon();
power& be_resource(string plural);
power& while_paused();
power& identified_name(string, string);
};
extern vector<power> 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<unique_ptr<struct entity>> entities;
eWall at(int x, int y) {
return eWall(block_at[y][x] >> 3);
}
void clear() {
for(int y=0; y<room_y; y++) for(int x=0; x<room_x; x++) block_at[y][x] = 0;
}
void clearfov() {
for(int y=0; y<room_y; y++) for(int x=0; x<room_x; x++) fov[y][x] = false;
}
void initial() {
int ylev = where->master->distance;
if(ylev <= 0)
for(int y=room_y-6; y<room_y; y++)
for(int x=0; x<room_x; x++)
block_at[y][x] = 8 + 4 + (x&1) + (y&1)*2;
if(ylev < 0)
for(int y=0; y<room_y-6; y++)
for(int x=0; x<room_x; x++)
block_at[y][x] = 8;
roomname = "UNNAMED-";
for(int i=0; i<8; i++) roomname += char('A' + rand() % 26);
println(hlog, "generated roomname as ", roomname);
}
void place_small(int x, int y) {
block_at[y][x] = 8;
}
void place_big(int x, int y) {
block_at[y][x] = 8+4;
block_at[y][x+1] = 8+5;
block_at[y+1][x] = 8+6;
block_at[y+1][x+1] = 8+7;
}
void place_block_full(int x, int y, int b);
void replace_block(int x, int y, eWall w) {
int b = 8 * w;
if(block_at[y][x] & 4) b += 4;
place_block_full(x, y, b);
}
void generate();
void reveal(int cx, int cy);
void reveal_around(int cx, int cy);
void fov_from(int sx, int sy);
void create_texture();
};
struct xy {
ld x, y;
xy() {}
xy(ld x, ld y) : x(x), y(y) {}
xy operator + (xy b) { return xy(x+b.x, y+b.y); }
xy operator - (xy b) { return xy(x-b.x, y-b.y); }
xy operator * (ld s) { return xy(x*s, y*s); }
xy operator / (ld s) { return xy(x/s, y/s); }
xy operator * (xy b) { return xy(x*b.x, y*b.y); }
xy operator / (xy b) { return xy(x/b.x, y/b.y); }
friend xy operator * (ld s, xy a) { return xy(s*a.x, s*a.y); }
xy& operator += (xy b) { x += b.x; y += b.y; return self; }
xy& operator -= (xy b) { x -= b.x; y -= b.y; return self; }
xy& operator *= (ld s) { x *= s; y *= s; return self; }
xy& operator *= (xy b) { x *= b.x; y *= b.y; return self; }
xy& operator /= (ld s) { x /= s; y /= s; return self; }
};
enum class stat { str, con, wis, dex };
constexpr stat allstats[] = { stat::str, stat::con, stat::wis, stat::dex };
constexpr int qstat = 4;
template<class T> struct statarray : array<T, qstat> {
statarray() {};
T& operator [] (stat s) { return array<T, qstat>::operator[] ((int) s); };
const T& operator [] (stat s) const { return array<T, qstat>::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<int> 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; }
};
}