diff --git a/descriptor/reader/roadsign_reader.cc b/descriptor/reader/roadsign_reader.cc index ed4883f1c..47479b129 100644 --- a/descriptor/reader/roadsign_reader.cc +++ b/descriptor/reader/roadsign_reader.cc @@ -43,8 +43,18 @@ obj_desc_t * roadsign_reader_t::read_node(FILE *fp, obj_node_info_t &node) const uint16 v = decode_uint16(p); const int version = v & 0x8000 ? v & 0x7FFF : 0; - if(version==4) { - // Versioned node, version 3 + if(version==5) { + // Versioned node, version 5 + desc->min_speed = kmh_to_speed(decode_uint16(p)); + desc->price = decode_uint32(p); + desc->flags = decode_uint16(p); + desc->offset_left = decode_sint8(p); + desc->wtyp = decode_uint8(p); + desc->intro_date = decode_uint16(p); + desc->retire_date = decode_uint16(p); + } + else if(version==4) { + // Versioned node, version 4 desc->min_speed = kmh_to_speed(decode_uint16(p)); desc->price = decode_uint32(p); desc->flags = decode_uint8(p); diff --git a/descriptor/roadsign_desc.h b/descriptor/roadsign_desc.h index 0bf32f8f6..fe56f6b28 100644 --- a/descriptor/roadsign_desc.h +++ b/descriptor/roadsign_desc.h @@ -34,7 +34,7 @@ class roadsign_desc_t : public obj_desc_transport_infrastructure_t { friend class roadsign_reader_t; private: - uint8 flags; + uint16 flags; sint8 offset_left; // default 14 @@ -50,7 +50,8 @@ public: SIGN_PRE_SIGNAL = 1U << 4, ONLY_BACKIMAGE = 1U << 5, SIGN_LONGBLOCK_SIGNAL = 1U << 6, - END_OF_CHOOSE_AREA = 1U << 7 + END_OF_CHOOSE_AREA = 1U << 7, + SIGN_PRIORITY_SIGNAL = 1U << 8 }; image_id get_image_id(ribi_t::dir dir) const @@ -65,32 +66,40 @@ public: uint16 get_min_speed() const { return min_speed; } - bool is_single_way() const { return (flags&ONE_WAY)!=0; } + bool is_single_way() const { return (flags & ONE_WAY) != 0; } - bool is_private_way() const { return (flags&PRIVATE_ROAD)!=0; } + bool is_private_way() const { return (flags & PRIVATE_ROAD) != 0; } // return true for a traffic light - bool is_traffic_light() const { return (get_count()>4); } + bool is_traffic_light() const { return (get_count() > 4); } - bool is_choose_sign() const { return flags&CHOOSE_SIGN; } + bool is_choose_sign() const { return (flags & CHOOSE_SIGN) != 0; } // return true for signal - bool is_signal() const { return flags&SIGN_SIGNAL; } + bool is_signal() const { return (flags & SIGN_SIGNAL) != 0; } // return true for presignal - bool is_pre_signal() const { return flags&SIGN_PRE_SIGNAL; } + bool is_pre_signal() const { return (flags & SIGN_PRE_SIGNAL) != 0; } + + // return true for priority signal + bool is_priority_signal() const { return (flags & SIGN_PRIORITY_SIGNAL) != 0; } // return true for single track section signal - bool is_longblock_signal() const { return flags&SIGN_LONGBLOCK_SIGNAL; } + bool is_longblock_signal() const { return (flags & SIGN_LONGBLOCK_SIGNAL) != 0; } - bool is_end_choose_signal() const { return flags&END_OF_CHOOSE_AREA; } + bool is_end_choose_signal() const { return (flags & END_OF_CHOOSE_AREA) != 0; } bool is_signal_type() const { - return (flags&(SIGN_SIGNAL|SIGN_PRE_SIGNAL|SIGN_LONGBLOCK_SIGNAL))!=0; + return (flags&( + SIGN_SIGNAL | + SIGN_PRE_SIGNAL | + SIGN_PRIORITY_SIGNAL | + SIGN_LONGBLOCK_SIGNAL) + ) != 0; } - uint8 get_flags() const { return flags; } + uint16 get_flags() const { return flags; } sint8 get_offset_left() const { return offset_left; } diff --git a/descriptor/writer/roadsign_writer.cc b/descriptor/writer/roadsign_writer.cc index b46069a33..426bac911 100644 --- a/descriptor/writer/roadsign_writer.cc +++ b/descriptor/writer/roadsign_writer.cc @@ -12,7 +12,7 @@ using std::string; void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& obj) { - obj_node_t node(this, 15, &parent); + obj_node_t node(this, 16, &parent); uint32 const price = obj.get_int("cost", 500) * 100; uint16 const min_speed = obj.get_int("min_speed", 0); @@ -24,25 +24,26 @@ void roadsign_writer_t::write_obj(FILE* fp, obj_node_t& parent, tabfileobj_t& ob (obj.get_int("is_private", 0) > 0 ? roadsign_desc_t::PRIVATE_ROAD : roadsign_desc_t::NONE) | (obj.get_int("is_signal", 0) > 0 ? roadsign_desc_t::SIGN_SIGNAL : roadsign_desc_t::NONE) | (obj.get_int("is_presignal", 0) > 0 ? roadsign_desc_t::SIGN_PRE_SIGNAL : roadsign_desc_t::NONE) | + (obj.get_int("is_prioritysignal", 0) > 0 ? roadsign_desc_t::SIGN_PRIORITY_SIGNAL : roadsign_desc_t::NONE) | (obj.get_int("no_foreground", 0) > 0 ? roadsign_desc_t::ONLY_BACKIMAGE : roadsign_desc_t::NONE) | (obj.get_int("is_longblocksignal", 0) > 0 ? roadsign_desc_t::SIGN_LONGBLOCK_SIGNAL : roadsign_desc_t::NONE) | (obj.get_int("end_of_choose", 0) > 0 ? roadsign_desc_t::END_OF_CHOOSE_AREA : roadsign_desc_t::NONE); // Hajo: write version data - node.write_uint16(fp, 0x8004, 0); // version 4 + node.write_uint16(fp, 0x8005, 0); // version 5 node.write_uint16(fp, min_speed, 2); node.write_uint32(fp, price, 4); - node.write_uint8 (fp, flags, 8); - node.write_uint8 (fp, offset_left, 9); - node.write_uint8 (fp, wtyp, 10); + node.write_uint16(fp, flags, 8); + node.write_uint8 (fp, offset_left,10); + node.write_uint8 (fp, wtyp, 11); uint16 intro_date = obj.get_int("intro_year", DEFAULT_INTRO_DATE) * 12; intro_date += obj.get_int("intro_month", 1) - 1; - node.write_uint16(fp, intro_date, 11); + node.write_uint16(fp, intro_date, 12); uint16 retire_date = obj.get_int("retire_year", DEFAULT_RETIRE_DATE) * 12; retire_date += obj.get_int("retire_month", 1) - 1; - node.write_uint16(fp, retire_date, 13); + node.write_uint16(fp, retire_date, 14); write_head(fp, node, obj); diff --git a/obj/roadsign.cc b/obj/roadsign.cc index 3dcdcdd1e..d4f9d89b9 100644 --- a/obj/roadsign.cc +++ b/obj/roadsign.cc @@ -139,7 +139,11 @@ void roadsign_t::set_dir(ribi_t::ribi dir) if( desc->get_wtyp()!=track_wt && desc->get_wtyp()!=monorail_wt && desc->get_wtyp()!=maglev_wt && desc->get_wtyp()!=narrowgauge_wt ) { weg->count_sign(); } - if( desc->is_single_way() || desc->is_signal() || desc->is_pre_signal() || desc->is_longblock_signal() ) { + if(desc->is_single_way() || + desc->is_signal() || + desc->is_pre_signal() || + desc->is_priority_signal() || + desc->is_longblock_signal()) { // set mask, if it is a single way ... weg->count_sign(); weg->set_ribi_maske(calc_mask()); diff --git a/script/api/api_obj_desc.cc b/script/api/api_obj_desc.cc index a7bcb9318..f8998a570 100644 --- a/script/api/api_obj_desc.cc +++ b/script/api/api_obj_desc.cc @@ -662,6 +662,10 @@ void export_goods_desc(HSQUIRRELVM vm) * @returns true if sign is pre signal (distant signal) */ register_method(vm, &roadsign_desc_t::is_pre_signal, "is_pre_signal"); + /** + * @returns true if sign is priority signal + */ + register_method(vm, &roadsign_desc_t::is_priority_signal, "is_priority_signal"); /** * @returns true if sign is long-block signal */ diff --git a/simconvoi.cc b/simconvoi.cc index 4b22ff84d..581b0219f 100644 --- a/simconvoi.cc +++ b/simconvoi.cc @@ -267,7 +267,7 @@ void convoi_t::unreserve_route() /** - * unreserves the whole remaining route + * reserves route until next_reservation_index */ void convoi_t::reserve_route() { diff --git a/simtool.cc b/simtool.cc index d7391c4ba..a419264a3 100644 --- a/simtool.cc +++ b/simtool.cc @@ -4762,7 +4762,10 @@ const char* tool_build_roadsign_t::check_pos_intern(player_t *player, koord3d po return error; } - const bool two_way = desc->is_single_way() || desc->is_signal() || desc->is_pre_signal(); + const bool two_way = desc->is_single_way() || + desc->is_signal() || + desc->is_pre_signal() || + desc->is_priority_signal(); if(!(desc->is_traffic_light() || two_way) || (two_way && ribi_t::is_twoway(dir)) || (desc->is_traffic_light() && ribi_t::is_threeway(dir))) { roadsign_t* rs; @@ -5044,7 +5047,10 @@ const char *tool_build_roadsign_t::place_sign_intern( player_t *player, grund_t* } ribi_t::ribi dir = weg->get_ribi_unmasked(); - const bool two_way = desc->is_single_way() || desc->is_signal() || desc->is_pre_signal(); + const bool two_way = desc->is_single_way() || + desc->is_signal() || + desc->is_pre_signal() || + desc->is_priority_signal(); if(!(desc->is_traffic_light() || two_way) || (two_way && ribi_t::is_twoway(dir)) || (desc->is_traffic_light() && ribi_t::is_threeway(dir))) { roadsign_t* rs; diff --git a/vehicle/simvehicle.cc b/vehicle/simvehicle.cc index 4962d8fa3..f5f7eb229 100644 --- a/vehicle/simvehicle.cc +++ b/vehicle/simvehicle.cc @@ -2788,7 +2788,9 @@ bool rail_vehicle_t::is_pre_signal_clear(signal_t *sig, uint16 next_block, sint3 // parse to next signal; if needed recurse, since we allow cascading uint16 next_signal, next_crossing; if( block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ) ) { - if( next_signal == INVALID_INDEX || cnv->get_route()->at(next_signal) == cnv->get_route()->back() || is_signal_clear( next_signal, restart_speed ) ) { + if(next_signal == INVALID_INDEX || + cnv->get_route()->at(next_signal) == cnv->get_route()->back() || + is_signal_clear( next_signal, restart_speed )) { // ok, end of route => we can go sig->set_state( roadsign_t::gruen ); cnv->set_next_stop_index( min( next_signal, next_crossing ) ); @@ -2807,6 +2809,79 @@ bool rail_vehicle_t::is_pre_signal_clear(signal_t *sig, uint16 next_block, sint3 } +bool rail_vehicle_t::is_priority_signal_clear(signal_t *sig, uint16 next_block, sint32 &restart_speed) +{ + // parse to next signal; if needed recurse, since we allow cascading + uint16 next_signal, next_crossing; + + if( !block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ) ) { + // if we end up here, there was not even the next block free + sig->set_state( roadsign_t::rot ); + restart_speed = 0; + return false; + } + + if( next_signal != INVALID_INDEX && cnv->get_route()->at(next_signal) != cnv->get_route()->back() ) { + // there is a signal before end of route + if( is_signal_clear( next_signal, restart_speed ) ) { + // ok => we can go + sig->set_state( roadsign_t::gruen ); + cnv->set_next_stop_index( min( next_signal, next_crossing ) ); + return true; + } + } + else { + // no signal before end_of_route => need to do route search in a step + // now we can use the route search array + uint8 schedule_index = cnv->get_schedule()->get_current_stop()+1; + route_t target_rt; + koord3d cur_pos = cnv->get_route()->back(); + uint16 dummy, next_next_signal; + if( schedule_index >= cnv->get_schedule()->get_count() ) { + schedule_index = 0; + } + while( schedule_index!=cnv->get_schedule()->get_current_stop() ) { + // search for route + bool success = target_rt.calc_route( welt, cur_pos, cnv->get_schedule()->entries[schedule_index].pos, this, speed_to_kmh(cnv->get_min_top_speed()), 8888 /*cnv->get_tile_length()*/ ); + if( success ) { + success = block_reserver( &target_rt, 1, next_next_signal, dummy, 0, true, false ); + } + + if( success ) { + // way is free + if( next_next_signal finished + // however, if it is this signal, we need to renew reservation ... + if( target_rt.at(next_next_signal) == cnv->get_route()->at( next_block ) ) { + block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ); + } + sig->set_state( roadsign_t::gruen ); + cnv->set_next_stop_index( min( min( next_crossing, next_signal ), cnv->get_route()->get_count() ) ); + return true; + } + } + else { + // failed to reserve. + break; + } + + // prepare for next leg of schedule + cur_pos = target_rt.back(); + schedule_index ++; + if( schedule_index>=cnv->get_schedule()->get_count() ) { + schedule_index = 0; + } + } + } + + // when we reached here, the way after next signal is not free though the way before is => we can still go + sig->set_state( roadsign_t::naechste_rot ); + cnv->set_next_stop_index( min( next_signal, next_crossing ) ); + + return false; +} + + bool rail_vehicle_t::is_signal_clear(uint16 next_block, sint32 &restart_speed) { // called, when there is a signal; will call other signal routines if needed @@ -2821,7 +2896,10 @@ bool rail_vehicle_t::is_signal_clear(uint16 next_block, sint32 &restart_speed) const roadsign_desc_t *sig_desc=sig->get_desc(); // simple signal: drive on, if next block is free - if( !sig_desc->is_longblock_signal() && !sig_desc->is_choose_sign() && !sig_desc->is_pre_signal() ) { + if(!sig_desc->is_longblock_signal() && + !sig_desc->is_choose_sign() && + !sig_desc->is_pre_signal() && + !sig_desc->is_priority_signal()) { uint16 next_signal, next_crossing; if( block_reserver( cnv->get_route(), next_block+1, next_signal, next_crossing, 0, true, false ) ) { @@ -2839,6 +2917,10 @@ bool rail_vehicle_t::is_signal_clear(uint16 next_block, sint32 &restart_speed) return is_pre_signal_clear( sig, next_block, restart_speed ); } + if ( sig_desc->is_priority_signal() ) { + return is_priority_signal_clear( sig, next_block, restart_speed ); + } + if( sig_desc->is_longblock_signal() ) { return is_longblock_signal_clear( sig, next_block, restart_speed ); } diff --git a/vehicle/simvehicle.h b/vehicle/simvehicle.h index 242a93f71..bc6924825 100644 --- a/vehicle/simvehicle.h +++ b/vehicle/simvehicle.h @@ -549,6 +549,7 @@ protected: bool is_signal_clear(uint16 start_index, sint32 &restart_speed); bool is_pre_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed); + bool is_priority_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed); bool is_longblock_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed); bool is_choose_signal_clear(signal_t *sig, uint16 start_index, sint32 &restart_speed);