From 7fff0a71f2e29ae8a0004f7b077089e30115fd4c Mon Sep 17 00:00:00 2001 From: rubidium Date: Fri, 22 Jun 2007 20:12:09 +0000 Subject: [PATCH] (svn r10280) [0.5] -Backport from trunk (r10109, r10219, r10222, r10230, r10246, r10258): - Fix: Do not look in every direction for tunnels when building one, one direction is enough (r10258) - Fix: Take the age of the front vehicle for station rating (r10246) - Fix: Terraforming wipes out canals. Now you always have to remove the canal before terraforming, instead of "just" removing the canal [FS#594] (r10240) - Fix: Only 2 trains could crash at one time as collision checking stopped on the first hit. This could technically cause desyncs in network games as the collision hash order is not guaranteed [FS#892] (r10222) - Fix: Land under foundations was terraform when it shouldn't be terraformed [FS#882, FS#890] (r10219) - Fix: Some NewGRFs use the same (unused in the "current" climate) sprite IDs. Normally this gives some artefacts, but when one NewGRF expects it to be a sprite and another NewGRF overwrites it with a non-sprite nasty things happen (drawing a non-sprite crashes OTTD) [FS#838] (r10109) --- clear_cmd.c | 10 ++++- economy.c | 2 +- lang/english.txt | 1 + spritecache.c | 24 ++++++++++-- spritecache.h | 6 +-- train_cmd.c | 91 ++++++++++++++++++++++++---------------------- tunnel_map.c | 2 +- tunnel_map.h | 1 + tunnelbridge_cmd.c | 9 ++++- water_map.h | 5 +++ 10 files changed, 96 insertions(+), 55 deletions(-) diff --git a/clear_cmd.c b/clear_cmd.c index 9ebd9e8bd3..c8ba25bbb4 100644 --- a/clear_cmd.c +++ b/clear_cmd.c @@ -17,6 +17,7 @@ #include "unmovable_map.h" #include "genworld.h" #include "industry.h" +#include "water_map.h" typedef struct TerraformerHeightMod { TileIndex tile; @@ -111,7 +112,7 @@ static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode) // basement and then you raise/lower the other corner. tileh = GetTileSlope(tile, &z); if (tileh == unsafe_slope[mode] || - tileh == ComplementSlope(unsafe_slope[mode])) { + tileh == (SLOPE_STEEP | ComplementSlope(unsafe_slope[mode]))) { _terraform_err_tile = tile; _error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK; return -1; @@ -136,6 +137,13 @@ static int TerraformProc(TerraformerState *ts, TileIndex tile, int mode) } } + /* Canals can't be terraformed */ + if (IsClearWaterTile(tile) && IsCanal(tile)) { + _terraform_err_tile = tile; + _error_message = STR_MUST_DEMOLISH_CANAL_FIRST; + return -1; + } + ret = DoCommand(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR); if (CmdFailed(ret)) { diff --git a/economy.c b/economy.c index da81cef3c0..7b82bc72f7 100644 --- a/economy.c +++ b/economy.c @@ -1468,7 +1468,7 @@ int LoadUnloadVehicle(Vehicle *v, bool just_arrived) // if last speed is 0, we treat that as if no vehicle has ever visited the station. ge->last_speed = min(t, 255); - ge->last_age = _cur_year - v->build_year; + ge->last_age = _cur_year - u->build_year; // If there's goods waiting at the station, and the vehicle // has capacity for it, load it on the vehicle. diff --git a/lang/english.txt b/lang/english.txt index 9c8594503f..47a94252ea 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -1801,6 +1801,7 @@ STR_3804_WATER :Water STR_3805_COAST_OR_RIVERBANK :Coast or riverbank STR_3806_SHIP_DEPOT :Ship depot STR_3807_CAN_T_BUILD_ON_WATER :{WHITE}...Can't build on water +STR_MUST_DEMOLISH_CANAL_FIRST :{WHITE}Must demolish canal first ##id 0x4000 STR_4000_SAVE_GAME :{WHITE}Save Game diff --git a/spritecache.c b/spritecache.c index 11e3ea2a40..c876dda19b 100644 --- a/spritecache.c +++ b/spritecache.c @@ -84,7 +84,7 @@ bool SpriteExists(SpriteID id) static void* AllocSprite(size_t); -static void* ReadSprite(SpriteID id) +static void* ReadSprite(SpriteID id, bool real_sprite) { uint num; byte type; @@ -104,7 +104,17 @@ static void* ReadSprite(SpriteID id) num = FioReadWord(); type = FioReadByte(); if (type == 0xFF) { - byte* dest = AllocSprite(num); + byte* dest; + + if (real_sprite) { + static byte warning_level = 0; + DEBUG(misc, warning_level) ("Tried to load non sprite #%d as a real sprite. Probable cause: NewGRF interference", id); + warning_level = 6; + if (id == SPR_IMG_QUERY) error("Uhm, would you be so kind not to load a NewGRF that makes the 'query' sprite a non- sprite?"); + return (void*)GetSprite(SPR_IMG_QUERY); + } + + dest = AllocSprite(num); _sprite_ptr[id] = dest; FioReadBlock(dest, num); @@ -116,6 +126,12 @@ static void* ReadSprite(SpriteID id) Sprite* sprite; byte* dest; + if (!real_sprite) { + static byte warning_level = 0; + DEBUG(misc, warning_level) ("Tried to load real sprite #%d as a non sprite. Probable cause: NewGRF interference", id); + warning_level = 6; + } + num = (type & 0x02) ? width * height : num - 8; sprite = AllocSprite(sizeof(*sprite) + num); _sprite_ptr[id] = sprite; @@ -424,7 +440,7 @@ static uint RotateSprite(uint s) } #endif -const void *GetRawSprite(SpriteID sprite) +const void *GetRawSprite(SpriteID sprite, bool real_sprite) { void* p; @@ -444,7 +460,7 @@ const void *GetRawSprite(SpriteID sprite) p = _sprite_ptr[sprite]; // Load the sprite, if it is not loaded, yet - if (p == NULL) p = ReadSprite(sprite); + if (p == NULL) p = ReadSprite(sprite, real_sprite); return p; } diff --git a/spritecache.h b/spritecache.h index 3a5676a636..5fbbc86cb2 100644 --- a/spritecache.h +++ b/spritecache.h @@ -12,17 +12,17 @@ typedef struct Sprite { byte data[VARARRAY_SIZE]; } Sprite; -const void *GetRawSprite(SpriteID sprite); +const void *GetRawSprite(SpriteID sprite, bool real_sprite); bool SpriteExists(SpriteID sprite); static inline const Sprite *GetSprite(SpriteID sprite) { - return GetRawSprite(sprite); + return GetRawSprite(sprite, true); } static inline const byte *GetNonSprite(SpriteID sprite) { - return GetRawSprite(sprite); + return GetRawSprite(sprite, false); } void GfxInitSpriteMem(void); diff --git a/train_cmd.c b/train_cmd.c index 7991c24d17..164cc66fa0 100644 --- a/train_cmd.c +++ b/train_cmd.c @@ -2915,28 +2915,6 @@ static void TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) } -typedef struct TrainCollideChecker { - const Vehicle *v; - const Vehicle *v_skip; -} TrainCollideChecker; - -static void *FindTrainCollideEnum(Vehicle *v, void *data) -{ - const TrainCollideChecker* tcc = data; - - if (v != tcc->v && - v != tcc->v_skip && - v->type == VEH_Train && - v->u.rail.track != 0x80 && - myabs(v->z_pos - tcc->v->z_pos) <= 6 && - myabs(v->x_pos - tcc->v->x_pos) < 6 && - myabs(v->y_pos - tcc->v->y_pos) < 6) { - return v; - } else { - return NULL; - } -} - static void SetVehicleCrashed(Vehicle *v) { Vehicle *u; @@ -2962,6 +2940,47 @@ static uint CountPassengersInTrain(const Vehicle* v) return num; } +typedef struct TrainCollideChecker { + Vehicle *v; + const Vehicle *v_skip; + uint num; +} TrainCollideChecker; + +static void *FindTrainCollideEnum(Vehicle *v, void *data) +{ + TrainCollideChecker* tcc = (TrainCollideChecker*)data; + + if (v != tcc->v && + v != tcc->v_skip && + v->type == VEH_Train && + v->u.rail.track != 0x80 && + myabs(v->z_pos - tcc->v->z_pos) < 6 && + myabs(v->x_pos - tcc->v->x_pos) < 6 && + myabs(v->y_pos - tcc->v->y_pos) < 6 ) { + + Vehicle *coll = GetFirstVehicleInChain(v); + + /* it can't collide with its own wagons */ + if (tcc->v == coll || + (tcc->v->u.rail.track == 0x40 && (tcc->v->direction & 2) != (v->direction & 2))) + return NULL; + + /* two drivers + passengers killed in train tcc->v (if it was not crashed already) */ + if (!(tcc->v->vehstatus & VS_CRASHED)) { + tcc->num += 2 + CountPassengersInTrain(tcc->v); + SetVehicleCrashed(tcc->v); + } + + if (!(coll->vehstatus & VS_CRASHED)) { + /* two drivers + passengers killed in train coll (if it was not crashed already) */ + tcc->num += 2 + CountPassengersInTrain(coll); + SetVehicleCrashed(coll); + } + } + + return NULL; +} + /* * Checks whether the specified train has a collision with another vehicle. If * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front. @@ -2971,9 +2990,6 @@ static uint CountPassengersInTrain(const Vehicle* v) static void CheckTrainCollision(Vehicle *v) { TrainCollideChecker tcc; - Vehicle *coll; - Vehicle *realcoll; - uint num; /* can't collide in depot */ if (v->u.rail.track == 0x80) return; @@ -2982,28 +2998,15 @@ static void CheckTrainCollision(Vehicle *v) tcc.v = v; tcc.v_skip = v->next; + tcc.num = 0; - /* find colliding vehicle */ - realcoll = VehicleFromPos(TileVirtXY(v->x_pos, v->y_pos), &tcc, FindTrainCollideEnum); - if (realcoll == NULL) return; + /* find colliding vehicles */ + VehicleFromPos(v->tile, &tcc, FindTrainCollideEnum); - coll = GetFirstVehicleInChain(realcoll); + /* any dead -> no crash */ + if (tcc.num == 0) return; - /* it can't collide with its own wagons */ - if (v == coll || - (v->u.rail.track & 0x40 && (v->direction & 2) != (realcoll->direction & 2))) - return; - - //two drivers + passangers killed in train v - num = 2 + CountPassengersInTrain(v); - if (!(coll->vehstatus & VS_CRASHED)) - //two drivers + passangers killed in train coll (if it was not crashed already) - num += 2 + CountPassengersInTrain(coll); - - SetVehicleCrashed(v); - if (IsFrontEngine(coll)) SetVehicleCrashed(coll); - - SetDParam(0, num); + SetDParam(0, tcc.num); AddNewsItem(STR_8868_TRAIN_CRASH_DIE_IN_FIREBALL, NEWS_FLAGS(NM_THIN, NF_VIEWPORT | NF_VEHICLE, NT_ACCIDENT, 0), v->index, diff --git a/tunnel_map.c b/tunnel_map.c index a4945591d9..9eda97b2d6 100644 --- a/tunnel_map.c +++ b/tunnel_map.c @@ -24,7 +24,7 @@ TileIndex GetOtherTunnelEnd(TileIndex tile) } -static bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir) +bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir) { TileIndexDiff delta = TileOffsByDiagDir(dir); uint height; diff --git a/tunnel_map.h b/tunnel_map.h index 9ad54d07ed..bda6c3749b 100644 --- a/tunnel_map.h +++ b/tunnel_map.h @@ -38,6 +38,7 @@ static inline TransportType GetTunnelTransportType(TileIndex t) TileIndex GetOtherTunnelEnd(TileIndex); bool IsTunnelInWay(TileIndex, uint z); +bool IsTunnelInWayDir(TileIndex tile, uint z, DiagDirection dir); static inline void MakeRoadTunnel(TileIndex t, Owner o, DiagDirection d) diff --git a/tunnelbridge_cmd.c b/tunnelbridge_cmd.c index d5c13a59ef..37c702a640 100644 --- a/tunnelbridge_cmd.c +++ b/tunnelbridge_cmd.c @@ -452,6 +452,7 @@ int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) uint end_z; int32 cost; int32 ret; + DiagDirection tunnel_in_way_dir; _build_tunnel_endtile = 0; @@ -476,6 +477,12 @@ int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) * position, because of increased-cost-by-length: 'cost += cost >> 3' */ cost = 0; delta = TileOffsByDiagDir(direction); + if (OtherAxis(DiagDirToAxis(direction)) == AXIS_X) { + tunnel_in_way_dir = (TileX(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SW : DIAGDIR_NE; + } else { + tunnel_in_way_dir = (TileY(start_tile) < (MapMaxX() / 2)) ? DIAGDIR_SE : DIAGDIR_NW; + } + end_tile = start_tile; for (;;) { end_tile += delta; @@ -483,7 +490,7 @@ int32 CmdBuildTunnel(TileIndex start_tile, uint32 flags, uint32 p1, uint32 p2) if (start_z == end_z) break; - if (!_cheats.crossing_tunnels.value && IsTunnelInWay(end_tile, start_z)) { + if (!_cheats.crossing_tunnels.value && IsTunnelInWayDir(end_tile, start_z, tunnel_in_way_dir)) { return_cmd_error(STR_5003_ANOTHER_TUNNEL_IN_THE_WAY); } diff --git a/water_map.h b/water_map.h index db3308cbf5..061a61e9d4 100644 --- a/water_map.h +++ b/water_map.h @@ -43,6 +43,11 @@ static inline bool IsCoast(TileIndex t) return GetWaterTileType(t) == WATER_COAST; } +static inline bool IsCanal(TileIndex t) +{ + return GetWaterTileType(t) == WATER_CLEAR && GetTileOwner(t) != OWNER_WATER; +} + static inline bool IsClearWaterTile(TileIndex t) { return IsTileType(t, MP_WATER) && IsWater(t) && GetTileSlope(t, NULL) == SLOPE_FLAT;