summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-09-17 04:23:03 +0000
committerrubidium <rubidium@openttd.org>2007-09-17 04:23:03 +0000
commit257fdb38e6dde17a1d3546d83c67679ccba7160b (patch)
tree7b1861fb2f716b857d3f3e5cc617f04cc8d36524
parentf3491cb062a5854b6a8c713520c6af3ca2b36335 (diff)
downloadopenttd-257fdb38e6dde17a1d3546d83c67679ccba7160b.tar.xz
(svn r11122) -Fix [FS#1234]: crash when building a NewGRF vehicle when the articulated build vehicle callback returneed a different value for the purchase window than the normal build. Thanks for Dalestan and _minime_ for pointers to possible causes.
-rw-r--r--src/articulated_vehicles.cpp13
-rw-r--r--src/articulated_vehicles.h2
-rw-r--r--src/build_vehicle_gui.cpp2
-rw-r--r--src/roadveh_cmd.cpp8
-rw-r--r--src/train_cmd.cpp16
5 files changed, 24 insertions, 17 deletions
diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp
index 0f6aa8954..0f9fe9cc1 100644
--- a/src/articulated_vehicles.cpp
+++ b/src/articulated_vehicles.cpp
@@ -15,16 +15,24 @@
#include "newgrf_engine.h"
-uint CountArticulatedParts(EngineID engine_type)
+uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
{
if (!HASBIT(EngInfo(engine_type)->callbackmask, CBM_ARTIC_ENGINE)) return 0;
+ Vehicle *v = NULL;;
+ if (!purchase_window) {
+ v = new InvalidVehicle();
+ v->engine_type = engine_type;
+ }
+
uint i;
for (i = 1; i < MAX_UVALUE(EngineID); i++) {
- uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, NULL);
+ uint16 callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, i, 0, engine_type, v);
if (callback == CALLBACK_FAILED || callback == 0xFF) break;
}
+ delete v;
+
return i - 1;
}
@@ -42,7 +50,6 @@ void AddArticulatedParts(Vehicle **vl, VehicleType type)
/* Attempt to use pre-allocated vehicles until they run out. This can happen
* if the callback returns different values depending on the cargo type. */
u->SetNext(vl[i]);
- if (u->Next() == NULL) u->SetNext(new InvalidVehicle());
if (u->Next() == NULL) return;
Vehicle *previous = u;
diff --git a/src/articulated_vehicles.h b/src/articulated_vehicles.h
index 45c9f1937..ff1342fb3 100644
--- a/src/articulated_vehicles.h
+++ b/src/articulated_vehicles.h
@@ -5,7 +5,7 @@
#ifndef ARTICULATED_VEHICLES_H
#define ARTICULATED_VEHICLES_H
-uint CountArticulatedParts(EngineID engine_type);
+uint CountArticulatedParts(EngineID engine_type, bool purchase_window);
void AddArticulatedParts(Vehicle **vl, VehicleType type);
#endif /* ARTICULATED_VEHICLES_H */
diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp
index 5728212ab..4cbc267be 100644
--- a/src/build_vehicle_gui.cpp
+++ b/src/build_vehicle_gui.cpp
@@ -621,7 +621,7 @@ int DrawVehiclePurchaseInfo(int x, int y, uint w, EngineID engine_number)
int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
SetDParam(0, rvi->cargo_type);
- SetDParam(1, (capacity * (CountArticulatedParts(engine_number) + 1)) << multihead);
+ SetDParam(1, (capacity * (CountArticulatedParts(engine_number, true) + 1)) << multihead);
SetDParam(2, refitable ? STR_9842_REFITTABLE : STR_EMPTY);
}
DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 9f7b31630..a7416f525 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -179,11 +179,11 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
if (HASBIT(GetRoadTypes(tile), ROADTYPE_TRAM) != HASBIT(EngInfo(p1)->misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_DEPOT_WRONG_DEPOT_TYPE);
- uint num_vehicles = 1 + CountArticulatedParts(p1);
+ uint num_vehicles = 1 + CountArticulatedParts(p1, false);
- /* Allow for the front and the articulated parts. */
- Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
- memset(vl, 0, sizeof(*vl) * num_vehicles);
+ /* Allow for the front and the articulated parts, plus one to "terminate" the list. */
+ Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
+ memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
if (!Vehicle::AllocateList(vl, num_vehicles)) {
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 188695148..f142389f7 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -514,12 +514,12 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 fla
const RailVehicleInfo *rvi = RailVehInfo(engine);
CommandCost value((GetEngineProperty(engine, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
- uint num_vehicles = 1 + CountArticulatedParts(engine);
+ uint num_vehicles = 1 + CountArticulatedParts(engine, false);
if (!(flags & DC_QUERY_COST)) {
- /* Allow for the wagon and the articulated parts. */
- Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
- memset(vl, 0, sizeof(*vl) * num_vehicles);
+ /* Allow for the wagon and the articulated parts, plus one to "terminate" the list. */
+ Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
+ memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
if (!Vehicle::AllocateList(vl, num_vehicles))
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
@@ -682,12 +682,12 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32
uint num_vehicles =
(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
- CountArticulatedParts(p1);
+ CountArticulatedParts(p1, false);
if (!(flags & DC_QUERY_COST)) {
- /* Allow for the dual-heads and the articulated parts. */
- Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
- memset(vl, 0, sizeof(*vl) * num_vehicles);
+ /* Allow for the dual-heads and the articulated parts, plus one to "terminate" the list. */
+ Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
+ memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
if (!Vehicle::AllocateList(vl, num_vehicles))
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);