Changeset - r24578:e105ade320f5
[Not reviewed]
master
0 6 0
Patric Stout - 4 years ago 2021-01-05 20:39:23
truebrain@openttd.org
Fix #7611: keeps news about accidents around after vehicle is cleaned up (#8497)

When a vehicle is cleaned up, all news that points to the news is
also removed. This was a bit evil, as it would also remove any
news related to crashed, acting like the crash never happened.
This left players a bit in the dark what was going on exactly.
6 files changed with 10 insertions and 14 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -1324,25 +1324,25 @@ static void CrashAirplane(Aircraft *v)
 
	const Station *st = GetTargetAirportIfValid(v);
 
	StringID newsitem;
 
	if (st == nullptr) {
 
		newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
 
	} else {
 
		SetDParam(1, st->index);
 
		newsitem = STR_NEWS_AIRCRAFT_CRASH;
 
	}
 

	
 
	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
 
	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
 

	
 
	AddVehicleNewsItem(newsitem, NT_ACCIDENT, v->index, st != nullptr ? st->index : INVALID_STATION);
 
	AddTileNewsItem(newsitem, NT_ACCIDENT, v->tile, nullptr, st != nullptr ? st->index : INVALID_STATION);
 

	
 
	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
 
	if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
}
 

	
 
/**
 
 * Decide whether aircraft \a v should crash.
 
 * @param v Aircraft to test.
 
 */
 
static void MaybeCrashAirplane(Aircraft *v)
 
{
 

	
src/disaster_vehicle.cpp
Show inline comments
 
@@ -234,25 +234,25 @@ static bool DisasterTick_Zeppeliner(Disa
 
				v->current_order.SetDestination(2);
 
				v->age = 0;
 
			}
 

	
 
			if (GB(v->tick_counter, 0, 3) == 0) CreateEffectVehicleRel(v, 0, -17, 2, EV_CRASH_SMOKE);
 

	
 
		} else if (v->current_order.GetDestination() == 0) {
 
			if (IsValidTile(v->tile) && IsAirportTile(v->tile)) {
 
				v->current_order.SetDestination(1);
 
				v->age = 0;
 

	
 
				SetDParam(0, GetStationIndex(v->tile));
 
				AddVehicleNewsItem(STR_NEWS_DISASTER_ZEPPELIN, NT_ACCIDENT, v->index); // Delete the news, when the zeppelin is gone
 
				AddTileNewsItem(STR_NEWS_DISASTER_ZEPPELIN, NT_ACCIDENT, v->tile);
 
				AI::NewEvent(GetTileOwner(v->tile), new ScriptEventDisasterZeppelinerCrashed(GetStationIndex(v->tile)));
 
			}
 
		}
 

	
 
		if (v->y_pos >= (int)((MapSizeY() + 9) * TILE_SIZE - 1)) {
 
			delete v;
 
			return false;
 
		}
 

	
 
		return true;
 
	}
 

	
 
@@ -368,25 +368,25 @@ static bool DisasterTick_Ufo(DisasterVeh
 
		v->direction = GetDirectionTowards(v, u->x_pos, u->y_pos);
 
		GetNewVehiclePosResult gp = GetNewVehiclePos(v);
 

	
 
		int z = v->z_pos;
 
		if (dist <= TILE_SIZE && z > u->z_pos) z--;
 
		v->UpdatePosition(gp.x, gp.y, z);
 

	
 
		if (z <= u->z_pos && (u->vehstatus & VS_HIDDEN) == 0) {
 
			v->age++;
 
			if (u->crashed_ctr == 0) {
 
				u->Crash();
 

	
 
				AddVehicleNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NT_ACCIDENT, u->index); // delete the news, when the roadvehicle is gone
 
				AddTileNewsItem(STR_NEWS_DISASTER_SMALL_UFO, NT_ACCIDENT, u->tile);
 

	
 
				AI::NewEvent(u->owner, new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
 
				Game::NewEvent(new ScriptEventVehicleCrashed(u->index, u->tile, ScriptEventVehicleCrashed::CRASH_RV_UFO));
 
			}
 
		}
 

	
 
		/* Destroy? */
 
		if (v->age > 50) {
 
			CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
 
			if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
			delete v;
 
			return false;
 
@@ -447,25 +447,25 @@ static bool DisasterTick_Aircraft(Disast
 

	
 
			if (++v->age >= 55) v->current_order.SetDestination(3);
 
		}
 
	} else if (v->current_order.GetDestination() == 1) {
 
		if (++v->age == 112) {
 
			v->current_order.SetDestination(2);
 
			v->age = 0;
 

	
 
			Industry *i = Industry::Get(v->dest_tile); // Industry destructor calls ReleaseDisastersTargetingIndustry, so this is valid
 
			DestructIndustry(i);
 

	
 
			SetDParam(0, i->town->index);
 
			AddIndustryNewsItem(news_message, NT_ACCIDENT, i->index); // delete the news, when the industry closes
 
			AddTileNewsItem(news_message, NT_ACCIDENT, v->dest_tile);
 
			if (_settings_client.sound.disaster) SndPlayTileFx(SND_12_EXPLOSION, i->location.tile);
 
		}
 
	} else if (v->current_order.GetDestination() == 0) {
 
		int x = v->x_pos + ((leave_at_top ? -15 : 15) * TILE_SIZE);
 
		int y = v->y_pos;
 

	
 
		if ((uint)x > MapMaxX() * TILE_SIZE - 1) return true;
 

	
 
		TileIndex tile = TileVirtXY(x, y);
 
		if (!IsTileType(tile, MP_INDUSTRY)) return true;
 

	
 
		IndustryID ind = GetIndustryIndex(tile);
src/news_func.h
Show inline comments
 
@@ -33,27 +33,27 @@ static inline void AddVehicleNewsItem(St
 
}
 

	
 
/**
 
 * Adds a vehicle-advice news item.
 
 *
 
 * @warning DParam 0 must reference the vehicle!
 
 */
 
static inline void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
 
{
 
	AddNewsItem(string, NT_ADVICE, NF_INCOLOUR | NF_SMALL | NF_VEHICLE_PARAM0, NR_VEHICLE, vehicle);
 
}
 

	
 
static inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, void *free_data = nullptr)
 
static inline void AddTileNewsItem(StringID string, NewsType type, TileIndex tile, void *free_data = nullptr, StationID station = INVALID_STATION)
 
{
 
	AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile, NR_NONE, UINT32_MAX, free_data);
 
	AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_TILE, tile, station == INVALID_STATION ? NR_NONE : NR_STATION, station, free_data);
 
}
 

	
 
