# newgrf_canal.cpp

Go to the documentation of this file.

    00001 /* $Id: newgrf_canal.cpp 26388 2014-03-03 20:02:31Z 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(CanalFeature feature, 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(CanalFeature feature, TileIndex tile,
    00125     CallbackID callback, uint32 callback_param1, uint32 callback_param2)
    00126     : ResolverObject(_water_feature[feature].grffile, callback, callback_param1, callback_param2), canal_scope(*this, tile)
    00127 {
    00128   this->root_spritegroup = _water_feature[feature].group;
    00129 }
    00130
    00137 SpriteID GetCanalSprite(CanalFeature feature, TileIndex tile)
    00138 {
    00139   CanalResolverObject object(feature, tile);
    00140   const SpriteGroup *group = object.Resolve();
    00141   if (group == NULL) return 0;
    00142
    00143   return group->GetResult();
    00144 }
    00145
    00155 static uint16 GetCanalCallback(CallbackID callback, uint32 param1, uint32 param2, CanalFeature feature, TileIndex tile)
    00156 {
    00157   CanalResolverObject object(feature, tile, callback, param1, param2);
    00158   return object.ResolveCallback();
    00159 }
    00160
    00168 uint GetCanalSpriteOffset(CanalFeature feature, TileIndex tile, uint cur_offset)
    00169 {
    00170   if (HasBit(_water_feature[feature].callback_mask, CBM_CANAL_SPRITE_OFFSET)) {
    00171     uint16 cb = GetCanalCallback(CBID_CANALS_SPRITE_OFFSET, cur_offset, 0, feature, tile);
    00172     if (cb != CALLBACK_FAILED) return cur_offset + cb;
    00173   }
    00174   return cur_offset;
    00175 }