Changeset - r4725:3a289e38fda7
[Not reviewed]
master
0 10 0
bjarni - 18 years ago 2006-10-04 12:01:59
bjarni@openttd.org
(svn r6637) -Codechange: merged all (vehicle type)EnterDepot into VehicleEnterDepot()
This revealed duplicated code like aircraft lists got invalidated twice
Moved invalidation of the vehicle detail window to VehicleServiceInDepot() as it should always be updated when serviced
10 files changed with 93 insertions and 197 deletions:
0 comments (0 inline, 0 general)
aircraft.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef AIRCRAFT_H
 
#define AIRCRAFT_H
 

	
 
#include "station_map.h"
 
#include "vehicle.h"
 

	
 

	
 
static inline bool IsAircraftInHangar(const Vehicle* v)
 
{
 
	assert(v->type == VEH_Aircraft);
 
	return v->vehstatus & VS_HIDDEN && IsHangarTile(v->tile);
 
}
 

	
 
static inline bool IsAircraftInHangarStopped(const Vehicle* v)
 
{
 
	return IsAircraftInHangar(v) && v->vehstatus & VS_STOPPED;
 
}
 

	
 
uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type);
 

	
 
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2);
 
inline void HandleAircraftEnterHangar(Vehicle *v);
 

	
 
#endif /* AIRCRAFT_H */
aircraft_cmd.c
Show inline comments
 
@@ -812,70 +812,69 @@ static void SetAircraftPosition(Vehicle 
 
	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);;
 

	
 
	safe_y = clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
 
	u->z_pos = GetSlopeZ(safe_x, safe_y);
 
	u->cur_image = v->cur_image;
 

	
 
	BeginVehicleMove(u);
 
	VehiclePositionChanged(u);
 
	EndVehicleMove(u);
 

	
 
	u = u->next;
 
	if (u != NULL) {
 
		u->x_pos = x;
 
		u->y_pos = y;
 
		u->z_pos = z + 5;
 

	
 
		BeginVehicleMove(u);
 
		VehiclePositionChanged(u);
 
		EndVehicleMove(u);
 
	}
 
}
 

	
 
static void ServiceAircraft(Vehicle *v)
 
/** Handle Aircraft specific tasks when a an Aircraft enters a hangar
 
 * Made inline because it's only called from one location (VehicleEnterDepot)
 
 * Can't be moved to vehicle.c because it calls static Aircraft specific functions
 
 * @param *v Vehicle that enters the hangar
 
 */
 
inline void HandleAircraftEnterHangar(Vehicle *v)
 
{
 
	Vehicle *u;
 

	
 
	v->cur_speed = 0;
 
	v->subspeed = 0;
 
	v->progress = 0;
 
	v->vehstatus |= VS_HIDDEN;
 

	
 
	u = v->next;
 
	u->vehstatus |= VS_HIDDEN;
 
	u = u->next;
 
	if (u != NULL) {
 
		u->vehstatus |= VS_HIDDEN;
 
		u->cur_speed = 0;
 
	}
 

	
 
	SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 

	
 
	VehicleServiceInDepot(v);
 
	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
}
 

	
 
static void PlayAircraftSound(const Vehicle* v)
 
{
 
	if (!PlayVehicleSound(v, VSE_START)) {
 
		SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v);
 
	}
 
}
 

	
 
static bool UpdateAircraftSpeed(Vehicle *v)
 
{
 
	uint spd = v->acceleration * 2;
 
	byte t;
 

	
 
	v->subspeed = (t=v->subspeed) + (byte)spd;
 
	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), v->max_speed);
 

	
 
	// adjust speed for broken vehicles
 
	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, 27);
 

	
 
	//updates statusbar only if speed have changed to save CPU time
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_patches.vehicle_speed)
 
@@ -1364,90 +1363,48 @@ static void AircraftEntersTerminal(Vehic
 
		AddNewsItem(
 
			STR_A033_CITIZENS_CELEBRATE_FIRST,
 
			flags,
 
			v->index,
 
			0);
 
	}
 

	
 
	old_order = v->current_order;
 
	v->current_order.type = OT_LOADING;
 
	v->current_order.flags = 0;
 

	
 
	if (old_order.type == OT_GOTO_STATION &&
 
			v->current_order.dest == v->last_station_visited) {
 
		v->current_order.flags =
 
			(old_order.flags & (OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER)) | OF_NON_STOP;
 
	}
 

	
 
	SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_INC);
 
	LoadUnloadVehicle(v);
 
	MarkAircraftDirty(v);
 
	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
}
 

	
 

	
 
static void AircraftEnterHangar(Vehicle *v)
 