static inline void AddIndustryNewsItem(StringID string, NewsType type, IndustryID industry)
 
{
 
	AddNewsItem(string, type, NF_NO_TRANSPARENT | NF_SHADE | NF_THIN, NR_INDUSTRY, industry);
 
}
 

	
 
void NewsLoop();
 
void InitNewsItemStructs();
 

	
 
extern const NewsItem *_statusbar_news_item;
 

	
src/roadveh_cmd.cpp
Show inline comments
 
@@ -543,30 +543,26 @@ uint RoadVehicle::Crash(bool flooded)
 
	this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
 
	return pass;
 
}
 

	
 
static void RoadVehCrash(RoadVehicle *v)
 
{
 
	uint pass = v->Crash();
 

	
 
	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
 
	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_RV_LEVEL_CROSSING));
 

	
 
	SetDParam(0, pass);
 
	AddVehicleNewsItem(
 
		(pass == 1) ?
 
			STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH,
 
		NT_ACCIDENT,
 
		v->index
 
	);
 
	StringID newsitem = (pass == 1) ? STR_NEWS_ROAD_VEHICLE_CRASH_DRIVER : STR_NEWS_ROAD_VEHICLE_CRASH;
 
	AddTileNewsItem(newsitem, NT_ACCIDENT, v->tile);
 

	
 
	ModifyStationRatingAround(v->tile, v->owner, -160, 22);
 
	if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
}
 

	
 
static bool RoadVehCheckTrainCrash(RoadVehicle *v)
 
{
 
	for (RoadVehicle *u = v; u != nullptr; u = u->Next()) {
 
		if (u->state == RVSB_WORMHOLE) continue;
 

	
 
		TileIndex tile = u->tile;
 

	
src/train_cmd.cpp
Show inline comments
 
@@ -3043,25 +3043,25 @@ static bool CheckTrainCollision(Train *v
 
	/* find colliding vehicles */
 
	if (v->track == TRACK_BIT_WORMHOLE) {
 
		FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum);
 
		FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum);
 
	} else {
 
		FindVehicleOnPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum);
 
	}
 

	
 
	/* any dead -> no crash */
 
	if (tcc.num == 0) return false;
 

	
 
	SetDParam(0, tcc.num);
 
	AddVehicleNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->index);
 
	AddTileNewsItem(STR_NEWS_TRAIN_CRASH, NT_ACCIDENT, v->tile);
 

	
 
	ModifyStationRatingAround(v->tile, v->owner, -160, 30);
 
	if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_13_BIG_CRASH, v);
 
	return true;
 
}
 

	
 
static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
 
{
 
	if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return nullptr;
 

	
 
	Train *t = Train::From(v);
 
	DiagDirection exitdir = *(DiagDirection *)data;
src/water_cmd.cpp
Show inline comments
 
@@ -968,25 +968,25 @@ static void GetTileDesc_Water(TileIndex 
 
/**
 
 * Handle the flooding of a vehicle. This sets the vehicle state to crashed,
 
 * creates a newsitem and dirties the necessary windows.
 
 * @param v The vehicle to flood.
 
 */
 
static void FloodVehicle(Vehicle *v)
 
{
 
	uint pass = v->Crash(true);
 

	
 
	AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED));
 
	Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_FLOODED));
 
	SetDParam(0, pass);
 
	AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NT_ACCIDENT, v->index);
 
	AddTileNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE, NT_ACCIDENT, v->tile);
 
	CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 
	if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
 
}
 

	
 
/**
 
 * Flood a vehicle if we are allowed to flood it, i.e. when it is on the ground.
 
 * @param v    The vehicle to test for flooding.
 
 * @param data The z of level to flood.
 
 * @return nullptr as we always want to remove everything.
 
 */
 
static Vehicle *FloodVehicleProc(Vehicle *v, void *data)
 
{
0 comments (0 inline, 0 general)