mirror of https://github.com/OpenTTD/OpenTTD
(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.
parent
f3491cb062
commit
257fdb38e6
|
@ -15,16 +15,24 @@
|
||||||
#include "newgrf_engine.h"
|
#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;
|
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;
|
uint i;
|
||||||
for (i = 1; i < MAX_UVALUE(EngineID); 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;
|
if (callback == CALLBACK_FAILED || callback == 0xFF) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete v;
|
||||||
|
|
||||||
return i - 1;
|
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
|
/* Attempt to use pre-allocated vehicles until they run out. This can happen
|
||||||
* if the callback returns different values depending on the cargo type. */
|
* if the callback returns different values depending on the cargo type. */
|
||||||
u->SetNext(vl[i]);
|
u->SetNext(vl[i]);
|
||||||
if (u->Next() == NULL) u->SetNext(new InvalidVehicle());
|
|
||||||
if (u->Next() == NULL) return;
|
if (u->Next() == NULL) return;
|
||||||
|
|
||||||
Vehicle *previous = u;
|
Vehicle *previous = u;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#ifndef ARTICULATED_VEHICLES_H
|
#ifndef ARTICULATED_VEHICLES_H
|
||||||
#define 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);
|
void AddArticulatedParts(Vehicle **vl, VehicleType type);
|
||||||
|
|
||||||
#endif /* ARTICULATED_VEHICLES_H */
|
#endif /* ARTICULATED_VEHICLES_H */
|
||||||
|
|
|
@ -621,7 +621,7 @@ int DrawVehiclePurchaseInfo(int x, int y, uint w, EngineID engine_number)
|
||||||
int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
|
int multihead = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 1 : 0);
|
||||||
|
|
||||||
SetDParam(0, rvi->cargo_type);
|
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);
|
SetDParam(2, refitable ? STR_9842_REFITTABLE : STR_EMPTY);
|
||||||
}
|
}
|
||||||
DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
|
DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, 0);
|
||||||
|
|
|
@ -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);
|
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. */
|
/* Allow for the front and the articulated parts, plus one to "terminate" the list. */
|
||||||
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
|
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
|
||||||
memset(vl, 0, sizeof(*vl) * num_vehicles);
|
memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
|
||||||
|
|
||||||
if (!Vehicle::AllocateList(vl, num_vehicles)) {
|
if (!Vehicle::AllocateList(vl, num_vehicles)) {
|
||||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||||
|
|
|
@ -514,12 +514,12 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 fla
|
||||||
const RailVehicleInfo *rvi = RailVehInfo(engine);
|
const RailVehicleInfo *rvi = RailVehInfo(engine);
|
||||||
CommandCost value((GetEngineProperty(engine, 0x17, rvi->base_cost) * _price.build_railwagon) >> 8);
|
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)) {
|
if (!(flags & DC_QUERY_COST)) {
|
||||||
/* Allow for the wagon and the articulated parts. */
|
/* Allow for the wagon and the articulated parts, plus one to "terminate" the list. */
|
||||||
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
|
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
|
||||||
memset(vl, 0, sizeof(*vl) * num_vehicles);
|
memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
|
||||||
|
|
||||||
if (!Vehicle::AllocateList(vl, num_vehicles))
|
if (!Vehicle::AllocateList(vl, num_vehicles))
|
||||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
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 =
|
uint num_vehicles =
|
||||||
(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
|
(rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) +
|
||||||
CountArticulatedParts(p1);
|
CountArticulatedParts(p1, false);
|
||||||
|
|
||||||
if (!(flags & DC_QUERY_COST)) {
|
if (!(flags & DC_QUERY_COST)) {
|
||||||
/* Allow for the dual-heads and the articulated parts. */
|
/* Allow for the dual-heads and the articulated parts, plus one to "terminate" the list. */
|
||||||
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * num_vehicles);
|
Vehicle **vl = (Vehicle**)alloca(sizeof(*vl) * (num_vehicles + 1));
|
||||||
memset(vl, 0, sizeof(*vl) * num_vehicles);
|
memset(vl, 0, sizeof(*vl) * (num_vehicles + 1));
|
||||||
|
|
||||||
if (!Vehicle::AllocateList(vl, num_vehicles))
|
if (!Vehicle::AllocateList(vl, num_vehicles))
|
||||||
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
|
||||||
|
|
Loading…
Reference in New Issue