{
 
	Order old_order;
 

	
 
	ServiceAircraft(v);
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 

	
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		int32 cost;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
		old_order = v->current_order;
 
		v->current_order.type = OT_NOTHING;
 
		v->current_order.flags = 0;
 

	
 
		_current_player = v->owner;
 
		cost = DoCommand(v->tile, v->index, old_order.refit_cargo | old_order.refit_subtype << 8, DC_EXEC, CMD_REFIT_AIRCRAFT);
 
		if (!CmdFailed(cost) && v->owner == _local_player && cost != 0) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
 

	
 
		if (HASBIT(old_order.flags, OFB_PART_OF_ORDERS)) {
 
			v->cur_order_index++;
 
		} else if (HASBIT(old_order.flags, OFB_HALT_IN_DEPOT)) { // force depot visit
 
			v->vehstatus |= VS_STOPPED;
 
			InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 

	
 
			if (v->owner == _local_player) {
 
				SetDParam(0, v->unitnumber);
 
				AddNewsItem(
 
					STR_A014_AIRCRAFT_IS_WAITING_IN,
 
					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
 
					v->index,
 
					0
 
				);
 
			}
 
		}
 
	}
 
}
 

	
 
static void AircraftLand(Vehicle *v)
 
{
 
	v->sprite_width = v->sprite_height = 2;
 
}
 

	
 
static void AircraftLandAirplane(Vehicle *v)
 
{
 
	AircraftLand(v);
 
	if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
 
		SndPlayVehicleFx(SND_17_SKID_PLANE, v);
 
	}
 
	MaybeCrashAirplane(v);
 
}
 

	
 
// set the right pos when heading to other airports after takeoff
 
static void AircraftNextAirportPos_and_Order(Vehicle *v)
 
{
 
	const Station* st;
 
	const AirportFTAClass *Airport;
 

	
 
	if (v->current_order.type == OT_GOTO_STATION ||
 
			v->current_order.type == OT_GOTO_DEPOT)
 
		v->u.air.targetairport = v->current_order.dest;
 

	
 
@@ -1472,49 +1429,49 @@ static void AircraftLeaveHangar(Vehicle 
 
		if (u != NULL) {
 
			u->vehstatus &= ~VS_HIDDEN;
 
			u->cur_speed = 80;
 
		}
 
	}
 

	
 
	VehicleServiceInDepot(v);
 
	SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
	InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
}
 

	
 

	
 
////////////////////////////////////////////////////////////////////////////////
 
///////////////////   AIRCRAFT MOVEMENT SCHEME  ////////////////////////////////
 
////////////////////////////////////////////////////////////////////////////////
 
static void AircraftEventHandler_EnterTerminal(Vehicle *v, const AirportFTAClass *Airport)
 
{
 
	AircraftEntersTerminal(v);
 
	v->u.air.state = Airport->layout[v->u.air.pos].heading;
 
}
 

	
 
static void AircraftEventHandler_EnterHangar(Vehicle *v, const AirportFTAClass *Airport)
 
{
 
	AircraftEnterHangar(v);
 
	VehicleEnterDepot(v);
 
	v->u.air.state = Airport->layout[v->u.air.pos].heading;
 
}
 

	
 
// In an Airport Hangar
 
static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *Airport)
 
{
 
	// if we just arrived, execute EnterHangar first
 
	if (v->u.air.previous_pos != v->u.air.pos) {
 
		AircraftEventHandler_EnterHangar(v, Airport);
 
		return;
 
	}
 

	
 
	// if we were sent to the depot, stay there
 
	if (v->current_order.type == OT_GOTO_DEPOT && (v->vehstatus & VS_STOPPED)) {
 
		v->current_order.type = OT_NOTHING;
 
		v->current_order.flags = 0;
 
		return;
 
	}
 

	
 
	if (v->current_order.type != OT_GOTO_STATION &&
 
			v->current_order.type != OT_GOTO_DEPOT)
 
		return;
 

	
 
	// if the block of the next position is busy, stay put
rail_cmd.c
Show inline comments
 
@@ -1985,49 +1985,49 @@ static uint32 VehicleEnter_Track(Vehicle
 
	dir = GetRailDepotDirection(tile);
 

	
 
	/* calculate the point where the following wagon should be activated */
 
	/* this depends on the length of the current vehicle */
 
	length = v->u.rail.cached_veh_length;
 

	
 
	fract_coord_leave =
 
		((_fractcoords_enter[dir] & 0x0F) + // x
 
			(length + 1) * _deltacoord_leaveoffset[dir]) +
 
		(((_fractcoords_enter[dir] >> 4) +  // y
 
			((length + 1) * _deltacoord_leaveoffset[dir+4])) << 4);
 

	
 
	fract_coord = (x & 0xF) + ((y & 0xF) << 4);
 

	
 
	if (_fractcoords_behind[dir] == fract_coord) {
 
		/* make sure a train is not entering the tile from behind */
 
		return 8;
 
	} else if (_fractcoords_enter[dir] == fract_coord) {
 
		if (DiagDirToDir(ReverseDiagDir(dir)) == v->direction) {
 
			/* enter the depot */
 
			v->u.rail.track = 0x80,
 
			v->vehstatus |= VS_HIDDEN; /* hide it */
 
			v->direction = ReverseDir(v->direction);
 
			if (v->next == NULL)
 
				TrainEnterDepot(v, tile);
 
				VehicleEnterDepot(v);
 
			v->tile = tile;
 
			InvalidateWindow(WC_VEHICLE_DEPOT, tile);
 
			return 4;
 
		}
 
	} else if (fract_coord_leave == fract_coord) {
 
		if (DiagDirToDir(dir) == v->direction) {
 
			/* leave the depot? */
 
			if ((v = v->next) != NULL) {
 
				v->vehstatus &= ~VS_HIDDEN;
 
				v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? 1 : 2);
 
			}
 
		}
 
	}
 

	
 
	return 0;
 
}
 

	
 

	
 
