Changeset - r12656:6db5e45ad71c
[Not reviewed]
master
0 5 0
frosch - 15 years ago 2009-08-08 18:45:12
frosch@openttd.org
(svn r17121) -Fix [FS#3060]: Update vehicle position cache when the vehicle sprite changes.
5 files changed with 38 insertions and 52 deletions:
0 comments (0 inline, 0 general)
src/aircraft_cmd.cpp
Show inline comments
 
@@ -684,17 +684,15 @@ static void HelicopterTickHandler(Aircra
 
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
 
{
 
	v->x_pos = x;
 
	v->y_pos = y;
 
	v->z_pos = z;
 

	
 
	v->cur_image = v->GetImage(v->direction);
 
	v->UpdateViewport(true, false);
 
	if (v->subtype == AIR_HELICOPTER) v->Next()->Next()->cur_image = GetRotorImage(v);
 

	
 
	VehicleMove(v, true);
 

	
 
	Aircraft *u = v->Next();
 

	
 
	int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
 
	int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
 
	u->x_pos = x;
 
	u->y_pos = y - ((v->z_pos - GetSlopeZ(safe_x, safe_y)) >> 3);;
 
@@ -1275,15 +1273,14 @@ TileIndex Aircraft::GetOrderStationLocat
 
	/* Aircraft do not use dest-tile */
 
	return 0;
 
}
 

	
 
void Aircraft::MarkDirty()
 
{
 
	this->cur_image = this->GetImage(this->direction);
 
	this->UpdateViewport(false, false);
 
	if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this);
 
	MarkSingleVehicleDirty(this);
 
}
 

	
 
static void CrashAirplane(Aircraft *v)
 
{
 
	v->vehstatus |= VS_CRASHED;
 
	v->crashed_counter = 0;
src/roadveh_cmd.cpp
Show inline comments
 
@@ -479,14 +479,13 @@ CommandCost CmdTurnRoadVeh(TileIndex til
 
}
 

	
 

	
 
void RoadVehicle::MarkDirty()
 
{
 
	for (Vehicle *v = this; v != NULL; v = v->Next()) {
 
		v->cur_image = v->GetImage(v->direction);
 
		MarkSingleVehicleDirty(v);
 
		v->UpdateViewport(false, false);
 
	}
 
}
 

	
 
void RoadVehicle::UpdateDeltaXY(Direction direction)
 
{
 
#define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
 
@@ -529,25 +528,25 @@ static void DeleteLastRoadVeh(RoadVehicl
 

	
 
	if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
 

	
 
	delete v;
 
}
 

	
 
static byte SetRoadVehPosition(RoadVehicle *v, int x, int y)
 
static byte SetRoadVehPosition(RoadVehicle *v, int x, int y, bool turned)
 
{
 
	byte new_z, old_z;
 

	
 
	/* need this hint so it returns the right z coordinate on bridges. */
 
	v->x_pos = x;
 
	v->y_pos = y;
 
	new_z = GetSlopeZ(x, y);
 

	
 
	old_z = v->z_pos;
 
	v->z_pos = new_z;
 

	
 
	VehicleMove(v, true);
 
	v->UpdateViewport(true, turned);
 
	return old_z;
 
}
 

	
 
static void RoadVehSetRandomDirection(RoadVehicle *v)
 
{
 
	static const DirDiff delta[] = {
 
@@ -555,15 +554,13 @@ static void RoadVehSetRandomDirection(Ro
 
	};
 

	
 
	do {
 
		uint32 r = Random();
 

	
 
		v->direction = ChangeDir(v->direction, delta[r & 3]);
 
		v->UpdateDeltaXY(v->direction);
 
		v->cur_image = v->GetImage(v->direction);
 
		SetRoadVehPosition(v, v->x_pos, v->y_pos);
 
		SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
 
	} while ((v = v->Next()) != NULL);
 
}
 

	
 
static bool RoadVehIsCrashed(RoadVehicle *v)
 
{
 
	v->crashed_ctr++;
 
@@ -1252,14 +1249,13 @@ static bool RoadVehLeaveDepot(RoadVehicl
 
	}
 

	
 
	v->vehstatus &= ~VS_HIDDEN;
 
	v->state = tdir;
 
	v->frame = RVC_DEPOT_START_FRAME;
 

	
 
	v->UpdateDeltaXY(v->direction);
 
	SetRoadVehPosition(v, x, y);
 
	SetRoadVehPosition(v, x, y, true);
 

	
 
	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 

	
 
	return true;
 
}
 

	
 
@@ -1380,14 +1376,13 @@ static bool IndividualRoadVehicleControl
 
				return false;
 
			}
 
		}
 

	
 
		if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
 
			/* Vehicle has just entered a bridge or tunnel */
 
			v->UpdateDeltaXY(v->direction);
 
			SetRoadVehPosition(v, gp.x, gp.y);
 
			SetRoadVehPosition(v, gp.x, gp.y, true);
 
			return true;
 
		}
 

	
 
		v->x_pos = gp.x;
 
		v->y_pos = gp.y;
 
		VehicleMove(v, !(v->vehstatus & VS_HIDDEN));
 
@@ -1526,14 +1521,13 @@ again:
 
		}
 
		if (new_dir != v->direction) {
 
			v->direction = new_dir;
 
			v->cur_speed -= v->cur_speed >> 2;
 
		}
 

	
 
		v->UpdateDeltaXY(v->direction);
 
		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
 
		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
 
		return true;
 
	}
 

	
 
	if (rd.x & RDE_TURNED) {
 
		/* Vehicle has finished turning around, it will now head back onto the same tile */
 
		Trackdir dir;
 
@@ -1591,14 +1585,13 @@ again:
 

	
 
		if (new_dir != v->direction) {
 
			v->direction = new_dir;
 
			v->cur_speed -= v->cur_speed >> 2;
 
		}
 

	
 
		v->UpdateDeltaXY(v->direction);
 
		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
 
		RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
 
		return true;
 
	}
 

	
 
	/* This vehicle is not in a wormhole and it hasn't entered a new tile. If
 
	 * it's on a depot tile, check if it's time to activate the next vehicle in
 
	 * the chain yet. */
 
