(svn r16376) -Codechange: Vehicle::Tick() now returns false if the vehicle was deleted

This commit is contained in:
smatz 2009-05-22 13:53:14 +00:00
parent 561d97880d
commit b687ac51ee
13 changed files with 189 additions and 107 deletions

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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)

View File

@ -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 */

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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())