diff --git a/simconvoi.cc b/simconvoi.cc index 5144244be..4f5d74350 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -163,6 +163,8 @@ void convoi_t::init(player_t *player) recalc_data_front = true; recalc_data = true; + + choose_signal_request.valid = false; } @@ -1330,6 +1332,18 @@ void convoi_t::step() destroy(); return; // must not continue method after deleting this object + case DRIVING: + if( fahr[0]->get_waytype()==track_wt || fahr[0]->get_waytype()==monorail_wt || fahr[0]->get_waytype()==maglev_wt || fahr[0]->get_waytype()==narrowgauge_wt ) { + rail_vehicle_t* v = dynamic_cast(fahr[0]); + if( v && choose_signal_request.valid ) { + // process choose signal judgement request + sint32 dummy = -1; + v->check_choose_signal(choose_signal_request.sig, choose_signal_request.start_block, dummy); + set_choose_signal_judge_request_invalid(); + } + } + break; + default: /* keeps compiler silent*/ break; } @@ -3857,3 +3871,9 @@ const char* convoi_t::send_to_depot(bool local) return txt; } + +void convoi_t::request_choose_signal_judge(signal_t *sig, uint16 start_block) { + choose_signal_request.sig = sig; + choose_signal_request.start_block = start_block; + choose_signal_request.valid = true; +} diff --git a/simconvoi.h b/simconvoi.h index cba4c23a6..d07ee1df6 100644 --- a/simconvoi.h +++ b/simconvoi.h @@ -31,6 +31,7 @@ class vehicle_t; class vehicle_desc_t; class schedule_t; class cbuffer_t; +class signal_t; /** * Base class for all vehicle consists. Convoys can be referenced by handles, see halthandle_t. @@ -297,6 +298,13 @@ private: states state; ribi_t::ribi alte_richtung; + + typedef struct { + bool valid; + signal_t* sig; + uint16 start_block; + } choose_signal_request_t; + choose_signal_request_t choose_signal_request; /** * Initialize all variables with default values. @@ -884,6 +892,10 @@ public: // Overtaking for convois virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other); + + void request_choose_signal_judge(signal_t *sig, uint16 start_block); + void set_choose_signal_judge_request_invalid() { choose_signal_request.valid = false; } + bool is_choose_signal_judge_request_valid() const { return choose_signal_request.valid; } }; #endif diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index a6b3e99b0..a68935ac7 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -2670,6 +2670,38 @@ bool rail_vehicle_t::is_longblock_signal_clear(signal_t *sig, uint16 next_block, } +bool rail_vehicle_t::check_choose_signal(signal_t *sig, uint16 start_block, sint32 &restart_speed) +{ + // now it we are in a step and can use the route search + grund_t const* const target = welt->lookup(cnv->get_route()->back()); + route_t target_rt; + uint16 next_signal, next_crossing; + const int richtung = ribi_type(get_pos(), pos_next); // to avoid confusion at diagonals + target_halt = target->get_halt(); + if( !target_rt.find_route( welt, cnv->get_route()->at(start_block), this, speed_to_kmh(cnv->get_min_top_speed()), richtung, welt->get_settings().get_max_choose_route_steps() ) ) { + // nothing empty or not route with less than get_max_choose_route_steps() tiles + target_halt = halthandle_t(); + sig->set_state( roadsign_t::rot ); + restart_speed = 0; + return false; + } + else { + // try to alloc the whole route + cnv->access_route()->remove_koord_from(start_block); + cnv->access_route()->append( &target_rt ); + if( !block_reserver( cnv->get_route(), start_block+1, next_signal, next_crossing, 100000, true, false ) ) { + dbg->error( "rail_vehicle_t::is_choose_signal_clear()", "could not reserved route after find_route!" ); + target_halt = halthandle_t(); + sig->set_state( roadsign_t::rot ); + restart_speed = 0; + return false; + } + } + sig->set_state( roadsign_t::gruen ); + cnv->set_next_stop_index( min( next_crossing, next_signal ) ); + return true; +} + bool rail_vehicle_t::is_choose_signal_clear(signal_t *sig, const uint16 start_block, sint32 &restart_speed) { bool choose_ok = false; @@ -2678,6 +2710,15 @@ bool rail_vehicle_t::is_choose_signal_clear(signal_t *sig, const uint16 start_bl uint16 next_signal, next_crossing; grund_t const* const target = welt->lookup(cnv->get_route()->back()); + if( cnv->is_waiting() ) { + cnv->set_choose_signal_judge_request_invalid(); + } + else if( cnv->is_choose_signal_judge_request_valid() ) { + // judgement is being processed in a step. + restart_speed = -1; + return false; + } + if( cnv->get_schedule_target()!=koord3d::invalid ) { // destination is a waypoint! goto skip_choose; @@ -2750,35 +2791,19 @@ skip_choose: // note: any old reservations should be invalid after the block reserver call. // => We can now start freshly all over - if(!cnv->is_waiting()) { + if( !cnv->is_waiting() ) { + // reservation must be done in step. restart_speed = -1; target_halt = halthandle_t(); + cnv->request_choose_signal_judge(sig, start_block); return false; } - // now we are in a step and can use the route search array - - // now it we are in a step and can use the route search - route_t target_rt; - const int richtung = ribi_type(get_pos(), pos_next); // to avoid confusion at diagonals - if( !target_rt.find_route( welt, cnv->get_route()->at(start_block), this, speed_to_kmh(cnv->get_min_top_speed()), richtung, welt->get_settings().get_max_choose_route_steps() ) ) { - // nothing empty or not route with less than get_max_choose_route_steps() tiles - target_halt = halthandle_t(); - sig->set_state( roadsign_t::rot ); - restart_speed = 0; + // we are in a step + else if( !check_choose_signal(sig, start_block, restart_speed) ){ + // we are stopping and signal is not clear. + // restart_speed and signal state are set in check_choose_signal return false; } - else { - // try to alloc the whole route - cnv->access_route()->remove_koord_from(start_block); - cnv->access_route()->append( &target_rt ); - if( !block_reserver( cnv->get_route(), start_block+1, next_signal, next_crossing, 100000, true, false ) ) { - dbg->error( "rail_vehicle_t::is_choose_signal_clear()", "could not reserved route after find_route!" ); - target_halt = halthandle_t(); - sig->set_state( roadsign_t::rot ); - restart_speed = 0; - return false; - } - } // reserved route to target } sig->set_state( roadsign_t::gruen ); diff --git a/vehicle/simvehicle.h b/vehicle/simvehicle.h index c060f5285..16330e7f0 100644 --- a/vehicle/simvehicle.h +++ b/vehicle/simvehicle.h @@ -585,6 +585,9 @@ public: virtual void set_convoi(convoi_t *c); virtual schedule_t * generate_new_schedule() const; + + // step() routine called by convoy + bool check_choose_signal(signal_t *sig, uint16 start_index, sint32 &restart_speed); };