@@ -1631,14 +1624,13 @@ again:
 
	Direction old_dir = v->direction;
 
	if (new_dir != old_dir) {
 
		v->direction = new_dir;
 
		v->cur_speed -= (v->cur_speed >> 2);
 
		if (old_dir != v->state) {
 
			/* The vehicle is in a road stop */
 
			v->UpdateDeltaXY(v->direction);
 
			SetRoadVehPosition(v, v->x_pos, v->y_pos);
 
			SetRoadVehPosition(v, v->x_pos, v->y_pos, true);
 
			/* Note, return here means that the frame counter is not incremented
 
			 * for vehicles changing direction in a road stop. This causes frames to
 
			 * be repeated. (XXX) Is this intended? */
 
			return true;
 
		}
 
	}
 
@@ -1679,13 +1671,13 @@ again:
 
						rs_n->num_vehicles++;
 
						v->slot = rs_n;
 
						v->dest_tile = rs_n->xy;
 
						v->slot_age = 14;
 

	
 
						v->frame++;
 
						RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
 
						RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false));
 
						return true;
 
					}
 
				}
 
			}
 

	
 
			rs->SetEntranceBusy(false);
 
@@ -1754,14 +1746,13 @@ again:
 
	}
 

	
 
	/* Move to next frame unless vehicle arrived at a stop position
 
	 * in a depot or entered a tunnel/bridge */
 
	if (!HasBit(r, VETS_ENTERED_WORMHOLE)) v->frame++;
 

	
 
	v->UpdateDeltaXY(v->direction);
 
	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
 
	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, true));
 
	return true;
 
}
 

	
 
