diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index 53eed51e..18a1ffed 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -30,6 +30,7 @@ struct power { hr::function get_glyph; hr::function get_color; hr::function picked_up; + hr::function refill; power& is_starting(); power& be_weapon(); power& be_resource(string plural); @@ -159,6 +160,7 @@ struct entity { int invinc_end; virtual int max_hp() { return 100; } + virtual void regenerate() {} virtual bool visible(room *r); @@ -312,6 +314,7 @@ struct enemy : public entity { int num_kills; void on_kill() override { entity::on_kill(); num_kills++; } enemy() { num_kills = 0; postfix(); } + void regenerate() override { where = respawn; vel = xy(0, 0); existing = true; hp = max_hp(); } }; @@ -326,7 +329,7 @@ struct boar : public enemy { }; struct snake : public enemy { - int dir; + int dir, respawn_dir; xy siz() override { return {18, 8}; } string glyph() override { return "S"; } color_t color() override { return 0x20D020FF; } @@ -334,9 +337,11 @@ 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; } }; struct kestrel : public enemy { + xy respawn_vel; xy siz() override { return {10, 10}; } string glyph() override { return "K"; } color_t color() override { return 0xD0A0A0FF; } @@ -344,6 +349,7 @@ 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; } }; struct bat : public enemy { diff --git a/rogueviz/ru/entity.cpp b/rogueviz/ru/entity.cpp index 0182f1b5..d1d7dffc 100644 --- a/rogueviz/ru/entity.cpp +++ b/rogueviz/ru/entity.cpp @@ -141,10 +141,6 @@ void entity::apply_walls() { for(int x = obb.maxx; x < jbb.maxx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { eWall b = current_room->at(x, y); - if(b == wFountain0) { - current_room->replace_block(x, y, wFountain1); - addMessage("A magic fountain! You feel safe and refill your potions."); - } if(walls[b].flags & W_BLOCK) { if(freezing()) { hit_wall(); } vel.x = (vel.x - max(vel.y, 0)/10) / 2; @@ -156,10 +152,6 @@ void entity::apply_walls() { for(int x = jbb.minx; x < obb.minx; x++) for(int y = jbb.miny; y < jbb.maxy; y++) { eWall b = current_room->at(x, y); - if(b == wFountain0) { - current_room->replace_block(x, y, wFountain1); - addMessage("A magic fountain! You feel safe and refill your potions."); - } if(walls[b].flags & W_BLOCK) { if(freezing()) { hit_wall(); } vel.x = (vel.x + max(vel.y, 0)/10) / 2; diff --git a/rogueviz/ru/globals.cpp b/rogueviz/ru/globals.cpp index 69ae86d4..5e5729ce 100644 --- a/rogueviz/ru/globals.cpp +++ b/rogueviz/ru/globals.cpp @@ -55,7 +55,7 @@ struct ruwall { string help; }; -enum eWall { wAir, wWall, wBouncy, wSpike, wWater, wFrozen, wDoor, wSmashedDoor, wLockedDoor, wFountain0, wFountain1, wBluePortal, wOrangePortal, wPlatform, wStaircase, wColumn, wForge, wGUARD }; +enum eWall { wAir, wWall, wBouncy, wSpike, wWater, wFrozen, wDoor, wSmashedDoor, wLockedDoor, wFountain, wBluePortal, wOrangePortal, wPlatform, wStaircase, wColumn, wForge, wGUARD }; flagtype W_BLOCK = 1; flagtype W_TRANS = 2; @@ -79,7 +79,6 @@ ruwall walls[qwall] = { {"smashed door", "'", 0xC06000FF, W_TRANS, "This door has been already opened."}, {"locked door", "+", 0xA05000FF, W_BLOCK, "What is behind this door is not your business."}, {"magic fountain", "!", 0x8080C0FF, W_TRANS, "Wow! A magic fountain!"}, - {"magic fountain (active)", "!", 0xA0A0FFFF, W_TRANS, "Wow! An active magic fountain!"}, {"blue portal", "=", 0x4040C0FF, W_TRANS, "Blue portal."}, {"orange portal", "=", 0xC08040FF, W_TRANS, "Orange portal."}, {"platform", "-", 0xFFFFFFFF, W_PLATFORM | W_TRANS | W_BLOCKBIRD, "You can fall down through such platforms."}, diff --git a/rogueviz/ru/man.cpp b/rogueviz/ru/man.cpp index d076572d..261b13a4 100644 --- a/rogueviz/ru/man.cpp +++ b/rogueviz/ru/man.cpp @@ -2,6 +2,28 @@ namespace rogue_unlike { void handle_powers(data& d); +bool on_fountain; +room *fountain_room; + +void check_fountains() { + bool next_on_fountain = false; + auto bb = pixel_to_block(m.get_pixel_bbox()); + for(int x = bb.minx; x < bb.maxx; x++) for(int y = bb.miny; y < bb.maxy; y++) { + eWall b = current_room->at(x, y); + println(hlog, tuple(x, y, int(b))); + if(b == wFountain) next_on_fountain = true; + } + if(next_on_fountain && !on_fountain) { + fountain_room = current_room; + addMessage("A magic fountain! You feel safe and refill your potions."); + m.hp = m.max_hp(); + for(auto& p: powers) p.refill(); + for(auto& r: rooms) for(auto& e: r.second.entities) e->regenerate(); + current_target = nullptr; + } + swap(on_fountain, next_on_fountain); + } + void man::act() { kino(); @@ -31,6 +53,8 @@ void man::act() { if(dat.dx) facing = dat.dx; current_room->fov_from(where.x / block_x, where.y / block_y); + + check_fountains(); } } diff --git a/rogueviz/ru/powers.cpp b/rogueviz/ru/powers.cpp index 9054b385..d74d6a9e 100644 --- a/rogueviz/ru/powers.cpp +++ b/rogueviz/ru/powers.cpp @@ -41,6 +41,7 @@ void power::init() { get_color = [this] { return color; }; get_glyph = [this] { return glyph; }; picked_up = [this] (int x) { qty_filled += x; qty_owned += x; }; + refill = [this] {}; } power& gen_power(int key, string name, string desc, string glyph, color_t color, powerfun pf) { diff --git a/rogueviz/ru/render.cpp b/rogueviz/ru/render.cpp index 5219fe49..031fb301 100644 --- a/rogueviz/ru/render.cpp +++ b/rogueviz/ru/render.cpp @@ -136,6 +136,9 @@ void compute_scrm() { void render_room_walls(room *r) { initquickqueue(); bool af = should_apply_fov(); + + walls[wFountain].color = (r == fountain_room) ? 0xA0A0FFFF : 0x8080C0FF; + for(int y=0; yfov[y][x]) continue; diff --git a/rogueviz/ru/save.cpp b/rogueviz/ru/save.cpp index b9fb9c3f..31865cdf 100644 --- a/rogueviz/ru/save.cpp +++ b/rogueviz/ru/save.cpp @@ -144,13 +144,13 @@ void load_room(fhstream& f, cell *c) { auto b = std::make_unique(); 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 = b->where; b->respawn_vel = b->vel; r.entities.emplace_back(std::move(b)); } else if(cap == "SNAKE") { auto b = std::make_unique(); sscanf(param.c_str(), "%lf%lf%d", &b->where.x, &b->where.y, &b->dir); - b->respawn = b->where; + b->respawn = b->where; b->respawn_dir = b->dir; r.entities.emplace_back(std::move(b)); } else if(cap == "FERRIS") {