newgrf_commons.cpp

Go to the documentation of this file.
00001 /* $Id: newgrf_commons.cpp 15583 2009-02-25 21:29:50Z frosch $ */
00002 
00007 #include "stdafx.h"
00008 #include "landscape.h"
00009 #include "town.h"
00010 #include "industry.h"
00011 #include "newgrf.h"
00012 #include "newgrf_commons.h"
00013 #include "station_map.h"
00014 #include "tree_map.h"
00015 
00021 OverrideManagerBase::OverrideManagerBase(uint16 offset, uint16 maximum, uint16 invalid)
00022 {
00023   max_offset = offset;
00024   max_new_entities = maximum;
00025   invalid_ID = invalid;
00026 
00027   mapping_ID = CallocT<EntityIDMapping>(max_new_entities);
00028   entity_overrides = MallocT<uint16>(max_offset);
00029   for (size_t i = 0; i < max_offset; i++) entity_overrides[i] = invalid;
00030   grfid_overrides = CallocT<uint32>(max_offset);
00031 }
00032 
00036 OverrideManagerBase::~OverrideManagerBase()
00037 {
00038   free(mapping_ID);
00039   free(entity_overrides);
00040   free(grfid_overrides);
00041 }
00042 
00050 void OverrideManagerBase::Add(uint8 local_id, uint32 grfid, uint entity_type)
00051 {
00052   assert(entity_type < max_offset);
00053   /* An override can be set only once */
00054   if (entity_overrides[entity_type] != invalid_ID) return;
00055   entity_overrides[entity_type] = local_id;
00056   grfid_overrides[entity_type] = grfid;
00057 }
00058 
00060 void OverrideManagerBase::ResetMapping()
00061 {
00062   memset(mapping_ID, 0, (max_new_entities - 1) * sizeof(EntityIDMapping));
00063 }
00064 
00066 void OverrideManagerBase::ResetOverride()
00067 {
00068   for (uint16 i = 0; i < max_offset; i++) {
00069     entity_overrides[i] = invalid_ID;
00070     grfid_overrides[i] = 0;
00071   }
00072 }
00073 
00079 uint16 OverrideManagerBase::GetID(uint8 grf_local_id, uint32 grfid)
00080 {
00081   const EntityIDMapping *map;
00082 
00083   for (uint16 id = 0; id < max_new_entities; id++) {
00084     map = &mapping_ID[id];
00085     if (map->entity_id == grf_local_id && map->grfid == grfid) {
00086       return id;
00087     }
00088   }
00089 
00090   return invalid_ID;
00091 }
00092 
00099 uint16 OverrideManagerBase::AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id)
00100 {
00101   uint16 id = this->GetID(grf_local_id, grfid);
00102   EntityIDMapping *map;
00103 
00104   /* Look to see if this entity has already been added. This is done
00105    * separately from the loop below in case a GRF has been deleted, and there
00106    * are any gaps in the array.
00107    */
00108   if (id != invalid_ID) {
00109     return id;
00110   }
00111 
00112   /* This entity hasn't been defined before, so give it an ID now. */
00113   for (id = max_offset; id < max_new_entities; id++) {
00114     map = &mapping_ID[id];
00115 
00116     if (CheckValidNewID(id) && map->entity_id == 0 && map->grfid == 0) {
00117       map->entity_id     = grf_local_id;
00118       map->grfid         = grfid;
00119       map->substitute_id = substitute_id;
00120       return id;
00121     }
00122   }
00123 
00124   return invalid_ID;
00125 }
00126 
00131 uint16 OverrideManagerBase::GetSubstituteID(byte entity_id)
00132 {
00133   return mapping_ID[entity_id].substitute_id;
00134 }
00135 
00140 void HouseOverrideManager::SetEntitySpec(const HouseSpec *hs)
00141 {
00142   HouseID house_id = this->AddEntityID(hs->local_id, hs->grffile->grfid, hs->substitute_id);
00143 
00144   if (house_id == invalid_ID) {
00145     grfmsg(1, "House.SetEntitySpec: Too many houses allocated. Ignoring.");
00146     return;
00147   }
00148 
00149   memcpy(&_house_specs[house_id], hs, sizeof(*hs));
00150 
00151   /* Now add the overrides. */
00152   for (int i = 0; i != max_offset; i++) {
00153     HouseSpec *overridden_hs = GetHouseSpecs(i);
00154 
00155     if (entity_overrides[i] != hs->local_id || grfid_overrides[i] != hs->grffile->grfid) continue;
00156 
00157     overridden_hs->override = house_id;
00158     entity_overrides[i] = invalid_ID;
00159     grfid_overrides[i] = 0;
00160   }
00161 }
00162 
00168 uint16 IndustryOverrideManager::GetID(uint8 grf_local_id, uint32 grfid)
00169 {
00170   uint16 id = OverrideManagerBase::GetID(grf_local_id, grfid);
00171   if (id != invalid_ID) return id;
00172 
00173   /* No mapping found, try the overrides */
00174   for (id = 0; id < max_offset; id++) {
00175     if (entity_overrides[id] == grf_local_id && grfid_overrides[id] == grfid) return id;
00176   }
00177 
00178   return invalid_ID;
00179 }
00180 
00187 uint16 IndustryOverrideManager::AddEntityID(byte grf_local_id, uint32 grfid, byte substitute_id)
00188 {
00189   /* This entity hasn't been defined before, so give it an ID now. */
00190   for (uint16 id = 0; id < max_new_entities; id++) {
00191     /* Skip overriden industries */
00192     if (id < max_offset && entity_overrides[id] != invalid_ID) continue;
00193 
00194     /* Get the real live industry */
00195     const IndustrySpec *inds = GetIndustrySpec(id);
00196 
00197     /* This industry must be one that is not available(enabled), mostly because of climate.
00198      * And it must not already be used by a grf (grffile == NULL).
00199      * So reseve this slot here, as it is the chosen one */
00200     if (!inds->enabled && inds->grf_prop.grffile == NULL) {
00201       EntityIDMapping *map = &mapping_ID[id];
00202 
00203       if (map->entity_id == 0 && map->grfid == 0) {
00204         /* winning slot, mark it as been used */
00205         map->entity_id     = grf_local_id;
00206         map->grfid         = grfid;
00207         map->substitute_id = substitute_id;
00208         return id;
00209       }
00210     }
00211   }
00212 
00213   return invalid_ID;
00214 }
00215 
00221 void IndustryOverrideManager::SetEntitySpec(IndustrySpec *inds)
00222 {
00223   /* First step : We need to find if this industry is already specified in the savegame data */
00224   IndustryType ind_id = this->GetID(inds->grf_prop.local_id, inds->grf_prop.grffile->grfid);
00225 
00226   if (ind_id == invalid_ID) {
00227     /* Not found.
00228      * Or it has already been overriden, so you've lost your place old boy.
00229      * Or it is a simple substitute.
00230      * We need to find a free available slot */
00231     ind_id = this->AddEntityID(inds->grf_prop.local_id, inds->grf_prop.grffile->grfid, inds->grf_prop.subst_id);
00232     inds->grf_prop.override = invalid_ID;  // make sure it will not be detected as overriden
00233   }
00234 
00235   if (ind_id == invalid_ID) {
00236     grfmsg(1, "Industry.SetEntitySpec: Too many industries allocated. Ignoring.");
00237     return;
00238   }
00239 
00240   /* Now that we know we can use the given id, copy the spech to its final destination*/
00241   memcpy(&_industry_specs[ind_id], inds, sizeof(*inds));
00242   /* and mark it as usable*/
00243   _industry_specs[ind_id].enabled = true;
00244 }
00245 
00246 void IndustryTileOverrideManager::SetEntitySpec(const IndustryTileSpec *its)
00247 {
00248   IndustryGfx indt_id = this->AddEntityID(its->grf_prop.local_id, its->grf_prop.grffile->grfid, its->grf_prop.subst_id);
00249 
00250   if (indt_id == invalid_ID) {
00251     grfmsg(1, "IndustryTile.SetEntitySpec: Too many industry tiles allocated. Ignoring.");
00252     return;
00253   }
00254 
00255   memcpy(&_industry_tile_specs[indt_id], its, sizeof(*its));
00256 
00257   /* Now add the overrides. */
00258   for (int i = 0; i < max_offset; i++) {
00259     IndustryTileSpec *overridden_its = &_industry_tile_specs[i];
00260 
00261     if (entity_overrides[i] != its->grf_prop.local_id || grfid_overrides[i] != its->grf_prop.grffile->grfid) continue;
00262 
00263     overridden_its->grf_prop.override = indt_id;
00264     overridden_its->enabled = false;
00265     entity_overrides[i] = invalid_ID;
00266     grfid_overrides[i] = 0;
00267   }
00268 }
00269 
00275 uint32 GetTerrainType(TileIndex tile)
00276 {
00277   switch (_settings_game.game_creation.landscape) {
00278     case LT_TROPIC: return GetTropicZone(tile);
00279     case LT_ARCTIC: return GetTileZ(tile) > GetSnowLine() ? 4 : 0;
00280     default:        return 0;
00281   }
00282 }
00283 
00284 TileIndex GetNearbyTile(byte parameter, TileIndex tile)
00285 {
00286   int8 x = GB(parameter, 0, 4);
00287   int8 y = GB(parameter, 4, 4);
00288 
00289   if (x >= 8) x -= 16;
00290   if (y >= 8) y -= 16;
00291 
00292   /* Swap width and height depending on axis for railway stations */
00293   if (IsRailwayStationTile(tile) && GetRailStationAxis(tile) == AXIS_Y) Swap(x, y);
00294 
00295   /* Make sure we never roam outside of the map, better wrap in that case */
00296   return TILE_MASK(tile + TileDiffXY(x, y));
00297 }
00298 
00305 uint32 GetNearbyTileInformation(TileIndex tile)
00306 {
00307   TileType tile_type = GetTileType(tile);
00308 
00309   /* Fake tile type for trees on shore */
00310   if (IsTileType(tile, MP_TREES) && GetTreeGround(tile) == TREE_GROUND_SHORE) tile_type = MP_WATER;
00311 
00312   uint z;
00313   Slope tileh = GetTileSlope(tile, &z);
00314   byte terrain_type = GetTerrainType(tile) << 2 | (tile_type == MP_WATER ? 1 : 0) << 1;
00315   return tile_type << 24 | z << 16 | terrain_type << 8 | tileh;
00316 }

Generated on Wed Jun 3 19:05:12 2009 for OpenTTD by  doxygen 1.5.6