From 5b86c7106109b605e6b36dcf69c80d7c2a94e3eb Mon Sep 17 00:00:00 2001 From: LISPCoC Date: Tue, 24 Oct 2023 21:37:50 +0900 Subject: [PATCH] Add favorite category to spell casting menu & minor bugfix (#68833) * add favorite * Update data/raw/keybindings.json Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * clang fix --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- data/raw/keybindings.json | 11 ++++++++ src/magic.cpp | 58 ++++++++++++++++++++++++++++++++++++--- src/magic.h | 5 ++++ src/ui.cpp | 12 +++----- 4 files changed, 74 insertions(+), 12 deletions(-) diff --git a/data/raw/keybindings.json b/data/raw/keybindings.json index 2097b497e1ded..c99518dd433dd 100644 --- a/data/raw/keybindings.json +++ b/data/raw/keybindings.json @@ -303,6 +303,17 @@ "name": "Scroll down spell info", "bindings": [ { "input_method": "keyboard_char", "key": ">" }, { "input_method": "keyboard_code", "key": ".", "mod": [ "shift" ] } ] }, + { + "type": "keybinding", + "id": "SCROLL_FAVORITE", + "category": "SPELL_MENU", + "name": "Toggle spell as favorite", + "bindings": [ + { "input_method": "keyboard_char", "key": "*" }, + { "input_method": "keyboard_code", "key": "KEYPAD_MULTIPLY" }, + { "input_method": "keyboard_code", "key": "8", "mod": [ "shift" ] } + ] + }, { "type": "keybinding", "id": "ADD_RULE", diff --git a/src/magic.cpp b/src/magic.cpp index b618825f7411e..a4bcee7260a92 100644 --- a/src/magic.cpp +++ b/src/magic.cpp @@ -1827,6 +1827,7 @@ void known_magic::serialize( JsonOut &json ) const } json.end_array(); json.member( "invlets", invlets ); + json.member( "favorites", favorites ); json.end_object(); } @@ -1846,6 +1847,7 @@ void known_magic::deserialize( const JsonObject &data ) } } data.read( "invlets", invlets ); + data.read( "favorites", favorites ); } bool known_magic::knows_spell( const std::string &sp ) const @@ -2156,6 +2158,19 @@ std::vector Character::spells_known_of_class( const trait_id &spell_class return ret; } +static void reflesh_favorite( uilist *menu, std::vector known_spells ) +{ + for( uilist_entry &entry : menu->entries ) { + if( get_player_character().magic->is_favorite( known_spells[entry.retval]->id() ) ) { + entry.extratxt.left = 0; + entry.extratxt.txt = _( "*" ); + entry.extratxt.color = c_white; + } else { + entry.extratxt.txt = ""; + } + } +} + class spellcasting_callback : public uilist_callback { private: @@ -2167,14 +2182,14 @@ class spellcasting_callback : public uilist_callback void draw_spell_info( const uilist *menu ); public: // invlets reserved for special functions - const std::set reserved_invlets{ 'I', '=' }; + const std::set reserved_invlets{ 'I', '=', '*' }; bool casting_ignore; spellcasting_callback( std::vector &spells, bool casting_ignore ) : known_spells( spells ), casting_ignore( casting_ignore ) {} bool key( const input_context &ctxt, const input_event &event, int entnum, - uilist * /*menu*/ ) override { + uilist *menu ) override { const std::string &action = ctxt.input_to_action( event ); if( action == "CAST_IGNORE" ) { casting_ignore = !casting_ignore; @@ -2198,6 +2213,9 @@ class spellcasting_callback : public uilist_callback return true; } else if( action == "SCROLL_UP_SPELL_MENU" || action == "SCROLL_DOWN_SPELL_MENU" ) { scroll_pos += action == "SCROLL_DOWN_SPELL_MENU" ? 1 : -1; + } else if( action == "SCROLL_FAVORITE" ) { + get_player_character().magic->toggle_favorite( known_spells[entnum]->id() ); + reflesh_favorite( menu, known_spells ); } return false; } @@ -2522,6 +2540,20 @@ void known_magic::rem_invlet( const spell_id &sp ) invlets.erase( sp ); } +void known_magic::toggle_favorite( const spell_id &sp ) +{ + if( favorites.count( sp ) > 0 ) { + favorites.erase( sp ); + } else { + favorites.emplace( sp ); + } +} + +bool known_magic::is_favorite( const spell_id &sp ) +{ + return favorites.count( sp ) > 0; +} + int known_magic::get_invlet( const spell_id &sp, std::set &used_invlets ) { auto found = invlets.find( sp ); @@ -2575,20 +2607,37 @@ int known_magic::select_spell( Character &guy ) spell_menu.additional_actions.emplace_back( "CAST_IGNORE", translation() ); spell_menu.additional_actions.emplace_back( "SCROLL_UP_SPELL_MENU", translation() ); spell_menu.additional_actions.emplace_back( "SCROLL_DOWN_SPELL_MENU", translation() ); + spell_menu.additional_actions.emplace_back( "SCROLL_FAVORITE", translation() ); spell_menu.hilight_disabled = true; spellcasting_callback cb( known_spells, casting_ignore ); spell_menu.callback = &cb; spell_menu.add_category( "all", _( "All" ) ); + spell_menu.add_category( "favorites", _( "Favorites" ) ); + + std::vector> categories; for( const spell *s : known_spells ) { if( s->can_cast( guy ) && s->spell_class().is_valid() ) { - spell_menu.add_category( s->spell_class().str(), s->spell_class().obj().name() ); + categories.emplace_back( s->spell_class().str(), s->spell_class().obj().name() ); + std::sort( categories.begin(), categories.end(), []( const std::pair &a, + const std::pair &b ) { + return localized_compare( a.second, b.second ); + } ); + const auto itr = std::unique( categories.begin(), categories.end() ); + categories.erase( itr, categories.end() ); } } - spell_menu.set_category_filter( [known_spells]( const uilist_entry & entry, + for( std::pair &cat : categories ) { + spell_menu.add_category( cat.first, cat.second ); + } + + spell_menu.set_category_filter( [&guy, known_spells]( const uilist_entry & entry, const std::string & key )->bool { if( key == "all" ) { return true; + } else if( key == "favorites" ) + { + return guy.magic->is_favorite( known_spells[entry.retval]->id() ); } return known_spells[entry.retval]->spell_class().is_valid() && known_spells[entry.retval]->spell_class().str() == key; } ); @@ -2600,6 +2649,7 @@ int known_magic::select_spell( Character &guy ) spell_menu.addentry( static_cast( i ), known_spells[i]->can_cast( guy ), get_invlet( known_spells[i]->id(), used_invlets ), known_spells[i]->name() ); } + reflesh_favorite( &spell_menu, known_spells ); spell_menu.query(); diff --git a/src/magic.h b/src/magic.h index 787e49fd3d5d2..63043df2a3696 100644 --- a/src/magic.h +++ b/src/magic.h @@ -629,6 +629,8 @@ class known_magic std::map spellbook; // invlets assigned to spell_id std::map invlets; + // list of favorite spells + std::unordered_set favorites; // the base mana a Character would start with int mana_base = 0; // NOLINT(cata-serialize) // current mana @@ -697,6 +699,9 @@ class known_magic // returns false if invlet is already used bool set_invlet( const spell_id &sp, int invlet, const std::set &used_invlets ); void rem_invlet( const spell_id &sp ); + + void toggle_favorite( const spell_id &sp ); + bool is_favorite( const spell_id &sp ); private: // gets length of longest spell name int get_spellname_max_width(); diff --git a/src/ui.cpp b/src/ui.cpp index 801c67e2cdd65..b901cde3aefd7 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -325,8 +325,10 @@ input_context uilist::create_main_input_context() const ctxt.register_action( "SELECT" ); } ctxt.register_action( "UILIST.FILTER" ); - ctxt.register_action( "UILIST.LEFT" ); - ctxt.register_action( "UILIST.RIGHT" ); + if( !categories.empty() ) { + ctxt.register_action( "UILIST.LEFT" ); + ctxt.register_action( "UILIST.RIGHT" ); + } ctxt.register_action( "ANY_INPUT" ); ctxt.register_action( "HELP_KEYBINDINGS" ); uilist_scrollbar->set_draggable( ctxt ); @@ -1267,12 +1269,6 @@ void uilist::set_selected( int index ) void uilist::add_category( const std::string &key, const std::string &name ) { categories.emplace_back( key, name ); - std::sort( categories.begin(), categories.end(), []( const std::pair &a, - const std::pair &b ) { - return localized_compare( a.second, b.second ); - } ); - const auto itr = std::unique( categories.begin(), categories.end() ); - categories.erase( itr, categories.end() ); } void uilist::set_category( const std::string &key )