diff --git a/dataobj/schedule.cc b/dataobj/schedule.cc index 1da4a45d5..5dc42ed30 100644 --- a/dataobj/schedule.cc +++ b/dataobj/schedule.cc @@ -23,7 +23,7 @@ #include "../tpl/slist_tpl.h" -schedule_entry_t schedule_t::dummy_entry(koord3d::invalid, 0, 0); +schedule_entry_t schedule_t::dummy_entry(koord3d::invalid, 0, 0, false); schedule_t::schedule_t(loadsave_t* const file) @@ -119,7 +119,7 @@ halthandle_t schedule_t::get_prev_halt( player_t *player ) const } -bool schedule_t::insert(const grund_t* gr, uint8 minimum_loading, uint8 waiting_time_shift ) +bool schedule_t::insert(const grund_t* gr, uint8 minimum_loading, uint8 waiting_time_shift, bool is_terminal ) { // stored in minivec, so we have to avoid adding too many if( entries.get_count()>=254 ) { @@ -128,7 +128,7 @@ bool schedule_t::insert(const grund_t* gr, uint8 minimum_loading, uint8 waiting_ } if( is_stop_allowed(gr) ) { - entries.insert_at(current_stop, schedule_entry_t(gr->get_pos(), minimum_loading, waiting_time_shift)); + entries.insert_at(current_stop, schedule_entry_t(gr->get_pos(), minimum_loading, waiting_time_shift, is_terminal)); current_stop ++; return true; } @@ -141,7 +141,7 @@ bool schedule_t::insert(const grund_t* gr, uint8 minimum_loading, uint8 waiting_ -bool schedule_t::append(const grund_t* gr, uint8 minimum_loading, uint8 waiting_time_shift) +bool schedule_t::append(const grund_t* gr, uint8 minimum_loading, uint8 waiting_time_shift, bool is_terminal) { // stored in minivec, so we have to avoid adding too many if(entries.get_count()>=254) { @@ -150,7 +150,7 @@ bool schedule_t::append(const grund_t* gr, uint8 minimum_loading, uint8 waiting_ } if(is_stop_allowed(gr)) { - entries.append(schedule_entry_t(gr->get_pos(), minimum_loading, waiting_time_shift), 4); + entries.append(schedule_entry_t(gr->get_pos(), minimum_loading, waiting_time_shift, is_terminal), 4); return true; } else { @@ -237,7 +237,7 @@ void schedule_t::rdwr(loadsave_t *file) uint32 dummy; pos.rdwr(file); file->rdwr_long(dummy); - entries.append(schedule_entry_t(pos, (uint8)dummy, 0)); + entries.append(schedule_entry_t(pos, (uint8)dummy, 0, false)); } } else { @@ -252,6 +252,12 @@ void schedule_t::rdwr(loadsave_t *file) if(file->get_version()>=99018) { file->rdwr_byte(entries[i].waiting_time_shift); } + if(file->get_version()>=120006) { + file->rdwr_bool(entries[i].is_terminal); + } + else { + entries[i].is_terminal = false; + } } } if(file->is_loading()) { @@ -409,7 +415,7 @@ void schedule_t::sprintf_schedule( cbuffer_t &buf ) const { buf.printf("%u|%d|", current_stop, (int)get_type()); FOR(minivec_tpl, const& i, entries) { - buf.printf("%s,%i,%i|", i.pos.get_str(), (int)i.minimum_loading, (int)i.waiting_time_shift); + buf.printf("%s,%i,%i,%i|", i.pos.get_str(), (int)i.minimum_loading, (int)i.waiting_time_shift, (int)i.is_terminal); } } @@ -452,24 +458,24 @@ bool schedule_t::sscanf_schedule( const char *ptr ) p++; // now scan the entries while( *p>0 ) { - sint16 values[5]; - for( sint8 i=0; i<5; i++ ) { + sint16 values[6]; + for( sint8 i=0; i<6; i++ ) { values[i] = atoi( p ); while( *p && (*p!=',' && *p!='|') ) { p++; } - if( i<4 && *p!=',' ) { + if( i<5 && *p!=',' ) { dbg->error( "schedule_t::sscanf_schedule()","incomplete string!" ); return false; } - if( i==4 && *p!='|' ) { + if( i==5 && *p!='|' ) { dbg->error( "schedule_t::sscanf_schedule()","incomplete entry termination!" ); return false; } p++; } // ok, now we have a complete entry - entries.append(schedule_entry_t(koord3d(values[0], values[1], values[2]), values[3], values[4])); + entries.append(schedule_entry_t(koord3d(values[0], values[1], values[2]), values[3], values[4], values[5])); } return true; } diff --git a/dataobj/schedule.h b/dataobj/schedule.h index 8ea8c4183..bb645cab3 100644 --- a/dataobj/schedule.h +++ b/dataobj/schedule.h @@ -116,12 +116,12 @@ public: /** * Inserts a coordinate at current_stop into the schedule. */ - bool insert(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0); + bool insert(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0, bool is_terminal = false); /** * Appends a coordinate to the schedule. */ - bool append(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0); + bool append(const grund_t* gr, uint8 minimum_loading = 0, uint8 waiting_time_shift = 0, bool is_terminal = false); /** * Cleanup a schedule, removes double entries. diff --git a/dataobj/schedule.h.gch b/dataobj/schedule.h.gch new file mode 100644 index 000000000..4af5ae649 Binary files /dev/null and b/dataobj/schedule.h.gch differ diff --git a/dataobj/schedule_entry.h b/dataobj/schedule_entry.h index 8ffff0498..48fc9b97d 100644 --- a/dataobj/schedule_entry.h +++ b/dataobj/schedule_entry.h @@ -12,10 +12,11 @@ struct schedule_entry_t public: schedule_entry_t() {} - schedule_entry_t(koord3d const& pos, uint const minimum_loading, sint8 const waiting_time_shift) : + schedule_entry_t(koord3d const& pos, uint const minimum_loading, sint8 const waiting_time_shift, bool const is_terminal) : pos(pos), minimum_loading(minimum_loading), - waiting_time_shift(waiting_time_shift) + waiting_time_shift(waiting_time_shift), + is_terminal(is_terminal) {} /** @@ -37,6 +38,13 @@ public: * @author prissi */ sint8 waiting_time_shift; + + /** + * if this stop is set as "terminnal" + * (ignored on waypoints) + * @author Hyper + */ + bool is_terminal; }; #endif diff --git a/dataobj/schedule_entry.h.gch b/dataobj/schedule_entry.h.gch new file mode 100644 index 000000000..225df8fa1 Binary files /dev/null and b/dataobj/schedule_entry.h.gch differ diff --git a/gui/convoi_info_t.cc b/gui/convoi_info_t.cc index c1f64b46e..4892fb011 100644 --- a/gui/convoi_info_t.cc +++ b/gui/convoi_info_t.cc @@ -37,8 +37,6 @@ #include "../utils/simstring.h" - - #include "convoi_detail_t.h" #define CHART_HEIGHT (100) @@ -244,10 +242,8 @@ void convoi_info_t::draw(scr_coord pos, scr_size size) else { go_home_button.enable(); } - - if( grund_t* gr=welt->lookup(cnv->get_schedule()->get_current_entry().pos) ) { - go_home_button.pressed = gr->get_depot() != NULL; - } + + go_home_button.pressed = cnv->get_go_home(); details_button.pressed = win_get_magic( magic_convoi_detail+cnv.get_id() ); no_load_button.pressed = cnv->get_no_load(); @@ -432,37 +428,15 @@ bool convoi_info_t::action_triggered( gui_action_creator_t *comp,value_t /* */) return true; } - if( comp == &no_load_button && !route_search_in_progress ) { + if( comp == &no_load_button && !route_search_in_progress ) { cnv->call_convoi_tool( 'n', NULL ); return true; } if( comp == &go_home_button && !route_search_in_progress ) { - // limit update to certain states that are considered to be safe for schedule updates - int state = cnv->get_state(); - if(state==convoi_t::EDIT_SCHEDULE) { - return true; - } - - grund_t* gr = welt->lookup(cnv->get_schedule()->get_current_entry().pos); - const bool enable_gohome = gr && gr->get_depot() == NULL; - - if( enable_gohome ) { - // go to depot - route_search_in_progress = true; - cnv->call_convoi_tool( 'd', NULL ); - } - else { - // back to normal schedule - schedule_t* schedule = cnv->get_schedule()->copy(); - schedule->remove(); // remove depot entry - - cbuffer_t buf; - schedule->sprintf_schedule( buf ); - cnv->call_convoi_tool( 'g', buf ); - delete schedule; - } - } // end go home button + cnv->call_convoi_tool( 'd', NULL ); + return true; + } } if ( comp == &toggler ) { @@ -529,7 +503,7 @@ void convoi_info_t::set_windowsize(scr_size size) { gui_frame_t::set_windowsize(size); - input.set_size(scr_size(get_windowsize().w - D_MARGIN_LEFT-D_MARGIN_RIGHT, D_EDIT_HEIGHT)); + input.set_size(scr_size(get_windowsize().w - D_MARGIN_LEFT-D_MARGIN_RIGHT, D_BUTTON_HEIGHT)); view.set_pos( scr_coord(get_windowsize().w - view.get_size().w - D_MARGIN_LEFT, D_MARGIN_TOP+D_BUTTON_HEIGHT+D_V_SPACE )); follow_button.set_pos( view.get_pos() + scr_coord( 0, view.get_size().h ) ); diff --git a/gui/convoi_info_t.h b/gui/convoi_info_t.h index 8fcae24a8..91a6722b0 100644 --- a/gui/convoi_info_t.h +++ b/gui/convoi_info_t.h @@ -133,5 +133,7 @@ public: uint32 get_rdwr_id() { return magic_convoi_info; } + void route_search_start() { route_search_in_progress = true; } + void route_search_finished() { route_search_in_progress = false; } }; diff --git a/gui/schedule_gui.cc b/gui/schedule_gui.cc index f6de90ea3..f7e3766bc 100644 --- a/gui/schedule_gui.cc +++ b/gui/schedule_gui.cc @@ -102,6 +102,9 @@ static void gimme_stop_name(cbuffer_t& buf, karte_t* welt, player_t const* const char const* what; halthandle_t const halt = haltestelle_t::get_halt(entry.pos, player_); if (halt.is_bound()) { + if (entry.is_terminal) { + buf.printf("T: "); + } if (entry.minimum_loading != 0) { buf.printf("%d%% ", entry.minimum_loading); } @@ -307,6 +310,12 @@ schedule_gui_t::schedule_gui_t(schedule_t* schedule_, player_t* player_, convoih lb_load.align_to( &numimp_load, ALIGN_CENTER_V, scr_coord( D_MARGIN_LEFT, 0 ) ); add_component( &lb_load ); + bt_terminal.init( button_t::square_state, "Terminal", scr_coord(BUTTON3_X, ypos) ); + bt_terminal.set_tooltip("Set the current stop as a terminal"); + bt_terminal.add_listener(this); + bt_terminal.pressed = false; + add_component( &bt_terminal ); + ypos += numimp_load.get_size().h; if( schedule->get_current_entry().waiting_time_shift==0 ) { @@ -423,6 +432,8 @@ void schedule_gui_t::update_selection() schedule->set_current_stop( min(schedule->get_count()-1,schedule->get_current_stop()) ); const uint8 current_stop = schedule->get_current_stop(); if( haltestelle_t::get_halt(schedule->entries[current_stop].pos, player).is_bound() ) { + bt_terminal.enable(); + bt_terminal.pressed = schedule->entries[current_stop].is_terminal; lb_load.set_color( SYSCOL_TEXT ); numimp_load.enable(); numimp_load.set_value( schedule->entries[current_stop].minimum_loading ); @@ -437,6 +448,7 @@ void schedule_gui_t::update_selection() } } else { + bt_terminal.disable(); lb_load.set_color( SYSCOL_BUTTON_TEXT_DISABLED ); numimp_load.disable(); numimp_load.set_value( 0 ); @@ -558,6 +570,13 @@ DBG_MESSAGE("schedule_gui_t::action_triggered()","komp=%p combo=%p",komp,&line_s bt_remove.pressed = true; update_tool( false ); } + else if(komp == &bt_terminal) { + if (!schedule->empty()) { + bt_terminal.pressed ^= 1; + schedule->entries[schedule->get_current_stop()].is_terminal = bt_terminal.pressed; + update_selection(); + } + } else if(komp == &numimp_load) { if (!schedule->empty()) { schedule->entries[schedule->get_current_stop()].minimum_loading = (uint8)p.i; diff --git a/gui/schedule_gui.h b/gui/schedule_gui.h index d96e50163..e0171ecf6 100644 --- a/gui/schedule_gui.h +++ b/gui/schedule_gui.h @@ -93,6 +93,8 @@ private: gui_label_t lb_load; gui_numberinput_t numimp_load; + button_t bt_terminal; // set stop as a terminal + char str_parts_month[32]; schedule_gui_stats_t stats; diff --git a/gui/schedule_gui.h.gch b/gui/schedule_gui.h.gch new file mode 100644 index 000000000..fa11d2c56 Binary files /dev/null and b/gui/schedule_gui.h.gch differ diff --git a/gui/schedule_list.cc b/gui/schedule_list.cc index d610ae840..b9d92e494 100644 --- a/gui/schedule_list.cc +++ b/gui/schedule_list.cc @@ -44,7 +44,6 @@ #include "../boden/wege/schiene.h" #include "../boden/wege/strasse.h" - #include "karte.h" @@ -221,7 +220,7 @@ schedule_list_gui_t::schedule_list_gui_t(player_t *player_) : // lower left corner: halt list of selected line cont_haltestellen.set_size(scr_size(3*D_BUTTON_WIDTH+2*D_H_SPACE, 28)); - scrolly_haltestellen.set_pos(scr_coord(D_MARGIN_LEFT, bt_y + D_BUTTON_HEIGHT+ D_V_SPACE)); + scrolly_haltestellen.set_pos(scr_coord(D_MARGIN_LEFT, bt_y + D_BUTTON_HEIGHT + D_V_SPACE)); scrolly_haltestellen.set_show_scroll_x(true); scrolly_haltestellen.set_scroll_amount_y(28); scrolly_haltestellen.set_visible(false); @@ -242,7 +241,7 @@ schedule_list_gui_t::schedule_list_gui_t(player_t *player_) : // convoi list cont.set_size(scr_size(200, 40)); - scrolly_convois.set_pos(scr_coord(RIGHT_COLUMN_OFFSET, bt_y + D_BUTTON_HEIGHT+ D_V_SPACE + 2*LINESPACE)); + scrolly_convois.set_pos(scr_coord(RIGHT_COLUMN_OFFSET, bt_y + D_BUTTON_HEIGHT + D_V_SPACE + 2*LINESPACE)); scrolly_convois.set_show_scroll_x(true); scrolly_convois.set_scroll_amount_y(40); scrolly_convois.set_visible(false); @@ -255,6 +254,13 @@ schedule_list_gui_t::schedule_list_gui_t(player_t *player_) : bt_withdraw_line.add_listener(this); add_component(&bt_withdraw_line); + bt_all_go_home.init(button_t::roundbox_state, "All Go Home", + scr_coord(RIGHT_COLUMN_OFFSET+D_BUTTON_WIDTH+D_H_SPACE, bt_y), scr_size(D_BUTTON_WIDTH, D_BUTTON_HEIGHT)); + bt_all_go_home.set_tooltip("Convoi returns to nearest depot."); + bt_all_go_home.set_visible(false); + bt_all_go_home.add_listener(this); + add_component(&bt_all_go_home); + //CHART chart.set_dimension(12, 1000); chart.set_pos( scr_coord(RIGHT_COLUMN_OFFSET, D_MARGIN_TOP) ); @@ -387,6 +393,17 @@ bool schedule_list_gui_t::action_triggered( gui_action_creator_t *komp, value_t delete tmp_tool; } } + else if( komp == &bt_all_go_home ) { + bt_all_go_home.pressed ^= 1; + if ( line.is_bound() ) { + tool_t *tmp_tool = create_tool( TOOL_CHANGE_LINE | SIMPLE_TOOL ); + cbuffer_t buf; + buf.printf( "h,%i,%i", line.get_id(), bt_all_go_home.pressed ); + tmp_tool->set_default_param(buf); + welt->set_tool( tmp_tool, player ); + delete tmp_tool; + } + } else if( komp == &tabs ) { int const tab = tabs.get_active_tab_index(); uint8 old_selected_tab = selected_tab[player->get_player_nr()]; @@ -546,7 +563,7 @@ void schedule_list_gui_t::display(scr_coord pos) break; } } - sint16 text_y = D_TITLEBAR_HEIGHT+bt_withdraw_line.get_pos().y + bt_withdraw_line.get_size().h + D_V_SPACE; + sint16 text_y = D_TITLEBAR_HEIGHT + bt_withdraw_line.get_pos().y + bt_withdraw_line.get_size().h + D_V_SPACE; int len=display_proportional_clip_rgb(pos.x+RIGHT_COLUMN_OFFSET, pos.y+text_y, buf, ALIGN_LEFT, SYSCOL_TEXT, true ); @@ -562,7 +579,7 @@ void schedule_list_gui_t::display(scr_coord pos) buf.clear(); buf.printf( translator::translate("Capacity: %s\nLoad: %d (%d%%)"), ctmp, load, loadfactor ); display_multiline_text_rgb(pos.x + RIGHT_COLUMN_OFFSET + rest_width, - pos.y+D_TITLEBAR_HEIGHT+D_MARGIN_TOP + SCL_HEIGHT + 2*D_BUTTON_HEIGHT+D_V_SPACE, buf, SYSCOL_TEXT); + pos.y+text_y, buf, SYSCOL_TEXT); } } @@ -655,10 +672,11 @@ void schedule_list_gui_t::update_lineinfo(linehandle_t new_line) cont.set_size(scr_size(500, ypos)); bt_delete_line.disable(); - add_component(&bt_withdraw_line); bt_withdraw_line.disable(); - if( icnv>0 ) { + bt_all_go_home.disable(); + if( icnv>0 ) { bt_withdraw_line.enable(); + bt_all_go_home.enable(); } else { bt_delete_line.enable(); @@ -666,6 +684,7 @@ void schedule_list_gui_t::update_lineinfo(linehandle_t new_line) bt_edit_line.enable(); bt_withdraw_line.pressed = new_line->get_withdraw(); + bt_all_go_home.pressed = new_line->get_go_home(); // fill haltestellen container with info of stops of the line cont_haltestellen.remove_all(); @@ -737,6 +756,7 @@ void schedule_list_gui_t::update_lineinfo(linehandle_t new_line) } line = new_line; bt_withdraw_line.set_visible( line.is_bound() ); + bt_all_go_home.set_visible( line.is_bound() ); reset_line_name(); } diff --git a/gui/schedule_list.h b/gui/schedule_list.h index b7fe85948..fb63244dd 100644 --- a/gui/schedule_list.h +++ b/gui/schedule_list.h @@ -32,7 +32,7 @@ class schedule_list_gui_t : public gui_frame_t, public action_listener_t private: player_t *player; - button_t bt_new_line, bt_edit_line, bt_delete_line, bt_withdraw_line; + button_t bt_new_line, bt_edit_line, bt_delete_line, bt_withdraw_line, bt_all_go_home; gui_container_t cont, cont_haltestellen; gui_scrollpane_t scrolly_convois, scrolly_haltestellen; gui_scrolled_list_t scl; @@ -71,8 +71,6 @@ private: void display(scr_coord pos); - void update_lineinfo(linehandle_t new_line); - linehandle_t line; vector_tpl lines; @@ -137,6 +135,8 @@ public: */ void update_data(linehandle_t changed_line); + void update_lineinfo(linehandle_t new_line); + // following: rdwr stuff void rdwr( loadsave_t *file ); uint32 get_rdwr_id(); diff --git a/simconvoi.cc b/simconvoi.cc index c15454e9b..91d9642d5 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -29,6 +29,7 @@ #include "gui/depot_frame.h" #include "gui/messagebox.h" #include "gui/convoi_detail_t.h" +#include "gui/schedule_list.h" #include "boden/grund.h" #include "boden/wege/schiene.h" // for railblocks @@ -124,6 +125,7 @@ void convoi_t::init(player_t *player) withdraw = false; has_obsolete = false; no_load = false; + go_home = false; wait_lock = 0; arrived_time = 0; @@ -1194,7 +1196,6 @@ void convoi_t::step() case EDIT_SCHEDULE: // schedule window closed? if(schedule!=NULL && schedule->is_editing_finished()) { - set_schedule(schedule); schedule_target = koord3d::invalid; @@ -1208,11 +1209,18 @@ void convoi_t::step() // this station? then complete loading task else drive on halthandle_t h = haltestelle_t::get_halt( get_pos(), get_owner() ); if( h.is_bound() && h==haltestelle_t::get_halt( schedule->get_current_entry().pos, get_owner() ) ) { - if (route.get_count() > 0) { - koord3d const& pos = route.back(); - if (h == haltestelle_t::get_halt(pos, get_owner())) { - state = get_pos() == pos ? LOADING : DRIVING; - break; + if ( go_home && schedule->get_current_entry().is_terminal ) { + schedule->advance(); + send_to_depot(true); + state = ROUTING_1; + } + else { + if (route.get_count() > 0) { + koord3d const& pos = route.back(); + if (h == haltestelle_t::get_halt(pos, get_owner())) { + state = get_pos() == pos ? LOADING : DRIVING; + break; + } } } else { @@ -1228,6 +1236,7 @@ void convoi_t::step() grund_t *gr = welt->lookup(schedule->get_current_entry().pos); if( gr && gr->get_depot() ) { betrete_depot( gr->get_depot() ); + update_schedule_list(); } else { state = ROUTING_1; @@ -1487,8 +1496,17 @@ void convoi_t::betrete_depot(depot_t *dep) maxspeed_average_count = 0; state = INITIAL; + set_go_home(false); } +void convoi_t::update_schedule_list() +{ + get_line()->set_go_home( get_line()->check_go_home_status() ); + schedule_list_gui_t *sl = dynamic_cast(win_get_magic( magic_line_management_t + get_owner()->get_player_nr() )); + if( sl ) { + sl->update_lineinfo( get_line() ); + } +} void convoi_t::start() { @@ -1576,11 +1594,13 @@ void convoi_t::ziel_erreicht() // we still book the money for the trip; however, the freight will be deleted (by the vehicle in the depot itself) calc_gewinn(); + go_home = false; akt_speed = 0; buf.printf( translator::translate("%s has entered a depot."), get_name() ); welt->get_message()->add_message(buf, v->get_pos().get_2d(),message_t::warnings, PLAYER_FLAG|get_owner()->get_player_nr(), IMG_EMPTY); betrete_depot(dp); + update_schedule_list(); } else { // no depot reached, check for stop! @@ -1799,7 +1819,7 @@ bool convoi_t::set_schedule(schedule_t * f) // happens to be identical? if(schedule!=f) { - // now check, we we have been bond to a line we are about to lose: + // now check, we have been bond to a line we are about to lose: bool changed = false; if( line.is_bound() ) { if( !f->matches( welt, line->get_schedule() ) ) { @@ -2563,6 +2583,12 @@ void convoi_t::rdwr(loadsave_t *file) file->rdwr_short( next_stop_index ); file->rdwr_short( next_reservation_index ); } + if( file->get_version()<120006 ) { + go_home = false; + } + else { + file->rdwr_bool(go_home); + } if( file->is_loading() ) { reserve_route(); @@ -2888,6 +2914,10 @@ station_tile_search_ready: ; break; } else if( !plan_halt.is_bound() ) { + if( schedule->entries[wrap_i].is_terminal && go_home ) { + // do not load for stops after a terminal if the convoy is scheduled to going to depot + break; + } if( grund_t *gr = welt->lookup( schedule->entries[wrap_i].pos ) ) { if( gr->get_depot() ) { // do not load for stops after a depot @@ -2923,7 +2953,8 @@ station_tile_search_ready: ; uint16 amount = v->unload_cargo(halt); - if( !no_load && v->get_total_cargo() < v->get_cargo_max()) { + if( !no_load && v->get_total_cargo() < v->get_cargo_max() && + !(go_home && schedule->entries[schedule->get_current_stop()].is_terminal) ) { // load if: unloaded something (might go back) or previous non-filled car requested different cargo type if (amount>0 || cargo_type_prev==NULL || !cargo_type_prev->is_interchangeable(v->get_cargo_type())) { // load @@ -2970,8 +3001,19 @@ station_tile_search_ready: ; } // loading is finished => maybe drive on - if( loading_level >= loading_limit || no_load - || (schedule->get_current_entry().waiting_time_shift > 0 && welt->get_ticks() - arrived_time > (welt->ticks_per_world_month >> (16 - schedule->get_current_entry().waiting_time_shift)) ) ) { + if( loading_level >= loading_limit || no_load || (go_home && schedule->get_current_entry().is_terminal) || (schedule->get_current_entry().waiting_time_shift > 0 + && welt->get_ticks() - arrived_time > (welt->ticks_per_world_month >> (16 - schedule->get_current_entry().waiting_time_shift)) ) ) { + + if( go_home && schedule->get_current_entry().is_terminal ) { + // if this convoy is scheduled to going to depot and reached to terminal stop, it will go to depot + if (convoi_info_t *info = dynamic_cast(win_get_magic( magic_convoi_info+self.get_id()))) { + info->route_search_start(); + } + schedule->advance(); + send_to_depot(true); + state = ROUTING_1; + return; + } if( withdraw && (loading_level == 0 || goods_catg_index.empty()) ) { // destroy when empty @@ -3574,6 +3616,90 @@ void convoi_t::set_withdraw(bool new_withdraw) } } +// convoi will go to depot if it is not searching for route. +void convoi_t::change_go_home(bool yes_no) +{ + // test if convoi in depot and not driving + grund_t *gr = welt->lookup( get_pos() ); + if( gr && gr->get_depot() && state == INITIAL ) { + // do not touch line bound convois in depots + set_go_home(false); + return; + } + set_go_home(yes_no); + if ( get_go_home() ) { + if ( !get_line()->has_terminal() ) { + if (convoi_info_t *info = dynamic_cast(win_get_magic( magic_convoi_info + self.get_id())) ) { + info->route_search_start(); + } + } + } + else { + // back to normal schedule if the convoi is going to depot + if (welt->lookup(get_schedule()->get_current_entry().pos)->get_depot() != NULL) { + schedule_t* schedule = get_schedule()->copy(); + schedule->remove(); // remove depot entry + + cbuffer_t buf; + schedule->sprintf_schedule( buf ); + call_convoi_tool( 'g', buf ); + delete schedule; + } + } +} + +bool convoi_t::send_to_depot(bool local) +{ + // iterate over all depots and try to find shortest route + route_t *shortest_route = new route_t(); + route_t *route = new route_t(); + koord3d home = koord3d::invalid; + vehicle_t *v = front(); + + // if convoi is going to a depot, return true + if (welt->lookup(get_schedule()->get_current_entry().pos)->get_depot() != NULL) { + dynamic_cast(win_get_magic( magic_convoi_info + self.get_id()))->route_search_finished(); + return true; + } + + FOR(slist_tpl, const depot, depot_t::get_depot_list()) { + if (depot->get_waytype() != v->get_desc()->get_waytype() || depot->get_owner() != get_owner()) { + continue; + } + koord3d pos = depot->get_pos(); + + if(!shortest_route->empty() && koord_distance(pos, get_pos()) >= shortest_route->get_count()-1) { + // the current route is already shorter, no need to search further + continue; + } + if (v->calc_route(get_pos(), pos, 50, route)) { // do not care about speed + if( route->get_count() < shortest_route->get_count() || shortest_route->empty() ) { + // just swap the pointers + sim::swap(shortest_route, route); + home = pos; + } + } + } + delete route; + DBG_MESSAGE("shortest route has ", "%i hops", shortest_route->get_count()-1); + + if (local) { + if (convoi_info_t *info = dynamic_cast(win_get_magic( magic_convoi_info+self.get_id()))) { + info->route_search_finished(); + } + } + // if route to a depot has been found, update the convoi's schedule + bool enable_go_home = !shortest_route->empty(); + if( enable_go_home ) { + schedule_t *schedule = get_schedule()->copy(); + schedule->insert(welt->lookup(home)); + schedule->set_current_stop( (schedule->get_current_stop()+schedule->get_count()-1)%schedule->get_count() ); + set_schedule(schedule); + } + delete shortest_route; + + return enable_go_home; +} /** * conditions for a city car to overtake another overtaker. @@ -3803,54 +3929,3 @@ sint64 convoi_t::get_stat_converted(int month, int cost_type) const } return value; } - - -const char* convoi_t::send_to_depot(bool local) -{ - // iterate over all depots and try to find shortest route - route_t *shortest_route = new route_t(); - route_t *route = new route_t(); - koord3d home = koord3d::invalid; - vehicle_t *v = front(); - FOR(slist_tpl, const depot, depot_t::get_depot_list()) { - if (depot->get_waytype() != v->get_desc()->get_waytype() || depot->get_owner() != get_owner()) { - continue; - } - koord3d pos = depot->get_pos(); - - if(!shortest_route->empty() && koord_distance(pos, get_pos()) >= shortest_route->get_count()-1) { - // the current route is already shorter, no need to search further - continue; - } - if (v->calc_route(get_pos(), pos, 50, route)) { // do not care about speed - if( route->get_count() < shortest_route->get_count() || shortest_route->empty() ) { - // just swap the pointers - sim::swap(shortest_route, route); - home = pos; - } - } - } - delete route; - DBG_MESSAGE("shortest route has ", "%i hops", shortest_route->get_count()-1); - - if (local) { - if (convoi_info_t *info = dynamic_cast(win_get_magic( magic_convoi_info+self.get_id()))) { - info->route_search_finished(); - } - } - // if route to a depot has been found, update the convoi's schedule - const char *txt; - if( !shortest_route->empty() ) { - schedule_t *schedule = get_schedule()->copy(); - schedule->insert(welt->lookup(home)); - schedule->set_current_stop( (schedule->get_current_stop()+schedule->get_count()-1)%schedule->get_count() ); - set_schedule(schedule); - txt = "Convoi has been sent\nto the nearest depot\nof appropriate type.\n"; - } - else { - txt = "Home depot not found!\nYou need to send the\nconvoi to the depot\nmanually."; - } - delete shortest_route; - - return txt; -} diff --git a/simconvoi.h b/simconvoi.h index cba4c23a6..da3e2a70a 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -167,6 +167,12 @@ private: bool no_load; /** + * the convoi is going to depot + * @author Hyper + */ + bool go_home; + + /** * the convoi caches its freight info; it is only recalculation after loading or resorting * @author prissi */ @@ -522,6 +528,12 @@ public: void betrete_depot(depot_t *dep); /** + * update 'All Go Home' button in schedule list + * @author Hyper + */ + void update_schedule_list(); + + /** * Return the internal name of the convois * @return Name of the convois * @author Hj. Malthaner @@ -838,7 +850,7 @@ public: * Has to be called synchronously on all clients in networkmode! * @returns success message */ - const char* send_to_depot(bool local); + bool send_to_depot(bool local); /** * this give the index of the next signal or the end of the route @@ -871,6 +883,13 @@ public: void set_no_load(bool new_no_load) { no_load = new_no_load; } + bool get_go_home() const { return go_home; } + + void set_go_home(bool new_go_home) { go_home = new_go_home; } + + // change state of go_home + void change_go_home(bool yes_no); + void must_recalc_data() { recalc_data = true; } void must_recalc_data_front() { recalc_data_front = true; } void must_recalc_speed_limit() { recalc_speed_limit = true; } diff --git a/simconvoi.h.gch b/simconvoi.h.gch new file mode 100644 index 000000000..7aa89f426 Binary files /dev/null and b/simconvoi.h.gch differ diff --git a/simline.cc b/simline.cc index 235f605a5..4ef790bfc 100644 --- a/simline.cc +++ b/simline.cc @@ -42,6 +42,7 @@ simline_t::simline_t(player_t* player, linetype type) this->schedule = NULL; this->player = player; withdraw = false; + go_home = false; state_color = SYSCOL_TEXT; create_schedule(); } @@ -55,6 +56,7 @@ simline_t::simline_t(player_t* player, linetype type, loadsave_t *file) this->schedule = NULL; this->player = player; withdraw = false; + go_home = false; create_schedule(); rdwr(file); // now self has the right id but the this-pointer is not assigned to the quickstone handle yet @@ -274,12 +276,15 @@ void simline_t::rdwr(loadsave_t *file) file->rdwr_bool(withdraw); } + if(file->get_version()>=120006) { + file->rdwr_bool(go_home); + } + // otherwise initialized to zero if loading ... financial_history[0][LINE_CONVOIS] = count_convoys(); } - void simline_t::finish_rd() { if( !self.is_bound() ) { @@ -392,6 +397,7 @@ void simline_t::recalc_status() // no convois assigned to this line state_color = SYSCOL_TEXT_HIGHLIGHT; withdraw = false; + go_home = false; } else if(financial_history[0][LINE_PROFIT]<0) { // ok, not performing best @@ -429,12 +435,13 @@ void simline_t::recalc_catg_index() } goods_catg_index.clear(); withdraw = !line_managed_convoys.empty(); + go_home = !line_managed_convoys.empty(); // then recreate current FOR(vector_tpl, const i, line_managed_convoys) { // what goods can this line transport? convoi_t const& cnv = *i; withdraw &= cnv.get_withdraw(); - + go_home &= cnv.get_go_home(); FOR(minivec_tpl, const catg_index, cnv.get_goods_catg_index()) { goods_catg_index.append_unique( catg_index ); } @@ -456,8 +463,6 @@ void simline_t::recalc_catg_index() } } - - void simline_t::set_withdraw( bool yes_no ) { withdraw = yes_no && !line_managed_convoys.empty(); @@ -468,6 +473,49 @@ void simline_t::set_withdraw( bool yes_no ) } } +void simline_t::set_go_home( bool yes_no ) +{ + go_home = yes_no && !line_managed_convoys.empty(); +} + +bool simline_t::change_go_home( bool yes_no ) +{ + set_go_home(yes_no); + bool enable_go_home = true; + for (size_t i = line_managed_convoys.get_count(); i-- != 0;) { + line_managed_convoys[i]->change_go_home(yes_no); + if ( yes_no && line_managed_convoys[i]->get_go_home() ) { + if ( has_terminal() ) { + // if this line has terminal stop + } + else { + // if this line has no terminal stops + enable_go_home &= line_managed_convoys[i]->send_to_depot(yes_no); + } + } + } + //update schedule list + line_managed_convoys[0]->update_schedule_list(); + return enable_go_home; +} + +bool simline_t::check_go_home_status() +{ + bool go_home_status = false; + for (size_t i = line_managed_convoys.get_count(); i-- != 0;) { + go_home_status |= line_managed_convoys[i]->get_go_home(); + } + return go_home_status; +} + +bool simline_t::has_terminal() +{ + bool has_terminal = false; + for(size_t i = schedule->get_count(); i-- !=0;) { + has_terminal |= schedule->entries[i].is_terminal; + } + return has_terminal; +} sint64 simline_t::get_stat_converted(int month, int cost_type) const { diff --git a/simline.h b/simline.h index 34fc430e1..c34faf713 100644 --- a/simline.h +++ b/simline.h @@ -44,6 +44,7 @@ protected: linetype type; bool withdraw; + bool go_home; private: static karte_ptr_t welt; @@ -197,6 +198,19 @@ public: bool get_withdraw() const { return withdraw; } + void set_go_home( bool yes_no ); + + bool get_go_home() const { return go_home; } + + // change state of go_home + bool change_go_home( bool yes_no ); + + // check the go_home status for all convoys in this line. + bool check_go_home_status(); + + // check if there is a terminal stop in this line + bool has_terminal(); + player_t *get_owner() const {return player;} }; diff --git a/simline.h.gch b/simline.h.gch new file mode 100644 index 000000000..106c35981 Binary files /dev/null and b/simline.h.gch differ diff --git a/simtool.cc b/simtool.cc index 0b0b4dfa7..858113100 100644 --- a/simtool.cc +++ b/simtool.cc @@ -57,6 +57,7 @@ #include "gui/trafficlight_info.h" #include "gui/privatesign_info.h" #include "gui/messagebox.h" +#include "gui/convoi_info_t.h" #include "obj/zeiger.h" #include "obj/bruecke.h" @@ -211,7 +212,6 @@ static char const* tooltip_with_price_maintenance_capacity(karte_t* const welt, return tool_t::toolstr; } - void open_error_msg_win(const char* error) { koord pos = message_t::get_coord_from_text(error); @@ -4632,7 +4632,7 @@ const char* tool_build_roadsign_t::check_pos_intern(player_t *player, koord3d po const char * error = "Hier kann kein\nSignal aufge-\nstellt werden!\n"; if (desc==NULL) { // read data from string - read_default_param(player); + desc = roadsign_t::find_desc(default_param); } if (desc==NULL) { return error; @@ -4699,57 +4699,27 @@ const char* tool_build_roadsign_t::check_pos_intern(player_t *player, koord3d po return error; } -char tool_build_roadsign_t::toolstring[256]; -const char* tool_build_roadsign_t::get_default_param(player_t *player) const +void tool_build_roadsign_t::rdwr_custom_data(memory_rw_t *packet) { - if (desc && player) { - signal_info const& s = signal[player->get_player_nr()]; - sprintf(toolstring, "%s,%d,%d,%d", desc->get_name(), s.spacing, s.remove_intermediate, s.replace_other); - return toolstring; - } - else { - return default_param; - } + two_click_tool_t::rdwr_custom_data(packet); + packet->rdwr_byte(current.spacing); + packet->rdwr_bool(current.remove_intermediate); + packet->rdwr_bool(current.replace_other); } + waytype_t tool_build_roadsign_t::get_waytype() const { return desc ? desc->get_wtyp() : invalid_wt; } -// read variables from default_param if cmd comes from network -// default_param: sign_name,signal_spacing,remove,replace -// if the static variable toolstring is the default_param then reset default_param to name of signal -void tool_build_roadsign_t::read_default_param(player_t * player) -{ - char name[256]=""; - uint32 i; - for(i=0; default_param[i]!=0 && default_param[i]!=','; i++) { - name[i]=default_param[i]; - } - name[i]=0; - desc = roadsign_t::find_desc(name); - if (default_param[i]) { - signal_info& s = signal[player->get_player_nr()]; - int i_signal_spacing = s.spacing; - int i_remove_intermediate_signals = s.remove_intermediate; - int i_replace_other_signals = s.replace_other; - sscanf(default_param+i, ",%d,%d,%d", &i_signal_spacing, &i_remove_intermediate_signals, &i_replace_other_signals); - s.spacing = (uint8)i_signal_spacing; - s.remove_intermediate = i_remove_intermediate_signals != 0; - s.replace_other = i_replace_other_signals != 0; - } - if (default_param==toolstring) { - default_param = desc->get_name(); - } -} - -bool tool_build_roadsign_t::init( player_t * player) +bool tool_build_roadsign_t::init( player_t *player) { - // read data from string - read_default_param(player); + desc = roadsign_t::find_desc(default_param); + // take default values from players settings + current = signal[player->get_player_nr()]; if (is_ctrl_pressed() && can_use_gui()) { create_win(new signal_spacing_frame_t(player, this), w_info, (ptrdiff_t)this); @@ -4813,7 +4783,7 @@ void tool_build_roadsign_t::mark_tiles( player_t *player, const koord3d &start, if (!calc_route(route, player, start, ziel)) { return; } - signal_info const& s = signal[player->get_player_nr()]; + signal_info const& s = current; uint8 const signal_density = 2 * s.spacing; // measured in half tiles (straight track count as 2, diagonal as 1, since sqrt(1/2) = 1/2 ;) uint8 next_signal = signal_density + 1; // to place a sign asap sint32 cost = 0; @@ -4891,7 +4861,7 @@ void tool_build_roadsign_t::mark_tiles( player_t *player, const koord3d &start, const char *tool_build_roadsign_t::do_work( player_t *player, const koord3d &start, const koord3d &end) { // read data from string - read_default_param(player); + desc = roadsign_t::find_desc(default_param); // single click ->place signal if( end == koord3d::invalid || start == end ) { grund_t *gr = welt->lookup(start); @@ -4953,6 +4923,7 @@ void tool_build_roadsign_t::set_values( player_t *player, uint8 spacing, bool re s.spacing = spacing; s.remove_intermediate = remove; s.replace_other = replace; + current = s; } @@ -6749,9 +6720,11 @@ bool tool_change_convoi_t::init( player_t *player ) break; case 'n': // change no_load - cnv->set_no_load( !cnv->get_no_load() ); - if( !cnv->get_no_load() ) { - cnv->set_withdraw( false ); + { + cnv->set_no_load( !cnv->get_no_load() ); + if( !cnv->get_no_load() ) { + cnv->set_withdraw( false ); + } } break; @@ -6768,16 +6741,34 @@ bool tool_change_convoi_t::init( player_t *player ) break; case 'w': // change withdraw - cnv->set_withdraw( !cnv->get_withdraw() ); - cnv->set_no_load( cnv->get_withdraw() ); + { + cnv->set_withdraw( !cnv->get_withdraw() ); + cnv->set_no_load( cnv->get_withdraw() ); + } break; - case 'd': // goto depot + case 'd': // go to depot or back to normal schedule { - const char* msg = cnv->send_to_depot(is_local_execution()); + // limit update to certain states that are considered to be safe for schedule updates + if( cnv->get_state() != convoi_t::EDIT_SCHEDULE ) { + cnv->change_go_home( !cnv->get_go_home() ); + + if( cnv->get_go_home() ) { + // go to depot + bool find_depot = cnv->send_to_depot(is_local_execution()); - if (is_local_execution()) { - create_win( new news_img(msg), w_time_delete, magic_none); + if (is_local_execution()) { + if( find_depot ) { + create_win( new news_img("Convoi has been sent\nto the nearest depot\nof appropriate type.\n"), w_time_delete, magic_none); + } + else { + create_win( new news_img("Home depot not found!\nYou need to send the\nconvoi to the depot\nmanually."), w_time_delete, magic_none); + } + } + } + else { + cnv->update_schedule_list(); + } } } } @@ -6804,7 +6795,14 @@ bool tool_change_convoi_t::init( player_t *player ) /* Handles all action of lines. Needs a default param: * [function],[line_id],addition stuff * following simple command exists: + * 'c' : create line * 'g' : apply new schedule to line [schedule follows] + * 'd' : delete line + * 'g' : change schedule + * 't' : trims away convois on all lines of linetype with this default parameter + * 'u' : unite all lineless convois with similar schedules + * 'w' : change withdraw + * 'h' : change go home */ bool tool_change_line_t::init( player_t *player ) { @@ -7027,6 +7025,27 @@ bool tool_change_line_t::init( player_t *player ) } } break; + + case 'h': //change go home + { + if (line.is_bound()) { + bool enable_go_home = line->change_go_home( atoi(p) ); + + if (line->get_go_home()) { + if (enable_go_home) { + if (line->has_terminal()) { + create_win( new news_img("After reaching to a terminal,\neach convoi in this line\nwill be sent to\nthe nearest depot.\n"), w_time_delete, magic_none); + } + else { + create_win( new news_img("Each convoi in this line\nhas been sent to\nthe nearest depot.\n"), w_time_delete, magic_none); + } + } + else { + create_win( new news_img("Some convoi in this line\ncan not found home depot!\nYou need to send the\nconvoi to the depot\nmanually.\n"), w_time_delete, magic_none); + } + } + } + } } return false; } @@ -7504,6 +7523,7 @@ bool tool_rename_t::init(player_t *player) } case 'm': + { if( grund_t *gr = welt->lookup(pos) ) { label_t *label = gr->find(); if (label && (!env_t::networkmode || player_t::check_owner(label->get_owner(), player)) ) { @@ -7512,8 +7532,10 @@ bool tool_rename_t::init(player_t *player) return false; } break; + } - case 'p': { + case 'p': + { player_t *other = welt->get_player((uint8)id); if( other && other == player ) { other->set_name(p); diff --git a/simtool.h b/simtool.h index b709a5907..cf43f3023 100644 --- a/simtool.h +++ b/simtool.h @@ -411,11 +411,11 @@ private: uint8 spacing; // place signals every n tiles bool remove_intermediate; bool replace_other; - } signal[MAX_PLAYER_COUNT]; - - static char toolstring[256]; - // read the variables from the default_param - void read_default_param(player_t *player); + }; + // default values for this tool per player + signal_info signal[MAX_PLAYER_COUNT]; + // values that will be used to build + signal_info current; const char* check_pos_intern(player_t *, koord3d); bool calc_route( route_t &, player_t *, const koord3d& start, const koord3d &to ); @@ -438,7 +438,7 @@ public: void get_values(player_t *player, uint8 &spacing, bool &remove, bool &replace ); bool is_init_network_save() const OVERRIDE { return true; } void draw_after(scr_coord, bool dirty) const OVERRIDE; - char const* get_default_param(player_t*) const OVERRIDE; + void rdwr_custom_data(memory_rw_t*) OVERRIDE; waytype_t get_waytype() const OVERRIDE; }; diff --git a/simversion.h b/simversion.h index 604790dfc..db7bdb65e 100644 --- a/simversion.h +++ b/simversion.h @@ -17,7 +17,7 @@ // Beware: SAVEGAME minor is often ahead of version minor when there were patches. // ==> These have no direct connection at all! -#define SIM_SAVE_MINOR 5 +#define SIM_SAVE_MINOR 6 #define SIM_SERVER_MINOR 6 // NOTE: increment before next release to enable save/load of new features diff --git a/simversion.h.gch b/simversion.h.gch new file mode 100644 index 000000000..026c49b08 Binary files /dev/null and b/simversion.h.gch differ diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index 59f806c3c..85ac0a91b 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -1763,9 +1763,15 @@ void vehicle_t::display_after(int xpos, int ypos, bool is_gobal) const case convoi_t::DRIVING: if( state>=1 ) { grund_t const* const gr = welt->lookup(cnv->get_route()->back()); - if( gr && gr->get_depot() ) { - tstrncpy( tooltip_text, translator::translate("go home"), lengthof(tooltip_text) ); - color = color_idx_to_rgb(COL_GREEN); + if( cnv->get_go_home() ) { + if( gr && gr->get_depot() ) { + tstrncpy( tooltip_text, translator::translate("go home"), lengthof(tooltip_text) ); + color = color_idx_to_rgb(COL_GREEN); + } + else { + tstrncpy( tooltip_text, translator::translate("go home after terminal"), lengthof(tooltip_text) ); + color = color_idx_to_rgb(COL_GREEN); + } } else if( cnv->get_no_load() ) { tstrncpy( tooltip_text, translator::translate("no load"), lengthof(tooltip_text) );