const TileTypeProcs _tile_type_rail_procs = {
 
	DrawTile_Track,           /* draw_tile_proc */
 
	GetSlopeZ_Track,          /* get_slope_z_proc */
 
	ClearTile_Track,          /* clear_tile_proc */
 
	GetAcceptedCargo_Track,   /* get_accepted_cargo_proc */
 
	GetTileDesc_Track,        /* get_tile_desc_proc */
road_cmd.c
Show inline comments
 
/* $Id$ */
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "bridge_map.h"
 
#include "rail_map.h"
 
#include "road_map.h"
 
#include "sprite.h"
 
#include "table/sprites.h"
 
#include "table/strings.h"
 
#include "functions.h"
 
#include "map.h"
 
#include "tile.h"
 
#include "town_map.h"
 
#include "vehicle.h"
 
#include "viewport.h"
 
#include "command.h"
 
#include "player.h"
 
#include "town.h"
 
#include "gfx.h"
 
#include "sound.h"
 
#include "yapf/yapf.h"
 
#include "depot.h"
 

	
 
void RoadVehEnterDepot(Vehicle *v);
 

	
 

	
 
static uint CountRoadBits(RoadBits r)
 
{
 
	uint count = 0;
 

	
 
	if (r & ROAD_NW) ++count;
 
	if (r & ROAD_SW) ++count;
 
	if (r & ROAD_SE) ++count;
 
	if (r & ROAD_NE) ++count;
 
	return count;
 
}
 

	
 

	
 
static bool CheckAllowRemoveRoad(TileIndex tile, RoadBits remove, bool* edge_road)
 
{
 
	RoadBits present;
 
	RoadBits n;
 
	byte owner;
 
	*edge_road = true;
 

	
 
	if (_game_mode == GM_EDITOR) return true;
 

	
 
	// Only do the special processing for actual players.
 
	if (_current_player >= MAX_PLAYERS) return true;
 
@@ -1036,49 +1034,49 @@ static void GetTileDesc_Road(TileIndex t
 
		default: td->str = _road_tile_strings[GetRoadside(tile)]; break;
 
	}
 
}
 

	
 
static const byte _roadveh_enter_depot_unk0[4] = {
 
	8, 9, 0, 1
 
};
 

	
 
static uint32 VehicleEnter_Road(Vehicle *v, TileIndex tile, int x, int y)
 
{
 
	switch (GetRoadTileType(tile)) {
 
		case ROAD_TILE_CROSSING:
 
			if (v->type == VEH_Train && !IsCrossingBarred(tile)) {
 
				/* train crossing a road */
 
				SndPlayVehicleFx(SND_0E_LEVEL_CROSSING, v);
 
				BarCrossing(tile);
 
				MarkTileDirtyByTile(tile);
 
			}
 
			break;
 

	
 
		case ROAD_TILE_DEPOT:
 
			if (v->type == VEH_Road &&
 
					v->u.road.frame == 11 &&
 
					_roadveh_enter_depot_unk0[GetRoadDepotDirection(tile)] == v->u.road.state) {
 
				RoadVehEnterDepot(v);
 
				VehicleEnterDepot(v);
 
				return 4;
 
			}
 
			break;
 

	
 
		default: break;
 
	}
 
	return 0;
 
}
 

	
 

	
 
static void ChangeTileOwner_Road(TileIndex tile, PlayerID old_player, PlayerID new_player)
 
{
 
	if (IsLevelCrossing(tile) && GetCrossingRoadOwner(tile) == old_player) {
 
		SetCrossingRoadOwner(tile, new_player == OWNER_SPECTATOR ? OWNER_NONE : new_player);
 
	}
 

	
 
	if (!IsTileOwner(tile, old_player)) return;
 

	
 
	if (new_player != OWNER_SPECTATOR) {
 
		SetTileOwner(tile, new_player);
 
	} else {
 
		switch (GetRoadTileType(tile)) {
 
			case ROAD_TILE_NORMAL:
 
				SetTileOwner(tile, OWNER_NONE);
roadveh_cmd.c
Show inline comments
 
@@ -1554,94 +1554,48 @@ again:
 
							st->index, v->current_order.dest);
 
			}
 

	
 
			DEBUG(ms, 0) ("           -- Force a slot clearing.");
 
			ClearSlot(v);
 
		}
 

	
 
		StartRoadVehSound(v);
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
	}
 

	
 
	r = VehicleEnterTile(v, v->tile, x, y);
 
	if (r & 8) {
 
		v->cur_speed = 0;
 
		return;
 
	}
 

	
 
	if ((r & 4) == 0) v->u.road.frame++;
 

	
 
	v->cur_image = GetRoadVehImage(v, v->direction);
 
	UpdateRoadVehDeltaXY(v);
 
	RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
 
}
 

	
 
void RoadVehEnterDepot(Vehicle *v)
 
