mirror of https://github.com/OpenTTD/OpenTTD
(svn r4259) -[multistop] Fix/Feature/Codechange:
1) Improved the road vehicle allocation (aka slotting) for multistop. Stops can now accept unlimited, er... 256, vehicles. 2) Removed the "wait for stop" feature, because it did not work in practise. 3) Slotting now ignores unreachable stations. Uses NPF at the moment because the old pathfinder cannot do it (yet) 4) Now matter how many vehicles approach a station, they will always be distributed evenly over existing stops. 5) Hopefully the last fundamental change to multistoprelease/0.5
parent
961b44e697
commit
5931b34aff
|
@ -92,30 +92,6 @@ static void IConsoleHelp(const char *str)
|
||||||
IConsolePrintF(_icolour_warn, "- %s", str);
|
IConsolePrintF(_icolour_warn, "- %s", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConResetSlots)
|
|
||||||
{
|
|
||||||
Vehicle *v;
|
|
||||||
RoadStop *rs;
|
|
||||||
if (argc == 0) {
|
|
||||||
IConsoleHelp("Resets all slots in the game. For debugging only. Usage: 'clearslots'");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FOR_ALL_VEHICLES(v) {
|
|
||||||
if (IsValidVehicle(v)) {
|
|
||||||
if (v->type == VEH_Road)
|
|
||||||
ClearSlot(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FOR_ALL_ROADSTOPS(rs) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < NUM_SLOTS; i++) rs->slot[i] = INVALID_VEHICLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DEF_CONSOLE_CMD(ConStopAllVehicles)
|
DEF_CONSOLE_CMD(ConStopAllVehicles)
|
||||||
{
|
{
|
||||||
Vehicle* v;
|
Vehicle* v;
|
||||||
|
@ -1389,7 +1365,6 @@ void IConsoleStdLibRegister(void)
|
||||||
IConsoleCmdRegister("cd", ConChangeDirectory);
|
IConsoleCmdRegister("cd", ConChangeDirectory);
|
||||||
IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
|
IConsoleCmdRegister("pwd", ConPrintWorkingDirectory);
|
||||||
IConsoleCmdRegister("clear", ConClearBuffer);
|
IConsoleCmdRegister("clear", ConClearBuffer);
|
||||||
IConsoleCmdRegister("clearslots", ConResetSlots);
|
|
||||||
IConsoleCmdRegister("stopall", ConStopAllVehicles);
|
IConsoleCmdRegister("stopall", ConStopAllVehicles);
|
||||||
|
|
||||||
IConsoleAliasRegister("dir", "ls");
|
IConsoleAliasRegister("dir", "ls");
|
||||||
|
|
|
@ -2494,7 +2494,6 @@ STR_8860_RELIABILITY_BREAKDOWNS :{BLACK}Reliabil
|
||||||
STR_8861_STOPPED :{RED}Stopped
|
STR_8861_STOPPED :{RED}Stopped
|
||||||
STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger...
|
STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL :{WHITE}Can't make train pass signal at danger...
|
||||||
STR_8863_CRASHED :{RED}Crashed!
|
STR_8863_CRASHED :{RED}Crashed!
|
||||||
STR_8864_WAIT_FOR_SLOT :{YELLOW}Waiting for a free stop
|
|
||||||
|
|
||||||
STR_8865_NAME_TRAIN :{WHITE}Name train
|
STR_8865_NAME_TRAIN :{WHITE}Name train
|
||||||
STR_8866_CAN_T_NAME_TRAIN :{WHITE}Can't name train...
|
STR_8866_CAN_T_NAME_TRAIN :{WHITE}Can't name train...
|
||||||
|
|
|
@ -356,7 +356,6 @@ static void FixOldTowns(void)
|
||||||
static void FixOldStations(void)
|
static void FixOldStations(void)
|
||||||
{
|
{
|
||||||
Station *st;
|
Station *st;
|
||||||
int i;
|
|
||||||
|
|
||||||
FOR_ALL_STATIONS(st) {
|
FOR_ALL_STATIONS(st) {
|
||||||
/* Check if we need to swap width and height for the station */
|
/* Check if we need to swap width and height for the station */
|
||||||
|
@ -373,7 +372,7 @@ static void FixOldStations(void)
|
||||||
st->bus_stops->station = st->index;
|
st->bus_stops->station = st->index;
|
||||||
st->bus_stops->next = NULL;
|
st->bus_stops->next = NULL;
|
||||||
st->bus_stops->prev = NULL;
|
st->bus_stops->prev = NULL;
|
||||||
for (i = 0; i < NUM_SLOTS; i++) st->bus_stops->slot[i] = INVALID_VEHICLE;
|
st->bus_stops->num_vehicles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (st->lorry_tile_obsolete != 0) {
|
if (st->lorry_tile_obsolete != 0) {
|
||||||
|
@ -384,7 +383,7 @@ static void FixOldStations(void)
|
||||||
st->truck_stops->station = st->index;
|
st->truck_stops->station = st->index;
|
||||||
st->truck_stops->next = NULL;
|
st->truck_stops->next = NULL;
|
||||||
st->truck_stops->prev = NULL;
|
st->truck_stops->prev = NULL;
|
||||||
for (i = 0; i < NUM_SLOTS; i++) st->truck_stops->slot[i] = INVALID_VEHICLE;
|
st->truck_stops->num_vehicles = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
openttd.c
11
openttd.c
|
@ -1391,6 +1391,17 @@ bool AfterLoadGame(void)
|
||||||
|
|
||||||
if (CheckSavegameVersion(22)) UpdatePatches();
|
if (CheckSavegameVersion(22)) UpdatePatches();
|
||||||
|
|
||||||
|
if (CheckSavegameVersion(25)) {
|
||||||
|
Vehicle *v;
|
||||||
|
FOR_ALL_VEHICLES(v) {
|
||||||
|
if (v->type == VEH_Road) {
|
||||||
|
v->vehstatus &= ~0x40;
|
||||||
|
v->u.road.slot = NULL;
|
||||||
|
v->u.road.slot_age = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
|
FOR_ALL_PLAYERS(p) p->avail_railtypes = GetPlayerRailtypes(p->index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
107
roadveh_cmd.c
107
roadveh_cmd.c
|
@ -1,5 +1,6 @@
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "openttd.h"
|
#include "openttd.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -164,10 +165,6 @@ int32 CmdBuildRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
// v->u.road.unk2 = 0;
|
// v->u.road.unk2 = 0;
|
||||||
// v->u.road.overtaking = 0;
|
// v->u.road.overtaking = 0;
|
||||||
|
|
||||||
v->u.road.slot = NULL;
|
|
||||||
v->u.road.slotindex = 0;
|
|
||||||
v->u.road.slot_age = 0;
|
|
||||||
|
|
||||||
v->last_station_visited = INVALID_STATION;
|
v->last_station_visited = INVALID_STATION;
|
||||||
v->max_speed = rvi->max_speed;
|
v->max_speed = rvi->max_speed;
|
||||||
v->engine_type = (byte)p1;
|
v->engine_type = (byte)p1;
|
||||||
|
@ -238,10 +235,10 @@ void ClearSlot(Vehicle *v)
|
||||||
v->u.road.slot = NULL;
|
v->u.road.slot = NULL;
|
||||||
v->u.road.slot_age = 0;
|
v->u.road.slot_age = 0;
|
||||||
|
|
||||||
// check that the slot is indeed assigned to the same vehicle
|
assert(rs->num_vehicles != 0);
|
||||||
assert(rs->slot[v->u.road.slotindex] == v->index);
|
rs->num_vehicles--;
|
||||||
rs->slot[v->u.road.slotindex] = INVALID_VEHICLE;
|
|
||||||
DEBUG(ms, 3) ("Multistop: Clearing slot %d at 0x%x", v->u.road.slotindex, rs->xy);
|
DEBUG(ms, 3) ("Multistop: Clearing slot at 0x%x", rs->xy);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sell a road vehicle.
|
/** Sell a road vehicle.
|
||||||
|
@ -382,7 +379,6 @@ int32 CmdSendRoadVehToDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
ClearSlot(v);
|
ClearSlot(v);
|
||||||
v->vehstatus &= ~VS_WAIT_FOR_SLOT;
|
|
||||||
v->current_order.type = OT_GOTO_DEPOT;
|
v->current_order.type = OT_GOTO_DEPOT;
|
||||||
v->current_order.flags = OF_NON_STOP | OF_HALT_IN_DEPOT;
|
v->current_order.flags = OF_NON_STOP | OF_HALT_IN_DEPOT;
|
||||||
v->current_order.station = dep->index;
|
v->current_order.station = dep->index;
|
||||||
|
@ -408,7 +404,7 @@ int32 CmdTurnRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
|
|
||||||
if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR;
|
if (v->type != VEH_Road || !CheckOwnership(v->owner)) return CMD_ERROR;
|
||||||
|
|
||||||
if (v->vehstatus & (VS_HIDDEN | VS_STOPPED | VS_WAIT_FOR_SLOT) ||
|
if (v->vehstatus & (VS_HIDDEN | VS_STOPPED) ||
|
||||||
v->u.road.crashed_ctr != 0 ||
|
v->u.road.crashed_ctr != 0 ||
|
||||||
v->breakdown_ctr != 0 ||
|
v->breakdown_ctr != 0 ||
|
||||||
v->u.road.overtaking != 0 ||
|
v->u.road.overtaking != 0 ||
|
||||||
|
@ -633,7 +629,6 @@ static void ProcessRoadVehOrder(Vehicle *v)
|
||||||
v->current_order.flags = 0;
|
v->current_order.flags = 0;
|
||||||
v->dest_tile = 0;
|
v->dest_tile = 0;
|
||||||
ClearSlot(v);
|
ClearSlot(v);
|
||||||
v->vehstatus &= ~VS_WAIT_FOR_SLOT;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,8 +640,6 @@ static void ProcessRoadVehOrder(Vehicle *v)
|
||||||
|
|
||||||
v->current_order = *order;
|
v->current_order = *order;
|
||||||
v->dest_tile = 0;
|
v->dest_tile = 0;
|
||||||
/* We have changed the destination STATION, so resume movement */
|
|
||||||
v->vehstatus &= ~VS_WAIT_FOR_SLOT;
|
|
||||||
|
|
||||||
if (order->type == OT_GOTO_STATION) {
|
if (order->type == OT_GOTO_STATION) {
|
||||||
const Station* st = GetStation(order->station);
|
const Station* st = GetStation(order->station);
|
||||||
|
@ -907,7 +900,7 @@ static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
|
||||||
od.u = u;
|
od.u = u;
|
||||||
|
|
||||||
if (u->max_speed >= v->max_speed &&
|
if (u->max_speed >= v->max_speed &&
|
||||||
!(u->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) &&
|
!(u->vehstatus & VS_STOPPED) &&
|
||||||
u->cur_speed != 0) {
|
u->cur_speed != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -929,7 +922,7 @@ static void RoadVehCheckOvertake(Vehicle *v, Vehicle *u)
|
||||||
od.tile = v->tile + TileOffsByDir(DirToDiagDir(v->direction));
|
od.tile = v->tile + TileOffsByDir(DirToDiagDir(v->direction));
|
||||||
if (FindRoadVehToOvertake(&od)) return;
|
if (FindRoadVehToOvertake(&od)) return;
|
||||||
|
|
||||||
if (od.u->cur_speed == 0 || od.u->vehstatus& (VS_STOPPED | VS_WAIT_FOR_SLOT)) {
|
if (od.u->cur_speed == 0 || od.u->vehstatus& VS_STOPPED) {
|
||||||
v->u.road.overtaking_ctr = 0x11;
|
v->u.road.overtaking_ctr = 0x11;
|
||||||
v->u.road.overtaking = 0x10;
|
v->u.road.overtaking = 0x10;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1133,7 +1126,6 @@ found_best_track:;
|
||||||
return best_track;
|
return best_track;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0 /* Commented out until NPF works properly here */
|
|
||||||
static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
|
static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
|
||||||
{
|
{
|
||||||
NPFFindStationOrTileData fstd;
|
NPFFindStationOrTileData fstd;
|
||||||
|
@ -1145,7 +1137,6 @@ static uint RoadFindPathToStop(const Vehicle *v, TileIndex tile)
|
||||||
|
|
||||||
return NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
|
return NPFRouteToStationOrTile(v->tile, trackdir, &fstd, TRANSPORT_ROAD, v->owner, INVALID_RAILTYPE).best_path_dist;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct RoadDriveEntry {
|
typedef struct RoadDriveEntry {
|
||||||
byte x,y;
|
byte x,y;
|
||||||
|
@ -1191,7 +1182,7 @@ static void RoadVehController(Vehicle *v)
|
||||||
v->breakdown_ctr--;
|
v->breakdown_ctr--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) return;
|
if (v->vehstatus & VS_STOPPED) return;
|
||||||
|
|
||||||
ProcessRoadVehOrder(v);
|
ProcessRoadVehOrder(v);
|
||||||
HandleRoadVehLoading(v);
|
HandleRoadVehLoading(v);
|
||||||
|
@ -1454,7 +1445,6 @@ again:
|
||||||
v->current_order.type = OT_NOTHING;
|
v->current_order.type = OT_NOTHING;
|
||||||
v->current_order.flags = 0;
|
v->current_order.flags = 0;
|
||||||
ClearSlot(v);
|
ClearSlot(v);
|
||||||
v->vehstatus &= ~VS_WAIT_FOR_SLOT;
|
|
||||||
}
|
}
|
||||||
SETBIT(rs->status, 7);
|
SETBIT(rs->status, 7);
|
||||||
|
|
||||||
|
@ -1560,7 +1550,7 @@ static void CheckIfRoadVehNeedsService(Vehicle *v)
|
||||||
|
|
||||||
if (_patches.servint_roadveh == 0) return;
|
if (_patches.servint_roadveh == 0) return;
|
||||||
if (!VehicleNeedsService(v)) return;
|
if (!VehicleNeedsService(v)) return;
|
||||||
if (v->vehstatus & (VS_STOPPED | VS_WAIT_FOR_SLOT)) return;
|
if (v->vehstatus & VS_STOPPED) return;
|
||||||
if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
|
if (_patches.gotodepot && VehicleHasDepotOrders(v)) return;
|
||||||
|
|
||||||
// Don't interfere with a depot visit scheduled by the user, or a
|
// Don't interfere with a depot visit scheduled by the user, or a
|
||||||
|
@ -1610,82 +1600,57 @@ void OnNewDay_RoadVeh(Vehicle *v)
|
||||||
CheckOrders(v);
|
CheckOrders(v);
|
||||||
|
|
||||||
//Current slot has expired
|
//Current slot has expired
|
||||||
if (v->u.road.slot_age-- == 0 && v->u.road.slot != NULL) {
|
if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot_age-- == 0 && v->u.road.slot != NULL) {
|
||||||
DEBUG(ms, 2) ("Multistop: Slot %d expired for vehicle %d (index %d) at stop 0x%x",
|
DEBUG(ms, 2) ("Multistop: Slot expired for vehicle %d (index %d) at stop 0x%x",
|
||||||
v->u.road.slotindex, v->unitnumber, v->index, v->u.road.slot->xy
|
v->unitnumber, v->index, v->u.road.slot->xy);
|
||||||
);
|
|
||||||
ClearSlot(v);
|
ClearSlot(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v->vehstatus & VS_STOPPED) return;
|
if (v->vehstatus & VS_STOPPED) return;
|
||||||
|
|
||||||
/* update destination */
|
/* update destination */
|
||||||
if (v->current_order.type == OT_GOTO_STATION &&
|
if (v->current_order.type == OT_GOTO_STATION && v->u.road.slot == NULL && !(v->vehstatus & VS_CRASHED)) {
|
||||||
v->u.road.slot == NULL &&
|
|
||||||
!IsLevelCrossing(v->tile) &&
|
|
||||||
v->u.road.overtaking == 0 &&
|
|
||||||
!(v->vehstatus & VS_CRASHED)) {
|
|
||||||
RoadStopType type = (v->cargo_type == CT_PASSENGERS) ? RS_BUS : RS_TRUCK;
|
|
||||||
RoadStop *rs;
|
RoadStop *rs;
|
||||||
uint mindist = 0xFFFFFFFF;
|
RoadStop *best = NULL;
|
||||||
int i;
|
|
||||||
RoadStop *nearest = NULL;
|
|
||||||
|
|
||||||
st = GetStation(v->current_order.station);
|
st = GetStation(v->current_order.station);
|
||||||
rs = GetPrimaryRoadStop(st, type);
|
rs = GetPrimaryRoadStop(st, v->cargo_type == CT_PASSENGERS ? RS_BUS : RS_TRUCK);
|
||||||
|
|
||||||
if (rs != NULL) {
|
if (rs != NULL) {
|
||||||
if (DistanceManhattan(v->tile, st->xy) < 16) {
|
if (DistanceManhattan(v->tile, st->xy) < 16) {
|
||||||
int new_slot = -1;
|
uint dist, badness;
|
||||||
|
uint minbadness = UINT_MAX;
|
||||||
|
|
||||||
DEBUG(ms, 2) ("Multistop: Attempting to obtain a slot for vehicle %d (index %d) at station %d (0x%x)", v->unitnumber,
|
DEBUG(ms, 2) ("Multistop: Attempting to obtain a slot for vehicle %d (index %d) at station %d (0x%x)", v->unitnumber,
|
||||||
v->index, st->index, st->xy);
|
v->index, st->index, st->xy);
|
||||||
/* Now we find the nearest road stop that has a free slot */
|
/* Now we find the nearest road stop that has a free slot */
|
||||||
for (i = 0; rs != NULL; rs = rs->next, i++) {
|
for (; rs != NULL; rs = rs->next) {
|
||||||
uint dist = 0xFFFFFFFF;
|
dist = RoadFindPathToStop(v, rs->xy);
|
||||||
bool is_slot_free = false;
|
if (dist == UINT_MAX) {
|
||||||
int k;
|
DEBUG(ms, 4) (" ---- stop 0x%x is not reachable, not treating further", rs->xy);
|
||||||
int last_free = -1;
|
|
||||||
|
|
||||||
for (k = 0; k < NUM_SLOTS; k++)
|
|
||||||
if (rs->slot[k] == INVALID_VEHICLE) {
|
|
||||||
is_slot_free = true;
|
|
||||||
last_free = k;
|
|
||||||
dist = DistanceManhattan(v->tile, st->xy);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_slot_free) {
|
|
||||||
DEBUG(ms, 4) ("Multistop: ---- stop %d is full", i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
badness = (rs->num_vehicles + 1) * (rs->num_vehicles + 1) + dist / NPF_TILE_LENGTH;
|
||||||
|
|
||||||
DEBUG(ms, 4) ("Multistop: ---- distance to stop %d is %d", i, dist);
|
DEBUG(ms, 4) (" ---- stop 0x%x has %d vehicle%s waiting", rs->xy, rs->num_vehicles, rs->num_vehicles == 1 ? "":"s");
|
||||||
if (dist < mindist) {
|
DEBUG(ms, 4) (" ---- Distance is %u", dist);
|
||||||
nearest = rs;
|
DEBUG(ms, 4) (" -- Badness %u", badness);
|
||||||
mindist = dist;
|
|
||||||
new_slot = last_free;
|
if (badness < minbadness) {
|
||||||
|
best = rs;
|
||||||
|
minbadness = badness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nearest != NULL) { /* We have a suitable stop */
|
if (best != NULL) {
|
||||||
DEBUG(ms, 3) ("Multistop: -- Slot %d of stop at 0x%x assinged.", new_slot, nearest->xy);
|
best->num_vehicles++;
|
||||||
nearest->slot[new_slot] = v->index;
|
DEBUG(ms, 3) (" -- Assigned to stop 0x%x", best->xy);
|
||||||
|
|
||||||
v->u.road.slot = nearest;
|
v->u.road.slot = best;
|
||||||
v->dest_tile = nearest->xy;
|
v->dest_tile = best->xy;
|
||||||
v->u.road.slot_age = 14;
|
v->u.road.slot_age = 14;
|
||||||
v->u.road.slotindex = new_slot;
|
|
||||||
|
|
||||||
if (v->vehstatus & VS_WAIT_FOR_SLOT) {
|
|
||||||
DEBUG(ms, 4) ("Multistop: ---- stopped vehicle got a slot. resuming movement");
|
|
||||||
v->vehstatus &= ~VS_WAIT_FOR_SLOT;
|
|
||||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
DEBUG(ms, 2) ("Multistop -- No free slot at station. Waiting");
|
DEBUG(ms, 3) (" -- Could not find a suitable stop");
|
||||||
v->vehstatus |= VS_WAIT_FOR_SLOT;
|
|
||||||
InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DEBUG(ms, 5) ("Multistop: --- Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%x)",
|
DEBUG(ms, 5) ("Multistop: --- Distance from station too far. Postponing slotting for vehicle %d (index %d) at station %d, (0x%x)",
|
||||||
|
|
|
@ -247,8 +247,6 @@ static void RoadVehViewWndProc(Window *w, WindowEvent *e)
|
||||||
str = STR_885C_BROKEN_DOWN;
|
str = STR_885C_BROKEN_DOWN;
|
||||||
} else if (v->vehstatus & VS_STOPPED) {
|
} else if (v->vehstatus & VS_STOPPED) {
|
||||||
str = STR_8861_STOPPED;
|
str = STR_8861_STOPPED;
|
||||||
} else if (v->vehstatus & VS_WAIT_FOR_SLOT) {
|
|
||||||
str = STR_8864_WAIT_FOR_SLOT;
|
|
||||||
} else {
|
} else {
|
||||||
switch (v->current_order.type) {
|
switch (v->current_order.type) {
|
||||||
case OT_GOTO_STATION: {
|
case OT_GOTO_STATION: {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include "variables.h"
|
#include "variables.h"
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
|
|
||||||
const uint16 SAVEGAME_VERSION = 24;
|
const uint16 SAVEGAME_VERSION = 25;
|
||||||
uint16 _sl_version; /// the major savegame version identifier
|
uint16 _sl_version; /// the major savegame version identifier
|
||||||
byte _sl_minor_version; /// the minor savegame version, DO NOT USE!
|
byte _sl_minor_version; /// the minor savegame version, DO NOT USE!
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ typedef enum RoadStopType {
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
INVALID_STATION = 0xFFFF,
|
INVALID_STATION = 0xFFFF,
|
||||||
NUM_SLOTS = 2,
|
|
||||||
ROAD_STOP_LIMIT = 16,
|
ROAD_STOP_LIMIT = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ typedef struct RoadStop {
|
||||||
bool used;
|
bool used;
|
||||||
byte status;
|
byte status;
|
||||||
uint32 index;
|
uint32 index;
|
||||||
VehicleID slot[NUM_SLOTS];
|
byte num_vehicles;
|
||||||
StationID station;
|
StationID station;
|
||||||
uint8 type;
|
uint8 type;
|
||||||
struct RoadStop *next;
|
struct RoadStop *next;
|
||||||
|
|
|
@ -87,15 +87,13 @@ static void MarkStationDirty(const Station* st)
|
||||||
|
|
||||||
static void InitializeRoadStop(RoadStop *road_stop, RoadStop *previous, TileIndex tile, StationID index)
|
static void InitializeRoadStop(RoadStop *road_stop, RoadStop *previous, TileIndex tile, StationID index)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
road_stop->xy = tile;
|
road_stop->xy = tile;
|
||||||
road_stop->used = true;
|
road_stop->used = true;
|
||||||
road_stop->status = 3; //stop is free
|
road_stop->status = 3; //stop is free
|
||||||
road_stop->next = NULL;
|
road_stop->next = NULL;
|
||||||
road_stop->prev = previous;
|
road_stop->prev = previous;
|
||||||
road_stop->station = index;
|
road_stop->station = index;
|
||||||
|
road_stop->num_vehicles = 0;
|
||||||
for (i = 0; i < NUM_SLOTS; i++) road_stop->slot[i] = INVALID_VEHICLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RoadStop* GetPrimaryRoadStop(const Station* st, RoadStopType type)
|
RoadStop* GetPrimaryRoadStop(const Station* st, RoadStopType type)
|
||||||
|
@ -1412,17 +1410,8 @@ static int32 RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
|
||||||
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
|
||||||
|
|
||||||
if (flags & DC_EXEC) {
|
if (flags & DC_EXEC) {
|
||||||
uint i;
|
|
||||||
DoClearSquare(tile);
|
DoClearSquare(tile);
|
||||||
|
|
||||||
/* Clear all vehicles destined for this station */
|
|
||||||
for (i = 0; i != NUM_SLOTS; i++) {
|
|
||||||
if (cur_stop->slot[i] != INVALID_VEHICLE) {
|
|
||||||
Vehicle *v = GetVehicle(cur_stop->slot[i]);
|
|
||||||
ClearSlot(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_stop->used = false;
|
cur_stop->used = false;
|
||||||
if (cur_stop->prev != NULL) cur_stop->prev->next = cur_stop->next;
|
if (cur_stop->prev != NULL) cur_stop->prev->next = cur_stop->next;
|
||||||
if (cur_stop->next != NULL) cur_stop->next->prev = cur_stop->prev;
|
if (cur_stop->next != NULL) cur_stop->next->prev = cur_stop->prev;
|
||||||
|
@ -2254,27 +2243,6 @@ void DeleteAllPlayerStations(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CheckOrphanedSlots(const Station *st, RoadStopType rst)
|
|
||||||
{
|
|
||||||
RoadStop *rs;
|
|
||||||
uint k;
|
|
||||||
|
|
||||||
for (rs = GetPrimaryRoadStop(st, rst); rs != NULL; rs = rs->next) {
|
|
||||||
for (k = 0; k < NUM_SLOTS; k++) {
|
|
||||||
if (rs->slot[k] != INVALID_VEHICLE) {
|
|
||||||
const Vehicle *v = GetVehicle(rs->slot[k]);
|
|
||||||
|
|
||||||
if (v->type != VEH_Road || v->u.road.slot != rs) {
|
|
||||||
DEBUG(ms, 0) (
|
|
||||||
"Multistop: Orphaned %s slot at 0x%X of station %d (don't panic)",
|
|
||||||
(rst == RS_BUS) ? "bus" : "truck", rs->xy, st->index);
|
|
||||||
rs->slot[k] = INVALID_VEHICLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this function is called for one station each tick */
|
/* this function is called for one station each tick */
|
||||||
static void StationHandleBigTick(Station *st)
|
static void StationHandleBigTick(Station *st)
|
||||||
{
|
{
|
||||||
|
@ -2282,9 +2250,6 @@ static void StationHandleBigTick(Station *st)
|
||||||
|
|
||||||
if (st->facilities == 0 && ++st->delete_ctr >= 8) DeleteStation(st);
|
if (st->facilities == 0 && ++st->delete_ctr >= 8) DeleteStation(st);
|
||||||
|
|
||||||
// Here we saveguard against orphaned slots
|
|
||||||
CheckOrphanedSlots(st, RS_BUS);
|
|
||||||
CheckOrphanedSlots(st, RS_TRUCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void byte_inc_sat(byte *p) { byte b = *p + 1; if (b != 0) *p = b; }
|
static inline void byte_inc_sat(byte *p) { byte b = *p + 1; if (b != 0) *p = b; }
|
||||||
|
@ -2783,7 +2748,8 @@ static const SaveLoad _roadstop_desc[] = {
|
||||||
SLE_REF(RoadStop,next, REF_ROADSTOPS),
|
SLE_REF(RoadStop,next, REF_ROADSTOPS),
|
||||||
SLE_REF(RoadStop,prev, REF_ROADSTOPS),
|
SLE_REF(RoadStop,prev, REF_ROADSTOPS),
|
||||||
|
|
||||||
SLE_ARR(RoadStop,slot, SLE_UINT16, NUM_SLOTS),
|
SLE_CONDNULL(4, 0, 24),
|
||||||
|
SLE_CONDVAR(RoadStop, num_vehicles, SLE_UINT8, 25, SL_MAX_VERSION),
|
||||||
|
|
||||||
SLE_END()
|
SLE_END()
|
||||||
};
|
};
|
||||||
|
@ -2952,6 +2918,7 @@ static void Load_ROADSTOP(void)
|
||||||
error("RoadStops: failed loading savegame: too many RoadStops");
|
error("RoadStops: failed loading savegame: too many RoadStops");
|
||||||
|
|
||||||
rs = GetRoadStop(index);
|
rs = GetRoadStop(index);
|
||||||
|
rs->num_vehicles = 0;
|
||||||
SlObject(rs, _roadstop_desc);
|
SlObject(rs, _roadstop_desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2213,7 +2213,7 @@ static const SaveLoad _roadveh_desc[] = {
|
||||||
SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,reverse_ctr), SLE_UINT8),
|
SLE_VARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,reverse_ctr), SLE_UINT8),
|
||||||
|
|
||||||
SLE_CONDREFX(offsetof(Vehicle,u)+offsetof(VehicleRoad,slot), REF_ROADSTOPS, 6, SL_MAX_VERSION),
|
SLE_CONDREFX(offsetof(Vehicle,u)+offsetof(VehicleRoad,slot), REF_ROADSTOPS, 6, SL_MAX_VERSION),
|
||||||
SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,slotindex), SLE_UINT8, 6, SL_MAX_VERSION),
|
SLE_CONDNULL(1, 6, SL_MAX_VERSION),
|
||||||
SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,slot_age), SLE_UINT8, 6, SL_MAX_VERSION),
|
SLE_CONDVARX(offsetof(Vehicle,u)+offsetof(VehicleRoad,slot_age), SLE_UINT8, 6, SL_MAX_VERSION),
|
||||||
// reserve extra space in savegame here. (currently 16 bytes)
|
// reserve extra space in savegame here. (currently 16 bytes)
|
||||||
SLE_CONDNULL(16, 2, SL_MAX_VERSION),
|
SLE_CONDNULL(16, 2, SL_MAX_VERSION),
|
||||||
|
|
|
@ -24,7 +24,6 @@ enum VehStatus {
|
||||||
VS_TRAIN_SLOWING = 0x10,
|
VS_TRAIN_SLOWING = 0x10,
|
||||||
VS_DISASTER = 0x20,
|
VS_DISASTER = 0x20,
|
||||||
VS_AIRCRAFT_BROKEN = 0x40,
|
VS_AIRCRAFT_BROKEN = 0x40,
|
||||||
VS_WAIT_FOR_SLOT = 0x40,
|
|
||||||
VS_CRASHED = 0x80,
|
VS_CRASHED = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,7 +110,6 @@ typedef struct VehicleRoad {
|
||||||
uint16 crashed_ctr;
|
uint16 crashed_ctr;
|
||||||
byte reverse_ctr;
|
byte reverse_ctr;
|
||||||
struct RoadStop *slot;
|
struct RoadStop *slot;
|
||||||
byte slotindex;
|
|
||||||
byte slot_age;
|
byte slot_age;
|
||||||
} VehicleRoad;
|
} VehicleRoad;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue