diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..2461de6a --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "rogueviz/seuphorica"] + path = rogueviz/seuphorica + url = https://github.com/zenorogue/seuphorica.git diff --git a/attack.cpp b/attack.cpp index 4d01f20f..a9c447a5 100644 --- a/attack.cpp +++ b/attack.cpp @@ -189,13 +189,13 @@ EX bool petrify(cell *c, eWall walltype, eMonster m) { if(c->land == laWestWall) return false; + if(do_not_touch_this_wall(c)) return false; + if(isWateryOrBoat(c) && c->land == laWhirlpool) { c->wall = waSea; return false; } - if(c->wall == waRoundTable) return false; - if(walltype == waGargoyle && cellUnstableOrChasm(c)) walltype = waGargoyleFloor; else if(walltype == waGargoyle && isWatery(c)) diff --git a/barriers.cpp b/barriers.cpp index a9d78a05..64327202 100644 --- a/barriers.cpp +++ b/barriers.cpp @@ -844,16 +844,18 @@ EX bool buildBarrier6(cellwalker cw, eLand m0, eLand m1) { setland((b[d+1]-2).cpeek(), m1); setland((b[d+1]+2).cpeek(), m0); } - int cp = curse_percentage; - if(m0 == laCrossroads6 || m1 == laCrossroads6) { - cp = 25; - if(m0 == laCursed || m1 == laCursed) cp = 100; - } - if(hrand(100) < cp) { - setland(cw.at, laCursed); - cw.at->wall = waRubble; - cw.at->monst = moHexer; - cw.at->item = random_curse(); + if(isLandIngame(laCursed)) { + int cp = curse_percentage; + if(m0 == laCrossroads6 || m1 == laCrossroads6) { + cp = 25; + if(m0 == laCursed || m1 == laCursed) cp = 100; + } + if(hrand(100) < cp) { + setland(cw.at, laCursed); + cw.at->wall = waRubble; + cw.at->monst = moHexer; + cw.at->item = random_curse(); + } } return true; diff --git a/complex.cpp b/complex.cpp index 3aca2509..3de3bb76 100644 --- a/complex.cpp +++ b/complex.cpp @@ -2721,7 +2721,7 @@ EX namespace dragon { c->monst = moNone; if(checkOrb(who, itOrbUndeath)) c->monst = moFriendlyGhost; - if(checkOrb(who, itOrbStone)) + if(!do_not_touch_this_wall(c) && checkOrb(who, itOrbStone)) c->wparam = m, c->wall = waPetrified; else if(c->wall == waFire) { if(delay) delay = false; @@ -2993,13 +2993,13 @@ EX namespace kraken { if(checkOrb(who, itOrbUndeath)) c->monst = moFriendlyGhost; if(c->land == laKraken && !c->item) c->item = itKraken; kills[moKrakenH]++; - if(checkOrb(who, itOrbStone)) c->wall = waNone; + if(!do_not_touch_this_wall(c) && checkOrb(who, itOrbStone)) c->wall = waNone; forCellEx(c1, c) if(c1->monst == moKrakenT) { changes.ccell(c1); drawParticles(c, minf[moKrakenT].color, 16); c1->monst = moNone; - if(checkOrb(who, itOrbStone)) { + if(!do_not_touch_this_wall(c1) && checkOrb(who, itOrbStone)) { if(isWatery(c1)) c1->wall = waNone; else diff --git a/config.cpp b/config.cpp index 5776cb42..f6c34b1b 100644 --- a/config.cpp +++ b/config.cpp @@ -1207,6 +1207,14 @@ EX void initConfig() { param_b(keybd_subdir_enabled, "keybd_subdir_enabled", 0)->editable("control the pushing direction with TAB", 'P')->help("If set, you control the off-heptagon pushing direction with TAB. Otherwise, you control it by rotating the screen."); + param_str(pinnedglyphs, "pinned_glyphs", "") + ->set_standard_editor(true) + ->editable("pinned glyphs", + "A list of glyphs to always sort at the front, " + "and reserve space for even when they're not being displayed.", + 'p') + ->set_reaction(updateglyphpinned); + param_enum(glyphsortorder, parameter_names("glyph_sort", "glyph sort order"), glyphsortorder) ->editable({ {"first on top", ""}, @@ -1224,6 +1232,11 @@ EX void initConfig() { {"icons", ""}, }, "orb display mode", 'o'); + param_b(orb_treasure_gap, "orb_treasure_gap", false) + ->editable("gap between orbs and treasures", 'G') + -> help("If set, a gap row will be left between orbs and treasures in the HUD") + -> set_reaction([] { vid.killreduction = 0; }); + param_b(less_in_landscape, "less_in_landscape", false) ->editable("less items/kills in landscape", 'L') -> help("If set, only the important items and kills will be shown") @@ -2564,6 +2577,7 @@ EX void configureInterface() { if(hr_hud_enabled) { add_edit(glyphsortorder); add_edit(vid.graphglyph); + add_edit(orb_treasure_gap); add_edit(less_in_landscape); add_edit(less_in_portrait); add_edit(display_yasc_codes); @@ -3522,6 +3536,9 @@ EX int config3 = addHook(hooks_configfile, 100, [] { ->set_sets([] { dialog::bound_low(1); }) ->set_reaction([] { if(game_active) { stop_game(); start_game(); } }); + param_enum(warn_before_killing_friends, "warn_before_killing_friends", 2) + ->editable({{"OFF", "never warn"}, {"TAME_BOMBERBIRDS", "warn only for Tame Bomberbirds"}, {"ON", "always warn"}}, "warn before killing friendly monsters", 'W'); + param_i(curse_percentage, "curse_percentage")->editable(0, 100, 1, "curse percentage", "The percentage of towers in Cursed Walls mode to be manned by Canyon Hags", 'R') diff --git a/debug.cpp b/debug.cpp index e7b34388..1821474c 100644 --- a/debug.cpp +++ b/debug.cpp @@ -123,6 +123,18 @@ vector cheats = { kills[moCultist] = qkills; kills[moTroll] = qkills; }}, + cheatkey{'H', "toggle hold of orb powers", [] { + if(cheat_items_enabled) { + cheat_items_enabled = false; + addMessage(XLAT("Hold of orb powers disabled!")); + } + else { + cheat_items = items; + cheat_items_enabled = true; + cheater++; + addMessage(XLAT("Hold of orb powers enabled!")); + } + }}, cheatkey{'M', "deplete orb powers", [] { for(int i=0; i= 0 && i < glyphs) glyphpinned[i] = true; + } while(ep.eat(",")); + } + } + +EX void updatepinnedglyphs() { + std::stringstream ss; + for(int i=0; i glyphpinned[j]; if(subclass(i) != subclass(j)) return subclass(i) < subclass(j); if(glyphsortorder == gsoFirstTop) @@ -462,7 +487,7 @@ EX void draw_crosshair() { return; } -EX bool less_in_portrait, less_in_landscape; +EX bool less_in_portrait, less_in_landscape, orb_treasure_gap; EX string mode_description() { string md; @@ -560,7 +585,7 @@ EX void drawStats() { else if(cornermode) { int bycorner[4]; for(int u=0; u<4; u++) bycorner[u] = 0; - for(int i=0; i glyphstoshow; for(int i=0; i columns) { vid.killreduction++; continue; } coltaken = 0; @@ -651,7 +678,7 @@ EX void drawStats() { for(int i0=0; i0= rows) rowid[z] = 0, colid[z]++; - displayglyph2(cx, cy, buttonsize, i); + if(ikappear(i)) displayglyph2(cx, cy, buttonsize, i); } } } diff --git a/items.cpp b/items.cpp index 6da798ce..f29441f3 100644 --- a/items.cpp +++ b/items.cpp @@ -14,6 +14,9 @@ EX int currentLocalTreasure; /** for treasures, the number collected; for orbs, the number of charges */ EX array items; +EX array cheat_items; +EX bool cheat_items_enabled; + EX map > hiitems; EX bool pickable_from_water(eItem it) { @@ -30,6 +33,8 @@ EX bool canPickupItemWithMagnetism(cell *c, cell *from) { return false; if(c->item == itCompass && from->item) return false; + if(saved_tortoise_on(c)) + return false; return true; } @@ -41,7 +46,7 @@ EX bool doPickupItemsWithMagnetism(cell *c) { cw += wstep; for(int j=1; jtype; j++) { cell *c4 = (cw+j).peek(); - if(!isNeighbor(c, c4) && c3->item && !c4->item && passable(c4, c3, ZERO)) { + if(!isNeighbor(c, c4) && c3->item && !c4->item && !saved_tortoise_on(c3) && passable(c4, c3, ZERO)) { changes.ccell(c3); changes.ccell(c4); moveItem(c3, c4, false); diff --git a/landlock.cpp b/landlock.cpp index fedf0bd7..f5854521 100644 --- a/landlock.cpp +++ b/landlock.cpp @@ -221,11 +221,15 @@ EX bool landUnlockedRPM(eLand n) { } EX int lands_for_hell() { - return casual ? 40 : 9; + int desired = casual ? 40 : 9; + int available = std::count_if(land_over.begin(), land_over.end(), [] (eLand l) { return !among(l, laHell, laCocytus, laPower) && !isCrossroads(l) && isLandIngame(l); }); + return min(desired, available); } EX int lands_for_cr3() { - return casual ? 20 : 9; + int desired = casual ? 20 : 9; + int available = std::count_if(land_over.begin(), land_over.end(), [] (eLand l) { return !isCrossroads(l) && isLandIngame(l); }); + return min(desired, available); } EX int variant_unlock_value() { diff --git a/mapeditor.cpp b/mapeditor.cpp index eb6cddb3..ebf8ae73 100644 --- a/mapeditor.cpp +++ b/mapeditor.cpp @@ -1096,7 +1096,7 @@ EX namespace mapstream { if(shmup::on) shmup::init(); - timerstart = time(NULL); turncount = 0; + timerstart = time(NULL); turncount = 0; lastexplore = 0; sagephase = 0; hardcoreAt = 0; timerstopped = false; savecount = 0; savetime = 0; diff --git a/mapeffects.cpp b/mapeffects.cpp index 80c9179e..ec56fb01 100644 --- a/mapeffects.cpp +++ b/mapeffects.cpp @@ -160,7 +160,7 @@ EX bool earthFloor(cell *c) { if(c->monst) return false; if(c->wall == waDeadwall) { c->wall = waDeadfloor; return true; } if(c->wall == waDune) { c->wall = waNone; return true; } - if(c->wall == waStone && c->land != laTerracotta) { c->wall = waNone; return true; } + if(c->wall == waStone && !among(c->land, laTerracotta, laMercuryRiver, laVariant)) { c->wall = waNone; return true; } if(c->wall == waAncientGrave || c->wall == waFreshGrave || c->wall == waRuinWall) { c->wall = waNone; return true; @@ -259,11 +259,11 @@ EX bool earthWall(cell *c) { c->wall = waChasm; return true; } - if(c->wall == waNone && c->land == laTerracotta) { + if(c->wall == waNone && among(c->land, laTerracotta, laMercuryRiver)) { c->wall = waMercury; return true; } - if(c->wall == waArrowTrap && c->land == laTerracotta) { + if(c->wall == waArrowTrap && among(c->land, laTerracotta, laMercuryRiver)) { destroyTrapsOn(c); c->wall = waMercury; return true; diff --git a/menus.cpp b/menus.cpp index c99bc70f..0f93d480 100644 --- a/menus.cpp +++ b/menus.cpp @@ -181,6 +181,11 @@ EX void showOverview() { } else if(udiv == 2 && umod < ittypes) { gotoHelp(generateHelpForItem(eItem(umod))); + help_extensions.push_back(help_extension{'p', glyphpinned[umod] ? XLAT("unpin from HUD") : XLAT("pin to HUD"), [umod] () { + glyphpinned[umod] ^= true; + updatepinnedglyphs(); + popScreen(); + }}); if(cheater) { dialog::helpToEdit(items[umod], 0, 200, 10, 10); dialog::get_ne().reaction = [] () { diff --git a/orbs.cpp b/orbs.cpp index af8ed506..15e2f96e 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -50,7 +50,7 @@ EX void useupOrb(eItem it, int qty) { } EX void drainOrb(eItem it, int target IS(0)) { - if(items[it] > target) useupOrb(it, items[it] - target); + if(!cheat_items_enabled && items[it] > target) useupOrb(it, items[it] - target); } EX void empathyMove(const movei& mi) { @@ -233,6 +233,14 @@ EX void reduceOrbPowers() { else items[itCrossbow]--; } + if(cheat_items_enabled) + for(int i=0; iwall = p.first[0]; c->wparam = p.first[0]; forCellEx(c1, c) { - if(c1->wall != waBarrier) + if(c1->wall != waBarrier && c1->land == c->land) c1->wparam = c1->wall = p.first[idx]; idx++; }