Changeset - r13863:252b1a5c4f87
[Not reviewed]
master
0 10 0
rubidium - 15 years ago 2009-12-04 20:29:46
rubidium@openttd.org
(svn r18402) -Codechange: unify/centralise the code for crashing vehicles
10 files changed with 77 insertions and 116 deletions:
0 comments (0 inline, 0 general)
src/aircraft.h
Show inline comments
 
@@ -99,12 +99,13 @@ struct Aircraft : public SpecializedVehi
 
	int GetDisplaySpeed() const { return this->cur_speed; }
 
	int GetDisplayMaxSpeed() const { return this->max_speed; }
 
	Money GetRunningCost() const;
 
	bool IsInDepot() const { return (this->vehstatus & VS_HIDDEN) != 0 && IsHangarTile(this->tile); }
 
	bool Tick();
 
	void OnNewDay();
 
	uint Crash(bool flooded = false);
 
	TileIndex GetOrderStationLocation(StationID station);
 
	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 

	
 
	/**
 
	 * Check if the aircraft type is a normal flying device; eg
 
	 * not a rotor or a shadow
src/aircraft_cmd.cpp
Show inline comments
 
@@ -1235,25 +1235,27 @@ TileIndex Aircraft::GetOrderStationLocat
 
void Aircraft::MarkDirty()
 
{
 
	this->UpdateViewport(false, false);
 
	if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this);
 
}
 

	
 

	
 
uint Aircraft::Crash(bool flooded)
 
{
 
	uint pass = Vehicle::Crash(flooded) + 2; // pilots
 
	this->crashed_counter = flooded ? 9000 : 0; // max 10000, disappear pretty fast when flooded
 

	
 
	return pass;
 
}
 

	
 
static void CrashAirplane(Aircraft *v)
 
{
 
	v->vehstatus |= VS_CRASHED;
 
	v->crashed_counter = 0;
 

	
 
	CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 

	
 
	v->MarkDirty();
 
	SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
	uint amt = 2;
 
	if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) amt += v->cargo.Count();
 
	SetDParam(0, amt);
 
	uint pass = v->Crash();
 
	SetDParam(0, pass);
 

	
 
	v->cargo.Truncate(0);
 
	v->Next()->cargo.Truncate(0);
 
	const Station *st = GetTargetAirportIfValid(v);
 
	StringID newsitem;
 
	AIEventVehicleCrashed::CrashReason crash_reason;
src/disaster_cmd.cpp
Show inline comments
 
@@ -337,24 +337,19 @@ static bool DisasterTick_Ufo(DisasterVeh
 
		if (dist <= TILE_SIZE && z > u->z_pos) z--;
 
		SetDisasterVehiclePos(v, gp.x, gp.y, z);
 

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

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

	
 
				AI::NewEvent(u->owner, new AIEventVehicleCrashed(u->index, u->tile, AIEventVehicleCrashed::CRASH_RV_UFO));
 

	
 
				for (Vehicle *w = u; w != NULL; w = w->Next()) {
 
					w->vehstatus |= VS_CRASHED;
 
					MarkSingleVehicleDirty(w);
 
				}
 
			}
 
		}
 

	
 
		/* Destroy? */
 
		if (v->age > 50) {
 
			CreateEffectVehicleRel(v, 0, 7, 8, EV_EXPLOSION_LARGE);
src/roadveh.h
Show inline comments
 
@@ -122,12 +122,13 @@ struct RoadVehicle : public SpecializedV
 
	Money GetRunningCost() const;
 
	int GetDisplayImageWidth(Point *offset = NULL) const;
 
	bool IsInDepot() const { return this->state == RVSB_IN_DEPOT; }
 
	bool IsStoppedInDepot() const;
 
	bool Tick();
 
	void OnNewDay();
 
	uint Crash(bool flooded = false);
 
	Trackdir GetVehicleTrackdir() const;
 
	TileIndex GetOrderStationLocation(StationID station);
 
	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 

	
 
	bool IsBus() const;
 

	
src/roadveh_cmd.cpp
Show inline comments
 
@@ -534,27 +534,23 @@ static Vehicle *EnumCheckRoadVehCrashTra
 
		abs(v->z_pos - u->z_pos) <= 6 &&
 
		abs(v->x_pos - u->x_pos) <= 4 &&
 
		abs(v->y_pos - u->y_pos) <= 4 ?
 
			v : NULL;
 
}
 

	
 
uint RoadVehicle::Crash(bool flooded)
 
{
 
	uint pass = Vehicle::Crash(flooded);
 
	if (this->IsRoadVehFront()) pass += 1; // driver
 
	this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
 
	return pass;
 
}
 

	
 
static void RoadVehCrash(RoadVehicle *v)
 
