mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r18764) -Fix [FS#3422]: split the (un)load ticks counter and signal wait counter; sometimes they might get into eachother's way
This commit is contained in:
parent
f65f276d10
commit
e4af35d316
|
@ -85,6 +85,9 @@ struct Aircraft : public SpecializedVehicle<Aircraft, VEH_AIRCRAFT> {
|
|||
DirectionByte last_direction;
|
||||
byte number_consecutive_turns;
|
||||
|
||||
/** Ticks between each turn to prevent > 45 degree turns. */
|
||||
byte turn_counter;
|
||||
|
||||
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
||||
Aircraft() : SpecializedVehicle<Aircraft, VEH_AIRCRAFT>() {}
|
||||
/** We want to 'destruct' the right class. */
|
||||
|
|
|
@ -979,7 +979,7 @@ static bool AircraftController(Aircraft *v)
|
|||
count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
|
||||
if (count == 0) return false;
|
||||
|
||||
if (v->time_counter != 0) v->time_counter--;
|
||||
if (v->turn_counter != 0) v->turn_counter--;
|
||||
|
||||
do {
|
||||
|
||||
|
@ -1003,13 +1003,13 @@ static bool AircraftController(Aircraft *v)
|
|||
Direction newdir = GetDirectionTowards(v, x + amd->x, y + amd->y);
|
||||
if (newdir != v->direction) {
|
||||
if (amd->flag & AMED_SLOWTURN && v->number_consecutive_turns < 8 && v->subtype == AIR_AIRCRAFT) {
|
||||
if (v->time_counter == 0 || newdir == v->last_direction) {
|
||||
if (v->turn_counter == 0 || newdir == v->last_direction) {
|
||||
if (newdir == v->last_direction) {
|
||||
v->number_consecutive_turns = 0;
|
||||
} else {
|
||||
v->number_consecutive_turns++;
|
||||
}
|
||||
v->time_counter = 2 * _settings_game.vehicle.plane_speed;
|
||||
v->turn_counter = 2 * _settings_game.vehicle.plane_speed;
|
||||
v->last_direction = v->direction;
|
||||
v->direction = newdir;
|
||||
}
|
||||
|
|
|
@ -1084,7 +1084,7 @@ void PrepareUnload(Vehicle *front_v)
|
|||
ClrBit(front_v->vehicle_flags, VF_LOADING_FINISHED);
|
||||
|
||||
/* Start unloading in at the first possible moment */
|
||||
front_v->time_counter = 1;
|
||||
front_v->load_unload_ticks = 1;
|
||||
|
||||
if ((front_v->current_order.GetUnloadType() & OUFB_NO_UNLOAD) == 0) {
|
||||
for (Vehicle *v = front_v; v != NULL; v = v->Next()) {
|
||||
|
@ -1110,10 +1110,10 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
|||
{
|
||||
assert(v->current_order.IsType(OT_LOADING));
|
||||
|
||||
assert(v->time_counter != 0);
|
||||
assert(v->load_unload_ticks != 0);
|
||||
|
||||
/* We have not waited enough time till the next round of loading/unloading */
|
||||
if (--v->time_counter != 0) {
|
||||
if (--v->load_unload_ticks != 0) {
|
||||
if (_settings_game.order.improved_load && (v->current_order.GetLoadType() & OLFB_FULL_LOAD)) {
|
||||
/* 'Reserve' this cargo for this vehicle, because we were first. */
|
||||
for (; v != NULL; v = v->Next()) {
|
||||
|
@ -1131,7 +1131,7 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
|||
/* The train reversed in the station. Take the "easy" way
|
||||
* out and let the train just leave as it always did. */
|
||||
SetBit(v->vehicle_flags, VF_LOADING_FINISHED);
|
||||
v->time_counter = 1;
|
||||
v->load_unload_ticks = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1364,7 +1364,7 @@ static void LoadUnloadVehicle(Vehicle *v, int *cargo_left)
|
|||
}
|
||||
|
||||
/* Always wait at least 1, otherwise we'll wait 'infinitively' long. */
|
||||
v->time_counter = max(1, unloading_time);
|
||||
v->load_unload_ticks = max(1, unloading_time);
|
||||
|
||||
if (completely_emptied) {
|
||||
TriggerVehicle(v, VEHICLE_TRIGGER_EMPTY);
|
||||
|
|
|
@ -709,8 +709,8 @@ static uint32 VehicleGetVariable(const ResolverObject *object, byte variable, by
|
|||
case 0x0B: return v->current_order.GetDestination();
|
||||
case 0x0C: return v->GetNumOrders();
|
||||
case 0x0D: return v->cur_order_index;
|
||||
case 0x10: return v->time_counter;
|
||||
case 0x11: return GB(v->time_counter, 8, 8);
|
||||
case 0x10: return v->load_unload_ticks;
|
||||
case 0x11: return GB(v->load_unload_ticks, 8, 8);
|
||||
case 0x12: return max(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0);
|
||||
case 0x13: return GB(max(v->date_of_last_service - DAYS_TILL_ORIGINAL_BASE_YEAR, 0), 8, 8);
|
||||
case 0x14: return v->service_interval;
|
||||
|
|
|
@ -1997,6 +1997,19 @@ bool AfterLoadGame()
|
|||
}
|
||||
}
|
||||
|
||||
/* Wait counter and load/unload ticks got split. */
|
||||
if (CheckSavegameVersion(136)) {
|
||||
Aircraft *a;
|
||||
FOR_ALL_AIRCRAFT(a) {
|
||||
a->turn_counter = a->current_order.IsType(OT_LOADING) ? 0 : a->load_unload_ticks;
|
||||
}
|
||||
|
||||
Train *t;
|
||||
FOR_ALL_TRAINS(t) {
|
||||
t->wait_counter = t->current_order.IsType(OT_LOADING) ? 0 : t->load_unload_ticks;
|
||||
}
|
||||
}
|
||||
|
||||
/* Road stops is 'only' updating some caches */
|
||||
AfterLoadRoadStops();
|
||||
AfterLoadLabelMaps();
|
||||
|
|
|
@ -1129,7 +1129,7 @@ static const OldChunks vehicle_chunk[] = {
|
|||
OCL_NULL ( 1 ), ///< num_orders, now calculated
|
||||
OCL_SVAR( OC_UINT8, Vehicle, cur_order_index ),
|
||||
OCL_SVAR( OC_TILE, Vehicle, dest_tile ),
|
||||
OCL_SVAR( OC_UINT16, Vehicle, time_counter ),
|
||||
OCL_SVAR( OC_UINT16, Vehicle, load_unload_ticks ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
|
||||
OCL_SVAR( OC_UINT16, Vehicle, service_interval ),
|
||||
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Vehicle, last_station_visited ),
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
|
||||
#include "saveload_internal.h"
|
||||
|
||||
extern const uint16 SAVEGAME_VERSION = 135;
|
||||
extern const uint16 SAVEGAME_VERSION = 136;
|
||||
|
||||
SavegameType _savegame_type; ///< type of savegame we are loading
|
||||
|
||||
|
|
|
@ -495,7 +495,7 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||
SLE_CONDVAR(Vehicle, build_year, SLE_FILE_U8 | SLE_VAR_I32, 0, 30),
|
||||
SLE_CONDVAR(Vehicle, build_year, SLE_INT32, 31, SL_MAX_VERSION),
|
||||
|
||||
SLE_VAR(Vehicle, time_counter, SLE_UINT16),
|
||||
SLE_VAR(Vehicle, load_unload_ticks, SLE_UINT16),
|
||||
SLEG_CONDVAR( _cargo_paid_for, SLE_UINT16, 45, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, vehicle_flags, SLE_UINT8, 40, SL_MAX_VERSION),
|
||||
|
||||
|
@ -540,6 +540,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||
SLE_CONDVAR(Train, flags, SLE_UINT16, 100, SL_MAX_VERSION),
|
||||
SLE_CONDNULL(2, 2, 59),
|
||||
|
||||
SLE_CONDVAR(Train, wait_counter, SLE_UINT16, 136, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDNULL(2, 2, 19),
|
||||
/* reserve extra space in savegame here. (currently 11 bytes) */
|
||||
SLE_CONDNULL(11, 2, SL_MAX_VERSION),
|
||||
|
@ -593,6 +595,8 @@ const SaveLoad *GetVehicleDescription(VehicleType vt)
|
|||
SLE_CONDVAR(Aircraft, last_direction, SLE_UINT8, 2, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Aircraft, number_consecutive_turns, SLE_UINT8, 2, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Aircraft, turn_counter, SLE_UINT8, 136, SL_MAX_VERSION),
|
||||
|
||||
/* reserve extra space in savegame here. (currently 13 bytes) */
|
||||
SLE_CONDNULL(13, 2, SL_MAX_VERSION),
|
||||
|
||||
|
|
|
@ -114,6 +114,9 @@ struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
|
|||
RailTypeByte railtype;
|
||||
RailTypes compatible_railtypes;
|
||||
|
||||
/** Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through signals. */
|
||||
uint16 wait_counter;
|
||||
|
||||
/** We don't want GCC to zero our struct! It already is zeroed and has an index! */
|
||||
Train() : SpecializedVehicle<Train, VEH_TRAIN>() {}
|
||||
/** We want to 'destruct' the right class. */
|
||||
|
|
|
@ -1614,10 +1614,7 @@ static void MarkTrainAsStuck(Train *v)
|
|||
/* It is the first time the problem occured, set the "train stuck" flag. */
|
||||
SetBit(v->flags, VRF_TRAIN_STUCK);
|
||||
|
||||
/* When loading the vehicle is already stopped. No need to change that. */
|
||||
if (v->current_order.IsType(OT_LOADING)) return;
|
||||
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
|
||||
/* Stop train */
|
||||
v->cur_speed = 0;
|
||||
|
@ -1957,7 +1954,7 @@ static void ReverseTrainDirection(Train *v)
|
|||
} else if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
|
||||
/* A train not inside a PBS block can't be stuck. */
|
||||
ClrBit(v->flags, VRF_TRAIN_STUCK);
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2304,12 +2301,12 @@ static bool CheckTrainStayInDepot(Train *v)
|
|||
|
||||
if (v->force_proceed == 0) {
|
||||
/* force proceed was not pressed */
|
||||
if (++v->time_counter < 37) {
|
||||
if (++v->wait_counter < 37) {
|
||||
SetWindowClassesDirty(WC_TRAINS_LIST);
|
||||
return true;
|
||||
}
|
||||
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
|
||||
seg_state = _settings_game.pf.reserve_paths ? SIGSEG_PBS : UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
|
||||
if (seg_state == SIGSEG_FULL || HasDepotReservation(v->tile)) {
|
||||
|
@ -2914,12 +2911,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
|
|||
}
|
||||
|
||||
if (HasBit(v->flags, VRF_TRAIN_STUCK)) {
|
||||
/* This might be called when a train is loading. At that time the counter
|
||||
* is (mis)used (or rather PBS misuses it) for determining how long to wait
|
||||
* till going to the next load cycle. If that number is set to 0 the wait
|
||||
* for loading will be 65535 ticks, which is not what we want. Actually, We
|
||||
* do not want to reset the waiting period during loading in any case. */
|
||||
if (!v->current_order.IsType(OT_LOADING)) v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
}
|
||||
ClrBit(v->flags, VRF_TRAIN_STUCK);
|
||||
|
@ -3396,12 +3388,12 @@ static void TrainController(Train *v, Vehicle *nomove)
|
|||
v->cur_speed = 0;
|
||||
v->subspeed = 0;
|
||||
v->progress = 255 - 100;
|
||||
if (_settings_game.pf.wait_oneway_signal == 255 || ++v->time_counter < _settings_game.pf.wait_oneway_signal * 20) return;
|
||||
if (_settings_game.pf.wait_oneway_signal == 255 || ++v->wait_counter < _settings_game.pf.wait_oneway_signal * 20) return;
|
||||
} else if (HasSignalOnTrackdir(gp.new_tile, i)) {
|
||||
v->cur_speed = 0;
|
||||
v->subspeed = 0;
|
||||
v->progress = 255 - 10;
|
||||
if (_settings_game.pf.wait_twoway_signal == 255 || ++v->time_counter < _settings_game.pf.wait_twoway_signal * 73) {
|
||||
if (_settings_game.pf.wait_twoway_signal == 255 || ++v->wait_counter < _settings_game.pf.wait_twoway_signal * 73) {
|
||||
DiagDirection exitdir = TrackdirToExitdir(i);
|
||||
TileIndex o_tile = TileAddByDiagDir(gp.new_tile, exitdir);
|
||||
|
||||
|
@ -3415,7 +3407,7 @@ static void TrainController(Train *v, Vehicle *nomove)
|
|||
/* If we would reverse but are currently in a PBS block and
|
||||
* reversing of stuck trains is disabled, don't reverse. */
|
||||
if (_settings_game.pf.wait_for_pbs_path == 255 && UpdateSignalsOnSegment(v->tile, enterdir, v->owner) == SIGSEG_PBS) {
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
return;
|
||||
}
|
||||
goto reverse_train_direction;
|
||||
|
@ -3509,7 +3501,7 @@ static void TrainController(Train *v, Vehicle *nomove)
|
|||
}
|
||||
|
||||
if (v->IsFrontEngine()) {
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
|
||||
/* If we are approching a crossing that is reserved, play the sound now. */
|
||||
TileIndex crossing = TrainApproachingCrossingTile(v);
|
||||
|
@ -3601,7 +3593,7 @@ invalid_rail:
|
|||
if (prev != NULL) error("Disconnecting train");
|
||||
|
||||
reverse_train_direction:
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
v->cur_speed = 0;
|
||||
v->subspeed = 0;
|
||||
ReverseTrainDirection(v);
|
||||
|
@ -3979,7 +3971,7 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
|||
|
||||
bool valid_order = !v->current_order.IsType(OT_NOTHING) && v->current_order.GetType() != OT_CONDITIONAL;
|
||||
if (ProcessOrders(v) && CheckReverseTrain(v)) {
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
v->cur_speed = 0;
|
||||
v->subspeed = 0;
|
||||
ReverseTrainDirection(v);
|
||||
|
@ -4001,17 +3993,17 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
|||
|
||||
/* Handle stuck trains. */
|
||||
if (!mode && HasBit(v->flags, VRF_TRAIN_STUCK)) {
|
||||
++v->time_counter;
|
||||
++v->wait_counter;
|
||||
|
||||
/* Should we try reversing this tick if still stuck? */
|
||||
bool turn_around = v->time_counter % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.wait_for_pbs_path < 255;
|
||||
bool turn_around = v->wait_counter % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.wait_for_pbs_path < 255;
|
||||
|
||||
if (!turn_around && v->time_counter % _settings_game.pf.path_backoff_interval != 0 && v->force_proceed == 0) return true;
|
||||
if (!turn_around && v->wait_counter % _settings_game.pf.path_backoff_interval != 0 && v->force_proceed == 0) return true;
|
||||
if (!TryPathReserve(v)) {
|
||||
/* Still stuck. */
|
||||
if (turn_around) ReverseTrainDirection(v);
|
||||
|
||||
if (HasBit(v->flags, VRF_TRAIN_STUCK) && v->time_counter > 2 * _settings_game.pf.wait_for_pbs_path * DAY_TICKS) {
|
||||
if (HasBit(v->flags, VRF_TRAIN_STUCK) && v->wait_counter > 2 * _settings_game.pf.wait_for_pbs_path * DAY_TICKS) {
|
||||
/* Show message to player. */
|
||||
if (_settings_client.gui.lost_train_warn && v->owner == _local_company) {
|
||||
SetDParam(0, v->index);
|
||||
|
@ -4021,12 +4013,12 @@ static bool TrainLocoHandler(Train *v, bool mode)
|
|||
v->index
|
||||
);
|
||||
}
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
}
|
||||
/* Exit if force proceed not pressed, else reset stuck flag anyway. */
|
||||
if (v->force_proceed == 0) return true;
|
||||
ClrBit(v->flags, VRF_TRAIN_STUCK);
|
||||
v->time_counter = 0;
|
||||
v->wait_counter = 0;
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -998,7 +998,7 @@ void VehicleEnterDepot(Vehicle *v)
|
|||
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(t->tile);
|
||||
|
||||
UpdateSignalsOnSegment(t->tile, INVALID_DIAGDIR, t->owner);
|
||||
t->time_counter = 0;
|
||||
t->wait_counter = 0;
|
||||
ClrBit(t->flags, VRF_TOGGLE_REVERSE);
|
||||
TrainConsistChanged(t, true);
|
||||
break;
|
||||
|
|
|
@ -184,13 +184,8 @@ public:
|
|||
|
||||
byte vehicle_flags; ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)
|
||||
|
||||
/**
|
||||
* Multi purpose variable used as counter for:
|
||||
* - loading/unloading: ticks to wait before starting next cycle.
|
||||
* - aircraft: ticks between each turn to prevent > 45 degree turns.
|
||||
* - trains: ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through signals.
|
||||
*/
|
||||
uint16 time_counter;
|
||||
/** Ticks to wait before starting next cycle. */
|
||||
uint16 load_unload_ticks;
|
||||
|
||||
GroupID group_id; ///< Index of group Pool array
|
||||
|
||||
|
|
Loading…
Reference in New Issue