mirror of https://github.com/OpenTTD/OpenTTD
(svn r2168) - Fix: Various stages of invisible trains, and wrong v->u.rail.track combinations. When a vehicle was sold its (possibly) assigned road slot for multislot was not cleared, thus resulting in a bug confusion. This should fix [ 1178520 ] Assertion failure in ai.c (invalid v->u.rail.track). With big thanks to TrueLight for the demo-recording patch, BJH for the wonderful savegame, Hackykid for his brilliant suggestions of the problem and Celestar for... ehm, making it all possible ;p
parent
a9c52454c8
commit
7ef681eaed
|
@ -229,6 +229,15 @@ int32 CmdStartStopRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void ClearSlot(Vehicle *v, RoadStop *rs)
|
||||||
|
{
|
||||||
|
DEBUG(ms, 3) ("Multistop: Clearing slot %d at 0x%x", v->u.road.slotindex, rs->xy);
|
||||||
|
v->u.road.slot = NULL;
|
||||||
|
v->u.road.slot_age = 0;
|
||||||
|
if (rs != NULL)
|
||||||
|
rs->slot[v->u.road.slotindex] = INVALID_SLOT;
|
||||||
|
}
|
||||||
|
|
||||||
// p1 = vehicle index in GetVehicle()
|
// p1 = vehicle index in GetVehicle()
|
||||||
// p2 not used
|
// p2 not used
|
||||||
int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
|
@ -253,6 +262,7 @@ int32 CmdSellRoadVeh(int x, int y, uint32 flags, uint32 p1, uint32 p2)
|
||||||
RebuildVehicleLists();
|
RebuildVehicleLists();
|
||||||
InvalidateWindow(WC_COMPANY, v->owner);
|
InvalidateWindow(WC_COMPANY, v->owner);
|
||||||
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
|
DeleteWindowById(WC_VEHICLE_VIEW, v->index);
|
||||||
|
ClearSlot(v, v->u.road.slot);
|
||||||
DeleteVehicle(v);
|
DeleteVehicle(v);
|
||||||
}
|
}
|
||||||
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Road); // updates the replace Road window
|
InvalidateWindow(WC_REPLACE_VEHICLE, VEH_Road); // updates the replace Road window
|
||||||
|
@ -1177,14 +1187,6 @@ static const byte _road_veh_data_1[] = {
|
||||||
|
|
||||||
static const byte _roadveh_data_2[4] = { 0,1,8,9 };
|
static const byte _roadveh_data_2[4] = { 0,1,8,9 };
|
||||||
|
|
||||||
static inline void ClearSlot(Vehicle *v, RoadStop *rs)
|
|
||||||
{
|
|
||||||
DEBUG(ms, 3) ("Multistop: Clearing slot %d at 0x%x", v->u.road.slotindex, rs->xy);
|
|
||||||
v->u.road.slot = NULL;
|
|
||||||
v->u.road.slot_age = 0;
|
|
||||||
rs->slot[v->u.road.slotindex] = INVALID_SLOT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void RoadVehController(Vehicle *v)
|
static void RoadVehController(Vehicle *v)
|
||||||
{
|
{
|
||||||
GetNewVehiclePosResult gp;
|
GetNewVehiclePosResult gp;
|
||||||
|
|
|
@ -2418,6 +2418,30 @@ void DeleteAllPlayerStations(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void CheckOrphanedSlots(const Station *st, RoadStopType rst)
|
||||||
|
{
|
||||||
|
RoadStop *rs;
|
||||||
|
int k;
|
||||||
|
|
||||||
|
for (rs = GetPrimaryRoadStop(st, rst); rs != NULL; rs = rs->next) {
|
||||||
|
for (k = 0; k < NUM_SLOTS; k++) {
|
||||||
|
if (rs->slot[k] != INVALID_SLOT) {
|
||||||
|
Vehicle *v = GetVehicle(rs->slot[k]);
|
||||||
|
|
||||||
|
assert(v->type == VEH_Road);
|
||||||
|
if (v->u.road.slot != rs) {
|
||||||
|
DEBUG(ms, 1) ("Multistop: %s slot desync between stop at 0x%X of station %d "
|
||||||
|
"and Vehicle %d at going to 0x%X! (don't panic)", (v->cargo_type == CT_PASSENGERS) ? "Bus" : "Truck",
|
||||||
|
rs->xy, st->index, v->unitnumber, v->dest_tile);
|
||||||
|
v->u.road.slot = NULL;
|
||||||
|
v->u.road.slot_age = 0;
|
||||||
|
rs->slot[k] = INVALID_SLOT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
|
@ -2429,51 +2453,8 @@ static void StationHandleBigTick(Station *st)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we saveguard against orphaned slots
|
// Here we saveguard against orphaned slots
|
||||||
{
|
CheckOrphanedSlots(st, RS_BUS);
|
||||||
RoadStop *rs;
|
CheckOrphanedSlots(st, RS_TRUCK);
|
||||||
|
|
||||||
for (rs = GetPrimaryRoadStop(st, RS_BUS); rs != NULL; rs = rs->next) {
|
|
||||||
int k;
|
|
||||||
for (k = 0; k < NUM_SLOTS; k++) {
|
|
||||||
if (rs->slot[k] != INVALID_SLOT) {
|
|
||||||
Vehicle *v = GetVehicle(rs->slot[k]);
|
|
||||||
|
|
||||||
if (v->u.road.slot != rs) {
|
|
||||||
DEBUG(ms, 1) ("Multistop: Truck Slot Desync between stop at "
|
|
||||||
"0x%x of station %d (at 0x%x) and Vehicle %d at 0x%x, "
|
|
||||||
"going to 0x%x! "
|
|
||||||
"cleaning up (Don't panic)",
|
|
||||||
rs->xy, st->index, st->xy, v->unitnumber, v->tile,
|
|
||||||
v->dest_tile);
|
|
||||||
v->u.road.slot = NULL;
|
|
||||||
v->u.road.slot_age = 0;
|
|
||||||
rs->slot[k] = INVALID_SLOT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (rs = GetPrimaryRoadStop(st, RS_TRUCK); rs != NULL; rs = rs->next) {
|
|
||||||
int k;
|
|
||||||
for (k = 0; k < NUM_SLOTS; k++) {
|
|
||||||
if (rs->slot[k] != INVALID_SLOT) {
|
|
||||||
Vehicle *v = GetVehicle(rs->slot[k]);
|
|
||||||
|
|
||||||
if (v->u.road.slot != rs) {
|
|
||||||
DEBUG(ms, 1) ("Multistop: Truck Slot Desync between stop at "
|
|
||||||
"0x%x of station %d (at 0x%x) and Vehicle %d at 0x%x, "
|
|
||||||
"going to 0x%x! "
|
|
||||||
"cleaning up (Don't panic)",
|
|
||||||
rs->xy, st->index, st->xy, v->unitnumber, v->tile,
|
|
||||||
v->dest_tile);
|
|
||||||
v->u.road.slot = NULL;
|
|
||||||
v->u.road.slot_age = 0;
|
|
||||||
rs->slot[k] = INVALID_SLOT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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; }
|
||||||
|
|
Loading…
Reference in New Issue