37 #include "table/strings.h"
60 static const uint16 _ship_sprites[] = {0x0E5D, 0x0E55, 0x0E65, 0x0E6D};
63 bool IsValidImageIndex<VEH_SHIP>(uint8 image_index)
65 return image_index <
lengthof(_ship_sprites);
76 uint8 spritenum = e->u.ship.image_index;
78 if (is_custom_sprite(spritenum)) {
79 SpriteID sprite = GetCustomVehicleIcon(engine,
DIR_W, image_type);
80 if (sprite != 0)
return sprite;
85 assert(IsValidImageIndex<VEH_SHIP>(spritenum));
86 return DIR_W + _ship_sprites[spritenum];
91 SpriteID sprite = GetShipIcon(engine, image_type);
93 preferred_x =
Clamp(preferred_x,
110 const Sprite *spr = GetSprite(GetShipIcon(engine, image_type),
ST_NORMAL);
122 if (is_custom_sprite(spritenum)) {
123 SpriteID sprite = GetCustomVehicleSprite(
this, direction, image_type);
124 if (sprite != 0)
return sprite;
129 assert(IsValidImageIndex<VEH_SHIP>(spritenum));
133 static const Depot *FindClosestShipDepot(
const Vehicle *v, uint max_distance)
137 const Depot *best_depot = NULL;
143 uint best_dist = max_distance == 0 ? UINT_MAX : max_distance + 1;
145 FOR_ALL_DEPOTS(depot) {
149 if (dist < best_dist) {
159 static void CheckIfShipNeedsService(
Vehicle *v)
169 case VPF_OPF: max_distance = 12;
break;
172 default: NOT_REACHED();
175 const Depot *depot = FindClosestShipDepot(v, max_distance);
221 CheckVehicleBreakdown(
this);
223 CheckIfShipNeedsService(
this);
265 static void PlayShipSound(
const Vehicle *v)
268 SndPlayVehicleFx(ShipVehInfo(v->
engine_type)->sfx, v);
292 static const int8 _delta_xy_table[8][4] = {
304 const int8 *bb = _delta_xy_table[
direction];
317 static bool CheckShipLeaveDepot(
Ship *v)
338 if (north_tracks && south_tracks) {
340 bool reverse =
false;
346 default: NOT_REACHED();
354 }
else if (south_tracks) {
377 static bool ShipAccelerate(
Vehicle *v)
394 if (spd == 0)
return false;
395 if ((byte)++spd == 0)
return true;
399 return (t < v->progress);
410 if (!(st->had_vehicle_of_type &
HVOT_SHIP)) {
415 STR_NEWS_FIRST_SHIP_ARRIVAL,
438 bool path_found =
true;
444 default: NOT_REACHED();
451 static const Direction _new_vehicle_direction_table[] = {
459 uint offs = (
TileY(new_tile) -
TileY(old_tile) + 1) * 4 +
461 assert(offs < 11 && offs != 3 && offs != 7);
462 return _new_vehicle_direction_table[offs];
467 uint offs = (y - v->
y_pos + 1) * 4 + (x - v->
x_pos + 1);
468 assert(offs < 11 && offs != 3 && offs != 7);
469 return _new_vehicle_direction_table[offs];
477 static const byte _ship_subcoord[4][6][3] = {
512 static void ShipController(
Ship *v)
532 if (CheckShipLeaveDepot(v))
return;
536 if (!ShipAccelerate(v))
return;
569 if ((gp.x & 0xF) == 8 && (gp.
y & 0xF) == 8) {
597 tracks = GetAvailShipTracks(gp.
new_tile, diagdir);
604 b = _ship_subcoord[diagdir][track];
606 gp.x = (gp.x & ~0xF) | b[0];
607 gp.
y = (gp.
y & ~0xF) | b[1];
637 dir = ShipGetNewDirection(v, gp.x, gp.
y);
640 v->
z_pos = GetSlopePixelZ(gp.x, gp.
y);
657 ShipController(
this);
689 v->
z_pos = GetSlopePixelZ(x, y);
706 _new_vehicle_id = v->
index;
735 const Depot *depot = FindClosestShipDepot(
this, 0);
737 if (depot == NULL)
return false;
739 if (location != NULL) *location = depot->xy;
740 if (destination != NULL) *destination = depot->
index;