summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/aircraft.h2
-rw-r--r--src/aircraft_cmd.cpp30
-rw-r--r--src/disaster_cmd.cpp102
-rw-r--r--src/effectvehicle.cpp65
-rw-r--r--src/effectvehicle_base.h2
-rw-r--r--src/roadveh.h2
-rw-r--r--src/roadveh_cmd.cpp27
-rw-r--r--src/ship.h2
-rw-r--r--src/ship_cmd.cpp4
-rw-r--r--src/train.h2
-rw-r--r--src/train_cmd.cpp47
-rw-r--r--src/vehicle.cpp5
-rw-r--r--src/vehicle_base.h6
13 files changed, 189 insertions, 107 deletions
diff --git a/src/aircraft.h b/src/aircraft.h
index 52b8c0252..c535cdbe5 100644
--- a/src/aircraft.h
+++ b/src/aircraft.h
@@ -106,7 +106,7 @@ struct Aircraft : public Vehicle {
int GetDisplayMaxSpeed() const { return this->max_speed; }
Money GetRunningCost() const;
bool IsInDepot() const { return (this->vehstatus & VS_HIDDEN) != 0 && IsHangarTile(this->tile); }
- void Tick();
+ bool Tick();
void OnNewDay();
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
index d3314d34f..25ba931b0 100644
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -1137,7 +1137,7 @@ static bool AircraftController(Vehicle *v)
}
-static void HandleCrashedAircraft(Vehicle *v)
+static bool HandleCrashedAircraft(Vehicle *v)
{
v->u.air.crashed_counter += 3;
@@ -1182,7 +1182,11 @@ static void HandleCrashedAircraft(Vehicle *v)
}
delete v;
+
+ return false;
}
+
+ return true;
}
static void HandleBrokenAircraft(Vehicle *v)
@@ -1988,16 +1992,15 @@ static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc)
return false; // it shouldn't get here anytime, but just to be sure
}
-static void AircraftEventHandler(Vehicle *v, int loop)
+static bool AircraftEventHandler(Vehicle *v, int loop)
{
v->tick_counter++;
if (v->vehstatus & VS_CRASHED) {
- HandleCrashedAircraft(v);
- return;
+ return HandleCrashedAircraft(v);
}
- if (v->vehstatus & VS_STOPPED) return;
+ if (v->vehstatus & VS_STOPPED) return true;
/* aircraft is broken down? */
if (v->breakdown_ctr != 0) {
@@ -2012,14 +2015,16 @@ static void AircraftEventHandler(Vehicle *v, int loop)
ProcessOrders(v);
v->HandleLoading(loop != 0);
- if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return;
+ if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return true;
AirportGoToNextPosition(v);
+
+ return true;
}
-void Aircraft::Tick()
+bool Aircraft::Tick()
{
- if (!IsNormalAircraft(this)) return;
+ if (!IsNormalAircraft(this)) return true;
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
@@ -2030,10 +2035,13 @@ void Aircraft::Tick()
this->current_order_time++;
for (uint i = 0; i != 2; i++) {
- AircraftEventHandler(this, i);
- if (this->type != VEH_AIRCRAFT) // In case it was deleted
- break;
+ /* stop if the aircraft was deleted */
+ if (!AircraftEventHandler(this, i)) return false;
+ assert(this->IsValid());
+ assert(IsNormalAircraft(this));
}
+
+ return true;
}
diff --git a/src/disaster_cmd.cpp b/src/disaster_cmd.cpp
index d83f55fe3..e262ca288 100644
--- a/src/disaster_cmd.cpp
+++ b/src/disaster_cmd.cpp
@@ -180,12 +180,12 @@ static void SetDisasterVehiclePos(Vehicle *v, int x, int y, byte z)
* 2: Clear the runway after some time and remove crashed zeppeliner
* If not airport was found, only state 0 is reached until zeppeliner leaves map
*/
-static void DisasterTick_Zeppeliner(Vehicle *v)
+static bool DisasterTick_Zeppeliner(Vehicle *v)
{
v->tick_counter++;
if (v->current_order.GetDestination() < 2) {
- if (HasBit(v->tick_counter, 0)) return;
+ if (HasBit(v->tick_counter, 0)) return true;
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
@@ -215,12 +215,16 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
}
}
- if (v->y_pos >= ((int)MapSizeY() + 9) * TILE_SIZE - 1) delete v;
- return;
+ if (v->y_pos >= ((int)MapSizeY() + 9) * TILE_SIZE - 1) {
+ delete v;
+ return false;
+ }
+
+ return true;
}
if (v->current_order.GetDestination() > 2) {
- if (++v->age <= 13320) return;
+ if (++v->age <= 13320) return true;
if (IsValidTile(v->tile) &&
IsTileType(v->tile, MP_STATION) &&
@@ -232,7 +236,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
SetDisasterVehiclePos(v, v->x_pos, v->y_pos, v->z_pos);
delete v;
- return;
+ return false;
}
int x = v->x_pos;
@@ -267,6 +271,8 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
IsAirport(v->tile)) {
SETBITS(GetStationByTile(v->tile)->airport_flags, RUNWAY_IN_block);
}
+
+ return true;
}
/**
@@ -275,7 +281,7 @@ static void DisasterTick_Zeppeliner(Vehicle *v)
* 1: Home in on a road vehicle and crash it >:)
* If not road vehicle was found, only state 0 is used and Ufo disappears after a while
*/
-static void DisasterTick_Ufo(Vehicle *v)
+static bool DisasterTick_Ufo(Vehicle *v)
{
v->u.disaster.image_override = (HasBit(++v->tick_counter, 3)) ? SPR_UFO_SMALL_SCOUT_DARKER : SPR_UFO_SMALL_SCOUT;
@@ -287,11 +293,11 @@ static void DisasterTick_Ufo(Vehicle *v)
v->direction = GetDirectionTowards(v, x, y);
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
- return;
+ return true;
}
if (++v->age < 6) {
v->dest_tile = RandomTile();
- return;
+ return true;
}
v->current_order.SetDestination(1);
@@ -300,17 +306,18 @@ static void DisasterTick_Ufo(Vehicle *v)
if (u->type == VEH_ROAD && IsRoadVehFront(u)) {
v->dest_tile = u->index;
v->age = 0;
- return;
+ return true;
}
}
delete v;
+ return false;
} else {
/* Target a vehicle */
Vehicle *u = Vehicle::Get(v->dest_tile);
if (u->type != VEH_ROAD || !IsRoadVehFront(u)) {
delete v;
- return;
+ return false;
}
uint dist = Delta(v->x_pos, u->x_pos) + Delta(v->y_pos, u->y_pos);
@@ -351,8 +358,11 @@ static void DisasterTick_Ufo(Vehicle *v)
CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
SndPlayVehicleFx(SND_12_EXPLOSION, v);
delete v;
+ return false;
}
}
+
+ return true;
}
static void DestructIndustry(Industry *i)
@@ -378,7 +388,7 @@ static void DestructIndustry(Industry *i)
* @param news_message The string that's used as news message.
* @param industry_flag Only attack industries that have this flag set.
*/
-static void DisasterTick_Aircraft(Vehicle *v, uint16 image_override, bool leave_at_top, StringID news_message, IndustryBehaviour industry_flag)
+static bool DisasterTick_Aircraft(Vehicle *v, uint16 image_override, bool leave_at_top, StringID news_message, IndustryBehaviour industry_flag)
{
v->tick_counter++;
v->u.disaster.image_override = (v->current_order.GetDestination() == 1 && HasBit(v->tick_counter, 2)) ? image_override : 0;
@@ -388,7 +398,7 @@ static void DisasterTick_Aircraft(Vehicle *v, uint16 image_override, bool leave_
if ((leave_at_top && gp.x < (-10 * TILE_SIZE)) || (!leave_at_top && gp.x > (int)MapSizeX() * TILE_SIZE + 9 * TILE_SIZE - 1)) {
delete v;
- return;
+ return false;
}
if (v->current_order.GetDestination() == 2) {
@@ -422,10 +432,10 @@ static void DisasterTick_Aircraft(Vehicle *v, uint16 image_override, bool leave_
int x = v->x_pos - (15 * TILE_SIZE);
int y = v->y_pos;
- if ((uint)x > MapMaxX() * TILE_SIZE - 1) return;
+ if ((uint)x > MapMaxX() * TILE_SIZE - 1) return true;
TileIndex tile = TileVirtXY(x, y);
- if (!IsTileType(tile, MP_INDUSTRY)) return;
+ if (!IsTileType(tile, MP_INDUSTRY)) return true;
IndustryID ind = GetIndustryIndex(tile);
v->dest_tile = ind;
@@ -435,29 +445,33 @@ static void DisasterTick_Aircraft(Vehicle *v, uint16 image_override, bool leave_
v->age = 0;
}
}
+
+ return true;
}
/** Airplane handling. */
-static void DisasterTick_Airplane(Vehicle *v)
+static bool DisasterTick_Airplane(Vehicle *v)
{
- DisasterTick_Aircraft(v, SPR_F_15_FIRING, true, STR_NEWS_DISASTER_AIRPLANE_OIL_REFINERY, INDUSTRYBEH_AIRPLANE_ATTACKS);
+ return DisasterTick_Aircraft(v, SPR_F_15_FIRING, true, STR_NEWS_DISASTER_AIRPLANE_OIL_REFINERY, INDUSTRYBEH_AIRPLANE_ATTACKS);
}
/** Helicopter handling. */
-static void DisasterTick_Helicopter(Vehicle *v)
+static bool DisasterTick_Helicopter(Vehicle *v)
{
- DisasterTick_Aircraft(v, SPR_AH_64A_FIRING, false, STR_NEWS_DISASTER_HELICOPTER_FACTORY, INDUSTRYBEH_CHOPPER_ATTACKS);
+ return DisasterTick_Aircraft(v, SPR_AH_64A_FIRING, false, STR_NEWS_DISASTER_HELICOPTER_FACTORY, INDUSTRYBEH_CHOPPER_ATTACKS);
}
/** Helicopter rotor blades; keep these spinning */
-static void DisasterTick_Helicopter_Rotors(Vehicle *v)
+static bool DisasterTick_Helicopter_Rotors(Vehicle *v)
{
v->tick_counter++;
- if (HasBit(v->tick_counter, 0)) return;
+ if (HasBit(v->tick_counter, 0)) return true;
if (++v->cur_image > SPR_ROTOR_MOVING_3) v->cur_image = SPR_ROTOR_MOVING_1;
VehicleMove(v, true);
+
+ return true;
}
/**
@@ -466,7 +480,7 @@ static void DisasterTick_Helicopter_Rotors(Vehicle *v)
* 1: Land there and breakdown all trains in a radius of 12 tiles; and now we wait...
* because as soon as the Ufo lands, a fighter jet, a Skyranger, is called to clear up the mess
*/
-static void DisasterTick_Big_Ufo(Vehicle *v)
+static bool DisasterTick_Big_Ufo(Vehicle *v)
{
v->tick_counter++;
@@ -478,19 +492,19 @@ static void DisasterTick_Big_Ufo(Vehicle *v)
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
- return;
+ return true;
}
if (!IsValidTile(v->dest_tile)) {
/* Make sure we don't land outside the map. */
delete v;
- return;
+ return false;
}
byte z = GetSlopeZ(v->x_pos, v->y_pos);
if (z < v->z_pos) {
SetDisasterVehiclePos(v, v->x_pos, v->y_pos, v->z_pos - 1);
- return;
+ return true;
}
v->current_order.SetDestination(2);
@@ -514,7 +528,7 @@ static void DisasterTick_Big_Ufo(Vehicle *v)
if (!Vehicle::CanAllocateItem(2)) {
delete v;
- return;
+ return false;
}
u = new DisasterVehicle();
@@ -533,12 +547,12 @@ static void DisasterTick_Big_Ufo(Vehicle *v)
v->direction = GetDirectionTowards(v, x, y);
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
- return;
+ return true;
}
if (++v->age < 6) {
v->dest_tile = RandomTile();
- return;
+ return true;
}
v->current_order.SetDestination(1);
@@ -554,13 +568,15 @@ static void DisasterTick_Big_Ufo(Vehicle *v)
v->dest_tile = tile;
v->age = 0;
}
+
+ return true;
}
/**
* Skyranger destroying (Big) Ufo handling, v->current_order.dest states:
* 0: Home in on landed Ufo and shoot it down
*/
-static void DisasterTick_Big_Ufo_Destroyer(Vehicle *v)
+static bool DisasterTick_Big_Ufo_Destroyer(Vehicle *v)
{
v->tick_counter++;
@@ -569,12 +585,12 @@ static void DisasterTick_Big_Ufo_Destroyer(Vehicle *v)
if (gp.x > (int)MapSizeX() * TILE_SIZE + 9 * TILE_SIZE - 1) {
delete v;
- return;
+ return false;
}
if (v->current_order.GetDestination() == 0) {
Vehicle *u = Vehicle::Get(v->u.disaster.big_ufo_destroyer_target);
- if (Delta(v->x_pos, u->x_pos) > TILE_SIZE) return;
+ if (Delta(v->x_pos, u->x_pos) > TILE_SIZE) return true;
v->current_order.SetDestination(1);
CreateEffectVehicleRel(u, 0, 7, 8, EV_EXPLOSION_LARGE);
@@ -598,22 +614,24 @@ static void DisasterTick_Big_Ufo_Destroyer(Vehicle *v)
}
}
}
+
+ return true;
}
/**
* Submarine, v->current_order.dest states:
* Unused, just float around aimlessly and pop up at different places, turning around
*/
-static void DisasterTick_Submarine(Vehicle *v)
+static bool DisasterTick_Submarine(Vehicle *v)
{
v->tick_counter++;
if (++v->age > 8880) {
delete v;
- return;
+ return false;
}
- if (!HasBit(v->tick_counter, 0)) return;
+ if (!HasBit(v->tick_counter, 0)) return true;
TileIndex tile = v->tile + TileOffsByDiagDir(DirToDiagDir(v->direction));
if (IsValidTile(tile)) {
@@ -621,16 +639,22 @@ static void DisasterTick_Submarine(Vehicle *v)
if (trackbits == TRACK_BIT_ALL && !Chance16(1, 90)) {
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
SetDisasterVehiclePos(v, gp.x, gp.y, v->z_pos);
- return;
+ return true;
}
}
v->direction = ChangeDir(v->direction, GB(Random(), 0, 1) ? DIRDIFF_90RIGHT : DIRDIFF_90LEFT);
+
+ return true;
}
-static void DisasterTick_NULL(Vehicle *v) {}
-typedef void DisasterVehicleTickProc(Vehicle *v);
+static bool DisasterTick_NULL(Vehicle *v)
+{
+ return true;
+}
+
+typedef bool DisasterVehicleTickProc(Vehicle *v);
static DisasterVehicleTickProc * const _disastervehicle_tick_procs[] = {
DisasterTick_Zeppeliner, DisasterTick_NULL,
@@ -644,9 +668,9 @@ static DisasterVehicleTickProc * const _disastervehicle_tick_procs[] = {
};
-void DisasterVehicle::Tick()
+bool DisasterVehicle::Tick()
{
- _disastervehicle_tick_procs[this->subtype](this);
+ return _disastervehicle_tick_procs[this->subtype](this);
}
typedef void DisasterInitProc();
diff --git a/src/effectvehicle.cpp b/src/effectvehicle.cpp
index 1b168daec..767c31702 100644
--- a/src/effectvehicle.cpp
+++ b/src/effectvehicle.cpp
@@ -20,7 +20,7 @@ static void ChimneySmokeInit(Vehicle *v)
v->progress = GB(r, 16, 3);
}
-static void ChimneySmokeTick(Vehicle *v)
+static bool ChimneySmokeTick(Vehicle *v)
{
if (v->progress > 0) {
v->progress--;
@@ -28,7 +28,7 @@ static void ChimneySmokeTick(Vehicle *v)
TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
if (!IsTileType(tile, MP_INDUSTRY)) {
delete v;
- return;
+ return false;
}
if (v->cur_image != SPR_CHIMNEY_SMOKE_7) {
@@ -39,6 +39,8 @@ static void ChimneySmokeTick(Vehicle *v)
v->progress = 7;
VehicleMove(v, true);
}
+
+ return true;
}
static void SteamSmokeInit(Vehicle *v)
@@ -47,7 +49,7 @@ static void SteamSmokeInit(Vehicle *v)
v->progress = 12;
}
-static void SteamSmokeTick(Vehicle *v)
+static bool SteamSmokeTick(Vehicle *v)
{
bool moved = false;
@@ -63,12 +65,14 @@ static void SteamSmokeTick(Vehicle *v)
v->cur_image++;
} else {
delete v;
- return;
+ return false;
}
moved = true;
}
if (moved) VehicleMove(v, true);
+
+ return true;
}
static void DieselSmokeInit(Vehicle *v)
@@ -77,7 +81,7 @@ static void DieselSmokeInit(Vehicle *v)
v->progress = 0;
}
-static void DieselSmokeTick(Vehicle *v)
+static bool DieselSmokeTick(Vehicle *v)
{
v->progress++;
@@ -90,8 +94,11 @@ static void DieselSmokeTick(Vehicle *v)
VehicleMove(v, true);
} else {
delete v;
+ return false;
}
}
+
+ return true;
}
static void ElectricSparkInit(Vehicle *v)
@@ -100,7 +107,7 @@ static void ElectricSparkInit(Vehicle *v)
v->progress = 1;
}
-static void ElectricSparkTick(Vehicle *v)
+static bool ElectricSparkTick(Vehicle *v)
{
if (v->progress < 2) {
v->progress++;
@@ -111,8 +118,11 @@ static void ElectricSparkTick(Vehicle *v)
VehicleMove(v, true);
} else {
delete v;
+ return false;
}
}
+
+ return true;
}
static void SmokeInit(Vehicle *v)
@@ -121,7 +131,7 @@ static void SmokeInit(Vehicle *v)
v->progress = 12;
}
-static void SmokeTick(Vehicle *v)
+static bool SmokeTick(Vehicle *v)
{
bool moved = false;
@@ -137,12 +147,14 @@ static void SmokeTick(Vehicle *v)
v->cur_image++;
} else {
delete v;
- return;
+ return false;
}
moved = true;
}
if (moved) VehicleMove(v, true);
+
+ return true;
}
static void ExplosionLargeInit(Vehicle *v)
@@ -151,7 +163,7 @@ static void ExplosionLargeInit(Vehicle *v)
v->progress = 0;
}
-static void ExplosionLargeTick(Vehicle *v)
+static bool ExplosionLargeTick(Vehicle *v)
{
v->progress++;
if ((v->progress & 3) == 0) {
@@ -160,8 +172,11 @@ static void ExplosionLargeTick(Vehicle *v)
VehicleMove(v, true);
} else {
delete v;
+ return false;
}
}
+
+ return true;
}
static void BreakdownSmokeInit(Vehicle *v)
@@ -170,7 +185,7 @@ static void BreakdownSmokeInit(Vehicle *v)
v->progress = 0;
}
-static void BreakdownSmokeTick(Vehicle *v)
+static bool BreakdownSmokeTick(Vehicle *v)
{
v->progress++;
if ((v->progress & 7) == 0) {
@@ -185,7 +200,10 @@ static void BreakdownSmokeTick(Vehicle *v)
v->u.effect.animation_state--;
if (v->u.effect.animation_state == 0) {
delete v;
+ return false;
}
+
+ return true;
}
static void ExplosionSmallInit(Vehicle *v)
@@ -194,7 +212,7 @@ static void ExplosionSmallInit(Vehicle *v)
v->progress = 0;
}
-static void ExplosionSmallTick(Vehicle *v)
+static bool ExplosionSmallTick(Vehicle *v)
{
v->progress++;
if ((v->progress & 3) == 0) {
@@ -203,8 +221,11 @@ static void ExplosionSmallTick(Vehicle *v)
VehicleMove(v, true);
} else {
delete v;
+ return false;
}
}
+
+ return true;
}
static void BulldozerInit(Vehicle *v)
@@ -254,7 +275,7 @@ static const struct {
{ 0, -1 }
};
-static void BulldozerTick(Vehicle *v)
+static bool BulldozerTick(Vehicle *v)
{
v->progress++;
if ((v->progress & 7) == 0) {
@@ -271,11 +292,13 @@ static void BulldozerTick(Vehicle *v)
v->u.effect.animation_state++;
if (v->u.effect.animation_state == lengthof(_bulldozer_movement)) {
delete v;
- return;
+ return false;
}
}
VehicleMove(v, true);
}
+
+ return true;
}
static void BubbleInit(Vehicle *v)
@@ -435,18 +458,18 @@ static const BubbleMovement * const _bubble_movement[] = {
_bubble_absorb,
};
-static void BubbleTick(Vehicle *v)
+static bool BubbleTick(Vehicle *v)
{
uint anim_state;
v->progress++;
- if ((v->progress & 3) != 0) return;
+ if ((v->progress & 3) != 0) return true;
if (v->spritenum == 0) {
v->cur_image++;
if (v->cur_image < SPR_BUBBLE_GENERATE_3) {
VehicleMove(v, true);
- return;
+ return true;
}
if (v->u.effect.animation_substate != 0) {
v->spritenum = GB(Random(), 0, 2) + 1;
@@ -462,7 +485,7 @@ static void BubbleTick(Vehicle *v)
if (b->y == 4 && b->x == 0) {
delete v;
- return;
+ return false;
}
if (b->y == 4 && b->x == 1) {
@@ -492,11 +515,13 @@ static void BubbleTick(Vehicle *v)
v->cur_image = SPR_BUBBLE_0 + b->image;
VehicleMove(v, true);
+
+ return true;
}
typedef void EffectInitProc(Vehicle *v);
-typedef void EffectTickProc(Vehicle *v);
+typedef bool EffectTickProc(Vehicle *v);
static EffectInitProc * const _effect_init_procs[] = {
ChimneySmokeInit,
@@ -558,9 +583,9 @@ Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVeh
return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type);
}
-void EffectVehicle::Tick()
+bool EffectVehicle::Tick()
{
- _effect_tick_procs[this->subtype](this);
+ return _effect_tick_procs[this->subtype](this);
}
void EffectVehicle::UpdateDeltaXY(Direction direction)
diff --git a/src/effectvehicle_base.h b/src/effectvehicle_base.h
index 92742cf90..789dd1f36 100644
--- a/src/effectvehicle_base.h
+++ b/src/effectvehicle_base.h
@@ -31,7 +31,7 @@ struct EffectVehicle : public Vehicle {
const char *GetTypeString() const { return "special vehicle"; }
void UpdateDeltaXY(Direction direction);
- void Tick();
+ bool Tick();
};
#endif /* EFFECTVEHICLE_BASE_H */
diff --git a/src/roadveh.h b/src/roadveh.h
index 31f8e49a8..2cfee9043 100644
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -99,7 +99,7 @@ struct RoadVehicle : public Vehicle {
Money GetRunningCost() const { return RoadVehInfo(this->engine_type)->running_cost * GetPriceByIndex(RoadVehInfo(this->engine_type)->running_cost_class); }
bool IsInDepot() const { return this->u.road.state == RVSB_IN_DEPOT; }
bool IsStoppedInDepot() const;
- void Tick();
+ bool Tick();
void OnNewDay();
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index f76f8428a..a84f473bf 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -540,7 +540,7 @@ static void RoadVehSetRandomDirection(Vehicle *v)
} while ((v = v->Next()) != NULL);
}
-static void RoadVehIsCrashed(Vehicle *v)
+static bool RoadVehIsCrashed(Vehicle *v)
{
v->u.road.crashed_ctr++;
if (v->u.road.crashed_ctr == 2) {
@@ -548,8 +548,12 @@ static void RoadVehIsCrashed(Vehicle *v)
} else if (v->u.road.crashed_ctr <= 45) {
if ((v->tick_counter & 7) == 0) RoadVehSetRandomDirection(v);
} else if (v->u.road.crashed_ctr >= 2220 && !(v->tick_counter & 0x1F)) {
+ bool ret = v->Next() != NULL;
DeleteLastRoadVeh(v);
+ return ret;
}
+
+ return true;
}
static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
@@ -1735,7 +1739,7 @@ again:
return true;
}
-static void RoadVehController(Vehicle *v)
+static bool RoadVehController(Vehicle *v)
{
/* decrease counters */
v->tick_counter++;
@@ -1744,8 +1748,7 @@ static void RoadVehController(Vehicle *v)
/* handle crashed */
if (v->vehstatus & VS_CRASHED) {
- RoadVehIsCrashed(v);
- return;
+ return RoadVehIsCrashed(v);
}
RoadVehCheckTrainCrash(v);
@@ -1754,19 +1757,19 @@ static void RoadVehController(Vehicle *v)
if (v->breakdown_ctr != 0) {
if (v->breakdown_ctr <= 2) {
HandleBrokenRoadVeh(v);
- return;
+ return true;
}
if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
- if (v->vehstatus & VS_STOPPED) return;
+ if (v->vehstatus & VS_STOPPED) return true;
ProcessOrders(v);
v->HandleLoading();
- if (v->current_order.IsType(OT_LOADING)) return;
+ if (v->current_order.IsType(OT_LOADING)) return true;
- if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return;
+ if (v->IsInDepot() && RoadVehLeaveDepot(v, true)) return true;
/* Check how far the vehicle needs to proceed */
int j = RoadVehAccelerate(v);
@@ -1796,6 +1799,8 @@ static void RoadVehController(Vehicle *v)
}
if (v->progress == 0) v->progress = j;
+
+ return true;
}
static void AgeRoadVehCargo(Vehicle *v)
@@ -1804,14 +1809,16 @@ static void AgeRoadVehCargo(Vehicle *v)
v->cargo.AgeCargo();
}
-void RoadVehicle::Tick()
+bool RoadVehicle::Tick()
{
AgeRoadVehCargo(this);
if (IsRoadVehFront(this)) {
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
- RoadVehController(this);
+ return RoadVehController(this);
}
+
+ return true;
}
static void CheckIfRoadVehNeedsService(Vehicle *v)
diff --git a/src/ship.h b/src/ship.h
index d826e1cbd..95df31e54 100644
--- a/src/ship.h
+++ b/src/ship.h
@@ -40,7 +40,7 @@ struct Ship: public Vehicle {
int GetDisplayMaxSpeed() const { return this->max_speed / 2; }
Money GetRunningCost() const;
bool IsInDepot() const { return this->u.ship.state == TRACK_BIT_DEPOT; }
- void Tick();
+ bool Tick();
void OnNewDay();
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp
index 17b56965d..d39bcdcbe 100644
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -708,12 +708,14 @@ static void AgeShipCargo(Vehicle *v)
v->cargo.AgeCargo();
}
-void Ship::Tick()
+bool Ship::Tick()
{
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
AgeShipCargo(this);
ShipController(this);
+
+ return true;
}
/** Build a ship.
diff --git a/src/train.h b/src/train.h
index 750dbe3f1..4816a251b 100644
--- a/src/train.h
+++ b/src/train.h
@@ -329,7 +329,7 @@ struct Train : public Vehicle {
Money GetRunningCost() const;
bool IsInDepot() const { return CheckTrainInDepot(this, false) != -1; }
bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; }
- void Tick();
+ bool Tick();
void OnNewDay();
TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index a0cc69e1a..e60df0daf 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -4022,7 +4022,7 @@ static void ChangeTrainDirRandomly(Vehicle *v)
} while ((v = v->Next()) != NULL);
}
-static void HandleCrashedTrain(Vehicle *v)
+static bool HandleCrashedTrain(Vehicle *v)
{
int state = ++v->u.rail.crash_anim_pos;
@@ -4052,9 +4052,13 @@ static void HandleCrashedTrain(Vehicle *v)
if (state <= 240 && !(v->tick_counter & 3)) ChangeTrainDirRandomly(v);
if (state >= 4440 && !(v->tick_counter & 0x1F)) {
+ bool ret = v->Next() != NULL;
DeleteLastWagon(v);
InvalidateWindow(WC_REPLACE_VEHICLE, (v->group_id << 16) | VEH_TRAIN);
+ return ret;
}
+
+ return true;
}
static void HandleBrokenTrain(Vehicle *v)
@@ -4249,12 +4253,11 @@ static bool TrainCheckIfLineEnds(Vehicle *v)
}
-static void TrainLocoHandler(Vehicle *v, bool mode)
+static bool TrainLocoHandler(Vehicle *v, bool mode)
{
/* train has crashed? */
if (v->vehstatus & VS_CRASHED) {
- if (!mode) HandleCrashedTrain(v);
- return;
+ return mode ? true : HandleCrashedTrain(v); // 'this' can be deleted here
}
if (v->u.rail.force_proceed != 0) {
@@ -4267,7 +4270,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
if (v->breakdown_ctr != 0) {
if (v->breakdown_ctr <= 2) {
HandleBrokenTrain(v);
- return;
+ return true;
}
if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--;
}
@@ -4277,7 +4280,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
}
/* exit if train is stopped */
- if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return;
+ if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return true;
bool valid_order = v->current_order.IsValid() && v->current_order.GetType() != OT_CONDITIONAL;
if (ProcessOrders(v) && CheckReverseTrain(v)) {
@@ -4285,14 +4288,14 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
v->cur_speed = 0;
v->subspeed = 0;
ReverseTrainDirection(v);
- return;
+ return true;
}
v->HandleLoading(mode);
- if (v->current_order.IsType(OT_LOADING)) return;
+ if (v->current_order.IsType(OT_LOADING)) return true;
- if (CheckTrainStayInDepot(v)) return;
+ if (CheckTrainStayInDepot(v)) return true;
if (!mode) HandleLocomotiveSmokeCloud(v);
@@ -4308,7 +4311,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
/* Should we try reversing this tick if still stuck? */
bool turn_around = v->load_unload_time_rem % (_settings_game.pf.wait_for_pbs_path * DAY_TICKS) == 0 && _settings_game.pf.wait_for_pbs_path < 255;
- if (!turn_around && v->load_unload_time_rem % _settings_game.pf.path_backoff_interval != 0 && v->u.rail.force_proceed == 0) return;
+ if (!turn_around && v->load_unload_time_rem % _settings_game.pf.path_backoff_interval != 0 && v->u.rail.force_proceed == 0) return true;
if (!TryPathReserve(v)) {
/* Still stuck. */
if (turn_around) ReverseTrainDirection(v);
@@ -4326,7 +4329,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
v->load_unload_time_rem = 0;
}
/* Exit if force proceed not pressed, else reset stuck flag anyway. */
- if (v->u.rail.force_proceed == 0) return;
+ if (v->u.rail.force_proceed == 0) return true;
ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
v->load_unload_time_rem = 0;
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
@@ -4336,7 +4339,7 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
if (v->current_order.IsType(OT_LEAVESTATION)) {
v->current_order.Free();
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
- return;
+ return true;
}
int j = UpdateTrainSpeed(v);
@@ -4387,6 +4390,8 @@ static void TrainLocoHandler(Vehicle *v, bool mode)
}
if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
+
+ return true;
}
@@ -4412,7 +4417,7 @@ Money Train::GetRunningCost() const
}
-void Train::Tick()
+bool Train::Tick()
{
if (_age_cargo_skip_counter == 0) this->cargo.AgeCargo();
@@ -4420,17 +4425,25 @@ void Train::Tick()
if (IsFrontEngine(this)) {
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
+
this->current_order_time++;
- TrainLocoHandler(this, false);
+ if (!TrainLocoHandler(this, false)) return false;
/* make sure vehicle wasn't deleted. */
- if (this->type == VEH_TRAIN && IsFrontEngine(this))
- TrainLocoHandler(this, true);
+ assert(this->IsValid());
+ assert(IsFrontEngine(this));
+
+ return TrainLocoHandler(this, true);
} else if (IsFreeWagon(this) && HASBITS(this->vehstatus, VS_CRASHED)) {
/* Delete flooded standalone wagon chain */
- if (++this->u.rail.crash_anim_pos >= 4400) delete this;
+ if (++this->u.rail.crash_anim_pos >= 4400) {
+ delete this;
+ return false;
+ }
}
+
+ return true;
}
static void CheckIfTrainNeedsService(Vehicle *v)
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index e449a03f5..2127d6aec 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -604,7 +604,10 @@ void CallVehicleTicks()
Vehicle *v;
FOR_ALL_VEHICLES(v) {
- v->Tick();
+ /* Vehicle could be deleted in this tick */
+ if (!v->Tick()) continue;
+
+ assert(v->IsValid());
switch (v->type) {
default: break;
diff --git a/src/vehicle_base.h b/src/vehicle_base.h
index 423da71af..e602cc4ed 100644
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -423,8 +423,9 @@ public:
/**
* Calls the tick handler of the vehicle
+ * @return is this vehicle still valid?
*/
- virtual void Tick() {};
+ virtual bool Tick() { return true; };
/**
* Calls the new day handler of the vehicle
@@ -620,7 +621,7 @@ struct DisasterVehicle : public Vehicle {
const char *GetTypeString() const { return "disaster vehicle"; }
void UpdateDeltaXY(Direction direction);
- void Tick();
+ bool Tick();
};
/**
@@ -639,7 +640,6 @@ struct InvalidVehicle : public Vehicle {
virtual ~InvalidVehicle() {}
const char *GetTypeString() const { return "invalid vehicle"; }
- void Tick() {}
};
#define FOR_ALL_VEHICLES_FROM(v, start) for (v = Vehicle::Get(start); v != NULL; v = (v->index + 1U < Vehicle::GetPoolSize()) ? Vehicle::Get(v->index + 1) : NULL) if (v->IsValid())