/* $Id$ */ /* * This file is part of OpenTTD. * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . */ /** @file newgrf_railtype.cpp NewGRF handling of rail types. */ #include "stdafx.h" #include "debug.h" #include "newgrf_spritegroup.h" #include "date_func.h" #include "depot_base.h" #include "town.h" static uint32 RailTypeGetRandomBits(const ResolverObject *object) { TileIndex tile = object->u.routes.tile; uint tmp = CountBits(tile + (TileX(tile) + TileY(tile)) * TILE_SIZE); return GB(tmp, 0, 2); } static uint32 RailTypeGetTriggers(const ResolverObject *object) { return 0; } static void RailTypeSetTriggers(const ResolverObject *object, int triggers) { } static uint32 RailTypeGetVariable(const ResolverObject *object, byte variable, uint32 parameter, bool *available) { TileIndex tile = object->u.routes.tile; if (tile == INVALID_TILE) { switch (variable) { case 0x40: return 0; case 0x41: return 0; case 0x42: return 0; case 0x43: return _date; case 0x44: return HZB_TOWN_EDGE; } } switch (variable) { case 0x40: return GetTerrainType(tile, object->u.routes.context); case 0x41: return 0; case 0x42: return IsLevelCrossingTile(tile) && IsCrossingBarred(tile); case 0x43: if (IsRailDepotTile(tile)) return Depot::GetByTile(tile)->build_date; return _date; case 0x44: { const Town *t = NULL; if (IsRailDepotTile(tile)) { t = Depot::GetByTile(tile)->town; } else if (IsLevelCrossingTile(tile)) { t = ClosestTownFromTile(tile, UINT_MAX); } return t != NULL ? GetTownRadiusGroup(t, tile) : HZB_TOWN_EDGE; } } DEBUG(grf, 1, "Unhandled rail type tile variable 0x%X", variable); *available = false; return UINT_MAX; } static const SpriteGroup *RailTypeResolveReal(const ResolverObject *object, const RealSpriteGroup *group) { if (group->num_loading > 0) return group->loading[0]; if (group->num_loaded > 0) return group->loaded[0]; return NULL; } static inline void NewRailTypeResolver(ResolverObject *res, TileIndex tile, TileContext context, const GRFFile *grffile, uint32 param1 = 0, uint32 param2 = 0) { res->GetRandomBits = &RailTypeGetRandomBits; res->GetTriggers = &RailTypeGetTriggers; res->SetTriggers = &RailTypeSetTriggers; res->GetVariable = &RailTypeGetVariable; res->ResolveRealMethod = &RailTypeResolveReal; res->u.routes.tile = tile; res->u.routes.context = context; res->callback = CBID_NO_CALLBACK; res->callback_param1 = param1; res->callback_param2 = param2; res->ResetState(); res->grffile = grffile; } /** * Get the sprite to draw for the given tile. * @param rti The rail type data (spec). * @param tile The tile to get the sprite for. * @param rtsg The type of sprite to draw. * @param content Where are we drawing the tile? * @return The sprite to draw. */ SpriteID GetCustomRailSprite(const RailtypeInfo *rti, TileIndex tile, RailTypeSpriteGroup rtsg, TileContext context) { assert(rtsg < RTSG_END); if (rti->group[rtsg] == NULL) return 0; const SpriteGroup *group; ResolverObject object; NewRailTypeResolver(&object, tile, context, rti->grffile[rtsg]); group = SpriteGroup::Resolve(rti->group[rtsg], &object); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult(); } /** * Get the sprite to draw for a given signal. * @param rti The rail type data (spec). * @param tile The tile to get the sprite for. * @param type Signal type. * @param var Signal variant. * @param state Signal state. * @param gui Is the sprite being used on the map or in the GUI? * @return The sprite to draw. */ SpriteID GetCustomSignalSprite(const RailtypeInfo *rti, TileIndex tile, SignalType type, SignalVariant var, SignalState state, bool gui) { if (rti->group[RTSG_SIGNALS] == NULL) return 0; ResolverObject object; uint32 param1 = gui ? 0x10 : 0x00; uint32 param2 = (type << 16) | (var << 8) | state; NewRailTypeResolver(&object, tile, TCX_NORMAL, rti->grffile[RTSG_SIGNALS], param1, param2); const SpriteGroup *group = SpriteGroup::Resolve(rti->group[RTSG_SIGNALS], &object); if (group == NULL || group->GetNumResults() == 0) return 0; return group->GetResult(); } /** * Perform a reverse railtype lookup to get the GRF internal ID. * @param railtype The global (OpenTTD) railtype. * @param grffile The GRF to do the lookup for. * @return the GRF internal ID. */ uint8 GetReverseRailTypeTranslation(RailType railtype, const GRFFile *grffile) { /* No rail type table present, return rail type as-is */ if (grffile == NULL || grffile->railtype_list.Length() == 0) return railtype; /* Look for a matching rail type label in the table */ RailTypeLabel label = GetRailTypeInfo(railtype)->label; int index = grffile->railtype_list.FindIndex(label); if (index >= 0) return index; /* If not found, return as invalid */ return 0xFF; } /** * Resolve a railtypes's spec and such so we can get a variable. * @param ro The resolver object to fill. * @param index The rail tile to get the data from. */ void GetRailTypeResolver(ResolverObject *ro, uint index) { /* There is no unique GRFFile for the tile. Multiple GRFs can define different parts of the railtype. * However, currently the NewGRF Debug GUI does not display variables depending on the GRF (like 0x7F) anyway. */ NewRailTypeResolver(ro, index, TCX_NORMAL, NULL); }