{
 
	v->u.road.state = 254;
 
	v->vehstatus |= VS_HIDDEN;
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 

	
 
	VehicleServiceInDepot(v);
 

	
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		Order t;
 
		int32 cost;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
		t = v->current_order;
 
		v->current_order.type = OT_DUMMY;
 
		v->current_order.flags = 0;
 

	
 
		_current_player = v->owner;
 
		cost = DoCommand(v->tile, v->index, t.refit_cargo | t.refit_subtype << 8, DC_EXEC, CMD_REFIT_ROAD_VEH);
 
		if (!CmdFailed(cost) && v->owner == _local_player && cost != 0) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
 

	
 
		// Part of the orderlist?
 
		if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
 
			v->cur_order_index++;
 
		} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
 
			v->vehstatus |= VS_STOPPED;
 
			if (v->owner == _local_player) {
 
				SetDParam(0, v->unitnumber);
 
				AddNewsItem(
 
					STR_9016_ROAD_VEHICLE_IS_WAITING,
 
					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
 
					v->index,
 
					0
 
				);
 
			}
 
		}
 
	}
 

	
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
	InvalidateWindowClasses(WC_ROADVEH_LIST);
 
}
 

	
 
static void AgeRoadVehCargo(Vehicle *v)
 
{
 
	if (_age_cargo_skip_counter != 0) return;
 
	if (v->cargo_days != 255) v->cargo_days++;
 
}
 

	
 
void RoadVeh_Tick(Vehicle *v)
 
{
 
	AgeRoadVehCargo(v);
 
	RoadVehController(v);
 
}
 

	
 
static void CheckIfRoadVehNeedsService(Vehicle *v)
 
{
 
	const Depot* depot;
 

	
 
	if (_patches.servint_roadveh == 0) return;
 
	if (!VehicleNeedsService(v)) return;
 
	if (v->vehstatus & VS_STOPPED) return;
 
	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
 

	
 
	// Don't interfere with a depot visit scheduled by the user, or a
 
	// depot visit by the order list.
 
	if (v->current_order.type == OT_GOTO_DEPOT &&
ship.h
Show inline comments
 
/* $Id$ */
 

	
 
#ifndef SHIP_H
 
#define SHIP_H
 

	
 
#include "vehicle.h"
 

	
 
void CcCloneShip(bool success, TileIndex tile, uint32 p1, uint32 p2);
 
void RecalcShipStuff(Vehicle *v);
 

	
 
static inline bool IsShipInDepot(const Vehicle* v)
 
{
 
	assert(v->type == VEH_Ship);
 
	return v->u.ship.state == 0x80;
 
}
 

	
 
static inline bool IsShipInDepotStopped(const Vehicle* v)
 
{
 
	return IsShipInDepot(v) && v->vehstatus & VS_STOPPED;
 
}
 

	
 
#endif /* SHIP_H */
ship_cmd.c
Show inline comments
 
@@ -295,49 +295,49 @@ static void HandleShipLoading(Vehicle *v
 
	InvalidateVehicleOrder(v);
 
}
 

	
 
static void UpdateShipDeltaXY(Vehicle *v, int dir)
 
{
 
#define MKIT(d,c,b,a) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0)
 
	static const uint32 _delta_xy_table[8] = {
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT(-16,  -3, 32,  6),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT( -3, -16,  6, 32),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT(-16,  -3, 32,  6),
 
		MKIT( -3,  -3,  6,  6),
 
		MKIT( -3, -16,  6, 32),
 
	};
 
#undef MKIT
 
	uint32 x = _delta_xy_table[dir];
 
	v->x_offs        = GB(x,  0, 8);
 
	v->y_offs        = GB(x,  8, 8);
 
	v->sprite_width  = GB(x, 16, 8);
 
	v->sprite_height = GB(x, 24, 8);
 
}
 

	
 
static void RecalcShipStuff(Vehicle *v)
 
void RecalcShipStuff(Vehicle *v)
 
{
 
	UpdateShipDeltaXY(v, v->direction);
 
	v->cur_image = GetShipImage(v, v->direction);
 
	MarkShipDirty(v);
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
}
 

	
 
static const TileIndexDiffC _ship_leave_depot_offs[] = {
 
	{-1,  0},
 
	{ 0, -1}
 
};
 

	
 
static void CheckShipLeaveDepot(Vehicle *v)
 
{
 
	TileIndex tile;
 
	Axis axis;
 
	uint m;
 

	
 
	if (!IsShipInDepot(v)) return;
 

	
 
	tile = v->tile;
 
	axis = GetShipDepotAxis(tile);
 

	
 
	// Check first side
 
@@ -370,92 +370,48 @@ static bool ShipAccelerate(Vehicle *v)
 

	
 
	//updates statusbar only if speed have changed to save CPU time
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_patches.vehicle_speed)
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
	}
 

	
 
	// Decrease somewhat when turning
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 

	
 
	if (spd == 0) return false;
 
	if ((byte)++spd == 0) return true;
 

	
 
	v->progress = (t = v->progress) - (byte)spd;
 

	
 
	return (t < v->progress);
 
}
 

	
 
static int32 EstimateShipCost(EngineID engine_type)
 
{
 
	return ShipVehInfo(engine_type)->base_cost * (_price.ship_base>>3)>>5;
 
}
 

	
 
