You can subscribe to this list here.
2006 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(15) |
Sep
(131) |
Oct
(149) |
Nov
(216) |
Dec
(222) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2007 |
Jan
(152) |
Feb
(58) |
Mar
(184) |
Apr
(249) |
May
(96) |
Jun
(207) |
Jul
(248) |
Aug
(87) |
Sep
(232) |
Oct
(440) |
Nov
(248) |
Dec
(212) |
2008 |
Jan
(216) |
Feb
(118) |
Mar
(508) |
Apr
(796) |
May
(597) |
Jun
(896) |
Jul
(475) |
Aug
(124) |
Sep
(200) |
Oct
(248) |
Nov
(377) |
Dec
(373) |
2009 |
Jan
(807) |
Feb
(430) |
Mar
(276) |
Apr
(138) |
May
(161) |
Jun
(210) |
Jul
(390) |
Aug
(141) |
Sep
(286) |
Oct
(826) |
Nov
(1123) |
Dec
(419) |
2010 |
Jan
(671) |
Feb
(625) |
Mar
(328) |
Apr
(349) |
May
(296) |
Jun
(485) |
Jul
(396) |
Aug
(113) |
Sep
(582) |
Oct
(414) |
Nov
(248) |
Dec
(377) |
2011 |
Jan
(400) |
Feb
(225) |
Mar
(321) |
Apr
(264) |
May
(148) |
Jun
(249) |
Jul
(270) |
Aug
(217) |
Sep
(262) |
Oct
(356) |
Nov
(426) |
Dec
(359) |
2012 |
Jan
(203) |
Feb
(131) |
Mar
(317) |
Apr
(313) |
May
(170) |
Jun
(272) |
Jul
(363) |
Aug
(364) |
Sep
(330) |
Oct
(188) |
Nov
(178) |
Dec
(141) |
2013 |
Jan
(177) |
Feb
(258) |
Mar
(459) |
Apr
(352) |
May
(443) |
Jun
(364) |
Jul
(185) |
Aug
(175) |
Sep
(242) |
Oct
(237) |
Nov
(359) |
Dec
(300) |
2014 |
Jan
(331) |
Feb
(272) |
Mar
(446) |
Apr
(301) |
May
(577) |
Jun
(435) |
Jul
(365) |
Aug
(358) |
Sep
(306) |
Oct
(617) |
Nov
(863) |
Dec
(466) |
2015 |
Jan
(295) |
Feb
(165) |
Mar
(319) |
Apr
(201) |
May
(158) |
Jun
(148) |
Jul
(62) |
Aug
(91) |
Sep
(147) |
Oct
(203) |
Nov
(346) |
Dec
(382) |
2016 |
Jan
(242) |
Feb
(280) |
Mar
(229) |
Apr
(157) |
May
(297) |
Jun
(335) |
Jul
(157) |
Aug
(219) |
Sep
(307) |
Oct
(212) |
Nov
(177) |
Dec
(112) |
2017 |
Jan
(100) |
Feb
(203) |
Mar
(112) |
Apr
(124) |
May
(81) |
Jun
(43) |
Jul
(39) |
Aug
(49) |
Sep
(24) |
Oct
(55) |
Nov
(68) |
Dec
(95) |
2018 |
Jan
(130) |
Feb
(73) |
Mar
(47) |
Apr
(57) |
May
(62) |
Jun
(76) |
Jul
(159) |
Aug
(158) |
Sep
(81) |
Oct
(100) |
Nov
(62) |
Dec
(75) |
2019 |
Jan
(130) |
Feb
(138) |
Mar
(80) |
Apr
(61) |
May
(88) |
Jun
(65) |
Jul
(61) |
Aug
(37) |
Sep
(85) |
Oct
(155) |
Nov
(133) |
Dec
(91) |
2020 |
Jan
(59) |
Feb
(123) |
Mar
(121) |
Apr
(155) |
May
(300) |
Jun
(136) |
Jul
(330) |
Aug
(84) |
Sep
(56) |
Oct
(87) |
Nov
(154) |
Dec
(200) |
2021 |
Jan
(205) |
Feb
(203) |
Mar
(292) |
Apr
(165) |
May
(56) |
Jun
(135) |
Jul
(248) |
Aug
(218) |
Sep
(165) |
Oct
(150) |
Nov
(135) |
Dec
(266) |
2022 |
Jan
(194) |
Feb
(149) |
Mar
(49) |
Apr
(38) |
May
(145) |
Jun
(213) |
Jul
(150) |
Aug
(126) |
Sep
(188) |
Oct
(121) |
Nov
(34) |
Dec
(142) |
2023 |
Jan
(105) |
Feb
(82) |
Mar
(138) |
Apr
(125) |
May
(112) |
Jun
(90) |
Jul
(222) |
Aug
(279) |
Sep
(157) |
Oct
(100) |
Nov
(85) |
Dec
(295) |
2024 |
Jan
(123) |
Feb
(353) |
Mar
(220) |
Apr
(112) |
May
(162) |
Jun
(169) |
Jul
(205) |
Aug
(174) |
Sep
(73) |
Oct
(62) |
Nov
(95) |
Dec
(62) |
2025 |
Jan
(125) |
Feb
(90) |
Mar
(127) |
Apr
(188) |
May
(74) |
Jun
(59) |
Jul
(154) |
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
From: <gi...@cr...> - 2025-07-11 10:40:34
|
via 77d58bd2100bb11ffeab9c7a04fb03be70d4e45d (commit) via b7c2e1d855219a9b867eeb221698a9f4ba1a647d (commit) via 7c6d325bc265f633814e8b385bd99b203b1cef93 (commit) via c6894e477c601c286bc8424506c9bb80e190084e (commit) via b873afd9ec3d35eefd53920da16130b7959612d6 (commit) via ff7e82441f3a8dd63c3da6cedf01375270e93ccd (commit) via 8903f4d545fb1a6463b2b6f2b865e772d1dfc1a2 (commit) from 71506e332b858dde8cde902e42d1823f00edc394 (commit) ----------------------------------------------------------------------- commit 77d58bd2100bb11ffeab9c7a04fb03be70d4e45d Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 08:07:07 2025 -0230 Fix Figment icon not rendering in webtiles commit b7c2e1d855219a9b867eeb221698a9f4ba1a647d Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:54:31 2025 -0230 Fix piety troves reporting their cost as "be buggy" (Ogregutan) (On the dungeon overview screen) commit 7c6d325bc265f633814e8b385bd99b203b1cef93 Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:54:01 2025 -0230 Fix a Yred reaping crash if Ostracised to 0 piety (Ogregutan) commit c6894e477c601c286bc8424506c9bb80e190084e Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:48:00 2025 -0230 Fix a force_more on allies getting banes (Lici) Turns out 'Doom befalls you' also matches 'Doom befalls your [something]'. commit b873afd9ec3d35eefd53920da16130b7959612d6 Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:47:16 2025 -0230 New option: always_show_doom_contam (Particleface) If true, this displays the doom and contam meters in the upper-right of the sidebar, regardless of whether the player currently has any doom or contam. commit ff7e82441f3a8dd63c3da6cedf01375270e93ccd Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:18:27 2025 -0230 Don't announce "You feel the reach of Zot diminish." for both tesseracts commit 8903f4d545fb1a6463b2b6f2b865e772d1dfc1a2 Author: DracoOmega <dra...@gm...> Date: Fri Jul 11 07:17:33 2025 -0230 Fix a crash with banishing a boundless tesseract (WizardIke) ----------------------------------------------------------------------- Summary of changes: crawl-ref/docs/options_guide.txt | 5 +++++ crawl-ref/source/dat/defaults/messages.txt | 2 +- crawl-ref/source/dat/dlua/lm_trove.lua | 2 +- crawl-ref/source/initfile.cc | 2 ++ crawl-ref/source/mon-death.cc | 7 +++++-- crawl-ref/source/options.h | 1 + crawl-ref/source/output.cc | 13 ++++++++----- crawl-ref/source/religion.cc | 2 +- .../source/webserver/game_data/static/cell_renderer.js | 1 + crawl-ref/source/webserver/game_data/static/player.js | 7 +++++-- 10 files changed, 30 insertions(+), 12 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index cb72c5bfc7..d0c1f42cc0 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1915,6 +1915,11 @@ show_resist_percent = true from each element, based on their current pips of resistance, will be shown on the % screen. +always_show_doom_contam = false + If set to true, always display the doom and contam meters in the + upper-right of the side panel, even if the player doesn't currently + have any doom or contamination. + 3-i Colours (messages and menus) ----------------- diff --git a/crawl-ref/source/dat/defaults/messages.txt b/crawl-ref/source/dat/defaults/messages.txt index d5487c221a..bb9ecd8f70 100644 --- a/crawl-ref/source/dat/defaults/messages.txt +++ b/crawl-ref/source/dat/defaults/messages.txt @@ -152,7 +152,7 @@ force_more_message += You are slowing down force_more_message += You fall asleep # Banes -force_more_message += befalls you +force_more_message += befalls you.... force_more_message += upon you is lifted # Abyss exits and rune diff --git a/crawl-ref/source/dat/dlua/lm_trove.lua b/crawl-ref/source/dat/dlua/lm_trove.lua index 834f7b2330..621ebcbd35 100644 --- a/crawl-ref/source/dat/dlua/lm_trove.lua +++ b/crawl-ref/source/dat/dlua/lm_trove.lua @@ -133,7 +133,7 @@ function TroveMarker:overview_note (marker) else return "give " .. self:item_name(false) end - elseif toll.type == "piety" then + elseif toll.type == "nopiety" then return "lose all piety" elseif toll.type == "bane" then return "suffer the " .. crawl.bane_name(toll.bane) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 057bd69cb8..1dd920756d 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -474,6 +474,7 @@ const vector<GameOption*> game_options::build_options_list() new BoolGameOption(SIMPLE_NAME(warn_hatches), false), new BoolGameOption(SIMPLE_NAME(warn_contam_cost), false), new BoolGameOption(SIMPLE_NAME(show_resist_percent), true), + new BoolGameOption(SIMPLE_NAME(always_show_doom_contam), false), new BoolGameOption(SIMPLE_NAME(enable_recast_spell), true), new BoolGameOption(SIMPLE_NAME(auto_hide_spells), false), new BoolGameOption(SIMPLE_NAME(blink_brightens_background), false), @@ -5393,6 +5394,7 @@ void game_options::write_webtiles_options(const string& name) tiles.json_write_int("glyph_mode_font_size", glyph_mode_font_size); tiles.json_write_bool("show_game_time", show_game_time); + tiles.json_write_bool("always_show_doom_contam", always_show_doom_contam); // TODO: convert action_panel_show into a yes/no/never option. It would be // better to have a more straightforward way of disabling the panel diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 3cded79120..8dee26a8a0 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -3163,12 +3163,14 @@ item_def* monster_die(monster& mons, killer_type killer, // Must be done after health is set to zero and monster is properly marked dead. if (mons.type == MONS_BOUNDLESS_TESSERACT) { - mprf(MSGCH_ORB, "You feel the reach of Zot diminish."); // Remove all non-rewarding spawns, along with the other tesseract. for (monster_iterator mi; mi; ++mi) { - if (mi->type == MONS_BOUNDLESS_TESSERACT && mi->mid != mons.mid) + if (mi->type == MONS_BOUNDLESS_TESSERACT && mi->mid != mons.mid + && !(mi->flags & MF_BANISHED)) + { monster_die(**mi, killer, killer_index); + } else if ((mi->flags & (MF_HARD_RESET | MF_NO_REWARD) && mi->props.exists(BLAME_KEY))) { @@ -3187,6 +3189,7 @@ item_def* monster_die(monster& mons, killer_type killer, if (you.props.exists(TESSERACT_START_TIME_KEY)) { + mprf(MSGCH_ORB, "You feel the reach of Zot diminish."); mark_milestone("tesseract.kill", "destroyed the tesseracts."); you.props.erase(TESSERACT_START_TIME_KEY); } diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 753fe3100c..0c8b7d9bb0 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -516,6 +516,7 @@ public: bool warn_hatches; // offer a y/n prompt when the player uses an escape hatch bool warn_contam_cost; // Prompt when casting a spell like Irradiate, with dangerous contam. bool show_resist_percent; // Show resist percentages on the % screen + bool always_show_doom_contam; // Always show doom/contam meters, even without doom/contam bool enable_recast_spell; // Allow recasting spells with 'z' Enter. skill_focus_mode skill_focus; // is the focus skills available bool auto_hide_spells; // hide new spells diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index e2a6f5744e..138e55ac4e 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1040,7 +1040,7 @@ static void _print_stats_doom(int x, int y) // Hide the bar entirely if there is no active doom (since that will be true // most of the time). - if (you.attribute[ATTR_DOOM] == 0) + if (you.attribute[ATTR_DOOM] == 0 && !Options.always_show_doom_contam) { CPRINTF(" "); return; @@ -1056,8 +1056,10 @@ static void _print_stats_doom(int x, int y) textcolour(LIGHTRED); else if (you.attribute[ATTR_DOOM] >= 25) textcolour(YELLOW); - else + else if (you.attribute[ATTR_DOOM] > 0) textcolour(LIGHTGRAY); + else + textcolour(DARKGRAY); CPRINTF("%d%% ", you.attribute[ATTR_DOOM]); you.redraw_doom = false; @@ -1068,9 +1070,9 @@ static void _print_stats_contam(int x, int y) CGOTOXY(x, y, GOTO_STAT); // Hide the bar entirely if the player has no contam - if (you.magic_contamination == 0) + if (you.magic_contamination == 0 && !Options.always_show_doom_contam) { - CPRINTF(" "); + CPRINTF(" "); return; } @@ -1078,7 +1080,8 @@ static void _print_stats_contam(int x, int y) textcolour(HUD_CAPTION_COLOUR); CPRINTF("Contam: "); - const int contam = max(1, you.magic_contamination / 10); + const int contam = max(you.magic_contamination > 0 ? 1 : 0, + you.magic_contamination / 10); if (contam >= 200) textcolour(RED); else if (contam >= 100) diff --git a/crawl-ref/source/religion.cc b/crawl-ref/source/religion.cc index d710794752..31db4eb5d3 100644 --- a/crawl-ref/source/religion.cc +++ b/crawl-ref/source/religion.cc @@ -1131,7 +1131,7 @@ bool yred_reap_chance() int ratio = min(piety_breakpoint(5), (int)you.piety()) * 100 / piety_breakpoint(5); int min_chance = 15 + (25 * ratio / 100); - ratio = min(100, (hd * 100 / you.piety() * 4)); + ratio = min(100, (hd * 100 / max(you.piety() * 4, 1))); int chance = (ratio * min_chance / 100) + ((100 - ratio)); return x_chance_in_y(chance, 100); diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index 395fcee6b3..d5d761df8d 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -1174,6 +1174,7 @@ function ($, view_data, gui, main, tileinfo_player, icons, dngn, enums, case icons.VEXED: case icons.PARADOX: case icons.WARDING: + case icons.FIGMENT: this.draw_icon(idx, x, y, ofsx, ofsy, img_scale); return 10; case icons.CONSTRICTED: diff --git a/crawl-ref/source/webserver/game_data/static/player.js b/crawl-ref/source/webserver/game_data/static/player.js index c4b51dda3a..fa22084f1c 100644 --- a/crawl-ref/source/webserver/game_data/static/player.js +++ b/crawl-ref/source/webserver/game_data/static/player.js @@ -290,7 +290,7 @@ function ($, comm, client, enums, map_knowledge, messages, options, util) { function update_doom() { - if (player.doom == 0) + if (player.doom == 0 && options.get("always_show_doom_contam") === false) { $("#stats_doom_ui").hide(); return; @@ -303,12 +303,15 @@ function ($, comm, client, enums, map_knowledge, messages, options, util) { elem.text(" " + val + "%"); var colour = "fg7"; + if (player.doom == 0) + colour = "fg8"; if (player.doom >= 75) colour = "fg5"; else if (player.doom >= 50) colour = "fg12"; else if (player.doom >= 25) colour = "fg14"; + elem.addClass(colour); $("#stats_doom").html(elem); @@ -323,7 +326,7 @@ function ($, comm, client, enums, map_knowledge, messages, options, util) { function update_contam() { - if (player.contam == 0) + if (player.contam == 0 && options.get("always_show_doom_contam") === false) { $("#stats_contam_ui").hide(); return; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-11 07:05:14
|
via 71506e332b858dde8cde902e42d1823f00edc394 (commit) from 79144c677037e29759d624930c45b1401d67b5c2 (commit) ----------------------------------------------------------------------- commit 71506e332b858dde8cde902e42d1823f00edc394 Author: David Lawrence Ramsey <poo...@gm...> Date: Wed Jul 9 20:01:16 2025 -0500 Adjust crawling flesh cage polymorphing/mutation. Since they're made of mostly ugly thing fragments, they shouldn't polymorph the usual way, and since they don't have different colours the way ordinary ugly things do, disallow their polymorphing, and make their mutation only cosmetic. (Coincidentally, both of these are exactly how polymorphed/mutated abominations are treated.) ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/monster.cc | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 596c8ad003..9ab429fca8 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -5107,10 +5107,15 @@ bool monster::can_mutate() const if (type == MONS_CHAOS_SPAWN) return false; - // Abominations re-randomize their tile when mutated. They do not gain the - // malmutate status or experience any other non-cosmetic effect. - if (type == MONS_ABOMINATION_SMALL || type == MONS_ABOMINATION_LARGE) + // Abominations and crawling flesh cages re-randomize their tile when + // mutated. They do not gain the malmutate status or experience any other + // non-cosmetic effect. + if (type == MONS_ABOMINATION_SMALL + || type == MONS_ABOMINATION_LARGE + || type == MONS_CRAWLING_FLESH_CAGE) + { return true; + } const mon_holy_type holi = holiness(); @@ -5128,10 +5133,17 @@ bool monster::can_polymorph() const if (type == MONS_CHAOS_SPAWN) return true; - // Abominations re-randomize their tile when mutated, so can_mutate returns - // true for them. Like all undead, they can't be polymorphed. - if (type == MONS_ABOMINATION_SMALL || type == MONS_ABOMINATION_LARGE) + // Abominations and crawling flesh cages re-randomize their tile when + // mutated, so can_mutate returns true for them. Abominations can't be + // polymorphed because they're undead, and crawling flesh cages can't be + // polymorphed the usual way because they're mostly made of ugly thing + // fragments. + if (type == MONS_ABOMINATION_SMALL + || type == MONS_ABOMINATION_LARGE + || type == MONS_CRAWLING_FLESH_CAGE) + { return false; + } // Polymorphing apostles breaks all sorts of things (like making challenges // unwinnable if it happens) and it would be complex to fix this, so let's @@ -5185,9 +5197,12 @@ bool monster::malmutate(const actor* source, const string& /*reason*/) if (!can_mutate()) return false; - // Abominations re-randomize their tile when mutated. They do not gain the - // malmutate status or experience any other non-cosmetic effect. - if (type == MONS_ABOMINATION_SMALL || type == MONS_ABOMINATION_LARGE) + // Abominations and crawling flesh cages re-randomize their tile when + // mutated. They do not gain the malmutate status or experience any other + // non-cosmetic effect. + if (type == MONS_ABOMINATION_SMALL + || type == MONS_ABOMINATION_LARGE + || type == MONS_CRAWLING_FLESH_CAGE) { #ifdef USE_TILE props[TILE_NUM_KEY].get_short() = ui_random(256); -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 16:50:10
|
via 79144c677037e29759d624930c45b1401d67b5c2 (commit) from bb92c9d70428e48777545ae3884f0e780995c5e2 (commit) ----------------------------------------------------------------------- commit 79144c677037e29759d624930c45b1401d67b5c2 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 14:16:10 2025 -0230 Add an actual message to the tesseract milestones ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/mon-abil.cc | 2 +- crawl-ref/source/mon-death.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index f1d077450b..a3330ba276 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -1471,7 +1471,7 @@ void tesseract_action(monster& mon) if (mon.behaviour != BEH_SLEEP && !mon.props.exists(TESSERACT_START_TIME_KEY)) { mprf(MSGCH_WARN, "You feel the power of Zot begin to gather its forces!"); - mark_milestone("tesseract.activate", ""); + mark_milestone("tesseract.activate", "activated a tesseract"); for (monster_iterator mi; mi; ++mi) { diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 454ab5680a..3cded79120 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -3187,7 +3187,7 @@ item_def* monster_die(monster& mons, killer_type killer, if (you.props.exists(TESSERACT_START_TIME_KEY)) { - mark_milestone("tesseract.kill", ""); + mark_milestone("tesseract.kill", "destroyed the tesseracts."); you.props.erase(TESSERACT_START_TIME_KEY); } } -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 12:35:11
|
via bb92c9d70428e48777545ae3884f0e780995c5e2 (commit) via f72e9069bfe63de11eaa828750857da25ad3fef5 (commit) via e64c27fa7ce588b53477c71df053ebd92be5f873 (commit) from 8c5cb908cfc73e627762bdf7436b292a5c2d4e03 (commit) ----------------------------------------------------------------------- commit bb92c9d70428e48777545ae3884f0e780995c5e2 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 09:42:52 2025 -0230 Adjust offlevel tesseract turn cap (acrobat) The comment mistakenly talk about turns when the value involved was in aut, but that made me also realize the cap was too small (since it was aut.) I have raised the cap to 1000 turns (ie: 10,000 aut). The comment should now also be accurate. commit f72e9069bfe63de11eaa828750857da25ad3fef5 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 09:40:11 2025 -0230 Add milestones for tesseracts activating/dying (gammafunk) commit e64c27fa7ce588b53477c71df053ebd92be5f873 Author: Isaac Clancy <ik...@ya...> Date: Thu Jul 10 12:47:33 2025 +1200 Fix a webtiles desync when a spectator joins When a spectactor joins we send the full map data to the spectator that just joined and record this map data is the last sent map data. However, the player and any pre-exiting spectators might not have received this map data yet and as we set it as the last sent map data it won't be sent again until it changes. To fix this, make sure all the pre-existing clients have the most up to date map data before sending the full map data to the new spectator. Fixes #1474 Fixes #1637 Fixes #2473 Fixes #2499 Fixes #2704 Fixes #3153 Fixes #3222 Fixes #3489 Fixes #3974 Fixes #4013 Fixes #4169 Fixes #4536 ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/mon-abil.cc | 7 ++++--- crawl-ref/source/mon-death.cc | 7 ++++++- crawl-ref/source/tileweb.cc | 23 +++++++++++++++++++--- crawl-ref/source/tileweb.h | 2 +- .../source/webserver/webtiles/process_handler.py | 12 +++++++++-- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index 39acbf7a06..f1d077450b 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -1471,6 +1471,7 @@ void tesseract_action(monster& mon) if (mon.behaviour != BEH_SLEEP && !mon.props.exists(TESSERACT_START_TIME_KEY)) { mprf(MSGCH_WARN, "You feel the power of Zot begin to gather its forces!"); + mark_milestone("tesseract.activate", ""); for (monster_iterator mi; mi; ++mi) { @@ -1502,10 +1503,10 @@ void tesseract_action(monster& mon) // Handle regular spawning int& timer = mon.props[TESSERACT_SPAWN_TIMER_KEY].get_int(); - // Don't act as if more than 3000 turns have passed off-level (in case the + // Don't act as if more than 1000 turns have passed off-level (in case the // player goes to do Extended in the meantime). - if (you.elapsed_time - timer > 3000) - timer = you.elapsed_time - 3000; + if (you.elapsed_time - timer > 10000) + timer = you.elapsed_time - 10000; // Catch up however many spawns should have happened since the last time // we activated. diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index c120b39a5c..454ab5680a 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -3184,7 +3184,12 @@ item_def* monster_die(monster& mons, killer_type killer, } } } - you.props.erase(TESSERACT_START_TIME_KEY); + + if (you.props.exists(TESSERACT_START_TIME_KEY)) + { + mark_milestone("tesseract.kill", ""); + you.props.erase(TESSERACT_START_TIME_KEY); + } } if (mons_is_tentacle_head(mons_base_type(mons))) { diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 66f0c554df..e8ca97965a 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1825,7 +1825,7 @@ void TilesFramework::_mcache_ref(bool inc) } } -void TilesFramework::_send_map(bool force_full) +void TilesFramework::_send_map(bool spectator_only) { // TODO: prevent in some other / better way? if (_send_lock) @@ -1835,7 +1835,7 @@ void TilesFramework::_send_map(bool force_full) map<uint32_t, coord_def> new_monster_locs; - force_full = force_full || m_need_full_map; + bool force_full = spectator_only || m_need_full_map; m_need_full_map = false; json_open_object(); @@ -1843,6 +1843,10 @@ void TilesFramework::_send_map(bool force_full) json_treat_as_empty(); // cautionary note: this is used in heuristic ways in process_handler.py, + // see `_is_spectator_only` + if (spectator_only) + json_write_bool("spect_only", true); + // cautionary note: this is used in heuristic ways in process_handler.py, // see `_is_full_map_msg` if (force_full) json_write_bool("clear", true); @@ -1939,6 +1943,10 @@ void TilesFramework::_send_map(bool force_full) if (force_full) _send_cursor(CURSOR_MAP); + // Everything should already be up to date when called with spectator_only + if (spectator_only) + return; + if (m_mcache_ref_done) _mcache_ref(false); @@ -2128,7 +2136,16 @@ void TilesFramework::_send_everything() // Map is sent after player, otherwise HP/MP bar can be left behind in the // old location if the player has moved - _send_map(true); + + // The player might not have received the latest map data yet and + // _send_map(true) only sends the full map to the newly connected + // spectator but resets the dirty flags. So make sure the player's + // map data is up to date first. + const bool sent_full_map = m_need_full_map; + _send_map(false); + // If we didn't send the full map, send it to the new spectator + if (!sent_full_map) + _send_map(true); // Menus json_open_object(); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 70712eeac8..affd2a0477 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -323,7 +323,7 @@ protected: void _mcache_ref(bool inc); void _send_cursor(cursor_type type); - void _send_map(bool force_full = false); + void _send_map(bool spectator_only = false); void _send_cell(const coord_def &gc, const screen_cell_t ¤t_sc, const screen_cell_t &next_sc, const map_cell ¤t_mc, const map_cell &next_mc, diff --git a/crawl-ref/source/webserver/webtiles/process_handler.py b/crawl-ref/source/webserver/webtiles/process_handler.py index e506c3b284..971c4c62c7 100644 --- a/crawl-ref/source/webserver/webtiles/process_handler.py +++ b/crawl-ref/source/webserver/webtiles/process_handler.py @@ -189,6 +189,10 @@ class CrawlProcessHandlerBase(object): return (re.search(r'"msg" *: *"map"', tocheck) and re.search(r'"clear" *: *true', tocheck)) + def _is_spectator_only(self, msg): + tocheck = msg[0:50] + return re.search(r'"spect_only" *: *true', tocheck) + def handle_process_message(self, msg, send): # type: (str, bool) -> None # special handling for map messages on a new spectator: these can be # massive, and the deflate time adds up, so only send it to new @@ -197,8 +201,12 @@ class CrawlProcessHandlerBase(object): # TODO: if multiple spectators join at the same time, it's probably # possible for this heuristic to fail and send a full map to everyone if self._fresh_watchers and self._is_full_map_msg(msg): - for w in self._fresh_watchers: - w.append_message(msg, send) + if self._is_spectator_only(msg): + for w in self._fresh_watchers: + w.append_message(msg, send) + else: + for receiver in self._receivers: + receiver.append_message(msg, send) self._fresh_watchers = set() return for receiver in self._receivers: -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 10:20:15
|
via 8c5cb908cfc73e627762bdf7436b292a5c2d4e03 (commit) from b1c27173d81cf9cc87b1b1341df54655f142ccb1 (commit) ----------------------------------------------------------------------- commit 8c5cb908cfc73e627762bdf7436b292a5c2d4e03 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 07:49:24 2025 -0230 Various adjustments to Boundless Tesseracts In response to assorted feedback (and noticing at least one bug in the original code), I have made the following adjustments: -While a tesseract is active, there is now a status light indicating this effect (and describing it, for those who overlooked the monster itself). Its color grows more intense the faster the spawn timer has become. -Tesseract spawn rate increases more slowly with time, but starts slightly faster. (This is a nerf, unless one was very fast.) -Tesseract spawns now properly 'catch up' while off-level, so there is no incentive to rest there as opposed to on Zot:5 itself (but this effect is capped to 3000 turns, just in case someone wanders off to do extended in the meantime). -Killing a tesseract immediately removes all unrewarding spawns created by the tesseract (to help with overcoming extremely monster pileups in the worst case, and maybe making things slightly more satisfying to players in general). XP-granting spawns are unaffected (since it is otherwise impossible for the player to differentiate them from regular monsters). -Zot:5 comes with slightly fewer natural spawns (to compensate for some of the tesseract's output; if you kill them fairly quickly, there may even be fewer monsters in total than in 0.33!) -Tesseracts are a little more durable, but have a larger XP pool to grant. -The message for tesseracts activating is a little less emphatic about the need to rush (which seemed to be frequently misinterpreted by players). -Tesseract spawns are now attributed to the tesseract itself, for death attribution. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/dat/descript/monsters.txt | 5 +++-- crawl-ref/source/dat/descript/status.txt | 6 ++++++ crawl-ref/source/dat/mons/boundless-tesseract.yaml | 2 +- crawl-ref/source/dungeon.cc | 3 +++ crawl-ref/source/mon-abil.cc | 21 +++++++++++++++------ crawl-ref/source/mon-death.cc | 18 ++++++++++++++++++ crawl-ref/source/output.cc | 1 + crawl-ref/source/status.cc | 18 ++++++++++++++++++ crawl-ref/source/status.h | 3 ++- 9 files changed, 67 insertions(+), 10 deletions(-) diff --git a/crawl-ref/source/dat/descript/monsters.txt b/crawl-ref/source/dat/descript/monsters.txt index 29f3ac814b..f35f619bd7 100644 --- a/crawl-ref/source/dat/descript/monsters.txt +++ b/crawl-ref/source/dat/descript/monsters.txt @@ -884,8 +884,9 @@ flows heavily through it, overlaying this reality with countless others where its domain remains pristine. Each tesseract is inextricably linked to the other, and destroying one will -destroy both. But so long as they are allowed to exist, there will be no end to -the forces which seek to keep you from the Orb. +destroy both (and expel many of the creatures they have beckoned to this +reality). But so long as they are allowed to exist, there will be no end to the +forces which seek to keep you from the Orb. %%%% brain worm diff --git a/crawl-ref/source/dat/descript/status.txt b/crawl-ref/source/dat/descript/status.txt index ba36f6cef5..5903c7b3b1 100644 --- a/crawl-ref/source/dat/descript/status.txt +++ b/crawl-ref/source/dat/descript/status.txt @@ -1222,3 +1222,9 @@ Ostracised status Your connection to the divine has been partially cut-off, temporarily reducing your effective piety. Gaining experience will eventually recover all piety that has been locked away this way. +%%%% +Tesseract status + +A Boundless Tesseract is drawing in forces from a parallel reality. New monsters +will steadily appear at random locations across the floor until either of the +tesseracts is destroyed. This rate is slow at first, but accelerates with time. diff --git a/crawl-ref/source/dat/mons/boundless-tesseract.yaml b/crawl-ref/source/dat/mons/boundless-tesseract.yaml index 76a2997faf..d86ebe1a32 100644 --- a/crawl-ref/source/dat/mons/boundless-tesseract.yaml +++ b/crawl-ref/source/dat/mons/boundless-tesseract.yaml @@ -6,7 +6,7 @@ holiness: [nonliving] will: invuln attacks: hd: 30 -hp_10x: 1800 +hp_10x: 2100 ac: 10 ev: 1 spells: boundless_tesseract diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc index 1ce584f05b..a1ef8031e6 100644 --- a/crawl-ref/source/dungeon.cc +++ b/crawl-ref/source/dungeon.cc @@ -1679,6 +1679,9 @@ static int _num_mons_wanted() int mon_wanted = roll_dice(3, _mon_die_size()); if (mon_wanted > 60) mon_wanted = 60; + + if (level_id::current() == level_id(BRANCH_ZOT, 5)) + mon_wanted = max(10, mon_wanted - 4); return mon_wanted; } diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index c85a0575f4..39acbf7a06 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -1470,8 +1470,7 @@ void tesseract_action(monster& mon) // When we become alerted, start the spawn timer and announce ourselves to the player. if (mon.behaviour != BEH_SLEEP && !mon.props.exists(TESSERACT_START_TIME_KEY)) { - mprf(MSGCH_WARN, "You feel the power of Zot begin to focus. " - "Strike quickly, lest you be overrun by monsters beyond count!"); + mprf(MSGCH_WARN, "You feel the power of Zot begin to gather its forces!"); for (monster_iterator mi; mi; ++mi) { @@ -1494,19 +1493,28 @@ void tesseract_action(monster& mon) } } + you.props[TESSERACT_START_TIME_KEY] = you.elapsed_time; mon.props[TESSERACT_START_TIME_KEY] = you.elapsed_time; mon.props[TESSERACT_SPAWN_TIMER_KEY] = you.elapsed_time; - mon.props[TESSERACT_XP_KEY] = 12000; + mon.props[TESSERACT_XP_KEY] = 15000; } // Handle regular spawning int& timer = mon.props[TESSERACT_SPAWN_TIMER_KEY].get_int(); + + // Don't act as if more than 3000 turns have passed off-level (in case the + // player goes to do Extended in the meantime). + if (you.elapsed_time - timer > 3000) + timer = you.elapsed_time - 3000; + + // Catch up however many spawns should have happened since the last time + // we activated. while (you.elapsed_time >= timer) { const int time_passed = you.elapsed_time - mon.props[TESSERACT_START_TIME_KEY].get_int(); - const int interval = max(200, 750 - (time_passed / 6)); + const int interval = max(200, 600 - (time_passed / 25)); - timer = you.elapsed_time + random_range(interval, interval * 4 / 3); + timer += random_range(interval, interval * 4 / 3); mgen_data mg(one_chance_in(6) ? MONS_ORB_GUARDIAN : WANDERING_MONSTER); mg.place = level_id::current(); @@ -1514,11 +1522,12 @@ void tesseract_action(monster& mon) mg.flags |= MG_FORBID_BANDS; mg.proximity = PROX_AWAY_FROM_PLAYER; mg.foe = MHITYOU; + mg.non_actor_summoner = "a Boundless Tesseract"; monster* spawn = mons_place(mg); if (!spawn) - return; + continue; // Allow the monster to be a normal monster if there is XP left in our // pool; otherwise, make them unrewarding (to make early spawns feel diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 48ff5421f1..c120b39a5c 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -3164,9 +3164,27 @@ item_def* monster_die(monster& mons, killer_type killer, if (mons.type == MONS_BOUNDLESS_TESSERACT) { mprf(MSGCH_ORB, "You feel the reach of Zot diminish."); + // Remove all non-rewarding spawns, along with the other tesseract. for (monster_iterator mi; mi; ++mi) + { if (mi->type == MONS_BOUNDLESS_TESSERACT && mi->mid != mons.mid) monster_die(**mi, killer, killer_index); + else if ((mi->flags & (MF_HARD_RESET | MF_NO_REWARD) + && mi->props.exists(BLAME_KEY))) + { + const CrawlVector& blame = mi->props[BLAME_KEY].get_vector(); + if (blame[blame.size() - 1].get_string() == "created by a Boundless Tesseract") + { + if (you.can_see(**mi)) + { + mprf(MSGCH_MONSTER_TIMEOUT, "%s is pulled back into %s original reality.", + mi->name(DESC_THE).c_str(), mi->pronoun(PRONOUN_POSSESSIVE).c_str()); + } + monster_die(**mi, KILL_RESET, NON_MONSTER); + } + } + } + you.props.erase(TESSERACT_START_TIME_KEY); } if (mons_is_tentacle_head(mons_base_type(mons))) { diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 336e9983cf..e2a6f5744e 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -1289,6 +1289,7 @@ static void _get_status_lights(vector<status_light>& out) // statuses important enough to appear first. (Rightmost) const unsigned int important_statuses[] = { + STATUS_TESSERACT, STATUS_ORB, STATUS_ZOT, STATUS_STAT_ZERO, diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 46549fa664..7f01064880 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -13,6 +13,7 @@ #include "fight.h" // weapon_cleaves #include "item-prop.h" #include "level-state-type.h" +#include "mon-abil.h" #include "mutation.h" #include "options.h" #include "orb.h" // orb_limits_translocation in fill_status_info @@ -987,6 +988,23 @@ bool fill_status_info(int status, status_info& inf) } break; + case STATUS_TESSERACT: + if (level_id::current() == level_id(BRANCH_ZOT, 5) + && you.props.exists(TESSERACT_START_TIME_KEY)) + { + const int time = you.elapsed_time - you.props[TESSERACT_START_TIME_KEY].get_int(); + + if (time >= 10000) + inf.light_colour = LIGHTMAGENTA; + else if (time > 4000) + inf.light_colour = RED; + else + inf.light_colour = YELLOW; + + inf.light_text = "Tesseract"; + } + break; + default: if (!found) { diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h index a9316a5f97..0cda436a50 100644 --- a/crawl-ref/source/status.h +++ b/crawl-ref/source/status.h @@ -57,7 +57,8 @@ enum status_type STATUS_SHROUD, STATUS_CLAUSTROPHOBIA, STATUS_OSTRACISM, - STATUS_LAST_STATUS = STATUS_OSTRACISM + STATUS_TESSERACT, + STATUS_LAST_STATUS = STATUS_TESSERACT }; struct status_info -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 08:10:14
|
via b1c27173d81cf9cc87b1b1341df54655f142ccb1 (commit) from 309a5445d7c1d1d52dac55110a22ffc13c5da6b9 (commit) ----------------------------------------------------------------------- commit b1c27173d81cf9cc87b1b1341df54655f142ccb1 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 05:34:28 2025 -0230 Don't resend the full Doom tooltip every single webtiles update ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/tileweb.cc | 2 +- crawl-ref/source/tileweb.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 7c913be153..66f0c554df 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1140,7 +1140,7 @@ void TilesFramework::_send_player(bool force_full) _update_int(force_full, c.dex, (int8_t) you.dex(false), "dex"); _update_int(force_full, c.doom, you.attribute[ATTR_DOOM], "doom"); - json_write_string("doom_desc", getLongDescription("doom status")); + _update_string(force_full, c.doom_desc, getLongDescription("doom status"), "doom_desc"); _update_int(force_full, c.contam, you.magic_contamination / 10, "contam"); diff --git a/crawl-ref/source/tileweb.h b/crawl-ref/source/tileweb.h index 54a25f4f47..70712eeac8 100644 --- a/crawl-ref/source/tileweb.h +++ b/crawl-ref/source/tileweb.h @@ -68,6 +68,7 @@ struct player_info int8_t dex; int doom; + string doom_desc; int experience_level; int8_t exp_progress; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 08:05:10
|
via 309a5445d7c1d1d52dac55110a22ffc13c5da6b9 (commit) from 17b53af623c32dce5a876bec18be2ead38f9ca2a (commit) ----------------------------------------------------------------------- commit 309a5445d7c1d1d52dac55110a22ffc13c5da6b9 Author: DracoOmega <dra...@gm...> Date: Thu Jul 10 05:30:24 2025 -0230 Don't crash if explore_auto_rest_status is given invalid text (Ogregutan) Giving it text that couldn't be parsed into a valid duration was resulting in it trying to rest to wear off NUM_DURATIONS (which is out of bounds and caused an assert). ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/initfile.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index 112501e67f..057bd69cb8 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -3218,6 +3218,9 @@ void game_options::update_explore_auto_rest_status() duration_type dur = duration_by_name(str_nospace); + if (dur == NUM_DURATIONS) + continue; + if (invert) durs.erase(dur); else -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-10 00:45:14
|
via 17b53af623c32dce5a876bec18be2ead38f9ca2a (commit) from 2db4d66fed52567eb4f6552d8ea7f6ca3e92d8e0 (commit) ----------------------------------------------------------------------- commit 17b53af623c32dce5a876bec18be2ead38f9ca2a Author: David Lawrence Ramsey <poo...@gm...> Date: Wed Jul 9 19:32:47 2025 -0500 Rename: persistent contam. -> contam susceptible. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/dat/descript/mutations.txt | 2 +- crawl-ref/source/mutation-data.h | 6 +++--- crawl-ref/source/mutation-type.h | 2 +- crawl-ref/source/player.cc | 2 +- crawl-ref/source/rltiles/dc-mutations.txt | 2 +- ...tent_contamination.png => contamination_susceptible.png} | Bin crawl-ref/source/spl-cast.cc | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) rename crawl-ref/source/rltiles/gui/mutations/{persistent_contamination.png => contamination_susceptible.png} (100%) diff --git a/crawl-ref/source/dat/descript/mutations.txt b/crawl-ref/source/dat/descript/mutations.txt index b38e1bab55..6bf3242408 100644 --- a/crawl-ref/source/dat/descript/mutations.txt +++ b/crawl-ref/source/dat/descript/mutations.txt @@ -485,7 +485,7 @@ persistent drain mutation Your health recovers twice as slowly from being drained. (The total experience needed is doubled.) %%%% -persistent contamination mutation +contamination susceptible mutation You absorb twice as much mutagenic energy from being contaminated. %%%% diff --git a/crawl-ref/source/mutation-data.h b/crawl-ref/source/mutation-data.h index 690c38d98a..cdc0bfbb34 100644 --- a/crawl-ref/source/mutation-data.h +++ b/crawl-ref/source/mutation-data.h @@ -381,13 +381,13 @@ static const mutation_def mut_data[] = TILEG_MUT_PERSISTENT_DRAIN, }, -{ MUT_PERSISTENT_CONTAMINATION, 5, 1, mutflag::bad, - "persistent contamination", +{ MUT_CONTAMINATION_SUSCEPTIBLE, 5, 1, mutflag::bad, + "contamination susceptible", {"You absorb twice as much mutagenic energy from being contaminated.", "", ""}, {"You feel more susceptible to contamination.", "", ""}, {"You feel less susceptible to contamination.", "", ""}, - TILEG_MUT_PERSISTENT_CONTAMINATION, + TILEG_MUT_CONTAMINATION_SUSCEPTIBLE, }, { MUT_STRONG_WILLED, 5, 3, mutflag::good, diff --git a/crawl-ref/source/mutation-type.h b/crawl-ref/source/mutation-type.h index c79eba9ca8..1190412482 100644 --- a/crawl-ref/source/mutation-type.h +++ b/crawl-ref/source/mutation-type.h @@ -338,7 +338,7 @@ enum mutation_type MUT_FEED_OFF_SUFFERING, MUT_ACCURSED, MUT_LUCKY, - MUT_PERSISTENT_CONTAMINATION, + MUT_CONTAMINATION_SUSCEPTIBLE, NUM_MUTATIONS, CATEGORY_MUTATIONS, RANDOM_MUTATION = CATEGORY_MUTATIONS, diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 4b74439c82..c90d757cd3 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -4172,7 +4172,7 @@ void contaminate_player(int change, bool controlled, bool msg) if (change > 0) { - const int mul = you.has_mutation(MUT_PERSISTENT_CONTAMINATION) + const int mul = you.has_mutation(MUT_CONTAMINATION_SUSCEPTIBLE) #if TAG_MAJOR_VERSION == 34 || you.unrand_equipped(UNRAND_ETHERIC_CAGE) #endif diff --git a/crawl-ref/source/rltiles/dc-mutations.txt b/crawl-ref/source/rltiles/dc-mutations.txt index 5a091680df..ea55cc1ab4 100644 --- a/crawl-ref/source/rltiles/dc-mutations.txt +++ b/crawl-ref/source/rltiles/dc-mutations.txt @@ -158,7 +158,7 @@ berserk_1 BERSERK berserk_2 deterioration_1 POOR_CONSTITUTION deterioration_2 -persistent_contamination PERSISTENT_CONTAMINATION +contamination_susceptible CONTAMINATION_SUSCEPTIBLE persistent_drain PERSISTENT_DRAIN scream_1 SCREAM scream_2 diff --git a/crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png b/crawl-ref/source/rltiles/gui/mutations/contamination_susceptible.png similarity index 100% rename from crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png rename to crawl-ref/source/rltiles/gui/mutations/contamination_susceptible.png diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index e17367df97..89820e3d75 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -3481,7 +3481,7 @@ bool warn_about_contam_cost(int max_contam) if (!Options.warn_contam_cost || you.magic_contamination >= 1000) return false; - const int mul = you.has_mutation(MUT_PERSISTENT_CONTAMINATION) ? 2 : 1; + const int mul = you.has_mutation(MUT_CONTAMINATION_SUSCEPTIBLE) ? 2 : 1; if (you.magic_contamination + (max_contam * mul) >= 1000) return !yesno("Casting this now could dangerously contaminate you. Continue?", true, 'n'); -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-09 21:20:14
|
via 2db4d66fed52567eb4f6552d8ea7f6ca3e92d8e0 (commit) from baadf7e5a714067a9958ba52ea3c00476695e9ac (commit) ----------------------------------------------------------------------- commit 2db4d66fed52567eb4f6552d8ea7f6ca3e92d8e0 Author: David Lawrence Ramsey <poo...@gm...> Date: Wed Jul 9 16:13:55 2025 -0500 Fix typo. ----------------------------------------------------------------------- Summary of changes: crawl-ref/docs/changelog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index f255bafeca..ed82e7bd53 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -50,7 +50,7 @@ Branches, Environment - Potential troves to discover include The Dread Knight's Derelict Chapel, Eringya's Secret Bog, The First Justicar's Armoury, Leda's Sunken Stockpile, The Lost Hoard of Erebora, The Name-Rending Infernalists' Reservoir, The - Octopus King's Forgotten Garden, Ozocubu's Refridgerator, Rutra's Hidden + Octopus King's Forgotten Garden, Ozocubu's Refrigerator, Rutra's Hidden Sanctum, The Storm Queen's Palace Crash Site, a devouring Rift, and an orange crystal hatchery. -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-09 19:30:15
|
via baadf7e5a714067a9958ba52ea3c00476695e9ac (commit) from 88f54759262d77cbcfb2dc8ee86c89f852030ddb (commit) ----------------------------------------------------------------------- commit baadf7e5a714067a9958ba52ea3c00476695e9ac Author: David Lawrence Ramsey <poo...@gm...> Date: Tue Jul 8 13:22:09 2025 -0500 New mutation: persistent contamination. This mutation makes the player absorb twice as much mutagenic energy from being contaminated than they would otherwise, just as they would if they were wielding the old Maxwell's Etheric Cage unrand. (Having the mutation and wielding the unrand do not stack.) It has the same rarity as the persistent draining mutation. The tile is currently a palette-tweaked version of the persistent draining mutation tile. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/dat/descript/mutations.txt | 4 ++++ crawl-ref/source/mutation-data.h | 9 +++++++++ crawl-ref/source/mutation-type.h | 1 + crawl-ref/source/player.cc | 10 ++++++++-- crawl-ref/source/rltiles/dc-mutations.txt | 1 + .../rltiles/gui/mutations/persistent_contamination.png | Bin 0 -> 494 bytes crawl-ref/source/spl-cast.cc | 4 +++- 7 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png diff --git a/crawl-ref/source/dat/descript/mutations.txt b/crawl-ref/source/dat/descript/mutations.txt index 130474af21..b38e1bab55 100644 --- a/crawl-ref/source/dat/descript/mutations.txt +++ b/crawl-ref/source/dat/descript/mutations.txt @@ -485,6 +485,10 @@ persistent drain mutation Your health recovers twice as slowly from being drained. (The total experience needed is doubled.) %%%% +persistent contamination mutation + +You absorb twice as much mutagenic energy from being contaminated. +%%%% initially attractive mutation The first time you see a monster, it may be magically pulled toward you. diff --git a/crawl-ref/source/mutation-data.h b/crawl-ref/source/mutation-data.h index 0cc1fe4637..690c38d98a 100644 --- a/crawl-ref/source/mutation-data.h +++ b/crawl-ref/source/mutation-data.h @@ -381,6 +381,15 @@ static const mutation_def mut_data[] = TILEG_MUT_PERSISTENT_DRAIN, }, +{ MUT_PERSISTENT_CONTAMINATION, 5, 1, mutflag::bad, + "persistent contamination", + + {"You absorb twice as much mutagenic energy from being contaminated.", "", ""}, + {"You feel more susceptible to contamination.", "", ""}, + {"You feel less susceptible to contamination.", "", ""}, + TILEG_MUT_PERSISTENT_CONTAMINATION, +}, + { MUT_STRONG_WILLED, 5, 3, mutflag::good, "strong-willed", diff --git a/crawl-ref/source/mutation-type.h b/crawl-ref/source/mutation-type.h index 341c67ebcb..c79eba9ca8 100644 --- a/crawl-ref/source/mutation-type.h +++ b/crawl-ref/source/mutation-type.h @@ -338,6 +338,7 @@ enum mutation_type MUT_FEED_OFF_SUFFERING, MUT_ACCURSED, MUT_LUCKY, + MUT_PERSISTENT_CONTAMINATION, NUM_MUTATIONS, CATEGORY_MUTATIONS, RANDOM_MUTATION = CATEGORY_MUTATIONS, diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 9698612a8b..4b74439c82 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -4170,10 +4170,16 @@ void contaminate_player(int change, bool controlled, bool msg) bool was_glowing = player_harmful_contamination(); int new_level = 0; + if (change > 0) + { + const int mul = you.has_mutation(MUT_PERSISTENT_CONTAMINATION) #if TAG_MAJOR_VERSION == 34 - if (change > 0 && you.unrand_equipped(UNRAND_ETHERIC_CAGE)) - change *= 2; + || you.unrand_equipped(UNRAND_ETHERIC_CAGE) #endif + ? 2 : 1; + + change *= mul; + } you.magic_contamination = max(0, min(3000, you.magic_contamination + change)); diff --git a/crawl-ref/source/rltiles/dc-mutations.txt b/crawl-ref/source/rltiles/dc-mutations.txt index 6c2846068d..5a091680df 100644 --- a/crawl-ref/source/rltiles/dc-mutations.txt +++ b/crawl-ref/source/rltiles/dc-mutations.txt @@ -158,6 +158,7 @@ berserk_1 BERSERK berserk_2 deterioration_1 POOR_CONSTITUTION deterioration_2 +persistent_contamination PERSISTENT_CONTAMINATION persistent_drain PERSISTENT_DRAIN scream_1 SCREAM scream_2 diff --git a/crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png b/crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png new file mode 100644 index 0000000000..24e0bad320 Binary files /dev/null and b/crawl-ref/source/rltiles/gui/mutations/persistent_contamination.png differ diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index d69c06db53..e17367df97 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -3481,7 +3481,9 @@ bool warn_about_contam_cost(int max_contam) if (!Options.warn_contam_cost || you.magic_contamination >= 1000) return false; - if (you.magic_contamination + max_contam >= 1000) + const int mul = you.has_mutation(MUT_PERSISTENT_CONTAMINATION) ? 2 : 1; + + if (you.magic_contamination + (max_contam * mul) >= 1000) return !yesno("Casting this now could dangerously contaminate you. Continue?", true, 'n'); return false; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-09 18:00:14
|
via 88f54759262d77cbcfb2dc8ee86c89f852030ddb (commit) from 7acc8d57e806615e4921a963a45d0ceb16042e3b (commit) ----------------------------------------------------------------------- commit 88f54759262d77cbcfb2dc8ee86c89f852030ddb Author: DracoOmega <dra...@gm...> Date: Wed Jul 9 15:25:26 2025 -0230 Fix the infinite autorest protection being overzealous (not_that_greg) It wasn't checking that the player was stuck in place, merely that they had been autoexploring for 500 turns without interruption. Which doesn't happen *often*, but can sometimes. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/travel.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index e97905bd2a..779837dd47 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -67,6 +67,8 @@ #include "view.h" #include "zot.h" +#define AUTO_REST_STATUS_POS "autorest_status_pos" + enum IntertravelDestination { // warning: the waypoint prompt menu uses values -1 to -10 for waypoints. @@ -1084,7 +1086,8 @@ command_type travel() // autoexplore can never move. We wait an arbitrary 500 turns before // deciding something must be wrong and stopping (to prevent an assert). if (you.elapsed_time > you.elapsed_time_at_last_input + 5000 - && !Options.explore_auto_rest_status.empty()) + && you.props.exists(AUTO_REST_STATUS_POS) + && you.props[AUTO_REST_STATUS_POS].get_coord() == you.pos()) { mprf(MSGCH_ERROR, "You appear to be waiting for the end of something which may " @@ -1118,6 +1121,9 @@ command_type travel() continue; } + // Save the player's position, so we can catch the degenerate case + // where this results in us waiting indefinitely. + you.props[AUTO_REST_STATUS_POS] = you.pos(); return CMD_WAIT; } -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-09 16:30:17
|
via 7acc8d57e806615e4921a963a45d0ceb16042e3b (commit) via 118629b06ae15267be9b6f78e880de1d99736480 (commit) via d11ae09b5d82e5716771dac4331de57c116d6db7 (commit) from 22a848724cb8892b6b1ff5a94f70ec54fcd0c00e (commit) ----------------------------------------------------------------------- commit 7acc8d57e806615e4921a963a45d0ceb16042e3b Author: DracoOmega <dra...@gm...> Date: Wed Jul 9 13:36:52 2025 -0230 Prevent explore_auto_rest_status from resting an infinite length of time This shouldn't be possible with default (or sane) settings, but the option does not exhaustively prevent the player from manually adding effects that do not expire with time (generally positive ones). In which case, autoexplore can wait so long for them to go away that the game will crash. This is a bit of a clunky solution, but it prevents a crash-on-demand that also shouldn't happen unless the player is trying to do something very silly. commit 118629b06ae15267be9b6f78e880de1d99736480 Author: DracoOmega <dra...@gm...> Date: Wed Jul 9 13:25:04 2025 -0230 feat: option to make autoexplore wait while listed durations are active Resolves #3210 from (laserbat) Added new rc option - explore_auto_rest_status (LIST) Checks list and converts to known durations based on short_text and name_text. Added two new duration_flags that signify negative effects and cooldowns that affect the explore_auto_rest_status_set option [Committer's note: updated to account for statuses added/removed since this was first written, squashed two options into one, fixed several bugs, added handling of resting off badforms and magic contamination, allowed subtracting statuses from large sets (instead of having to manually specify dozens of effects just to remove a single negative one), removed inclusion of several statuses that do not expire with time, cleaned up unncessary flag changes for removed status effects and rewrote the options_guide entry. I also made the option default to all negative effects, cooldowns, and magic contamination. I think this is the most sensible default for average players and only a very few will care about taking a tiny amount more turns on some unimportant things. Note that the new D_NEGATIVE flag is used on a handful of effects that are not time-based or for which this option does not meaningfully apply (eg: Paralysis). But even if there is no present use of this, I think categorizing negative effects has future design applications.] # Conflicts: # crawl-ref/docs/options_guide.txt # crawl-ref/source/duration-data.h # crawl-ref/source/initfile.cc # crawl-ref/source/options.h # crawl-ref/source/status.cc commit d11ae09b5d82e5716771dac4331de57c116d6db7 Author: DracoOmega <dra...@gm...> Date: Wed Jul 9 13:34:20 2025 -0230 Mark 'bad' forms as such in form-data To be used in a follow-up commit to allow automatically resting them off before autoexploring. (It's a little ambiguous whether tree form is good or bad, but I decided that it should count as such for this purpose.) ----------------------------------------------------------------------- Summary of changes: crawl-ref/docs/options_guide.txt | 23 +++++- crawl-ref/source/dat/forms/bat.yaml | 1 + crawl-ref/source/dat/forms/fungus.yaml | 1 + crawl-ref/source/dat/forms/pig.yaml | 1 + crawl-ref/source/dat/forms/tree.yaml | 1 + crawl-ref/source/dat/forms/wisp.yaml | 1 + crawl-ref/source/duration-data.h | 129 +++++++++++++++++------------- crawl-ref/source/initfile.cc | 53 ++++++++++++ crawl-ref/source/options.h | 8 ++ crawl-ref/source/status.cc | 55 ++++++++++--- crawl-ref/source/status.h | 2 + crawl-ref/source/transform.cc | 6 ++ crawl-ref/source/transform.h | 3 + crawl-ref/source/travel.cc | 41 ++++++++++ crawl-ref/source/util/form-gen.py | 2 + crawl-ref/source/util/form-gen/body.txt | 2 +- crawl-ref/source/util/form-gen/header.txt | 1 + 17 files changed, 262 insertions(+), 68 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index 6908a59ffb..cb72c5bfc7 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -51,7 +51,8 @@ The contents of this text are: tc_forbidden, runrest_ignore_message, runrest_stop_message, interrupt_<delay>, delay_safe_poison, runrest_ignore_monster, rest_wait_both, rest_wait_ancestor, rest_wait_percent, - explore_auto_rest, auto_exclude, travel_open_doors + explore_auto_rest, explore_auto_rest_status, + auto_exclude, travel_open_doors 3-g Command Enhancements. auto_switch, easy_unequip, equip_unequip, jewellery_prompt, easy_confirm, simple_targeting, force_spell_targeter, @@ -1101,6 +1102,26 @@ explore_auto_rest = true If true, auto-explore waits until your HP and MP are both at rest_wait_percent before moving. +explore_auto_rest_status = <status name>, <cooldown name>, <duration name>... + (List option) + Auto-explore will wait until all statuses, durations, and cooldowns in + the list are finished before moving. The list will accept most + duration-based statuses by either the name of their status light or + the phrasing that appears on the % screen. + + There are several special values: + "all_negative" = all time-based negative statuses (eg: Slow) + "all_cooldown" = all time-based cooldowns (eg: -Blink) + "contam" = any amount of magic contamination + "transformation" = any time-based negative form (ie: pig/wisp). + + To exclude a specific status from all_negative or all_cooldown, include + the status with an * at the start. For instance: + explore_auto_rest_status += *-blink + will remove -blink from the list of cooldowns it wants to wait on. + + Defaults to "all_negative", "all_cooldown", "contam" + auto_exclude += <monster name>, <monster name>, ... (List option) Whenever you encounter a sleeping or stationary monster during diff --git a/crawl-ref/source/dat/forms/bat.yaml b/crawl-ref/source/dat/forms/bat.yaml index b1f3ce6f47..6990a14825 100644 --- a/crawl-ref/source/dat/forms/bat.yaml +++ b/crawl-ref/source/dat/forms/bat.yaml @@ -14,6 +14,7 @@ unarmed_verbs: animal can_fly: yes can_swim: false changes_anatomy: yes +is_badform: yes has_hair: yes has_bones: yes has_feet: yes diff --git a/crawl-ref/source/dat/forms/fungus.yaml b/crawl-ref/source/dat/forms/fungus.yaml index a9baa7f7f8..187d09f1af 100644 --- a/crawl-ref/source/dat/forms/fungus.yaml +++ b/crawl-ref/source/dat/forms/fungus.yaml @@ -14,6 +14,7 @@ can_swim: no changes_anatomy: yes changes_substance: yes holiness: plant +is_badform: yes has_blood: no has_hair: no has_bones: no diff --git a/crawl-ref/source/dat/forms/pig.yaml b/crawl-ref/source/dat/forms/pig.yaml index 38f6f17e23..16cde99306 100644 --- a/crawl-ref/source/dat/forms/pig.yaml +++ b/crawl-ref/source/dat/forms/pig.yaml @@ -10,6 +10,7 @@ unarmed_colour: lightgrey unarmed_name: Teeth unarmed_verbs: animal can_swim: no +is_badform: yes changes_anatomy: yes has_hair: yes has_bones: yes diff --git a/crawl-ref/source/dat/forms/tree.yaml b/crawl-ref/source/dat/forms/tree.yaml index 5fa82b7508..4ec52f7d20 100644 --- a/crawl-ref/source/dat/forms/tree.yaml +++ b/crawl-ref/source/dat/forms/tree.yaml @@ -11,6 +11,7 @@ unarmed_name: Branches unarmed_verbs: [hit, smack, pummel, thrash] can_fly: no can_swim: no +is_badform: yes changes_anatomy: yes changes_substance: yes holiness: plant diff --git a/crawl-ref/source/dat/forms/wisp.yaml b/crawl-ref/source/dat/forms/wisp.yaml index ca999a0cc4..9cd77bfa17 100644 --- a/crawl-ref/source/dat/forms/wisp.yaml +++ b/crawl-ref/source/dat/forms/wisp.yaml @@ -12,6 +12,7 @@ unarmed_name: Misty tendrils unarmed_verbs: [touch, touch, engulf, engulf] can_fly: yes can_swim: no +is_badform: yes changes_anatomy: yes changes_substance: yes holiness: nonliving diff --git a/crawl-ref/source/duration-data.h b/crawl-ref/source/duration-data.h index 9f8211cbd6..0993d11bd9 100644 --- a/crawl-ref/source/duration-data.h +++ b/crawl-ref/source/duration-data.h @@ -4,7 +4,9 @@ #pragma once +#include "areas.h" #include "act-iter.h" +#include "cloud.h" #include "mon-death.h" #include "god-abil.h" #include "god-companions.h" @@ -12,9 +14,15 @@ #include "spl-damage.h" #include "spl-other.h" #include "spl-selfench.h" +#include "mon-transit.h" // untag_followers() in duration-data +#include "random.h" // for midpoint_msg.offset() in duration-data +#include "spl-summoning.h" // NEXT_OBLIVION_HOUND_KEY in duration-data +#include "spl-transloc.h" // for you_teleport_now() in duration-data +#include "stairs.h" // rise_through_ceiling #include "tag-version.h" #include "timed-effects.h" + static void _end_invis() { if (you.invisible()) @@ -92,6 +100,13 @@ enum duration_flags : uint32_t // Whether !cancellation (and the like) end the duration. D_DISPELLABLE = 1<< 1, + + // Whether it is a negative effect. + D_NEGATIVE = 1<< 2, + + // Whether it is a time-based cooldown for an effect. + D_COOLDOWN = 1<< 3, + }; /// A description of the behaviour when a duration begins 'expiring'. @@ -194,11 +209,11 @@ static const duration_def duration_data[] = { DUR_BERSERK_COOLDOWN, YELLOW, "-Berserk", "on berserk cooldown", "berserk cooldown", - "You are unable to berserk.", D_NO_FLAGS}, + "You are unable to berserk.", D_COOLDOWN }, { DUR_BREATH_WEAPON, YELLOW, "-Breath", "short of breath", "breath weapon", - "You are short of breath.", D_NO_FLAGS, + "You are short of breath.", D_COOLDOWN, { { "You have got your breath back." }, {}, true }}, { DUR_BRILLIANCE, LIGHTBLUE, "Brill", @@ -208,12 +223,12 @@ static const duration_def duration_data[] = { DUR_DIMINISHED_SPELLS, RED, "Dim", "diminished spells", "diminished spells", - "Your spell have diminished power.", D_DISPELLABLE, + "Your spell have diminished power.", D_DISPELLABLE | D_NEGATIVE, {{ "Your spells return to their normal power." }}}, { DUR_CONF, RED, "Conf", "confused", "conf", - "You are confused.", D_DISPELLABLE, + "You are confused.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel less confused." }}}, { DUR_CONFUSING_TOUCH, // Has custom long_text LIGHTBLUE, "Touch", @@ -226,7 +241,7 @@ static const duration_def duration_data[] = { DUR_CORONA, // Has custom long_text YELLOW, "Corona", "lit by a corona", "corona", - "", D_DISPELLABLE, + "", D_DISPELLABLE | D_NEGATIVE, {{ "", []() { if (!you.backlit()) mprf(MSGCH_DURATION, "You are no longer glowing."); @@ -250,7 +265,7 @@ static const duration_def duration_data[] = { DUR_EXHAUSTED, YELLOW, "Exh", "exhausted", "", - "You are exhausted.", D_NO_FLAGS, + "You are exhausted.", D_COOLDOWN, {{ "You feel less exhausted." }}}, { DUR_ICY_ARMOUR, 0, "", @@ -267,11 +282,11 @@ static const duration_def duration_data[] = { DUR_STICKY_FLAME, RED, "Fire", "on fire", "liquid fire", - "You are covered in liquid fire.", D_DISPELLABLE /*but special-cased*/}, + "You are covered in liquid fire.", D_DISPELLABLE /*but special-cased*/ | D_NEGATIVE}, { DUR_LOWERED_WL, RED, "Will/2", "weak-willed", "lowered wl", - "You are weak-willed.", D_DISPELLABLE, + "You are weak-willed.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel your willpower return." }}}, { DUR_MIGHT, LIGHTBLUE, "Might", @@ -281,15 +296,15 @@ static const duration_def duration_data[] = { DUR_PARALYSIS, RED, "Para", "paralysed", "paralysis", - "You are paralysed.", D_DISPELLABLE}, + "You are paralysed.", D_DISPELLABLE | D_NEGATIVE}, { DUR_PETRIFIED, RED, "Stone", "petrified", "", - "You are petrified.", D_DISPELLABLE}, + "You are petrified.", D_DISPELLABLE | D_NEGATIVE}, { DUR_VEXED, RED, "Vexed", "vexed", "vex", - "You are vexed.", D_DISPELLABLE, + "You are vexed.", D_DISPELLABLE | D_NEGATIVE, {{ "", []() { mprf(MSGCH_DURATION, "You feel more in control of yourself again."); you.give_stun_immunity(random_range(3, 5)); @@ -297,12 +312,12 @@ static const duration_def duration_data[] = { DUR_PETRIFYING, LIGHTRED, "Petr", "petrifying", "", - "You are turning to stone.", D_DISPELLABLE /*but special-cased*/ | D_EXPIRES, + "You are turning to stone.", D_DISPELLABLE /*but special-cased*/ | D_EXPIRES | D_NEGATIVE, {}, 1}, { DUR_VITRIFIED, RED, "Fragile", "fragile (+50% incoming damage)", "vitrified", - "You are fragile as glass.", D_DISPELLABLE, + "You are fragile as glass.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel less fragile." }}}, { DUR_RESISTANCE, BLUE, "Resist", @@ -324,7 +339,7 @@ static const duration_def duration_data[] = { DUR_SLEEP, 0, "", "sleeping", "sleep", - "You are sleeping.", D_DISPELLABLE}, + "You are sleeping.", D_DISPELLABLE | D_NEGATIVE}, { DUR_SWIFTNESS, BLUE, "Swift", "swift", "swiftness", @@ -349,7 +364,7 @@ static const duration_def duration_data[] = { DUR_DEATHS_DOOR_COOLDOWN, YELLOW, "-DDoor", "on death's door cooldown", "deaths door cooldown", - "You are unable to enter death's door.", D_NO_FLAGS, + "You are unable to enter death's door.", D_COOLDOWN, {{ "You step away from death's doorway." }}}, { DUR_QUAD_DAMAGE, BLUE, "Quad", @@ -370,7 +385,7 @@ static const duration_def duration_data[] = { DUR_AFRAID, RED, "Fear", "afraid", "", - "You are terrified.", D_DISPELLABLE | D_EXPIRES, + "You are terrified.", D_DISPELLABLE | D_EXPIRES | D_NEGATIVE, {{ "Your fear fades away.", []() { you.clear_fearmongers(); }}, {}, true }}, { DUR_VORTEX, @@ -411,7 +426,7 @@ static const duration_def duration_data[] = { DUR_VORTEX_COOLDOWN, YELLOW, "-Vortex", "on vortex cooldown", "vortex cooldown", - "You are unable to create a polar vortex.", D_NO_FLAGS, + "You are unable to create a polar vortex.", D_COOLDOWN, {{ "The winds around you calm down.", []() { remove_vortex_clouds(MID_PLAYER); }}}}, @@ -425,7 +440,7 @@ static const duration_def duration_data[] = { DUR_SENTINEL_MARK, LIGHTRED, "Mark", "marked", "sentinel's mark", - "A sentinel's mark is revealing your location to enemies.", D_DISPELLABLE | D_EXPIRES, + "A sentinel's mark is revealing your location to enemies.", D_DISPELLABLE | D_EXPIRES | D_NEGATIVE, {{ "The sentinel's mark upon you fades away." }}}, { DUR_FUGUE, BLUE, "Fugue", @@ -436,26 +451,26 @@ static const duration_def duration_data[] = { DUR_FLAYED, RED, "Flay", "flayed", "", - "You are covered in terrible wounds.", D_DISPELLABLE /* but special-cased */ | D_EXPIRES}, + "You are covered in terrible wounds.", D_DISPELLABLE /* but special-cased */ | D_EXPIRES | D_NEGATIVE}, { DUR_WEAK, RED, "Weak", "weakened", "weak", - "Your attacks are enfeebled.", D_DISPELLABLE, + "Your attacks are enfeebled.", D_DISPELLABLE | D_NEGATIVE, {{ "Your attacks no longer feel as feeble." }}}, { DUR_DIMENSION_ANCHOR, RED, "-Tele", "untranslocatable", "dimension anchor", - "You are firmly anchored to this plane.", D_DISPELLABLE, + "You are firmly anchored to this plane.", D_DISPELLABLE | D_NEGATIVE, {{ "You are no longer firmly anchored in space." }}}, { DUR_NO_MOMENTUM, RED, "-Move", "immotile", "", - "You are unable to move around.", D_DISPELLABLE, + "You are unable to move around.", D_DISPELLABLE | D_NEGATIVE, {{ "You are able to move again." }}}, { DUR_VAINGLORY, RED, "Vainglory", "no stairs", "", - "You refuse to leave the level so soon after announcing yourself.", D_EXPIRES, + "You refuse to leave the level so soon after announcing yourself.", D_EXPIRES | D_NEGATIVE, {{ "You feel willing to depart the floor again." }}}, { DUR_ENLIGHTENED, BLUE, "Will+", @@ -474,26 +489,26 @@ static const duration_def duration_data[] = { DUR_RECITE_COOLDOWN, YELLOW, "-Recite", "on recite cooldown", "", - "You are unable to recite.", D_NO_FLAGS, + "You are unable to recite.", D_COOLDOWN, {{ "You are ready to recite again." }}}, { DUR_FIRE_VULN, RED, "rF-", "fire vulnerable", "fire vulnerability", - "You are more vulnerable to fire.", D_DISPELLABLE, + "You are more vulnerable to fire.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel less vulnerable to fire." }}}, { DUR_BARBS, RED, "Barbs", "spiked", "barbed spikes", - "Barbed spikes are embedded in your body.", D_NO_FLAGS}, + "Barbed spikes are embedded in your body.", D_NEGATIVE}, { DUR_POISON_VULN, RED, "rP-", "poison vulnerable", "poison vulnerability", - "You are more vulnerable to poison.", D_DISPELLABLE, + "You are more vulnerable to poison.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel less vulnerable to poison." }}}, { DUR_FROZEN, RED, "Frozen", "frozen", "", - "You are partly encased in ice.", D_DISPELLABLE, + "You are partly encased in ice.", D_DISPELLABLE | D_NEGATIVE, {{ "The ice encasing you melts away." }, {}, true }}, { DUR_DIMENSIONAL_BULLSEYE, LIGHTBLUE, "Bullseye", @@ -515,7 +530,7 @@ static const duration_def duration_data[] = { DUR_DRAGON_CALL_COOLDOWN, YELLOW, "-Dragoncall", "on dragon call cooldown", "dragon call cooldown", - "You are unable to call dragons.", D_NO_FLAGS, + "You are unable to call dragons.", D_COOLDOWN, {{ "You can once more reach out to the dragon horde." }}}, { DUR_QAZLAL_FIRE_RES, LIGHTBLUE, "rF+", @@ -544,12 +559,12 @@ static const duration_def duration_data[] = { DUR_CORROSION, RED, "Corr", "corroded", "corrosion", - "You are corroded.", D_DISPELLABLE, + "You are corroded.", D_DISPELLABLE | D_NEGATIVE, {{ "You are no longer corroded.", _end_corrosion }}}, { DUR_HORROR, RED, "Horr", "horrified", "horror", - "You are horrified, weakening your attacks and spells.", D_NO_FLAGS}, + "You are horrified, weakening your attacks and spells.", D_NEGATIVE}, { DUR_DIVINE_SHIELD, LIGHTBLUE, "", "divinely shielded", "divine shield", @@ -574,13 +589,13 @@ static const duration_def duration_data[] = { DUR_OBLIVION_HOWL, RED, "Howl", "oblivion-hounded", "howl", - "A terrible howling echoes in your mind.", D_DISPELLABLE, + "A terrible howling echoes in your mind.", D_DISPELLABLE | D_NEGATIVE, {{ "The infernal howling subsides.", []() { you.props.erase(NEXT_OBLIVION_SPAWN_KEY); }}}}, { DUR_VERTIGO, YELLOW, "Vertigo", "vertiginous", "vertigo", - "Vertigo is making it harder to attack, cast, and dodge.", D_DISPELLABLE, + "Vertigo is making it harder to attack, cast, and dodge.", D_DISPELLABLE | D_NEGATIVE, {{ "The world stops spinning.", []() { you.redraw_evasion = true; }}}}, @@ -594,11 +609,11 @@ static const duration_def duration_data[] = {{ "", _redraw_armour }}}, { DUR_NO_HOP, YELLOW, "-Hop", "unable to hop", "no hop", - "You are unable to hop.", D_NO_FLAGS, + "You are unable to hop.", D_COOLDOWN, {{ "You are ready to hop once more." }}}, { DUR_BLINKBOLT_COOLDOWN, YELLOW, "-Bbolt", "blinkbolt cooldown", "no blinkbolt", - "", D_NO_FLAGS, + "", D_COOLDOWN, {{ "You feel energetic enough to blinkbolt again." }}}, { DUR_ACROBAT, 0, "", "acrobatic", "acrobat", @@ -609,23 +624,23 @@ static const duration_def duration_data[] = { DUR_ATTRACTIVE, LIGHTBLUE, "Attr", "attractive", "attract", - "You attract monsters toward you.", D_DISPELLABLE }, + "You attract monsters toward you.", D_DISPELLABLE | D_NEGATIVE }, { DUR_ELIXIR, WHITE, "Elixir", "elixired", "elixir", "You are rapidly regenerating health and magic.", D_NO_FLAGS}, { DUR_WORD_OF_CHAOS_COOLDOWN, YELLOW, "-Word", "on word of chaos cooldown", "word of chaos cooldown", - "You are unable to speak a word of chaos.", D_NO_FLAGS, + "You are unable to speak a word of chaos.", D_COOLDOWN, {{ "You are ready to speak a word of chaos again." }}}, { DUR_SAP_MAGIC, YELLOW, "Sap", "magic-sapped", "sap magic", "Casting spells may cause you to lose access to your magic.", - D_DISPELLABLE, + D_DISPELLABLE | D_NEGATIVE, {{ "Your magic seems less tainted." }}}, { DUR_NO_CAST, RED, "-Cast", "unable to cast spells", "no cast", - "You are unable to cast spells.", D_DISPELLABLE, + "You are unable to cast spells.", D_DISPELLABLE | D_NEGATIVE, {{ "You regain access to your magic." }}}, { DUR_RISING_FLAME, LIGHTBLUE, "Rise", @@ -635,17 +650,17 @@ static const duration_def duration_data[] = { DUR_SICKNESS, RED, "Sick", "sick", "sickness", - "Your sickness prevents you from regenerating health.", D_DISPELLABLE, + "Your sickness prevents you from regenerating health.", D_DISPELLABLE | D_NEGATIVE, {{ "You feel your health improve." }}}, { DUR_BLINK_COOLDOWN, YELLOW, "-Blink", "on blink cooldown", "blink cooldown", - "You are unable to blink.", D_NO_FLAGS, + "You are unable to blink.", D_NO_FLAGS | D_COOLDOWN, {{ "You feel ready to blink again."}}}, { DUR_GAVOTTE_COOLDOWN, YELLOW, "-Gavotte", "on gavotte cooldown", "gavotte cooldown", - "You are unable to cast Gavotte.", D_NO_FLAGS, + "You are unable to cast Gavotte.", D_NO_FLAGS | D_COOLDOWN, {{ "Gravity stabilises in your vicinity."}}}, { DUR_ANIMATE_DEAD, MAGENTA, "Reap", @@ -656,7 +671,7 @@ static const duration_def duration_data[] = { DUR_SIPHON_COOLDOWN, YELLOW, "-Siphon", "on siphon cooldown", "siphon cooldown", - "You are unable to siphon essence.", D_NO_FLAGS, + "You are unable to siphon essence.", D_COOLDOWN, {{ "You are ready to siphon essence again." }}}, { DUR_CELEBRANT_COOLDOWN, YELLOW, "-Bloodrite", @@ -687,11 +702,11 @@ static const duration_def duration_data[] = {{ "Night gives way to day once more.", update_vision_range }}}, { DUR_BLIND, RED, "Blind", "blinded", "blindness", "The further away your target is the more your accuracy is reduced.", - D_DISPELLABLE | D_EXPIRES, {{ "", + D_DISPELLABLE | D_EXPIRES | D_NEGATIVE, {{ "", [](){mprf(MSGCH_RECOVERY, "Your vision returns to normal.");}}}}, { DUR_SIGN_OF_RUIN, RED, "Ruin", "sign of ruin", "ruin", - "The sign of ruin enfeebles you when you suffer attacks.", D_DISPELLABLE, + "The sign of ruin enfeebles you when you suffer attacks.", D_DISPELLABLE | D_NEGATIVE, {{ "The sign of ruin upon you fades." }}}, { DUR_INFERNAL_LEGION, WHITE, "Legion", @@ -710,7 +725,7 @@ static const duration_def duration_data[] = {{ "", _end_growing_destruction}}}, { DUR_BLINKITIS, RED, "Unstable", "blinking rapidly", "blinkitis", - "You are untethered in space.", D_DISPELLABLE, {{"You feel more stable."}} }, + "You are untethered in space.", D_DISPELLABLE | D_NEGATIVE, {{"You feel more stable."}} }, { DUR_CACOPHONY, WHITE, "Cacophony", "making a cacophony", "cacophony", @@ -725,7 +740,7 @@ static const duration_def duration_data[] = { DUR_SHROUD_TIMEOUT, DARKGREY, "Shroud", "shroud timeout", "shroud timeout", - "Your shroud of slime is broken and needs time to repair.", D_EXPIRES, + "Your shroud of slime is broken and needs time to repair.", D_EXPIRES | D_COOLDOWN, {{ "Your slime shroud regrows." }}}, { DUR_WEREFURY, BLUE, "Slay", @@ -739,14 +754,14 @@ static const duration_def duration_data[] = { DUR_INVIS, 0, "", "", "invis", "", D_DISPELLABLE, {{ "", _end_invis }, { "You flicker for a moment.", 1}}, 6}, - { DUR_SLOW, 0, "", "", "slow", "", D_DISPELLABLE}, - { DUR_MESMERISED, 0, "", "", "mesmerised", "", D_DISPELLABLE, + { DUR_SLOW, 0, "", "", "slow", "", D_DISPELLABLE | D_NEGATIVE}, + { DUR_MESMERISED, 0, "", "", "mesmerised", "", D_DISPELLABLE | D_NEGATIVE, {{ "You break out of your daze.", []() { you.clear_beholders(); }}, {}, true }}, { DUR_MESMERISE_IMMUNE, 0, "", "", "mesmerisation immunity", "", D_NO_FLAGS, {{""}} }, { DUR_HASTE, 0, "", "", "haste", "", D_DISPELLABLE, {}, 6}, { DUR_FLIGHT, 0, "", "", "flight", "", D_DISPELLABLE /*but special-cased*/, {}, 10}, - { DUR_POISONING, 0, "", "", "poisoning", "", D_NO_FLAGS}, + { DUR_POISONING, 0, "", "", "poisoning", "", D_NEGATIVE}, { DUR_PIETY_POOL, 0, "", "", "piety pool", "", D_NO_FLAGS}, { DUR_TRANSFORMATION, 0, "", "", "transformation", "", D_DISPELLABLE /*but special-cased*/, {}, 10}, { DUR_DEMONIC_GUARDIAN, 0, "", "", "demonic guardian", "", D_NO_FLAGS, {{""}}}, @@ -755,12 +770,12 @@ static const duration_def duration_data[] = { DUR_REPEL_STAIRS_CLIMB, 0, "", "", "repel stairs climb", "", D_NO_FLAGS, {{""}}}, { DUR_CLOUD_TRAIL, 0, "", "", "cloud trail", "", D_NO_FLAGS}, { DUR_TIME_STEP, 0, "", "", "time step", "", D_NO_FLAGS}, - { DUR_ICEMAIL_DEPLETED, 0, "", "", "icemail depleted", "", D_NO_FLAGS, + { DUR_ICEMAIL_DEPLETED, 0, "", "", "icemail depleted", "", D_COOLDOWN, {{ "Your icy envelope is restored.", _redraw_armour }}}, { DUR_STUN_IMMUNITY, 0, "", "", "immune to disabling effects", "", D_NO_FLAGS}, { DUR_VEHUMET_GIFT, 0, "", "", "vehumet gift", "", D_NO_FLAGS, {{""}}}, - { DUR_SICKENING, 0, "", "", "sickening", "", D_NO_FLAGS, {{""}}}, - { DUR_WATER_HOLD, 0, "", "", "drowning", "", D_NO_FLAGS}, + { DUR_SICKENING, 0, "", "", "sickening", "", D_NEGATIVE, {{""}}}, + { DUR_WATER_HOLD, 0, "", "", "drowning", "", D_NEGATIVE}, // Regeneration information handled separately. { DUR_TROGS_HAND, 0, "", "strong-willed", "trogs hand", "Your willpower is greatly increased.", D_EXPIRES, @@ -784,12 +799,12 @@ static const duration_def duration_data[] = { DUR_HEAVENLY_STORM, 0, "", "in a heavenly storm", "heavenly storm", "Heavenly clouds are increasing your accuracy and damage.", D_NO_FLAGS, {{ "", wu_jian_decrement_heavenly_storm }}}, - { DUR_NO_POTIONS, 0, "", "", "no potions", "", D_NO_FLAGS, + { DUR_NO_POTIONS, 0, "", "", "no potions", "", D_NEGATIVE, {{ "", []() { if (you.can_drink() && !player_in_branch(BRANCH_COCYTUS)) mprf(MSGCH_RECOVERY, "You can drink potions again."); }}}}, - { DUR_NO_SCROLLS, 0, "", "", "no scrolls", "", D_NO_FLAGS, + { DUR_NO_SCROLLS, 0, "", "", "no scrolls", "", D_NEGATIVE, {{ "", []() { if (!player_in_branch(BRANCH_GEHENNA)) mprf(MSGCH_RECOVERY, "You can read scrolls again."); @@ -811,10 +826,10 @@ static const duration_def duration_data[] = { DUR_FORTRESS_BLAST_TIMER, 0, "", "", "fortress blast charging", "", D_DISPELLABLE}, { DUR_PHALANX_BARRIER, 0, "", "phalanx barrier", "phalanx barrier", "", D_NO_FLAGS}, { DUR_TRICKSTER_GRACE, 0, "", "", "trickster", "", D_NO_FLAGS, {{""}}}, - { DUR_DROWSY, 0, "Drowsy", "", "drowsy", "", D_NO_FLAGS, {{"You feel less drowsy."}}}, + { DUR_DROWSY, 0, "Drowsy", "", "drowsy", "", D_NEGATIVE, {{"You feel less drowsy."}}}, { DUR_RIME_YAK_AURA, 0, "", "", "cold aura", "", D_NO_FLAGS, {{""}}}, { DUR_AUTODODGE, 0, "", "", "autododge", "", D_NO_FLAGS}, - { DUR_DAZED, 0, "", "", "dazed", "", D_NO_FLAGS}, + { DUR_DAZED, 0, "", "", "dazed", "", D_NEGATIVE}, #if TAG_MAJOR_VERSION == 34 // And removed ones diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index fddfd25506..112501e67f 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -35,6 +35,7 @@ #include "describe.h" #include "directn.h" #include "dlua.h" +#include "duration-data.h" #include "end.h" #include "errors.h" #include "explore-greedy-options.h" @@ -64,6 +65,7 @@ #include "spl-util.h" #include "stash.h" #include "state.h" +#include "status.h" #include "stringutil.h" #include "syscalls.h" #include "tags.h" @@ -554,6 +556,9 @@ const vector<GameOption*> game_options::build_options_list() new BoolGameOption(SIMPLE_NAME(dos_use_background_intensity), true), new BoolGameOption(SIMPLE_NAME(explore_greedy), true), new BoolGameOption(SIMPLE_NAME(explore_auto_rest), true), + new ListGameOption<string>(ON_SET_NAME(explore_auto_rest_status), + {"all_negative", "all_cooldown", "contam"}, false, + [this]() { update_explore_auto_rest_status(); }), new BoolGameOption(SIMPLE_NAME(travel_key_stop), true), new ListGameOption<string>(ON_SET_NAME(explore_stop), {"item", "stair", "portal", "branch", "shop", "altar", @@ -3180,6 +3185,54 @@ void game_options::update_explore_greedy_visit_conditions() explore_greedy_visit = conditions; } +void game_options::update_explore_auto_rest_status() +{ + set<duration_type> durs; + explore_auto_rest_contam = false; + + for (const auto& str : explore_auto_rest_status_option) + { + if (str == "all_negative") + { + const vector<duration_type> neg = all_duration_with_flag(D_NEGATIVE); + durs.insert(neg.begin(), neg.end()); + } + else if (str == "all_cooldown") + { + const vector<duration_type> cooldown = all_duration_with_flag(D_COOLDOWN); + durs.insert(cooldown.begin(), cooldown.end()); + } + else if (str == "contam") + explore_auto_rest_contam = true; + else + { + string str_nospace = lowercase_string(str); + remove_whitespace(str_nospace); + + bool invert = false; + if (!str_nospace.empty() && str_nospace[0] == '*') + { + invert = true; + str_nospace = str_nospace.substr(1); + } + + duration_type dur = duration_by_name(str_nospace); + + if (invert) + durs.erase(dur); + else + durs.insert(dur); + } + } + + // Erase effects that do not expire with time in general. + durs.erase(DUR_HORROR); + durs.erase(DUR_MESMERISED); + durs.erase(DUR_AFRAID); + + explore_auto_rest_status.assign(durs.begin(), durs.end()); +} + message_filter::message_filter(const string &filter) : message_filter() { diff --git a/crawl-ref/source/options.h b/crawl-ref/source/options.h index 4e2c7ac707..753fe3100c 100644 --- a/crawl-ref/source/options.h +++ b/crawl-ref/source/options.h @@ -9,6 +9,7 @@ #include "activity-interrupt-type.h" #include "char-set-type.h" #include "confirm-prompt-type.h" +#include "duration-type.h" #include "easy-confirm-type.h" #include "explore-greedy-options.h" #include "explore-stop-options.h" @@ -711,6 +712,12 @@ public: // Wait for rest wait percent HP and MP before exploring. bool explore_auto_rest; + // Which temporary statuses and cooldowns to wait for before exploring. + vector<string> explore_auto_rest_status_option; + // Processed into these automatically: + vector<duration_type> explore_auto_rest_status; + bool explore_auto_rest_contam; + bool travel_key_stop; // Travel stops on keypress. bool travel_one_unsafe_move; // Allow one unsafe move of auto travel @@ -973,6 +980,7 @@ private: void update_explore_stop_conditions(); void update_explore_greedy_visit_conditions(); + void update_explore_auto_rest_status(); void update_use_animations(); void update_travel_terrain(); diff --git a/crawl-ref/source/status.cc b/crawl-ref/source/status.cc index 3892b6480f..46549fa664 100644 --- a/crawl-ref/source/status.cc +++ b/crawl-ref/source/status.cc @@ -3,31 +3,22 @@ #include "status.h" #include "ability.h" -#include "areas.h" #include "art-enum.h" // bearserk #include "artefact.h" #include "branch.h" -#include "cloud.h" #include "dungeon.h" // DESCENT_STAIRS_KEY #include "duration-type.h" #include "env.h" #include "evoke.h" #include "fight.h" // weapon_cleaves -#include "god-abil.h" -#include "god-passive.h" #include "item-prop.h" #include "level-state-type.h" -#include "mon-transit.h" // untag_followers() in duration-data #include "mutation.h" #include "options.h" #include "orb.h" // orb_limits_translocation in fill_status_info #include "player-stats.h" -#include "random.h" // for midpoint_msg.offset() in duration-data #include "religion.h" #include "spl-damage.h" // COUPLING_TIME_KEY -#include "spl-summoning.h" // NEXT_OBLIVION_SPAWN_KEY in duration-data -#include "spl-transloc.h" // for you_teleport_now() in duration-data -#include "stairs.h" // rise_through_ceiling #include "state.h" // crawl_state #include "stringutil.h" #include "throw.h" @@ -69,6 +60,52 @@ const char *duration_name(duration_type dur) return _lookup_duration(dur)->name(); } +duration_type duration_by_name(const string &name) +{ + string match_str = lowercase_string(name); + for (int i = 0; i < NUM_DURATIONS; i++) + { + const duration_def& def = duration_data[i]; + + string light_text = def.light_text; + string short_text = def.short_text; + string name_text = def.name_text; + + lowercase(light_text); + lowercase(short_text); + lowercase(name_text); + + if (match_str == short_text + || match_str == name_text + || match_str == light_text + || light_text.find(match_str) != string::npos + || short_text.find(match_str) != string::npos + || name_text.find(match_str) != string::npos) + { + return def.dur; + } + } + return NUM_DURATIONS; +} + +/** + * Vector of all durations with flag + * + */ +vector<duration_type> all_duration_with_flag(uint64_t flag) +{ + vector<duration_type> durations_with_flag = {}; + for (int i = 0; i < NUM_DURATIONS; i++) + { + duration_type type = (duration_type) duration_index[i]; + const duration_def* def = _lookup_duration(type); + if (def && def->duration_has_flag(flag)) { + durations_with_flag.push_back(type); + } + } + return durations_with_flag; +} + bool duration_dispellable(duration_type dur) { return _lookup_duration(dur)->duration_has_flag(D_DISPELLABLE); diff --git a/crawl-ref/source/status.h b/crawl-ref/source/status.h index e40067fa33..a9316a5f97 100644 --- a/crawl-ref/source/status.h +++ b/crawl-ref/source/status.h @@ -79,6 +79,8 @@ struct status_info bool fill_status_info(int status, status_info& info); const char *duration_name(duration_type dur); +duration_type duration_by_name(const string &name); +vector<duration_type> all_duration_with_flag(uint64_t flag); bool duration_dispellable(duration_type dur); void init_duration_index(); diff --git a/crawl-ref/source/transform.cc b/crawl-ref/source/transform.cc index 962ef51a59..b699a1538d 100644 --- a/crawl-ref/source/transform.cc +++ b/crawl-ref/source/transform.cc @@ -170,6 +170,7 @@ Form::Form(const form_entry &fe) changes_anatomy(fe.changes_anatomy), changes_substance(fe.changes_substance), holiness(fe.holiness), + is_badform(fe.is_badform), has_blood(fe.has_blood), has_hair(fe.has_hair), has_bones(fe.has_bones), has_feet(fe.has_feet), has_ears(fe.has_ears), @@ -1385,6 +1386,11 @@ bool form_can_swim(transformation form) return get_form(form)->player_can_swim(); } +bool form_is_bad(transformation form) +{ + return get_form(form)->is_badform; +} + // Used to mark transformations which change the basic matter the player is // made up of (ie: statue/storm form) bool form_changes_substance(transformation form) diff --git a/crawl-ref/source/transform.h b/crawl-ref/source/transform.h index 1157847e5f..2913f69872 100644 --- a/crawl-ref/source/transform.h +++ b/crawl-ref/source/transform.h @@ -215,6 +215,8 @@ public: /// What does this form change the player's holiness to? (MH_NONE if it leaves it unchanged) /// Note that vampire is special-cased in player::holiness(). const mon_holy_type holiness; + /// Is this form considered 'bad' (ie: hostile) + const bool is_badform; /// Does this form have blood (used for sublimation and bloodsplatters)? const form_capability has_blood; @@ -314,6 +316,7 @@ const Form* cur_form(bool temp = true); bool lifeless_prevents_form(transformation form = you.form); +bool form_is_bad(transformation form = you.form); bool form_can_wield(transformation form = you.form); bool form_can_wear(transformation form = you.form); bool form_can_fly(transformation form = you.form); diff --git a/crawl-ref/source/travel.cc b/crawl-ref/source/travel.cc index 90f5172c53..e97905bd2a 100644 --- a/crawl-ref/source/travel.cc +++ b/crawl-ref/source/travel.cc @@ -53,10 +53,12 @@ #include "religion.h" #include "stairs.h" #include "state.h" +#include "status.h" #include "stringutil.h" #include "tag-version.h" #include "terrain.h" #include "tiles-build-specific.h" +#include "transform.h" #include "traps.h" #include "travel-open-doors-type.h" #include "ui.h" @@ -1077,12 +1079,51 @@ command_type travel() if (you.running.is_explore()) { + // XXX: It is possible for the player to manually add a non-duration-based + // status effect to this option, resulting in situations where + // autoexplore can never move. We wait an arbitrary 500 turns before + // deciding something must be wrong and stopping (to prevent an assert). + if (you.elapsed_time > you.elapsed_time_at_last_input + 5000 + && !Options.explore_auto_rest_status.empty()) + { + mprf(MSGCH_ERROR, + "You appear to be waiting for the end of something which may " + "never occur. Examine your explore_auto_rest_status option."); + stop_running(); + return CMD_NO_CMD; + } + if (Options.explore_auto_rest && !you.is_sufficiently_rested() || you.duration[DUR_NO_MOMENTUM]) { return CMD_WAIT; } + for (unsigned int i = 0; i < Options.explore_auto_rest_status.size(); ++i) + { + duration_type type = Options.explore_auto_rest_status[i]; + + if (you.duration[type] == 0) + continue; + + // Only rest off the bad part of Swiftness + if (type == DUR_SWIFTNESS && you.attribute[ATTR_SWIFTNESS] > 0) + continue; + + // Only try to rest off transformations when this is both possible + // and the form is negative. + if (type == DUR_TRANSFORMATION + && (!you.transform_uncancellable || !form_is_bad())) + { + continue; + } + + return CMD_WAIT; + } + + if (Options.explore_auto_rest_contam && you.magic_contamination) + return CMD_WAIT; + // Exploring. if (env.grid(you.pos()) == DNGN_ENTER_SHOP && you.running == RMODE_EXPLORE_GREEDY) diff --git a/crawl-ref/source/util/form-gen.py b/crawl-ref/source/util/form-gen.py index b971c58c34..4ce03d5c12 100644 --- a/crawl-ref/source/util/form-gen.py +++ b/crawl-ref/source/util/form-gen.py @@ -350,6 +350,7 @@ keyfns = { 'changes_substance': Field(parse_bool), 'holiness': Field(lambda s: "MH_" + s.upper()), + 'is_badform': Field(parse_bool), 'has_blood': Field(parse_capability), 'has_hair': Field(parse_capability), 'has_bones': Field(parse_capability), @@ -410,6 +411,7 @@ defaults = { 'changes_substance': "false", 'holiness': "MH_NONE", + 'is_badform': 'false', 'has_blood': "FC_DEFAULT", 'has_hair': "FC_DEFAULT", 'has_bones': "FC_DEFAULT", diff --git a/crawl-ref/source/util/form-gen/body.txt b/crawl-ref/source/util/form-gen/body.txt index 966f8d4935..5e582d9811 100644 --- a/crawl-ref/source/util/form-gen/body.txt +++ b/crawl-ref/source/util/form-gen/body.txt @@ -8,7 +8,7 @@ {ac_scaling}, {ev_scaling}, {body_ac_mult_scaling}, {can_cast}, {unarmed_scaling}, {unarmed_brand}, {unarmed_colour}, "{unarmed_name}", {unarmed_verbs}, {can_fly}, {can_swim}, {offhand_punch}, {changes_anatomy}, {changes_substance}, {holiness}, - {has_blood}, {has_hair}, {has_bones}, {has_feet}, {has_ears}, + {is_badform}, {has_blood}, {has_hair}, {has_bones}, {has_feet}, {has_ears}, "{shout_verb}", {shout_volume}, "{hand_name}", "{foot_name}", "{prayer_action}", "{flesh_name}", {special_dice}, "{special_damage_name}", {{{fakemuts}}}, diff --git a/crawl-ref/source/util/form-gen/header.txt b/crawl-ref/source/util/form-gen/header.txt index 4a6a140fa4..8317dce482 100644 --- a/crawl-ref/source/util/form-gen/header.txt +++ b/crawl-ref/source/util/form-gen/header.txt @@ -56,6 +56,7 @@ struct form_entry mon_holy_type holiness; // Row 9: + bool is_badform; form_capability has_blood; form_capability has_hair; form_capability has_bones; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-09 07:50:16
|
via 22a848724cb8892b6b1ff5a94f70ec54fcd0c00e (commit) from 740026549f8b43eceff41d839dff048cf23d9f53 (commit) ----------------------------------------------------------------------- commit 22a848724cb8892b6b1ff5a94f70ec54fcd0c00e Author: DracoOmega <dra...@gm...> Date: Wed Jul 9 05:15:33 2025 -0230 Remove a leftover debugging statement (Undo) ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/mon-death.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index 12015108a5..48ff5421f1 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -257,10 +257,7 @@ static int _calc_player_experience(const monster* mons) // Award the player any XP remaining in the tesseract's XP pool. if (mons->type == MONS_BOUNDLESS_TESSERACT && mons->props.exists(TESSERACT_XP_KEY)) - { experience += mons->props[TESSERACT_XP_KEY].get_int(); - mprf("Awarding %d bonus XP.", mons->props[TESSERACT_XP_KEY].get_int()); - } return experience; } -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 18:00:29
|
via 92974b8de6179edbd4d80ff7fe8bd95b4779db9e (commit) from a00341b0ceeb71f9798f37140eb40583dd6a359b (commit) ----------------------------------------------------------------------- commit 92974b8de6179edbd4d80ff7fe8bd95b4779db9e Author: RypoFalem <ryp...@gm...> Date: Tue Jul 8 11:21:27 2025 -0500 fix: equipment truncation with show_resist_percent (adinsx) It just needed 3 fewer characters so it didn't overflow to the next line. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/output.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index ba4b3c72ad..336e9983cf 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -2142,14 +2142,16 @@ static void _print_overview_screen_equip(column_composer& cols, const int item_idx = equipped[i].item; const char equip_char = index_to_letter(item_idx); + const int equip_width = (melded ? sw - 32 : sw - 25) + - (Options.show_resist_percent ? 3 : 0); str = make_stringf( "<w>%c</w> - <%s>%s%s</%s>", equip_char, colname.c_str(), melded ? "melded " : "", - chop_string(item.name(DESC_PLAIN, true), - melded ? sw - 32 : sw - 25, false).c_str(), + chop_string(item.name(DESC_PLAIN, true), equip_width, + false).c_str(), colname.c_str()); equip_chars.push_back(equip_char); -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 17:45:09
|
via 740026549f8b43eceff41d839dff048cf23d9f53 (commit) from f559632a36f990224cb2edb4f49eaee648e830e9 (commit) ----------------------------------------------------------------------- commit 740026549f8b43eceff41d839dff048cf23d9f53 Author: DracoOmega <dra...@gm...> Date: Tue Jul 8 15:11:58 2025 -0230 Let vampire bloodprinces fly (Lightli) This was possibly an oversight to begin with; they even have wings in their tile! ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/dat/mons/vampire-bloodprince.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crawl-ref/source/dat/mons/vampire-bloodprince.yaml b/crawl-ref/source/dat/mons/vampire-bloodprince.yaml index 75f5e051a8..8658393473 100644 --- a/crawl-ref/source/dat/mons/vampire-bloodprince.yaml +++ b/crawl-ref/source/dat/mons/vampire-bloodprince.yaml @@ -1,6 +1,6 @@ name: "vampire bloodprince" glyph: {char: "V", colour: lightred} -flags: [fighter, see_invis, speaks, warm_blood, gender_neutral] +flags: [fighter, see_invis, speaks, warm_blood, gender_neutral, flies] resists: {cold: 1} exp: 2240 species: vampire -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 17:40:26
|
via f559632a36f990224cb2edb4f49eaee648e830e9 (commit) from 92974b8de6179edbd4d80ff7fe8bd95b4779db9e (commit) ----------------------------------------------------------------------- commit f559632a36f990224cb2edb4f49eaee648e830e9 Author: DracoOmega <dra...@gm...> Date: Tue Jul 8 15:07:53 2025 -0230 Fix sometimes knowing Zot orb monster at game start (hyperactiveChipmunk) I continue to forget that one can't assume bools actually start false. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/player.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 12153321d5..9698612a8b 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -5512,6 +5512,8 @@ player::player() transit_stair = DNGN_UNSEEN; entering_level = false; + zot_orb_monster_known = false; + reset_escaped_death(); on_current_level = true; seen_portals = 0; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 15:30:11
|
via a00341b0ceeb71f9798f37140eb40583dd6a359b (commit) via c8829d1dcfce3a3edd22ed31c1c089868b3a85a3 (commit) via 7335e6a58e337fd3b347215cee8ab5c84d244516 (commit) via bb4d5816a9feff6dead4cbce9cb61a7e9ac9e394 (commit) via ad3b09032c7003098d32853ad525631d4c29c246 (commit) from 9a6fec6d823cfc27d24a0f0d84553c713a4e90d1 (commit) ----------------------------------------------------------------------- commit a00341b0ceeb71f9798f37140eb40583dd6a359b Author: regret-index <clo...@ho...> Date: Tue Jul 8 12:59:21 2025 -0230 Changelog updates for 0.34 Timed a little late for the big Doom and Troves and Zot updates, but still relevant for helping people read about such nonetheless. commit c8829d1dcfce3a3edd22ed31c1c089868b3a85a3 Author: regret-index <clo...@ho...> Date: Tue Jul 8 12:32:01 2025 -0230 Add a Sentinel's Mark icon, display it on players by default While there is technically a force_more involved with alarm traps since 0644d94 and a unique flash over the player for the spell since 82142fb, it is possible to miss both in the walls of animations, tiles, and text one can get on a turn, and it's one of the most relevant debuffs one can otherwise miss. With this new icon being enabled by default in the tile_player_status_icons option, it will hopefully be yet more difficult for players to miss it in a relatively non-obtrusive fashion. commit 7335e6a58e337fd3b347215cee8ab5c84d244516 Author: regret-index <clo...@ho...> Date: Tue Jul 8 12:05:53 2025 -0230 Recent tile adjustments * To help with parsing their outlines, the bottom fringe of reaper robes has been brightened. * To help it be more obvious and more readily resemble other current vfx tiles, ostracism's bolt effect now has brighter highlights. * To help with parsing each of them as traps and not new decorations or item tiles, archmage's traps, tyrant's traps, and devourer's traps now all use the same old trap plate / pit graphic Denzi used for many traps and which still survives currently with pressure plate + net traps. It's still a bit of a weird rift to have such a style versus the monochromatic ground-sigil types of trap graphics, but I'd prefer to emphasize such shared language over raising confusion between traps types as currently exists between teleportation trap variations and dispersal traps. commit bb4d5816a9feff6dead4cbce9cb61a7e9ac9e394 Author: regret-index <clo...@ho...> Date: Tue Jul 8 12:05:33 2025 -0230 Nudge up devourer's traps In line with 70c6c67 trying to make rarer and less consistent sources of corrosion be more effective so they're more noticeable when they do happen, and with the introduction of a corrosion effect doing more than 4 at a time, I'm nudging up devourer's traps to match the Corrosive Bolt changes: 75% chance of -6 AC and slaying, as opposed to ~66% for -4. They're far less directly effective (or anecdotally noticed) than the other traps of their quartet, but are also inherently themed towards a very late placement; as such, they can take the buff. commit ad3b09032c7003098d32853ad525631d4c29c246 Author: regret-index <clo...@ho...> Date: Tue Jul 8 08:56:49 2025 -0230 Fix a rare temple entry removing its own orb statues (Darby) ----------------------------------------------------------------------- Summary of changes: crawl-ref/docs/changelog.txt | 231 +++++++++++++++++++++ crawl-ref/source/dat/des/branches/temple.des | 4 +- crawl-ref/source/initfile.cc | 2 +- .../{dngn/traps => UNUSED/floor}/archmage.png | Bin .../{dngn/traps => UNUSED/floor}/devourer.png | Bin .../{dngn/traps => UNUSED/floor}/tyrant.png | Bin crawl-ref/source/rltiles/dc-icons.txt | 1 + crawl-ref/source/rltiles/dngn/traps/archmage.png | Bin 8209 -> 1828 bytes crawl-ref/source/rltiles/dngn/traps/devourer.png | Bin 8176 -> 2328 bytes crawl-ref/source/rltiles/dngn/traps/tyrant.png | Bin 6994 -> 1930 bytes crawl-ref/source/rltiles/effect/ostracise.png | Bin 7532 -> 7859 bytes .../icons/{regeneration.png => sentinel_mark.png} | Bin 4790 -> 5232 bytes crawl-ref/source/rltiles/mon/demons/reaper.png | Bin 8906 -> 8976 bytes .../rltiles/mon/demons/reaper_scytheless.png | Bin 8288 -> 8371 bytes crawl-ref/source/tilepick.cc | 2 +- crawl-ref/source/traps.cc | 4 +- .../webserver/game_data/static/cell_renderer.js | 1 + 17 files changed, 239 insertions(+), 6 deletions(-) copy crawl-ref/source/rltiles/{dngn/traps => UNUSED/floor}/archmage.png (100%) copy crawl-ref/source/rltiles/{dngn/traps => UNUSED/floor}/devourer.png (100%) copy crawl-ref/source/rltiles/{dngn/traps => UNUSED/floor}/tyrant.png (100%) copy crawl-ref/source/rltiles/misc/icons/{regeneration.png => sentinel_mark.png} (56%) diff --git a/crawl-ref/docs/changelog.txt b/crawl-ref/docs/changelog.txt index 899c335a8f..f255bafeca 100644 --- a/crawl-ref/docs/changelog.txt +++ b/crawl-ref/docs/changelog.txt @@ -1,3 +1,234 @@ +Stone Soup 0.34 (through 0.34-a0-329-gc8829d1dcf) +-------------------------------------------------- + +Artefacts +--------- +* The faerie dragon scales now has a higher average enchantment, can sometimes + come with evokable invisibility, and is a Hexes enhancer. +* The Sword of the Doom Knight has been renamed to the Sword of the Dread + Knight. +* Randarts can now come with a Bane property, which inflicts a Bane on the + player when equipped. Randarts with this property have higher enchantment. + +Branches, Environment +--------------------- +* The Crypt end vault's old thematic item rewards have been moved into a unique, + guaranteed shop containing a larger quantity of the prior options at high + prices. +* The Halls of Zot will now contain one of three types of orb monster each game, + each wielding a different element and form of strategic damage. + - The orb type one will encountered that game is indicated via statues placed + by the Temple entrance in the Dungeon and the Zot entrance in Depths. This + can also be viewed from the the Dungeon overview screen (ctrl+O) once seen. +* The last floor of Zot contains now contains two Boundless Tesseracts, immobile + enemy spawners with fast regeneration. + - Once a tesseract wakes up, new monsters will slowly appear across the entire + floor (always out of the player's line of sight). The rate at which they + appear will slowly increase and they will eventually stop giving experience + when killed. + - Destroying one will destroy the other and reward all the experience one + would have gotten from waiting to kill their spawns individually. +* The Orb status from being in Zot or having picked up the Orb of Zot now also + fuzzes the destination of scrolls of blinking by up to two spaces. +* Hell effects can now inflict a small amount of Doom instead of inflicting + transient mutations. +* Troves prices and costs have been heavily revised: + - Troves will no longer ask for any consumables besides scrolls of acquirement + and will no longer ask for specific named items from shops. + - Equipment costs are less common. Demon weapons are all interchangeable and + and heavier dragon scales are rarer. + - The Slimy / Abyssal rune troves and Horn of Geryon troves are more common. + - Piety troves now use a new debuff that temporarily caps one's piety at 0 + until XP is gained instead of permanently draining it, allowing them to + function with more gods than before. + - New trove costs include accepting pre-announced Banes and being extremely + drained. + - Trove contents are no longer grouped by item category, and contain a + slightly lower amount of higher-quality items themed after spell namesakes + or unrand items. These items are also far less likely to be useless + according to god restrictions or species limits. + - Potential troves to discover include The Dread Knight's Derelict Chapel, + Eringya's Secret Bog, The First Justicar's Armoury, Leda's Sunken Stockpile, + The Lost Hoard of Erebora, The Name-Rending Infernalists' Reservoir, The + Octopus King's Forgotten Garden, Ozocubu's Refridgerator, Rutra's Hidden + Sanctum, The Storm Queen's Palace Crash Site, a devouring Rift, and an + orange crystal hatchery. + +Character +--------- +* Players can now accumulate Doom from enemies and other hostile effects, a + new form of medium-term damage displayed as a percentage. Doom has no effect + on its own and disappears with gaining experience, but at 100% causes one to + gain a random Bane, which itself only disappears with gaining significantly + more experience differing between Bane types. Banes include: + - Bane of Claustrophobia, which lowers melee damage and accuracy for each + wall the player is adjacent to. + - Bane of the Dilettante, which reduces the player's highest weapon skill + as well as their two highest magic / invocation / evocation skills. + - Bane of Electrospasm, which makes suffering electric damage sometimes + inflict the -Move status. + - Bane of Heatstroke, which makes suffering fire damage sometimes Slow you. + - Bane of the Hunted, which makes any creatures summoned by enemy appear + next to the player, last longer, and be better at tracking you. + - Bane of Lethargy, which slows the player's movement speed. + - Bane of Mortality, which gives a chance for reapers to appear near wounded + players when no other enemies are around. + - Bane of Multiplicity, which gives a chance for any monster you fight to + create fragile clones of itself. + - Bane of Paradox, which gives a small chance for each new monster you + encounter to learn Manifold Assault with a chance to blink after casting it. + - Bane of the Reckless, which sets one's SH to 0. + - Bane of Snow-blindness, which makes suffering cold damage something inflict + Blind and Weak. + - Bane of Stumbling, which inflicts -25 EV when moving or standing still. + - Bane of Succour, which makes killing enemies heal other nearby enemies + based on the slain foe's max HP. + - Bane of Warding, which gives a small chance to give groups of monster the + Warding buff when first seen, which grants damage immunity from non-adjacent + sources of damage. +* Undead species and forms lose Doom/Banes half as quickly as other species. +* Player contamination has been heavily adjusted. + - The exact amount one is contaminated is now indicated as a percentage in the + sidebar. Harmful effects begin at 100% and cap at 300%. + - Crossing the 100% threshold is more likely to result in a bad mutation than + before (but very high amounts are less dangerous). + - Explosions from contamination are now possible at a lower threshold, ignore + AC, and are more damaging. + - Many existing effects have been rescaled to be similarly dangerous as before + this change. +* New mutations: + - Efficient Metabolism, which doubles the duration of potion status effects. + - Feed Off Suffering, which restores HP and MP after killing poisoned or + drained foes. + - Lucky, which gives a small chance for floor items the player encounters to + be randarts. + - Protean Grace, which gives +Slay and +EV based on how mutated you are. +* Other individual mutation changes: + - Electricity Vulnerability is now in the normal mutation pool. + - Thick Fur can now only be mutated by Trolls and Felids. + - Sense Surroundings is now stronger and only has two levels. + - The unsafe potion and scroll mutations have now been revised: they now + prevent using potions or scrolls with monsters in sight while your HP is + high (and have no effect when badly injured). +* Transient mutations are now only removed by slaying a sufficient number of + non-trivial monsters, and can no longer roll stat loss or Berserk mutations. +* Players have a longer stun immunity after being Vexed. +* Players can now negate intrinsic rPois- with two sources of rPois. +* Players succeeding at certain optional challenges can now obtain unique titles + proclaiming their triumph (or madness). + +Gods +---- +* Gozag's Gold Lust passive now properly displays when monsters are affected + by it (instead of regularly losing its visual indication before its effects + ended). +* Jiyva's jellies can no longer eat spellbooks. +* Vehumet's first level 1 spell gift is now given immediately upon worship. +* Vehumet's spell gift choices now account for Conjurations and Alchemy skill. +* Xom has a new action: slightly Dooming the player. +* All gods besides the good gods no longer allow rejoining them if one is + undergoing their wrath. +* Several wrath adjustments: + - Fedhas and Jiyva wraths have been simplified. + - Kiku wrath applies the Sign of Ruin instead of tormenting, and drains for + lower amounts that can no longer be resisted by rN+. + - Okawaru wrath summons are more varied and scale more smoothly to player xl. + - Qazlal wrath now applies the Banes of Heatstroke, Snow-blindness, and + Electrospasm instead of transient mutations of rF-, rC-, or rElec-. + +Interface and Options +--------------------- +* The character overview screen (%) now displays how much damage is prevented + by each pip of resistance the player has. + - the show_resist_percent option can be used to hide these numbers. +* The "Trivial" monster threat level threshold is now a little higher. +* warn_contam_cost option: warns the player before casting Irradiate if it + could potentially result in going over 100% contamination. + +Items +----- +* Parchments now replace the majority of spellbooks found in game, each + granting knowledge of a single spell. + - Parchments are much more common than spellbooks used to be, making the + total number of spells found in the game roughly equal to previous + versions. + - Floors with shops past the Dungeon and Lair have increasing likelihood to + contain an additional parchment shop. + - Randbooks now only appear in select vaults or via acquirement and + Sif Muna gifts. + - Higher-spell-level are now somewhat rarer early in the game and more + common later. +* Stones are now less common. + +Monsters +-------- +* Two new orb types rotate with orbs of fire in Zot each game: + - Orbs of Winter, which cast Flash Freeze, Ozocubu's Refrigeration, + and inflict a new Ostracism debuff that temporarily reduces one's piety. + - Orbs of Entropy, which cast Bolt of Draining, Acid Ball, and + inflict Doom upon their foes. +* New and returning monsters: + - Chonchon, chaotic flying heads for Depths. + - Cognitogaunts, antimagic starghouls for Crypt and Abyss. + - Crawling flesh cages, augmented ugly things for Vaults. + - Drudes, new weak Doom-inflicting tier-5 demons for D and the Abyss. + - Kobold fleshcrafters, abomination makers for Depths. + - Ravens, Doom-inflicting birds for Lair. + - Screaming refractions, crystal injury-mirroring undead for the Abyss. + - Zykzyls, the new malmutating tier-2 demon, now focused on hexes. +* Cacodemons no longer know Malmutate or Bolt of Devastation, but can cut + willpower in half with their melee and cast Doom Bolt: a penetrating bolt + that inflicts Doom on hit. +* Death knights trade Injury Mirror for higher stats, an umbra, and Hurl + Torchlight (like the Yred ability), and now place in the Vaults with draugr + instead of in late D. +* Doom hounds have been renamed to oblivion hounds. +* Draugr replace skeletons as derived undead monsters, losing health for more + AC, no speed penalty, an ability to wield weapons regardless of their original + form, and Doom-inflicting melee. They are rarer than the previous skeletons. +* Glowing orange brains no longer have Brain Bite. +* The moon troll now is warded from damage from non-adjacent foes, and loses + Dazzling Flash in exchange for Lee's Rapid Deconstruction. +* Neqoxecs no longer can inflict permanent mutations, but have a new Warp Body + spell that deals minor damage and inflicts transient mutations (or Vitrify, + if the player has already been repeatedly Warped). +* Purple very / ugly things now have extra Will and antimagic attacks. +* Reapers have a new non-skeletal flavour and now fly. +* Shining eyes trade Malmutate for Mutagenic Gaze, which inflicts contamination + over time (but is usable anywhere in line of sight). +* Sphinx marauders do less damage on average with their airstrike attacks. +* Monster purple draconians have slightly less Willpower, and classed draconians + have more Willpower. +* Mummy death curses now inflict more Draining, less Torment and Slow, and + have a chance to inflict Doom. +* Monsters with necromancy spells deal more damage with pain brand weapons. +* Monster Corrosive Bolt now has a higher chance to corrode for higher amounts + and does slightly more damage. +* Monster Bolts of Draining are more accurate. +* Monsters blindness resistance has been refactored: all sources of Blind + outside of light effects, Enfeeble, and divine powers are limited to + natural / demonic / holy monsters, while light can also work on undead and + Enfeeble / most divine Blind effects ignore Blind resistance entirely. +* Daze now makes monsters skip their actions until they take any damage, + instead of giving them a 1-in-4 chance to skip each action (but last less time). + +Spells +------ +* Dazzling Flash has been renamed Gloom and moved from Hexes / Fire to + Hexes / Necromancy. +* Enfeeble now inflicts a new Diminished Spells debuff that lowers the target's + spellpower rather than inflicting antimagic. +* Summon Horrible Things now increases the caster's Doom rather than sometimes + inflicting temporary Will- mutations. + +Tiles +----- +* New tiles for existing game elements: + * Spells: Confusion Gaze, Vitrifying Gaze, Weakening Gaze. + * Icons: frenzied, magnetized, sentinel's mark. + * Traps: Archmage's trap, devourer's trap, tyrant's trap. + * Walls: Zot:5 stone walls. + Stone Soup 0.33.1 (20250606) ---------------------------- diff --git a/crawl-ref/source/dat/des/branches/temple.des b/crawl-ref/source/dat/des/branches/temple.des index 5401645d90..b97b594967 100644 --- a/crawl-ref/source/dat/des/branches/temple.des +++ b/crawl-ref/source/dat/des/branches/temple.des @@ -144,9 +144,9 @@ ENDMAP NAME: temple_doors_cd TAGS: transparent WEIGHT: 2 -SHUFFLE: Y'"C& / ZD~~~ +SHUFFLE: Y'"C& / yD~~~ NSUBST: XY = + / m+ -SUBST: Z = m, cCD : cxxx +SUBST: y = m, cCD : cxxx SUBST: ? : ?:40 T:30 U, ? = T:30 U, & = @ CLEAR: ~ : temple_entry(_G) diff --git a/crawl-ref/source/initfile.cc b/crawl-ref/source/initfile.cc index d849f6069d..fddfd25506 100644 --- a/crawl-ref/source/initfile.cc +++ b/crawl-ref/source/initfile.cc @@ -890,7 +890,7 @@ const vector<GameOption*> game_options::build_options_list() split_string(",", "minimap, inventory, command, " "spell, ability, monster")), new ListGameOption<string>(SIMPLE_NAME(tile_player_status_icons), - split_string(",", "slow, fragile, constr, will/2")), + split_string(",", "slow, fragile, constr, will/2, mark")), new ListGameOption<colour_remapping>(SIMPLE_NAME(custom_text_colours), {}, false), #endif #ifdef USE_TILE_LOCAL diff --git a/crawl-ref/source/rltiles/dngn/traps/archmage.png b/crawl-ref/source/rltiles/UNUSED/floor/archmage.png similarity index 100% copy from crawl-ref/source/rltiles/dngn/traps/archmage.png copy to crawl-ref/source/rltiles/UNUSED/floor/archmage.png diff --git a/crawl-ref/source/rltiles/dngn/traps/devourer.png b/crawl-ref/source/rltiles/UNUSED/floor/devourer.png similarity index 100% copy from crawl-ref/source/rltiles/dngn/traps/devourer.png copy to crawl-ref/source/rltiles/UNUSED/floor/devourer.png diff --git a/crawl-ref/source/rltiles/dngn/traps/tyrant.png b/crawl-ref/source/rltiles/UNUSED/floor/tyrant.png similarity index 100% copy from crawl-ref/source/rltiles/dngn/traps/tyrant.png copy to crawl-ref/source/rltiles/UNUSED/floor/tyrant.png diff --git a/crawl-ref/source/rltiles/dc-icons.txt b/crawl-ref/source/rltiles/dc-icons.txt index 7f5a66c24d..19ea465033 100644 --- a/crawl-ref/source/rltiles/dc-icons.txt +++ b/crawl-ref/source/rltiles/dc-icons.txt @@ -115,6 +115,7 @@ figment FIGMENT paradox PARADOX warding WARDING dim DIMMED +sentinel_mark SENTINEL_MARK something_under SOMETHING_UNDER new_stair NEW_STAIR diff --git a/crawl-ref/source/rltiles/dngn/traps/archmage.png b/crawl-ref/source/rltiles/dngn/traps/archmage.png index d60480537c..61cb4d69b8 100644 Binary files a/crawl-ref/source/rltiles/dngn/traps/archmage.png and b/crawl-ref/source/rltiles/dngn/traps/archmage.png differ diff --git a/crawl-ref/source/rltiles/dngn/traps/devourer.png b/crawl-ref/source/rltiles/dngn/traps/devourer.png index b2e8de6734..9cb298166d 100644 Binary files a/crawl-ref/source/rltiles/dngn/traps/devourer.png and b/crawl-ref/source/rltiles/dngn/traps/devourer.png differ diff --git a/crawl-ref/source/rltiles/dngn/traps/tyrant.png b/crawl-ref/source/rltiles/dngn/traps/tyrant.png index 4663f9063d..55601fbb17 100644 Binary files a/crawl-ref/source/rltiles/dngn/traps/tyrant.png and b/crawl-ref/source/rltiles/dngn/traps/tyrant.png differ diff --git a/crawl-ref/source/rltiles/effect/ostracise.png b/crawl-ref/source/rltiles/effect/ostracise.png index c3a38699a8..d8026eec45 100644 Binary files a/crawl-ref/source/rltiles/effect/ostracise.png and b/crawl-ref/source/rltiles/effect/ostracise.png differ diff --git a/crawl-ref/source/rltiles/misc/icons/regeneration.png b/crawl-ref/source/rltiles/misc/icons/sentinel_mark.png similarity index 56% copy from crawl-ref/source/rltiles/misc/icons/regeneration.png copy to crawl-ref/source/rltiles/misc/icons/sentinel_mark.png index afd9725999..f202fcc823 100644 Binary files a/crawl-ref/source/rltiles/misc/icons/regeneration.png and b/crawl-ref/source/rltiles/misc/icons/sentinel_mark.png differ diff --git a/crawl-ref/source/rltiles/mon/demons/reaper.png b/crawl-ref/source/rltiles/mon/demons/reaper.png index deca5e1384..123ca25886 100644 Binary files a/crawl-ref/source/rltiles/mon/demons/reaper.png and b/crawl-ref/source/rltiles/mon/demons/reaper.png differ diff --git a/crawl-ref/source/rltiles/mon/demons/reaper_scytheless.png b/crawl-ref/source/rltiles/mon/demons/reaper_scytheless.png index f67c4c41a8..eb6b077209 100644 Binary files a/crawl-ref/source/rltiles/mon/demons/reaper_scytheless.png and b/crawl-ref/source/rltiles/mon/demons/reaper_scytheless.png differ diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc index f84b64b03f..1e653e685b 100644 --- a/crawl-ref/source/tilepick.cc +++ b/crawl-ref/source/tilepick.cc @@ -2474,6 +2474,7 @@ static const map<duration_type, pair<tileidx_t, string>> player_status_icons = { { DUR_SLOW, {TILEI_SLOWED, "slow"} }, { DUR_VITRIFIED, {TILEI_VITRIFIED, "fragile"} }, { DUR_LOWERED_WL, {TILEI_WEAK_WILLED, "will/2"} }, + { DUR_SENTINEL_MARK, {TILEI_SENTINEL_MARK, "mark"} }, // Less critical or positive effects (or ones already covered by a default // force_more_message). Not enabled by default. @@ -2484,7 +2485,6 @@ static const map<duration_type, pair<tileidx_t, string>> player_status_icons = { { DUR_BRILLIANCE, {TILEI_BRILLIANCE, "brill"} }, { DUR_NO_MOMENTUM, {TILEI_BIND, "-move"} }, { DUR_PETRIFYING, {TILEI_PETRIFYING, "petr"} }, - { DUR_SENTINEL_MARK, {TILEI_BULLSEYE, "mark"} }, }; #ifdef USE_TILE diff --git a/crawl-ref/source/traps.cc b/crawl-ref/source/traps.cc index a8c1a72a95..8b1a2dcd0d 100644 --- a/crawl-ref/source/traps.cc +++ b/crawl-ref/source/traps.cc @@ -720,7 +720,7 @@ void trap_def::trigger(actor& triggerer) if (you_trigger) mpr("You enter a devourer's trap."); - if (x_chance_in_y(2, 3)) + if (x_chance_in_y(3, 4)) { if (!you_trigger) { @@ -729,7 +729,7 @@ void trap_def::trigger(actor& triggerer) "sets off an devourer's trap"); } flash_tile(you.pos(), YELLOW, 60, TILE_BOLT_DEFAULT_YELLOW); - you.corrode(nullptr, "The trap's stomach acid"); + you.corrode(nullptr, "The trap's stomach acid", 6); } else if (!you_trigger) mprf("%s enters a devourer's trap.", triggerer.name(DESC_THE).c_str()); diff --git a/crawl-ref/source/webserver/game_data/static/cell_renderer.js b/crawl-ref/source/webserver/game_data/static/cell_renderer.js index 3e39fead74..395fcee6b3 100644 --- a/crawl-ref/source/webserver/game_data/static/cell_renderer.js +++ b/crawl-ref/source/webserver/game_data/static/cell_renderer.js @@ -1126,6 +1126,7 @@ function ($, view_data, gui, main, tileinfo_player, icons, dngn, enums, case icons.VITRIFIED: case icons.CONFUSED: case icons.LACED_WITH_CHAOS: + case icons.SENTINEL_MARK: this.draw_icon(idx, x, y, ofsx, ofsy, img_scale); return 6; case icons.CONC_VENOM: -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 11:30:10
|
via 9a6fec6d823cfc27d24a0f0d84553c713a4e90d1 (commit) via 0396ba8ddbc24c5654335460f38e8b56c1af91fa (commit) from 4f5a5d9d27a146ba959c4bcd139d227b19bcf069 (commit) ----------------------------------------------------------------------- commit 9a6fec6d823cfc27d24a0f0d84553c713a4e90d1 Author: DracoOmega <dra...@gm...> Date: Tue Jul 8 08:55:54 2025 -0230 Don't double-note entering a Trove (regret-index) commit 0396ba8ddbc24c5654335460f38e8b56c1af91fa Author: DracoOmega <dra...@gm...> Date: Tue Jul 8 08:55:37 2025 -0230 Make notes in the log for gaining/losing banes Not exactly queryable by the bots, but might still help me get a better sense of how often (and for how long) players are encountering banes. (Also: it's probably a sufficiently noteworthy event in general.) ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/dat/dlua/lm_trove.lua | 2 +- crawl-ref/source/god-wrath.cc | 2 +- crawl-ref/source/l-you.cc | 5 ++++- crawl-ref/source/mutation.cc | 7 ++++++- crawl-ref/source/mutation.h | 2 +- crawl-ref/source/notes.cc | 16 ++++++++++++++-- crawl-ref/source/notes.h | 2 ++ crawl-ref/source/player-equip.cc | 2 +- 8 files changed, 30 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/dat/dlua/lm_trove.lua b/crawl-ref/source/dat/dlua/lm_trove.lua index 41c23f92a2..834f7b2330 100644 --- a/crawl-ref/source/dat/dlua/lm_trove.lua +++ b/crawl-ref/source/dat/dlua/lm_trove.lua @@ -655,7 +655,7 @@ function TroveMarker:accept_nopiety () end function TroveMarker:accept_bane () - you.gain_bane(get_toll(self.props).bane) + you.gain_bane(get_toll(self.props).bane, "Entering a Trove") end function TroveMarker:accept_drain () diff --git a/crawl-ref/source/god-wrath.cc b/crawl-ref/source/god-wrath.cc index 60d3861d8a..c547a1d2eb 100644 --- a/crawl-ref/source/god-wrath.cc +++ b/crawl-ref/source/god-wrath.cc @@ -1438,7 +1438,7 @@ static void _qazlal_elemental_vulnerability() you.banes[bane] += 1000; } else - add_bane(banes[random2(banes.size())]); + add_bane(banes[random2(banes.size())], "The Wrath of Qazlal"); } /** diff --git a/crawl-ref/source/l-you.cc b/crawl-ref/source/l-you.cc index c1f8fdbfa4..7767ba8257 100644 --- a/crawl-ref/source/l-you.cc +++ b/crawl-ref/source/l-you.cc @@ -1745,7 +1745,10 @@ LUAFN(you_gain_bane) string banename = luaL_checkstring(ls, 1); bane_type bane = bane_from_name(banename); if (bane != NUM_BANES) - PLUARET(boolean, add_bane(bane)); + { + string reason = luaL_checkstring(ls, 2); + PLUARET(boolean, add_bane(bane, reason)); + } string err = make_stringf("No such bane: '%s'.", banename.c_str()); return luaL_argerror(ls, 1, err.c_str()); diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index a6142dff6a..35eb5d988e 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -3401,12 +3401,13 @@ static void _init_bane_dilettante() * * @param bane The type of bane to give. If NUM_BANES, give an entirely * random bane that the player does not already have. + * @param reason The source of this bane (for note-taking) * @param duration The duration (in XP-units) this bane will last. If 0, use * the default duration for this type of bane. * * @return Whether a bane was successfully added. */ -bool add_bane(bane_type bane, int duration) +bool add_bane(bane_type bane, string reason, int duration) { if (bane == NUM_BANES) { @@ -3441,6 +3442,8 @@ bool add_bane(bane_type bane, int duration) if (bane == BANE_DILETTANTE) _init_bane_dilettante(); + take_note(Note(NOTE_GET_BANE, bane, 0, reason)); + return true; } @@ -3454,6 +3457,8 @@ void remove_bane(bane_type bane) if (bane == BANE_MORTALITY) add_daction(DACT_BANE_MORTALITY_CLEANUP); + + take_note(Note(NOTE_LOSE_BANE, bane)); } int xl_to_remove_bane(bane_type bane) diff --git a/crawl-ref/source/mutation.h b/crawl-ref/source/mutation.h index 22d7b6a419..83c905edd1 100644 --- a/crawl-ref/source/mutation.h +++ b/crawl-ref/source/mutation.h @@ -103,7 +103,7 @@ const string bane_desc(bane_type bane); const string bane_name(bane_type mut, bool dbkey = false); int bane_base_duration(bane_type bane); bane_type bane_from_name(string name); -bool add_bane(bane_type bane = NUM_BANES, int duration = 0); +bool add_bane(bane_type bane = NUM_BANES, string reason = "Doom", int duration = 0); void remove_bane(bane_type bane); int xl_to_remove_bane(bane_type bane); diff --git a/crawl-ref/source/notes.cc b/crawl-ref/source/notes.cc index af111f33b9..3582b37d04 100644 --- a/crawl-ref/source/notes.cc +++ b/crawl-ref/source/notes.cc @@ -68,7 +68,7 @@ static bool _is_noteworthy_dlevel(level_id place) return lev == _dungeon_branch_depth(branch); // These get their note in the .des files. - if (branch == BRANCH_WIZLAB) + if (branch == BRANCH_WIZLAB || branch == BRANCH_TROVE) return false; // Other portal levels are always interesting. @@ -123,7 +123,9 @@ static bool _is_noteworthy(const Note& note) || note.type == NOTE_GAIN_LIFE || note.type == NOTE_LOSE_LIFE || note.type == NOTE_FLED_CHALLENGE - || note.type == NOTE_INFERNAL_MARK) + || note.type == NOTE_INFERNAL_MARK + || note.type == NOTE_GET_BANE + || note.type == NOTE_LOSE_BANE) { return true; } @@ -336,6 +338,16 @@ string Note::describe(bool when, bool where, bool what) const if (!name.empty()) result << " [" << name << "]"; break; + case NOTE_GET_BANE: + result << "Gained bane: " + << bane_name(static_cast<bane_type>(first)); + if (!name.empty()) + result << " [" << name << "]"; + break; + case NOTE_LOSE_BANE: + result << "Lost bane: " + << bane_name(static_cast<bane_type>(first)); + break; case NOTE_DEATH: result << name; break; diff --git a/crawl-ref/source/notes.h b/crawl-ref/source/notes.h index 3c687b9bb5..b3c2af3c1b 100644 --- a/crawl-ref/source/notes.h +++ b/crawl-ref/source/notes.h @@ -70,6 +70,8 @@ enum NOTE_TYPES NOTE_FLED_CHALLENGE, NOTE_INFERNAL_MARK, /* needs: name of mark accepted (string) */ NOTE_VEXED, + NOTE_GET_BANE, /* needs: bane type, reason (string) */ + NOTE_LOSE_BANE, /* needs: bane_type */ NOTE_NUM_TYPES }; diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index 6e6ffa03d5..bedd8c875a 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -1697,7 +1697,7 @@ void equip_artefact_effect(item_def &item, bool *show_msgs, bool unmeld) { if (msg) mpr("You feel a malign power afflict you."); - add_bane(); + add_bane(NUM_BANES, "Equipping an artefact"); } if (proprt[ARTP_RAMPAGING] && msg && !unmeld -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 09:35:15
|
via 4f5a5d9d27a146ba959c4bcd139d227b19bcf069 (commit) from b9c99e84c20c0a90bf52ce57f4c917513284c342 (commit) ----------------------------------------------------------------------- commit 4f5a5d9d27a146ba959c4bcd139d227b19bcf069 Author: DracoOmega <dra...@gm...> Date: Tue Jul 8 07:01:32 2025 -0230 Fix knowledge of which orb type Zot gets being lost on reload (Dhd) I'd actually forgotten to write marshalling code for it. Whoops! ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/tag-version.h | 1 + crawl-ref/source/tags.cc | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/crawl-ref/source/tag-version.h b/crawl-ref/source/tag-version.h index 8faca1a0c3..629de33b6e 100644 --- a/crawl-ref/source/tag-version.h +++ b/crawl-ref/source/tag-version.h @@ -329,6 +329,7 @@ enum tag_minor_version TAG_MINOR_CONTAM_PERCENT, // Rescale internal values for magic contamination TAG_MINOR_ZOT_ORB_ROTATION, // Add multiple rotating orb monster types to Zot TAG_MINOR_GHOST_TITLE, // Store ghost titles instead of generating them + TAG_MINOR_ZOT_ORB_MEMORY, // Fix whether the player has learned the Zot orb type not being saved #endif NUM_TAG_MINORS, TAG_MINOR_VERSION = NUM_TAG_MINORS - 1 diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index f0f0af1e63..9bf96ac2d3 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -2101,6 +2101,7 @@ static void _tag_construct_you_dungeon(writer &th) write_level_connectivity(th); marshallMonType(th, you.zot_orb_monster); + marshallBoolean(th, you.zot_orb_monster_known); } static void marshall_follower(writer &th, const follower &f) @@ -5314,6 +5315,13 @@ static void _tag_read_you_dungeon(reader &th) else #endif you.zot_orb_monster = unmarshallMonType(th); + +#if TAG_MAJOR_VERSION == 34 + if (th.getMinorVersion() < TAG_MINOR_ZOT_ORB_MEMORY) + you.zot_orb_monster_known = false; + else +#endif + you.zot_orb_monster_known = unmarshallBoolean(th); } static void _tag_read_lost_monsters(reader &th) -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 03:35:15
|
via b9c99e84c20c0a90bf52ce57f4c917513284c342 (commit) via 826fe50d78a1dbc03aa9e0dbc39f8fd3a81ea09f (commit) from 747caa52fdb131d5585626dbc4a8c6708146f6c8 (commit) ----------------------------------------------------------------------- commit b9c99e84c20c0a90bf52ce57f4c917513284c342 Author: Jared Miller <jared@smell.flowers> Date: Mon Jul 7 23:30:35 2025 -0400 Handle ?-key spell description from cast menu (#4586) This change adds `[?] help` to the cast menu, similar to the memorization menu. commit 826fe50d78a1dbc03aa9e0dbc39f8fd3a81ea09f Author: WizardIke <ik...@ya...> Date: Tue Jul 8 15:30:13 2025 +1200 Fix resizing the console while in a menu on windows (#4506) Responding to console resize events in menus was disabled in 9746042 as the way we were handling them lead to generating another resize event resulting in an infinite loop. However, this results in the menu becoming fairly unreadable until you exit it and go back in. With a slight adjustment we can use the normal resize handling code in menus as well which doesn't have this problem. ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/cio.h | 1 - crawl-ref/source/libconsole.h | 1 - crawl-ref/source/libunix.cc | 15 ++------------- crawl-ref/source/libw32c.cc | 15 ++------------- crawl-ref/source/macro.cc | 1 - crawl-ref/source/menu.cc | 1 - crawl-ref/source/spl-cast.cc | 24 +++++++++++++++++++++--- crawl-ref/source/state.cc | 1 + crawl-ref/source/state.h | 1 + crawl-ref/source/ui.cc | 29 ++++++++++------------------- crawl-ref/source/view.cc | 14 ++++++++++++-- 11 files changed, 49 insertions(+), 54 deletions(-) diff --git a/crawl-ref/source/cio.h b/crawl-ref/source/cio.h index 436d0ccfbf..f368ff2918 100644 --- a/crawl-ref/source/cio.h +++ b/crawl-ref/source/cio.h @@ -308,7 +308,6 @@ enum KEYS CK_MOUSE_CLICK, CK_TOUCH_DUMMY, // so a non-event can be passed from handle_mouse to the controlling code CK_REDRAW, // no-op to force redraws of things - CK_RESIZE, CK_NO_KEY, // so that the handle_mouse loop can be broken from early (for // popups), and otherwise for keys to ignore diff --git a/crawl-ref/source/libconsole.h b/crawl-ref/source/libconsole.h index dbfcff26e1..17f38a6b12 100644 --- a/crawl-ref/source/libconsole.h +++ b/crawl-ref/source/libconsole.h @@ -31,7 +31,6 @@ void cprintf(const char *format, ...); int wherex(); int wherey(); void putwch(char32_t c); -void set_getch_returns_resizes(bool rr); int getch_ck(); bool kbhit(); void delay(unsigned int ms); diff --git a/crawl-ref/source/libunix.cc b/crawl-ref/source/libunix.cc index 72a34b8729..f1f4d688ba 100644 --- a/crawl-ref/source/libunix.cc +++ b/crawl-ref/source/libunix.cc @@ -550,19 +550,13 @@ static int _get_key_from_curses() static void unix_handle_resize_event() { crawl_state.last_winch = time(0); - if (crawl_state.waiting_for_command) + if (crawl_state.waiting_for_command || crawl_state.waiting_for_ui) handle_terminal_resize(); else crawl_state.terminal_resized = true; } #endif -static bool getch_returns_resizes; -void set_getch_returns_resizes(bool rr) -{ - getch_returns_resizes = rr; -} - static int _headless_getchk() { #ifdef WATCHDOG @@ -642,8 +636,7 @@ int getch_ck() // then scroll down one line. To fix this, we always sync termsz: crawl_view.init_geometry(); - if (!getch_returns_resizes) - continue; + continue; } #endif @@ -688,10 +681,6 @@ int getch_ck() case KEY_C1: return CK_NUMPAD_1; case KEY_C3: return CK_NUMPAD_3; -#ifdef KEY_RESIZE - case KEY_RESIZE: return CK_RESIZE; -#endif - // Undocumented ncurses control keycodes, here be dragons!!! case 515: return CK_CTRL_DELETE; // Mac case 526: return CK_CTRL_DELETE; // Linux diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index 9a37f0b693..0ee95ca22f 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -323,16 +323,12 @@ static void set_w32_screen_size() } screen = new CHAR_INFO[screensize.X * screensize.Y]; - - COORD topleft; - SMALL_RECT used; - topleft.X = topleft.Y = 0; - ::ReadConsoleOutputW(outbuf, screen, screensize, topleft, &used); + clrscr_sys(); } static void w32_handle_resize_event() { - if (crawl_state.waiting_for_command) + if (crawl_state.waiting_for_command || crawl_state.waiting_for_ui) handle_terminal_resize(); else crawl_state.terminal_resized = true; @@ -854,13 +850,6 @@ static int w32_proc_mouse_event(const MOUSE_EVENT_RECORD &mer) return 0; } - -void set_getch_returns_resizes(bool rr) -{ - UNUSED(rr); - // no-op on windows console: see mantis issue #11532 -} - int getch_ck() { INPUT_RECORD ir; diff --git a/crawl-ref/source/macro.cc b/crawl-ref/source/macro.cc index 435dcc6aa5..bef98e02b0 100644 --- a/crawl-ref/source/macro.cc +++ b/crawl-ref/source/macro.cc @@ -2045,7 +2045,6 @@ bool is_synthetic_key(int key) case CK_MOUSE_CMD: case CK_MOUSE_MOVE: case CK_REDRAW: - case CK_RESIZE: return true; default: return false; diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 218773cca7..d2a5d95cca 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -2030,7 +2030,6 @@ bool Menu::process_key(int keyin) { case CK_NO_KEY: case CK_REDRAW: - case CK_RESIZE: return true; case 0: return true; diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index 114dba15d7..d69c06db53 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -213,13 +213,30 @@ public: | MF_NO_WRAP_ROWS | MF_ALLOW_FORMATTING | MF_ARROWS_SELECT | MF_INIT_HOVER) {} protected: - bool process_command(command_type c) override + command_type get_command(int keyin) override { + if (keyin == '?') + return CMD_MENU_HELP; + return ToggleableMenu::get_command(keyin); + } + + bool process_command(command_type cmd) override + { + if (cmd == CMD_MENU_HELP) + { + int idx = last_hovered; + if (idx >= 0 && idx < static_cast<int>(items.size())) + { + examine_index(idx); + return true; + } + } + get_selected(&sel); // if there's a preselected item, and no current selection, select it. // for arrow selection, the hover starts on the preselected item so no // special handling is needed. - if (menu_action == ACT_EXECUTE && c == CMD_MENU_SELECT + if (menu_action == ACT_EXECUTE && cmd == CMD_MENU_SELECT && !(flags & MF_ARROWS_SELECT) && sel.empty()) { for (size_t i = 0; i < items.size(); ++i) @@ -231,7 +248,7 @@ protected: } } } - return ToggleableMenu::process_command(c); + return ToggleableMenu::process_command(cmd); } bool examine_index(int i) override @@ -274,6 +291,7 @@ int list_spells(bool toggle_with_I, bool transient, bool viewing, string more_str = make_stringf("<lightgrey>Select a spell to %s</lightgrey>", real_action.c_str()); + more_str = pad_more_with_esc(more_str + " [<w>?</w>] help"); string toggle_desc = menu_keyhelp_cmd(CMD_MENU_CYCLE_MODE); if (toggle_with_I) { diff --git a/crawl-ref/source/state.cc b/crawl-ref/source/state.cc index ee266502de..cc508f7405 100644 --- a/crawl-ref/source/state.cc +++ b/crawl-ref/source/state.cc @@ -28,6 +28,7 @@ game_state::game_state() : game_crashed(false), crash_debug_scans_safe(true), mouse_enabled(false), waiting_for_command(false), + waiting_for_ui(false), terminal_resized(false), last_winch(0), seed(0), io_inited(false), diff --git a/crawl-ref/source/state.h b/crawl-ref/source/state.h index 7626e02c58..88d361c6be 100644 --- a/crawl-ref/source/state.h +++ b/crawl-ref/source/state.h @@ -45,6 +45,7 @@ struct game_state bool mouse_enabled; // True if mouse input is currently relevant. bool waiting_for_command; // True when the game is waiting for a command. + bool waiting_for_ui; // True when waiting for input from the ui overlay bool terminal_resized; // True if the term was resized and we need to // take action to handle it. time_t last_winch; // Time of last resize, for crash dumps. diff --git a/crawl-ref/source/ui.cc b/crawl-ref/source/ui.cc index 1552edcb05..02483582c5 100644 --- a/crawl-ref/source/ui.cc +++ b/crawl-ref/source/ui.cc @@ -3290,28 +3290,19 @@ void pump_events(int wait_event_timeout) #else if (wait_event_timeout <= 0) // resizing probably breaks this case return; - set_getch_returns_resizes(true); - int k = macro_key != -1 ? macro_key : getch_ck(); - set_getch_returns_resizes(false); - if (k == CK_RESIZE) + int k; { - // This may be superfluous, since the resize handler may have already - // resized the screen - clrscr(); - console_shutdown(); - console_startup(); - ui_root.resize(get_number_of_cols(), get_number_of_lines()); - } - else - { - wm_event ev = {0}; - ev.type = WME_KEYDOWN; - ev.key.keysym.sym = k; - if (macro_key == -1) - remap_key(ev); - ui_root.on_event(ev); + unwind_bool safe_resize(crawl_state.waiting_for_ui, true); + k = macro_key != -1 ? macro_key : getch_ck(); } + + wm_event ev = {0}; + ev.type = WME_KEYDOWN; + ev.key.keysym.sym = k; + if (macro_key == -1) + remap_key(ev); + ui_root.on_event(ev); #endif } diff --git a/crawl-ref/source/view.cc b/crawl-ref/source/view.cc index a9a9eef84b..6ce6546092 100644 --- a/crawl-ref/source/view.cc +++ b/crawl-ref/source/view.cc @@ -77,6 +77,7 @@ #include "transform.h" #include "traps.h" #include "travel.h" +#include "ui.h" #include "unicode.h" #include "unwind.h" #include "viewchar.h" @@ -1966,6 +1967,15 @@ void handle_terminal_resize() else crawl_view.init_geometry(); - redraw_screen(); - update_screen(); + if (crawl_state.waiting_for_ui) + { + ui::resize(crawl_view.termsz.x, crawl_view.termsz.y); + // We always need a redraw as the console was cleared when resizing + ui::force_render(); + } + else + { + redraw_screen(); + update_screen(); + } } -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 03:30:15
|
via 747caa52fdb131d5585626dbc4a8c6708146f6c8 (commit) from 6ecf20f4ee650c88a32fdb5cb242fac581635053 (commit) ----------------------------------------------------------------------- commit 747caa52fdb131d5585626dbc4a8c6708146f6c8 Author: WizardIke <ik...@ya...> Date: Tue Jul 8 15:30:01 2025 +1200 Fix clear_to_end_of_line for windows console builds (#4504) It isn't meant to change the cursor position. However, it was changing it which meant we had to disable some asserts on windows in b0d7ede ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/libconsole.h | 2 -- crawl-ref/source/libutil.cc | 6 +----- crawl-ref/source/libw32c.cc | 4 +++- crawl-ref/source/mutation.cc | 4 ++++ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crawl-ref/source/libconsole.h b/crawl-ref/source/libconsole.h index e1acdadb2e..dbfcff26e1 100644 --- a/crawl-ref/source/libconsole.h +++ b/crawl-ref/source/libconsole.h @@ -62,10 +62,8 @@ struct save_cursor_pos save_cursor_pos() : region(get_cursor_region()), pos(cgetpos(region)) { -#ifndef TARGET_OS_WINDOWS ASSERTM(valid_cursor_pos(pos.x, pos.y, region), "invalid cursor position %d,%d in region %d", pos.x, pos.y, region); -#endif }; ~save_cursor_pos() { diff --git a/crawl-ref/source/libutil.cc b/crawl-ref/source/libutil.cc index 4fcdbed427..5cb28791d0 100644 --- a/crawl-ref/source/libutil.cc +++ b/crawl-ref/source/libutil.cc @@ -380,7 +380,6 @@ bool valid_cursor_pos(int x, int y, GotoRegion region) return x >= 1 && y >= 1 && x <= sz.x && y <= sz.y; } -#ifndef TARGET_OS_WINDOWS static GotoRegion _find_correct_region() { for (int r = GOTO_MSG; r < GOTO_MLIST; r++) @@ -394,25 +393,22 @@ static GotoRegion _find_correct_region() // should probably fail for entirely invalid coords somehow return GOTO_CRT; } -#endif void assert_valid_cursor_pos() { -#ifndef TARGET_OS_WINDOWS GotoRegion region(get_cursor_region()); coord_def pos(cgetpos(region)); ASSERTM(valid_cursor_pos(pos.x, pos.y, region), "invalid cursor position %d,%d in region %d, should be %d,%d in region %d", pos.x, pos.y, region, cgetpos(_find_correct_region()).x, cgetpos(_find_correct_region()).y, _find_correct_region()); -#endif } static GotoRegion _current_region = GOTO_CRT; void cgotoxy(int x, int y, GotoRegion region) { -#if defined(ASSERTS) && !defined(TARGET_OS_WINDOWS) +#if defined(ASSERTS) if (!valid_cursor_pos(x, y, region)) { const coord_def sz = cgetsize(region); diff --git a/crawl-ref/source/libw32c.cc b/crawl-ref/source/libw32c.cc index c4e2b6fea8..9a37f0b693 100644 --- a/crawl-ref/source/libw32c.cc +++ b/crawl-ref/source/libw32c.cc @@ -488,9 +488,11 @@ void set_cursor_enabled(bool curstype) gotoxy_sys(cx+1, cy+1); } -// This will force the cursor down to the next line. void clear_to_end_of_line() { + // We shouldn't move cursor pos + save_cursor_pos save; + const int pos = wherex(); const int cols = get_number_of_cols(); if (pos <= cols) diff --git a/crawl-ref/source/mutation.cc b/crawl-ref/source/mutation.cc index 4dbe1a61c5..a6142dff6a 100644 --- a/crawl-ref/source/mutation.cc +++ b/crawl-ref/source/mutation.cc @@ -943,8 +943,12 @@ string terse_mutation_list() string describe_mutations(bool drop_title) { #ifdef DEBUG +#ifndef USE_TILE_LOCAL + validate_mutations(!crawl_state.smallterm); +#else validate_mutations(true); #endif +#endif string result; if (!drop_title) -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 03:25:09
|
via 6ecf20f4ee650c88a32fdb5cb242fac581635053 (commit) from d528656974bfe6f1009bb390b27139a71b5d63c2 (commit) ----------------------------------------------------------------------- commit 6ecf20f4ee650c88a32fdb5cb242fac581635053 Author: RypoFalem <ryp...@gm...> Date: Mon Jul 7 22:23:56 2025 -0500 update options guide documentation (#4640) of force_spell_targeter and force_ability_targeter defaults. ----------------------------------------------------------------------- Summary of changes: crawl-ref/docs/options_guide.txt | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/crawl-ref/docs/options_guide.txt b/crawl-ref/docs/options_guide.txt index d87e12187f..6908a59ffb 100644 --- a/crawl-ref/docs/options_guide.txt +++ b/crawl-ref/docs/options_guide.txt @@ -1162,9 +1162,11 @@ simple_targeting = false zapping as well as autotarget selection for quivered spells. force_spell_targeter = hailstorm, starburst, frozen ramparts, ignition, - eringya's noxious bog, cause fear, alistair's + eringya's noxious bog, anguish, cause fear, alistair's intoxication, discord, dispersal, metabolic englaciation, - dazzling flash, flame wave, anguish, plasma beam + gloom, flame wave, plasma beam, + maxwell's portable piledriver, diamond sawblades, + fortress blast Force showing a targeter for the listed spells when casting normally, even if the spell isn't targeted. This for practical purposes only has an effect on statically targeted spells, such as the ones in the @@ -1174,9 +1176,10 @@ force_spell_targeter = hailstorm, starburst, frozen ramparts, ignition, be shown with every spell. force_ability_targeter = sanctuary, cleansing flame, word of chaos, recite, - elemental force, oozemancy, breathe lightning, torment, - drain life, slouch, disaster area, apocalypse, - corrupt, foxfire swarm + elemental force, oozemancy, galvanic breath, + fathomless shackles, slouch, disaster area, apocalypse, + corrupt, foxfire swarm, siphon essence, shadowslip, + watery grave Force showing a targeter for the listed abilities when activating them normally, even if the ability isn't targeted. This for practical purposes only has an effect on statically targeted abilities, such as -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 03:15:09
|
via d2f241eafa7d39c7415aadfa053c96878903eda6 (commit) from d2946b48681c32b47cf8a1489cb629540d6bd994 (commit) ----------------------------------------------------------------------- commit d2f241eafa7d39c7415aadfa053c96878903eda6 Author: hellmonk <nld...@gm...> Date: Mon Jul 7 22:12:39 2025 -0500 incredible tile work ----------------------------------------------------------------------- Summary of changes: .../source/rltiles/item/armour/brands/i-deflection.png | Bin 0 -> 319 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 crawl-ref/source/rltiles/item/armour/brands/i-deflection.png diff --git a/crawl-ref/source/rltiles/item/armour/brands/i-deflection.png b/crawl-ref/source/rltiles/item/armour/brands/i-deflection.png new file mode 100644 index 0000000000..0ec8c620b7 Binary files /dev/null and b/crawl-ref/source/rltiles/item/armour/brands/i-deflection.png differ -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 03:10:14
|
via d2946b48681c32b47cf8a1489cb629540d6bd994 (commit) from 0f9b07d5f1b243982e24dc39b52033680adbac01 (commit) ----------------------------------------------------------------------- commit d2946b48681c32b47cf8a1489cb629540d6bd994 Author: hellmonk <nld...@gm...> Date: Mon Jul 7 22:06:27 2025 -0500 Gloves of deflection The anti-acrobat, they provide SH bonus if the last action was a melee attack. This bonus is halved if your offhand is occupied by a non-weapon item. I would like to call this "parrying" ego, but would need to rename coglin revparry. (People keep asking for two handers to have innate SH, which seems like bad design, but there may be space for a limited availability ego in that idea). ----------------------------------------------------------------------- Summary of changes: crawl-ref/source/describe.cc | 4 ++++ crawl-ref/source/duration-data.h | 6 ++++++ crawl-ref/source/duration-type.h | 1 + crawl-ref/source/fight.cc | 3 +++ crawl-ref/source/item-name.cc | 2 ++ crawl-ref/source/item-prop-enum.h | 1 + crawl-ref/source/item-prop.cc | 1 + crawl-ref/source/makeitem.cc | 1 + crawl-ref/source/mapdef.cc | 1 + crawl-ref/source/output.cc | 3 ++- crawl-ref/source/player-equip.cc | 5 +++++ crawl-ref/source/player-equip.h | 1 + crawl-ref/source/player.cc | 28 ++++++++++++++++++++++++++++ crawl-ref/source/player.h | 3 +++ crawl-ref/source/rltiles/dc-item.txt | 3 ++- crawl-ref/source/shopping.cc | 1 + crawl-ref/source/tileweb.cc | 7 +++++++ 17 files changed, 69 insertions(+), 2 deletions(-) diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index db574cea69..536a88db2d 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -2377,6 +2377,10 @@ static const char* _item_ego_desc(special_armour_type ego) return "it improves the success rate of the wearer's forgecraft spells " " and enhances their melee attacks proportionally to forgecraft " " skill"; + case SPARM_DEFLECTION: + return "It shields the wearer if their last action was a melee attack. " + "The shielding is half as effective if the wielder's offhand is " + "occupied by an item other than their weapon."; default: return "it makes the wearer crave the taste of eggplant."; } diff --git a/crawl-ref/source/duration-data.h b/crawl-ref/source/duration-data.h index 9d1bded502..32a1e63ac7 100644 --- a/crawl-ref/source/duration-data.h +++ b/crawl-ref/source/duration-data.h @@ -728,6 +728,12 @@ static const duration_def duration_data[] = "Your melee attacks are strengthened by primal bloodlust.", D_EXPIRES, {{ "Your bloodlust subsides." }, { "You feel your bloodlust ebbing." }}, 6}, + { DUR_DEFLECTION, 0, "", + "deflection", "deflecting", + "You are deflecting attacks and have increased SH.", D_NO_FLAGS, + {{ "", []() { + you.redraw_armour_class = true; + }}}}, // The following are visible in wizmode only, or are handled // specially in the status lights and/or the % or @ screens. diff --git a/crawl-ref/source/duration-type.h b/crawl-ref/source/duration-type.h index b6f8311033..d5eadfe6cf 100644 --- a/crawl-ref/source/duration-type.h +++ b/crawl-ref/source/duration-type.h @@ -291,5 +291,6 @@ enum duration_type DUR_HIVE_COOLDOWN, DUR_WEREFURY, DUR_MEDUSA_COOLDOWN, + DUR_DEFLECTION, NUM_DURATIONS }; diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc index 607fa615e1..c4c9f97fa7 100644 --- a/crawl-ref/source/fight.cc +++ b/crawl-ref/source/fight.cc @@ -636,6 +636,9 @@ void do_player_post_attack(actor *defender, bool was_firewood, bool simu) if (you.form == transformation::medusa) _do_medusa_stinger(); + + if (!was_firewood) + update_deflection_status(); } /** diff --git a/crawl-ref/source/item-name.cc b/crawl-ref/source/item-name.cc index ea98578a82..305bc67717 100644 --- a/crawl-ref/source/item-name.cc +++ b/crawl-ref/source/item-name.cc @@ -579,6 +579,7 @@ const char* special_armour_type_name(special_armour_type ego, bool terse) case SPARM_COMMAND: return "command"; case SPARM_DEATH: return "death"; case SPARM_RESONANCE: return "resonance"; + case SPARM_DEFLECTION: return "deflection"; default: return "bugginess"; } } @@ -635,6 +636,7 @@ const char* special_armour_type_name(special_armour_type ego, bool terse) case SPARM_COMMAND: return "command"; case SPARM_DEATH: return "death"; case SPARM_RESONANCE: return "resonance"; + case SPARM_DEFLECTION: return "deflection"; default: return "buggy"; } } diff --git a/crawl-ref/source/item-prop-enum.h b/crawl-ref/source/item-prop-enum.h index 20e99706cc..ad1e67da45 100644 --- a/crawl-ref/source/item-prop-enum.h +++ b/crawl-ref/source/item-prop-enum.h @@ -531,6 +531,7 @@ enum special_armour_type SPARM_COMMAND, SPARM_DEATH, SPARM_RESONANCE, + SPARM_DEFLECTION, NUM_REAL_SPECIAL_ARMOURS, NUM_SPECIAL_ARMOURS, }; diff --git a/crawl-ref/source/item-prop.cc b/crawl-ref/source/item-prop.cc index abe9a5c26e..ee60252ea7 100644 --- a/crawl-ref/source/item-prop.cc +++ b/crawl-ref/source/item-prop.cc @@ -195,6 +195,7 @@ static const armour_def Armour_prop[] = SLOT_GLOVES, SIZE_SMALL, SIZE_MEDIUM, true, 0, { { SPARM_DEXTERITY, 1 }, { SPARM_STRENGTH, 1 }, + { SPARM_DEFLECTION,1 }, { SPARM_HURLING, 1 }, { SPARM_STEALTH, 1 }, { SPARM_INFUSION, 1 }, diff --git a/crawl-ref/source/makeitem.cc b/crawl-ref/source/makeitem.cc index cfd9388877..791c62c686 100644 --- a/crawl-ref/source/makeitem.cc +++ b/crawl-ref/source/makeitem.cc @@ -811,6 +811,7 @@ bool is_armour_brand_ok(int type, int brand, bool strict) // deliberate fall-through case SPARM_HURLING: case SPARM_FIRE: + case SPARM_DEFLECTION: return slot == SLOT_GLOVES; case SPARM_SEE_INVISIBLE: diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc index c579871db2..5e58e59c03 100644 --- a/crawl-ref/source/mapdef.cc +++ b/crawl-ref/source/mapdef.cc @@ -4992,6 +4992,7 @@ int str_to_ego(object_class_type item_type, string ego_str) "command", "death", "resonance", + "deflection", nullptr }; COMPILE_CHECK(ARRAYSZ(armour_egos) == NUM_REAL_SPECIAL_ARMOURS); diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc index 065b1ddea7..cf8bd96690 100644 --- a/crawl-ref/source/output.cc +++ b/crawl-ref/source/output.cc @@ -637,7 +637,8 @@ static bool _boosted_sh() || (you.get_mutation_level(MUT_EPHEMERAL_SHIELD) && you.duration[DUR_EPHEMERAL_SHIELD]) || (you.get_mutation_level(MUT_CONDENSATION_SHIELD) - && !you.duration[DUR_ICEMAIL_DEPLETED]); + && !you.duration[DUR_ICEMAIL_DEPLETED]) + || you.duration[DUR_DEFLECTION]; } #ifdef DGL_SIMPLE_MESSAGING diff --git a/crawl-ref/source/player-equip.cc b/crawl-ref/source/player-equip.cc index c34496a71c..6617501232 100644 --- a/crawl-ref/source/player-equip.cc +++ b/crawl-ref/source/player-equip.cc @@ -2455,6 +2455,11 @@ bool acrobat_boost_active() && (!you.is_constricted()); } +bool deflection_boost_active() +{ + return player_deflection() && you.duration[DUR_DEFLECTION]; +} + static void _equip_amulet_of_reflection() { you.redraw_armour_class = true; diff --git a/crawl-ref/source/player-equip.h b/crawl-ref/source/player-equip.h index 16425f503a..68bc808938 100644 --- a/crawl-ref/source/player-equip.h +++ b/crawl-ref/source/player-equip.h @@ -144,5 +144,6 @@ void equip_artefact_effect(item_def &item, bool *show_msgs, bool unmeld); void unequip_artefact_effect(item_def &item, bool *show_msgs, bool meld); bool acrobat_boost_active(); +bool deflection_boost_active(); void unwield_distortion(bool brand = false); diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index ccb0d02e14..c47ff792c8 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -1825,6 +1825,30 @@ void update_acrobat_status() you.redraw_evasion = true; } +int player_deflection() +{ + int sh = 8 * you.wearing_ego(OBJ_ARMOUR, SPARM_DEFLECTION); + if (you.get_mutation_level(MUT_MISSING_HAND)) + sh /= 2; + else + { + item_def* item = you.equipment.get_first_slot_item(SLOT_OFFHAND); + if (item && item->base_type != OBJ_WEAPONS) + sh /= 2; + } + + return sh; +} + +void update_deflection_status() +{ + if (player_deflection() <= 0) + return; + + you.duration[DUR_DEFLECTION] = you.time_taken+1; + you.redraw_armour_class = true; +} + // An evasion factor based on the player's body size, smaller == higher // evasion size factor. static int _player_evasion_size_factor(bool base = false) @@ -2124,6 +2148,9 @@ int player_shield_class(int scale, bool random, bool ignore_temporary) shield += you.wearing_jewellery(AMU_REFLECTION) * AMU_REFLECT_SH * 100; shield += you.scan_artefacts(ARTP_SHIELDING) * 200; + if (you.duration[DUR_DEFLECTION]) + shield += player_deflection() * 200; + return random ? div_rand_round(shield * scale, 100) : ((shield * scale) / 100); } @@ -5875,6 +5902,7 @@ bool player::shielded() const return shield() || duration[DUR_DIVINE_SHIELD] || duration[DUR_EPHEMERAL_SHIELD] + || duration[DUR_DEFLECTION] || get_mutation_level(MUT_LARGE_BONE_PLATES) > 0 || qazlal_sh_boost() > 0 || you.wearing_jewellery(AMU_REFLECTION) diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 53941f3e8c..8b7503ed8d 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -1013,6 +1013,9 @@ bool player_can_hear(const coord_def& p, int hear_distance = 999); void update_acrobat_status(); bool player_acrobatic(); +int player_deflection(); +void update_deflection_status(); + bool is_effectively_light_armour(const item_def *item); bool player_effectively_in_light_armour(); diff --git a/crawl-ref/source/rltiles/dc-item.txt b/crawl-ref/source/rltiles/dc-item.txt index f7362dccb3..87053bda51 100644 --- a/crawl-ref/source/rltiles/dc-item.txt +++ b/crawl-ref/source/rltiles/dc-item.txt @@ -595,7 +595,8 @@ i-earth BRAND_ARM_EARTH i-archery BRAND_ARM_ARCHERY i-command BRAND_ARM_COMMAND i-death BRAND_ARM_DEATH -i-resonance BRAND_ARM_RESONANCE BRAND_ARM_LAST +i-resonance BRAND_ARM_RESONANCE +i-deflection BRAND_ARM_DEFLECTION BRAND_ARM_LAST %rim 1 ###########OBJ_WANDS diff --git a/crawl-ref/source/shopping.cc b/crawl-ref/source/shopping.cc index c877a00be5..8ff2e62ea0 100644 --- a/crawl-ref/source/shopping.cc +++ b/crawl-ref/source/shopping.cc @@ -390,6 +390,7 @@ unsigned int item_value(item_def item, bool ident) case SPARM_INFUSION: case SPARM_LIGHT: case SPARM_ENERGY: + case SPARM_DEFLECTION: valued += 50; break; diff --git a/crawl-ref/source/tileweb.cc b/crawl-ref/source/tileweb.cc index 1b6e19d95a..c47feb408d 100644 --- a/crawl-ref/source/tileweb.cc +++ b/crawl-ref/source/tileweb.cc @@ -1006,6 +1006,13 @@ static bool _update_statuses(player_info& c) continue; inf.short_text = "acrobatic"; } + else if (status == DUR_DEFLECTION) + { + inf = status_info(); + if (!deflection_boost_active()) + continue; + inf.short_text = "deflecting"; + } else if (!fill_status_info(status, inf)) // this will reset inf itself continue; -- Dungeon Crawl Stone Soup |
From: <gi...@cr...> - 2025-07-08 02:30:15
|
via d528656974bfe6f1009bb390b27139a71b5d63c2 (commit) from 87ee97bf79e4f45ab42af9477cfd38f99c844ade (commit) ----------------------------------------------------------------------- commit d528656974bfe6f1009bb390b27139a71b5d63c2 Author: David Lawrence Ramsey <poo...@gm...> Date: Mon Jul 7 21:14:14 2025 -0500 Fix missing pixel on inert gravitambourine tile. ----------------------------------------------------------------------- Summary of changes: .../rltiles/item/misc/misc_tambourine_inert.png | Bin 1165 -> 1147 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/crawl-ref/source/rltiles/item/misc/misc_tambourine_inert.png b/crawl-ref/source/rltiles/item/misc/misc_tambourine_inert.png index aa3e4522e3..8da1ddaa33 100644 Binary files a/crawl-ref/source/rltiles/item/misc/misc_tambourine_inert.png and b/crawl-ref/source/rltiles/item/misc/misc_tambourine_inert.png differ -- Dungeon Crawl Stone Soup |