Merge branch 'master' into jgrpp
# Conflicts: # .github/workflows/release-windows.yml # src/company_base.h # src/company_cmd.cpp # src/company_gui.cpp # src/console_cmds.cpp # src/economy.cpp # src/economy_cmd.h # src/fios.h # src/goal.cpp # src/group_gui.cpp # src/network/core/config.h # src/network/network_admin.cpp # src/newgrf_config.cpp # src/os/windows/win32.cpp # src/saveload/afterload.cpp # src/saveload/company_sl.cpp # src/saveload/saveload.cpp # src/saveload/saveload_error.hpp # src/settings_gui.cpp # src/ship_cmd.cpp # src/stdafx.h # src/story.cpp # src/story_base.h # src/string.cpp # src/table/settings/economy_settings.ini # src/tests/CMakeLists.txt # src/tests/math_func.cpp
This commit is contained in:
382
src/ship_cmd.cpp
382
src/ship_cmd.cpp
@@ -485,37 +485,38 @@ static inline void UpdateShipSpeed(Vehicle *v, uint speed)
|
||||
}
|
||||
}
|
||||
|
||||
static bool ShipAccelerate(Vehicle *v)
|
||||
/**
|
||||
* Accelerates the ship towards its target speed.
|
||||
* @param v Ship to accelerate.
|
||||
* @return Number of steps to move the ship.
|
||||
*/
|
||||
static uint ShipAccelerate(Vehicle *v)
|
||||
{
|
||||
uint spd;
|
||||
byte t;
|
||||
uint speed;
|
||||
|
||||
spd = std::min<uint>(v->cur_speed + 1, Ship::From(v)->GetEffectiveMaxSpeed());
|
||||
spd = std::min<uint>(spd, v->current_order.GetMaxSpeed() * 2);
|
||||
speed = std::min<uint>(v->cur_speed + 1, Ship::From(v)->GetEffectiveMaxSpeed());
|
||||
speed = std::min<uint>(speed, v->current_order.GetMaxSpeed() * 2);
|
||||
|
||||
if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_POWER && v->cur_speed > (v->breakdown_severity * ShipVehInfo(v->engine_type)->max_speed) >> 8) {
|
||||
if ((v->tick_counter & 0x7) == 0 && v->cur_speed > 0) {
|
||||
spd = v->cur_speed - 1;
|
||||
speed = v->cur_speed - 1;
|
||||
} else {
|
||||
spd = v->cur_speed;
|
||||
speed = v->cur_speed;
|
||||
}
|
||||
}
|
||||
|
||||
if (v->breakdown_ctr == 1 && v->breakdown_type == BREAKDOWN_LOW_SPEED) {
|
||||
spd = std::min<uint>(spd, v->breakdown_severity);
|
||||
speed = std::min<uint>(speed, v->breakdown_severity);
|
||||
}
|
||||
|
||||
UpdateShipSpeed(v, spd);
|
||||
UpdateShipSpeed(v, speed);
|
||||
|
||||
/* Convert direction-independent speed into direction-dependent speed. (old movement method) */
|
||||
spd = v->GetOldAdvanceSpeed(spd);
|
||||
|
||||
if (spd == 0) return false;
|
||||
if ((byte)++spd == 0) return true;
|
||||
|
||||
v->progress = (t = v->progress) - (byte)spd;
|
||||
|
||||
return (t < v->progress);
|
||||
const uint advance_speed = v->GetAdvanceSpeed(speed);
|
||||
const uint number_of_steps = (advance_speed + v->progress) / v->GetAdvanceDistance();
|
||||
const uint remainder = (advance_speed + v->progress) % v->GetAdvanceDistance();
|
||||
dbg_assert(remainder <= std::numeric_limits<byte>::max());
|
||||
v->progress = static_cast<byte>(remainder);
|
||||
return number_of_steps;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -866,13 +867,43 @@ bool IsShipDestinationTile(TileIndex tile, StationID station)
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ReverseShipIntoTrackdir(Ship *v, Trackdir trackdir)
|
||||
{
|
||||
static constexpr Direction _trackdir_to_direction[] = {
|
||||
DIR_NE, DIR_SE, DIR_E, DIR_E, DIR_S, DIR_S, INVALID_DIR, INVALID_DIR,
|
||||
DIR_SW, DIR_NW, DIR_W, DIR_W, DIR_N, DIR_N, INVALID_DIR, INVALID_DIR,
|
||||
};
|
||||
|
||||
v->direction = _trackdir_to_direction[trackdir];
|
||||
dbg_assert(v->direction != INVALID_DIR);
|
||||
v->state = TrackdirBitsToTrackBits(TrackdirToTrackdirBits(trackdir));
|
||||
|
||||
/* Remember our current location to avoid movement glitch */
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->path.clear();
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
}
|
||||
|
||||
static void ReverseShip(Ship *v)
|
||||
{
|
||||
v->direction = ReverseDir(v->direction);
|
||||
|
||||
/* Remember our current location to avoid movement glitch */
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->path.clear();
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
}
|
||||
|
||||
static void ShipController(Ship *v)
|
||||
{
|
||||
uint32 r;
|
||||
Track track;
|
||||
TrackBits tracks;
|
||||
GetNewVehiclePosResult gp;
|
||||
|
||||
v->tick_counter++;
|
||||
v->current_order_time++;
|
||||
|
||||
@@ -880,7 +911,7 @@ static void ShipController(Ship *v)
|
||||
|
||||
if (v->vehstatus & VS_STOPPED) return;
|
||||
|
||||
if (ProcessOrders(v) && CheckReverseShip(v)) goto reverse_direction;
|
||||
if (ProcessOrders(v) && CheckReverseShip(v)) return ReverseShip(v);
|
||||
|
||||
v->HandleLoading();
|
||||
|
||||
@@ -902,183 +933,164 @@ static void ShipController(Ship *v)
|
||||
|
||||
if (ShipMoveUpDownOnLock(v)) return;
|
||||
|
||||
if (!ShipAccelerate(v) && !v->current_order.IsType(OT_LEAVESTATION)) return;
|
||||
uint number_of_steps = ShipAccelerate(v);
|
||||
if (number_of_steps == 0 && v->current_order.IsType(OT_LEAVESTATION)) number_of_steps = 1;
|
||||
for (uint i = 0; i < number_of_steps; ++i) {
|
||||
GetNewVehiclePosResult gp = GetNewVehiclePos(v);
|
||||
if (v->state != TRACK_BIT_WORMHOLE) {
|
||||
/* Not on a bridge */
|
||||
if (gp.old_tile == gp.new_tile) {
|
||||
/* Staying in tile */
|
||||
if (v->IsInDepot()) {
|
||||
gp.x = v->x_pos;
|
||||
gp.y = v->y_pos;
|
||||
} else {
|
||||
/* Not inside depot */
|
||||
const VehicleEnterTileStatus r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
|
||||
if (HasBit(r, VETS_CANNOT_ENTER)) return ReverseShip(v);
|
||||
|
||||
gp = GetNewVehiclePos(v);
|
||||
if (v->state != TRACK_BIT_WORMHOLE) {
|
||||
/* Not on a bridge */
|
||||
if (gp.old_tile == gp.new_tile) {
|
||||
/* Staying in tile */
|
||||
if (v->IsInDepot()) {
|
||||
gp.x = v->x_pos;
|
||||
gp.y = v->y_pos;
|
||||
} else {
|
||||
/* Not inside depot */
|
||||
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
|
||||
if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
|
||||
/* A leave station order only needs one tick to get processed, so we can
|
||||
* always skip ahead. */
|
||||
if (v->current_order.IsType(OT_LEAVESTATION)) {
|
||||
StationID station_id = v->current_order.GetDestination();
|
||||
v->current_order.Free();
|
||||
|
||||
/* A leave station order only needs one tick to get processed, so we can
|
||||
* always skip ahead. */
|
||||
if (v->current_order.IsType(OT_LEAVESTATION)) {
|
||||
StationID station_id = v->current_order.GetDestination();
|
||||
v->current_order.Free();
|
||||
bool may_reverse = ProcessOrders(v);
|
||||
|
||||
bool may_reverse = ProcessOrders(v);
|
||||
|
||||
if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id &&
|
||||
IsDockingTile(gp.new_tile) && Company::Get(v->owner)->settings.remain_if_next_order_same_station) {
|
||||
Station *st = Station::Get(station_id);
|
||||
if (st->facilities & FACIL_DOCK && st->docking_station.Contains(gp.new_tile) && IsShipDestinationTile(gp.new_tile, station_id)) {
|
||||
v->last_station_visited = station_id;
|
||||
ShipArrivesAt(v, st);
|
||||
v->BeginLoading();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
v->PlayLeaveStationSound();
|
||||
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
if (may_reverse && CheckReverseShip(v)) goto reverse_direction;
|
||||
/* Test if continuing forward would lead to a dead-end, moving into the dock. */
|
||||
DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
|
||||
TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
|
||||
if (TrackdirBitsToTrackBits(GetTileTrackdirBits(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) goto reverse_direction;
|
||||
} else if (v->dest_tile != 0) {
|
||||
/* We have a target, let's see if we reached it... */
|
||||
if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
|
||||
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 */
|
||||
UpdateVehicleTimetable(v, true);
|
||||
v->IncrementRealOrderIndex();
|
||||
v->current_order.MakeDummy();
|
||||
} else if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
||||
v->dest_tile == gp.new_tile) {
|
||||
/* Depot orders really need to reach the tile */
|
||||
if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
|
||||
VehicleEnterDepot(v);
|
||||
return;
|
||||
}
|
||||
} else if (v->current_order.IsType(OT_GOTO_STATION) && IsDockingTile(gp.new_tile)) {
|
||||
/* Process station in the orderlist. */
|
||||
Station *st = Station::Get(v->current_order.GetDestination());
|
||||
if (st->docking_station.Contains(gp.new_tile) && IsShipDestinationTile(gp.new_tile, st->index)) {
|
||||
v->last_station_visited = st->index;
|
||||
if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
|
||||
if (v->current_order.IsType(OT_GOTO_STATION) && v->current_order.GetDestination() == station_id &&
|
||||
IsDockingTile(gp.new_tile) && Company::Get(v->owner)->settings.remain_if_next_order_same_station) {
|
||||
Station *st = Station::Get(station_id);
|
||||
if (st->facilities & FACIL_DOCK && st->docking_station.Contains(gp.new_tile) && IsShipDestinationTile(gp.new_tile, station_id)) {
|
||||
v->last_station_visited = station_id;
|
||||
ShipArrivesAt(v, st);
|
||||
v->BeginLoading();
|
||||
} else { // leave stations without docks right away
|
||||
v->current_order.MakeLeaveStation();
|
||||
v->IncrementRealOrderIndex();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
v->PlayLeaveStationSound();
|
||||
|
||||
SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
|
||||
if (may_reverse && CheckReverseShip(v)) return ReverseShip(v);
|
||||
/* Test if continuing forward would lead to a dead-end, moving into the dock. */
|
||||
const DiagDirection exitdir = VehicleExitDir(v->direction, v->state);
|
||||
const TileIndex tile = TileAddByDiagDir(v->tile, exitdir);
|
||||
if (TrackdirBitsToTrackBits(GetTileTrackdirBits(tile, TRANSPORT_WATER, 0, exitdir)) == TRACK_BIT_NONE) return ReverseShip(v);
|
||||
} else if (v->dest_tile != 0) {
|
||||
/* We have a target, let's see if we reached it... */
|
||||
if (v->current_order.IsType(OT_GOTO_WAYPOINT) &&
|
||||
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 */
|
||||
UpdateVehicleTimetable(v, true);
|
||||
v->IncrementRealOrderIndex();
|
||||
v->current_order.MakeDummy();
|
||||
} else if (v->current_order.IsType(OT_GOTO_DEPOT) &&
|
||||
v->dest_tile == gp.new_tile) {
|
||||
/* Depot orders really need to reach the tile */
|
||||
if ((gp.x & 0xF) == 8 && (gp.y & 0xF) == 8) {
|
||||
VehicleEnterDepot(v);
|
||||
return;
|
||||
}
|
||||
} else if (v->current_order.IsType(OT_GOTO_STATION) && IsDockingTile(gp.new_tile)) {
|
||||
/* Process station in the orderlist. */
|
||||
Station *st = Station::Get(v->current_order.GetDestination());
|
||||
if (st->docking_station.Contains(gp.new_tile) && IsShipDestinationTile(gp.new_tile, st->index)) {
|
||||
v->last_station_visited = st->index;
|
||||
if (st->facilities & FACIL_DOCK) { // ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations
|
||||
ShipArrivesAt(v, st);
|
||||
v->BeginLoading();
|
||||
} else { // leave stations without docks right away
|
||||
v->current_order.MakeLeaveStation();
|
||||
v->IncrementRealOrderIndex();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* New tile */
|
||||
if (!IsValidTile(gp.new_tile)) return ReverseShip(v);
|
||||
|
||||
const DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
|
||||
dbg_assert(diagdir != INVALID_DIAGDIR);
|
||||
const TrackBits tracks = GetAvailShipTracks(gp.new_tile, diagdir);
|
||||
if (tracks == TRACK_BIT_NONE) {
|
||||
Trackdir trackdir = INVALID_TRACKDIR;
|
||||
CheckReverseShip(v, &trackdir);
|
||||
if (trackdir == INVALID_TRACKDIR) return ReverseShip(v);
|
||||
return ReverseShipIntoTrackdir(v, trackdir);
|
||||
}
|
||||
|
||||
/* Choose a direction, and continue if we find one */
|
||||
Track track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
|
||||
if (track == INVALID_TRACK) return ReverseShip(v);
|
||||
|
||||
/* Try to avoid collision and keep distance between ships. */
|
||||
if (_settings_game.vehicle.ship_collision_avoidance) CheckDistanceBetweenShips(gp.new_tile, v, tracks, &track, diagdir);
|
||||
|
||||
const ShipSubcoordData &b = _ship_subcoord[diagdir][track];
|
||||
|
||||
gp.x = (gp.x & ~0xF) | b.x_subcoord;
|
||||
gp.y = (gp.y & ~0xF) | b.y_subcoord;
|
||||
|
||||
/* Call the landscape function and tell it that the vehicle entered the tile */
|
||||
const VehicleEnterTileStatus r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
|
||||
if (HasBit(r, VETS_CANNOT_ENTER)) return ReverseShip(v);
|
||||
|
||||
if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
|
||||
v->tile = gp.new_tile;
|
||||
v->state = TrackToTrackBits(track);
|
||||
|
||||
/* Update ship cache when the water class changes. Aqueducts are always canals. */
|
||||
if (GetEffectiveWaterClass(gp.old_tile) != GetEffectiveWaterClass(gp.new_tile)) v->UpdateCache();
|
||||
}
|
||||
|
||||
const Direction new_direction = b.dir;
|
||||
const DirDiff diff = DirDifference(new_direction, v->direction);
|
||||
switch (diff) {
|
||||
case DIRDIFF_SAME:
|
||||
case DIRDIFF_45RIGHT:
|
||||
case DIRDIFF_45LEFT:
|
||||
/* Continue at speed */
|
||||
v->rotation = v->direction = new_direction;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Stop for rotation */
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->direction = new_direction;
|
||||
/* Remember our current location to avoid movement glitch */
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* New tile */
|
||||
if (!IsValidTile(gp.new_tile)) goto reverse_direction;
|
||||
|
||||
DiagDirection diagdir = DiagdirBetweenTiles(gp.old_tile, gp.new_tile);
|
||||
dbg_assert(diagdir != INVALID_DIAGDIR);
|
||||
tracks = GetAvailShipTracks(gp.new_tile, diagdir);
|
||||
if (tracks == TRACK_BIT_NONE) {
|
||||
Trackdir trackdir = INVALID_TRACKDIR;
|
||||
CheckReverseShip(v, &trackdir);
|
||||
if (trackdir == INVALID_TRACKDIR) goto reverse_direction;
|
||||
static const Direction _trackdir_to_direction[] = {
|
||||
DIR_NE, DIR_SE, DIR_E, DIR_E, DIR_S, DIR_S, INVALID_DIR, INVALID_DIR,
|
||||
DIR_SW, DIR_NW, DIR_W, DIR_W, DIR_N, DIR_N, INVALID_DIR, INVALID_DIR,
|
||||
};
|
||||
v->direction = _trackdir_to_direction[trackdir];
|
||||
dbg_assert(v->direction != INVALID_DIR);
|
||||
v->state = TrackdirBitsToTrackBits(TrackdirToTrackdirBits(trackdir));
|
||||
goto direction_changed;
|
||||
/* On a bridge */
|
||||
if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
|
||||
if (_settings_game.vehicle.ship_collision_avoidance && gp.new_tile != TileVirtXY(v->x_pos, v->y_pos)) HandleSpeedOnAqueduct(v, gp.new_tile, v->tile);
|
||||
v->x_pos = gp.x;
|
||||
v->y_pos = gp.y;
|
||||
v->UpdatePosition();
|
||||
if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Choose a direction, and continue if we find one */
|
||||
track = ChooseShipTrack(v, gp.new_tile, diagdir, tracks);
|
||||
if (track == INVALID_TRACK) goto reverse_direction;
|
||||
|
||||
/* Try to avoid collision and keep distance between ships. */
|
||||
if (_settings_game.vehicle.ship_collision_avoidance) CheckDistanceBetweenShips(gp.new_tile, v, tracks, &track, diagdir);
|
||||
|
||||
const ShipSubcoordData &b = _ship_subcoord[diagdir][track];
|
||||
|
||||
gp.x = (gp.x & ~0xF) | b.x_subcoord;
|
||||
gp.y = (gp.y & ~0xF) | b.y_subcoord;
|
||||
|
||||
/* Call the landscape function and tell it that the vehicle entered the tile */
|
||||
r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
|
||||
if (HasBit(r, VETS_CANNOT_ENTER)) goto reverse_direction;
|
||||
|
||||
if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
|
||||
v->tile = gp.new_tile;
|
||||
v->state = TrackToTrackBits(track);
|
||||
|
||||
/* Update ship cache when the water class changes. Aqueducts are always canals. */
|
||||
WaterClass old_wc = GetEffectiveWaterClass(gp.old_tile);
|
||||
WaterClass new_wc = GetEffectiveWaterClass(gp.new_tile);
|
||||
if (old_wc != new_wc) v->UpdateCache();
|
||||
}
|
||||
|
||||
Direction new_direction = b.dir;
|
||||
DirDiff diff = DirDifference(new_direction, v->direction);
|
||||
switch (diff) {
|
||||
case DIRDIFF_SAME:
|
||||
case DIRDIFF_45RIGHT:
|
||||
case DIRDIFF_45LEFT:
|
||||
/* Continue at speed */
|
||||
v->rotation = v->direction = new_direction;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Stop for rotation */
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->direction = new_direction;
|
||||
/* Remember our current location to avoid movement glitch */
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* On a bridge */
|
||||
if (!IsTileType(gp.new_tile, MP_TUNNELBRIDGE) || !HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
|
||||
/* Bridge exit */
|
||||
if (_settings_game.vehicle.ship_collision_avoidance && gp.new_tile != TileVirtXY(v->x_pos, v->y_pos)) HandleSpeedOnAqueduct(v, gp.new_tile, v->tile);
|
||||
v->x_pos = gp.x;
|
||||
v->y_pos = gp.y;
|
||||
v->UpdatePosition();
|
||||
if ((v->vehstatus & VS_HIDDEN) == 0) v->Vehicle::UpdateViewport(true);
|
||||
return;
|
||||
|
||||
/* Ship is back on the bridge head, we need to consume its path
|
||||
* cache entry here as we didn't have to choose a ship track. */
|
||||
if (!v->path.empty()) v->path.pop_front();
|
||||
}
|
||||
/* Bridge exit */
|
||||
if (_settings_game.vehicle.ship_collision_avoidance && gp.new_tile != TileVirtXY(v->x_pos, v->y_pos)) HandleSpeedOnAqueduct(v, gp.new_tile, v->tile);
|
||||
|
||||
/* Ship is back on the bridge head, we need to consume its path
|
||||
* cache entry here as we didn't have to choose a ship track. */
|
||||
if (!v->path.empty()) v->path.pop_front();
|
||||
/* update image of ship, as well as delta XY */
|
||||
v->x_pos = gp.x;
|
||||
v->y_pos = gp.y;
|
||||
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
}
|
||||
|
||||
/* update image of ship, as well as delta XY */
|
||||
v->x_pos = gp.x;
|
||||
v->y_pos = gp.y;
|
||||
|
||||
getout:
|
||||
v->UpdatePosition();
|
||||
v->UpdateViewport(true, true);
|
||||
return;
|
||||
|
||||
reverse_direction:
|
||||
v->direction = ReverseDir(v->direction);
|
||||
direction_changed:
|
||||
/* Remember our current location to avoid movement glitch */
|
||||
v->rotation_x_pos = v->x_pos;
|
||||
v->rotation_y_pos = v->y_pos;
|
||||
UpdateShipSpeed(v, 0);
|
||||
v->path.clear();
|
||||
goto getout;
|
||||
}
|
||||
|
||||
bool Ship::Tick()
|
||||
|
Reference in New Issue
Block a user