diff --git a/src/newgrf_house.cpp b/src/newgrf_house.cpp --- a/src/newgrf_house.cpp +++ b/src/newgrf_house.cpp @@ -99,20 +99,25 @@ void DecreaseBuildingCount(Town *t, Hous static uint32 HouseGetRandomBits(const ResolverObject *object) { - const TileIndex tile = object->u.house.tile; - return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseRandomBits(tile); + /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */ + TileIndex tile = object->u.house.tile; + assert(IsValidTile(tile) && (object->u.house.not_yet_constructed || IsTileType(tile, MP_HOUSE))); + return object->u.house.not_yet_constructed ? 0 : GetHouseRandomBits(tile); } static uint32 HouseGetTriggers(const ResolverObject *object) { - const TileIndex tile = object->u.house.tile; - return (tile == INVALID_TILE || !IsTileType(tile, MP_HOUSE)) ? 0 : GetHouseTriggers(tile); + /* Note: Towns build houses over houses. So during construction checks 'tile' may be a valid but unrelated house. */ + TileIndex tile = object->u.house.tile; + assert(IsValidTile(tile) && (object->u.house.not_yet_constructed || IsTileType(tile, MP_HOUSE))); + return object->u.house.not_yet_constructed ? 0 : GetHouseTriggers(tile); } static void HouseSetTriggers(const ResolverObject *object, int triggers) { - const TileIndex tile = object->u.house.tile; - if (IsTileType(tile, MP_HOUSE)) SetHouseTriggers(tile, triggers); + TileIndex tile = object->u.house.tile; + assert(!object->u.house.not_yet_constructed && IsValidTile(tile) && IsTileType(tile, MP_HOUSE)); + SetHouseTriggers(tile, triggers); } static uint32 GetNumHouses(HouseID house_id, const Town *town) @@ -370,6 +375,7 @@ static void NewHouseResolver(ResolverObj res->u.house.tile = tile; res->u.house.town = town; res->u.house.house_id = house_id; + res->u.house.not_yet_constructed = false; res->callback = CBID_NO_CALLBACK; res->callback_param1 = 0; @@ -383,15 +389,18 @@ static void NewHouseResolver(ResolverObj res->grffile = (hs != NULL ? hs->grffile : NULL); } -uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile) +uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed) { ResolverObject object; const SpriteGroup *group; + assert(IsValidTile(tile) && (not_yet_constructed || IsTileType(tile, MP_HOUSE))); + NewHouseResolver(&object, house_id, tile, town); object.callback = callback; object.callback_param1 = param1; object.callback_param2 = param2; + object.u.house.not_yet_constructed = not_yet_constructed; group = SpriteGroup::Resolve(HouseSpec::Get(house_id)->spritegroup, &object); if (group == NULL) return CALLBACK_FAILED; diff --git a/src/newgrf_house.h b/src/newgrf_house.h --- a/src/newgrf_house.h +++ b/src/newgrf_house.h @@ -44,7 +44,7 @@ void DrawNewHouseTile(TileInfo *ti, Hous void AnimateNewHouseTile(TileIndex tile); void ChangeHouseAnimationFrame(const struct GRFFile *file, TileIndex tile, uint16 callback_result); -uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile); +uint16 GetHouseCallback(CallbackID callback, uint32 param1, uint32 param2, HouseID house_id, Town *town, TileIndex tile, bool not_yet_constructed = false); bool CanDeleteHouse(TileIndex tile); diff --git a/src/newgrf_industries.cpp b/src/newgrf_industries.cpp --- a/src/newgrf_industries.cpp +++ b/src/newgrf_industries.cpp @@ -345,18 +345,23 @@ static const SpriteGroup *IndustryResolv static uint32 IndustryGetRandomBits(const ResolverObject *object) { - return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random; + const Industry *ind = object->u.industry.ind; + assert(ind != NULL); + return ind->random; } static uint32 IndustryGetTriggers(const ResolverObject *object) { - return object->u.industry.ind == NULL ? 0 : object->u.industry.ind->random_triggers; + const Industry *ind = object->u.industry.ind; + assert(ind != NULL); + return ind->random_triggers; } static void IndustrySetTriggers(const ResolverObject *object, int triggers) { - if (object->u.industry.ind == NULL) return; - object->u.industry.ind->random_triggers = triggers; + Industry *ind = object->u.industry.ind; + assert(ind != NULL && ind->index != INVALID_INDUSTRY); + ind->random_triggers = triggers; } static void NewIndustryResolver(ResolverObject *res, TileIndex tile, Industry *indus, IndustryType type) diff --git a/src/newgrf_industrytiles.cpp b/src/newgrf_industrytiles.cpp --- a/src/newgrf_industrytiles.cpp +++ b/src/newgrf_industrytiles.cpp @@ -118,26 +118,35 @@ static const SpriteGroup *IndustryTileRe static uint32 IndustryTileGetRandomBits(const ResolverObject *object) { const TileIndex tile = object->u.industry.tile; - if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; - return (object->scope == VSG_SCOPE_SELF) ? GetIndustryRandomBits(tile) : Industry::GetByTile(tile)->random; + const Industry *ind = object->u.industry.ind; + assert(ind != NULL && IsValidTile(tile)); + assert(ind->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY)); + + return (object->scope == VSG_SCOPE_SELF) ? + (ind->index != INVALID_INDUSTRY ? GetIndustryRandomBits(tile) : 0) : + ind->random; } static uint32 IndustryTileGetTriggers(const ResolverObject *object) { const TileIndex tile = object->u.industry.tile; - if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return 0; - return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : Industry::GetByTile(tile)->random_triggers; + const Industry *ind = object->u.industry.ind; + assert(ind != NULL && IsValidTile(tile)); + assert(ind->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY)); + if (ind->index == INVALID_INDUSTRY) return 0; + return (object->scope == VSG_SCOPE_SELF) ? GetIndustryTriggers(tile) : ind->random_triggers; } static void IndustryTileSetTriggers(const ResolverObject *object, int triggers) { const TileIndex tile = object->u.industry.tile; - if (tile == INVALID_TILE || !IsTileType(tile, MP_INDUSTRY)) return; + Industry *ind = object->u.industry.ind; + assert(ind != NULL && ind->index != INVALID_INDUSTRY && IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY)); if (object->scope == VSG_SCOPE_SELF) { SetIndustryTriggers(tile, triggers); } else { - Industry::GetByTile(tile)->random_triggers = triggers; + ind->random_triggers = triggers; } } @@ -194,6 +203,9 @@ uint16 GetIndustryTileCallback(CallbackI ResolverObject object; const SpriteGroup *group; + assert(industry != NULL && IsValidTile(tile)); + assert(industry->index == INVALID_INDUSTRY || IsTileType(tile, MP_INDUSTRY)); + NewIndustryTileResolver(&object, gfx_id, tile, industry); object.callback = callback; object.callback_param1 = param1; @@ -396,6 +408,8 @@ static void DoTriggerIndustryTile(TileIn { ResolverObject object; + assert(IsValidTile(tile) && IsTileType(tile, MP_INDUSTRY)); + IndustryGfx gfx = GetIndustryGfx(tile); const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); diff --git a/src/newgrf_spritegroup.h b/src/newgrf_spritegroup.h --- a/src/newgrf_spritegroup.h +++ b/src/newgrf_spritegroup.h @@ -319,6 +319,7 @@ struct ResolverObject { TileIndex tile; Town *town; HouseID house_id; + bool not_yet_constructed; ///< True for construction check } house; struct { TileIndex tile; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -2165,7 +2165,7 @@ static bool BuildTownHouse(Town *t, Tile } if (HasBit(hs->callback_mask, CBM_HOUSE_ALLOW_CONSTRUCTION)) { - uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile); + uint16 callback_res = GetHouseCallback(CBID_HOUSE_ALLOW_CONSTRUCTION, 0, 0, house, t, tile, true); if (callback_res != CALLBACK_FAILED && GB(callback_res, 0, 8) == 0) continue; }