(svn r13838) -Codechange: Make industry tiles aware of WaterClasses.

This commit is contained in:
frosch 2008-07-26 16:14:10 +00:00
parent ea7ed286a6
commit 16c80d031c
12 changed files with 110 additions and 36 deletions

View File

@ -1035,6 +1035,7 @@
<ul>
<li>m1 bit 7: clear = under construction
<ul>
<li>m1 bits 6..5 : Water class (sea, canal, river or land)
<li>m1 bits 3..2: construction counter, for buildings under construction incremented on every periodic tile processing</li>
<li>m1 bits 1..0: stage of construction (<tt>3</tt> = completed), incremented when the construction counter wraps around<br>
the meaning is different for some animated tiles which are never under construction (types <tt>01</tt>, <tt>1E</tt>..<tt>20</tt>, <tt>30</tt>, <tt>58</tt>; see above)</li>

View File

@ -293,7 +293,7 @@ the array so you can quickly see what is used and what is not.
<td>8</td>
<td class="caption">industry</td>
<td class="bits">XXXX XXXX</td>
<td class="bits">X<span class="free">OOO</span> <span class="abuse">
<td class="bits">XXX<span class="free">O</span> <span class="abuse">
XXXX</span></td>
<td class="bits">XXXX XXXX XXXX XXXX</td>
<td class="bits">XXXX XXXX</td>

View File

