diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index b2fbba52..8e5997fb 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -26,7 +26,7 @@ struct randeff { randeff (string name, string desc, string effect, powerfun act) : name(name), desc(desc), effect(effect), act(act) {} }; -enum class mod { burning, freezing }; +enum class mod { burning, freezing, disarming }; struct power { int key; @@ -214,6 +214,8 @@ struct entity { virtual struct trader* as_trader() { return nullptr; } virtual struct missile* as_missile() { return nullptr; } + virtual bool is_disarmer() override { return false; } + int hp; int invinc_end; @@ -310,7 +312,7 @@ struct entity { struct statdata { statarray stats; int jump_control, coyote_time, hallucinating; - ld detect_area, detect_cross; + ld detect_area, detect_cross, rough_detect; void reset(); vector> mods; }; diff --git a/rogueviz/ru/man.cpp b/rogueviz/ru/man.cpp index a58a7450..afdf8054 100644 --- a/rogueviz/ru/man.cpp +++ b/rogueviz/ru/man.cpp @@ -43,6 +43,7 @@ void statdata::reset() { jump_control = 0; detect_area = 0; detect_cross = 0; + rough_detect = 0; hallucinating = false; mods.clear(); } @@ -139,6 +140,10 @@ void man::launch_attack(power *p, int fac, boxfun f) { for(auto& [m, qty]: p->mods) { if(m == mod::burning) { e->invinc_end = sav; e->attacked(qty); } if(m == mod::freezing) { e->invinc_end = sav; e->attacked(qty); } + if(m == mod::disarming && e->hidden()) { + e->existing = false; + addMessage("You have disarmed a "+e->get_name()+"."); + } } } for(int y=bb.miny; yreplace_block_frev(x, y, wFrozen); addMessage("You freeze the water!"); } + if(m == mod::disarming && b == wRogueWallHidden) { + current_room->replace_block_frev(x, y, wRogueWall); + addMessage("You open a secret passage!"); + } } } } diff --git a/rogueviz/ru/powers.cpp b/rogueviz/ru/powers.cpp index a1b9bb99..55aa7a77 100644 --- a/rogueviz/ru/powers.cpp +++ b/rogueviz/ru/powers.cpp @@ -31,12 +31,14 @@ power& power::be_weapon() { for(auto& [m, qty]: mods) { if(m == mod::burning) s = "flaming " + s; if(m == mod::freezing) s = "freezing " + s; + if(m == mod::disarming) s = "disarming " + s; } return s; }; auto gc = get_color; get_color = [gc, this] { auto col = gc(); for(auto& [m, qty]: mods) { + if(m == mod::disarming) col = 0x4040C0FF; if(m == mod::burning) col = gradient(0xFFFF00FF, 0xFF0000FF, -1, sin(ticks/100), 1); if(m == mod::freezing) col = 0x8080FFFF; } diff --git a/rogueviz/ru/randeff.cpp b/rogueviz/ru/randeff.cpp index 41d001cb..1e325349 100644 --- a/rogueviz/ru/randeff.cpp +++ b/rogueviz/ru/randeff.cpp @@ -50,7 +50,12 @@ randeff trap_detect_cross("Detect cross", "Lets you see traps and secret passage }); randeff trap_snake("Snake Hair", "Lets you create snakes that can be used to disarm traps and secret passages.", "You grow snakes on your head!", [] (data &d) { }); -randeff trap_disarm("Disarm traps", "Lets you see all traps on the level for a short time, and to attack them with your [weapon] to destroy them.", "You suddenly feel able to disarm traps with your [weapon]!", [] (data &d) { }); + +randeff trap_disarm("Disarm traps", "Lets you see all traps on the level for a short time, and to attack them with your [weapon] to destroy them.", "You suddenly feel able to disarm traps with your [weapon]!", [] (data &d) { + m.next.rough_detect = 0.1; + if(d.mode == rev::active) + m.next.mods.emplace_back(d.re->which_weapon, mod::disarming, m.current.stats[stat::wis]); + }); // health powers randeff health_heal("Healing", "Instantly heals you.", "You feel healthier!", [] (data &d) { diff --git a/rogueviz/ru/render.cpp b/rogueviz/ru/render.cpp index 89925c26..78deaa6a 100644 --- a/rogueviz/ru/render.cpp +++ b/rogueviz/ru/render.cpp @@ -287,6 +287,33 @@ void man::draw() { }); } + if(m.current.rough_detect > 0) { + ld r = inverse_wvolarea_auto(m.current.rough_detect); + + auto h0 = to_hyper(m.where); + + bool found = false; + for(auto& e: current_room->entities) if(e->existing && e->hidden() && hdist(h0, to_hyper(e->where)) < r) found = true; + + if(!found) current_room->bfs(xy_to_block(m.where), [&] (intxy xy) { + if(hdist(h0, block_to_hyper(xy)) > r) return false; + auto what = current_room->at(xy); + if(what == wRogueWallHidden) { found = true; return false; } + return true; + }); + + if(found) { + auto T = eupush(h0); + for(int a=0; a<=360; a++) { + auto h = from_hyper(T * xspinpush0(a*1._deg, r)); + curvepoint(eupush(h.x, h.y) * C0); + } + vid.linewidth *= 3; + queuecurve(scrm, 0xFF000080, 0, PPR::LINE); + vid.linewidth /= 3; + } + } + if(m.current.detect_cross > 0) for(int d: {0, 1, 2, 3}) { transmatrix T = eupush(to_hyper(m.where)) * spin(90._deg * d); ld dist = 0;