{
 
	uint16 pass = 1;
 

	
 
	v->crashed_ctr++;
 

	
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
 

	
 
		u->vehstatus |= VS_CRASHED;
 

	
 
		MarkSingleVehicleDirty(u);
 
	}
 

	
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	uint pass = v->Crash();
 

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

	
 
	SetDParam(0, pass);
 
	AddVehicleNewsItem(
 
		(pass == 1) ?
src/train.h
Show inline comments
 
@@ -133,12 +133,13 @@ struct Train : public SpecializedVehicle
 
	Money GetRunningCost() const;
 
	int GetDisplayImageWidth(Point *offset = NULL) const;
 
	bool IsInDepot() const { return CheckTrainInDepot(this, false) != -1; }
 
	bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; }
 
	bool Tick();
 
	void OnNewDay();
 
	uint Crash(bool flooded = false);
 
	Trackdir GetVehicleTrackdir() const;
 
	TileIndex GetOrderStationLocation(StationID station);
 
	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 

	
 
	void ReserveTrackUnderConsist() const;
 

	
src/train_cmd.cpp
Show inline comments
 
@@ -3185,62 +3185,40 @@ void Train::ReserveTrackUnderConsist() c
 
				TryReserveRailTrack(u->tile, TrackBitsToTrack(u->track));
 
				break;
 
		}
 
	}
 
}
 

	
 
static void SetVehicleCrashed(Train *v)
 
uint Train::Crash(bool flooded)
 
{
 
	if (v->crash_anim_pos != 0) return;
 

	
 
	if (v->IsFrontEngine()) {
 
	uint pass = 0;
 
	if (this->IsFrontEngine()) {
 
		pass += 4; // driver
 

	
 
		/* Remove the reserved path in front of the train if it is not stuck.
 
		 * Also clear all reserved tracks the train is currently on. */
 
		if (!HasBit(v->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(v);
 
		for (const Train *u = v; u != NULL; u = u->Next()) {
 
			ClearPathReservation(u, u->tile, u->GetVehicleTrackdir());
 
			if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
 
		if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this);
 
		for (const Train *v = this; v != NULL; v = v->Next()) {
 
			ClearPathReservation(v, v->tile, v->GetVehicleTrackdir());
 
			if (IsTileType(v->tile, MP_TUNNELBRIDGE)) {
 
				/* ClearPathReservation will not free the wormhole exit
 
				 * if the train has just entered the wormhole. */
 
				SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(u->tile), false);
 
				SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(v->tile), false);
 
			}
 
		}
 
	}
 

	
 
	/* we may need to update crossing we were approaching */
 
	TileIndex crossing = TrainApproachingCrossingTile(v);
 

	
 
	v->crash_anim_pos++;
 

	
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
 

	
 
	if (v->track == TRACK_BIT_DEPOT) {
 
		SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 

	
 
		/* we may need to update crossing we were approaching,
 
		* but must be updated after the train has been marked crashed */
 
		TileIndex crossing = TrainApproachingCrossingTile(this);
 
		if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
 
	}
 

	
 
	InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 

	
 
	for (; v != NULL; v = v->Next()) {
 
		v->vehstatus |= VS_CRASHED;
 
		MarkSingleVehicleDirty(v);
 
	}
 

	
 
	/* must be updated after the train has been marked crashed */
 
	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
 
}
 

	
 
static uint CountPassengersInTrain(const Train *v)
 
{
 
	uint num = 0;
 

	
 
	for (; v != NULL; v = v->Next()) {
 
		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count();
 
	}
 

	
 
	return num;
 
	pass += Vehicle::Crash(flooded);
 

	
 
	this->crash_anim_pos = flooded ? 4000 : 1; // max 4440, disappear pretty fast when flooded
 
	return pass;
 
}
 

	
 
/**
 
 * Marks train as crashed and creates an AI event.
 
 * Doesn't do anything if the train is crashed already.
 
 * @param v first vehicle of chain
 
@@ -3249,16 +3227,13 @@ static uint CountPassengersInTrain(const
 
static uint TrainCrashed(Train *v)
 
{
 
	uint num = 0;
 

	
 
	/* do not crash train twice */
 
	if (!(v->vehstatus & VS_CRASHED)) {
 
		/* two drivers + passengers */
 
		num = 2 + CountPassengersInTrain(v);
 

	
 
		SetVehicleCrashed(v);
 
		num = v->Crash();
 
		AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_TRAIN));
 
	}
 

	
 
	/* Try to re-reserve track under already crashed train too.
 
	 * SetVehicleCrashed() clears the reservation! */
 
	v->ReserveTrackUnderConsist();
src/vehicle.cpp
Show inline comments
 
@@ -109,12 +109,35 @@ bool Vehicle::NeedsAutomaticServicing() 
 
	if (_settings_game.order.gotodepot && VehicleHasDepotOrders(this)) return false;
 
	if (this->current_order.IsType(OT_LOADING))            return false;
 
	if (this->current_order.IsType(OT_GOTO_DEPOT) && this->current_order.GetDepotOrderType() != ODTFB_SERVICE) return false;
 
	return NeedsServicing();
 
}
 

	
 
uint Vehicle::Crash(bool flooded)
 
