diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index d663ca62..0606d2c4 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -114,6 +114,7 @@ struct room { int timed_orb_end; vector> entities; + vector> room_mods; eWall at(int x, int y) { return eWall(block_at[y][x] >> 3); @@ -580,6 +581,17 @@ struct fakesaw : public saw { void act() override; }; +struct room_mod { + virtual void draw() {} + virtual void act() {} + }; + +struct reflector : public room_mod { + xy pos1, pos2; + void draw() override; + void act() override; + }; + /* entities with a defined 'respawn' location */ struct located_entity : public entity { xy respawn; diff --git a/rogueviz/ru/entity.cpp b/rogueviz/ru/entity.cpp index b890bee1..508f1e30 100644 --- a/rogueviz/ru/entity.cpp +++ b/rogueviz/ru/entity.cpp @@ -1105,5 +1105,37 @@ void rollingsaw::act() { } } +void reflector::draw() { + hyperpoint h1 = to_hyper(pos1); + hyperpoint h2 = to_hyper(pos2); + for(int i=0; i<=100; i++) { + hyperpoint h = lerp(h1, h2, i/100.); + auto p = from_hyper(h); + curvepoint(eupush(p.x, p.y) * C0); + } + queuecurve(scrm, 0xFF0000FF, 0, PPR::LINE); + } + +void reflector::act() { + auto x1 = to_hyper(pos1); + auto x2 = to_hyper(pos2); + transmatrix T = gpushxto0(x1); + x2 = T * x2; + transmatrix T1 = spintox(x2); + T = T1 * T; + x2 = T1 * x2; + for(auto& e: current_room->entities) if(e->existing && e->get_name() != "REFLECTOR") { + hyperpoint h_at = T * to_hyper(e->where); + hyperpoint h_was = T * to_hyper(e->where - e->vel); + if(h_at[0] >= 0 && h_at[0] < x2[0]) + if(h_was[0] >= 0 && h_was[0] < x2[0]) + if(h_was[1] > 0 && h_at[1] <= 0) { + h_was[1] *= -1; + h_at[1] *= -1; + e->where = from_hyper(iso_inverse(T) * h_at); + e->vel = e->where - from_hyper(iso_inverse(T) * h_was); + } + } + } } diff --git a/rogueviz/ru/load-world.cpp b/rogueviz/ru/load-world.cpp index 4d5288d7..f6104005 100644 --- a/rogueviz/ru/load-world.cpp +++ b/rogueviz/ru/load-world.cpp @@ -465,6 +465,12 @@ void load_room(fhstream& f, cell *c) { ev.back().wall = eWall(i), ok = true; if(!ok) println(hlog, "warning: SWITCHEVENT wall not recognized"); } + else if(cap == "KREF") { + auto b = std::make_unique(); + b->pos1 = get_xy(); + b->pos2 = get_xy(); + r.room_mods.emplace_back(std::move(b)); + } else println(hlog, "unknown mapline ", s); } else println(hlog, "unknown mapline ", s); diff --git a/rogueviz/ru/render.cpp b/rogueviz/ru/render.cpp index 7db50fad..2d57b091 100644 --- a/rogueviz/ru/render.cpp +++ b/rogueviz/ru/render.cpp @@ -349,6 +349,7 @@ void man::draw() { void render_room_objects(room *r) { initquickqueue(); if(r == current_room && m.visible_inv() && m.existing) m.draw(); + for(auto& e: r->room_mods) e->draw(); for(auto& e: r->entities) if(e->existing && (cmode == mode::editmap || (e->visible(r) && e->visible_inv()))) { if(e->hidden() && !m.can_see(*e)) continue; diff --git a/rogueviz/ru/ru.cpp b/rogueviz/ru/ru.cpp index 2f2f9458..a7d013f4 100644 --- a/rogueviz/ru/ru.cpp +++ b/rogueviz/ru/ru.cpp @@ -150,6 +150,8 @@ vector> new_entities; void playing_frame() { auto& ents = current_room->entities; + for(auto& e: current_room->room_mods) e->act(); + for(auto& e: ents) if(e->existing) e->preact(); m.act();