@@ -60,6 +60,10 @@ class path
60
60
* Avatar must be at one of the ends of the path.
61
61
*/
62
62
void set_avatar_path () const ;
63
+ /* *
64
+ * Avatar stands in the middle of the path, so go towards the end or start selected by `towards_end`.
65
+ */
66
+ void set_avatar_path ( bool towards_end ) const ;
63
67
void set_name_start ();
64
68
void set_name_end ();
65
69
/* *
@@ -105,6 +109,13 @@ class path_manager_impl
105
109
* Crash on fail <==> when avatar_at_what_start_or_end returns -1.
106
110
*/
107
111
void auto_route_from_path () const ;
112
+ /* *
113
+ * Let the player choose on what path to walk and in what direction.
114
+ * Set avatars auto route to the selected path.
115
+ *
116
+ * Return true if path was selected, false otherwise.
117
+ */
118
+ bool auto_route_from_path_middle () const ;
108
119
/* *
109
120
* Start recording a new path.
110
121
*/
@@ -134,6 +145,10 @@ class path_manager_impl
134
145
* -1 if the avatar stands at no start or end.
135
146
*/
136
147
int avatar_at_what_start_or_end () const ;
148
+ /* *
149
+ * Return indexes of paths the avatar stands on.
150
+ */
151
+ std::vector<int > avatar_at_what_paths () const ;
137
152
private:
138
153
bool is_recording_path () const ;
139
154
/* *
@@ -203,22 +218,40 @@ void path::record_step( const tripoint_abs_ms &new_pos )
203
218
}
204
219
205
220
void path::set_avatar_path () const
221
+ {
222
+ if ( is_avatar_at_start () || is_avatar_at_end () ) {
223
+ set_avatar_path ( is_avatar_at_start () );
224
+ } else {
225
+ debugmsg ( " Tried to set auto route but the player character doesn't stand at path start or end." );
226
+ return ;
227
+ }
228
+ }
229
+
230
+ void path::set_avatar_path ( bool towards_end ) const
206
231
{
207
232
avatar &player_character = get_avatar ();
208
233
std::vector<tripoint_bub_ms> route;
234
+ std::string from;
209
235
if ( is_avatar_at_start () ) {
210
- add_msg ( m_info, _ ( string_format ( " Auto path: Go from %s to %s." , name_start, name_end ) ) );
211
- for ( auto it = std::next ( recorded_path.begin () ); it != recorded_path.end (); ++it ) {
212
- route.emplace_back ( get_map ().bub_from_abs ( *it ) );
213
- }
236
+ from = name_start;
214
237
} else if ( is_avatar_at_end () ) {
215
- add_msg ( m_info, _ ( string_format ( " Auto path: Go from %s to %s." , name_end, name_start ) ) );
216
- for ( auto it = std::next ( recorded_path.rbegin () ); it != recorded_path.rend (); ++it ) {
238
+ from = name_end;
239
+ } else {
240
+ from = _ ( " the middle of path" );
241
+ }
242
+
243
+ int avatar_at = avatar_closest_i_approximate ();
244
+ if ( towards_end ) {
245
+ add_msg ( m_info, _ ( string_format ( " Auto path: Go from %s to %s." , from, name_end ) ) );
246
+ for ( auto it = std::next ( recorded_path.begin () + avatar_at ); it != recorded_path.end (); ++it ) {
217
247
route.emplace_back ( get_map ().bub_from_abs ( *it ) );
218
248
}
219
249
} else {
220
- debugmsg ( " Tried to set auto route but the player character doesn't stand at path start or end." );
221
- return ;
250
+ add_msg ( m_info, _ ( string_format ( " Auto path: Go from %s to %s." , from, name_start ) ) );
251
+ for ( auto it = std::next ( recorded_path.rbegin () + recorded_path.size () - avatar_at - 1 );
252
+ it != recorded_path.rend (); ++it ) {
253
+ route.emplace_back ( get_map ().bub_from_abs ( *it ) );
254
+ }
222
255
}
223
256
player_character.set_destination ( route );
224
257
}
@@ -266,7 +299,7 @@ bool path::is_avatar_at_end() const
266
299
int path::avatar_closest_i_approximate () const
267
300
{
268
301
cata_assert ( !recorded_path.empty () );
269
- tripoint_abs_ms avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
302
+ const tripoint_abs_ms & avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
270
303
// Check start and end so that the path is not further away than either of those.
271
304
int closest_i = recorded_path.size () - 1 ;
272
305
int closest_dist = square_dist ( recorded_path.back (), avatar_pos );
@@ -393,6 +426,18 @@ int path_manager_impl::avatar_at_what_start_or_end() const
393
426
return -1 ;
394
427
}
395
428
429
+ std::vector<int > path_manager_impl::avatar_at_what_paths () const
430
+ {
431
+ std::vector<int > ret;
432
+ const tripoint_abs_ms &avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
433
+ for ( auto it = paths.begin (); it != paths.end (); ++it ) {
434
+ if ( avatar_pos == it->recorded_path [it->avatar_closest_i_approximate ()] ) {
435
+ ret.emplace_back ( static_cast <int >( it - paths.begin () ) );
436
+ }
437
+ }
438
+ return ret;
439
+ }
440
+
396
441
bool path_manager_impl::is_recording_path () const
397
442
{
398
443
return recording_path_index != -1 ;
@@ -405,6 +450,35 @@ void path_manager_impl::auto_route_from_path() const
405
450
paths[p_index].set_avatar_path ();
406
451
}
407
452
453
+ bool path_manager_impl::auto_route_from_path_middle () const
454
+ {
455
+ const tripoint_abs_ms &avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
456
+ uilist path_selection;
457
+ path_selection.text = _ ( " Select path and direction to walk in." );
458
+ for ( int i : avatar_at_what_paths () ) {
459
+ const path &curr_path = paths[i];
460
+ const std::string from_to = string_format ( " from %s (%s) to %s (%s)" ,
461
+ curr_path.name_start ,
462
+ direction_suffix ( avatar_pos, curr_path.recorded_path .front () ),
463
+ curr_path.name_end ,
464
+ direction_suffix ( avatar_pos, curr_path.recorded_path .back () ) );
465
+ const int avatar_at_i = curr_path.avatar_closest_i_approximate ();
466
+ const int start_steps = avatar_at_i;
467
+ const int end_steps = curr_path.recorded_path .size () - avatar_at_i - 1 ;
468
+ const std::string start = string_format ( " %s (%d steps)" , curr_path.name_start , avatar_at_i );
469
+ const std::string end = string_format ( " %s (%d steps)" , curr_path.name_end , end_steps );
470
+ path_selection.addentry ( -1 , false , MENU_AUTOASSIGN, from_to );
471
+ path_selection.addentry ( i << 1 , start_steps > 0 , MENU_AUTOASSIGN, start );
472
+ path_selection.addentry ( ( i << 1 ) + 1 , end_steps > 0 , MENU_AUTOASSIGN, end );
473
+ }
474
+ path_selection.query ();
475
+ if ( path_selection.ret < 0 ) {
476
+ return false ;
477
+ }
478
+ paths[path_selection.ret >> 1 ].set_avatar_path ( path_selection.ret % 2 );
479
+ return true ;
480
+ }
481
+
408
482
void path_manager_impl::set_recording_path ( int p_index )
409
483
{
410
484
cata_assert ( -1 <= p_index && p_index < static_cast <int >( paths.size () ) );
@@ -431,7 +505,7 @@ void path_manager_ui::enabled_active_button( const std::string action, bool enab
431
505
432
506
static void draw_distance_from_tile ( const tripoint_abs_ms &tile )
433
507
{
434
- const tripoint_abs_ms avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
508
+ const tripoint_abs_ms & avatar_pos = get_map ().getglobal ( get_avatar ().pos_bub () );
435
509
if ( avatar_pos == tile ) {
436
510
cataimgui::draw_colored_text ( _ ( " It's under your feet." ), c_light_green );
437
511
} else {
@@ -442,18 +516,25 @@ static void draw_distance_from_tile( const tripoint_abs_ms &tile )
442
516
443
517
void path_manager_ui::draw_controls ()
444
518
{
445
- // general buttons
519
+ // walk buttons
520
+ cataimgui::draw_colored_text ( _ ( " Walk:" ) );
521
+ ImGui::SameLine ();
446
522
enabled_active_button ( " WALK_PATH" , pimpl->avatar_at_what_start_or_end () != -1 );
447
523
ImGui::SameLine ();
524
+ enabled_active_button ( " WALK_PATH_FROM_MIDDLE" , !pimpl->avatar_at_what_paths ().empty () );
525
+
526
+ // recording buttons
527
+ cataimgui::draw_colored_text ( _ ( " Recording:" ) );
528
+ ImGui::SameLine ();
448
529
enabled_active_button ( " START_RECORDING" , !pimpl->is_recording_path () );
449
530
ImGui::SameLine ();
450
531
enabled_active_button ( " CONTINUE_RECORDING" , !pimpl->is_recording_path ()
451
532
&& pimpl->avatar_at_what_start_or_end () != -1 );
452
533
ImGui::SameLine ();
453
534
enabled_active_button ( " STOP_RECORDING" , pimpl->is_recording_path () );
454
535
455
- // buttons related to selected path
456
- cataimgui::draw_colored_text ( _ ( " Selected path :" ), c_white );
536
+ // manage buttons
537
+ cataimgui::draw_colored_text ( _ ( " Manage :" ) );
457
538
ImGui::SameLine ();
458
539
enabled_active_button ( " DELETE_PATH" , pimpl->selected_id != -1 );
459
540
ImGui::SameLine ();
@@ -462,6 +543,9 @@ void path_manager_ui::draw_controls()
462
543
enabled_active_button ( " MOVE_PATH_DOWN" , pimpl->selected_id != -1 &&
463
544
pimpl->selected_id + 1 < static_cast <int >( pimpl->paths .size () ) );
464
545
546
+ // name buttons
547
+ cataimgui::draw_colored_text ( _ ( " Rename:" ) );
548
+ ImGui::SameLine ();
465
549
enabled_active_button ( " RENAME_START" , pimpl->selected_id != -1 );
466
550
ImGui::SameLine ();
467
551
enabled_active_button ( " RENAME_END" , pimpl->selected_id != -1 );
@@ -524,6 +608,7 @@ void path_manager_ui::run()
524
608
ctxt.register_action ( " HELP_KEYBINDINGS" );
525
609
526
610
ctxt.register_action ( " WALK_PATH" );
611
+ ctxt.register_action ( " WALK_PATH_FROM_MIDDLE" );
527
612
ctxt.register_action ( " START_RECORDING" );
528
613
ctxt.register_action ( " STOP_RECORDING" );
529
614
ctxt.register_action ( " CONTINUE_RECORDING" );
@@ -548,6 +633,10 @@ void path_manager_ui::run()
548
633
if ( action == " WALK_PATH" && pimpl->avatar_at_what_start_or_end () != -1 ) {
549
634
pimpl->auto_route_from_path ();
550
635
break ;
636
+ } else if ( action == " WALK_PATH_FROM_MIDDLE" && !pimpl->avatar_at_what_paths ().empty () ) {
637
+ if ( pimpl->auto_route_from_path_middle () ) {
638
+ break ;
639
+ }
551
640
} else if ( action == " START_RECORDING" && !pimpl->is_recording_path () ) {
552
641
pimpl->start_recording ();
553
642
break ;
0 commit comments