Skip to content

Commit

Permalink
Prevent selected NPC jumping to the top in training session menus (#5…
Browse files Browse the repository at this point in the history
  • Loading branch information
haveric authored Feb 21, 2022
1 parent 552323c commit 90f84f4
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 69 deletions.
40 changes: 1 addition & 39 deletions src/npctalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,44 +349,6 @@ static int npc_select_menu( const std::vector<npc *> &npc_list, const std::strin

}

static std::vector<int> npcs_select_menu( const std::vector<npc *> &npc_list,
const std::string &prompt,
std::function<bool( const npc * )> exclude_func = nullptr )
{
std::vector<int> picked;
if( npc_list.empty() ) {
return picked;
}
const int npc_count = npc_list.size();
do {
uilist nmenu;
nmenu.text = prompt;
for( int i = 0; i < npc_count; i++ ) {
std::string entry;
if( std::find( picked.begin(), picked.end(), i ) != picked.end() ) {
entry = "* ";
}
bool enable = exclude_func == nullptr || !exclude_func( npc_list[i] );
entry += npc_list[i]->name_and_activity();
nmenu.addentry( i, enable, MENU_AUTOASSIGN, entry );
}
nmenu.addentry( npc_count, true, MENU_AUTOASSIGN, _( "Finish selection" ) );
nmenu.query();
if( nmenu.ret < 0 ) {
return std::vector<int>();
} else if( nmenu.ret >= npc_count ) {
break;
}
std::vector<int>::iterator exists = std::find( picked.begin(), picked.end(), nmenu.ret );
if( exists != picked.end() ) {
picked.erase( exists );
} else {
picked.push_back( nmenu.ret );
}
} while( true );
return picked;
}

static skill_id skill_select_menu( const Character &c, const std::string &prompt )
{
int i = 0;
Expand Down Expand Up @@ -713,7 +675,7 @@ void game::chat()
if( !sk.is_valid() ) {
return;
}
std::vector<int> selected = npcs_select_menu( followers,
std::vector<int> selected = npcs_select_menu<npc>( followers,
_( "Who should participate in the training seminar?" ), [&]( const npc * n ) {
return !n || n->get_knowledge_level( sk ) >= player_character.get_skill_level( sk );
} );
Expand Down
48 changes: 47 additions & 1 deletion src/npctalk.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#ifndef CATA_SRC_NPCTALK_H
#define CATA_SRC_NPCTALK_H

#include "npc.h"
#include "type_id.h"
#include "character.h"

class item;
class json_talk_topic;
Expand Down Expand Up @@ -137,4 +137,50 @@ int calc_spell_training_cost( const Character &teacher, const Character &student

const json_talk_topic *get_talk_topic( const std::string &id );

template<class T>
std::vector<int> npcs_select_menu( const std::vector<T *> &npc_list,
const std::string &prompt,
std::function<bool( const T * )> exclude_func )
{
std::vector<int> picked;
if( npc_list.empty() ) {
return picked;
}
const int npc_count = npc_list.size();
int last_index = 0;
do {
uilist nmenu;
nmenu.text = prompt;
for( int i = 0; i < npc_count; i++ ) {
std::string entry;
if( std::find( picked.begin(), picked.end(), i ) != picked.end() ) {
entry = "* ";
}
bool enable = exclude_func == nullptr || !exclude_func( npc_list[i] );
if( const npc *np = dynamic_cast<const npc *>( npc_list[i] ) ) {
entry += np->name_and_activity();
} else {
entry += npc_list[i]->disp_name( false, true );
}
nmenu.addentry( i, enable, MENU_AUTOASSIGN, entry );
}
nmenu.addentry( npc_count, true, MENU_AUTOASSIGN, _( "Finish selection" ) );
nmenu.selected = nmenu.fselected = last_index;
nmenu.query();
if( nmenu.ret < 0 ) {
return std::vector<int>();
} else if( nmenu.ret >= npc_count ) {
break;
}
std::vector<int>::iterator exists = std::find( picked.begin(), picked.end(), nmenu.ret );
if( exists != picked.end() ) {
picked.erase( exists );
} else {
picked.push_back( nmenu.ret );
}
last_index = nmenu.fselected;
} while( true );
return picked;
}

#endif // CATA_SRC_NPCTALK_H
38 changes: 9 additions & 29 deletions src/npctalk_funcs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,6 @@ void talk_function::start_training_seminar( npc &p )
}
students.push_back( &get_player_character() );

const int s_count = students.size();
std::vector<Character *> picked;
std::function<bool( const Character * )> include_func = [&]( const Character * c ) {
if( d.skill != skill_id() ) {
Expand All @@ -1062,37 +1061,18 @@ void talk_function::start_training_seminar( npc &p )
}
return false;
};
do {
uilist nmenu;
nmenu.text = _( "Who should participate?" );
for( int i = 0; i < s_count; i++ ) {
std::string entry;
if( std::find( picked.begin(), picked.end(), students[i] ) != picked.end() ) {
entry = "* ";
}
bool enable = include_func( students[i] );
entry += students[i]->disp_name( false, true );
nmenu.addentry( i, enable, MENU_AUTOASSIGN, entry );
}
nmenu.addentry( s_count, true, MENU_AUTOASSIGN, _( "Finish selection" ) );
nmenu.query();
if( nmenu.ret < 0 ) {
return;
} else if( nmenu.ret >= s_count ) {
break;
}
std::vector<Character *>::iterator exists = std::find( picked.begin(), picked.end(),
students[nmenu.ret] );
if( exists != picked.end() ) {
picked.erase( exists );
} else {
picked.emplace_back( students[nmenu.ret] );
}
} while( true );
std::vector<int> selected = npcs_select_menu<Character>( students, _( "Who should participate?" ),
[&include_func]( const Character * ch ) {
return !include_func( ch );
} );

if( picked.empty() ) {
if( selected.empty() ) {
return;
}
picked.reserve( selected.size() );
for( int sel : selected ) {
picked.emplace_back( students[sel] );
}
start_training_gen( p, picked, d );
}

Expand Down

0 comments on commit 90f84f4

Please sign in to comment.