@@ -1035,26 +1035,12 @@ static bool HandleCrashedAircraft(Aircra
return false;
}
return true;
static void HandleBrokenAircraft(Aircraft *v)
{
if (v->breakdown_ctr != 1) {
v->breakdown_ctr = 1;
v->vehstatus |= VS_AIRCRAFT_BROKEN;
if (v->breakdowns_since_last_service != 255) {
v->breakdowns_since_last_service++;
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
static void HandleAircraftSmoke(Aircraft *v)
static const struct {
int8 x;
int8 y;
@@ -1789,13 +1775,13 @@ static bool AircraftEventHandler(Aircraf
if (v->vehstatus & VS_STOPPED) return true;
/* aircraft is broken down? */
if (v->breakdown_ctr != 0) {
if (v->breakdown_ctr <= 2) {
HandleBrokenAircraft(v);
v->HandleBreakdown();
} else {
if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
HandleAircraftSmoke(v);
@@ -28,13 +28,12 @@
#include "date_func.h"
#include "vehicle_func.h"
#include "sound_func.h"
#include "ai/ai.hpp"
#include "depot_map.h"
#include "effectvehicle_func.h"
#include "effectvehicle_base.h"
#include "roadstop_base.h"
#include "spritecache.h"
#include "core/random_func.hpp"
#include "company_base.h"
#include "core/backup_type.hpp"
@@ -529,46 +528,12 @@ static bool RoadVehCheckTrainCrash(RoadV
static void HandleBrokenRoadVeh(RoadVehicle *v)
v->cur_speed = 0;
v->MarkDirty();
if (!PlayVehicleSound(v, VSE_BREAKDOWN)) {
SndPlayVehicleFx((_settings_game.game_creation.landscape != LT_TOYLAND) ?
SND_0F_VEHICLE_BREAKDOWN : SND_35_COMEDY_BREAKDOWN, v);
if (!(v->vehstatus & VS_HIDDEN)) {
EffectVehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE);
if (u != NULL) u->animation_state = v->breakdown_delay * 2;
if ((v->tick_counter & 1) == 0) {
if (--v->breakdown_delay == 0) {
v->breakdown_ctr = 0;
TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
if (station == this->last_station_visited) this->last_station_visited = INVALID_STATION;
const Station *st = Station::Get(station);
if (!CanVehicleUseStation(this, st)) {
@@ -1519,13 +1484,13 @@ static bool RoadVehController(RoadVehicl
return RoadVehIsCrashed(v);
/* road vehicle has broken down? */
HandleBrokenRoadVeh(v);
@@ -27,14 +27,12 @@
#include "strings_func.h"
#include "functions.h"
#include "window_func.h"
#include "pathfinder/opf/opf_ship.h"
#include "landscape_type.h"
#include "engine_base.h"
@@ -202,46 +200,12 @@ Trackdir Ship::GetVehicleTrackdir() cons
return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction);
static void HandleBrokenShip(Vehicle *v)
SND_10_TRAIN_BREAKDOWN : SND_3A_COMEDY_BREAKDOWN_2, v);
if (!(v->tick_counter & 1)) {
if (!--v->breakdown_delay) {
void Ship::MarkDirty()
this->UpdateViewport(false, false);
static void PlayShipSound(const Vehicle *v)
@@ -459,13 +423,13 @@ static void ShipController(Ship *v)
v->tick_counter++;
v->current_order_time++;
HandleBrokenShip(v);
return;
if (v->vehstatus & VS_STOPPED) return;
@@ -26,13 +26,12 @@
#include "newgrf_station.h"
#include "gamelog.h"
#include "network/network.h"
#include "newgrf.h"
@@ -3540,46 +3539,12 @@ static bool HandleCrashedTrain(Train *v)
return ret;
static void HandleBrokenTrain(Train *v)
if (!(v->tick_counter & 3)) {
/** Maximum speeds for train that is broken down or approaching line end */
static const uint16 _breakdown_speeds[16] = {
225, 210, 195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15, 15
};
@@ -3750,13 +3715,13 @@ static bool TrainLocoHandler(Train *v, b
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
/* train is broken down? */
HandleBrokenTrain(v);
if (HasBit(v->flags, VRF_REVERSING) && v->cur_speed == 0) {
@@ -43,12 +43,15 @@
#include "economy_base.h"
#include "articulated_vehicles.h"
#include "order_backup.h"
#include "table/strings.h"
#define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
VehicleID _vehicle_id_ctr_day;
@@ -980,12 +983,62 @@ void CheckVehicleBreakdown(Vehicle *v)
v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
v->breakdown_delay = GB(r, 24, 7) + 0x80;
v->breakdown_chance = 0;
void Vehicle::HandleBreakdown()
/* Possible states for Vehicle::breakdown_ctr
* 0 - vehicle is running normally
* 1 - vehicle is currently broken down
* 2 - vehicle is going to break down now
* >2 - vehicle is counting down to the actual breakdown event */
if (this->breakdown_ctr != 1) {
this->breakdown_ctr = 1;
if (this->breakdowns_since_last_service != 255) {
this->breakdowns_since_last_service++;
this->MarkDirty();
SetWindowDirty(WC_VEHICLE_VIEW, this->index);
SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
if (this->type == VEH_AIRCRAFT) {
/* Aircraft just need this flag, the rest is handled elsewhere */
this->vehstatus |= VS_AIRCRAFT_BROKEN;
this->cur_speed = 0;
if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
(this->type == VEH_TRAIN ? SND_10_TRAIN_BREAKDOWN : SND_0F_VEHICLE_BREAKDOWN) :
(this->type == VEH_TRAIN ? SND_3A_COMEDY_BREAKDOWN_2 : SND_35_COMEDY_BREAKDOWN), this);
if (!(this->vehstatus & VS_HIDDEN)) {
EffectVehicle *u = CreateEffectVehicleRel(this, 4, 4, 5, EV_BREAKDOWN_SMOKE);
if (u != NULL) u->animation_state = this->breakdown_delay * 2;
/* Aircraft breakdowns end only when arriving at the airport */
if (this->type == VEH_AIRCRAFT) return;
/* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
if (--this->breakdown_delay == 0) {
this->breakdown_ctr = 0;
void AgeVehicle(Vehicle *v)
if (v->age < MAX_DAY) v->age++;
int age = v->age - v->max_age;
if (age == DAYS_IN_LEAP_YEAR * 0 || age == DAYS_IN_LEAP_YEAR * 1 ||
@@ -520,12 +520,18 @@ public:
if (HasBit(src->vehicle_flags, VF_AUTOFILL_TIMETABLE)) SetBit(this->vehicle_flags, VF_AUTOFILL_TIMETABLE);
if (HasBit(src->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME)) SetBit(this->vehicle_flags, VF_AUTOFILL_PRES_WAIT_TIME);
this->service_interval = src->service_interval;
/**
* Handle all of the aspects of a vehicle breakdown.
* This includes adding smoke and sounds, and ending the breakdown when appropriate.
*/
void HandleBreakdown();
bool NeedsAutorenewing(const Company *c) const;
* Check if the vehicle needs to go to a depot in near future (if a opportunity presents itself) for service or replacement.
*
* @see NeedsAutomaticServicing()
Status change: