diff --git a/simconvoi.cc b/simconvoi.cc index 54de5e0f6..02c22c177 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -146,6 +146,9 @@ void convoi_t::init(player_t *player) next_stop_index = 65535; next_coupling_index = INVALID_INDEX; next_coupling_steps = 0; + + coupling_done = false; + next_initial_direction = ribi_t::none; line_update_pending = linehandle_t(); @@ -1671,9 +1674,17 @@ void convoi_t::ziel_erreicht() if( halt.is_bound() && gr->get_weg_ribi(v->get_waytype())!=0 ) { halt->book(1, HALT_CONVOIS_ARRIVED); } - v->get_convoi()->couple_convoi(self); + if( ribi_t::backward(front()->get_direction())==v->get_convoi()->get_next_initial_direction() ) { + // this convoy leads the other. + couple_convoi(v->get_convoi()->self); + } else { + // this convoy follows the other. + v->get_convoi()->couple_convoi(self); + } wait_lock = 0; set_next_coupling(INVALID_INDEX, 0); + v->get_convoi()->set_coupling_done(true); + coupling_done = true; return; } } @@ -2723,6 +2734,8 @@ void convoi_t::rdwr(loadsave_t *file) rdwr_convoihandle_t( file, coupling_convoi ); file->rdwr_short( next_coupling_index ); file->rdwr_byte( next_coupling_steps ); + file->rdwr_bool(coupling_done); + file->rdwr_byte(next_initial_direction); } if( file->is_loading() ) { @@ -3155,18 +3168,33 @@ station_tile_search_ready: ; } bool departure_cond = true; + bool need_coupling_at_this_stop = false; c = self; - while( c.is_bound() ) { + // A coupled convoy does not have to judge the departure. + while( !is_coupled() && c.is_bound() ) { bool cond = c->get_loading_level() >= c->get_schedule()->get_current_entry().minimum_loading; // minimum loading - cond &= (c->get_schedule()->get_current_entry().coupling_point!=1 || c->get_coupling_convoi().is_bound()); // coupling done? + need_coupling_at_this_stop |= (c->get_schedule()->get_current_entry().coupling_point==1 && !c->is_coupling_done() && !(c->get_coupling_convoi().is_bound() && c->is_coupled())); // coupling done? cond |= c->get_no_load(); // no load cond |= (c->get_schedule()->get_current_entry().waiting_time_shift > 0 && welt->get_ticks() - arrived_time > (welt->ticks_per_world_month >> (16 - c->get_schedule()->get_current_entry().waiting_time_shift)) ); // waiting time departure_cond &= cond; c = c->get_coupling_convoi(); } + departure_cond &= !need_coupling_at_this_stop; + + if( need_coupling_at_this_stop && next_initial_direction==ribi_t::none ) { + // calc the initial direction to the next stop. + route_t r; + route_t::route_result_t res = r.calc_route(welt, front()->get_pos(), schedule->get_next_entry().pos, front(), speed_to_kmh(min_top_speed), 8888); + if( res==route_t::no_route || r.get_count()<2 ) { + // assume we do not turn here + next_initial_direction = front()->get_direction(); + } else { + next_initial_direction = ribi_type(r.at(0), r.at(1)); + } + } // loading is finished => maybe drive on - if( state==COUPLED || departure_cond ) { + if( is_coupled() || departure_cond ) { if( !is_coupled() && !coupling_convoi.is_bound() && withdraw && (loading_level == 0 || goods_catg_index.empty()) ) { // destroy when empty, alone @@ -3182,15 +3210,17 @@ station_tile_search_ready: ; } // Advance schedule - if( state!=COUPLED && state!=COUPLED_LOADING ) { + if( !is_coupled() ) { schedule->advance(); state = ROUTING_1; loading_limit = 0; + coupling_done = false; // Advance schedule of coupling convoy recursively. convoihandle_t c_cnv = coupling_convoi; while( c_cnv.is_bound() ) { c_cnv->get_schedule()->advance(); c_cnv->set_state(COUPLED); + c_cnv->set_coupling_done(false); c_cnv = c_cnv->get_coupling_convoi(); } } @@ -3738,11 +3768,20 @@ PIXVAL convoi_t::get_status_color() const // returns tiles needed for this convoi -uint16 convoi_t::get_tile_length() const +uint16 convoi_t::get_tile_length(bool entire) const { uint16 carunits=0; - for(uint8 i=0; iget_desc()->get_length(); + convoihandle_t c = self; + while( c.is_bound() ) { + for(uint8 i=0; iget_vehicle_count()-1; i++) { + carunits += c->get_vehikel(i)->get_desc()->get_length(); + } + if( !entire || !c->get_coupling_convoi().is_bound() ) { + break; + } else { + carunits += c->back()->get_desc()->get_length(); + c = c->get_coupling_convoi(); + } } // the last vehicle counts differently in stations and for reserving track // (1) add 8 = 127/256 tile to account for the driving in stations in north/west direction @@ -4062,6 +4101,7 @@ const char* convoi_t::send_to_depot(bool local) bool convoi_t::couple_convoi(convoihandle_t coupled) { coupled->set_state(COUPLED_LOADING); + set_state(LOADING); coupling_convoi = coupled; coupling_convoi->front()->set_leading(false); back()->set_last(false); diff --git a/simconvoi.h b/simconvoi.h index fe91424c6..62fcf904c 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -268,6 +268,9 @@ private: */ uint16 next_coupling_index; uint8 next_coupling_steps; + + bool coupling_done; + ribi_t::ribi next_initial_direction; /** * The convoi is not processed every sync step for various actions @@ -905,7 +908,7 @@ public: PIXVAL get_status_color() const; // returns tiles needed for this convoi - uint16 get_tile_length() const; + uint16 get_tile_length(bool entire_convoy = false) const; bool has_obsolete_vehicles() const { return has_obsolete; } @@ -945,6 +948,10 @@ public: bool can_continue_coupling() const; bool can_start_coupling(convoi_t* parent) const; + ribi_t::ribi get_next_initial_direction() const { return next_initial_direction; } + bool is_coupling_done() const { return coupling_done; } + void set_coupling_done(bool tf) { coupling_done = tf; } + void set_arrived_time(uint32 t) { arrived_time = t; } }; diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index a04f5dbde..7e9f5c613 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -2479,7 +2479,7 @@ bool rail_vehicle_t::calc_route(koord3d start, koord3d ziel, sint32 max_speed, r cnv->set_next_reservation_index( 0 ); // nothing to reserve target_halt = halthandle_t(); // no block reserved // use length 8888 tiles to advance to the end of all stations - return route->calc_route(welt, start, ziel, this, max_speed, 8888 /*cnv->get_tile_length()*/ ); + return route->calc_route(welt, start, ziel, this, max_speed, cnv->get_tile_length(true) ); } @@ -2543,8 +2543,8 @@ bool rail_vehicle_t::check_next_tile(const grund_t *bd, bool coupling) const if( rail_vehicle_t* const v = dynamic_cast(bd->obj_bei(pos)) ) { // there is a suitable waiting convoy for coupling -> this is coupling point. if( cnv->can_start_coupling(v->get_convoi()) && v->get_convoi()->is_loading() ) { - if( v!=v->get_convoi()->back() ) { - // we have to couple with the last car of the convoy. + if( !v->is_last() && !v->is_leading() ) { + // we have to couple with either end of the convoy. continue; } return true; @@ -2640,8 +2640,8 @@ bool rail_vehicle_t::is_coupling_target(const grund_t *gr, const grund_t *prev_g if( rail_vehicle_t* const v = dynamic_cast(gr->obj_bei(pos)) ) { // there is a suitable waiting convoy for coupling -> this is coupling point. if( cnv->can_start_coupling(v->get_convoi()) && v->get_convoi()->is_loading() ) { - if( v!=v->get_convoi()->back() ) { - // we have to couple with the last car of the convoy. + if( !v->is_last() && !v->is_leading() ) { + // we have to couple with either end of the convoy. continue; } // set coupling index and step @@ -3275,8 +3275,8 @@ bool rail_vehicle_t::can_couple(const route_t* route, uint16 start_index, uint16 if( rail_vehicle_t* const v = dynamic_cast(gr->obj_bei(pos)) ) { // there is a suitable waiting convoy for coupling -> this is coupling point. if( cnv->can_start_coupling(v->get_convoi()) && v->get_convoi()->is_loading() ) { - if( v!=v->get_convoi()->back() ) { - // we have to couple with the last car of the convoy. + if( !v->is_last() && !v->is_leading() ) { + // we have to couple with either end of the convoy. continue; } //reserve tiles