(svn r13816) -Fix [FS#2150]: check for vehicle length changes outside a depot (callback 0x11) and give a warning about that
This commit is contained in:
@@ -51,6 +51,8 @@
|
||||
#include "order_func.h"
|
||||
#include "newgrf_station.h"
|
||||
#include "effectvehicle_func.h"
|
||||
#include "gamelog.h"
|
||||
#include "network/network.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/train_cmd.h"
|
||||
@@ -181,13 +183,76 @@ static void TrainCargoChanged(Vehicle *v)
|
||||
}
|
||||
|
||||
|
||||
/** Logs a bug in GRF and shows a warning message if this
|
||||
* is for the first time this happened.
|
||||
* @param u first vehicle of chain
|
||||
*/
|
||||
static void RailVehicleLengthChanged(const Vehicle *u)
|
||||
{
|
||||
/* show a warning once for each engine in whole game and once for each GRF after each game load */
|
||||
const Engine *engine = GetEngine(u->engine_type);
|
||||
uint32 grfid = engine->grffile->grfid;
|
||||
GRFConfig *grfconfig = GetGRFConfig(grfid);
|
||||
if (GamelogGRFBugReverse(grfid, engine->internal_id) || !HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
|
||||
SetBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH);
|
||||
SetDParamStr(0, grfconfig->name);
|
||||
SetDParam(1, u->engine_type);
|
||||
ShowErrorMessage(STR_NEWGRF_BROKEN_VEHICLE_LENGTH, STR_NEWGRF_BROKEN, 0, 0);
|
||||
|
||||
/* debug output */
|
||||
char buffer[512];
|
||||
|
||||
SetDParamStr(0, grfconfig->name);
|
||||
GetString(buffer, STR_NEWGRF_BROKEN, lastof(buffer));
|
||||
DEBUG(grf, 0, "%s", buffer + 3);
|
||||
|
||||
SetDParam(1, u->engine_type);
|
||||
GetString(buffer, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, lastof(buffer));
|
||||
DEBUG(grf, 0, "%s", buffer + 3);
|
||||
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (!_networking) _pause_game = -1;
|
||||
#else
|
||||
_pause_game = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks if lengths of all rail vehicles are valid. If not, shows an error message. */
|
||||
void CheckTrainsLengths()
|
||||
{
|
||||
const Vehicle *v;
|
||||
|
||||
FOR_ALL_VEHICLES(v) {
|
||||
if (v->type == VEH_TRAIN && v->First() == v && !(v->vehstatus & VS_CRASHED)) {
|
||||
for (const Vehicle *u = v, *w = v->Next(); w != NULL; u = w, w = w->Next()) {
|
||||
if (u->u.rail.track != TRACK_BIT_DEPOT) {
|
||||
if ((w->u.rail.track != TRACK_BIT_DEPOT &&
|
||||
max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->u.rail.cached_veh_length) ||
|
||||
(w->u.rail.track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
|
||||
SetDParam(0, v->index);
|
||||
SetDParam(1, v->owner);
|
||||
ShowErrorMessage(INVALID_STRING_ID, STR_BROKEN_VEHICLE_LENGTH, 0, 0);
|
||||
#ifdef ENABLE_NETWORK
|
||||
if (!_networking) _pause_game = -1;
|
||||
#else
|
||||
_pause_game = -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the cached stuff of a train. Should be called each time a vehicle is added
|
||||
* to/removed from the chain, and when the game is loaded.
|
||||
* Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
|
||||
* @param v First vehicle of the chain.
|
||||
* @param same_length should length of vehicles stay the same?
|
||||
*/
|
||||
void TrainConsistChanged(Vehicle *v)
|
||||
void TrainConsistChanged(Vehicle *v, bool same_length)
|
||||
{
|
||||
uint16 max_speed = UINT16_MAX;
|
||||
|
||||
@@ -295,8 +360,14 @@ void TrainConsistChanged(Vehicle *v)
|
||||
veh_len = GetVehicleCallback(CBID_VEHICLE_LENGTH, 0, 0, u->engine_type, u);
|
||||
}
|
||||
if (veh_len == CALLBACK_FAILED) veh_len = rvi_u->shorten_factor;
|
||||
veh_len = Clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
|
||||
u->u.rail.cached_veh_length = 8 - veh_len;
|
||||
veh_len = 8 - Clamp(veh_len, 0, u->Next() == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
|
||||
|
||||
/* verify length hasn't changed */
|
||||
if (same_length && veh_len != u->u.rail.cached_veh_length) RailVehicleLengthChanged(u);
|
||||
|
||||
/* update vehicle length? */
|
||||
if (!same_length) u->u.rail.cached_veh_length = veh_len;
|
||||
|
||||
v->u.rail.cached_total_length += u->u.rail.cached_veh_length;
|
||||
}
|
||||
|
||||
@@ -618,7 +689,7 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, uint32 fla
|
||||
_new_vehicle_id = v->index;
|
||||
|
||||
VehiclePositionChanged(v);
|
||||
TrainConsistChanged(v->First());
|
||||
TrainConsistChanged(v->First(), false);
|
||||
UpdateTrainGroupID(v->First());
|
||||
|
||||
InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
|
||||
@@ -794,7 +865,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32
|
||||
AddArticulatedParts(vl, VEH_TRAIN);
|
||||
}
|
||||
|
||||
TrainConsistChanged(v);
|
||||
TrainConsistChanged(v, false);
|
||||
UpdateTrainGroupID(v);
|
||||
|
||||
if (!HasBit(p2, 1) && !(flags & DC_AUTOREPLACE)) { // check if the cars should be added to the new vehicle
|
||||
@@ -1247,7 +1318,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p
|
||||
|
||||
if (src_head != NULL) {
|
||||
NormaliseTrainConsist(src_head);
|
||||
TrainConsistChanged(src_head);
|
||||
TrainConsistChanged(src_head, false);
|
||||
UpdateTrainGroupID(src_head);
|
||||
if (IsFrontEngine(src_head)) {
|
||||
/* Update the refit button and window */
|
||||
@@ -1260,7 +1331,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32 p
|
||||
|
||||
if (dst_head != NULL) {
|
||||
NormaliseTrainConsist(dst_head);
|
||||
TrainConsistChanged(dst_head);
|
||||
TrainConsistChanged(dst_head, false);
|
||||
UpdateTrainGroupID(dst_head);
|
||||
if (IsFrontEngine(dst_head)) {
|
||||
/* Update the refit button and window */
|
||||
@@ -1432,7 +1503,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
/* 5. If the train still exists, update its acceleration, window, etc. */
|
||||
if (first != NULL) {
|
||||
NormaliseTrainConsist(first);
|
||||
TrainConsistChanged(first);
|
||||
TrainConsistChanged(first, false);
|
||||
UpdateTrainGroupID(first);
|
||||
if (IsFrontEngine(first)) InvalidateWindow(WC_VEHICLE_REFIT, first->index);
|
||||
}
|
||||
@@ -1497,7 +1568,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
/* 3. If it is still a valid train after selling, update its acceleration and cached values */
|
||||
if (flags & DC_EXEC && first != NULL) {
|
||||
NormaliseTrainConsist(first);
|
||||
TrainConsistChanged(first);
|
||||
TrainConsistChanged(first, false);
|
||||
UpdateTrainGroupID(first);
|
||||
InvalidateWindow(WC_VEHICLE_REFIT, first->index);
|
||||
}
|
||||
@@ -1832,7 +1903,7 @@ static void ReverseTrainDirection(Vehicle *v)
|
||||
ClrBit(v->u.rail.flags, VRF_REVERSING);
|
||||
|
||||
/* recalculate cached data */
|
||||
TrainConsistChanged(v);
|
||||
TrainConsistChanged(v, true);
|
||||
|
||||
/* update all images */
|
||||
for (Vehicle *u = v; u != NULL; u = u->Next()) u->cur_image = u->GetImage(u->direction);
|
||||
@@ -2009,7 +2080,7 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, uint32 flags, uint32 p1, uint32
|
||||
_returned_refit_capacity = num;
|
||||
|
||||
/* Update the train's cached variables */
|
||||
if (flags & DC_EXEC) TrainConsistChanged(GetVehicle(p1)->First());
|
||||
if (flags & DC_EXEC) TrainConsistChanged(GetVehicle(p1)->First(), false);
|
||||
|
||||
return cost;
|
||||
}
|
||||
@@ -3147,7 +3218,7 @@ static void DeleteLastWagon(Vehicle *v)
|
||||
InvalidateWindow(WC_COMPANY, v->owner);
|
||||
} else {
|
||||
/* Recalculate cached train properties */
|
||||
TrainConsistChanged(first);
|
||||
TrainConsistChanged(first, false);
|
||||
/* Update the depot window if the first vehicle is in depot -
|
||||
* if v == first, then it is updated in PreDestructor() */
|
||||
if (first->u.rail.track == TRACK_BIT_DEPOT) {
|
||||
|
Reference in New Issue
Block a user