@ -147,7 +147,8 @@ Industry::~Industry()
BEGIN_TILE_LOOP(tile_cur, this->width, this->height, this->xy);
if (IsTileType(tile_cur, MP_INDUSTRY)) {
if (GetIndustryIndex(tile_cur) == this->index) {
DoClearSquare(tile_cur);
/* MakeWaterKeepingClass() can also handle 'land' */
MakeWaterKeepingClass(tile_cur, OWNER_NONE);
}
} else if (IsTileType(tile_cur, MP_STATION) && IsOilRig(tile_cur)) {
DeleteOilRig(tile_cur);
@ -300,7 +301,13 @@ static void DrawTile_Industry(TileInfo *ti)
/* DrawFoundation() modifes ti->z and ti->tileh */
if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
DrawGroundSprite(image, pal);
/* If the ground sprite is the default flat water sprite, draw also canal/river borders.
* Do not do this if the tile's WaterClass is 'land'. */
if (image == SPR_FLAT_WATER_TILE && IsIndustryTileOnWater(ti->tile)) {
DrawWaterClassGround(ti);
} else {
DrawGroundSprite(image, pal);
}
/* If industries are transparent and invisible, do not draw the upper part */
if (IsInvisibilitySet(TO_INDUSTRIES)) return;
@ -724,6 +731,8 @@ static void TileLoop_Industry(TileIndex tile)
IndustryGfx newgfx;
IndustryGfx gfx;
if (IsIndustryTileOnWater(tile)) TileLoop_Water(tile);
TriggerIndustryTile(tile, INDTILE_TRIGGER_TILE_LOOP);
if (!IsIndustryCompleted(tile)) {
@ -748,14 +757,6 @@ static void TileLoop_Industry(TileIndex tile)
gfx = GetIndustryGfx(tile);
switch (gfx) {
case GFX_OILRIG_1: // coast line at oilrigs
case GFX_OILRIG_2:
case GFX_OILRIG_3:
case GFX_OILRIG_4:
case GFX_OILRIG_5:
TileLoop_Water(tile);
break;
case GFX_COAL_MINE_TOWER_NOT_ANIMATED:
case GFX_COPPER_MINE_TOWER_NOT_ANIMATED:
case GFX_GOLD_MINE_TOWER_NOT_ANIMATED:
@ -1548,9 +1549,11 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, int type, const Ind
size = it->ti.y;
if (size > i->height)i->height = size;
WaterClass wc = (IsWaterTile(cur_tile) ? GetWaterClass(cur_tile) : WATER_CLASS_INVALID);
DoCommand(cur_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
MakeIndustry(cur_tile, i->index, it->gfx, Random());
MakeIndustry(cur_tile, i->index, it->gfx, Random(), wc);
if (_generating_world) {
SetIndustryConstructionCounter(cur_tile, 3);

View File

@ -7,7 +7,7 @@
#include "industry.h"
#include "tile_map.h"
#include "water_map.h"
/**
@ -154,6 +154,17 @@ static inline void SetIndustryGfx(TileIndex t, IndustryGfx gfx)
SB(_m[t].m6, 2, 1, GB(gfx, 8, 1));
}
/**
* Tests if the industry tile was built on water.
* @param t the industry tile
* @return true iff on water
*/
static inline bool IsIndustryTileOnWater(TileIndex t)
{
assert(IsTileType(t, MP_INDUSTRY));
return (GetWaterClass(t) != WATER_CLASS_INVALID);
}
/**
* Make the given tile an industry tile
* @param t the tile to make an industry tile
@ -161,7 +172,7 @@ static inline void SetIndustryGfx(TileIndex t, IndustryGfx gfx)
* @param gfx the graphics to use for the tile
* @param random the random value
*/
static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, uint8 random)
static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx, uint8 random, WaterClass wc)
{
SetTileType(t, MP_INDUSTRY);
_m[t].m1 = 0;
@ -170,6 +181,7 @@ static inline void MakeIndustry(TileIndex t, IndustryID index, IndustryGfx gfx,
_m[t].m4 = 0;
SetIndustryGfx(t, gfx);
_me[t].m7 = random;
SetWaterClass(t, wc);
}
/**

View File

@ -25,6 +25,7 @@
#include "town.h"
#include "command_func.h"
#include "animated_tile_func.h"
#include "water.h"
#include "table/sprites.h"
#include "table/strings.h"
@ -185,7 +186,15 @@ void IndustryDrawTileLayout(const TileInfo *ti, const SpriteGroup *group, byte r
if (IS_CUSTOM_SPRITE(image)) image += stage;
if (GB(image, 0, SPRITE_WIDTH) != 0) DrawGroundSprite(image, pal);
if (GB(image, 0, SPRITE_WIDTH) != 0) {
/* If the ground sprite is the default flat water sprite, draw also canal/river borders
* Do not do this if the tile's WaterClass is 'land'. */
if (image == SPR_FLAT_WATER_TILE && IsIndustryTileOnWater(ti->tile)) {
DrawWaterClassGround(ti);
} else {
DrawGroundSprite(image, pal);
}
}
foreach_draw_tile_seq(dtss, dts->seq) {
if (GB(dtss->image.sprite, 0, SPRITE_WIDTH) == 0) continue;

View File

@ -2340,8 +2340,8 @@ bool AfterLoadGame()
for (TileIndex t = 0; t < map_size; t++) {
if (GetTileSlope(t, NULL) != SLOPE_FLAT) continue;
if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t);
if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t);
if (IsTileType(t, MP_WATER) && IsLock(t)) SetWaterClassDependingOnSurroundings(t, false);
if (IsTileType(t, MP_STATION) && (IsDock(t) || IsBuoy(t))) SetWaterClassDependingOnSurroundings(t, false);
}
}
@ -2438,6 +2438,22 @@ bool AfterLoadGame()
}
}
if (CheckSavegameVersion(99)) {
/* Set newly introduced WaterClass of industry tiles */
for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_STATION) && IsOilRig(t)) {
SetWaterClassDependingOnSurroundings(t, true);
}
if (IsTileType(t, MP_INDUSTRY)) {
if ((GetIndustrySpec(GetIndustryType(t))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0) {
SetWaterClassDependingOnSurroundings(t, true);
} else {
SetWaterClass(t, WATER_CLASS_INVALID);
}
}
}
}
GamelogPrintDebug(1);
return InitializeWindowsAndCaches();

View File

@ -36,7 +36,7 @@
#include "table/strings.h"
extern const uint16 SAVEGAME_VERSION = 98;
extern const uint16 SAVEGAME_VERSION = 99;
SavegameType _savegame_type; ///< type of savegame we are loading

View File

