mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2026-10-08 18:31:43 +00:00
ru:: stater system implemented
This commit is contained in:
+73
-43
@@ -198,6 +198,17 @@ template<class T> struct statarray : array<T, qstat> {
|
||||
const T& operator [] (stat s) const { return array<T, qstat>::operator[] ((int) s); };
|
||||
};
|
||||
|
||||
struct stater {
|
||||
virtual stater& act(const string& s, int& i, int _i) = 0;
|
||||
virtual stater& act(const string& s, bool& b, bool _b) = 0;
|
||||
virtual stater& act(const string& s, ld& d, ld _d) = 0;
|
||||
virtual stater& act(const string& s, string& w, const string& _w) = 0;
|
||||
virtual stater& act(const string& s, color_t& c, color_t _c) = 0;
|
||||
virtual stater& act(const string& s, intxy& xy, intxy _xy) { act(s+".x", xy.x, _xy.x); act(s+".y", xy.y, _xy.y); return self; }
|
||||
virtual stater& act(const string& s, xy& p, xy _p) { act(s+".x", p.x, _p.x); act(s+".y", p.y, _p.y); return self; }
|
||||
virtual stater& only_full() { return self; }
|
||||
};
|
||||
|
||||
struct entity {
|
||||
string name;
|
||||
virtual ~entity() {}
|
||||
@@ -221,27 +232,26 @@ struct entity {
|
||||
int invinc_end;
|
||||
|
||||
virtual int max_hp() { return 100; }
|
||||
virtual void regenerate() {}
|
||||
|
||||
virtual bool visible(room *r);
|
||||
|
||||
void clearg() {
|
||||
virtual xy default_where() { return {screen_x/2., screen_y/2.}; }
|
||||
virtual xy default_vel() { return {0, 0}; }
|
||||
virtual bool default_existing() { return true; }
|
||||
|
||||
virtual void hs(stater& s) {
|
||||
println(hlog, "called hs for ", get_name(), " '", name, "' with default_where() of ", make_pair(default_where().x, default_where().y));
|
||||
// println(hlog, name + ": where is ", tie(where.x, where.y), " respawn is ", tie(respawn.x, respawn.y), " default_where is ", make_pair(default_where().x, default_where().y));
|
||||
s.act("where", where, default_where())
|
||||
.act("vel", vel, default_vel())
|
||||
.act("existing", existing, default_existing())
|
||||
.act("hp", hp, max_hp())
|
||||
.act("invinc_end", invinc_end, -1)
|
||||
.act("destroyed", destroyed, false);
|
||||
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();
|
||||
|
||||
virtual bool hidden() { return false; }
|
||||
@@ -347,12 +357,7 @@ struct man : public entity {
|
||||
virtual int max_hp() { return 10 * current.stats[stat::con]; }
|
||||
|
||||
bool can_see(entity& e);
|
||||
man() {
|
||||
facing = 1; attack_facing = 1;
|
||||
for(auto s: allstats) base_stats[s] = 10;
|
||||
next.reset(); current.reset();
|
||||
postfix();
|
||||
}
|
||||
man();
|
||||
xy siz() override {
|
||||
if(morphed) return morphed->siz();
|
||||
return {12, 12};
|
||||
@@ -388,12 +393,14 @@ extern man m;
|
||||
struct moving_platform : public entity {
|
||||
xy ctr;
|
||||
ld radius, shift;
|
||||
ld cur_t;
|
||||
virtual int width() { return 3; }
|
||||
virtual eWall platform_type() { return wWall; }
|
||||
xy siz() override { return {12.*width(), 12}; }
|
||||
string glyph() override { return "#"; }
|
||||
color_t color() override { return 0xFFFFFFFF; }
|
||||
virtual xy location_at(ld t) = 0;
|
||||
virtual xy default_where() override { return location_at(cur_t); }
|
||||
void draw() override;
|
||||
void act() override;
|
||||
virtual moving_platform* as_platform() { return this; }
|
||||
@@ -426,7 +433,13 @@ struct rope_platform : public moving_platform {
|
||||
void draw() override;
|
||||
};
|
||||
|
||||
struct timed_orb : public entity {
|
||||
/* entities with a defined 'respawn' location */
|
||||
struct located_entity : public entity {
|
||||
xy respawn;
|
||||
xy default_where() override { return respawn; }
|
||||
};
|
||||
|
||||
struct timed_orb : public located_entity {
|
||||
int duration;
|
||||
xy siz() override { return {18, 18}; }
|
||||
string glyph() override { return "O"; }
|
||||
@@ -440,12 +453,13 @@ struct timed_orb : public entity {
|
||||
string get_help() override { return "These orbs activate mechanisms for a limited time."; }
|
||||
};
|
||||
|
||||
struct npc_or_trader : public entity {
|
||||
struct npc_or_trader : public located_entity {
|
||||
string text;
|
||||
int talk_on;
|
||||
xy siz() override { return {12, 12}; }
|
||||
void act() override;
|
||||
string get_name() override { return name; }
|
||||
virtual void hs(stater& s) override { entity::hs(s); s.act("talk_on", talk_on, 0); }
|
||||
};
|
||||
|
||||
struct npc : public npc_or_trader {
|
||||
@@ -466,22 +480,20 @@ struct trader : public npc_or_trader {
|
||||
virtual struct trader* as_trader() { return this; }
|
||||
};
|
||||
|
||||
struct enemy : public entity {
|
||||
xy respawn;
|
||||
struct enemy : public located_entity {
|
||||
int num_kills;
|
||||
void on_kill() override {
|
||||
entity::on_kill();
|
||||
num_kills++;
|
||||
m.experience += (base_xp() * 25 + 24) / (4 + num_kills) / (4 + num_kills);
|
||||
}
|
||||
enemy() { num_kills = 0; postfix(); }
|
||||
virtual void hs(stater& s) override { located_entity::hs(s); s.only_full().act("kills", num_kills, 0); }
|
||||
void attacked(int s) override;
|
||||
void regenerate() override { where = respawn; vel = xy(0, 0); existing = true; hp = max_hp(); }
|
||||
virtual int base_xp() { return 0; }
|
||||
bool hit_by_missile(missile *m) override { return true; }
|
||||
};
|
||||
|
||||
struct vtrap : public entity {
|
||||
struct vtrap : public located_entity {
|
||||
xy siz() override { return {6, 18}; }
|
||||
string glyph() override { return "^"; }
|
||||
color_t color() override { return 0xD00000FF; }
|
||||
@@ -496,6 +508,8 @@ struct cat_color {
|
||||
color_t col;
|
||||
};
|
||||
|
||||
void sact(stater& s, string t, cat_color co) { s.act(t+".name", co.name, "black").act(t+".col", co.col, 0xFFFFFFFF); }
|
||||
|
||||
struct cat : public enemy {
|
||||
cat_color col;
|
||||
cat();
|
||||
@@ -504,6 +518,7 @@ struct cat : public enemy {
|
||||
color_t color() override { return col.col; }
|
||||
string get_name() override { return col.name + " cat"; }
|
||||
string get_help() override { return "Do not fight cats!"; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); sact(s, "color", col); }
|
||||
int base_xp() { return 10; }
|
||||
int max_hp() { return 20; }
|
||||
};
|
||||
@@ -543,6 +558,7 @@ struct frog : public enemy {
|
||||
string get_help() override { return "What a nice frog."; }
|
||||
int base_xp() { return 30; }
|
||||
int max_hp() { return 30; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("jphase", jphase, 0).act("jump_at", jump_at, 0); }
|
||||
};
|
||||
|
||||
struct giantfrog : public frog {
|
||||
@@ -556,7 +572,7 @@ struct giantfrog : public frog {
|
||||
};
|
||||
|
||||
struct ghost : public enemy {
|
||||
int xp, hp;
|
||||
int ghost_xp, ghost_hp, extra_invinc;
|
||||
bool flipped;
|
||||
xy siz() override { return {12, 12}; }
|
||||
string glyph() override { return "g"; }
|
||||
@@ -564,9 +580,14 @@ struct ghost : public enemy {
|
||||
void act() override;
|
||||
string get_name() override { return "ghost"; }
|
||||
string get_help() override { return "This apparition looks strangely like you..."; }
|
||||
int base_xp() { return hp; }
|
||||
int max_hp() { return xp; }
|
||||
void regenerate() override {}
|
||||
int base_xp() { return ghost_hp; }
|
||||
int max_hp() { return ghost_xp; }
|
||||
xy default_where() override { return where; } // do not reset on fountains
|
||||
virtual void hs(stater& s) override {
|
||||
enemy::hs(s);
|
||||
s.act("extra_invinc", extra_invinc, 2 * game_fps).
|
||||
only_full().act("flipped", flipped, false).act("xp", ghost_xp, 50).act("hp", ghost_hp, 100).act("where", where, {0, 0});
|
||||
}
|
||||
};
|
||||
|
||||
struct snake : public enemy {
|
||||
@@ -578,10 +599,10 @@ struct snake : public enemy {
|
||||
void attacked(int s) override;
|
||||
string get_name() override { return "snake"; }
|
||||
string get_help() override { return "A nasty dungeon snake."; }
|
||||
void regenerate() override { enemy::regenerate(); dir = respawn_dir; }
|
||||
int base_xp() override { return 10; }
|
||||
int max_hp() override { return 30; }
|
||||
virtual int bite() { return 25; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("dir", dir, respawn_dir); }
|
||||
};
|
||||
|
||||
struct disnake : public snake {
|
||||
@@ -605,9 +626,9 @@ struct kestrel : public enemy {
|
||||
void attacked(int s) override;
|
||||
string get_name() override { return "kestrel"; }
|
||||
string get_help() override { return "A standard dungeon kestrel."; }
|
||||
void regenerate() override { enemy::regenerate(); vel = respawn_vel; }
|
||||
int base_xp() { return 30; }
|
||||
int max_hp() { return 30; }
|
||||
xy default_vel() override { return respawn_vel; }
|
||||
};
|
||||
|
||||
struct gridbug : public enemy {
|
||||
@@ -620,6 +641,7 @@ struct gridbug : public enemy {
|
||||
string get_help() override { return "You are not sure whether this is some kind of insect or some glitch in the fabric of the reality."; }
|
||||
int base_xp() { return 10; }
|
||||
int max_hp() { return 10; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("nextmove", next_move, 0); }
|
||||
};
|
||||
|
||||
struct bat : public enemy {
|
||||
@@ -633,6 +655,7 @@ struct bat : public enemy {
|
||||
string get_help() override { return "A cave bat."; }
|
||||
int base_xp() { return 10; }
|
||||
int max_hp() { return 10; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("nextchange", next_change, 0); }
|
||||
};
|
||||
|
||||
struct guineapig : public enemy {
|
||||
@@ -647,9 +670,9 @@ struct guineapig : public enemy {
|
||||
void attacked(int s) override;
|
||||
string get_name() override { return "guinea pig"; }
|
||||
string get_help() override { return "A standard dungeon guinea pig."; }
|
||||
void regenerate() override { enemy::regenerate(); falling = true; spindir = respawn_spindir; }
|
||||
int base_xp() { return 30; }
|
||||
int max_hp() { return 30; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("falling", falling, true).act("spindir", spindir, respawn_spindir).act("ca", ca, 0); }
|
||||
};
|
||||
|
||||
struct icicle : public enemy {
|
||||
@@ -658,14 +681,16 @@ struct icicle : public enemy {
|
||||
xy siz() override { return {10, 10}; }
|
||||
string glyph() override { return "|"; }
|
||||
color_t color() override { return 0xA0A0F0FF; }
|
||||
xy default_vel() override { auto dat = get_dat(); return { 0, 150 * 0.005 * dat.modv * dat.d }; }
|
||||
void act() override;
|
||||
string get_name() override { return "icicle"; }
|
||||
string get_help() override { return "A dangerous looking icicle."; }
|
||||
int base_xp() { return 1; }
|
||||
int max_hp() { return 1; }
|
||||
virtual void hs(stater& s) override { enemy::hs(s); s.act("state", state, 0); }
|
||||
};
|
||||
|
||||
struct hint : public entity {
|
||||
struct hint : public located_entity {
|
||||
string hint_text;
|
||||
int state;
|
||||
xy size;
|
||||
@@ -677,25 +702,26 @@ struct hint : public entity {
|
||||
bool have_help() { return false; }
|
||||
};
|
||||
|
||||
struct item : public entity {
|
||||
int id, qty;
|
||||
struct item : public located_entity {
|
||||
power *p;
|
||||
int 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(); }
|
||||
string glyph() override { return p->get_glyph(); }
|
||||
color_t color() override { return p->get_color(); }
|
||||
void act() override {
|
||||
stay_on_screen();
|
||||
kino();
|
||||
if(intersect(get_pixel_bbox(), m.get_pixel_bbox())) {
|
||||
addMessage(pickup_message);
|
||||
add_revert(death_revert, {"ITEM", powers[id].name, its(powers[id].qty_filled), its(powers[id].qty_owned)});
|
||||
add_revert(death_revert, {"ITEM", p->name, its(p->qty_filled), its(p->qty_owned)});
|
||||
add_revert(death_revert, {"EXIST", name});
|
||||
powers[id].picked_up(qty);
|
||||
p->picked_up(qty);
|
||||
existing = false;
|
||||
}
|
||||
}
|
||||
string get_name() override { return powers[id].name; }
|
||||
string get_help() override { return powers[id].get_desc(); }
|
||||
string get_name() override { return p->name; }
|
||||
string get_help() override { return p->get_desc(); }
|
||||
};
|
||||
|
||||
struct shopitem : public item {
|
||||
@@ -716,11 +742,13 @@ struct shopitem : public item {
|
||||
string get_name() override { if(bought) return its(price) + " gold"; return item::get_name(); }
|
||||
string get_help() override { if(bought) return "You have bought something from this shop. The trader has stored the gold here."; return item::get_help() + "\n\nPrice: " + its(price); }
|
||||
shopitem* as_shopitem() override { return this; }
|
||||
virtual void hs(stater& s) override { item::hs(s); s.act("bought", bought, false).act("last_intersect", last_intersect, 0); }
|
||||
};
|
||||
|
||||
struct loot : public item {
|
||||
entity *owner;
|
||||
bool dropped;
|
||||
virtual bool default_existing() { return dropped; }
|
||||
void act() {
|
||||
item::act();
|
||||
if(on_floor) {
|
||||
@@ -735,6 +763,7 @@ struct loot : public item {
|
||||
dropped = true; existing = true;
|
||||
}
|
||||
}
|
||||
virtual void hs(stater& s) override { s.act("dropped", dropped, false); item::hs(s); }
|
||||
};
|
||||
|
||||
struct missile : public entity {
|
||||
@@ -746,6 +775,7 @@ struct missile : public entity {
|
||||
void act() override;
|
||||
void hit_wall() override { destroyed = true; }
|
||||
struct missile* as_missile() override { return this; }
|
||||
virtual void hs(stater& s) override { entity::hs(s); s.act("power", power, 0); }
|
||||
};
|
||||
|
||||
struct ice_missile : public missile {
|
||||
|
||||
@@ -446,6 +446,7 @@ void frog::attacked(int dmg) {
|
||||
}
|
||||
|
||||
void ghost::act() {
|
||||
if(gframeid >= invinc_end && extra_invinc) gframeid += extra_invinc, extra_invinc = 0;
|
||||
hyperpoint g = to_hyper(where);
|
||||
hyperpoint h = to_hyper(m.where);
|
||||
ld d = hdist(g, h);
|
||||
@@ -800,7 +801,6 @@ void icicle::act() {
|
||||
kino();
|
||||
if(on_floor) break;
|
||||
}
|
||||
regenerate();
|
||||
}
|
||||
if(state == 0) {
|
||||
auto w = m.where;
|
||||
|
||||
+59
-69
@@ -134,57 +134,56 @@ void load_room(fhstream& f, cell *c) {
|
||||
auto pos = s.find(" ");
|
||||
if(pos != string::npos) {
|
||||
string cap = s.substr(0, pos);
|
||||
string param = s.substr(pos+1);
|
||||
auto nam = [&] (entity& b) {
|
||||
if(param == "") { println(hlog, "got nothing"); b.name = "NOTHING"; return; }
|
||||
if(param[0] >= '0' && param[0] <= '9') { println(hlog, "error: expecting a name, got ", param); b.name = "UNNAMED"; return; }
|
||||
pos = param.find(" "); b.name = param.substr(0, pos); param = param.substr(pos + 1);
|
||||
string param = s.substr(pos+1) + " ";
|
||||
auto cutoff = [&] (const string& val) {
|
||||
if(param == "") { println(hlog, "parameter missing"); return val; }
|
||||
pos = param.find(" "); auto res = param.substr(0, pos); param = param.substr(pos + 1);
|
||||
return res;
|
||||
};
|
||||
auto nam = [&] (entity& b) { b.name = cutoff("NOTHING"); };
|
||||
auto get_ld = [&] () { return atof(cutoff("0").c_str()); };
|
||||
auto get_int = [&] () { return atoi(cutoff("0").c_str()); };
|
||||
auto get_color = [&] () { color_t col; sscanf(cutoff("0").c_str(), "%08x", &col); return col; };
|
||||
auto get_xy = [&] () { ld x = get_ld(); ld y = get_ld(); return xy{x, y}; };
|
||||
|
||||
if(cap == "START") {
|
||||
fountain_room = current_room = &r;
|
||||
sscanf(param.c_str(), "%lf%lf", &m.where.x, &m.where.y);
|
||||
m.where = get_xy();
|
||||
fountain_where = m.where;
|
||||
}
|
||||
else if(cap == "ITEM") {
|
||||
auto b = std::make_unique<item>();
|
||||
b->qty = 1;
|
||||
sscanf(param.c_str(), "%lf%lf%d", &b->where.x, &b->where.y, &b->qty);
|
||||
s = scanline_noblank(f);
|
||||
b->id = -1;
|
||||
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
|
||||
if(b->id == -1) println(hlog, "error: unknown item name ", s), b->id = 0;
|
||||
b->respawn = get_xy();
|
||||
b->qty = param == "" ? 1 : get_int();
|
||||
println(hlog, "qty is ", b->qty);
|
||||
b->p = &find_power(scanline_noblank(f));
|
||||
b->name = b->pickup_message = scanline_noblank(f);
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "LOOT") {
|
||||
auto b = std::make_unique<loot>();
|
||||
b->qty = 1;
|
||||
b->owner = &*r.entities.back();
|
||||
sscanf(param.c_str(), "%d", &b->qty);
|
||||
s = scanline_noblank(f);
|
||||
b->id = -1;
|
||||
b->where = xy(320, 200);
|
||||
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
|
||||
if(b->id == -1) println(hlog, "error: unknown loot name ", s), b->id = 0;
|
||||
b->qty = param == "" ? 1 : get_int();
|
||||
b->p = &find_power(scanline_noblank(f));
|
||||
b->name = b->pickup_message = scanline_noblank(f);
|
||||
b->existing = false; b->dropped = false;
|
||||
b->existing = false;
|
||||
r.entities.emplace_back(std::move(b));
|
||||
println(hlog, "loot pushed");
|
||||
}
|
||||
else if(cap == "SHOPITEM") {
|
||||
auto b = std::make_unique<shopitem>();
|
||||
b->qty = 1; b->qty1 = 0;
|
||||
sscanf(param.c_str(), "%lf%lf%d%d%d", &b->where.x, &b->where.y, &b->price, &b->qty, &b->qty1);
|
||||
s = scanline_noblank(f);
|
||||
b->id = -1;
|
||||
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
|
||||
if(b->id == -1) println(hlog, "error: unknown item name ", s), b->id = 0;
|
||||
b->respawn = get_xy();
|
||||
b->price = get_int();
|
||||
b->qty = param == "" ? 1 : get_int();
|
||||
b->qty1 = param == "" ? 0 : get_int();
|
||||
b->p = &find_power(scanline_noblank(f));
|
||||
b->name = b->pickup_message = scanline_noblank(f);
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "NPC") {
|
||||
auto b = std::make_unique<npc>();
|
||||
sscanf(param.c_str(), "%lf%lf%08x", &b->where.x, &b->where.y, &b->col);
|
||||
b->respawn = get_xy();
|
||||
b->col = get_color();
|
||||
s = scanline_noblank(f);
|
||||
b->sglyph = s[0];
|
||||
b->name = s.substr(1);
|
||||
@@ -193,87 +192,73 @@ void load_room(fhstream& f, cell *c) {
|
||||
}
|
||||
else if(cap == "TRADER") {
|
||||
auto b = std::make_unique<trader>();
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = get_xy();
|
||||
b->name = scanline_noblank(f);
|
||||
b->text = scanline_noblank(f);
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "BOAR") {
|
||||
auto b = std::make_unique<boar>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "GIANTFROG") {
|
||||
auto b = std::make_unique<giantfrog>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "FROG") {
|
||||
auto b = std::make_unique<frog>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "TIMEORB") {
|
||||
auto b = std::make_unique<timed_orb>(); nam(*b);
|
||||
ld dur = 0;
|
||||
sscanf(param.c_str(), "%lf%lf%lf", &b->where.x, &b->where.y, &dur);
|
||||
b->duration = dur * game_fps;
|
||||
b->respawn = get_xy();
|
||||
b->duration = get_ld() * game_fps;
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "BAT") {
|
||||
auto b = std::make_unique<bat>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "GUINEAPIG") {
|
||||
auto b = std::make_unique<guineapig>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf%lf%d", &b->where.x, &b->where.y, &b->pigvel, &b->spindir);
|
||||
b->pigvel /= game_fps; b->falling = true; b->vel = xy{0,0};
|
||||
b->respawn = b->where; b->respawn_spindir = b->spindir; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
b->pigvel = get_ld() / game_fps;
|
||||
b->respawn_spindir = get_int();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "ICICLE") {
|
||||
auto b = std::make_unique<icicle>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->state = 0; b->vel = xy{0,0};
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "VTRAP") {
|
||||
auto b = std::make_unique<vtrap>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
auto dat = b->get_dat();
|
||||
b->vel.x = 0; b->vel.y = 150 * 0.005 * dat.modv * dat.d;
|
||||
|
||||
b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "GRIDBUG") {
|
||||
auto b = std::make_unique<gridbug>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
|
||||
b->respawn = b->where; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "KESTREL") {
|
||||
auto b = std::make_unique<kestrel>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf%lf%lf", &b->where.x, &b->where.y, &b->vel.x, &b->vel.y);
|
||||
b->vel *= xy(block_x, block_y) / game_fps;
|
||||
b->respawn = b->where; b->respawn_vel = b->vel; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
b->respawn_vel = get_xy() * xy(block_x, block_y) / game_fps;
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "SNAKE") {
|
||||
auto b = std::make_unique<snake>(); nam(*b);
|
||||
sscanf(param.c_str(), "%lf%lf%d", &b->where.x, &b->where.y, &b->dir);
|
||||
b->respawn = b->where; b->respawn_dir = b->dir; b->postfix();
|
||||
b->respawn = get_xy();
|
||||
b->respawn_dir = get_int();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "FERRIS") {
|
||||
ld cx, cy, radius; int qty;
|
||||
sscanf(param.c_str(), "%lf%lf%lf%d", &cx, &cy, &radius, &qty);
|
||||
ld cx = get_ld(), cy = get_ld(), radius = get_ld(); int qty = get_int();
|
||||
|
||||
for(int i=0; i<qty; i++) {
|
||||
auto b = std::make_unique<ferris_platform>();
|
||||
@@ -283,8 +268,9 @@ void load_room(fhstream& f, cell *c) {
|
||||
}
|
||||
}
|
||||
else if(cap == "ROPE") {
|
||||
ld cx, cy, radius, period, shift, max_swing; int qty;
|
||||
sscanf(param.c_str(), "%lf%lf%lf%d%lf%lf%lf", &cx, &cy, &radius, &qty, &period, &shift, &max_swing);
|
||||
ld cx = get_ld(), cy = get_ld(), radius = get_ld();
|
||||
int qty = get_int();
|
||||
ld period = get_ld(), shift = get_ld(), max_swing = get_ld();
|
||||
|
||||
for(int i=0; i<qty; i++) {
|
||||
auto b = std::make_unique<rope_platform>();
|
||||
@@ -298,12 +284,12 @@ void load_room(fhstream& f, cell *c) {
|
||||
}
|
||||
else if(cap == "PENDULUM") {
|
||||
auto b = std::make_unique<pendulum_platform>();
|
||||
sscanf(param.c_str(), "%lf%lf%lf%lf%lf%lf", &b->a.x, &b->a.y, &b->b.x, &b->b.y, &b->period, &b->shift);
|
||||
b->a = get_xy(); b->b = get_xy(); b->period = get_ld(); b->shift = get_ld();
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
else if(cap == "HINT") {
|
||||
auto b = std::make_unique<hint>();
|
||||
sscanf(param.c_str(), "%lf%lf%lf%lf", &b->where.x, &b->where.y, &b->size.x, &b->size.y);
|
||||
b->respawn = get_xy(); b->size = get_xy();
|
||||
b->hint_text = scanline_noblank(f);
|
||||
r.entities.emplace_back(std::move(b));
|
||||
}
|
||||
@@ -328,13 +314,17 @@ void load_map(string fname) {
|
||||
}
|
||||
else err("load_map", s);
|
||||
}
|
||||
for(auto& [c,r]: rooms)
|
||||
for(auto& e: r.entities) if(e->name != "") {
|
||||
while(entity_by_name.count(e->name)) {
|
||||
println(hlog, "error: double entity name: ", e->name);
|
||||
e->name += "'";
|
||||
for(auto& [c,r]: rooms) {
|
||||
for(auto& e: r.entities) {
|
||||
e->hs(resetter);
|
||||
if(e->name != "") {
|
||||
while(entity_by_name.count(e->name)) {
|
||||
println(hlog, "error: double entity name: ", e->name);
|
||||
e->name += "'";
|
||||
}
|
||||
entity_by_name[e->name] = &*e;
|
||||
}
|
||||
}
|
||||
entity_by_name[e->name] = &*e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-2
@@ -10,9 +10,9 @@ room *stable_room;
|
||||
xy stable_where;
|
||||
|
||||
void regenerate_all() {
|
||||
m.hp = m.max_hp();
|
||||
m.hs(fountain_resetter);
|
||||
for(auto& p: powers) p.refill();
|
||||
for(auto& r: rooms) for(auto& e: r.second.entities) e->regenerate();
|
||||
for(auto& r: rooms) for(auto& e: r.second.entities) e->hs(fountain_resetter);
|
||||
revert_all(fountain_revert);
|
||||
current_target = nullptr;
|
||||
shuffle_all();
|
||||
@@ -48,6 +48,13 @@ void statdata::reset() {
|
||||
mods.clear();
|
||||
}
|
||||
|
||||
man::man() {
|
||||
facing = 1; attack_facing = 1;
|
||||
for(auto s: allstats) base_stats[s] = 10;
|
||||
next.reset(); current.reset();
|
||||
hs(fountain_resetter);
|
||||
}
|
||||
|
||||
void man::act() {
|
||||
kino();
|
||||
|
||||
|
||||
+13
-11
@@ -247,14 +247,16 @@ void gen_powers() {
|
||||
|
||||
if(m.experience >= 50) {
|
||||
auto g = std::make_unique<ghost>();
|
||||
g->where = w; g->hp = hp; g->xp = m.experience/2; m.experience -= g->xp; g->postfix();
|
||||
g->extra_invinc = 2 * game_fps;
|
||||
g->where = w; g->ghost_hp = hp; g->ghost_xp = m.experience/2; m.experience -= g->ghost_xp;
|
||||
g->hs(fountain_resetter);
|
||||
cr->entities.emplace_back(std::move(g));
|
||||
}
|
||||
|
||||
auto bones = std::make_unique<item>();
|
||||
bones->qty = 10;
|
||||
bones->where = stable_where;
|
||||
bones->id = gold_id;
|
||||
bones->p = &powers[gold_id];
|
||||
bones->pickup_message = "You got it back.";
|
||||
stable_room->entities.emplace_back(std::move(bones));
|
||||
}
|
||||
@@ -511,15 +513,15 @@ void gen_powers() {
|
||||
if(it == 0 && on && si->existing && !si->bought) {
|
||||
done_something = true;
|
||||
addMessage(si->pickup_message);
|
||||
power_death_revert(powers[si->id]);
|
||||
powers[si->id].qty_owned += si->qty; powers[si->id].qty_filled += si->qty1;
|
||||
power_death_revert(*si->p);
|
||||
si->p->qty_owned += si->qty; si->p->qty_filled += si->qty1;
|
||||
add_revert(death_revert, {"EXIST", si->name});
|
||||
si->existing = false;
|
||||
}
|
||||
else if(it == 0 && on && si->existing && si->bought) {
|
||||
done_something = true;
|
||||
addMessage("You get some gold.");
|
||||
power_death_revert(powers[gold_id]);
|
||||
power_death_revert(*si->p);
|
||||
powers[gold_id].qty_owned += si->price; powers[gold_id].qty_filled += si->price;
|
||||
add_revert(death_revert, {"EXIST", si->name});
|
||||
si->existing = false;
|
||||
@@ -527,30 +529,30 @@ void gen_powers() {
|
||||
else if((it ? !done_something : on) && !si->existing && !si->bought) {
|
||||
done_something = true;
|
||||
addMessage("You rethink your purchase.");
|
||||
power_death_revert(powers[si->id]);
|
||||
powers[si->id].qty_owned -= si->qty; powers[si->id].qty_filled -= si->qty1;
|
||||
power_death_revert(*si->p);
|
||||
si->p->qty_owned -= si->qty; si->p->qty_filled -= si->qty1;
|
||||
add_revert(death_revert, {"UNEXIST", si->name});
|
||||
si->existing = true;
|
||||
}
|
||||
else if((it ? !done_something : on) && !si->existing && si->bought) {
|
||||
done_something = true;
|
||||
addMessage("You rethink your actions.");
|
||||
power_death_revert(powers[gold_id]);
|
||||
power_death_revert(*si->p);
|
||||
powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price;
|
||||
add_revert(death_revert, {"UNEXIST", si->name});
|
||||
si->existing = true;
|
||||
}
|
||||
else if(it == 0 && on_trader && !si->existing && d.p->qty_owned >= si->price) {
|
||||
done_something = true;
|
||||
addMessage("You buy the " + powers[si->id].get_name() + ".");
|
||||
power_death_revert(powers[gold_id]);
|
||||
addMessage("You buy the " + si->p->get_name() + ".");
|
||||
power_death_revert(*si->p);
|
||||
powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price;
|
||||
si->existing = true; si->bought = true;
|
||||
add_revert(death_revert, {"UNBOUGHT", si->name});
|
||||
}
|
||||
else if(it == 0 && on_trader && !si->existing && !si->bought) {
|
||||
done_something = true;
|
||||
addMessage("You have not enough gold to buy the " + powers[si->id].get_name() + ".");
|
||||
addMessage("You have not enough gold to buy the " + si->p->get_name() + ".");
|
||||
}
|
||||
}
|
||||
if(!done_something) addMessage("You count your gold. You have " + its(d.p->qty_owned) + " gold.");
|
||||
|
||||
@@ -53,11 +53,10 @@ randeff trap_snake("Snake Hair", "Lets you create snakes that can be used to dis
|
||||
if(d.mode == rev::start || (d.mode == rev::active && d.keystate == 1)) {
|
||||
auto d = m.get_dat();
|
||||
auto mi = std::make_unique<disnake>();
|
||||
mi->where = m.where + xy(m.facing * m.get_scale() * m.siz().y * 0.45, 0);
|
||||
mi->vel = m.vel + xy(m.facing * d.modv * 2, -d.modv * 3.5);
|
||||
mi->clearg();
|
||||
mi->respawn = m.where + xy(m.facing * m.get_scale() * m.siz().y * 0.45, 0);
|
||||
mi->hs(fountain_resetter);
|
||||
mi->invinc_end = gframeid + 50;
|
||||
mi->postfix();
|
||||
mi->vel = m.vel + xy(m.facing * d.modv * 2, -d.modv * 3.5);
|
||||
mi->dir = m.facing * 2;
|
||||
current_room->entities.emplace_back(std::move(mi));
|
||||
}
|
||||
@@ -109,9 +108,9 @@ randeff fire_spit("Fiery Spit", "Lets you spit fire.", "You feel fire in your mo
|
||||
for(int i=1; i<10; i++) {
|
||||
auto d = m.get_dat();
|
||||
auto mi = std::make_unique<fire_missile>();
|
||||
mi->hs(fountain_resetter);
|
||||
mi->where = m.where + xy(m.facing * m.get_scale() * m.siz().y * 0.45, 0);
|
||||
mi->vel = m.vel + xy(m.facing * d.modv * i, d.modv * (10-i) / 5.);
|
||||
mi->clearg();
|
||||
mi->index = i; mi->power = m.current.stats[stat::wis] * 2 / 5 + 1e-6;
|
||||
current_room->entities.emplace_back(std::move(mi));
|
||||
}
|
||||
|
||||
+2
-2
@@ -25,6 +25,7 @@ Have fun!
|
||||
|
||||
#include "globals.cpp"
|
||||
#include "classes.cpp"
|
||||
#include "staters.cpp"
|
||||
#include "geometry.cpp"
|
||||
#include "entity.cpp"
|
||||
#include "man.cpp"
|
||||
@@ -32,7 +33,7 @@ Have fun!
|
||||
#include "render.cpp"
|
||||
#include "portals.cpp"
|
||||
#include "powers.cpp"
|
||||
#include "save.cpp"
|
||||
#include "load-world.cpp"
|
||||
#include "stats.cpp"
|
||||
#include "randeff.cpp"
|
||||
#include "reverts.cpp"
|
||||
@@ -160,7 +161,6 @@ void playing_frame() {
|
||||
m.where = w1;
|
||||
m.vel *= vmul;
|
||||
switch_to_adjacent_room(cr);
|
||||
m.clearg();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace rogue_unlike {
|
||||
|
||||
// state manager
|
||||
|
||||
struct nop : stater {
|
||||
virtual stater& act(const string& s, int& i, int _i) { return self; }
|
||||
virtual stater& act(const string& s, ld& d, ld _d) { return self; }
|
||||
virtual stater& act(const string& s, bool& b, bool _b) { return self; }
|
||||
virtual stater& act(const string& s, string& w, const string& _w) { return self; }
|
||||
virtual stater& act(const string& s, color_t& c, color_t _c) { return self; }
|
||||
} nop;
|
||||
|
||||
struct changeseeker : stater {
|
||||
bool changed = false;
|
||||
stater& act(const string& s, int& i, int _i) override { if(i != _i) changed = true; return self; }
|
||||
stater& act(const string& s, ld& d, ld _d) override { if(d != _d) changed = true; return self; }
|
||||
stater& act(const string& s, bool& b, bool _b) override { if(b != _b) changed = true; return self; }
|
||||
stater& act(const string& s, string& w, const string& _w) override { if(w != _w) changed = true; return self; }
|
||||
stater& act(const string& s, color_t& c, color_t _c) override { if(c != _c) changed = true; return self; }
|
||||
};
|
||||
|
||||
struct saver : stater {
|
||||
fhstream f;
|
||||
stater& act(const string& s, int& i, int _i) override { if(i != _i) println(f, s, "=", i); return self; }
|
||||
stater& act(const string& s, ld& d, ld _d) override { if(d != _d) println(f, s, "=", d); return self; }
|
||||
stater& act(const string& s, bool& b, bool _b) override { if(b != _b) println(f, s, "=", b); return self; }
|
||||
stater& act(const string& s, string& w, const string& _w) override { if(w != _w) println(f, s, "=", w); return self; }
|
||||
stater& act(const string& s, color_t& c, color_t _c) override { if(c != _c) println(f, s, "=", format("%08X", c)); return self; }
|
||||
};
|
||||
|
||||
struct loader : stater {
|
||||
string name, value;
|
||||
bool loaded = false;
|
||||
stater& act(const string& s, int& i, int _i) override { if(s == name) loaded = true, i = atoi(value.c_str()); return self; }
|
||||
stater& act(const string& s, ld& d, ld _d) override { if(s == name) loaded = true, d = atof(value.c_str()); return self; }
|
||||
stater& act(const string& s, bool& b, bool _b) override { if(s == name) loaded = true, b = atoi(value.c_str()); return self; }
|
||||
stater& act(const string& s, string& w, const string& _w) override { if(s == name) loaded = true, w = value; return self; }
|
||||
stater& act(const string& s, color_t& c, color_t _c) override { if(s == name) loaded = true, sscanf(value.c_str(), "%08X", &c); return self; }
|
||||
};
|
||||
|
||||
struct resetter : stater {
|
||||
stater& act(const string& s, int& i, int _i) override { i = _i; return self; }
|
||||
stater& act(const string& s, ld& d, ld _d) override { d = _d; return self; }
|
||||
stater& act(const string& s, bool& b, bool _b) override { b = _b; return self; }
|
||||
stater& act(const string& s, string& w, const string& _w) override { w = _w; return self; }
|
||||
stater& act(const string& s, color_t& c, color_t _c) override { c = _c; return self; }
|
||||
} resetter;
|
||||
|
||||
struct fountain_resetter : resetter {
|
||||
virtual stater& only_full() { return nop; }
|
||||
} fountain_resetter;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user