static void ShipEnterDepot(Vehicle *v)
 
{
 
	v->u.ship.state = 0x80;
 
	v->vehstatus |= VS_HIDDEN;
 
	v->cur_speed = 0;
 
	RecalcShipStuff(v);
 

	
 
	VehicleServiceInDepot(v);
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 

	
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		Order t;
 
		int32 cost;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
		t = v->current_order;
 
		v->current_order.type = OT_DUMMY;
 
		v->current_order.flags = 0;
 

	
 
		_current_player = v->owner;
 
		cost = DoCommand(v->tile, v->index, t.refit_cargo | t.refit_subtype << 8, DC_EXEC, CMD_REFIT_SHIP);
 
		if (!CmdFailed(cost) && v->owner == _local_player && cost != 0) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
 

	
 
		if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
 
			v->cur_order_index++;
 
		} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
 
			v->vehstatus |= VS_STOPPED;
 
			if (v->owner == _local_player) {
 
				SetDParam(0, v->unitnumber);
 
				AddNewsItem(
 
					STR_981C_SHIP_IS_WAITING_IN_DEPOT,
 
					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
 
					v->index,
 
					0);
 
			}
 
		}
 
	}
 
	InvalidateWindowClasses(WC_SHIPS_LIST);
 
}
 

	
 
static void ShipArrivesAt(const Vehicle* v, Station* st)
 
{
 
	/* Check if station was ever visited before */
 
	if (!(st->had_vehicle_of_type & HVOT_SHIP)) {
 
		uint32 flags;
 

	
 
		st->had_vehicle_of_type |= HVOT_SHIP;
 

	
 
		SetDParam(0, st->index);
 
		flags = (v->owner == _local_player) ? NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_PLAYER, 0) : NEWS_FLAGS(NM_THIN, NF_VIEWPORT|NF_VEHICLE, NT_ARRIVAL_OTHER, 0);
 
		AddNewsItem(
 
			STR_9833_CITIZENS_CELEBRATE_FIRST,
 
			flags,
 
			v->index,
 
			0);
 
	}
 
}
 

	
 
typedef struct {
 
	TileIndex skiptile;
 
	TileIndex dest_coords;
 
	uint best_bird_dist;
 
	uint best_length;
 
} PathFindShip;
 
