newgrf_canal.cpp

Go to the documentation of this file.
00001 /* $Id: newgrf_canal.cpp 26085 2013-11-24 14:41:19Z frosch $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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 <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #include "stdafx.h"
00013 #include "debug.h"
00014 #include "newgrf_spritegroup.h"
00015 #include "newgrf_canal.h"
00016 #include "water.h"
00017 #include "water_map.h"
00018 
00020 WaterFeature _water_feature[CF_END];
00021 
00023 struct CanalScopeResolver : public ScopeResolver {
00024   TileIndex tile; 
00025 
00026   CanalScopeResolver(ResolverObject &ro, TileIndex tile);
00027 
00028   /* virtual */ uint32 GetRandomBits() const;
00029   /* virtual */ uint32 GetVariable(byte variable, uint32 parameter, bool *available) const;
00030 };
00031 
00033 struct CanalResolverObject : public ResolverObject {
00034   CanalScopeResolver canal_scope;
00035 
00036   CanalResolverObject(const GRFFile *grffile, TileIndex tile,
00037       CallbackID callback = CBID_NO_CALLBACK, uint32 callback_param1 = 0, uint32 callback_param2 = 0);
00038 
00039   /* virtual */ ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, byte relative = 0)
00040   {
00041     switch (scope) {
00042       case VSG_SCOPE_SELF: return &this->canal_scope;
00043       default: return ResolverObject::GetScope(scope, relative);
00044     }
00045   }
00046 
00047   /* virtual */ const SpriteGroup *ResolveReal(const RealSpriteGroup *group) const;
00048 };
00049 
00050 /* virtual */ uint32 CanalScopeResolver::GetRandomBits() const
00051 {
00052   /* Return random bits only for water tiles, not station tiles */
00053   return IsTileType(this->tile, MP_WATER) ? GetWaterTileRandomBits(this->tile) : 0;
00054 }
00055 
00056 /* virtual */ uint32 CanalScopeResolver::GetVariable(byte variable, uint32 parameter, bool *available) const
00057 {
00058   switch (variable) {
00059     /* Height of tile */
00060     case 0x80: {
00061       int z = GetTileZ(this->tile);
00062       /* Return consistent height within locks */
00063       if (IsTileType(this->tile, MP_WATER) && IsLock(this->tile) && GetLockPart(this->tile) == LOCK_PART_UPPER) z--;
00064       return z;
00065     }
00066 
00067     /* Terrain type */
00068     case 0x81: return GetTerrainType(this->tile);
00069 
00070     /* Dike map: Connectivity info for river and canal tiles
00071      *
00072      * Assignment of bits to directions defined in agreement with
00073      * http://projects.tt-forums.net/projects/ttdpatch/repository/revisions/2367/entry/trunk/patches/water.asm#L879
00074      *         7
00075      *      3     0
00076      *   6     *     4
00077      *      2     1
00078      *         5
00079      */
00080     case 0x82: {
00081       uint32 connectivity =
00082           (!IsWateredTile(TILE_ADDXY(tile, -1,  0), DIR_SW) << 0)  // NE
00083         + (!IsWateredTile(TILE_ADDXY(tile,  0,  1), DIR_NW) << 1)  // SE
00084         + (!IsWateredTile(TILE_ADDXY(tile,  1,  0), DIR_NE) << 2)  // SW
00085         + (!IsWateredTile(TILE_ADDXY(tile,  0, -1), DIR_SE) << 3)  // NW
00086         + (!IsWateredTile(TILE_ADDXY(tile, -1,  1), DIR_W)  << 4)  // E
00087         + (!IsWateredTile(TILE_ADDXY(tile,  1,  1), DIR_N)  << 5)  // S
00088         + (!IsWateredTile(TILE_ADDXY(tile,  1, -1), DIR_E)  << 6)  // W
00089         + (!IsWateredTile(TILE_ADDXY(tile, -1, -1), DIR_S)  << 7); // N
00090       return connectivity;
00091     }
00092 
00093     /* Random data for river or canal tiles, otherwise zero */
00094     case 0x83: return IsTileType(this->tile, MP_WATER) ? GetWaterTileRandomBits(this->tile) : 0;
00095   }
00096 
00097   DEBUG(grf, 1, "Unhandled canal variable 0x%02X", variable);
00098 
00099   *available = false;
00100   return UINT_MAX;
00101 }
00102 
00103 
00104 /* virtual */ const SpriteGroup *CanalResolverObject::ResolveReal(const RealSpriteGroup *group) const
00105 {
00106   if (group->num_loaded == 0) return NULL;
00107 
00108   return group->loaded[0];
00109 }
00110 
00111 CanalScopeResolver::CanalScopeResolver(ResolverObject &ro, TileIndex tile) : ScopeResolver(ro)
00112 {
00113   this->tile = tile;
00114 }
00115 
00124 CanalResolverObject::CanalResolverObject(const GRFFile *grffile, TileIndex tile,
00125     CallbackID callback, uint32 callback_param1, uint32 callback_param2)
00126     : ResolverObject(grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile)
00127 {
00128 }
00129 
00136 SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
00137 {
00138   CanalResolverObject object(_water_feature[feature].grffile, tile);
00139   const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
00140   if (group == NULL) return 0;
00141 
00142   return group->GetResult();
00143 }
00144 
00154 static uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile)
00155 {
00156   CanalResolverObject object(_water_feature[feature].grffile, tile, callback, param1, param2);
00157   const SpriteGroup *group = SpriteGroup::Resolve(_water_feature[feature].group, object);
00158   if (group == NULL) return CALLBACK_FAILED;
00159 
00160   return group->GetCallbackResult();
00161 }
00162 
00170 uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
00171 {
00172   if (HasBit(_water_feature[feature].callback_mask, CBM_CANAL_SPRITE_OFFSET)) {
00173     uint16 cb = GetCanalCallback(CBID_CANALS_SPRITE_OFFSET, cur_offset, 0, feature, tile);
00174     if (cb != CALLBACK_FAILED) return cur_offset + cb;
00175   }
00176   return cur_offset;
00177 }