Add freight train load/unload mode: through load
This commit is contained in:
@@ -295,7 +295,7 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5],
|
|||||||
status = D_CANCELLED;
|
status = D_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*v)->current_order.IsType(OT_LOADING)) {
|
if ((*v)->current_order.IsAnyLoadingType()) {
|
||||||
/* Account for the vehicle having reached the current order and being in the loading phase. */
|
/* Account for the vehicle having reached the current order and being in the loading phase. */
|
||||||
status = D_ARRIVED;
|
status = D_ARRIVED;
|
||||||
start_date -= order->GetTravelTime() + (((*v)->lateness_counter < 0) ? (*v)->lateness_counter : 0);
|
start_date -= order->GetTravelTime() + (((*v)->lateness_counter < 0) ? (*v)->lateness_counter : 0);
|
||||||
@@ -381,7 +381,7 @@ DepartureList* MakeDepartureList(StationID station, bool show_vehicle_types[5],
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
|
/* If we are early, use the scheduled date as the expected date. We also take lateness to be zero. */
|
||||||
if (!should_reset_lateness && (*v)->lateness_counter < 0 && !(*v)->current_order.IsType(OT_LOADING)) {
|
if (!should_reset_lateness && (*v)->lateness_counter < 0 && !(*v)->current_order.IsAnyLoadingType()) {
|
||||||
od->expected_date -= (*v)->lateness_counter;
|
od->expected_date -= (*v)->lateness_counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1646,12 +1646,13 @@ static void ReserveConsist(Station *st, Vehicle *u, CargoArray *consist_capleft,
|
|||||||
* @param front The vehicle to be updated.
|
* @param front The vehicle to be updated.
|
||||||
* @param st The station the vehicle is loading at.
|
* @param st The station the vehicle is loading at.
|
||||||
* @param ticks The time it would normally wait, based on cargo loaded and unloaded.
|
* @param ticks The time it would normally wait, based on cargo loaded and unloaded.
|
||||||
|
* @param platform_length_left Platform length left, negative values indicate train is overhanging platform
|
||||||
*/
|
*/
|
||||||
static void UpdateLoadUnloadTicks(Vehicle *front, const Station *st, int ticks)
|
static void UpdateLoadUnloadTicks(Vehicle *front, const Station *st, int ticks, int platform_length_left)
|
||||||
{
|
{
|
||||||
if (front->type == VEH_TRAIN) {
|
if (front->type == VEH_TRAIN) {
|
||||||
/* Each platform tile is worth 2 rail vehicles. */
|
/* Each platform tile is worth 2 rail vehicles. */
|
||||||
int overhang = front->GetGroundVehicleCache()->cached_total_length - st->GetPlatformLength(front->tile) * TILE_SIZE;
|
int overhang = -platform_length_left;
|
||||||
if (overhang > 0) {
|
if (overhang > 0) {
|
||||||
ticks <<= 1;
|
ticks <<= 1;
|
||||||
ticks += (overhang * ticks) / 8;
|
ticks += (overhang * ticks) / 8;
|
||||||
@@ -1672,13 +1673,39 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
StationID last_visited = front->last_station_visited;
|
StationID last_visited = front->last_station_visited;
|
||||||
Station *st = Station::Get(last_visited);
|
Station *st = Station::Get(last_visited);
|
||||||
|
|
||||||
|
TileIndex station_tile = front->tile;
|
||||||
|
if (front->type == VEH_TRAIN) station_tile = Train::From(front)->GetStationLoadingVehicle()->tile;
|
||||||
|
|
||||||
|
bool pull_through_mode = false;
|
||||||
|
bool load_unload_not_yet_in_station = false;
|
||||||
|
if (front->type == VEH_TRAIN && front->cur_real_order_index < front->GetNumOrders()) {
|
||||||
|
Order *order = front->GetOrder(front->cur_real_order_index);
|
||||||
|
if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == last_visited &&
|
||||||
|
order->GetStopLocation() == OSL_PLATFORM_THROUGH) {
|
||||||
|
pull_through_mode = true;
|
||||||
|
for (Vehicle *v = front; v != NULL; v = v->Next()) {
|
||||||
|
/* Passengers may not be through-loaded */
|
||||||
|
if (v->cargo_cap > 0 && IsCargoInClass(v->cargo_type, CC_PASSENGERS)) {
|
||||||
|
pull_through_mode = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int platform_length_left = 0;
|
||||||
|
if (pull_through_mode) {
|
||||||
|
platform_length_left = st->GetPlatformLength(station_tile) * TILE_SIZE;
|
||||||
|
} else if (front->type == VEH_TRAIN) {
|
||||||
|
platform_length_left = st->GetPlatformLength(station_tile) * TILE_SIZE - front->GetGroundVehicleCache()->cached_total_length;
|
||||||
|
}
|
||||||
|
|
||||||
CargoStationIDStackSet next_station = front->GetNextStoppingStation();
|
CargoStationIDStackSet next_station = front->GetNextStoppingStation();
|
||||||
|
|
||||||
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
|
bool use_autorefit = front->current_order.IsRefit() && front->current_order.GetRefitCargo() == CT_AUTO_REFIT;
|
||||||
CargoArray consist_capleft;
|
CargoArray consist_capleft;
|
||||||
bool should_reserve_consist = false;
|
bool should_reserve_consist = false;
|
||||||
bool reserve_consist_cargo_type_loading = false;
|
bool reserve_consist_cargo_type_loading = false;
|
||||||
if (_settings_game.order.improved_load && use_autorefit) {
|
if ((_settings_game.order.improved_load && use_autorefit) || pull_through_mode) {
|
||||||
if (front->cargo_payment == NULL) should_reserve_consist = true;
|
if (front->cargo_payment == NULL) should_reserve_consist = true;
|
||||||
} else {
|
} else {
|
||||||
if ((front->current_order.GetLoadType() & OLFB_FULL_LOAD) || (front->current_order.GetLoadType() == OLFB_CARGO_TYPE_LOAD)) {
|
if ((front->current_order.GetLoadType() & OLFB_FULL_LOAD) || (front->current_order.GetLoadType() == OLFB_CARGO_TYPE_LOAD)) {
|
||||||
@@ -1696,7 +1723,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
/* We have not waited enough time till the next round of loading/unloading */
|
/* We have not waited enough time till the next round of loading/unloading */
|
||||||
if (front->load_unload_ticks != 0) return;
|
if (front->load_unload_ticks != 0) return;
|
||||||
|
|
||||||
if (front->type == VEH_TRAIN && (!IsTileType(front->tile, MP_STATION) || GetStationIndex(front->tile) != st->index)) {
|
if (front->type == VEH_TRAIN && (!IsTileType(station_tile, MP_STATION) || GetStationIndex(station_tile) != st->index)) {
|
||||||
/* The train reversed in the station. Take the "easy" way
|
/* The train reversed in the station. Take the "easy" way
|
||||||
* out and let the train just leave as it always did. */
|
* out and let the train just leave as it always did. */
|
||||||
SetBit(front->vehicle_flags, VF_LOADING_FINISHED);
|
SetBit(front->vehicle_flags, VF_LOADING_FINISHED);
|
||||||
@@ -1722,6 +1749,25 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
|
|
||||||
uint artic_part = 0; // Articulated part we are currently trying to load. (not counting parts without capacity)
|
uint artic_part = 0; // Articulated part we are currently trying to load. (not counting parts without capacity)
|
||||||
for (Vehicle *v = front; v != NULL; v = v->Next()) {
|
for (Vehicle *v = front; v != NULL; v = v->Next()) {
|
||||||
|
if (pull_through_mode && HasBit(Train::From(v)->flags, VRF_BEYOND_PLATFORM_END)) continue;
|
||||||
|
if (pull_through_mode && !v->IsArticulatedPart()) {
|
||||||
|
int length = Train::From(v)->gcache.cached_veh_length;
|
||||||
|
Vehicle *u = v;
|
||||||
|
while (u->HasArticulatedPart()) {
|
||||||
|
u = u->GetNextArticulatedPart();
|
||||||
|
length += Train::From(u)->gcache.cached_veh_length;
|
||||||
|
}
|
||||||
|
if (v != front && !HasBit(Train::From(v->Previous())->flags, VRF_BEYOND_PLATFORM_END) && length > platform_length_left) {
|
||||||
|
for (Vehicle *skip = v; skip != NULL; skip = skip->Next()) {
|
||||||
|
SetBit(Train::From(skip)->flags, VRF_NOT_YET_IN_PLATFORM);
|
||||||
|
if (skip->cargo.ReservedCount() || skip->cargo.UnloadCount()) {
|
||||||
|
load_unload_not_yet_in_station = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // articulated vehicle won't fit in platform, no loading
|
||||||
|
}
|
||||||
|
platform_length_left -= length;
|
||||||
|
}
|
||||||
if (v == front || !v->Previous()->HasArticulatedPart()) artic_part = 0;
|
if (v == front || !v->Previous()->HasArticulatedPart()) artic_part = 0;
|
||||||
if (v->cargo_cap == 0) continue;
|
if (v->cargo_cap == 0) continue;
|
||||||
artic_part++;
|
artic_part++;
|
||||||
@@ -1895,7 +1941,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
/* Only set completely_emptied, if we just unloaded all remaining cargo */
|
/* Only set completely_emptied, if we just unloaded all remaining cargo */
|
||||||
completely_emptied &= anything_unloaded;
|
completely_emptied &= anything_unloaded;
|
||||||
|
|
||||||
if (!anything_unloaded) delete payment;
|
if (!anything_unloaded && !load_unload_not_yet_in_station) delete payment;
|
||||||
|
|
||||||
ClrBit(front->vehicle_flags, VF_STOP_LOADING);
|
ClrBit(front->vehicle_flags, VF_STOP_LOADING);
|
||||||
|
|
||||||
@@ -1923,9 +1969,9 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
SetBit(front->vehicle_flags, VF_STOP_LOADING);
|
SetBit(front->vehicle_flags, VF_STOP_LOADING);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateLoadUnloadTicks(front, st, new_load_unload_ticks);
|
UpdateLoadUnloadTicks(front, st, new_load_unload_ticks, platform_length_left);
|
||||||
} else {
|
} else {
|
||||||
UpdateLoadUnloadTicks(front, st, 20); // We need the ticks for link refreshing.
|
UpdateLoadUnloadTicks(front, st, 20, platform_length_left); // We need the ticks for link refreshing.
|
||||||
bool finished_loading = true;
|
bool finished_loading = true;
|
||||||
if (has_full_load_order) {
|
if (has_full_load_order) {
|
||||||
if (front->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
|
if (front->current_order.GetLoadType() == OLF_FULL_LOAD_ANY) {
|
||||||
@@ -1938,15 +1984,20 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
} else if (cargo_not_full != 0) {
|
} else if (cargo_not_full != 0) {
|
||||||
finished_loading = false;
|
finished_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Refresh next hop stats if we're full loading to make the links
|
|
||||||
* known to the distribution algorithm and allow cargo to be sent
|
|
||||||
* along them. Otherwise the vehicle could wait for cargo
|
|
||||||
* indefinitely if it hasn't visited the other links yet, or if the
|
|
||||||
* links die while it's loading. */
|
|
||||||
if (!finished_loading) LinkRefresher::Run(front, true, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pull_through_mode && (front->current_order.IsRefit() || load_unload_not_yet_in_station)) {
|
||||||
|
finished_loading = false;
|
||||||
|
SetBit(Train::From(front)->flags, VRF_ADVANCE_IN_PLATFORM);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Refresh next hop stats if we're full loading to make the links
|
||||||
|
* known to the distribution algorithm and allow cargo to be sent
|
||||||
|
* along them. Otherwise the vehicle could wait for cargo
|
||||||
|
* indefinitely if it hasn't visited the other links yet, or if the
|
||||||
|
* links die while it's loading. */
|
||||||
|
if (!finished_loading) LinkRefresher::Run(front, true, true);
|
||||||
|
|
||||||
SB(front->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
|
SB(front->vehicle_flags, VF_LOADING_FINISHED, 1, finished_loading);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1956,7 +2007,8 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||||||
* if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
|
* if _settings_client.gui.loading_indicators == 1, _local_company must be the owner or must be a spectator to show ind., so 1 > 0
|
||||||
* if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
|
* if _settings_client.gui.loading_indicators == 0, do not display indicators ... 0 is never greater than anything
|
||||||
*/
|
*/
|
||||||
if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(front->owner != _local_company && _local_company != COMPANY_SPECTATOR))) {
|
if (_game_mode != GM_MENU && (_settings_client.gui.loading_indicators > (uint)(front->owner != _local_company && _local_company != COMPANY_SPECTATOR))
|
||||||
|
&& !front->current_order.IsType(OT_LOADING_ADVANCE)) {
|
||||||
StringID percent_up_down = STR_NULL;
|
StringID percent_up_down = STR_NULL;
|
||||||
int percent = CalcPercentVehicleFilled(front, &percent_up_down);
|
int percent = CalcPercentVehicleFilled(front, &percent_up_down);
|
||||||
if (front->fill_percent_te_id == INVALID_TE_ID) {
|
if (front->fill_percent_te_id == INVALID_TE_ID) {
|
||||||
@@ -1999,7 +2051,7 @@ void LoadUnloadStation(Station *st)
|
|||||||
|
|
||||||
/* Check if anything will be loaded at all. Otherwise we don't need to reserve either. */
|
/* Check if anything will be loaded at all. Otherwise we don't need to reserve either. */
|
||||||
for (Vehicle *v : st->loading_vehicles) {
|
for (Vehicle *v : st->loading_vehicles) {
|
||||||
if ((v->vehstatus & (VS_STOPPED | VS_CRASHED))) continue;
|
if ((v->vehstatus & (VS_STOPPED | VS_CRASHED)) || v->current_order.IsType(OT_LOADING_ADVANCE)) continue;
|
||||||
|
|
||||||
assert(v->load_unload_ticks != 0);
|
assert(v->load_unload_ticks != 0);
|
||||||
if (--v->load_unload_ticks == 0) last_loading = v;
|
if (--v->load_unload_ticks == 0) last_loading = v;
|
||||||
@@ -2015,7 +2067,7 @@ void LoadUnloadStation(Station *st)
|
|||||||
if (last_loading == NULL) return;
|
if (last_loading == NULL) return;
|
||||||
|
|
||||||
for (Vehicle *v : st->loading_vehicles) {
|
for (Vehicle *v : st->loading_vehicles) {
|
||||||
if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED))) LoadUnloadVehicle(v);
|
if (!(v->vehstatus & (VS_STOPPED | VS_CRASHED)) && !v->current_order.IsType(OT_LOADING_ADVANCE)) LoadUnloadVehicle(v);
|
||||||
if (v == last_loading) break;
|
if (v == last_loading) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -418,6 +418,8 @@ protected:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->current_order.IsType(OT_LOADING_ADVANCE)) tempmax = min(tempmax, 15);
|
||||||
|
|
||||||
if (this->cur_speed > max_speed) {
|
if (this->cur_speed > max_speed) {
|
||||||
tempmax = max(this->cur_speed - (this->cur_speed / 10) - 1, max_speed);
|
tempmax = max(this->cur_speed - (this->cur_speed / 10) - 1, max_speed);
|
||||||
}
|
}
|
||||||
|
@@ -147,6 +147,7 @@ static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owne
|
|||||||
case OT_GOTO_STATION:
|
case OT_GOTO_STATION:
|
||||||
case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
|
case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
|
||||||
case OT_GOTO_DEPOT: dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
|
case OT_GOTO_DEPOT: dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
|
||||||
|
case OT_LOADING_ADVANCE:
|
||||||
case OT_LOADING: dest_owner = Station::Get(v->last_station_visited)->owner; break;
|
case OT_LOADING: dest_owner = Station::Get(v->last_station_visited)->owner; break;
|
||||||
default: return true;
|
default: return true;
|
||||||
}
|
}
|
||||||
@@ -290,7 +291,7 @@ void HandleSharingCompanyDeletion(Owner owner)
|
|||||||
}
|
}
|
||||||
/* current order */
|
/* current order */
|
||||||
if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
|
if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
|
||||||
if (v->current_order.IsType(OT_LOADING)) {
|
if (v->current_order.IsAnyLoadingType()) {
|
||||||
v->LeaveStation();
|
v->LeaveStation();
|
||||||
} else {
|
} else {
|
||||||
v->current_order.MakeDummy();
|
v->current_order.MakeDummy();
|
||||||
|
@@ -4223,6 +4223,7 @@ STR_VEHICLE_VIEW_AIRCRAFT_STATE_START_STOP_TOOLTIP :{BLACK}Current
|
|||||||
|
|
||||||
# Messages in the start stop button in the vehicle view
|
# Messages in the start stop button in the vehicle view
|
||||||
STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Loading / Unloading
|
STR_VEHICLE_STATUS_LOADING_UNLOADING :{LTBLUE}Loading / Unloading
|
||||||
|
STR_VEHICLE_STATUS_LOADING_UNLOADING_ADVANCE :{STRING}, {VELOCITY}
|
||||||
STR_VEHICLE_STATUS_LEAVING :{LTBLUE}Leaving
|
STR_VEHICLE_STATUS_LEAVING :{LTBLUE}Leaving
|
||||||
STR_VEHICLE_STATUS_CRASHED :{RED}Crashed!
|
STR_VEHICLE_STATUS_CRASHED :{RED}Crashed!
|
||||||
STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Broken down
|
STR_VEHICLE_STATUS_BROKEN_DOWN :{RED}Broken down
|
||||||
@@ -4561,6 +4562,7 @@ STR_ORDER_AUTO_REFIT_ANY :available cargo
|
|||||||
STR_ORDER_STOP_LOCATION_NEAR_END :[near end]
|
STR_ORDER_STOP_LOCATION_NEAR_END :[near end]
|
||||||
STR_ORDER_STOP_LOCATION_MIDDLE :[middle]
|
STR_ORDER_STOP_LOCATION_MIDDLE :[middle]
|
||||||
STR_ORDER_STOP_LOCATION_FAR_END :[far end]
|
STR_ORDER_STOP_LOCATION_FAR_END :[far end]
|
||||||
|
STR_ORDER_STOP_LOCATION_THROUGH :[through load]
|
||||||
|
|
||||||
STR_ORDER_OUT_OF_RANGE :{RED} (Next destination is out of range)
|
STR_ORDER_OUT_OF_RANGE :{RED} (Next destination is out of range)
|
||||||
|
|
||||||
|
@@ -114,6 +114,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline bool IsType(OrderType type) const { return this->GetType() == type; }
|
inline bool IsType(OrderType type) const { return this->GetType() == type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this order is either of OT_LOADING or OT_LOADING_ADVANCE.
|
||||||
|
* @return true if the order matches.
|
||||||
|
*/
|
||||||
|
inline bool IsAnyLoadingType() const { return this->GetType() == OT_LOADING || this->GetType() == OT_LOADING_ADVANCE; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the type of order of this order.
|
* Get the type of order of this order.
|
||||||
* @return the order type.
|
* @return the order type.
|
||||||
@@ -131,6 +137,7 @@ public:
|
|||||||
void MakeConditional(VehicleOrderID order);
|
void MakeConditional(VehicleOrderID order);
|
||||||
void MakeImplicit(StationID destination);
|
void MakeImplicit(StationID destination);
|
||||||
void MakeWaiting();
|
void MakeWaiting();
|
||||||
|
void MakeLoadingAdvance(StationID destination);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a 'goto' order with a real destination?
|
* Is this a 'goto' order with a real destination?
|
||||||
|
@@ -193,6 +193,12 @@ void Order::MakeWaiting()
|
|||||||
this->type = OT_WAITING;
|
this->type = OT_WAITING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Order::MakeLoadingAdvance(StationID destination)
|
||||||
|
{
|
||||||
|
this->type = OT_LOADING_ADVANCE;
|
||||||
|
this->dest = destination;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make this depot/station order also a refit order.
|
* Make this depot/station order also a refit order.
|
||||||
* @param cargo the cargo type to change to.
|
* @param cargo the cargo type to change to.
|
||||||
@@ -898,6 +904,7 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
switch (new_order.GetStopLocation()) {
|
switch (new_order.GetStopLocation()) {
|
||||||
case OSL_PLATFORM_NEAR_END:
|
case OSL_PLATFORM_NEAR_END:
|
||||||
case OSL_PLATFORM_MIDDLE:
|
case OSL_PLATFORM_MIDDLE:
|
||||||
|
case OSL_PLATFORM_THROUGH:
|
||||||
if (v->type != VEH_TRAIN) return CMD_ERROR;
|
if (v->type != VEH_TRAIN) return CMD_ERROR;
|
||||||
FALLTHROUGH;
|
FALLTHROUGH;
|
||||||
|
|
||||||
@@ -1232,6 +1239,11 @@ CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
*/
|
*/
|
||||||
static void CancelLoadingDueToDeletedOrder(Vehicle *v)
|
static void CancelLoadingDueToDeletedOrder(Vehicle *v)
|
||||||
{
|
{
|
||||||
|
if (v->current_order.IsType(OT_LOADING_ADVANCE)) {
|
||||||
|
SetBit(v->vehicle_flags, VF_LOADING_FINISHED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
assert(v->current_order.IsType(OT_LOADING));
|
assert(v->current_order.IsType(OT_LOADING));
|
||||||
/* NON-stop flag is misused to see if a train is in a station that is
|
/* NON-stop flag is misused to see if a train is in a station that is
|
||||||
* on his order list or not */
|
* on his order list or not */
|
||||||
@@ -1255,7 +1267,7 @@ void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
|
|||||||
for (; u != NULL; u = u->NextShared()) {
|
for (; u != NULL; u = u->NextShared()) {
|
||||||
assert(v->orders.list == u->orders.list);
|
assert(v->orders.list == u->orders.list);
|
||||||
|
|
||||||
if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
|
if (sel_ord == u->cur_real_order_index && u->current_order.IsAnyLoadingType()) {
|
||||||
CancelLoadingDueToDeletedOrder(u);
|
CancelLoadingDueToDeletedOrder(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1332,7 +1344,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
if (ret.Failed()) return ret;
|
if (ret.Failed()) return ret;
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
|
if (v->current_order.IsAnyLoadingType()) v->LeaveStation();
|
||||||
if (v->current_order.IsType(OT_WAITING)) v->HandleWaiting(true);
|
if (v->current_order.IsType(OT_WAITING)) v->HandleWaiting(true);
|
||||||
|
|
||||||
v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
|
v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
|
||||||
@@ -1741,7 +1753,7 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||||||
* when this function is called.
|
* when this function is called.
|
||||||
*/
|
*/
|
||||||
if (sel_ord == u->cur_real_order_index &&
|
if (sel_ord == u->cur_real_order_index &&
|
||||||
(u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
|
(u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsAnyLoadingType()) &&
|
||||||
u->current_order.GetLoadType() != order->GetLoadType()) {
|
u->current_order.GetLoadType() != order->GetLoadType()) {
|
||||||
u->current_order.SetLoadType(order->GetLoadType());
|
u->current_order.SetLoadType(order->GetLoadType());
|
||||||
}
|
}
|
||||||
@@ -2214,7 +2226,7 @@ void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indic
|
|||||||
if (reset_order_indices) {
|
if (reset_order_indices) {
|
||||||
v->cur_implicit_order_index = v->cur_real_order_index = 0;
|
v->cur_implicit_order_index = v->cur_real_order_index = 0;
|
||||||
v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
|
v->cur_timetable_order_index = INVALID_VEH_ORDER_ID;
|
||||||
if (v->current_order.IsType(OT_LOADING)) {
|
if (v->current_order.IsAnyLoadingType()) {
|
||||||
CancelLoadingDueToDeletedOrder(v);
|
CancelLoadingDueToDeletedOrder(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2512,6 +2524,9 @@ bool ProcessOrders(Vehicle *v)
|
|||||||
case OT_LOADING:
|
case OT_LOADING:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
case OT_LOADING_ADVANCE:
|
||||||
|
return false;
|
||||||
|
|
||||||
case OT_WAITING:
|
case OT_WAITING:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -2605,6 +2620,7 @@ bool ProcessOrders(Vehicle *v)
|
|||||||
*/
|
*/
|
||||||
bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
|
bool Order::ShouldStopAtStation(const Vehicle *v, StationID station) const
|
||||||
{
|
{
|
||||||
|
if (this->IsType(OT_LOADING_ADVANCE) && this->dest == station) return true;
|
||||||
bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
|
bool is_dest_station = this->IsType(OT_GOTO_STATION) && this->dest == station;
|
||||||
|
|
||||||
return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
|
return (!this->IsType(OT_GOTO_DEPOT) || (this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0) &&
|
||||||
|
@@ -1849,8 +1849,18 @@ public:
|
|||||||
this->selected_order = -1;
|
this->selected_order = -1;
|
||||||
} else if (sel == this->selected_order) {
|
} else if (sel == this->selected_order) {
|
||||||
if (this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
|
if (this->vehicle->type == VEH_TRAIN && sel < this->vehicle->GetNumOrders()) {
|
||||||
|
int osl = ((this->vehicle->GetOrder(sel)->GetStopLocation() + 1) % OSL_END);
|
||||||
|
if (osl == OSL_PLATFORM_THROUGH) {
|
||||||
|
for (const Vehicle *u = this->vehicle; u != NULL; u = u->Next()) {
|
||||||
|
/* Passengers may not be through-loaded */
|
||||||
|
if (u->cargo_cap > 0 && IsCargoInClass(u->cargo_type, CC_PASSENGERS)) {
|
||||||
|
osl = OSL_PLATFORM_NEAR_END;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
DoCommandP(this->vehicle->tile, this->vehicle->index + (sel << 20),
|
DoCommandP(this->vehicle->tile, this->vehicle->index + (sel << 20),
|
||||||
MOF_STOP_LOCATION | ((this->vehicle->GetOrder(sel)->GetStopLocation() + 1) % OSL_END) << 4,
|
MOF_STOP_LOCATION | osl << 4,
|
||||||
CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
|
CMD_MODIFY_ORDER | CMD_MSG(STR_ERROR_CAN_T_MODIFY_THIS_ORDER));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -46,6 +46,7 @@ enum OrderType {
|
|||||||
OT_CONDITIONAL = 7,
|
OT_CONDITIONAL = 7,
|
||||||
OT_IMPLICIT = 8,
|
OT_IMPLICIT = 8,
|
||||||
OT_WAITING = 9,
|
OT_WAITING = 9,
|
||||||
|
OT_LOADING_ADVANCE = 10,
|
||||||
OT_END
|
OT_END
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,6 +96,7 @@ enum OrderStopLocation {
|
|||||||
OSL_PLATFORM_NEAR_END = 0, ///< Stop at the near end of the platform
|
OSL_PLATFORM_NEAR_END = 0, ///< Stop at the near end of the platform
|
||||||
OSL_PLATFORM_MIDDLE = 1, ///< Stop at the middle of the platform
|
OSL_PLATFORM_MIDDLE = 1, ///< Stop at the middle of the platform
|
||||||
OSL_PLATFORM_FAR_END = 2, ///< Stop at the far end of the platform
|
OSL_PLATFORM_FAR_END = 2, ///< Stop at the far end of the platform
|
||||||
|
OSL_PLATFORM_THROUGH = 3, ///< Load/unload through the platform
|
||||||
OSL_END
|
OSL_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -3180,6 +3180,8 @@ static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int
|
|||||||
/* this routine applies only to trains in depot tiles */
|
/* this routine applies only to trains in depot tiles */
|
||||||
if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE;
|
if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE;
|
||||||
|
|
||||||
|
if (u->current_order.IsType(OT_LOADING_ADVANCE)) u->LeaveStation();
|
||||||
|
|
||||||
Train *v = Train::From(u);
|
Train *v = Train::From(u);
|
||||||
|
|
||||||
/* depot direction */
|
/* depot direction */
|
||||||
|
@@ -81,6 +81,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 1, 1, "multiple_docks", NULL, NULL, "DOCK" },
|
{ XSLFI_MULTIPLE_DOCKS, XSCF_NULL, 1, 1, "multiple_docks", NULL, NULL, "DOCK" },
|
||||||
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 1, 1, "timetable_extra", NULL, NULL, "ORDX" },
|
{ XSLFI_TIMETABLE_EXTRA, XSCF_NULL, 1, 1, "timetable_extra", NULL, NULL, "ORDX" },
|
||||||
{ XSLFI_TRAIN_FLAGS_EXTRA, XSCF_NULL, 1, 1, "train_flags_extra", NULL, NULL, NULL },
|
{ XSLFI_TRAIN_FLAGS_EXTRA, XSCF_NULL, 1, 1, "train_flags_extra", NULL, NULL, NULL },
|
||||||
|
{ XSLFI_TRAIN_THROUGH_LOAD, XSCF_NULL, 1, 1, "train_through_load", NULL, NULL, NULL },
|
||||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker
|
{ XSLFI_NULL, XSCF_NULL, 0, 0, NULL, NULL, NULL, NULL },// This is the end marker
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -55,6 +55,7 @@ enum SlXvFeatureIndex {
|
|||||||
XSLFI_MULTIPLE_DOCKS, ///< Multiple docks
|
XSLFI_MULTIPLE_DOCKS, ///< Multiple docks
|
||||||
XSLFI_TIMETABLE_EXTRA, ///< Vehicle timetable extra fields
|
XSLFI_TIMETABLE_EXTRA, ///< Vehicle timetable extra fields
|
||||||
XSLFI_TRAIN_FLAGS_EXTRA, ///< Train flags field extra size
|
XSLFI_TRAIN_FLAGS_EXTRA, ///< Train flags field extra size
|
||||||
|
XSLFI_TRAIN_THROUGH_LOAD, ///< Train through load/unload
|
||||||
|
|
||||||
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
||||||
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk
|
XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk
|
||||||
|
@@ -328,7 +328,7 @@
|
|||||||
if (v->breakdown_ctr != 0) return ScriptVehicle::VS_BROKEN;
|
if (v->breakdown_ctr != 0) return ScriptVehicle::VS_BROKEN;
|
||||||
if (v->IsStoppedInDepot()) return ScriptVehicle::VS_IN_DEPOT;
|
if (v->IsStoppedInDepot()) return ScriptVehicle::VS_IN_DEPOT;
|
||||||
if (vehstatus & ::VS_STOPPED) return ScriptVehicle::VS_STOPPED;
|
if (vehstatus & ::VS_STOPPED) return ScriptVehicle::VS_STOPPED;
|
||||||
if (v->current_order.IsType(OT_LOADING)) return ScriptVehicle::VS_AT_STATION;
|
if (v->current_order.IsAnyLoadingType()) return ScriptVehicle::VS_AT_STATION;
|
||||||
return ScriptVehicle::VS_RUNNING;
|
return ScriptVehicle::VS_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3300,8 +3300,12 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
|
|||||||
// reverse at waypoint
|
// reverse at waypoint
|
||||||
if (t->reverse_distance == 0) t->reverse_distance = t->gcache.cached_total_length;
|
if (t->reverse_distance == 0) t->reverse_distance = t->gcache.cached_total_length;
|
||||||
}
|
}
|
||||||
if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
|
if (HasBit(Train::From(v)->flags, VRF_BEYOND_PLATFORM_END)) return VETSB_CONTINUE;
|
||||||
if (!IsRailStation(tile) || !v->IsFrontEngine()) return VETSB_CONTINUE;
|
Train *front = Train::From(v)->First();
|
||||||
|
if (!front->IsFrontEngine()) return VETSB_CONTINUE;
|
||||||
|
if (!(v == front || HasBit(Train::From(v)->Previous()->flags, VRF_BEYOND_PLATFORM_END))) return VETSB_CONTINUE;
|
||||||
|
if (!IsRailStation(tile)) return VETSB_CONTINUE;
|
||||||
|
if (!front->current_order.ShouldStopAtStation(front, station_id)) return VETSB_CONTINUE;
|
||||||
|
|
||||||
int station_ahead;
|
int station_ahead;
|
||||||
int station_length;
|
int station_length;
|
||||||
@@ -3326,9 +3330,9 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
|
|||||||
if (x == stop) {
|
if (x == stop) {
|
||||||
return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); // enter station
|
return VETSB_ENTERED_STATION | (VehicleEnterTileStatus)(station_id << VETS_STATION_ID_OFFSET); // enter station
|
||||||
} else if (x < stop) {
|
} else if (x < stop) {
|
||||||
v->vehstatus |= VS_TRAIN_SLOWING;
|
front->vehstatus |= VS_TRAIN_SLOWING;
|
||||||
uint16 spd = max(0, (stop - x) * 20 - 15);
|
uint16 spd = max(0, (stop - x) * 20 - 15);
|
||||||
if (spd < v->cur_speed) v->cur_speed = spd;
|
if (spd < front->cur_speed) front->cur_speed = spd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (v->type == VEH_ROAD) {
|
} else if (v->type == VEH_ROAD) {
|
||||||
|
@@ -292,8 +292,8 @@ static int CDECL VehicleTimetableSorter(Vehicle * const *ap, Vehicle * const *bp
|
|||||||
int j = (int)b_order - (int)a_order;
|
int j = (int)b_order - (int)a_order;
|
||||||
|
|
||||||
/* Are we currently at an ordered station (un)loading? */
|
/* Are we currently at an ordered station (un)loading? */
|
||||||
bool a_load = a->current_order.IsType(OT_LOADING) && a->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
|
bool a_load = (a->current_order.IsType(OT_LOADING) && a->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) || a->current_order.IsType(OT_LOADING_ADVANCE);
|
||||||
bool b_load = b->current_order.IsType(OT_LOADING) && b->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE;
|
bool b_load = (b->current_order.IsType(OT_LOADING) && b->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) || b->current_order.IsType(OT_LOADING_ADVANCE);
|
||||||
|
|
||||||
/* If the current order is not loading at the ordered station, decrease the order index by one since we have
|
/* If the current order is not loading at the ordered station, decrease the order index by one since we have
|
||||||
* not yet arrived at the station (and thus the timetable entry; still in the travelling of the previous one).
|
* not yet arrived at the station (and thus the timetable entry; still in the travelling of the previous one).
|
||||||
|
@@ -215,7 +215,7 @@ struct TimetableWindow : Window {
|
|||||||
{
|
{
|
||||||
assert(HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED));
|
assert(HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED));
|
||||||
|
|
||||||
bool travelling = (!(v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_WAITING)) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE);
|
bool travelling = (!(v->current_order.IsAnyLoadingType() || v->current_order.IsType(OT_WAITING)) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE);
|
||||||
Ticks start_time = -v->current_order_time;
|
Ticks start_time = -v->current_order_time;
|
||||||
if (v->cur_timetable_order_index != INVALID_VEH_ORDER_ID && v->cur_timetable_order_index != v->cur_real_order_index) {
|
if (v->cur_timetable_order_index != INVALID_VEH_ORDER_ID && v->cur_timetable_order_index != v->cur_real_order_index) {
|
||||||
/* vehicle is taking a conditional order branch, adjust start time to compensate */
|
/* vehicle is taking a conditional order branch, adjust start time to compensate */
|
||||||
|
17
src/train.h
17
src/train.h
@@ -41,6 +41,9 @@ enum VehicleRailFlags {
|
|||||||
VRF_BREAKDOWN_STOPPED = 13,///< used to mark a train that is stopped because of a breakdown
|
VRF_BREAKDOWN_STOPPED = 13,///< used to mark a train that is stopped because of a breakdown
|
||||||
VRF_NEED_REPAIR = 14,///< used to mark a train that has a reduced maximum speed because of a critical breakdown
|
VRF_NEED_REPAIR = 14,///< used to mark a train that has a reduced maximum speed because of a critical breakdown
|
||||||
VRF_TOO_HEAVY = 15,
|
VRF_TOO_HEAVY = 15,
|
||||||
|
VRF_BEYOND_PLATFORM_END = 16,
|
||||||
|
VRF_NOT_YET_IN_PLATFORM = 17,
|
||||||
|
VRF_ADVANCE_IN_PLATFORM = 18,
|
||||||
|
|
||||||
VRF_IS_BROKEN = (1 << VRF_BREAKDOWN_POWER) | (1 << VRF_BREAKDOWN_SPEED) | (1 << VRF_BREAKDOWN_STOPPED), ///< Bitmask of all flags that indicate a broken train (braking is not included)
|
VRF_IS_BROKEN = (1 << VRF_BREAKDOWN_POWER) | (1 << VRF_BREAKDOWN_SPEED) | (1 << VRF_BREAKDOWN_STOPPED), ///< Bitmask of all flags that indicate a broken train (braking is not included)
|
||||||
};
|
};
|
||||||
@@ -76,7 +79,7 @@ bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay =
|
|||||||
|
|
||||||
void DeleteVisibleTrain(Train *v);
|
void DeleteVisibleTrain(Train *v);
|
||||||
|
|
||||||
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
|
int GetTrainStopLocation(StationID station_id, TileIndex tile, Train *v, int *station_ahead, int *station_length);
|
||||||
void CheckBreakdownFlags(Train *v);
|
void CheckBreakdownFlags(Train *v);
|
||||||
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
|
void GetTrainSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type);
|
||||||
|
|
||||||
@@ -206,6 +209,18 @@ struct Train FINAL : public GroundVehicle<Train, VEH_TRAIN> {
|
|||||||
return this->gcache.cached_veh_length / 2 + (this->Next() != NULL ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
|
return this->gcache.cached_veh_length / 2 + (this->Next() != NULL ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Train *GetStationLoadingVehicle() const
|
||||||
|
{
|
||||||
|
const Train *v = this->First();
|
||||||
|
while (v && HasBit(v->flags, VRF_BEYOND_PLATFORM_END)) v = v->Next();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
Train *GetStationLoadingVehicle()
|
||||||
|
{
|
||||||
|
return const_cast<Train *>(const_cast<const Train *>(this)->GetStationLoadingVehicle());
|
||||||
|
}
|
||||||
|
|
||||||
protected: // These functions should not be called outside acceleration code.
|
protected: // These functions should not be called outside acceleration code.
|
||||||
/**
|
/**
|
||||||
* Gets the speed a broken down train (low speed breakdown) is limited to.
|
* Gets the speed a broken down train (low speed breakdown) is limited to.
|
||||||
|
@@ -341,8 +341,9 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
|||||||
* @param station_length 'return' the station length in 1/16th tiles
|
* @param station_length 'return' the station length in 1/16th tiles
|
||||||
* @return the location, calculated from the begin of the station to stop at.
|
* @return the location, calculated from the begin of the station to stop at.
|
||||||
*/
|
*/
|
||||||
int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
|
int GetTrainStopLocation(StationID station_id, TileIndex tile, Train *v, int *station_ahead, int *station_length)
|
||||||
{
|
{
|
||||||
|
Train *front = v->First();
|
||||||
const Station *st = Station::Get(station_id);
|
const Station *st = Station::Get(station_id);
|
||||||
*station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
|
*station_ahead = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
|
||||||
*station_length = st->GetPlatformLength(tile) * TILE_SIZE;
|
*station_length = st->GetPlatformLength(tile) * TILE_SIZE;
|
||||||
@@ -350,11 +351,49 @@ int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, i
|
|||||||
/* Default to the middle of the station for stations stops that are not in
|
/* Default to the middle of the station for stations stops that are not in
|
||||||
* the order list like intermediate stations when non-stop is disabled */
|
* the order list like intermediate stations when non-stop is disabled */
|
||||||
OrderStopLocation osl = OSL_PLATFORM_MIDDLE;
|
OrderStopLocation osl = OSL_PLATFORM_MIDDLE;
|
||||||
if (v->gcache.cached_total_length >= *station_length) {
|
if (front->current_order.IsType(OT_GOTO_STATION) && front->current_order.GetDestination() == station_id) {
|
||||||
|
osl = front->current_order.GetStopLocation();
|
||||||
|
}
|
||||||
|
int overhang = front->gcache.cached_total_length - *station_length;
|
||||||
|
int adjust = 0;
|
||||||
|
if (osl == OSL_PLATFORM_THROUGH && overhang > 0) {
|
||||||
|
for (Train *u = front; u != NULL; u = u->Next()) {
|
||||||
|
/* Passengers may not be through-loaded */
|
||||||
|
if (u->cargo_cap > 0 && IsCargoInClass(u->cargo_type, CC_PASSENGERS)) {
|
||||||
|
osl = OSL_PLATFORM_FAR_END;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (osl == OSL_PLATFORM_THROUGH && overhang > 0) {
|
||||||
|
/* The train is longer than the station, and we can run through the station to load/unload */
|
||||||
|
for (Train *u = v; u != nullptr; u = u->Next()) {
|
||||||
|
if (overhang > 0 && !HasBit(u->flags, VRF_BEYOND_PLATFORM_END) && !u->IsArticulatedPart()) {
|
||||||
|
bool skip = true;
|
||||||
|
for (const Train *part = u; part != nullptr; part = part->HasArticulatedPart() ? part->GetNextArticulatedPart() : nullptr) {
|
||||||
|
if (part->cargo_cap != 0) {
|
||||||
|
skip = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skip) {
|
||||||
|
for (Train *part = u; part != nullptr; part = part->HasArticulatedPart() ? part->GetNextArticulatedPart() : nullptr) {
|
||||||
|
SetBit(part->flags, VRF_BEYOND_PLATFORM_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (HasBit(u->flags, VRF_BEYOND_PLATFORM_END)) {
|
||||||
|
overhang -= u->gcache.cached_veh_length;
|
||||||
|
adjust += u->gcache.cached_veh_length;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Train *u = front; u != v; u = u->Next()) overhang -= u->gcache.cached_veh_length; // only advance until rear of train is in platform
|
||||||
|
if (overhang < 0) adjust += overhang;
|
||||||
|
} else if (overhang >= 0) {
|
||||||
/* The train is longer than the station, make it stop at the far end of the platform */
|
/* The train is longer than the station, make it stop at the far end of the platform */
|
||||||
osl = OSL_PLATFORM_FAR_END;
|
osl = OSL_PLATFORM_FAR_END;
|
||||||
} else if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id) {
|
|
||||||
osl = v->current_order.GetStopLocation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The stop location of the FRONT! of the train */
|
/* The stop location of the FRONT! of the train */
|
||||||
@@ -363,21 +402,22 @@ int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, i
|
|||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
|
|
||||||
case OSL_PLATFORM_NEAR_END:
|
case OSL_PLATFORM_NEAR_END:
|
||||||
stop = v->gcache.cached_total_length;
|
stop = front->gcache.cached_total_length;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSL_PLATFORM_MIDDLE:
|
case OSL_PLATFORM_MIDDLE:
|
||||||
stop = *station_length - (*station_length - v->gcache.cached_total_length) / 2;
|
stop = *station_length - (*station_length -front->gcache.cached_total_length) / 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSL_PLATFORM_FAR_END:
|
case OSL_PLATFORM_FAR_END:
|
||||||
|
case OSL_PLATFORM_THROUGH:
|
||||||
stop = *station_length;
|
stop = *station_length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Subtract half the front vehicle length of the train so we get the real
|
/* Subtract half the front vehicle length of the train so we get the real
|
||||||
* stop location of the train. */
|
* stop location of the train. */
|
||||||
return stop - (v->gcache.cached_veh_length + 1) / 2;
|
return stop - ((v->gcache.cached_veh_length + 1) / 2) + adjust;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -460,27 +500,31 @@ int Train::GetCurrentMaxSpeed() const
|
|||||||
this->gcache.cached_max_track_speed :
|
this->gcache.cached_max_track_speed :
|
||||||
this->tcache.cached_max_curve_speed;
|
this->tcache.cached_max_curve_speed;
|
||||||
|
|
||||||
if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC && IsRailStationTile(this->tile)) {
|
if (_settings_game.vehicle.train_acceleration_model == AM_REALISTIC) {
|
||||||
StationID sid = GetStationIndex(this->tile);
|
Train *v_platform = const_cast<Train *>(this->GetStationLoadingVehicle());
|
||||||
if (this->current_order.ShouldStopAtStation(this, sid)) {
|
TileIndex platform_tile = v_platform->tile;
|
||||||
int station_ahead;
|
if (IsRailStationTile(platform_tile)) {
|
||||||
int station_length;
|
StationID sid = GetStationIndex(platform_tile);
|
||||||
int stop_at = GetTrainStopLocation(sid, this->tile, this, &station_ahead, &station_length);
|
if (this->current_order.ShouldStopAtStation(this, sid)) {
|
||||||
|
int station_ahead;
|
||||||
|
int station_length;
|
||||||
|
int stop_at = GetTrainStopLocation(sid, platform_tile, v_platform, &station_ahead, &station_length);
|
||||||
|
|
||||||
/* The distance to go is whatever is still ahead of the train minus the
|
/* The distance to go is whatever is still ahead of the train minus the
|
||||||
* distance from the train's stop location to the end of the platform */
|
* distance from the train's stop location to the end of the platform */
|
||||||
int distance_to_go = station_ahead / TILE_SIZE - (station_length - stop_at) / TILE_SIZE;
|
int distance_to_go = station_ahead / TILE_SIZE - (station_length - stop_at) / TILE_SIZE;
|
||||||
|
|
||||||
if (distance_to_go > 0) {
|
if (distance_to_go > 0) {
|
||||||
int st_max_speed = 120;
|
int st_max_speed = 120;
|
||||||
|
|
||||||
int delta_v = this->cur_speed / (distance_to_go + 1);
|
int delta_v = this->cur_speed / (distance_to_go + 1);
|
||||||
if (max_speed > (this->cur_speed - delta_v)) {
|
if (max_speed > (this->cur_speed - delta_v)) {
|
||||||
st_max_speed = this->cur_speed - (delta_v / 10);
|
st_max_speed = this->cur_speed - (delta_v / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
st_max_speed = max(st_max_speed, 25 * distance_to_go);
|
||||||
|
max_speed = min(max_speed, st_max_speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
st_max_speed = max(st_max_speed, 25 * distance_to_go);
|
|
||||||
max_speed = min(max_speed, st_max_speed);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2008,6 +2052,8 @@ void ReverseTrainDirection(Train *v)
|
|||||||
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v->current_order.IsType(OT_LOADING_ADVANCE)) v->LeaveStation();
|
||||||
|
|
||||||
v->reverse_distance = 0;
|
v->reverse_distance = 0;
|
||||||
|
|
||||||
/* Clear path reservation in front if train is not stuck. */
|
/* Clear path reservation in front if train is not stuck. */
|
||||||
@@ -2145,12 +2191,14 @@ CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32
|
|||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
/* Properly leave the station if we are loading and won't be loading anymore */
|
/* Properly leave the station if we are loading and won't be loading anymore */
|
||||||
if (v->current_order.IsType(OT_LOADING)) {
|
if (v->current_order.IsAnyLoadingType()) {
|
||||||
const Vehicle *last = v;
|
const Vehicle *last = v;
|
||||||
while (last->Next() != NULL) last = last->Next();
|
while (last->Next() != NULL) last = last->Next();
|
||||||
|
|
||||||
/* not a station || different station --> leave the station */
|
/* not a station || different station --> leave the station */
|
||||||
if (!IsTileType(last->tile, MP_STATION) || GetStationIndex(last->tile) != GetStationIndex(v->tile)) {
|
if (!IsTileType(last->tile, MP_STATION) || !IsTileType(v->tile, MP_STATION) ||
|
||||||
|
GetStationIndex(last->tile) != GetStationIndex(v->tile) ||
|
||||||
|
HasBit(v->flags, VRF_BEYOND_PLATFORM_END)) {
|
||||||
v->LeaveStation();
|
v->LeaveStation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2931,7 +2979,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
|||||||
* order list itself is empty. */
|
* order list itself is empty. */
|
||||||
if (v->current_order.IsType(OT_LEAVESTATION)) {
|
if (v->current_order.IsType(OT_LEAVESTATION)) {
|
||||||
orders.SwitchToNextOrder(false);
|
orders.SwitchToNextOrder(false);
|
||||||
} else if (v->current_order.IsType(OT_LOADING) || (!v->current_order.IsType(OT_GOTO_DEPOT) && (
|
} else if (v->current_order.IsAnyLoadingType() || (!v->current_order.IsType(OT_GOTO_DEPOT) && (
|
||||||
v->current_order.IsType(OT_GOTO_STATION) ?
|
v->current_order.IsType(OT_GOTO_STATION) ?
|
||||||
IsRailStationTile(v->tile) && v->current_order.GetDestination() == GetStationIndex(v->tile) :
|
IsRailStationTile(v->tile) && v->current_order.GetDestination() == GetStationIndex(v->tile) :
|
||||||
v->tile == v->dest_tile))) {
|
v->tile == v->dest_tile))) {
|
||||||
@@ -3233,8 +3281,9 @@ static void TrainEnterStation(Train *v, StationID station)
|
|||||||
|
|
||||||
v->BeginLoading();
|
v->BeginLoading();
|
||||||
|
|
||||||
TriggerStationRandomisation(st, v->tile, SRT_TRAIN_ARRIVES);
|
TileIndex station_tile = v->GetStationLoadingVehicle()->tile;
|
||||||
TriggerStationAnimation(st, v->tile, SAT_TRAIN_ARRIVES);
|
TriggerStationRandomisation(st, station_tile, SRT_TRAIN_ARRIVES);
|
||||||
|
TriggerStationAnimation(st, station_tile, SAT_TRAIN_ARRIVES);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the vehicle is compatible with the specified tile */
|
/* Check if the vehicle is compatible with the specified tile */
|
||||||
@@ -3691,7 +3740,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||||||
}
|
}
|
||||||
if (HasBit(r, VETS_ENTERED_STATION)) {
|
if (HasBit(r, VETS_ENTERED_STATION)) {
|
||||||
/* The new position is the end of the platform */
|
/* The new position is the end of the platform */
|
||||||
TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
|
TrainEnterStation(v->First(), r >> VETS_STATION_ID_OFFSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -3916,7 +3965,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
|||||||
|
|
||||||
if (HasBit(r, VETS_ENTERED_STATION)) {
|
if (HasBit(r, VETS_ENTERED_STATION)) {
|
||||||
/* The new position is the location where we want to stop */
|
/* The new position is the location where we want to stop */
|
||||||
TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET);
|
TrainEnterStation(v->First(), r >> VETS_STATION_ID_OFFSET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@@ -294,6 +294,7 @@ bool Vehicle::NeedsAutomaticServicing() const
|
|||||||
{
|
{
|
||||||
if (this->HasDepotOrder()) return false;
|
if (this->HasDepotOrder()) return false;
|
||||||
if (this->current_order.IsType(OT_LOADING)) return false;
|
if (this->current_order.IsType(OT_LOADING)) return false;
|
||||||
|
if (this->current_order.IsType(OT_LOADING_ADVANCE)) return false;
|
||||||
if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
|
if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
|
||||||
return NeedsServicing();
|
return NeedsServicing();
|
||||||
}
|
}
|
||||||
@@ -2530,8 +2531,13 @@ static void VehicleIncreaseStats(const Vehicle *front)
|
|||||||
*/
|
*/
|
||||||
void Vehicle::BeginLoading()
|
void Vehicle::BeginLoading()
|
||||||
{
|
{
|
||||||
assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
|
if (this->type == VEH_TRAIN) {
|
||||||
|
assert(IsTileType(Train::From(this)->GetStationLoadingVehicle()->tile, MP_STATION));
|
||||||
|
} else {
|
||||||
|
assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool no_load_prepare = false;
|
||||||
if (this->current_order.IsType(OT_GOTO_STATION) &&
|
if (this->current_order.IsType(OT_GOTO_STATION) &&
|
||||||
this->current_order.GetDestination() == this->last_station_visited) {
|
this->current_order.GetDestination() == this->last_station_visited) {
|
||||||
this->DeleteUnreachedImplicitOrders();
|
this->DeleteUnreachedImplicitOrders();
|
||||||
@@ -2546,7 +2552,9 @@ void Vehicle::BeginLoading()
|
|||||||
* whether the train is lost or not; not marking a train lost
|
* whether the train is lost or not; not marking a train lost
|
||||||
* that arrives at random stations is bad. */
|
* that arrives at random stations is bad. */
|
||||||
this->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
|
this->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
|
||||||
|
} else if (this->current_order.IsType(OT_LOADING_ADVANCE)) {
|
||||||
|
this->current_order.MakeLoading(true);
|
||||||
|
no_load_prepare = true;
|
||||||
} else {
|
} else {
|
||||||
/* We weren't scheduled to stop here. Insert an implicit order
|
/* We weren't scheduled to stop here. Insert an implicit order
|
||||||
* to show that we are stopping here.
|
* to show that we are stopping here.
|
||||||
@@ -2634,9 +2642,11 @@ void Vehicle::BeginLoading()
|
|||||||
this->current_order.MakeLoading(false);
|
this->current_order.MakeLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
VehicleIncreaseStats(this);
|
if (!no_load_prepare) {
|
||||||
|
VehicleIncreaseStats(this);
|
||||||
|
|
||||||
PrepareUnload(this);
|
PrepareUnload(this);
|
||||||
|
}
|
||||||
|
|
||||||
SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
|
SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
|
||||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
|
SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
|
||||||
@@ -2687,11 +2697,18 @@ uint32 Vehicle::GetLastLoadingStationValidCargoMask() const
|
|||||||
*/
|
*/
|
||||||
void Vehicle::LeaveStation()
|
void Vehicle::LeaveStation()
|
||||||
{
|
{
|
||||||
assert(this->current_order.IsType(OT_LOADING));
|
assert(this->current_order.IsAnyLoadingType());
|
||||||
|
|
||||||
delete this->cargo_payment;
|
delete this->cargo_payment;
|
||||||
assert(this->cargo_payment == NULL); // cleared by ~CargoPayment
|
assert(this->cargo_payment == NULL); // cleared by ~CargoPayment
|
||||||
|
|
||||||
|
if (this->type == VEH_TRAIN) {
|
||||||
|
for (Train *v = Train::From(this); v != nullptr; v = v->Next()) {
|
||||||
|
ClrBit(v->flags, VRF_BEYOND_PLATFORM_END);
|
||||||
|
ClrBit(v->flags, VRF_NOT_YET_IN_PLATFORM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Only update the timetable if the vehicle was supposed to stop here. */
|
/* Only update the timetable if the vehicle was supposed to stop here. */
|
||||||
if (this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
|
if (this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
|
||||||
|
|
||||||
@@ -2756,9 +2773,10 @@ void Vehicle::LeaveStation()
|
|||||||
|
|
||||||
if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
|
if (this->type == VEH_TRAIN && !(this->vehstatus & VS_CRASHED)) {
|
||||||
/* Trigger station animation (trains only) */
|
/* Trigger station animation (trains only) */
|
||||||
if (IsTileType(this->tile, MP_STATION)) {
|
TileIndex station_tile = Train::From(this)->GetStationLoadingVehicle()->tile;
|
||||||
TriggerStationRandomisation(st, this->tile, SRT_TRAIN_DEPARTS);
|
if (IsTileType(station_tile, MP_STATION)) {
|
||||||
TriggerStationAnimation(st, this->tile, SAT_TRAIN_DEPARTS);
|
TriggerStationRandomisation(st, station_tile, SRT_TRAIN_DEPARTS);
|
||||||
|
TriggerStationAnimation(st, station_tile, SAT_TRAIN_DEPARTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
|
SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
|
||||||
@@ -2791,6 +2809,30 @@ void Vehicle::LeaveStation()
|
|||||||
|
|
||||||
this->MarkDirty();
|
this->MarkDirty();
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Perform all actions when switching to advancing within a station for loading/unloading
|
||||||
|
* @pre this->current_order.IsType(OT_LOADING)
|
||||||
|
* @pre this->type == VEH_TRAIN
|
||||||
|
*/
|
||||||
|
void Vehicle::AdvanceLoadingInStation()
|
||||||
|
{
|
||||||
|
assert(this->current_order.IsType(OT_LOADING));
|
||||||
|
assert(this->type == VEH_TRAIN);
|
||||||
|
|
||||||
|
ClrBit(Train::From(this)->flags, VRF_ADVANCE_IN_PLATFORM);
|
||||||
|
|
||||||
|
for (Train *v = Train::From(this); v != nullptr; v = v->Next()) {
|
||||||
|
if (HasBit(v->flags, VRF_NOT_YET_IN_PLATFORM)) {
|
||||||
|
ClrBit(v->flags, VRF_NOT_YET_IN_PLATFORM);
|
||||||
|
} else {
|
||||||
|
SetBit(v->flags, VRF_BEYOND_PLATFORM_END);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HideFillingPercent(&this->fill_percent_te_id);
|
||||||
|
this->current_order.MakeLoadingAdvance(this->last_station_visited);
|
||||||
|
this->MarkDirty();
|
||||||
|
}
|
||||||
|
|
||||||
void Vehicle::RecalculateOrderOccupancyAverage()
|
void Vehicle::RecalculateOrderOccupancyAverage()
|
||||||
{
|
{
|
||||||
@@ -2839,7 +2881,10 @@ void Vehicle::HandleLoading(bool mode)
|
|||||||
if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
|
if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
|
||||||
|
|
||||||
/* Not the first call for this tick, or still loading */
|
/* Not the first call for this tick, or still loading */
|
||||||
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) return;
|
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || this->current_order_time < wait_time) {
|
||||||
|
if (!mode && this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_ADVANCE_IN_PLATFORM)) this->AdvanceLoadingInStation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this->PlayLeaveStationSound();
|
this->PlayLeaveStationSound();
|
||||||
|
|
||||||
@@ -2966,7 +3011,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command, Tile
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
|
if (this->current_order.IsAnyLoadingType()) this->LeaveStation();
|
||||||
|
|
||||||
if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
|
if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
|
||||||
uint16 &gv_flags = this->GetGroundVehicleFlags();
|
uint16 &gv_flags = this->GetGroundVehicleFlags();
|
||||||
|
@@ -354,6 +354,7 @@ public:
|
|||||||
void BeginLoading();
|
void BeginLoading();
|
||||||
void CancelReservation(StationID next, Station *st);
|
void CancelReservation(StationID next, Station *st);
|
||||||
void LeaveStation();
|
void LeaveStation();
|
||||||
|
void AdvanceLoadingInStation();
|
||||||
|
|
||||||
GroundVehicleCache *GetGroundVehicleCache();
|
GroundVehicleCache *GetGroundVehicleCache();
|
||||||
const GroundVehicleCache *GetGroundVehicleCache() const;
|
const GroundVehicleCache *GetGroundVehicleCache() const;
|
||||||
|
@@ -3213,6 +3213,12 @@ public:
|
|||||||
str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
|
str = STR_VEHICLE_STATUS_LOADING_UNLOADING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OT_LOADING_ADVANCE:
|
||||||
|
str = STR_VEHICLE_STATUS_LOADING_UNLOADING_ADVANCE;
|
||||||
|
SetDParam(0, STR_VEHICLE_STATUS_LOADING_UNLOADING);
|
||||||
|
SetDParam(1, v->GetDisplaySpeed());
|
||||||
|
break;
|
||||||
|
|
||||||
case OT_GOTO_WAYPOINT: {
|
case OT_GOTO_WAYPOINT: {
|
||||||
assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
|
assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
|
||||||
SetDParam(0, v->current_order.GetDestination());
|
SetDParam(0, v->current_order.GetDestination());
|
||||||
|
Reference in New Issue
Block a user