@@ -710,49 +666,49 @@ static void ShipController(Vehicle *v)
 
			r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
 
			if (r & 0x8) goto reverse_direction;
 

	
 
			/* A leave station order only needs one tick to get processed, so we can
 
			 * always skip ahead. */
 
			if (v->current_order.type == OT_LEAVESTATION) {
 
				v->current_order.type = OT_NOTHING;
 
				v->current_order.flags = 0;
 
				InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
			} else if (v->dest_tile != 0) {
 
				/* We have a target, let's see if we reached it... */
 
				if (v->current_order.type == OT_GOTO_STATION &&
 
						IsBuoyTile(v->dest_tile) &&
 
						DistanceManhattan(v->dest_tile, gp.new_tile) <= 3) {
 
					/* We got within 3 tiles of our target buoy, so let's skip to our
 
					 * next order */
 
					v->cur_order_index++;
 
					v->current_order.type = OT_DUMMY;
 
					InvalidateVehicleOrder(v);
 
				} else {
 
					/* Non-buoy orders really need to reach the tile */
 
					if (v->dest_tile == gp.new_tile) {
 
						if (v->current_order.type == OT_GOTO_DEPOT) {
 
							if ((gp.x&0xF)==8 && (gp.y&0xF)==8) {
 
								ShipEnterDepot(v);
 
								VehicleEnterDepot(v);
 
								return;
 
							}
 
						} else if (v->current_order.type == OT_GOTO_STATION) {
 
							Station *st;
 

	
 
							v->last_station_visited = v->current_order.dest;
 

	
 
							/* Process station in the orderlist. */
 
							st = GetStation(v->current_order.dest);
 
							if (st->facilities & FACIL_DOCK) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */
 
								v->current_order.type = OT_LOADING;
 
								v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER;
 
								v->current_order.flags |= OF_NON_STOP;
 
								ShipArrivesAt(v, st);
 

	
 
								SET_EXPENSES_TYPE(EXPENSES_SHIP_INC);
 
								if (LoadUnloadVehicle(v)) {
 
									InvalidateWindow(WC_SHIPS_LIST, v->owner);
 
									MarkShipDirty(v);
 
								}
 
								InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
 
							} else { /* leave stations without docks right aways */
 
								v->current_order.type = OT_LEAVESTATION;
 
								v->current_order.flags = 0;
train_cmd.c
Show inline comments
 
@@ -3455,97 +3455,48 @@ static void TrainLocoHandler(Vehicle *v,
 
	SetLastSpeed(v, v->cur_speed);
 
}
 

	
 

	
 
void Train_Tick(Vehicle *v)
 
{
 
	if (_age_cargo_skip_counter == 0 && v->cargo_days != 0xff)
 
		v->cargo_days++;
 

	
 
	v->tick_counter++;
 

	
 
	if (IsFrontEngine(v)) {
 
		TrainLocoHandler(v, false);
 

	
 
		// make sure vehicle wasn't deleted.
 
		if (v->type == VEH_Train && IsFrontEngine(v))
 
			TrainLocoHandler(v, true);
 
	} else if (IsFreeWagon(v) && HASBITS(v->vehstatus, VS_CRASHED)) {
 
		// Delete flooded standalone wagon
 
		if (++v->u.rail.crash_anim_pos >= 4400)
 
			DeleteVehicle(v);
 
	}
 
}
 

	
 

	
 
void TrainEnterDepot(Vehicle *v, TileIndex tile)
 
{
 
	UpdateSignalsOnSegment(tile, GetRailDepotDirection(tile));
 

	
 
	if (!IsFrontEngine(v)) v = GetFirstVehicleInChain(v);
 

	
 
	VehicleServiceInDepot(v);
 

	
 
	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 

	
 
	v->load_unload_time_rem = 0;
 
	v->cur_speed = 0;
 

	
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		Order t;
 
		int32 cost;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
		t = v->current_order;
 
		v->current_order.type = OT_DUMMY;
 
		v->current_order.flags = 0;
 

	
 
		_current_player = v->owner;
 
		cost = DoCommand(v->tile, v->index, t.refit_cargo | t.refit_subtype << 8, DC_EXEC, CMD_REFIT_RAIL_VEHICLE);
 
		if (!CmdFailed(cost) && v->owner == _local_player && cost != 0) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
 

	
 
		if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) { // Part of the orderlist?
 
			v->u.rail.days_since_order_progr = 0;
 
			v->cur_order_index++;
 
		} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) { // User initiated?
 
			v->vehstatus |= VS_STOPPED;
 
			if (v->owner == _local_player) {
 
				SetDParam(0, v->unitnumber);
 
				AddNewsItem(
 
					STR_8814_TRAIN_IS_WAITING_IN_DEPOT,
 
					NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
 
					v->index,
 
					0
 
				);
 
			}
 
		}
 
	}
 
	InvalidateWindowClasses(WC_TRAINS_LIST);
 
}
 

	
 
#define MAX_ACCEPTABLE_DEPOT_DIST 16
 

	
 
static void CheckIfTrainNeedsService(Vehicle *v)
 
{
 
	const Depot* depot;
 
	TrainFindDepotData tfdd;
 

	
 
	if (_patches.servint_trains == 0)                   return;
 
	if (!VehicleNeedsService(v))                        return;
 
	if (v->vehstatus & VS_STOPPED)                      return;
 
	if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
 

	
 
	// Don't interfere with a depot visit scheduled by the user, or a
 
	// depot visit by the order list.
 
	if (v->current_order.type == OT_GOTO_DEPOT &&
 
			(v->current_order.flags & (OF_HALT_IN_DEPOT | OF_PART_OF_ORDERS)) != 0)
 
		return;
 

	
 
	if (CheckTrainIsInsideDepot(v)) {
 
		VehicleServiceInDepot(v);
 
		return;
 
	}
 

	
 
	tfdd = FindClosestTrainDepot(v, MAX_ACCEPTABLE_DEPOT_DIST);
vehicle.c
Show inline comments
 
@@ -85,48 +85,49 @@ enum {
 

	
 
	BLOCKS_FOR_SPECIAL_VEHICLES   = 2, ///< Blocks needed for special vehicles
 
};
 

	
 
/**
 
 * Called if a new block is added to the vehicle-pool
 
 */
 
static void VehiclePoolNewBlock(uint start_item)
 
{
 
	Vehicle *v;
 

	
 
	/* We don't use FOR_ALL here, because FOR_ALL skips invalid items.
 
	 * TODO - This is just a temporary stage, this will be removed. */
 
	for (v = GetVehicle(start_item); v != NULL; v = (v->index + 1 < GetVehiclePoolSize()) ? GetVehicle(v->index + 1) : NULL) v->index = start_item++;
 
}
 

	
 
/* Initialize the vehicle-pool */
 
MemoryPool _vehicle_pool = { "Vehicle", VEHICLES_POOL_MAX_BLOCKS, VEHICLES_POOL_BLOCK_SIZE_BITS, sizeof(Vehicle), &VehiclePoolNewBlock, NULL, 0, 0, NULL };
 

	
 
void VehicleServiceInDepot(Vehicle *v)
 
{
 
	v->date_of_last_service = _date;
 
	v->breakdowns_since_last_service = 0;
 
	v->reliability = GetEngine(v->engine_type)->reliability;
 
	InvalidateWindow(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
 
}
 

	
 
bool VehicleNeedsService(const Vehicle *v)
 
{
 
	if (v->vehstatus & VS_CRASHED)
 
		return false; /* Crashed vehicles don't need service anymore */
 

	
 
	if (_patches.no_servicing_if_no_breakdowns && _opt.diff.vehicle_breakdowns == 0) {
 
		return EngineHasReplacementForPlayer(GetPlayer(v->owner), v->engine_type);  /* Vehicles set for autoreplacing needs to go to a depot even if breakdowns are turned off */
 
	}
 

	
 
	return _patches.servint_ispercent ?
 
		(v->reliability < GetEngine(v->engine_type)->reliability * (100 - v->service_interval) / 100) :
 
		(v->date_of_last_service + v->service_interval < _date);
 
}
 

	
 
StringID VehicleInTheWayErrMsg(const Vehicle* v)
 
{
 
	switch (v->type) {
 
		case VEH_Train:    return STR_8803_TRAIN_IN_THE_WAY;
 
		case VEH_Road:     return STR_9000_ROAD_VEHICLE_IN_THE_WAY;
 
		case VEH_Aircraft: return STR_A015_AIRCRAFT_IN_THE_WAY;
 
		default:           return STR_980E_SHIP_IN_THE_WAY;
 
	}
 
@@ -2395,48 +2396,126 @@ int32 SendAllVehiclesToDepot(byte type, 
 
	uint n, i;
 
	uint16 array_length = 0;
 

	
 
	n = GenerateVehicleSortList(&sort_list, &array_length, type, owner, id, id, id, vlw_flag);
 

	
 
	/* Send all the vehicles to a depot */
 
	for (i = 0; i < n; i++) {
 
		const Vehicle *v = sort_list[i];
 
		int32 ret = DoCommand(v->tile, v->index, service | DEPOT_DONT_CANCEL, flags, CMD_SEND_TO_DEPOT(type));
 

	
 
		/* Return 0 if DC_EXEC is not set this is a valid goto depot command)
 
			* In this case we know that at least one vehicle can be sent to a depot
 
			* and we will issue the command. We can now safely quit the loop, knowing
 
			* it will succeed at least once. With DC_EXEC we really need to send them to the depot */
 
		if (!CmdFailed(ret) && !(flags & DC_EXEC)) {
 
			free((void*)sort_list);
 
			return 0;
 
		}
 
	}
 

	
 
	free((void*)sort_list);
 
	return (flags & DC_EXEC) ? 0 : CMD_ERROR;
 
}
 

	
 
void VehicleEnterDepot(Vehicle *v)
 
{
 
	switch (v->type) {
 
		case VEH_Train:
 
			InvalidateWindowClasses(WC_TRAINS_LIST);
 
			if (!IsFrontEngine(v)) v = GetFirstVehicleInChain(v);
 
			UpdateSignalsOnSegment(v->tile, GetRailDepotDirection(v->tile));
 
			v->load_unload_time_rem = 0;
 
			break;
 

	
 
		case VEH_Road:
 
			InvalidateWindowClasses(WC_ROADVEH_LIST);
 
			v->u.road.state = 254;
 
			break;
 

	
 
		case VEH_Ship:
 
			InvalidateWindowClasses(WC_SHIPS_LIST);
 
			v->u.ship.state = 0x80;
 
			RecalcShipStuff(v);
 
			break;
 

	
 
		case VEH_Aircraft:
 
			InvalidateWindowClasses(WC_AIRCRAFT_LIST);
 
			HandleAircraftEnterHangar(v);
 
			break;
 
		default: NOT_REACHED();
 
	}
 

	
 
	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 

	
 
	v->vehstatus |= VS_HIDDEN;
 
	v->cur_speed = 0;
 

	
 
	VehicleServiceInDepot(v);
 

	
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 

	
 
	if (v->current_order.type == OT_GOTO_DEPOT) {
 
		Order t;
 

	
 
		InvalidateWindow(WC_VEHICLE_VIEW, v->index);
 

	
 
		t = v->current_order;
 
		v->current_order.type = OT_DUMMY;
 
		v->current_order.flags = 0;
 

	
 
		if (t.refit_cargo != CT_NO_REFIT) {
 
			int32 cost;
 

	
 
			_current_player = v->owner;
 
			cost = DoCommand(v->tile, v->index, t.refit_cargo | t.refit_subtype << 8, DC_EXEC, CMD_REFIT_VEH(v->type));
 
			if (!CmdFailed(cost) && v->owner == _local_player && cost != 0) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
 
		}
 

	
 
		if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
 
			/* Part of orders */
 
			if (v->type == VEH_Train) v->u.rail.days_since_order_progr = 0;
 
			v->cur_order_index++;
 
		} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
 
			/* Force depot visit */
 
			v->vehstatus |= VS_STOPPED;
 
			if (v->owner == _local_player) {
 
				StringID string;
 

	
 
				switch (v->type) {
 
					case VEH_Train:    string = STR_8814_TRAIN_IS_WAITING_IN_DEPOT; break;
 
					case VEH_Road:     string = STR_9016_ROAD_VEHICLE_IS_WAITING;   break;
 
					case VEH_Ship:     string = STR_981C_SHIP_IS_WAITING_IN_DEPOT;  break;
 
					case VEH_Aircraft: string = STR_A014_AIRCRAFT_IS_WAITING_IN;    break;
 
					default: NOT_REACHED(); string = STR_EMPTY; // Set the string to something to avoid a compiler warning
 
				}
 

	
 
				SetDParam(0, v->unitnumber);
 
				AddNewsItem(string, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),	v->index, 0);
 
			}
 
		}
 
	}
 
}
 

	
 
/** Give a custom name to your vehicle
 
 * @param tile unused
 
 * @param p1 vehicle ID to name
 
 * @param p2 unused
 
 */
 
int32 CmdNameVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 
{
 
	Vehicle *v;
 
	StringID str;
 

	
 
	if (!IsValidVehicleID(p1) || _cmd_text[0] == '\0') return CMD_ERROR;
 

	
 
	v = GetVehicle(p1);
 

	
 
	if (!CheckOwnership(v->owner)) return CMD_ERROR;
 

	
 
	str = AllocateNameUnique(_cmd_text, 2);
 
	if (str == 0) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		StringID old_str = v->string_id;
 
		v->string_id = str;
 
		DeleteName(old_str);
vehicle.h
Show inline comments
 
@@ -251,96 +251,95 @@ bool AllocateVehicles(Vehicle **vl, int 
 
Vehicle *ForceAllocateVehicle(void);
 
Vehicle *ForceAllocateSpecialVehicle(void);
 
void VehiclePositionChanged(Vehicle *v);
 
void AfterLoadVehicles(void);
 
Vehicle *GetLastVehicleInChain(Vehicle *v);
 
Vehicle *GetPrevVehicleInChain(const Vehicle *v);
 
Vehicle *GetFirstVehicleInChain(const Vehicle *v);
 
uint CountVehiclesInChain(const Vehicle* v);
 
bool IsEngineCountable(const Vehicle *v);
 
void DeleteVehicleChain(Vehicle *v);
 
void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
 
void CallVehicleTicks(void);
 
Vehicle *FindVehicleOnTileZ(TileIndex tile, byte z);
 

	
 
void InitializeTrains(void);
 
byte VehicleRandomBits(void);
 

	
 
bool CanFillVehicle(Vehicle *v);
 
bool CanRefitTo(EngineID engine_type, CargoID cid_to);
 
CargoID FindFirstRefittableCargo(EngineID engine_type);
 
int32 GetRefitCost(EngineID engine_type);
 

	
 
void ViewportAddVehicles(DrawPixelInfo *dpi);
 

	
 
void TrainEnterDepot(Vehicle *v, TileIndex tile);
 

	
 
/* train_cmd.h */
 
int GetTrainImage(const Vehicle* v, Direction direction);
 
int GetAircraftImage(const Vehicle* v, Direction direction);
 
int GetRoadVehImage(const Vehicle* v, Direction direction);
 
int GetShipImage(const Vehicle* v, Direction direction);
 

	
 
Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type);
 
Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type);
 
Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type);
 

	
 
uint32 VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y);
 

	
 
StringID VehicleInTheWayErrMsg(const Vehicle* v);
 
Vehicle *FindVehicleBetween(TileIndex from, TileIndex to, byte z);
 
TileIndex GetVehicleOutOfTunnelTile(const Vehicle *v);
 

	
 
bool UpdateSignalsOnSegment(TileIndex tile, DiagDirection direction);
 
void SetSignalsOnBothDir(TileIndex tile, byte track);
 

	
 
Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y);
 

	
 
void DecreaseVehicleValue(Vehicle *v);
 
void CheckVehicleBreakdown(Vehicle *v);
 
void AgeVehicle(Vehicle *v);
 
void VehicleEnteredDepotThisTick(Vehicle *v);
 

	
 
void BeginVehicleMove(Vehicle *v);
 
void EndVehicleMove(Vehicle *v);
 

	
 
void ShowAircraftViewWindow(const Vehicle* v);
 

	
 
UnitID GetFreeUnitNumber(byte type);
 

	
 
int LoadUnloadVehicle(Vehicle *v);
 

	
 
void TrainConsistChanged(Vehicle *v);
 
void TrainPowerChanged(Vehicle *v);
 
int32 GetTrainRunningCost(const Vehicle *v);
 

	
 
int CheckTrainStoppedInDepot(const Vehicle *v);
 

	
 
