1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-06-26 15:12:48 +00:00

ru:: magic fountain respawns enemies and refills potions

This commit is contained in:
Zeno Rogue 2025-05-05 10:52:58 +02:00
parent 5a761c43c5
commit 129d3bbe89
7 changed files with 38 additions and 13 deletions

View File

@ -30,6 +30,7 @@ struct power {
hr::function<string()> get_glyph;
hr::function<color_t()> get_color;
hr::function<void(int)> picked_up;
hr::function<void()> 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 {

View File

@ -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<ld>(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<ld>(vel.y, 0)/10) / 2;

View File

@ -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."},

View File

@ -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();
}
}

View File

@ -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) {

View File

@ -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; y<room_y; y++)
for(int x=0; x<room_x; x++) {
if(af && !r->fov[y][x]) continue;

View File

@ -144,13 +144,13 @@ void load_room(fhstream& f, cell *c) {
auto b = std::make_unique<kestrel>();
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<snake>();
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") {