From 5eec26059dd2f85b8099ee8c5498593a72421385 Mon Sep 17 00:00:00 2001 From: Procyonae <45432782+Procyonae@users.noreply.github.com> Date: Sun, 15 Dec 2024 21:54:34 +0000 Subject: [PATCH] Add more functionality to the json messages, remove hardcoded special tags DRAW_NOTE_COLORS is redundant, it already shows when adding a map note HELP_DRAW_DIRECTIONS can be done in json instead now --- data/core/help.json | 48 ++++++++++----- doc/HELP_MENU.md | 1 + src/help.cpp | 143 ++++++++++++++++++++++---------------------- src/help.h | 9 ++- src/options.cpp | 4 +- 5 files changed, 113 insertions(+), 92 deletions(-) diff --git a/data/core/help.json b/data/core/help.json index 10af37f5ceacf..6c18863717742 100644 --- a/data/core/help.json +++ b/data/core/help.json @@ -15,8 +15,25 @@ "order": 1, "name": "Movement", "messages": [ - "Movement is performed using the numpad, the arrow keys, or vikeys.", - "", + "Movement is typically performed using the numpad, vikeys, the mouse or arrow keys. Here are the layouts for numpad and vikeys, where the central bind is to wait in place:", + { + "force_monospaced": "7 8 9 y k u\n \\|/ \\|/ \n4-5-6 h-.-l\n /|\\ /|\\ \n1 2 3 b j n\n" + }, + "Movement is also possible using the arrow keys by first enabling the \"Diagonal movement with cursor keys and modifiers\" setting in the Interface tab to one of these four modes:", + "- Numpad Emulation: In this mode you hold Ctrl throughout, first pressing a direction which will then modify further key presses to be in altered by that direction, for example if you first press Up, then further Left, Up, Right and Down presses will become NW, N, NE, and wait respectively.", + { + "force_monospaced": " After Up After Right\n N NE\n NW O NE O SE E\n" + }, + "- CW/CCW: In this mode holding Shift modifies each key 45 degrees clockwise while holding Ctrl modifies each key 45 degrees counter-clockwise.", + { + "force_monospaced": " With Shift With Ctrl\n NE NW\n NW SW SE SW SE NE\n" + }, + "- L/R Tilt: In this mode holding Shift/Ctrl makes Left and Right behave as NW/SW and NE/SE respectively. Up and Down behave normally regardless of modifiers.", + { + "force_monospaced": " With Shift With Ctrl\n N NW\n NW S NE SW S SE\n" + }, + "- Diagonal Lock: In this mode holding Shift or Ctrl results in only diagonal combinations of two directions being accepted for example Ctrl + Up + Right becomes NE.", + { "seperator": "color_green" }, "Each step will take 100 movement points (or more, depending on the terrain); you will then replenish a variable amount of movement points, depending on many factors (press to see the exact amount).", "To attempt to hit a monster with your weapon, simply move into it.", "You may find doors, ('+'); these may be opened with or closed with . Some doors are locked. Locked doors, windows, and some other obstacles can be destroyed by smashing them (, then choose a direction). Smashing down obstacles is much easier with a good weapon or a strong character.", @@ -276,18 +293,23 @@ { "type": "help", "order": 19, - "name": "Description of map symbols", + "name": "Overmap key", "messages": [ - "MAP SYMBOLS:", + "OVERMAP SYMBOLS:", ". Field - Empty grassland with occasional wild fruit.", + ", Meadow - .", "F Forest - May be dense or sparse. Movement will be slowed. You might be able to forage for food here.", - "│─└┌┐┘├┴┤┬┼ Road - Safe from burrowing animals.", - "H= Highway - Like roads, but lined with guard rails.", - "|- Bridge - Helps you cross rivers.", - "R River - Most creatures cannot swim across them, but you can.", - "O Parking lot - Empty lot, few items. Mostly useless.", - "^>v< House - Filled with a variety of items. Good place to sleep.", - "^>v< Gas station - A good place to collect gasoline. Risk of explosion.", + "│─└┌┐┘├┴┤┬┼ Forest Trail - A path through the forest. Faster and more open than walking through the forest proper. Consider breaking line of sight through the forest if anything does catch up with you.", + "T Trailhead - The start of a trail. If you're lucky you'll find a map and maybe even a working vehicle here.", + "F Freshwater Swamp - .", + "│─└┌┐┘├┴┤┬┼ Road - Safe from burrowing animals.", + ">-< Roadbridge - Helps you cross rivers.", + ". Stream - A small body of water that you can drive over.", + "RR River - Most creatures cannot swim across them, but you can.", + "## Lake/Ocean - .", + "X Radio Tower - A tall tower useful for getting a good view of the surrounding area. Beware any fauna that may have made its home here.", + "^>v< House - Come in many forms. Good place to find basic supplies and everyday tools.", + "^>v< Gas station - A good place to collect gasoline.", "^>v< Pharmacy - The best source for vital medications.", "^>v< Grocery store - A good source of canned food and other supplies.", "^>v< Hardware store - Home to tools, melee weapons and crafting goods.", @@ -296,9 +318,7 @@ "^>v< Gun store - Firearms and ammunition are very valuable.", "^>v< Clothing store - High-capacity clothing, some light armor.", "^>v< Library - Home to books, both entertaining and informative.", - "^>v< Man-made buildings - The pointed side indicates the front door.", - " There are many others out there… search for them!", - "" + "^>v< Man-made buildings - The pointed side indicates the front door." ] }, { diff --git a/doc/HELP_MENU.md b/doc/HELP_MENU.md index bcc4a51d09dcf..89cb4e4c73b4d 100644 --- a/doc/HELP_MENU.md +++ b/doc/HELP_MENU.md @@ -1,3 +1,4 @@ +BEFOREMERGE Update # Help Menu The help menu consists of scrollable categorised help pages that would ideally explain everything a new survivor needs to know, as well as any information the game can't convey clearly in an immersive way. diff --git a/src/help.cpp b/src/help.cpp index 26db2b27fa626..901e5173d6223 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -49,6 +49,13 @@ void help::reset_instance() read_categories.clear(); } +enum message_modifier { + MM_NORMAL = 0, // Normal message + MM_SUBTITLE, // Formatted subtitle + MM_MONOFONT, // Forced monofont for fixed space diagrams + MM_SEPERATOR // ImGui seperator, value is the color to use +}; + void help::load_object( const JsonObject &jo, const std::string &src ) { if( src == "dda" ) { @@ -59,60 +66,32 @@ void help::load_object( const JsonObject &jo, const std::string &src ) current_order_start = help_categories.empty() ? 0 : help_categories.crbegin()->first + 1; current_src = src; } + help_category category; - jo.read( "messages", category.paragraphs ); translation name; jo.read( "name", category.name ); - const int modified_order = jo.get_int( "order" ) + current_order_start; - if( !help_categories.try_emplace( modified_order, category ).second ) { - jo.throw_error_at( "order", "\"order\" must be unique per source" ); - } -} -std::string help_window::get_dir_grid() -{ - static const std::array movearray = {{ - ACTION_MOVE_FORTH_LEFT, ACTION_MOVE_FORTH, ACTION_MOVE_FORTH_RIGHT, - ACTION_MOVE_LEFT, ACTION_PAUSE, ACTION_MOVE_RIGHT, - ACTION_MOVE_BACK_LEFT, ACTION_MOVE_BACK, ACTION_MOVE_BACK_RIGHT - } - }; - - std::string movement = " \n" - " \\ | / \\ | /\n" - " \\|/ \\|/\n" - "---- ----\n" - " /|\\ /|\\\n" - " / | \\ / | \\\n" - " "; - - for( action_id dir : movearray ) { - std::vector keys = keys_bound_to( dir, /*maximum_modifier_count=*/0 ); - for( size_t i = 0; i < 2; i++ ) { - movement = string_replace( movement, "<" + action_ident( dir ) + string_format( "_%d>", i ), - i < keys.size() - ? string_format( "%s", - keys[i].short_description() ) - : "?" ); + for( JsonValue jv : jo.get_array( "messages" ) ) { + if( jv.test_string() ) { + category.paragraphs.emplace_back( to_translation( jv.get_string() ), MM_NORMAL ); + } else { + JsonObject jobj = jv.get_object(); + if( jobj.has_string( "subtitle" ) ) { + category.paragraphs.emplace_back( to_translation( jobj.get_string( "subtitle" ) ), MM_SUBTITLE ); + } else if( jobj.has_string( "force_monospaced" ) ) { + category.paragraphs.emplace_back( to_translation( jobj.get_string( "force_monospaced" ) ), + MM_MONOFONT ); + } else if( jobj.has_string( "seperator" ) ) { + category.paragraphs.emplace_back( no_translation( jobj.get_string( "seperator" ) ), MM_SEPERATOR ); + } } } - return movement; -} -void help_window::note_colors() -{ - ImGui::TextUnformatted( _( "Note colors: " ) ); - ImGui::SameLine( 0.f, 0.f ); - for( const auto &color_pair : get_note_color_names() ) { - // The color index is not translatable, but the name is. - //~ %1$s: note color abbreviation, %2$s: note color name - cataimgui::TextColoredParagraph( c_white, string_format( pgettext( "note color", "%1$s:%2$s, " ), - colorize( color_pair.first, color_pair.second.color ), - color_pair.second.name ) ); - // TODO: Has a stray comma at the end - ImGui::SameLine( 0.f, 0.f ); + const int modified_order = jo.get_int( "order" ) + current_order_start; + if( !help_categories.try_emplace( modified_order, category ).second ) { + jo.throw_error_at( "order", "\"order\" must be unique per source" ); } } @@ -193,6 +172,10 @@ void help_window::draw_category_option( const int &option, const help_category & } cat_name += category.name.translated(); if( data.read_categories.find( option ) != data.read_categories.end() ) { + if( screen_reader ) { + //~ Prefix for options that has already been viewed when using a screen reader + cat_name = _( "(read) " ) + cat_name; + } ImGui::PushStyleColor( ImGuiCol_Text, c_light_gray ); ImGui::Selectable( remove_color_tags( cat_name ).c_str() ); ImGui::PopStyleColor(); @@ -206,7 +189,7 @@ void help_window::draw_category_option( const int &option, const help_category & void help_window::format_title( const std::string translated_category_name ) { - if( get_option( "SCREEN_READER_MODE" ) ) { + if( screen_reader ) { cataimgui::TextColoredParagraph( c_white, translated_category_name ); ImGui::NewLine(); return; @@ -300,16 +283,37 @@ void help_window::draw_category() cataimgui::set_scroll( s ); ImGui::TableNextRow(); ImGui::TableNextColumn(); - for( const std::string &translated_paragraph : translated_paragraphs ) { - if( translated_paragraph == "" ) { - note_colors(); - continue; - } else if( translated_paragraph == "" ) { - static const std::string dir_grid = get_dir_grid(); - cataimgui::draw_colored_text( dir_grid, wrap_width ); - continue; + for( const std::pair &translated_paragraph : + translated_paragraphs ) { + switch( translated_paragraph.second ) { + case MM_NORMAL: + cataimgui::TextColoredParagraph( c_white, translated_paragraph.first ); + break; + case MM_SUBTITLE: + // BEFOREMERGE: Do something different + cataimgui::TextColoredParagraph( c_white, translated_paragraph.first ); + break; + case MM_MONOFONT: + cataimgui::PushMonoFont(); + cataimgui::TextColoredParagraph( c_white, translated_paragraph.first ); + ImGui::PopFont(); + break; + // Causing a missing EndChild() ImGui crash? + //case MM_SEPERATOR: { + // nc_color col = get_all_colors().name_to_color( translated_paragraph.first ); + // ImGui::PushStyleColor( ImGuiCol_Separator, cataimgui::imvec4_from_color( col ) ); + // ImGui::Separator(); + // ImGui::PopStyleColor(); + // break; + //} + // Temporary until crash is worked out + case MM_SEPERATOR: + ImGui::Separator(); + break; + default: + debugmsg( "Unexpected help message modifier" ); + continue; } - cataimgui::TextColoredParagraph( c_white, translated_paragraph ); ImGui::NewLine(); ImGui::NewLine(); } @@ -317,31 +321,26 @@ void help_window::draw_category() } } -// Would ideally be merged with parse_tags()? -void help_window::parse_tags_help_window() +// Would ideally share parse_tags() code for keybinds +void help_window::parse_keybind_tags() { - for( std::string &translated_paragraph : translated_paragraphs ) { - if( translated_paragraph == "" ) { - continue; - } else if( translated_paragraph == "" ) { - continue; - } - size_t pos = translated_paragraph.find( " &translated_paragraph : translated_paragraphs ) { + std::string &text = translated_paragraph.first; + size_t pos = text.find( "", pos, 1 ); + size_t pos2 = text.find( ">", pos, 1 ); - std::string action = translated_paragraph.substr( pos + 7, pos2 - pos - 7 ); + std::string action = text.substr( pos + 7, pos2 - pos - 7 ); std::string replace = "" + press_x( look_up_action( action ), "", "" ) + ""; if( replace.empty() ) { debugmsg( "Help json: Unknown action: %s", action ); } else { - translated_paragraph = string_replace( translated_paragraph, "", - replace ); + text = string_replace( text, "", replace ); } - pos = translated_paragraph.find( " ¶graph : cat.paragraphs ) { + translated_paragraphs.emplace_back( paragraph.first.translated(), paragraph.second ); } - parse_tags_help_window(); + parse_keybind_tags(); } std::string get_hint() diff --git a/src/help.h b/src/help.h index b1563914d9588..bf5a5de260e41 100644 --- a/src/help.h +++ b/src/help.h @@ -24,7 +24,7 @@ class window; struct help_category { translation name; - std::vector paragraphs; + std::vector> paragraphs; }; class help @@ -60,6 +60,7 @@ class help_window : public cataimgui::window float window_height = static_cast( str_width_to_pixels( TERMY ) ); float wrap_width = window_width * 0.95f; cataimgui::bounds bounds{ 0.f, 0.f, static_cast( str_width_to_pixels( TERMX ) ), static_cast( str_height_to_pixels( TERMY ) ) }; + const bool screen_reader = get_option( "SCREEN_READER_MODE" ); // 66 is optimal characters per line for reading? //float window_width = static_cast( wrap_width ) * 2.025f; @@ -80,12 +81,10 @@ class help_window : public cataimgui::window int loaded_option; void swap_translated_paragraphs(); - std::vector translated_paragraphs; - void parse_tags_help_window(); + std::vector> translated_paragraphs; + void parse_keybind_tags(); void draw_category(); - void note_colors(); - std::string get_dir_grid(); cataimgui::scroll s; }; diff --git a/src/options.cpp b/src/options.cpp index 012932f23050b..39c9580f71f34 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -2029,7 +2029,9 @@ void options_manager::add_options_interface() * Example 3: Press → while holding Shift and ← results in input rejection */ - to_translation( "Allows diagonal movement with cursor keys using CTRL and SHIFT modifiers. Diagonal movement action keys are taken from keybindings, so you need these to be configured." ), { { "none", to_translation( "None" ) }, { "mode1", to_translation( "Mode 1: Numpad Emulation" ) }, { "mode2", to_translation( "Mode 2: CW/CCW" ) }, { "mode3", to_translation( "Mode 3: L/R Tilt" ) }, { "mode4", to_translation( "Mode 4: Diagonal Lock" ) } }, + // BEFOREMERGE: Check if this works with curses + to_translation( "Allows diagonal movement with cursor keys using CTRL and SHIFT modifiers. Diagonal movement action keys are taken from keybindings, so you need these to be configured. See the movement category in the help menu for full descriptions of the options." ), + { { "none", to_translation( "None" ) }, { "mode1", to_translation( "Mode 1: Numpad Emulation" ) }, { "mode2", to_translation( "Mode 2: CW/CCW" ) }, { "mode3", to_translation( "Mode 3: L/R Tilt" ) }, { "mode4", to_translation( "Mode 4: Diagonal Lock" ) } }, "none", COPT_CURSES_HIDE ); add_empty_line();