src/ship_cmd.cpp
branchcustombridgeheads
changeset 5650 aefc131bf5ce
parent 5649 55c8267c933f
child 5849 58039c9dc565
equal deleted inserted replaced
5649:55c8267c933f 5650:aefc131bf5ce
    27 #include "newgrf_text.h"
    27 #include "newgrf_text.h"
    28 #include "newgrf_sound.h"
    28 #include "newgrf_sound.h"
    29 #include "date.h"
    29 #include "date.h"
    30 
    30 
    31 static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
    31 static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
    32 static const byte _ship_sometracks[4] = {0x19, 0x16, 0x25, 0x2A};
    32 
    33 
    33 static const TrackBits _ship_sometracks[4] = {
    34 static byte GetTileShipTrackStatus(TileIndex tile)
    34 	TRACK_BIT_X | TRACK_BIT_LOWER | TRACK_BIT_LEFT,  // 0x19, // DIAGDIR_NE
       
    35 	TRACK_BIT_Y | TRACK_BIT_UPPER | TRACK_BIT_LEFT,  // 0x16, // DIAGDIR_SE
       
    36 	TRACK_BIT_X | TRACK_BIT_UPPER | TRACK_BIT_RIGHT, // 0x25, // DIAGDIR_SW
       
    37 	TRACK_BIT_Y | TRACK_BIT_LOWER | TRACK_BIT_RIGHT, // 0x2A, // DIAGDIR_NW
       
    38 };
       
    39 
       
    40 static TrackBits GetTileShipTrackStatus(TileIndex tile)
    35 {
    41 {
    36 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
    42 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
    37 	return r | r >> 8;
    43 	return TrackdirBitsToTrackBits((TrackdirBits)(TRACKDIR_BIT_MASK & (r | r >> 8)));
    38 }
    44 }
    39 
    45 
    40 void DrawShipEngine(int x, int y, EngineID engine, uint32 image_ormod)
    46 void DrawShipEngine(int x, int y, EngineID engine, uint32 image_ormod)
    41 {
    47 {
    42 	int spritenum = ShipVehInfo(engine)->image_index;
    48 	int spritenum = ShipVehInfo(engine)->image_index;
    75 	TileIndex tile;
    81 	TileIndex tile;
    76 	TileIndex tile2 = v->tile;
    82 	TileIndex tile2 = v->tile;
    77 
    83 
    78 	if (_patches.new_pathfinding_all) {
    84 	if (_patches.new_pathfinding_all) {
    79 		NPFFoundTargetData ftd;
    85 		NPFFoundTargetData ftd;
    80 		byte trackdir = GetVehicleTrackdir(v);
    86 		Trackdir trackdir = GetVehicleTrackdir(v);
    81 		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
    87 		ftd = NPFRouteToDepotTrialError(v->tile, trackdir, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
    82 		if (ftd.best_bird_dist == 0) {
    88 		if (ftd.best_bird_dist == 0) {
    83 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
    89 			best_depot = GetDepotByTile(ftd.node.tile); /* Found target */
    84 		} else {
    90 		} else {
    85 			best_depot = NULL; /* Did not find target */
    91 			best_depot = NULL; /* Did not find target */
   348 	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   354 	} else if (_ship_sometracks[axis + 2] & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) {
   349 		m = (axis == AXIS_X) ? 0x105 : 0x203;
   355 		m = (axis == AXIS_X) ? 0x105 : 0x203;
   350 	} else {
   356 	} else {
   351 		return;
   357 		return;
   352 	}
   358 	}
   353 	v->direction    = GB(m, 0, 8);
   359 	v->direction    = (Direction)GB(m, 0, 8);
   354 	v->u.ship.state = GB(m, 8, 8);
   360 	v->u.ship.state = (TrackBits)GB(m, 8, 8);
   355 	v->vehstatus &= ~VS_HIDDEN;
   361 	v->vehstatus &= ~VS_HIDDEN;
   356 
   362 
   357 	v->cur_speed = 0;
   363 	v->cur_speed = 0;
   358 	RecalcShipStuff(v);
   364 	RecalcShipStuff(v);
   359 
   365 
   445 	{ 9, 9, 1, 0 },
   451 	{ 9, 9, 1, 0 },
   446 };
   452 };
   447 
   453 
   448 static const byte _pick_shiptrack_table[6] = {1, 3, 2, 2, 0, 0};
   454 static const byte _pick_shiptrack_table[6] = {1, 3, 2, 2, 0, 0};
   449 
   455 
   450 static uint FindShipTrack(Vehicle *v, TileIndex tile, int dir, uint bits, TileIndex skiptile, int *track)
   456 static uint FindShipTrack(Vehicle *v, TileIndex tile, DiagDirection dir, TrackBits bits, TileIndex skiptile, Track *track)
   451 {
   457 {
   452 	PathFindShip pfs;
   458 	PathFindShip pfs;
   453 	int i, best_track;
   459 	Track i, best_track;
   454 	uint best_bird_dist = 0;
   460 	uint best_bird_dist = 0;
   455 	uint best_length    = 0;
   461 	uint best_length    = 0;
   456 	uint r;
   462 	uint r;
   457 	byte ship_dir = v->direction & 3;
   463 	byte ship_dir = v->direction & 3;
   458 
   464 
   459 	pfs.dest_coords = v->dest_tile;
   465 	pfs.dest_coords = v->dest_tile;
   460 	pfs.skiptile = skiptile;
   466 	pfs.skiptile = skiptile;
   461 
   467 
   462 	best_track = -1;
   468 	best_track = INVALID_TRACK;
   463 
   469 
   464 	do {
   470 	do {
   465 		i = FIND_FIRST_BIT(bits);
   471 		i = RemoveFirstTrack(bits);
   466 		bits = KILL_FIRST_BIT(bits);
       
   467 
   472 
   468 		pfs.best_bird_dist = (uint)-1;
   473 		pfs.best_bird_dist = (uint)-1;
   469 		pfs.best_length = (uint)-1;
   474 		pfs.best_length = (uint)-1;
   470 
   475 
   471 		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, _ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   476 		FollowTrack(tile, 0x3800 | TRANSPORT_WATER, (DiagDirection)_ship_search_directions[i][dir], (TPFEnumProc*)ShipTrackFollower, NULL, &pfs);
   472 
   477 
   473 		if (best_track >= 0) {
   478 		if (best_track != INVALID_TRACK) {
   474 			if (pfs.best_bird_dist != 0) {
   479 			if (pfs.best_bird_dist != 0) {
   475 				/* neither reached the destination, pick the one with the smallest bird dist */
   480 				/* neither reached the destination, pick the one with the smallest bird dist */
   476 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   481 				if (pfs.best_bird_dist > best_bird_dist) goto bad;
   477 				if (pfs.best_bird_dist < best_bird_dist) goto good;
   482 				if (pfs.best_bird_dist < best_bird_dist) goto good;
   478 			} else {
   483 			} else {
   510 }
   515 }
   511 
   516 
   512 /* returns the track to choose on the next tile, or -1 when it's better to
   517 /* returns the track to choose on the next tile, or -1 when it's better to
   513  * reverse. The tile given is the tile we are about to enter, enterdir is the
   518  * reverse. The tile given is the tile we are about to enter, enterdir is the
   514  * direction in which we are entering the tile */
   519  * direction in which we are entering the tile */
   515 static int ChooseShipTrack(Vehicle *v, TileIndex tile, int enterdir, uint tracks)
   520 static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
   516 {
   521 {
   517 	assert(enterdir>=0 && enterdir<=3);
   522 	assert(enterdir>=0 && enterdir<=3);
   518 
   523 
   519 	if (_patches.yapf.ship_use_yapf) {
   524 	if (_patches.yapf.ship_use_yapf) {
   520 		Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
   525 		Trackdir trackdir = YapfChooseShipTrack(v, tile, enterdir, tracks);
   521 		return (trackdir != INVALID_TRACKDIR) ? (int)TrackdirToTrack(trackdir) : -1;
   526 		return (trackdir != INVALID_TRACKDIR) ? TrackdirToTrack(trackdir) : INVALID_TRACK;
   522 	} else if (_patches.new_pathfinding_all) {
   527 	} else if (_patches.new_pathfinding_all) {
   523 		NPFFindStationOrTileData fstd;
   528 		NPFFindStationOrTileData fstd;
   524 		NPFFoundTargetData ftd;
   529 		NPFFoundTargetData ftd;
   525 		TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
   530 		TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
   526 		byte trackdir = GetVehicleTrackdir(v);
   531 		Trackdir trackdir = GetVehicleTrackdir(v);
   527 		assert (trackdir != 0xFF); /* Check that we are not in a depot */
   532 		assert(trackdir != INVALID_TRACKDIR); /* Check that we are not in a depot */
   528 
   533 
   529 		NPFFillWithOrderData(&fstd, v);
   534 		NPFFillWithOrderData(&fstd, v);
   530 
   535 
   531 		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
   536 		ftd = PerfNPFRouteToStationOrTile(src_tile, trackdir, &fstd, TRANSPORT_WATER, v->owner, INVALID_RAILTYPE);
   532 
   537 
   533 		if (ftd.best_trackdir != 0xff) {
   538 		if (ftd.best_trackdir != 0xff) {
   534 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
   539 			/* If ftd.best_bird_dist is 0, we found our target and ftd.best_trackdir contains
   535 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
   540 			the direction we need to take to get there, if ftd.best_bird_dist is not 0,
   536 			we did not find our target, but ftd.best_trackdir contains the direction leading
   541 			we did not find our target, but ftd.best_trackdir contains the direction leading
   537 			to the tile closest to our target. */
   542 			to the tile closest to our target. */
   538 			return ftd.best_trackdir & 7; /* TODO: Wrapper function? */
   543 			return TrackdirToTrack(ftd.best_trackdir); /* TODO: Wrapper function? */
   539 		} else {
   544 		} else {
   540 			return -1; /* Already at target, reverse? */
   545 			return INVALID_TRACK; /* Already at target, reverse? */
   541 		}
   546 		}
   542 	} else {
   547 	} else {
   543 		uint b;
       
   544 		uint tot_dist, dist;
   548 		uint tot_dist, dist;
   545 		int track;
   549 		Track track;
   546 		TileIndex tile2;
   550 		TileIndex tile2;
   547 
   551 
   548 		tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir));
   552 		tile2 = TILE_ADD(tile, -TileOffsByDiagDir(enterdir));
   549 		tot_dist = (uint)-1;
   553 		tot_dist = (uint)-1;
   550 
   554 
   551 		/* Let's find out how far it would be if we would reverse first */
   555 		/* Let's find out how far it would be if we would reverse first */
   552 		b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->u.ship.state;
   556 		TrackBits b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->u.ship.state;
   553 		if (b != 0) {
   557 		if (b != 0) {
   554 			dist = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track);
   558 			dist = FindShipTrack(v, tile2, ReverseDiagDir(enterdir), b, tile, &track);
   555 			if (dist != (uint)-1)
   559 			if (dist != (uint)-1)
   556 				tot_dist = dist + 1;
   560 				tot_dist = dist + 1;
   557 		}
   561 		}
   558 		/* And if we would not reverse? */
   562 		/* And if we would not reverse? */
   559 		dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track);
   563 		dist = FindShipTrack(v, tile, enterdir, tracks, 0, &track);
   560 		if (dist > tot_dist)
   564 		if (dist > tot_dist)
   561 			/* We could better reverse */
   565 			/* We could better reverse */
   562 			return -1;
   566 			return INVALID_TRACK;
   563 		return track;
   567 		return track;
   564 	}
   568 	}
   565 }
   569 }
   566 
   570 
   567 static const Direction _new_vehicle_direction_table[] = {
   571 static const Direction _new_vehicle_direction_table[] = {
   568 	DIR_N , DIR_NW, DIR_W , 0,
   572 	DIR_N , DIR_NW, DIR_W , INVALID_DIR,
   569 	DIR_NE, DIR_N , DIR_SW, 0,
   573 	DIR_NE, DIR_N , DIR_SW, INVALID_DIR,
   570 	DIR_E , DIR_SE, DIR_S
   574 	DIR_E , DIR_SE, DIR_S
   571 };
   575 };
   572 
   576 
   573 static int ShipGetNewDirectionFromTiles(TileIndex new_tile, TileIndex old_tile)
   577 static Direction ShipGetNewDirectionFromTiles(TileIndex new_tile, TileIndex old_tile)
   574 {
   578 {
   575 	uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
   579 	uint offs = (TileY(new_tile) - TileY(old_tile) + 1) * 4 +
   576 							TileX(new_tile) - TileX(old_tile) + 1;
   580 							TileX(new_tile) - TileX(old_tile) + 1;
   577 	assert(offs < 11 && offs != 3 && offs != 7);
   581 	assert(offs < 11 && offs != 3 && offs != 7);
   578 	return _new_vehicle_direction_table[offs];
   582 	return _new_vehicle_direction_table[offs];
   579 }
   583 }
   580 
   584 
   581 static int ShipGetNewDirection(Vehicle *v, int x, int y)
   585 static Direction ShipGetNewDirection(Vehicle *v, int x, int y)
   582 {
   586 {
   583 	uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1);
   587 	uint offs = (y - v->y_pos + 1) * 4 + (x - v->x_pos + 1);
   584 	assert(offs < 11 && offs != 3 && offs != 7);
   588 	assert(offs < 11 && offs != 3 && offs != 7);
   585 	return _new_vehicle_direction_table[offs];
   589 	return _new_vehicle_direction_table[offs];
   586 }
   590 }
   587 
   591 
   588 static int GetAvailShipTracks(TileIndex tile, int dir)
   592 static TrackBits GetAvailShipTracks(TileIndex tile, int dir)
   589 {
   593 {
   590 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
   594 	uint32 r = GetTileTrackStatus(tile, TRANSPORT_WATER);
   591 	return (byte) ((r | r >> 8)) & _ship_sometracks[dir];
   595 	return (TrackBits)((r | r >> 8) & _ship_sometracks[dir]);
   592 }
   596 }
   593 
   597 
   594 static const byte _ship_subcoord[4][6][3] = {
   598 static const byte _ship_subcoord[4][6][3] = {
   595 	{
   599 	{
   596 		{15, 8, 1},
   600 		{15, 8, 1},
   630 {
   634 {
   631 	GetNewVehiclePosResult gp;
   635 	GetNewVehiclePosResult gp;
   632 	uint32 r;
   636 	uint32 r;
   633 	const byte *b;
   637 	const byte *b;
   634 	Direction dir;
   638 	Direction dir;
   635 	int track;
   639 	Track track;
   636 	int tracks;
   640 	TrackBits tracks;
   637 
   641 
   638 	v->tick_counter++;
   642 	v->tick_counter++;
   639 
   643 
   640 	if (v->breakdown_ctr != 0) {
   644 	if (v->breakdown_ctr != 0) {
   641 		if (v->breakdown_ctr <= 2) {
   645 		if (v->breakdown_ctr <= 2) {
   735 		if (tracks == 0)
   739 		if (tracks == 0)
   736 			goto reverse_direction;
   740 			goto reverse_direction;
   737 
   741 
   738 		// Choose a direction, and continue if we find one
   742 		// Choose a direction, and continue if we find one
   739 		track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
   743 		track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
   740 		if (track < 0)
   744 		if (track == INVALID_TRACK)
   741 			goto reverse_direction;
   745 			goto reverse_direction;
   742 
   746 
   743 		b = _ship_subcoord[diagdir][track];
   747 		b = _ship_subcoord[diagdir][track];
   744 
   748 
   745 		gp.x = (gp.x&~0xF) | b[0];
   749 		gp.x = (gp.x&~0xF) | b[0];
   749 		r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
   753 		r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
   750 		if (r&0x8) goto reverse_direction;
   754 		if (r&0x8) goto reverse_direction;
   751 
   755 
   752 		if (!(r&0x4)) {
   756 		if (!(r&0x4)) {
   753 			v->tile = gp.new_tile;
   757 			v->tile = gp.new_tile;
   754 			v->u.ship.state = 1 << track;
   758 			v->u.ship.state = TrackToTrackBits(track);
   755 		}
   759 		}
   756 
   760 
   757 		v->direction = b[2];
   761 		v->direction = (Direction)b[2];
   758 	}
   762 	}
   759 
   763 
   760 	/* update image of ship, as well as delta XY */
   764 	/* update image of ship, as well as delta XY */
   761 	dir = ShipGetNewDirection(v, gp.x, gp.y);
   765 	dir = ShipGetNewDirection(v, gp.x, gp.y);
   762 	v->x_pos = gp.x;
   766 	v->x_pos = gp.x;
   870 		v->reliability_spd_dec = e->reliability_spd_dec;
   874 		v->reliability_spd_dec = e->reliability_spd_dec;
   871 		v->max_age = e->lifelength * 366;
   875 		v->max_age = e->lifelength * 366;
   872 		_new_vehicle_id = v->index;
   876 		_new_vehicle_id = v->index;
   873 
   877 
   874 		v->string_id = STR_SV_SHIP_NAME;
   878 		v->string_id = STR_SV_SHIP_NAME;
   875 		v->u.ship.state = 0x80;
   879 		v->u.ship.state = TRACK_BIT_SPECIAL;
   876 
   880 
   877 		v->service_interval = _patches.servint_ships;
   881 		v->service_interval = _patches.servint_ships;
   878 		v->date_of_last_service = _date;
   882 		v->date_of_last_service = _date;
   879 		v->build_year = _cur_year;
   883 		v->build_year = _cur_year;
   880 		v->cur_image = 0x0E5E;
   884 		v->cur_image = 0x0E5E;