summaryrefslogtreecommitdiff
path: root/src/vehicle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/vehicle.cpp')
-rw-r--r--src/vehicle.cpp65
1 files changed, 61 insertions, 4 deletions
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 2f11421d6..b1ee33a1b 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -15,6 +15,7 @@
#include "ship.h"
#include "spritecache.h"
#include "timetable.h"
+#include "layer_func.h"
#include "viewport_func.h"
#include "news_func.h"
#include "command_func.h"
@@ -49,6 +50,7 @@
#include "bridge_map.h"
#include "tunnel_map.h"
#include "depot_map.h"
+#include "cargodest_func.h"
#include "gamelog.h"
#include "table/strings.h"
@@ -206,6 +208,17 @@ uint Vehicle::Crash(bool flooded)
return RandomRange(pass + 1); // Randomise deceased passengers.
}
+/** Marks the separation of this vehicle's order list invalid. */
+void Vehicle::MarkSeparationInvalid()
+{
+ if (this->orders.list != NULL) this->orders.list->MarkSeparationInvalid();
+}
+
+/** Sets new separation settings for this vehicle's shared orders. */
+void Vehicle::SetSepSettings(TTSepMode Mode, uint Parameter)
+{
+ if (this->orders.list != NULL) this->orders.list->SetSepSettings(Mode, Parameter);
+}
/**
* Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
@@ -268,7 +281,10 @@ Vehicle::Vehicle(VehicleType type)
this->fill_percent_te_id = INVALID_TE_ID;
this->first = this;
this->colourmap = PAL_NONE;
+ this->last_station_loaded = INVALID_STATION;
this->cargo_age_counter = 1;
+ this->current_order.index = INVALID_ORDER;
+ this->last_order_id = INVALID_ORDER;
}
/**
@@ -887,9 +903,12 @@ void CallVehicleTicks()
}
if (v->type == VEH_TRAIN && Train::From(v)->IsWagon()) continue;
- if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue;
if (v->type == VEH_ROAD && !RoadVehicle::From(v)->IsFrontEngine()) continue;
+ v->travel_time++;
+
+ if (v->type == VEH_AIRCRAFT && v->subtype != AIR_HELICOPTER) continue;
+
v->motion_counter += v->cur_speed;
/* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
if (GB(v->motion_counter, 0, 8) < v->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
@@ -1008,8 +1027,8 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
for (int x = xl;; x = (x + 1) & 0x3F) {
const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
-
while (v != NULL) {
+ if (LayerIndex(v->tile) == dpi->layer)
if (!(v->vehstatus & VS_HIDDEN) &&
l <= v->coord.right &&
t <= v->coord.bottom &&
@@ -1398,6 +1417,7 @@ void VehicleEnterDepot(Vehicle *v)
AddVehicleAdviceNewsItem(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index);
}
AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
+ v->MarkSeparationInvalid();
}
}
}
@@ -1869,12 +1889,15 @@ void Vehicle::DeleteUnreachedImplicitOrders()
/**
* Prepare everything to begin the loading when arriving at a station.
+ * @param station The station ID of the station.
* @pre IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP.
*/
-void Vehicle::BeginLoading()
+void Vehicle::BeginLoading(StationID station)
{
assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
+ this->last_station_visited = station;
+
if (this->current_order.IsType(OT_GOTO_STATION) &&
this->current_order.GetDestination() == this->last_station_visited) {
this->DeleteUnreachedImplicitOrders();
@@ -1955,6 +1978,7 @@ void Vehicle::BeginLoading()
implicit_order->MakeImplicit(this->last_station_visited);
InsertOrder(this, implicit_order, this->cur_implicit_order_index);
if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
+ this->current_order.index = implicit_order->index;
/* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
* Reenable it for this vehicle */
@@ -1966,7 +1990,35 @@ void Vehicle::BeginLoading()
this->current_order.MakeLoading(false);
}
- Station::Get(this->last_station_visited)->loading_vehicles.push_back(this);
+ UpdateVehicleRouteLinks(this, station);
+
+ /* Save the id of the order which made us arrive here. MakeLoading
+ * does not overwrite the index so it is still valid here. */
+ this->last_order_id = this->current_order.index;
+ this->last_station_loaded = station;
+ /* If all requirements for separation are met, we can initialize it. */
+ if (_settings_game.order.automatic_timetable_separation
+ && this->IsOrderListShared()
+ && this->orders.list->IsCompleteTimetable()
+ && (this->cur_real_order_index == 0)) {
+
+ if (!this->orders.list->IsSeparationValid()) this->orders.list->InitializeSeparation();
+ this->lateness_counter = this->orders.list->SeparateVehicle();
+ }
+
+
+ Station *last_visited = Station::Get(this->last_station_visited);
+ last_visited->loading_vehicles.push_back(this);
+
+ /* Update the next hop for waiting cargo. */
+ CargoID cid;
+ FOR_EACH_SET_CARGO_ID(cid, this->vcache.cached_cargo_mask) {
+ /* Only update if the last update was at least route_recalc_delay ticks earlier. */
+ if (CargoHasDestinations(cid) && last_visited->goods[cid].cargo_counter == 0) {
+ last_visited->goods[cid].cargo.UpdateCargoNextHop(last_visited, cid);
+ last_visited->goods[cid].cargo_counter = _settings_game.economy.cargodest.route_recalc_delay;
+ }
+ }
PrepareUnload(this);
@@ -1993,6 +2045,9 @@ void Vehicle::LeaveStation()
/* Only update the timetable if the vehicle was supposed to stop here. */
if (this->current_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) UpdateVehicleTimetable(this, false);
+ /* Reset travel time counter. */
+ this->travel_time = 0;
+
this->current_order.MakeLeaveStation();
Station *st = Station::Get(this->last_station_visited);
st->loading_vehicles.remove(this);
@@ -2381,6 +2436,7 @@ void Vehicle::AddToShared(Vehicle *shared_chain)
if (this->next_shared != NULL) this->next_shared->previous_shared = this;
shared_chain->orders.list->AddVehicle(this);
+ shared_chain->orders.list->MarkSeparationInvalid();
}
/**
@@ -2393,6 +2449,7 @@ void Vehicle::RemoveFromShared()
bool were_first = (this->FirstShared() == this);
VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
+ this->orders.list->MarkSeparationInvalid();
this->orders.list->RemoveVehicle(this);
if (!were_first) {