static bool RoadVehController(RoadVehicle *v)
 
{
 
	/* decrease counters */
 
@@ -1813,15 +1804,13 @@ static bool RoadVehController(RoadVehicl
 
		if (j >= adv_spd && RoadVehCheckTrainCrash(v)) break;
 
	}
 

	
 
	for (RoadVehicle *u = v; u != NULL; u = u->Next()) {
 
		if ((u->vehstatus & VS_HIDDEN) != 0) continue;
 

	
 
		uint16 old_image = u->cur_image;
 
		u->cur_image = u->GetImage(u->direction);
 
		if (old_image != u->cur_image) VehicleMove(u, true);
 
		u->UpdateViewport(false, false);
 
	}
 

	
 
	if (v->progress == 0) v->progress = j;
 

	
 
	return true;
 
}
src/ship_cmd.cpp
Show inline comments
 
@@ -226,14 +226,13 @@ static void HandleBrokenShip(Vehicle *v)
 
		}
 
	}
 
}
 

	
 
void Ship::MarkDirty()
 
{
 
	this->cur_image = this->GetImage(this->direction);
 
	MarkSingleVehicleDirty(this);
 
	this->UpdateViewport(false, false);
 
}
 

	
 
static void PlayShipSound(const Vehicle *v)
 
{
 
	if (!PlayVehicleSound(v, VSE_START)) {
 
		SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v);
 
@@ -280,15 +279,13 @@ void Ship::UpdateDeltaXY(Direction direc
 
	this->y_extent      = GB(x, 24, 8);
 
	this->z_extent      = 6;
 
}
 

	
 
void RecalcShipStuff(Vehicle *v)
 
{
 
	v->UpdateDeltaXY(v->direction);
 
	v->cur_image = v->GetImage(v->direction);
 
	v->MarkDirty();
 
	v->UpdateViewport(false, true);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
}
 

	
 
static const TileIndexDiffC _ship_leave_depot_offs[] = {
 
	{-1,  0},
 
	{ 0, -1}
 
@@ -705,15 +702,13 @@ static void ShipController(Ship *v)
 
	dir = ShipGetNewDirection(v, gp.x, gp.y);
 
	v->x_pos = gp.x;
 
	v->y_pos = gp.y;
 
	v->z_pos = GetSlopeZ(gp.x, gp.y);
 

	
 
getout:
 
	v->UpdateDeltaXY(dir);
 
	v->cur_image = v->GetImage(dir);
 
	VehicleMove(v, true);
 
	v->UpdateViewport(true, true);
 
	return;
 

	
 
reverse_direction:
 
	dir = ReverseDir(v->direction);
 
	v->direction = dir;
 
	goto getout;
src/train_cmd.cpp
Show inline comments
 
@@ -1617,19 +1617,12 @@ void Train::UpdateDeltaXY(Direction dire
 
	this->y_offs        = GB(x,  8, 8);
 
	this->x_extent      = GB(x, 16, 8);
 
	this->y_extent      = GB(x, 24, 8);
 
	this->z_extent      = 6;
 
}
 

	
 
static void UpdateVarsAfterSwap(Train *v)
 
{
 
	v->UpdateDeltaXY(v->direction);
 
	v->cur_image = v->GetImage(v->direction);
 
	VehicleMove(v, true);
 
}
 

	
 
static inline void SetLastSpeed(Train *v, int spd)
 
{
 
	int old = v->tcache.last_speed;
 
	if (spd != old) {
 
		v->tcache.last_speed = spd;
 
		if (_settings_client.gui.vehicle_speed || (old == 0) != (spd == 0)) {
 
@@ -1711,21 +1704,21 @@ static void ReverseTrainSwapVeh(Train *v
 
		Swap(a->tile,  b->tile);
 
		Swap(a->z_pos, b->z_pos);
 

	
 
		SwapTrainFlags(&a->flags, &b->flags);
 

	
 
		/* update other vars */
 
		UpdateVarsAfterSwap(a);
 
		UpdateVarsAfterSwap(b);
 
		a->UpdateViewport(true, true);
 
		b->UpdateViewport(true, true);
 

	
 
		/* call the proper EnterTile function unless we are in a wormhole */
 
		if (a->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
 
		if (b->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(b, b->tile, b->x_pos, b->y_pos);
 
	} else {
 
		if (a->track != TRACK_BIT_DEPOT) a->direction = ReverseDir(a->direction);
 
		UpdateVarsAfterSwap(a);
 
		a->UpdateViewport(true, true);
 

	
 
		if (a->track != TRACK_BIT_WORMHOLE) VehicleEnterTile(a, a->tile, a->x_pos, a->y_pos);
 
	}
 

	
 
	/* Update train's power incase tiles were different rail type */
 
	TrainPowerChanged(v);
 
@@ -1945,13 +1938,13 @@ static void ReverseTrainDirection(Train 
 
	ClrBit(v->flags, VRF_REVERSING);
 

	
 
	/* recalculate cached data */
 
	TrainConsistChanged(v, true);
 

	
 
	/* update all images */
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction);
 
	for (Vehicle *u = v; u != NULL; u = u->Next()) u->UpdateViewport(false, false);
 

	
 
	/* update crossing we were approaching */
 
	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
 

	
 
	/* maybe we are approaching crossing now, after reversal */
 
	crossing = TrainApproachingCrossingTile(v);
 
@@ -3321,14 +3314,13 @@ TileIndex Train::GetOrderStationLocation
 
}
 

	
 
void Train::MarkDirty()
 
{
 
	Vehicle *v = this;
 
	do {
 
		v->cur_image = v->GetImage(v->direction);
 
		MarkSingleVehicleDirty(v);
 
		v->UpdateViewport(false, false);
 
	} while ((v = v->Next()) != NULL);
 

	
 
	/* need to update acceleration and cached values since the goods on the train changed. */
 
	TrainCargoChanged(this);
 
	UpdateTrainAcceleration(this);
 
}
 
@@ -4447,15 +4439,13 @@ static bool TrainLocoHandler(Train *v, b
 
		SetLastSpeed(v, v->cur_speed);
 
	}
 

	
 
	for (Train *u = v; u != NULL; u = u->Next()) {
 
		if ((u->vehstatus & VS_HIDDEN) != 0) continue;
 

	
 
		uint16 old_image = u->cur_image;
 
		u->cur_image = u->GetImage(u->direction);
 
		if (old_image != u->cur_image) VehicleMove(u, true);
 
		u->UpdateViewport(false, false);
 
	}
 

	
 
	if (v->progress == 0) v->progress = j; // Save unused spd for next time, if TrainController didn't set progress
 

	
 
	return true;
 
}
src/vehicle_base.h
Show inline comments
 
@@ -306,12 +306,27 @@ public:
 
	/**
 
	 * Calls the new day handler of the vehicle
 
	 */
 
	virtual void OnNewDay() {};
 

	
 
	/**
 
	 * 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)
 
	{
 
		extern void VehicleMove(Vehicle *v, bool update_viewport);
 

	
 
		if (turned) this->UpdateDeltaXY(this->direction);
 
		SpriteID old_image = this->cur_image;
 
		this->cur_image = this->GetImage(this->direction);
 
		if (moved || this->cur_image != old_image) VehicleMove(this, true);
 
	}
 

	
 
	/**
 
	 * Returns the Trackdir on which the vehicle is currently located.
 
	 * Works for trains and ships.
 
	 * Currently works only sortof for road vehicles, since they have a fuzzy
 
	 * concept of being "on" a trackdir. Dunno really what it returns for a road
 
	 * vehicle that is halfway a tile, never really understood that part. For road
 
	 * vehicles that are at the beginning or end of the tile, should just return
0 comments (0 inline, 0 general)