Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign upSafemode UI #17916
Conversation
This comment has been minimized.
This comment has been minimized.
|
One possible addition would be to allow ignoring specific monsters from the interruption prompt? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
The message that interrupts long activities (especially crafting) |
This comment has been minimized.
This comment has been minimized.
|
@OzoneH3 could possible be implemented via the critter tracker? |
OzoneH3
added some commits
Aug 2, 2016
OzoneH3
force-pushed the
OzoneH3:safemode_ui
branch
to
db5fc7d
Aug 5, 2016
OzoneH3
changed the title
[WiP][CR] Safemode UI
Safemode UI
Aug 5, 2016
This comment has been minimized.
This comment has been minimized.
|
I'll try to figure out the long activity interrution in another PR. It's not really related with the ui. |
Coolthulhu
reviewed
Aug 5, 2016
| @@ -1710,6 +1862,7 @@ | |||
| { "type":"keybinding", "name": "Control Vehicle", "category":"DEFAULTMODE", "id":"control_vehicle", "bindings":[ { "input_method":"keyboard", "key":"^" } ] }, | |||
| { "type":"keybinding", "name": "Toggle Safemode", "category":"DEFAULTMODE", "id":"safemode", "bindings":[ { "input_method":"keyboard", "key":"!" } ] }, | |||
| { "type":"keybinding", "name": "Ignore Nearby Enemy", "category":"DEFAULTMODE", "id":"ignore_enemy", "bindings":[ { "input_method":"keyboard", "key":"'" } ] }, | |||
| { "type":"keybinding", "name": "Whitelist enemy", "category":"DEFAULTMODE", "id":"whitelist_enemy", "bindings":[ { "input_method":"keyboard", "key":"~" } ] }, | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
OzoneH3
Aug 5, 2016
Author
Member
Why? You can still ignore enemys without whitelisting them forever.
Coolthulhu
reviewed
Aug 5, 2016
| @@ -1542,3 +1542,23 @@ void Creature::check_dead_state() { | |||
| die( nullptr ); | |||
| } | |||
| } | |||
|
|
|||
| std::pair<std::string, nc_color> const &Creature::get_creature_attitude( Attitude att ) | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
This name is very misleading. Should be something like attitude_name or attitude_ui_data.
Coolthulhu
reviewed
Aug 5, 2016
| @@ -11556,14 +11623,21 @@ bool game::check_safe_mode_allowed( bool repeat_safe_mode_warnings ) | |||
| if( new_seen_mon.empty() ) { | |||
| // naming consistent with code in game::mon_info | |||
| spotted_creature_name = _( "a hostile survivor" ); | |||
| get_safemode().whitelist = "human"; | |||
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
Would be useful if you could also trigger it on neutral survivors. They can become hostile, steal stuff etc.
Coolthulhu
reviewed
Aug 5, 2016
| const int iContentHeight = FULL_SCREEN_HEIGHT - 2 - iHeaderHeight; | ||
|
|
||
| const int iOffsetX = ( TERMX > FULL_SCREEN_WIDTH ) ? ( TERMX - FULL_SCREEN_WIDTH ) / 2 : 0; | ||
| const int iOffsetY = ( TERMY > FULL_SCREEN_HEIGHT ) ? ( TERMY - FULL_SCREEN_HEIGHT ) / 2 : 0; |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
Are you copy+pasting the UI from somewhere?
It would be a good idea to clean it up. For example, make it cover the whole screen instead of just the middle.
This comment has been minimized.
This comment has been minimized.
OzoneH3
Aug 5, 2016
Author
Member
It's a copy of the autopickup ui. Shouldn't it stay in line with the other option menus?
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
Both should cover the whole screen eventually. It doesn't need to be in this PR, though.
This comment has been minimized.
This comment has been minimized.
OzoneH3
Aug 5, 2016
Author
Member
Well, all 4 of these are copies: options -> autopickup -> color manager -> safmode
Do they really need to fill the whole screen though?
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
They don't need to, but it can be useful when there are many entries. Options and color manager could sure use it, I don't use autopickup except for NPCs so I don't know how big should it be.
Coolthulhu
reviewed
Aug 5, 2016
| ( iLine == i && iColumn == col_IE ) ? hilite( cLineColor ) : cLineColor, | ||
| "%s", ( ( vRules[iTab][i].bExclude ) ? rm_prefix( _( "Exclude" ) ).c_str() : rm_prefix( | ||
| _( "Include" ) ).c_str() ) | ||
| ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
This code is hard to read. The non-standard naming scheme (hungarian notation itself, hungarian notation being mixed with non-hungarian notation) doesn't help.
Could be cleaned up by:
- Extracting a lambda to cover all 3
mvwprintzwithout a lot of repetition (wouldn't be easy, but doable) - Extracting
vRules[iTab][i]to a variable likecurrent_tab - Extracting some of the inlined data to named variables, to show what is being displayed
Coolthulhu
reviewed
Aug 5, 2016
| tmpx += shortcut_print( w_header, 0, tmpx, c_white, c_ltgreen, _( "<M>ove" ) ) + 2; | ||
| tmpx += shortcut_print( w_header, 0, tmpx, c_white, c_ltgreen, _( "<E>nable" ) ) + 2; | ||
| tmpx += shortcut_print( w_header, 0, tmpx, c_white, c_ltgreen, _( "<D>isable" ) ) + 2; | ||
| shortcut_print( w_header, 0, tmpx, c_white, c_ltgreen, _( "<T>est" ) ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
A lot of nearly identical entries, consider a vector+loop (easier to maintain).
Coolthulhu
reviewed
Aug 5, 2016
| ctxt.register_action( "MOVE_RULE_UP" ); | ||
| ctxt.register_action( "MOVE_RULE_DOWN" ); | ||
| ctxt.register_action( "TEST_RULE" ); | ||
| ctxt.register_action( "HELP_KEYBINDINGS" ); |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
Side note here:
We should probably have a register_action overload that takes a container argument.
Coolthulhu
reviewed
Aug 5, 2016
| wprintz( w, c_yellow, ">> " ); | ||
| } else { | ||
| wprintz( w, c_yellow, " " ); | ||
| } |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
reviewed
Aug 5, 2016
| bool bActive; | ||
| bool bExclude; | ||
| int attCreature; | ||
| int iProxyDist; |
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 5, 2016
Contributor
Is this variable supposed to be proximity distance? proxy and proximity aren't highly related words, it would be better to use just proximity or distance.
BevapDin
reviewed
Aug 12, 2016
| // display safemode | ||
| for( int i = start_pos; i < ( int )creature_list.size(); i++ ) { | ||
| if( i >= start_pos && | ||
| i < start_pos + ( ( content_height > ( int )creature_list.size() ) ? |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Looks like this is supposed to get the content_height or creature_list.size(), whatever is smaller. If so, it should be std::min(static_cast<int>(creature_list.size()), content_height) as that's easier to reason about.
BevapDin
reviewed
Aug 12, 2016
| int nmatch = creature_list.size(); | ||
| std::string buf = string_format( ngettext( "%1$d monster matches: %2$s", | ||
| "%1$d monsters match: %2$s", | ||
| nmatch ), nmatch, temp_rules[row_in].rule.c_str() ); |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| void safemode::test_pattern( const int tab_in, const int row_in ) | ||
| { | ||
| std::vector<std::string> creature_list; | ||
| std::string creature_name = ""; |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
I'm wondering why people write this explicit initialization for strings, but use the default constructor for the vector (above). The = "" is entirely redundant here.
BevapDin
reviewed
Aug 12, 2016
| auto &temp_rules_from = ( tab == GLOBAL_TAB ) ? global_rules : character_rules; | ||
| auto &temp_rules_to = ( tab == GLOBAL_TAB ) ? character_rules : global_rules; | ||
|
|
||
| temp_rules_to.push_back( rules_class( |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Looks like you're copying the rules_class object. Why not use the copy constructor for that?
temp_rules_to.push_back(temp_rules_from[...]);
BevapDin
reviewed
Aug 12, 2016
| int ci_find_substr( const charT &str1, const charT &str2, const std::locale &loc = std::locale() ); | ||
| // templated version of ci_equal so it could work with both char and wchar_t | ||
| template<typename charT> | ||
| struct ci_equal { |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
We really don't need the generic templated version of that function. charT will never be anything but char. Same with the function above.
In fact, this will not currently even work with anything else but char. Try to call ci_find_substr<int>(...) (with suitable dummy arguments) from a source file other than output.cpp. The linker will complain that can not find the function ci_find_substr<int>: only the function ci_find_substr<char> is (implicitly) instantiated in output.cpp (as it's called from another functions).
BevapDin
reviewed
Aug 12, 2016
| } | ||
| } else { //inbetween: vPat[i] | ||
| if (*it != "") { | ||
| if ((iPos = (int)ci_find_substr(sText, *it)) == -1) { |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Coolthulhu
Aug 12, 2016
Contributor
Also in the same line: assignment in if is bad practice and saves only one line.
BevapDin
reviewed
Aug 12, 2016
| } | ||
|
|
||
| for (auto it = vPattern.begin(); it != vPattern.end(); ++it) { | ||
| if (it == vPattern.begin() && *it != "") { //beginning: ^vPat[i] |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
|
|
||
| //case insenitive search | ||
|
|
||
| /* Possible patterns |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
This kind of comment belongs into the function documentation in the header. None of those functions are currently documented at all.
BevapDin
reviewed
Aug 12, 2016
|
|
||
| std::string whitelist = ""; | ||
| if ( !get_safemode().empty() ) { | ||
| whitelist = string_format( " or %s to whitelist the monster", press_x( ACTION_WHITELIST_ENEMY ).c_str() ); |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| } | ||
| }; | ||
|
|
||
| if( ( int ) att < 0 || ( int ) att > 4 ) { |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Use >= strings.size() and either strings.back() or strings[strings.size() - 1] instead of the magic number.
BevapDin
reviewed
Aug 12, 2016
| case ACTION_WHITELIST_ENEMY: | ||
| if ( safe_mode == SAFE_MODE_STOP && !get_safemode().empty() ) { | ||
| get_safemode().add_rule( get_safemode().whitelist, Creature::A_ANY, 0, RULE_WHITELISTED ); | ||
| add_msg( m_info, string_format( _( "Creature whitelisted: %s" ), get_safemode().whitelist.c_str() ).c_str() ); |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| if (rl_dist( u.pos(), p->pos() ) <= iProxyDist) { | ||
| //Safemode NPC check | ||
|
|
||
| const int mondist = rl_dist( u.pos(), p->pos() ); |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Looks like a repetition of the code above for the monster (only obvious difference is "human" instead of critter.name()), even the variable mondist (should be npcdist, shouldn't it?) - this figuratively screams to be put into a function/lambda.
BevapDin
reviewed
Aug 12, 2016
| sText = npc_attitude_name( p->attitude ); | ||
| color = p->symbol_color(); | ||
| std::string sSafemode = _("<A>dd do safemode Blacklist"); | ||
| const std::string monName = (bTypeNPC) ? "human" : m->name(); |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
A small helper function (probably in the safemode ui class) that translates a const Creature & into this string (name() for monsters and "human" for NPCs) would make this a bit simpler and safer.
Coolthulhu
reviewed
Aug 12, 2016
| return false; | ||
| } | ||
| } else { //inbetween: vPat[i] | ||
| if (*it != "") { |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| } | ||
| } else if( action == "QUIT" ) { | ||
| break; | ||
| } else if( tab == CHARACTER_TAB && g->u.name.empty() ) { |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Now I'm wondering why this tests for empty(), while other code in this PR uses == "". Have the same behavior, but using empty() is generic and states the intend clearer.
Anyway, this is inconsistent. (Through the problem is not just here.)
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| } | ||
|
|
||
| auto ¤t_tab = ( tab == GLOBAL_TAB ) ? global_rules : character_rules; | ||
| const bool current_tab_non_empty = !current_tab.empty(); |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
What's the advantages of using this variable instead of !current_tab.empty() directly? The later is always up to date, while this variable can easily be wrong:
const bool is_non_empty = !foo.empty();
...
foo.clear();
...
if(is_non_empty) {
foo[0]; // boom
}
BevapDin
reviewed
Aug 12, 2016
| for( int i = start_pos; i < ( int )current_tab.size(); i++ ) { | ||
| if( i >= start_pos && | ||
| i < start_pos + ( ( content_height > ( int )current_tab.size() ) ? | ||
| ( int )current_tab.size() : content_height ) ) { |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
| attitude = Creature::A_ANY; | ||
| break; | ||
| case Creature::A_ANY: | ||
| default: |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
The default case should be avoided when switching over an enumeration value. That allows the compiler to warn you when an enumeration value has not been handled (e.g. when somebody added a new value to the enumeration without updating the switch). The default case suppresses those warnings.
BevapDin
reviewed
Aug 12, 2016
| } else { | ||
| //Let the options class handle the validity of the new value | ||
| auto temp_option = get_options().get_option( "SAFEMODEPROXIMITY" ); | ||
| temp_option.setValue( text.c_str() ); |
This comment has been minimized.
This comment has been minimized.
BevapDin
reviewed
Aug 12, 2016
|
|
||
| wprintz( w_test_rule_content, c_yellow, ( line == i ) ? ">> " : " " ); | ||
|
|
||
| wprintz( w_test_rule_content, ( line == i ) ? hilite( line_color ) : line_color, |
This comment has been minimized.
This comment has been minimized.
BevapDin
Aug 12, 2016
Contributor
Should be "%s", creature_list[i].c_str()); - just in case the monster name contains a '%'.
This comment has been minimized.
This comment has been minimized.
|
No time to fix this in the forseeable future. |

OzoneH3 commentedAug 4, 2016
•
edited
Closes #9285
Closes #17635
This PR implements a autopickup like UI for white-/blacklisting safemode monsters.
If no rules are specified, the old safemode checks will be used.
Todo:
The example below would: