src/ship_cmd.cpp
branchNewGRF_ports
changeset 6719 4cc327ad39d5
parent 6683 7ec558346172
child 6720 35756db7e577
equal deleted inserted replaced
6718:5a8b295aa345 6719:4cc327ad39d5
     1 /* $Id$ */
     1 /* $Id$ */
       
     2 
       
     3 /** @file ship_cmd.cpp */
     2 
     4 
     3 #include "stdafx.h"
     5 #include "stdafx.h"
     4 #include "openttd.h"
     6 #include "openttd.h"
     5 #include "ship.h"
     7 #include "ship.h"
     6 #include "table/strings.h"
     8 #include "table/strings.h"
     7 #include "functions.h"
     9 #include "functions.h"
       
    10 #include "landscape.h"
     8 #include "map.h"
    11 #include "map.h"
     9 #include "tile.h"
    12 #include "tile.h"
    10 #include "vehicle.h"
    13 #include "vehicle.h"
    11 #include "command.h"
    14 #include "command.h"
    12 #include "pathfind.h"
    15 #include "pathfind.h"
    38 	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_RIGHT, // 0x2A, // DIAGDIR_NW
    41 	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_RIGHT, // 0x2A, // DIAGDIR_NW
    39 };
    42 };
    40 
    43 
    41 static TrackBits GetTileShipTrackStatus(TileIndex tile)
    44 static TrackBits GetTileShipTrackStatus(TileIndex tile)
    42 {
    45 {
    43 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
    46 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER, 0);
    44 	return TrackdirBitsToTrackBits((TrackdirBits)(TRACKDIR_BIT_MASK & (r | r >> 8)));
    47 	return TrackdirBitsToTrackBits((TrackdirBits)(TRACKDIR_BIT_MASK & (r | r >> 8)));
    45 }
    48 }
    46 
    49 
    47 void DrawShipEngine(int x, int y, EngineID engine, SpriteID pal)
    50 void DrawShipEngine(int x, int y, EngineID engine, SpriteID pal)
    48 {
    51 {
    60 	DrawSprite(6 + _ship_sprites[spritenum], pal, x, y);
    63 	DrawSprite(6 + _ship_sprites[spritenum], pal, x, y);
    61 }
    64 }
    62 
    65 
    63 /** Get the size of the sprite of a ship sprite heading west (used for lists)
    66 /** Get the size of the sprite of a ship sprite heading west (used for lists)
    64  * @param engine The engine to get the sprite from
    67  * @param engine The engine to get the sprite from
    65  * @param &width The width of the sprite
    68  * @param width The width of the sprite
    66  * @param &height The height of the sprite
    69  * @param height The height of the sprite
    67  */
    70  */
    68 void GetShipSpriteSize(EngineID engine, uint &width, uint &height)
    71 void GetShipSpriteSize(EngineID engine, uint &width, uint &height)
    69 {
    72 {
    70 	SpriteID spritenum = ShipVehInfo(engine)->image_index;
    73 	SpriteID spritenum = ShipVehInfo(engine)->image_index;
    71 	SpriteID custom_sprite = 0;
    74 	SpriteID custom_sprite = 0;
   109 	TileIndex tile2 = v->tile;
   112 	TileIndex tile2 = v->tile;
   110 
   113 
   111 	if (_patches.new_pathfinding_all) {
   114 	if (_patches.new_pathfinding_all) {
   112 		NPFFoundTargetData ftd;
   115 		NPFFoundTargetData ftd;
   113 		Trackdir trackdir = GetVehicleTrackdir(v);
   116 		Trackdir trackdir = GetVehicleTrackdir(v);
   114 		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
   117 		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPE);
   115 		if (ftd.best_bird_dist == 0) {
   118 		if (ftd.best_bird_dist == 0) {
   116 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
   119 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
   117 		} else {
   120 		} else {
   118 			best_depot = NULL; /* Did not find target */
   121 			best_depot = NULL; /* Did not find target */
   119 		}
   122 		}
   160 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   163 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   161 		}
   164 		}
   162 		return;
   165 		return;
   163 	}
   166 	}
   164 
   167 
       
   168 	if (v->current_order.type == OT_LOADING) v->LeaveStation();
   165 	v->current_order.type = OT_GOTO_DEPOT;
   169 	v->current_order.type = OT_GOTO_DEPOT;
   166 	v->current_order.flags = OF_NON_STOP;
   170 	v->current_order.flags = OF_NON_STOP;
   167 	v->current_order.dest = depot->index;
   171 	v->current_order.dest = depot->index;
   168 	v->dest_tile = depot->xy;
   172 	v->dest_tile = depot->xy;
   169 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   173 	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   182 
   186 
   183 	CheckOrders(v);
   187 	CheckOrders(v);
   184 
   188 
   185 	if (v->vehstatus & VS_STOPPED) return;
   189 	if (v->vehstatus & VS_STOPPED) return;
   186 
   190 
   187 	cost = ShipVehInfo(v->engine_type)->running_cost * _price.ship_running / 364;
   191 	cost = GetVehicleProperty(v, 0x0F, ShipVehInfo(v->engine_type)->running_cost) * _price.ship_running / 364;
   188 	v->profit_this_year -= cost >> 8;
   192 	v->profit_this_year -= cost >> 8;
   189 
   193 
   190 	SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
   194 	SET_EXPENSES_TYPE(EXPENSES_SHIP_RUN);
   191 	SubtractMoneyFromPlayerFract(v->owner, cost);
   195 	SubtractMoneyFromPlayerFract(v->owner, cost);
   192 
   196 
   193 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
   197 	InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
   194 	//we need this for the profit
   198 	/* we need this for the profit */
   195 	InvalidateWindowClasses(WC_SHIPS_LIST);
   199 	InvalidateWindowClasses(WC_SHIPS_LIST);
   196 }
   200 }
   197 
   201 
   198 static void HandleBrokenShip(Vehicle *v)
   202 static void HandleBrokenShip(Vehicle *v)
   199 {
   203 {
   224 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
   228 			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
   225 		}
   229 		}
   226 	}
   230 	}
   227 }
   231 }
   228 
   232 
   229 static void MarkShipDirty(Vehicle *v)
   233 void Ship::MarkDirty()
   230 {
   234 {
   231 	v->cur_image = GetShipImage(v, v->direction);
   235 	this->cur_image = GetShipImage(this, this->direction);
   232 	MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1);
   236 	MarkAllViewportsDirty(this->left_coord, this->top_coord, this->right_coord + 1, this->bottom_coord + 1);
   233 }
   237 }
   234 
   238 
   235 static void PlayShipSound(Vehicle *v)
   239 static void PlayShipSound(const Vehicle *v)
   236 {
   240 {
   237 	if (!PlayVehicleSound(v, VSE_START)) {
   241 	if (!PlayVehicleSound(v, VSE_START)) {
   238 		SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v);
   242 		SndPlayVehicleFx(ShipVehInfo(v->engine_type)->sfx, v);
   239 	}
   243 	}
       
   244 }
       
   245 
       
   246 void Ship::PlayLeaveStationSound() const
       
   247 {
       
   248 	PlayShipSound(this);
   240 }
   249 }
   241 
   250 
   242 static void ProcessShipOrder(Vehicle *v)
   251 static void ProcessShipOrder(Vehicle *v)
   243 {
   252 {
   244 	const Order *order;
   253 	const Order *order;
   295 	InvalidateVehicleOrder(v);
   304 	InvalidateVehicleOrder(v);
   296 
   305 
   297 	InvalidateWindowClasses(WC_SHIPS_LIST);
   306 	InvalidateWindowClasses(WC_SHIPS_LIST);
   298 }
   307 }
   299 
   308 
   300 static void HandleShipLoading(Vehicle *v)
   309 void Ship::UpdateDeltaXY(Direction direction)
   301 {
   310 {
   302 	switch (v->current_order.type) {
   311 #define MKIT(a, b, c, d) ((a & 0xFF) << 24) | ((b & 0xFF) << 16) | ((c & 0xFF) << 8) | ((d & 0xFF) << 0)
   303 		case OT_LOADING: {
       
   304 			if (--v->load_unload_time_rem) return;
       
   305 
       
   306 			if (CanFillVehicle(v) && (
       
   307 						v->current_order.flags & OF_FULL_LOAD ||
       
   308 						(_patches.gradual_loading && !HASBIT(v->vehicle_flags, VF_LOADING_FINISHED))
       
   309 					)) {
       
   310 				SET_EXPENSES_TYPE(EXPENSES_SHIP_INC);
       
   311 				if (LoadUnloadVehicle(v, false)) {
       
   312 					InvalidateWindow(WC_SHIPS_LIST, v->owner);
       
   313 					MarkShipDirty(v);
       
   314 				}
       
   315 				return;
       
   316 			}
       
   317 			PlayShipSound(v);
       
   318 
       
   319 			Order b = v->current_order;
       
   320 			v->LeaveStation();
       
   321 			if (!(b.flags & OF_NON_STOP)) return;
       
   322 			break;
       
   323 		}
       
   324 
       
   325 		case OT_DUMMY: break;
       
   326 
       
   327 		default: return;
       
   328 	}
       
   329 
       
   330 	v->cur_order_index++;
       
   331 	InvalidateVehicleOrder(v);
       
   332 }
       
   333 
       
   334 static void UpdateShipDeltaXY(Vehicle *v, int dir)
       
   335 {
       
   336 #define MKIT(d,c,b,a) ((a&0xFF)<<24) | ((b&0xFF)<<16) | ((c&0xFF)<<8) | ((d&0xFF)<<0)
       
   337 	static const uint32 _delta_xy_table[8] = {
   312 	static const uint32 _delta_xy_table[8] = {
   338 		MKIT( -3,  -3,  6,  6),
   313 		MKIT( 6,  6,  -3,  -3),
   339 		MKIT(-16,  -3, 32,  6),
   314 		MKIT( 6, 32,  -3, -16),
   340 		MKIT( -3,  -3,  6,  6),
   315 		MKIT( 6,  6,  -3,  -3),
   341 		MKIT( -3, -16,  6, 32),
   316 		MKIT(32,  6, -16,  -3),
   342 		MKIT( -3,  -3,  6,  6),
   317 		MKIT( 6,  6,  -3,  -3),
   343 		MKIT(-16,  -3, 32,  6),
   318 		MKIT( 6, 32,  -3, -16),
   344 		MKIT( -3,  -3,  6,  6),
   319 		MKIT( 6,  6,  -3,  -3),
   345 		MKIT( -3, -16,  6, 32),
   320 		MKIT(32,  6, -16,  -3),
   346 	};
   321 	};
   347 #undef MKIT
   322 #undef MKIT
   348 	uint32 x = _delta_xy_table[dir];
   323 
   349 	v->x_offs        = GB(x,  0, 8);
   324 	uint32 x = _delta_xy_table[direction];
   350 	v->y_offs        = GB(x,  8, 8);
   325 	this->x_offs        = GB(x,  0, 8);
   351 	v->sprite_width  = GB(x, 16, 8);
   326 	this->y_offs        = GB(x,  8, 8);
   352 	v->sprite_height = GB(x, 24, 8);
   327 	this->sprite_width  = GB(x, 16, 8);
       
   328 	this->sprite_height = GB(x, 24, 8);
       
   329 	this->z_height      = 6;
   353 }
   330 }
   354 
   331 
   355 void RecalcShipStuff(Vehicle *v)
   332 void RecalcShipStuff(Vehicle *v)
   356 {
   333 {
   357 	UpdateShipDeltaXY(v, v->direction);
   334 	v->UpdateDeltaXY(v->direction);
   358 	v->cur_image = GetShipImage(v, v->direction);
   335 	v->cur_image = GetShipImage(v, v->direction);
   359 	MarkShipDirty(v);
   336 	v->MarkDirty();
   360 	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   337 	InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
   361 }
   338 }
   362 
   339 
   363 static const TileIndexDiffC _ship_leave_depot_offs[] = {
   340 static const TileIndexDiffC _ship_leave_depot_offs[] = {
   364 	{-1,  0},
   341 	{-1,  0},
   374 	if (!IsShipInDepot(v)) return;
   351 	if (!IsShipInDepot(v)) return;
   375 
   352 
   376 	tile = v->tile;
   353 	tile = v->tile;
   377 	axis = GetShipDepotAxis(tile);
   354 	axis = GetShipDepotAxis(tile);
   378 
   355 
   379 	// Check first side
   356 	/* Check first side */
   380 	if (_ship_sometracks[axis] & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   357 	if (_ship_sometracks[axis] & GetTileShipTrackStatus(TILE_ADD(tile, ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   381 		m = (axis == AXIS_X) ? 0x101 : 0x207;
   358 		m = (axis == AXIS_X) ? 0x101 : 0x207;
   382 	// Check second side
   359 	/* Check second side */
   383 	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   360 	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   384 		m = (axis == AXIS_X) ? 0x105 : 0x203;
   361 		m = (axis == AXIS_X) ? 0x105 : 0x203;
   385 	} else {
   362 	} else {
   386 		return;
   363 		return;
   387 	}
   364 	}
   401 static bool ShipAccelerate(Vehicle *v)
   378 static bool ShipAccelerate(Vehicle *v)
   402 {
   379 {
   403 	uint spd;
   380 	uint spd;
   404 	byte t;
   381 	byte t;
   405 
   382 
   406 	spd = min(v->cur_speed + 1, v->max_speed);
   383 	spd = min(v->cur_speed + 1, GetVehicleProperty(v, 0x0B, v->max_speed));
   407 
   384 
   408 	//updates statusbar only if speed have changed to save CPU time
   385 	/*updates statusbar only if speed have changed to save CPU time */
   409 	if (spd != v->cur_speed) {
   386 	if (spd != v->cur_speed) {
   410 		v->cur_speed = spd;
   387 		v->cur_speed = spd;
   411 		if (_patches.vehicle_speed)
   388 		if (_patches.vehicle_speed)
   412 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   389 			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
   413 	}
   390 	}
   414 
   391 
   415 	// Decrease somewhat when turning
   392 	/* Decrease somewhat when turning */
   416 	if (!(v->direction & 1)) spd = spd * 3 / 4;
   393 	if (!(v->direction & 1)) spd = spd * 3 / 4;
   417 
   394 
   418 	if (spd == 0) return false;
   395 	if (spd == 0) return false;
   419 	if ((byte)++spd == 0) return true;
   396 	if ((byte)++spd == 0) return true;
   420 
   397 
   423 	return (t < v->progress);
   400 	return (t < v->progress);
   424 }
   401 }
   425 
   402 
   426 static int32 EstimateShipCost(EngineID engine_type)
   403 static int32 EstimateShipCost(EngineID engine_type)
   427 {
   404 {
   428 	return ShipVehInfo(engine_type)->base_cost * (_price.ship_base>>3)>>5;
   405 	return GetEngineProperty(engine_type, 0x0A, ShipVehInfo(engine_type)->base_cost) * (_price.ship_base>>3)>>5;
   429 }
   406 }
   430 
   407 
   431 static void ShipArrivesAt(const Vehicle* v, Station* st)
   408 static void ShipArrivesAt(const Vehicle* v, Station* st)
   432 {
   409 {
   433 	/* Check if station was ever visited before */
   410 	/* Check if station was ever visited before */
   453 	uint best_length;
   430 	uint best_length;
   454 };
   431 };
   455 
   432 
   456 static bool ShipTrackFollower(TileIndex tile, PathFindShip *pfs, int track, uint length, byte *state)
   433 static bool ShipTrackFollower(TileIndex tile, PathFindShip *pfs, int track, uint length, byte *state)
   457 {
   434 {
   458 	// Found dest?
   435 	/* Found dest? */
   459 	if (tile == pfs->dest_coords) {
   436 	if (tile == pfs->dest_coords) {
   460 		pfs->best_bird_dist = 0;
   437 		pfs->best_bird_dist = 0;
   461 
   438 
   462 		pfs->best_length = minu(pfs->best_length, length);
   439 		pfs->best_length = minu(pfs->best_length, length);
   463 		return true;
   440 		return true;
   464 	}
   441 	}
   465 
   442 
   466 	// Skip this tile in the calculation
   443 	/* Skip this tile in the calculation */
   467 	if (tile != pfs->skiptile) {
   444 	if (tile != pfs->skiptile) {
   468 		pfs->best_bird_dist = minu(pfs->best_bird_dist, DistanceMaxPlusManhattan(pfs->dest_coords, tile));
   445 		pfs->best_bird_dist = minu(pfs->best_bird_dist, DistanceMaxPlusManhattan(pfs->dest_coords, tile));
   469 	}
   446 	}
   470 
   447 
   471 	return false;
   448 	return false;
   500 		i = RemoveFirstTrack(&bits);
   477 		i = RemoveFirstTrack(&bits);
   501 
   478 
   502 		pfs.best_bird_dist = (uint)-1;
   479 		pfs.best_bird_dist = (uint)-1;
   503 		pfs.best_length = (uint)-1;
   480 		pfs.best_length = (uint)-1;
   504 
   481 
   505 		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   482 		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, 0, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   506 
   483 
   507 		if (best_track != INVALID_TRACK) {
   484 		if (best_track != INVALID_TRACK) {
   508 			if (pfs.best_bird_dist != 0) {
   485 			if (pfs.best_bird_dist != 0) {
   509 				/* neither reached the destination, pick the one with the smallest bird dist */
   486 				/* neither reached the destination, pick the one with the smallest bird dist */
   510 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   487 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   535 
   512 
   536 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
   513 static inline NPFFoundTargetData PerfNPFRouteToStationOrTile(TileIndex tile, Trackdir trackdir, NPFFindStationOrTileData* target, TransportType type, Owner owner, RailTypeMask railtypes)
   537 {
   514 {
   538 
   515 
   539 	void* perf = NpfBeginInterval();
   516 	void* perf = NpfBeginInterval();
   540 	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, owner, railtypes);
   517 	NPFFoundTargetData ret = NPFRouteToStationOrTile(tile, trackdir, target, type, 0, owner, railtypes);
   541 	int t = NpfEndInterval(perf);
   518 	int t = NpfEndInterval(perf);
   542 	DEBUG(yapf, 4, "[NPFW] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
   519 	DEBUG(yapf, 4, "[NPFW] %d us - %d rounds - %d open - %d closed -- ", t, 0, _aystar_stats_open_size, _aystar_stats_closed_size);
   543 	return ret;
   520 	return ret;
   544 }
   521 }
   545 
   522 
   546 /* returns the track to choose on the next tile, or -1 when it's better to
   523 /** returns the track to choose on the next tile, or -1 when it's better to
   547  * reverse. The tile given is the tile we are about to enter, enterdir is the
   524  * reverse. The tile given is the tile we are about to enter, enterdir is the
   548  * direction in which we are entering the tile */
   525  * direction in which we are entering the tile */
   549 static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
   526 static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
   550 {
   527 {
   551 	assert(enterdir>=0 && enterdir<=3);
   528 	assert(enterdir >= 0 && enterdir <= 3);
   552 
   529 
   553 	if (_patches.yapf.ship_use_yapf) {
   530 	if (_patches.yapf.ship_use_yapf) {
   554 		Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
   531 		Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
   555 		return (trackdir != INVALID_TRACKDIR) ? TrackdirToTrack(trackdir) : INVALID_TRACK;
   532 		return (trackdir != INVALID_TRACKDIR) ? TrackdirToTrack(trackdir) : INVALID_TRACK;
   556 	} else if (_patches.new_pathfinding_all) {
   533 	} else if (_patches.new_pathfinding_all) {
   557 		NPFFindStationOrTileData fstd;
   534 		NPFFindStationOrTileData fstd;
   558 		NPFFoundTargetData ftd;
   535 		NPFFoundTargetData ftd;
   559 		TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
   536 		TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
   560 		Trackdir trackdir = GetVehicleTrackdir(v);
   537 		Trackdir trackdir = GetVehicleTrackdir(v);
   561 		assert(trackdir != INVALID_TRACKDIR); /* Check that we are not in a depot */
   538 		assert(trackdir != INVALID_TRACKDIR); // Check that we are not in a depot
   562 
   539 
   563 		NPFFillWithOrderData(&fstd, v);
   540 		NPFFillWithOrderData(&fstd, v);
   564 
   541 
   565 		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
   542 		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
   566 
   543 
   618 	return _new_vehicle_direction_table[offs];
   595 	return _new_vehicle_direction_table[offs];
   619 }
   596 }
   620 
   597 
   621 static TrackBits GetAvailShipTracks(TileIndex tile, int dir)
   598 static TrackBits GetAvailShipTracks(TileIndex tile, int dir)
   622 {
   599 {
   623 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
   600 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER, 0);
   624 	return (TrackBits)((r | r >> 8) & _ship_sometracks[dir]);
   601 	return (TrackBits)((r | r >> 8) & _ship_sometracks[dir]);
   625 }
   602 }
   626 
   603 
   627 static const byte _ship_subcoord[4][6][3] = {
   604 static const byte _ship_subcoord[4][6][3] = {
   628 	{
   605 	{
   649 		{ 0, 0, 0},
   626 		{ 0, 0, 0},
   650 		{ 0, 8, 4},
   627 		{ 0, 8, 4},
   651 	},
   628 	},
   652 	{
   629 	{
   653 		{ 0, 0, 0},
   630 		{ 0, 0, 0},
   654 		{ 8,15, 7},
   631 		{ 8, 15, 7},
   655 		{ 0, 0, 0},
   632 		{ 0, 0, 0},
   656 		{ 8,15, 6},
   633 		{ 8, 15, 6},
   657 		{ 0, 0, 0},
   634 		{ 0, 0, 0},
   658 		{ 7,15, 0},
   635 		{ 7, 15, 0},
   659 	}
   636 	}
   660 };
   637 };
   661 
   638 
   662 static void ShipController(Vehicle *v)
   639 static void ShipController(Vehicle *v)
   663 {
   640 {
   678 	}
   655 	}
   679 
   656 
   680 	if (v->vehstatus & VS_STOPPED) return;
   657 	if (v->vehstatus & VS_STOPPED) return;
   681 
   658 
   682 	ProcessShipOrder(v);
   659 	ProcessShipOrder(v);
   683 	HandleShipLoading(v);
   660 	v->HandleLoading();
   684 
   661 
   685 	if (v->current_order.type == OT_LOADING) return;
   662 	if (v->current_order.type == OT_LOADING) return;
   686 
   663 
   687 	CheckShipLeaveDepot(v);
   664 	CheckShipLeaveDepot(v);
   688 
   665 
   729 
   706 
   730 							v->last_station_visited = v->current_order.dest;
   707 							v->last_station_visited = v->current_order.dest;
   731 
   708 
   732 							/* Process station in the orderlist. */
   709 							/* Process station in the orderlist. */
   733 							st = GetStation(v->current_order.dest);
   710 							st = GetStation(v->current_order.dest);
   734 							if (st->facilities & FACIL_DOCK) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */
   711 							if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
       
   712 								ShipArrivesAt(v, st);
   735 								v->BeginLoading();
   713 								v->BeginLoading();
   736 								v->current_order.flags &= OF_FULL_LOAD | OF_UNLOAD | OF_TRANSFER;
   714 							} else { // leave stations without docks right aways
   737 								v->current_order.flags |= OF_NON_STOP;
       
   738 								ShipArrivesAt(v, st);
       
   739 
       
   740 								SET_EXPENSES_TYPE(EXPENSES_SHIP_INC);
       
   741 								if (LoadUnloadVehicle(v, true)) {
       
   742 									InvalidateWindow(WC_SHIPS_LIST, v->owner);
       
   743 									MarkShipDirty(v);
       
   744 								}
       
   745 								InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
       
   746 							} else { /* leave stations without docks right aways */
       
   747 								v->current_order.type = OT_LEAVESTATION;
   715 								v->current_order.type = OT_LEAVESTATION;
   748 								v->cur_order_index++;
   716 								v->cur_order_index++;
   749 								InvalidateVehicleOrder(v);
   717 								InvalidateVehicleOrder(v);
   750 							}
   718 							}
   751 						}
   719 						}
   792 	v->x_pos = gp.x;
   760 	v->x_pos = gp.x;
   793 	v->y_pos = gp.y;
   761 	v->y_pos = gp.y;
   794 	v->z_pos = GetSlopeZ(gp.x, gp.y);
   762 	v->z_pos = GetSlopeZ(gp.x, gp.y);
   795 
   763 
   796 getout:
   764 getout:
   797 	UpdateShipDeltaXY(v, dir);
   765 	v->UpdateDeltaXY(dir);
   798 	v->cur_image = GetShipImage(v, dir);
   766 	v->cur_image = GetShipImage(v, dir);
   799 	VehiclePositionChanged(v);
   767 	VehiclePositionChanged(v);
   800 	EndVehicleMove(v);
   768 	EndVehicleMove(v);
   801 	return;
   769 	return;
   802 
   770 
   832 	}
   800 	}
   833 }
   801 }
   834 
   802 
   835 /** Build a ship.
   803 /** Build a ship.
   836  * @param tile tile of depot where ship is built
   804  * @param tile tile of depot where ship is built
       
   805  * @param flags type of operation
   837  * @param p1 ship type being built (engine)
   806  * @param p1 ship type being built (engine)
   838  * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number
   807  * @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number
   839  */
   808  */
   840 int32 CmdBuildShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   809 int32 CmdBuildShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   841 {
   810 {
   842 	int32 value;
   811 	int32 value;
   843 	Vehicle *v;
   812 	Vehicle *v;
   844 	UnitID unit_num;
   813 	UnitID unit_num;
   845 	Engine *e;
   814 	Engine *e;
   846 
   815 
   847 	if (!IsEngineBuildable(p1, VEH_SHIP, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE);
   816 	if (!IsEngineBuildable(p1, VEH_SHIP, _current_player)) return_cmd_error(STR_SHIP_NOT_AVAILABLE);
   848 
   817 
   849 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   818 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
   850 
   819 
   851 	value = EstimateShipCost(p1);
   820 	value = EstimateShipCost(p1);
   852 	if (flags & DC_QUERY_COST) return value;
   821 	if (flags & DC_QUERY_COST) return value;
   874 		v->tile = tile;
   843 		v->tile = tile;
   875 		x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
   844 		x = TileX(tile) * TILE_SIZE + TILE_SIZE / 2;
   876 		y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
   845 		y = TileY(tile) * TILE_SIZE + TILE_SIZE / 2;
   877 		v->x_pos = x;
   846 		v->x_pos = x;
   878 		v->y_pos = y;
   847 		v->y_pos = y;
   879 		v->z_pos = GetSlopeZ(x,y);
   848 		v->z_pos = GetSlopeZ(x, y);
   880 
   849 
   881 		v->z_height = 6;
   850 		v->UpdateDeltaXY(v->direction);
   882 		v->sprite_width = 6;
       
   883 		v->sprite_height = 6;
       
   884 		v->x_offs = -3;
       
   885 		v->y_offs = -3;
       
   886 		v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   851 		v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
   887 
   852 
   888 		v->spritenum = svi->image_index;
   853 		v->spritenum = svi->image_index;
   889 		v->cargo_type = svi->cargo_type;
   854 		v->cargo_type = svi->cargo_type;
   890 		v->cargo_subtype = 0;
   855 		v->cargo_subtype = 0;
   906 
   871 
   907 		v->service_interval = _patches.servint_ships;
   872 		v->service_interval = _patches.servint_ships;
   908 		v->date_of_last_service = _date;
   873 		v->date_of_last_service = _date;
   909 		v->build_year = _cur_year;
   874 		v->build_year = _cur_year;
   910 		v->cur_image = 0x0E5E;
   875 		v->cur_image = 0x0E5E;
   911 		v->type = VEH_SHIP;
   876 		v = new (v) Ship();
   912 		v->random_bits = VehicleRandomBits();
   877 		v->random_bits = VehicleRandomBits();
   913 
   878 
   914 		v->vehicle_flags = 0;
   879 		v->vehicle_flags = 0;
   915 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
   880 		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SETBIT(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
       
   881 
       
   882 		v->cargo_cap = GetVehicleProperty(v, 0x0D, svi->capacity);
   916 
   883 
   917 		VehiclePositionChanged(v);
   884 		VehiclePositionChanged(v);
   918 
   885 
   919 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   886 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
   920 		RebuildVehicleLists();
   887 		RebuildVehicleLists();
   928 	return value;
   895 	return value;
   929 }
   896 }
   930 
   897 
   931 /** Sell a ship.
   898 /** Sell a ship.
   932  * @param tile unused
   899  * @param tile unused
       
   900  * @param flags type of operation
   933  * @param p1 vehicle ID to be sold
   901  * @param p1 vehicle ID to be sold
   934  * @param p2 unused
   902  * @param p2 unused
   935  */
   903  */
   936 int32 CmdSellShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   904 int32 CmdSellShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   937 {
   905 {
   961 	return -(int32)v->value;
   929 	return -(int32)v->value;
   962 }
   930 }
   963 
   931 
   964 /** Start/Stop a ship.
   932 /** Start/Stop a ship.
   965  * @param tile unused
   933  * @param tile unused
       
   934  * @param flags type of operation
   966  * @param p1 ship ID to start/stop
   935  * @param p1 ship ID to start/stop
   967  * @param p2 unused
   936  * @param p2 unused
   968  */
   937  */
   969 int32 CmdStartStopShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   938 int32 CmdStartStopShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
   970 {
   939 {
   999 	return 0;
   968 	return 0;
  1000 }
   969 }
  1001 
   970 
  1002 /** Send a ship to the depot.
   971 /** Send a ship to the depot.
  1003  * @param tile unused
   972  * @param tile unused
       
   973  * @param flags type of operation
  1004  * @param p1 vehicle ID to send to the depot
   974  * @param p1 vehicle ID to send to the depot
  1005  * @param p2 various bitmasked elements
   975  * @param p2 various bitmasked elements
  1006  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
   976  * - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
  1007  * - p2 bit 8-10 - VLW flag (for mass goto depot)
   977  * - p2 bit 8-10 - VLW flag (for mass goto depot)
  1008  */
   978  */
  1056 
  1026 
  1057 	dep = FindClosestShipDepot(v);
  1027 	dep = FindClosestShipDepot(v);
  1058 	if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT);
  1028 	if (dep == NULL) return_cmd_error(STR_981A_UNABLE_TO_FIND_LOCAL_DEPOT);
  1059 
  1029 
  1060 	if (flags & DC_EXEC) {
  1030 	if (flags & DC_EXEC) {
       
  1031 		if (v->current_order.type == OT_LOADING) v->LeaveStation();
       
  1032 
  1061 		v->dest_tile = dep->xy;
  1033 		v->dest_tile = dep->xy;
  1062 		v->current_order.type = OT_GOTO_DEPOT;
  1034 		v->current_order.type = OT_GOTO_DEPOT;
  1063 		v->current_order.flags = OF_NON_STOP;
  1035 		v->current_order.flags = OF_NON_STOP;
  1064 		if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
  1036 		if (!(p2 & DEPOT_SERVICE)) SETBIT(v->current_order.flags, OFB_HALT_IN_DEPOT);
  1065 		v->current_order.refit_cargo = CT_INVALID;
  1037 		v->current_order.refit_cargo = CT_INVALID;
  1071 }
  1043 }
  1072 
  1044 
  1073 
  1045 
  1074 /** Refits a ship to the specified cargo type.
  1046 /** Refits a ship to the specified cargo type.
  1075  * @param tile unused
  1047  * @param tile unused
       
  1048  * @param flags type of operation
  1076  * @param p1 vehicle ID of the ship to refit
  1049  * @param p1 vehicle ID of the ship to refit
  1077  * @param p2 various bitstuffed elements
  1050  * @param p2 various bitstuffed elements
  1078  * - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
  1051  * - p2 = (bit 0-7) - the new cargo type to refit to (p2 & 0xFF)
  1079  * - p2 = (bit 8-15) - the new cargo subtype to refit to
  1052  * - p2 = (bit 8-15) - the new cargo subtype to refit to
       
  1053  * - p2 = (bit 16) - refit only this vehicle (ignored)
       
  1054  * @return cost of refit or error
  1080  */
  1055  */
  1081 int32 CmdRefitShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1056 int32 CmdRefitShip(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
  1082 {
  1057 {
  1083 	Vehicle *v;
  1058 	Vehicle *v;
  1084 	int32 cost;
  1059 	int32 cost;
  1116 		v->cargo_type = temp_cid;
  1091 		v->cargo_type = temp_cid;
  1117 		v->cargo_subtype = temp_subtype;
  1092 		v->cargo_subtype = temp_subtype;
  1118 	}
  1093 	}
  1119 
  1094 
  1120 	if (capacity == CALLBACK_FAILED) {
  1095 	if (capacity == CALLBACK_FAILED) {
  1121 		capacity = ShipVehInfo(v->engine_type)->capacity;
  1096 		capacity = GetVehicleProperty(v, 0x0D, ShipVehInfo(v->engine_type)->capacity);
  1122 	}
  1097 	}
  1123 	_returned_refit_capacity = capacity;
  1098 	_returned_refit_capacity = capacity;
  1124 
  1099 
  1125 	cost = 0;
  1100 	cost = 0;
  1126 	if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) {
  1101 	if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) {