diff options
Diffstat (limited to 'src/vehicle.cpp')
-rw-r--r-- | src/vehicle.cpp | 65 |
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) { |