{
 
	assert((this->vehstatus & VS_CRASHED) == 0);
 
	assert(this->Previous() == NULL); // IsPrimaryVehicle fails for free-wagon-chains
 

	
 
	uint pass = 0;
 
	/* crash all wagons, and count passengers */
 
	for (Vehicle *v = this; v != NULL; v = v->Next()) {
 
		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) pass += v->cargo.Count();
 
		v->vehstatus |= VS_CRASHED;
 
		MarkSingleVehicleDirty(v);
 
	}
 

	
 
	/* Dirty some windows */
 
	InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
 
	SetWindowDirty(WC_VEHICLE_DEPOT, this->tile);
 

	
 
	return pass;
 
}
 

	
 

	
 
/**
 
 * Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
 
 * @param engine The engine that caused the problem
 
 * @param part1  Part 1 of the error message, taking the grfname as parameter 1
 
 * @param part2  Part 2 of the error message, taking the engine as parameter 2
 
 * @param bug_type Flag to check and set in grfconfig
src/vehicle_base.h
Show inline comments
 
@@ -321,12 +321,19 @@ public:
 
	/**
 
	 * Calls the new day handler of the vehicle
 
	 */
 
	virtual void OnNewDay() {};
 

	
 
	/**
 
	 * Crash the (whole) vehicle chain.
 
	 * @param flooded whether the cause of the crash is flooding or not.
 
	 * @return the number of lost souls.
 
	 */
 
	virtual uint Crash(bool flooded = false);
 

	
 
	/**
 
	 * Update vehicle sprite- and position caches
 
	 * @param moved Was the vehicle moved?
 
	 * @param turned Did the vehicle direction change?
 
	 */
 
	inline void UpdateViewport(bool moved, bool turned)
 
	{
src/water_cmd.cpp
Show inline comments
 
@@ -786,64 +786,24 @@ static void FloodVehicle(Vehicle *v)
 
{
 
	if ((v->vehstatus & VS_CRASHED) != 0) return;
 
	if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_AIRCRAFT) return;
 

	
 
	if (v->type == VEH_AIRCRAFT) {
 
		/* Crashing aircraft are always at z_pos == 1, never on z_pos == 0,
 
			* because that's always the shadow. Except for the heliport, because
 
			* that station has a big z_offset for the aircraft. */
 
		 * because that's always the shadow. Except for the heliport, because
 
		 * that station has a big z_offset for the aircraft. */
 
		if (!IsTileType(v->tile, MP_STATION) || !IsAirport(v->tile) || GetTileMaxZ(v->tile) != 0) return;
 
		const Station *st = Station::GetByTile(v->tile);
 
		const AirportFTAClass *airport = st->Airport();
 

	
 
		if (v->z_pos != airport->delta_z + 1) return;
 
	} else {
 
		v = v->First();
 
	}
 

	
 
	uint pass = 0;
 
	/* crash all wagons, and count passengers */
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
		if (IsCargoInClass(u->cargo_type, CC_PASSENGERS)) pass += u->cargo.Count();
 
		u->vehstatus |= VS_CRASHED;
 
		MarkSingleVehicleDirty(u);
 
	}
 

	
 
	switch (v->type) {
 
		default: NOT_REACHED();
 
		case VEH_TRAIN: {
 
			Train *t = Train::From(v);
 
			if (t->IsFrontEngine()) {
 
				pass += 4; // driver
 
				/* FreeTrainTrackReservation() calls GetVehicleTrackdir() that doesn't like crashed vehicles.
 
					* In this case, v->direction matches v->u.rail.track, so we can do this (it wasn't crashed before) */
 
				t->vehstatus &= ~VS_CRASHED;
 
				if (!HasBit(t->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(t);
 
				t->vehstatus |= VS_CRASHED;
 
			}
 
			t->crash_anim_pos = 4000; // max 4440, disappear pretty fast
 
			InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 
			break;
 
		}
 

	
 
		case VEH_ROAD: {
 
			RoadVehicle *rv = RoadVehicle::From(v);
 
			if (rv->IsRoadVehFront()) pass += 1; // driver
 
			rv->crashed_ctr = 2000; // max 2220, disappear pretty fast
 
			InvalidateWindowClassesData(WC_ROADVEH_LIST, 0);
 
		} break;
 

	
 
		case VEH_AIRCRAFT:
 
			pass += 2; // driver
 
			Aircraft::From(v)->crashed_counter = 9000; // max 10000, disappear pretty fast
 
			InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 
			break;
 
	}
 

	
 
	SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
 
	uint pass = v->Crash(true);
 

	
 
	AI::NewEvent(v->owner, new AIEventVehicleCrashed(v->index, v->tile, AIEventVehicleCrashed::CRASH_FLOODED));
 
	SetDParam(0, pass);
 
	AddVehicleNewsItem(STR_NEWS_DISASTER_FLOOD_VEHICLE,
 
		NS_ACCIDENT,
 
		v->index);
0 comments (0 inline, 0 general)