bool VehicleNeedsService(const Vehicle *v);
 

	
 
uint GenerateVehicleSortList(const Vehicle*** sort_list, uint16 *length_of_array, byte type, PlayerID owner, StationID station, OrderID order, uint16 depot_airport_index, uint16 window_type);
 
void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, uint16 *engine_list_length, uint16 *engine_count, Vehicle ***wagon_list, uint16 *wagon_list_length, uint16 *wagon_count);
 
int32 SendAllVehiclesToDepot(byte type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id);
 
void VehicleEnterDepot(Vehicle *v);
 

	
 
/* Flags to add to p2 for goto depot commands */
 
/* Note: bits 8-10 are used for VLW flags */
 
enum {
 
	DEPOT_SERVICE       = (1 << 0),	// The vehicle will leave the depot right after arrival (serivce only)
 
	DEPOT_MASS_SEND     = (1 << 1), // Tells that it's a mass send to depot command (type in VLW flag)
 
	DEPOT_DONT_CANCEL   = (1 << 2), // Don't cancel current goto depot command if any
 
	DEPOT_LOCATE_HANGAR = (1 << 3), // Find another airport if the target one lacks a hangar
 
};
 

	
 
typedef struct GetNewVehiclePosResult {
 
	int x,y;
 
	TileIndex old_tile;
 
	TileIndex new_tile;
 
} GetNewVehiclePosResult;
 

	
 
/**
 
 * 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
 
 * the diagonal trackdir on which they are driving. I _think_.
0 comments (0 inline, 0 general)