From 6e43d5ac56c4e1f81506a5fae92f60ef67a734c8 Mon Sep 17 00:00:00 2001 From: RenechCDDA <84619419+RenechCDDA@users.noreply.github.com> Date: Sat, 8 Jun 2024 19:54:06 -0400 Subject: [PATCH] ...Move settings around between your followers. Why not --- src/npctalk_rules.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++ src/npctalk_rules.h | 1 + 2 files changed, 208 insertions(+) diff --git a/src/npctalk_rules.cpp b/src/npctalk_rules.cpp index 94b5b196e05b3..0e4f31ea128ff 100644 --- a/src/npctalk_rules.cpp +++ b/src/npctalk_rules.cpp @@ -16,9 +16,11 @@ #include "cata_imgui.h" #include "dialogue.h" +#include "game.h" #include "npctalk.h" #include "ui_manager.h" #include "imgui/imgui.h" +#include "imgui/imgui_internal.h" static std::map<cbm_recharge_rule, std::string> recharge_map = { {cbm_recharge_rule::CBM_RECHARGE_ALL, "<ally_rule_cbm_recharge_all_text>" }, @@ -121,6 +123,193 @@ void follower_rules_ui_impl::print_hotkey( input_event &hotkey ) ImGui::SameLine(); } +void follower_rules_ui_impl::rules_transfer_popup( bool &exporting_rules, bool &still_in_popup ) +{ + std::string toggle_label; + if( exporting_rules ) { + draw_colored_text( string_format( _( "Exporting rules from <color_white>%s</color>" ), + guy->disp_name() ), c_blue ); + //~Label for a button used to copy NPC follower rules to another NPC + toggle_label = _( "Export" ); + } else { + draw_colored_text( string_format( _( "Importing rules to <color_white>%s</color>" ), + guy->disp_name() ), c_yellow ); + //~Label for a button used to copy NPC follower rules from another NPC + toggle_label = _( "Import" ); + } + // Not ideal but leaves plenty of room for even verbose languages. Really anywhere top-right-ish is fine + ImGui::SameLine( ImGui::GetWindowWidth() * 0.7 ); + if( ImGui::Button( _( "Return to rules settings" ) ) ) { + still_in_popup = false; + return; + } + if( ImGui::Button( _( "Toggle export/import" ) ) ) { + exporting_rules = !exporting_rules; + } + ImGui::NewLine(); + draw_colored_text( string_format( + _( "Individual settings are colored if they already match to %s." ), + guy->disp_name() ) ); + if( ImGui::BeginTable( "##SETTINGS_SWAP_TABLE", 8, ImGuiTableFlags_None, + ImVec2( window_width, window_height ) ) ) { + // Missions selection is purposefully thinner than the description, it has less to convey. + ImGui::TableSetupColumn( _( "Name" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "Behaviors" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "Aiming" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "Engagement" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "CBM recharge" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "CBM reserve" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "Pickup list" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableSetupColumn( _( "ALL" ), ImGuiTableColumnFlags_WidthStretch, + window_width / 8 ); + ImGui::TableHeadersRow(); + int button_number = 0; + for( npc &role_model : g->all_npcs() ) { + if( &role_model == guy ) { + continue; // No copying settings to/from yourself + } + if( role_model.is_player_ally() ) { + bool do_flags_overrides = false; + bool do_aim = false; + bool do_engagement = false; + bool do_cbm_recharge = false; + bool do_cbm_reserve = false; + bool do_pickup = false; + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + draw_colored_text( role_model.disp_name() ); + /*Flags and overrides*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.flags == guy->rules.flags ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_flags_overrides = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*Aim rule*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.aim == guy->rules.aim ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_aim = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*Engagement rule*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.engagement == guy->rules.engagement ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_engagement = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*CBM recharge rule*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.cbm_recharge == guy->rules.cbm_recharge ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_cbm_recharge = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*CBM reserve rule*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.cbm_reserve == guy->rules.cbm_reserve ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_cbm_reserve = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*Pickup whitelist rule*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + // This is not correct if both have rules and both have *different* rules, but comparison is expensive + if( role_model.rules.pickup_whitelist->empty() == guy->rules.pickup_whitelist->empty() ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_pickup = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*The ALL button*/ + ImGui::TableNextColumn(); + ImGui::PushID( button_number ); + button_number++; + if( role_model.rules.flags == guy->rules.flags && + role_model.rules.aim == guy->rules.aim && + role_model.rules.engagement == guy->rules.engagement && + role_model.rules.cbm_recharge == guy->rules.cbm_recharge && + role_model.rules.cbm_reserve == guy->rules.cbm_reserve && + role_model.rules.pickup_whitelist->empty() == guy->rules.pickup_whitelist->empty() ) { + ImGui::PushStyleColor( ImGuiCol_Button, c_green ); + } + if( ImGui::Button( toggle_label.c_str() ) ) { + do_flags_overrides = true; + do_aim = true; + do_engagement = true; + do_cbm_recharge = true; + do_cbm_reserve = true; + do_pickup = true; + } + ImGui::PopID(); + ImGui::PopStyleColor(); + /*The great swap*/ + // To make this slightly easier... + npc *guy_with_same = exporting_rules ? guy : &role_model; + npc *guy_with_new = exporting_rules ? &role_model : guy; + if( do_flags_overrides ) { + guy_with_new->rules.flags = guy_with_same->rules.flags; + guy_with_new->rules.overrides = guy_with_same->rules.overrides; + guy_with_new->rules.override_enable = guy_with_same->rules.override_enable; + } + if( do_aim ) { + guy_with_new->rules.aim = guy_with_same->rules.aim; + } + if( do_engagement ) { + guy_with_new->rules.engagement = guy_with_same->rules.engagement; + } + if( do_cbm_recharge ) { + guy_with_new->rules.cbm_recharge = guy_with_same->rules.cbm_recharge; + } + if( do_cbm_reserve ) { + guy_with_new->rules.cbm_reserve = guy_with_same->rules.cbm_reserve; + } + if( do_pickup ) { + guy_with_new->rules.pickup_whitelist = guy_with_same->rules.pickup_whitelist; + } + } + } + ImGui::EndTable(); + } +} + void follower_rules_ui_impl::draw_controls() { if( !guy ) { @@ -131,6 +320,13 @@ void follower_rules_ui_impl::draw_controls() ImGui::SetWindowSize( ImVec2( window_width, window_height ), ImGuiCond_Once ); + static bool exporting_rules = false; + static bool in_popup = false; + if( in_popup ) { + rules_transfer_popup( exporting_rules, in_popup ); + return; + } + ImGui::InvisibleButton( "TOP_OF_WINDOW_KB_SCROLL_SELECTABLE", ImVec2() ); const hotkey_queue &hotkeys = hotkey_queue::alphabets(); @@ -142,6 +338,17 @@ void follower_rules_ui_impl::draw_controls() draw_colored_text( _( "Hotkey:" ) ); ImGui::NewLine(); + if( ImGui::Button( _( "Import settings from follower" ) ) ) { + exporting_rules = false; + in_popup = true; + return; + } + if( ImGui::Button( _( "Export settings to follower" ) ) ) { + exporting_rules = true; + in_popup = true; + return; + } + print_hotkey( assigned_hotkey ); if( ImGui::Button( _( "Default ALL" ) ) || pressed_key == assigned_hotkey ) { ImGui::SetKeyboardFocusHere( -1 ); diff --git a/src/npctalk_rules.h b/src/npctalk_rules.h index 43f2a00ef446a..841ab7144a38d 100644 --- a/src/npctalk_rules.h +++ b/src/npctalk_rules.h @@ -44,6 +44,7 @@ class follower_rules_ui_impl : public cataimgui::window npc *guy = nullptr; std::string get_parsed( std::string initial_string ); void print_hotkey( input_event &hotkey ); + void rules_transfer_popup( bool &exporting_rules, bool &still_in_popup ); size_t window_width = str_width_to_pixels( TERMX ) / 2; size_t window_height = str_height_to_pixels( TERMY ) / 2;