@ -2932,7 +2932,8 @@ void BuildOilRig(TileIndex tile)
st->string_id = GenerateStationName(st, tile, STATIONNAMING_OILRIG);
MakeOilrig(tile, st->index);
assert(IsTileType(tile, MP_INDUSTRY));
MakeOilrig(tile, st->index, GetWaterClass(tile));
st->owner = OWNER_NONE;
st->airport_flags = 0;
@ -2967,7 +2968,8 @@ void DeleteOilRig(TileIndex tile)
{
Station *st = GetStationByTile(tile);
MakeWater(tile);
MakeWaterKeepingClass(tile, OWNER_NONE);
MarkTileDirtyByTile(tile);
st->dock_tile = 0;
st->airport_tile = 0;

View File

@ -313,9 +313,10 @@ static inline void MakeDock(TileIndex t, Owner o, StationID sid, DiagDirection d
SetWaterClass(t + TileOffsByDiagDir(d), wc);
}
static inline void MakeOilrig(TileIndex t, StationID sid)
static inline void MakeOilrig(TileIndex t, StationID sid, WaterClass wc)
{
MakeStation(t, OWNER_NONE, sid, STATION_OILRIG, 0);
SetWaterClass(t, wc);
}
#endif /* STATION_MAP_H */

View File

@ -15,6 +15,6 @@ void DrawWaterClassGround(const struct TileInfo *ti);
void DrawShoreTile(Slope tileh);
void MakeWaterKeepingClass(TileIndex tile, Owner o);
void SetWaterClassDependingOnSurroundings(TileIndex t);
void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_water_class);
#endif /* WATER_H */

View File

