summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbjarni <bjarni@openttd.org>2005-10-31 12:59:47 +0000
committerbjarni <bjarni@openttd.org>2005-10-31 12:59:47 +0000
commit682b9ee8e4e594b4737528ff769bbe526aee2f8e (patch)
tree27e67e4ab96bd9ad2c2eea8092cd15b2d09de93c
parent95d1c43565402743d5cf6f215886ba028a54bb93 (diff)
downloadopenttd-682b9ee8e4e594b4737528ff769bbe526aee2f8e.tar.xz
(svn r3111) -Fix: [autoreplace] [ 1341783 ] Assertion failure in vehicle.c line 378
running MaybeReplaceVehicle() is now delayed until after the loop in CallVehicleTicks() This avoids selling the vehicle the loop currently works with (and continues to work with afterwards)
-rw-r--r--aircraft_cmd.c2
-rw-r--r--engine.c6
-rw-r--r--roadveh_cmd.c2
-rw-r--r--ship_cmd.c2
-rw-r--r--train_cmd.c2
-rw-r--r--vehicle.c51
-rw-r--r--vehicle.h6
7 files changed, 54 insertions, 17 deletions
diff --git a/aircraft_cmd.c b/aircraft_cmd.c
index 545a9f92e..2478a8e10 100644
--- a/aircraft_cmd.c
+++ b/aircraft_cmd.c
@@ -1302,8 +1302,6 @@ static void AircraftEnterHangar(Vehicle *v)
ServiceAircraft(v);
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
- v = MaybeReplaceVehicle(v);
-
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
if (v->current_order.type == OT_GOTO_DEPOT) {
diff --git a/engine.c b/engine.c
index acb4df082..df0a16308 100644
--- a/engine.c
+++ b/engine.c
@@ -718,6 +718,12 @@ static void DoTriggerVehicle(Vehicle *veh, VehicleTrigger trigger, byte base_ran
(resolve_callback) TriggerVehicleSpriteGroup);
}
+ if (trigger == VEHICLE_TRIGGER_DEPOT) {
+ // store that the vehicle entered a depot this tick
+ // it needs to be before all possible return statements;
+ VehicleEnteredDepotThisTick(veh);
+ }
+
if (group == NULL)
return;
diff --git a/roadveh_cmd.c b/roadveh_cmd.c
index 149fe3fd1..32a2fd25d 100644
--- a/roadveh_cmd.c
+++ b/roadveh_cmd.c
@@ -1522,8 +1522,6 @@ void RoadVehEnterDepot(Vehicle *v)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
- v = MaybeReplaceVehicle(v);
-
VehicleServiceInDepot(v);
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
diff --git a/ship_cmd.c b/ship_cmd.c
index 30f68c014..e0e099009 100644
--- a/ship_cmd.c
+++ b/ship_cmd.c
@@ -414,8 +414,6 @@ static void ShipEnterDepot(Vehicle *v)
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
- v = MaybeReplaceVehicle(v);
-
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
if (v->current_order.type == OT_GOTO_DEPOT) {
diff --git a/train_cmd.c b/train_cmd.c
index ef11c55ce..a93093a30 100644
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -3328,8 +3328,6 @@ void TrainEnterDepot(Vehicle *v, TileIndex tile)
v->load_unload_time_rem = 0;
v->cur_speed = 0;
- v = MaybeReplaceVehicle(v);
-
TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
if (v->current_order.type == OT_GOTO_DEPOT) {
diff --git a/vehicle.c b/vehicle.c
index e477c3667..fbbd7db3b 100644
--- a/vehicle.c
+++ b/vehicle.c
@@ -264,6 +264,7 @@ static Vehicle *InitializeVehicle(Vehicle *v)
v->string_id = 0;
v->next_shared = NULL;
v->prev_shared = NULL;
+ v->depot_list = NULL;
/* random_bits is used to pick out a random sprite for vehicles
which are technical the same (newgrf stuff).
Because RandomRange() results in desyncs, and because it does
@@ -515,6 +516,24 @@ void Ship_Tick(Vehicle *v);
void Train_Tick(Vehicle *v);
static void EffectVehicle_Tick(Vehicle *v);
void DisasterVehicle_Tick(Vehicle *v);
+static void MaybeReplaceVehicle(Vehicle *v);
+
+// head of the linked list to tell what vehicles that visited a depot in a tick
+Vehicle *_first_veh_in_depot_list;
+
+/** Adds a vehicle to the list of vehicles, that visited a depot this tick
+* @param *v vehicle to add
+*/
+void VehicleEnteredDepotThisTick(Vehicle *v)
+{
+ if (_first_veh_in_depot_list == NULL) {
+ _first_veh_in_depot_list = v;
+ } else {
+ Vehicle *w = _first_veh_in_depot_list;
+ while (w->depot_list != NULL) w = w->depot_list;
+ w->depot_list = v;
+ }
+}
VehicleTickProc *_vehicle_tick_procs[] = {
Train_Tick,
@@ -529,9 +548,21 @@ void CallVehicleTicks(void)
{
Vehicle *v;
+ _first_veh_in_depot_list = NULL; // now we are sure it's initialized at the start of each tick
+
FOR_ALL_VEHICLES(v) {
- if (v->type != 0)
+ if (v->type != 0) {
_vehicle_tick_procs[v->type - 0x10](v);
+ }
+ }
+
+ // now we handle all the vehicles that entered a depot this tick
+ v = _first_veh_in_depot_list;
+ while (v != NULL) {
+ Vehicle *w = v->depot_list;
+ v->depot_list = NULL; // it should always be NULL at the end of each tick
+ MaybeReplaceVehicle(v);
+ v = w;
}
}
@@ -1566,18 +1597,21 @@ static int32 ReplaceVehicle(Vehicle **w, byte flags)
* if the vehicle is a train, v needs to be the front engine
* return value is a pointer to the new vehicle, which is the same as the argument if nothing happened
*/
-Vehicle * MaybeReplaceVehicle(Vehicle *v)
+static void MaybeReplaceVehicle(Vehicle *v)
{
Vehicle *w;
const Player *p = GetPlayer(v->owner);
byte flags = 0;
int32 cost = 0, temp_cost = 0;
+ bool stopped = false;
_current_player = v->owner;
assert(v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || v->type == VEH_Aircraft);
-
- DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type));
+ if (!(v->vehstatus&VS_STOPPED)) {
+ stopped = true; // we stop the vehicle to do this, so we have to remember to start it again when we are done
+ DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type));
+ }
while (true) {
w = v;
@@ -1626,8 +1660,9 @@ Vehicle * MaybeReplaceVehicle(Vehicle *v)
AddNewsItem(message, NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0), v->index, 0);
}
- DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again
- return v;
+ if (stopped)
+ DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again
+ return;
}
if (flags & DC_EXEC) {
@@ -1641,9 +1676,9 @@ Vehicle * MaybeReplaceVehicle(Vehicle *v)
SubtractMoneyFromPlayer(cost);
if (IsLocalPlayer()) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost);
- DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again
+ if (stopped)
+ DoCommand(0, 0, v->index, 0, DC_EXEC, CMD_STARTSTOP_VEH(v->type)); //we start the vehicle again
_current_player = OWNER_NONE;
- return v;
}
diff --git a/vehicle.h b/vehicle.h
index ef0646b5f..b1d3d81fe 100644
--- a/vehicle.h
+++ b/vehicle.h
@@ -153,6 +153,7 @@ struct Vehicle {
Vehicle *next; // next
Vehicle *first; // NOSAVE: pointer to the first vehicle in the chain
+ Vehicle *depot_list; //NOSAVE: linked list to tell what vehicles entered a depot during the last tick. Used by autoreplace
StringID string_id; // Displayed string
@@ -164,6 +165,7 @@ struct Vehicle {
int32 x_pos; // coordinates
int32 y_pos;
+
byte z_pos;
byte direction; // facing
@@ -240,6 +242,8 @@ struct Vehicle {
int32 profit_last_year;
uint32 value;
+
+
union {
VehicleRail rail;
VehicleAir air;
@@ -309,7 +313,7 @@ Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y);
void DecreaseVehicleValue(Vehicle *v);
void CheckVehicleBreakdown(Vehicle *v);
void AgeVehicle(Vehicle *v);
-Vehicle * MaybeReplaceVehicle(Vehicle *v);
+void VehicleEnteredDepotThisTick(Vehicle *v);
void BeginVehicleMove(Vehicle *v);
void EndVehicleMove(Vehicle *v);