@ -109,10 +109,20 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile)
* whether the tile used to be canal or 'normal' water.
* @param t the tile to change.
* @param o the owner of the new tile.
* @param include_invalid_water_class Also consider WATER_CLASS_INVALID, i.e. industry tiles on land
*/
void SetWaterClassDependingOnSurroundings(TileIndex t)
void SetWaterClassDependingOnSurroundings(TileIndex t, bool include_invalid_water_class)
{
assert(GetTileSlope(t, NULL) == SLOPE_FLAT);
/* If the slope is not flat, we always assume 'land' (if allowed). Also for one-corner-raised-shores.
* Note: Wrt. autosloping under industry tiles this is the most fool-proof behaviour. */
if (GetTileSlope(t, NULL) != SLOPE_FLAT) {
if (include_invalid_water_class) {
SetWaterClass(t, WATER_CLASS_INVALID);
return;
} else {
NOT_REACHED();
}
}
/* Mark tile dirty in all cases */
MarkTileDirtyByTile(t);
@ -158,6 +168,11 @@ void SetWaterClassDependingOnSurroundings(TileIndex t)
}
}
if (!has_water && !has_canal && !has_river && include_invalid_water_class) {
SetWaterClass(t, WATER_CLASS_INVALID);
return;
}
if (has_river && !has_canal) {
SetWaterClass(t, WATER_CLASS_RIVER);
} else if (has_canal || !has_water) {
@ -219,12 +234,21 @@ CommandCost CmdBuildShipDepot(TileIndex tile, uint32 flags, uint32 p1, uint32 p2
void MakeWaterKeepingClass(TileIndex tile, Owner o)
{
assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile))));
assert(IsTileType(tile, MP_WATER) || (IsTileType(tile, MP_STATION) && (IsBuoy(tile) || IsDock(tile) || IsOilRig(tile))) || IsTileType(tile, MP_INDUSTRY));
switch (GetWaterClass(tile)) {
WaterClass wc = GetWaterClass(tile);
/* Autoslope might turn an originally canal or river tile into land */
uint z;
if (GetTileSlope(tile, &z) != SLOPE_FLAT) wc = WATER_CLASS_INVALID;
if (wc == WATER_CLASS_SEA && z > 0) wc = WATER_CLASS_CANAL;
switch (wc) {
case WATER_CLASS_SEA: MakeWater(tile); break;
case WATER_CLASS_CANAL: MakeCanal(tile, o, Random()); break;
case WATER_CLASS_RIVER: MakeRiver(tile, Random()); break;
default: DoClearSquare(tile); break;
}
}
@ -512,7 +536,7 @@ static bool IsWateredTile(TileIndex tile, Direction from)
return false;
case MP_STATION: return IsOilRig(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsBuoy(tile);
case MP_INDUSTRY: return (GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0;
case MP_INDUSTRY: return IsIndustryTileOnWater(tile);
case MP_TUNNELBRIDGE: return GetTunnelBridgeTransportType(tile) == TRANSPORT_WATER && ReverseDiagDir(GetTunnelBridgeDirection(tile)) == DirToDiagDir(from);
default: return false;
}
@ -671,6 +695,7 @@ void DrawWaterClassGround(const TileInfo *ti) {
case WATER_CLASS_SEA: DrawSeaWater(ti->tile); break;
case WATER_CLASS_CANAL: DrawCanalWater(ti->tile); break;
case WATER_CLASS_RIVER: DrawRiverWater(ti); break;
default: NOT_REACHED();
}
}
@ -882,9 +907,9 @@ static void FloodVehicle(Vehicle *v)
*/
static FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
{
/* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile
/* FLOOD_ACTIVE: 'single-corner-raised'-coast, sea, sea-shipdepots, sea-buoys, sea-docks (water part), rail with flooded halftile, sea-water-industries, sea-oilrigs
* FLOOD_DRYUP: coast with more than one corner raised, coast with rail-track, coast with trees
* FLOOD_PASSIVE: oilrig, water-industries
* FLOOD_PASSIVE: (not used)
* FLOOD_NONE: canals, rivers, everything else
*/
switch (GetTileType(tile)) {
@ -906,13 +931,13 @@ static FloodingBehaviour GetFloodingBehaviour(TileIndex tile)
return (GetTreeGround(tile) == TREE_GROUND_SHORE ? FLOOD_DRYUP : FLOOD_NONE);
case MP_STATION:
if (IsBuoy(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT)) {
if (IsBuoy(tile) || (IsDock(tile) && GetTileSlope(tile, NULL) == SLOPE_FLAT) || IsOilRig(tile)) {
return (GetWaterClass(tile) == WATER_CLASS_SEA ? FLOOD_ACTIVE : FLOOD_NONE);
}
return (IsOilRig(tile) ? FLOOD_PASSIVE : FLOOD_NONE);
return FLOOD_NONE;
case MP_INDUSTRY:
return ((GetIndustrySpec(GetIndustryType(tile))->behaviour & INDUSTRYBEH_BUILT_ONWATER) != 0 ? FLOOD_PASSIVE : FLOOD_NONE);
return ((IsIndustryTileOnWater(tile) && GetWaterClass(tile) == WATER_CLASS_SEA) ? FLOOD_ACTIVE : FLOOD_NONE);
default:
return FLOOD_NONE;

View File

@ -16,6 +16,7 @@ enum WaterClass {
WATER_CLASS_SEA,
WATER_CLASS_CANAL,
WATER_CLASS_RIVER,
WATER_CLASS_INVALID, ///< Used for industry tiles on land (also for oilrig if newgrf says so)
};
enum DepotPart {
@ -45,14 +46,18 @@ static inline WaterTileType GetWaterTileType(TileIndex t)
static inline WaterClass GetWaterClass(TileIndex t)
{
assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION));
return (WaterClass)GB(_m[t].m3, 0, 2);
assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY));
return (WaterClass)(IsTileType(t, MP_INDUSTRY) ? GB(_m[t].m1, 5, 2) : GB(_m[t].m3, 0, 2));
}
static inline void SetWaterClass(TileIndex t, WaterClass wc)
{
assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION));
SB(_m[t].m3, 0, 2, wc);
assert(IsTileType(t, MP_WATER) || IsTileType(t, MP_STATION) || IsTileType(t, MP_INDUSTRY));
if (IsTileType(t, MP_INDUSTRY)) {
SB(_m[t].m1, 5, 2, wc);
} else {
SB(_m[t].m3, 0, 2, wc);
}
}
/** IsWater return true if any type of clear water like ocean, river, canal */