Add NewGRF object properties to set viewport map mode/smallmap tile type

pull/374/head
Jonathan G Rennison 2 years ago
parent 1d885c462f
commit d4f11eca42

@ -1895,6 +1895,7 @@
<li>m7: animation counter</li>
<li style="color: blue">m4 bits 7..5: update counter (for objects using land ground sprites), incremented on every periodic processing.<BR>
For snow and desert, these bits are not used, tile is updated on every periodic processing.</li>
<li style="color: blue">m4 bit 4: object type has viewport map colour/type override.</li>
<li style="color: blue">m4 bits 3..2: ground type (for objects using land ground sprites):
<table style="color: blue">
<tr>

@ -329,7 +329,7 @@ the array so you can quickly see what is used and what is not.
<td class="bits"><span class="free">O</span><span class="used" title="Water class">XX</span> <span class="used" title="Owner">XXXXX</span></td>
<td class="bits"><span class="pool" title="Object index on pool (m2 + m5)">XXXX XXXX XXXX XXXX</span></td>
<td class="bits"><span class="used" title="Random bits">XXXX XXXX</span></td>
<td class="bits"><span class="patch" title="Ground update counter">PPP</span><span class="free">O</span> <span class="patch" title="Ground type: grass/bare, snow/desert, shore">PP</span> <span class="patch" title="Ground density">PP</span></td>
<td class="bits"><span class="patch" title="Ground update counter">PPP</span> <span class="patch" title="Viewport map override">P</span> <span class="patch" title="Ground type: grass/bare, snow/desert, shore">PP</span> <span class="patch" title="Ground density">PP</span></td>
<td class="bits"><span class="pool" title="Object index on pool (m2 + m5)">XXXX XXXX</span></td>
<td class="bits"><span class="free">OOOO OO</span><span class="patch" title="Foundation type">PP</span> </td>
<td class="bits"><span class="used" title="Animation counter">XXXX XXXX</span></td>

@ -161,6 +161,55 @@
Flood resistance is always enabled for objects which can be built on water.<br />
This property can be used to enable flood resistance without enabling the object to be built on water.
</td></tr>
<tr><td>map_tile_type</td><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_XXX</td><td>
Set tile type used for display in viewport map mode and the small-map window.<br />
The value should be one of:
<table>
<tr><th>Value</th><th>Meaning</th><th>Notes</th></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_DEFAULT</td><td>Default object</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_CLEAR</td><td>Clear/bare dirt</td><td>If use_land_ground is enabled, the underlying ground type will be used instead</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_GRASS</td><td>Grass</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_ROUGH</td><td>Rough ground</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_ROCKS</td><td>Rocky ground</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_FIELDS</td><td>Farm fields</td><td>The specific type of field can be set using map_tile_subtype</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_SNOW</td><td>Snow</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_DESERT</td><td>Desert</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREES</td><td>Trees</td><td>The specific tree count and ground type/density can be set using map_tile_subtype</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_HOUSE</td><td>House</td><td></td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_WATER</td><td>Water</td><td></td></tr>
</table>
</td></tr>
<tr><td>map_tile_subtype</td><td>0 .. 65535</td><td>
<p>This can be used to further refine the type set in map_tile_type.</p>
<p>Farm fields:
<table>
<tr><th>Bit</th><th>Meaning</th></tr>
<tr><td>0 - 2</td><td>
Which field type to use
</td></tr>
</table></p>
<p>Trees:
<table>
<tr><th>Bit</th><th>Meaning</th></tr>
<tr><td>0 - 3</td><td>
Tree ground type
<table>
<tr><th>Value</th><th>Meaning</th></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREE_GROUND_GRASS</td><td>Grass</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREE_GROUND_ROUGH</td><td>Rough ground</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREE_GROUND_SNOW_DESERT</td><td>Snow/desert</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREE_GROUND_SHORE</td><td>Shore</td></tr>
<tr><td>OBJECT_VIEWPORT_MAP_TILE_TYPE_TREE_GROUND_ROUGH_SNOW</td><td>Rough snow</td></tr>
</table>
</td></tr>
<tr><td>4 - 7</td><td>
Tree ground density (clamped to: 0 - 3)
</td></tr>
<tr><td>8 - 11</td><td>
Number of trees on the tile (clamped to: 1 - 4)
</td></tr>
</table></p>
</td></tr>
</table>
<h3><a href="https://newgrf-specs.tt-wiki.net/wiki/NML:Objects#Object_variables">Object variables</a></h3>
<p>Variables in the table below which are not supported by the version of OpenTTD being used return a value of 0.</p>

@ -413,6 +413,56 @@
This property can be used to enable flood resistance without enabling the object to be built on water.<br />
The property length is 1 byte. 0 is disabled (default). 1 is enabled.</p>
<p>This is indicated by the feature name: <font face="monospace">action0_object_flood_resistant</font>, version 1</p>
<h4 id="object_viewport_map_tile_type">Set tile type used for display in viewport map mode and the small-map window (mappable property: object_viewport_map_tile_type)</h4>
<p>This property sets how object tiles are displayed in viewport map mode and the small-map window.<br />
The property length is 1 byte.</p>
<table>
<tr><th>Value</th><th>Meaning</th><th>Notes</th></tr>
<tr><td>00</td><td>Default object</td><td></td></tr>
<tr><td>01</td><td>Clear/bare dirt</td><td>If object_use_land_ground is enabled, the underlying ground type will be used instead</td></tr>
<tr><td>02</td><td>Grass</td><td></td></tr>
<tr><td>03</td><td>Rough ground</td><td></td></tr>
<tr><td>04</td><td>Rocky ground</td><td></td></tr>
<tr><td>05</td><td>Farm fields</td><td>The specific type of field can be set using object_viewport_map_tile_subtype</td></tr>
<tr><td>06</td><td>Snow</td><td></td></tr>
<tr><td>07</td><td>Desert</td><td></td></tr>
<tr><td>08</td><td>Trees</td><td>The specific tree count and ground type/density can be set using object_viewport_map_tile_subtype</td></tr>
<tr><td>09</td><td>House</td><td></td></tr>
<tr><td>0A</td><td>Water</td><td></td></tr>
</table></p>
<p>This is indicated by the feature name: <font face="monospace">action0_object_viewport_map_tile_type</font>, version 1</p>
<h4 id="object_viewport_map_tile_subtype">Set tile sub-type used for display in viewport map mode and the small-map window (mappable property: object_viewport_map_tile_subtype)</h4>
<p>This property can be used to further refine the type set in object_viewport_map_tile_type.<br />
The property length is 2 bytes.</p>
<p>Farm fields:
<table>
<tr><th>Bit</th><th>Value</th><th>Meaning</th></tr>
<tr><td>0 - 2</td><td>0 - 7</td><td>
Which field type to use
</td></tr>
</table></p>
<p>Trees:
<table>
<tr><th>Bit</th><th>Meaning</th></tr>
<tr><td>0 - 3</td><td>
Tree ground type
<table>
<tr><th>Value</th><th>Meaning</th></tr>
<tr><td>0</td><td>Grass</td></tr>
<tr><td>1</td><td>Rough ground</td></tr>
<tr><td>2</td><td>Snow/desert</td></tr>
<tr><td>3</td><td>Shore</td></tr>
<tr><td>4</td><td>Rough snow</td></tr>
</table>
</td></tr>
<tr><td>4 - 7</td><td>
Tree ground density (clamped to: 0 - 3)
</td></tr>
<tr><td>8 - 11</td><td>
Number of trees on the tile (clamped to: 1 - 4)
</td></tr>
</table></p>
<p>This is indicated by the feature name: <font face="monospace">action0_object_viewport_map_tile_type</font>, version 1</p>
<br />
<h3 id="variable-mapping">Action 14 - Variable Mapping for Variational Action 2</h3>
<p>See <a href="https://newgrf-specs.tt-wiki.net/wiki/Action14">Action 14 Specification</a> and <a href="https://newgrf-specs.tt-wiki.net/wiki/VariationalAction2">Variational Action 2 Specification</a> for background information.</p>

@ -4327,6 +4327,17 @@ static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, const G
if (buf->ReadByte() != 0) spec->ctrl_flags |= OBJECT_CTRL_FLAG_FLOOD_RESISTANT;
break;
case A0RPI_OBJECT_VIEWPORT_MAP_TYPE:
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
spec->vport_map_type = (ObjectViewportMapType)buf->ReadByte();
spec->ctrl_flags |= OBJECT_CTRL_FLAG_VPORT_MAP_TYPE;
break;
case A0RPI_OBJECT_VIEWPORT_MAP_SUBTYPE:
if (MappedPropertyLengthMismatch(buf, 2, mapping_entry)) break;
spec->vport_map_subtype = buf->ReadWord();
break;
default:
ret = HandleAction0PropertyDefault(buf, prop);
break;

@ -50,6 +50,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("action0_object_use_land_ground", 1),
GRFFeatureInfo("action0_object_edge_foundation_mode", 2),
GRFFeatureInfo("action0_object_flood_resistant", 1),
GRFFeatureInfo("action0_object_viewport_map_tile_type", 1),
GRFFeatureInfo(),
};
@ -85,6 +86,8 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_USE_LAND_GROUND, "object_use_land_ground"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_EDGE_FOUNDATION_MODE, "object_edge_foundation_mode"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_FLOOD_RESISTANT, "object_flood_resistant"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_VIEWPORT_MAP_TYPE, "object_viewport_map_tile_type"),
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_VIEWPORT_MAP_SUBTYPE, "object_viewport_map_tile_subtype"),
GRFPropertyMapDefinition(),
};

@ -37,6 +37,8 @@ enum Action0RemapPropertyIds {
A0RPI_OBJECT_USE_LAND_GROUND,
A0RPI_OBJECT_EDGE_FOUNDATION_MODE,
A0RPI_OBJECT_FLOOD_RESISTANT,
A0RPI_OBJECT_VIEWPORT_MAP_TYPE,
A0RPI_OBJECT_VIEWPORT_MAP_SUBTYPE,
};

@ -45,6 +45,7 @@ enum ObjectCtrlFlags {
OBJECT_CTRL_FLAG_USE_LAND_GROUND = 1 << 0, ///< Use land for ground sprite.
OBJECT_CTRL_FLAG_EDGE_FOUNDATION = 1 << 1, ///< Use edge foundation mode.
OBJECT_CTRL_FLAG_FLOOD_RESISTANT = 1 << 2, ///< Object is flood-resistant.
OBJECT_CTRL_FLAG_VPORT_MAP_TYPE = 1 << 3, ///< Viewport map type is set.
};
DECLARE_ENUM_AS_BIT_SET(ObjectCtrlFlags)
@ -67,6 +68,20 @@ enum ObjectClassID {
/** Allow incrementing of ObjectClassID variables */
DECLARE_POSTFIX_INCREMENT(ObjectClassID)
enum ObjectViewportMapType {
OVMT_DEFAULT = 0,
OVMT_CLEAR,
OVMT_GRASS,
OVMT_ROUGH,
OVMT_ROCKS,
OVMT_FIELDS,
OVMT_SNOW,
OVMT_DESERT,
OVMT_TREES,
OVMT_HOUSE,
OVMT_WATER,
};
/** An object that isn't use for transport, industries or houses.
* @note If you change this struct, adopt the initialization of
* default objects in table/object_land.h
@ -92,6 +107,8 @@ struct ObjectSpec {
uint8 views; ///< The number of views.
uint8 generate_amount; ///< Number of objects which are attempted to be generated per 256^2 map during world generation.
bool enabled; ///< Is this spec enabled?
ObjectViewportMapType vport_map_type; ///< Viewport map type
uint16 vport_map_subtype; ///< Viewport map subtype
/**
* Get the cost for building a structure of this type.

@ -182,6 +182,9 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u
SetObjectGroundTypeDensity(t, OBJECT_GROUND_GRASS, 0);
}
SetObjectFoundationType(t, SLOPE_ELEVATED, type, spec);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) {
SetObjectHasViewportMapViewOverride(t, true);
}
MarkTileDirtyByTile(t, VMDF_NOT_MAP_MODE);
}
@ -953,11 +956,11 @@ static void TileLoop_Object(TileIndex tile)
} else {
SetObjectGroundCounter(tile, 0);
SetObjectGroundDensity(tile, GetObjectGroundDensity(tile) + 1);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
MarkTileDirtyByTile(tile, spec->vport_map_type != OVMT_CLEAR ? VMDF_NOT_MAP_MODE : VMDF_NONE);
}
} else {
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_GRASS, 3);
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
MarkTileDirtyByTile(tile, spec->vport_map_type != OVMT_CLEAR ? VMDF_NOT_MAP_MODE : VMDF_NONE);
}
}
}

@ -168,6 +168,18 @@ static inline void SetObjectEffectiveFoundationType(TileIndex t, ObjectEffective
SB(_me[t].m6, 0, 2, foundation_type);
}
static inline bool GetObjectHasViewportMapViewOverride(TileIndex t)
{
assert_tile(IsTileType(t, MP_OBJECT), t);
return HasBit(_m[t].m4, 4);
}
static inline void SetObjectHasViewportMapViewOverride(TileIndex t, bool map_view_override)
{
assert_tile(IsTileType(t, MP_OBJECT), t);
SB(_m[t].m4, 4, 1, map_view_override ? 1 : 0);
}
/**
* Make an Object tile.
* @param t The tile to make and object tile.

@ -3989,13 +3989,20 @@ bool AfterLoadGame()
}
}
if (SlXvIsFeatureMissing(XSLFI_OBJECT_GROUND_TYPES, 2)) {
if (SlXvIsFeatureMissing(XSLFI_OBJECT_GROUND_TYPES, 3)) {
for (TileIndex t = 0; t < map_size; t++) {
if (IsTileType(t, MP_OBJECT)) {
if (SlXvIsFeatureMissing(XSLFI_OBJECT_GROUND_TYPES)) _m[t].m4 = 0;
ObjectType type = GetObjectType(t);
extern void SetObjectFoundationType(TileIndex tile, Slope tileh, ObjectType type, const ObjectSpec *spec);
SetObjectFoundationType(t, SLOPE_ELEVATED, type, ObjectSpec::Get(type));
if (SlXvIsFeatureMissing(XSLFI_OBJECT_GROUND_TYPES, 2)) {
ObjectType type = GetObjectType(t);
extern void SetObjectFoundationType(TileIndex tile, Slope tileh, ObjectType type, const ObjectSpec *spec);
SetObjectFoundationType(t, SLOPE_ELEVATED, type, ObjectSpec::Get(type));
}
if (SlXvIsFeatureMissing(XSLFI_OBJECT_GROUND_TYPES, 3)) {
if (ObjectSpec::GetByTile(t)->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) {
SetObjectHasViewportMapViewOverride(t, true);
}
}
}
}
}

@ -161,7 +161,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_DEPOT_ORDER_EXTRA_FLAGS,XSCF_IGNORABLE_UNKNOWN, 1, 1, "depot_order_extra_flags", nullptr, nullptr, nullptr },
{ XSLFI_EXTRA_SIGNAL_TYPES, XSCF_NULL, 1, 1, "extra_signal_types", nullptr, nullptr, nullptr },
{ XSLFI_BANKRUPTCY_EXTRA, XSCF_NULL, 1, 1, "bankruptcy_extra", nullptr, nullptr, nullptr },
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 2, 2, "object_ground_types", nullptr, nullptr, nullptr },
{ XSLFI_OBJECT_GROUND_TYPES, XSCF_NULL, 3, 3, "object_ground_types", nullptr, nullptr, nullptr },
{ XSLFI_LINKGRAPH_AIRCRAFT, XSCF_NULL, 1, 1, "linkgraph_aircraft", nullptr, nullptr, nullptr },
{ XSLFI_COMPANY_PW, XSCF_IGNORABLE_ALL, 1, 1, "company_password", nullptr, nullptr, "PLYP" },
{ XSLFI_ST_INDUSTRY_CARGO_MODE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "st_industry_cargo_mode", nullptr, nullptr, nullptr },

@ -24,6 +24,8 @@
#include "screenshot.h"
#include "guitimer_func.h"
#include "zoom_func.h"
#include "object_map.h"
#include "newgrf_object.h"
#include "smallmap_colours.h"
#include "smallmap_gui.h"
@ -319,6 +321,41 @@ void BuildOwnerLegend()
_smallmap_company_count = i;
}
static TileType GetSmallMapTileType(TileIndex tile, TileType t)
{
if (t == MP_OBJECT && GetObjectHasViewportMapViewOverride(tile)) {
ObjectViewportMapType vmtype = OVMT_DEFAULT;
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) vmtype = spec->vport_map_type;
if (vmtype == OVMT_CLEAR && spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
if (IsTileOnWater(tile) && GetObjectGroundType(tile) != OBJECT_GROUND_SHORE) {
vmtype = OVMT_WATER;
}
}
switch (vmtype) {
case OVMT_DEFAULT:
break;
case OVMT_TREES:
t = MP_TREES;
break;
case OVMT_HOUSE:
t = MP_HOUSE;
break;
case OVMT_WATER:
t = MP_WATER;
break;
default:
t = MP_CLEAR;
break;
}
}
return t;
}
/**
* Return the colour a tile would be displayed with in the small map in mode "Contour".
* @param tile The tile of which we would like to get the colour.
@ -328,7 +365,7 @@ void BuildOwnerLegend()
static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
{
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[t]);
return ApplyMask(cs->height_colours[TileHeight(tile)], &_smallmap_contours_andor[GetSmallMapTileType(tile, t)]);
}
/**
@ -341,7 +378,7 @@ static inline uint32 GetSmallMapContoursPixels(TileIndex tile, TileType t)
static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
{
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[t]);
return ApplyMask(cs->default_colour, &_smallmap_vehicles_andor[GetSmallMapTileType(tile, t)]);
}
/**
@ -354,7 +391,7 @@ static inline uint32 GetSmallMapVehiclesPixels(TileIndex tile, TileType t)
static inline uint32 GetSmallMapIndustriesPixels(TileIndex tile, TileType t)
{
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[t]);
return ApplyMask(_smallmap_show_heightmap ? cs->height_colours[TileHeight(tile)] : cs->default_colour, &_smallmap_vehicles_andor[GetSmallMapTileType(tile, t)]);
}
/**
@ -409,7 +446,7 @@ static inline uint32 GetSmallMapRoutesPixels(TileIndex tile, TileType t)
default:
/* Ground colour */
const SmallMapColourScheme *cs = &_heightmap_schemes[_settings_client.gui.smallmap_land_colour];
return ApplyMask(cs->default_colour, &_smallmap_contours_andor[t]);
return ApplyMask(cs->default_colour, &_smallmap_contours_andor[GetSmallMapTileType(tile, t)]);
}
}
@ -451,6 +488,72 @@ static inline uint32 GetSmallMapVegetationPixels(TileIndex tile, TileType t)
}
return (GetTropicZone(tile) == TROPICZONE_RAINFOREST) ? MKCOLOUR_XYYX(PC_RAINFOREST, PC_TREES) : MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
case MP_OBJECT: {
if (!GetObjectHasViewportMapViewOverride(tile)) return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
ObjectViewportMapType vmtype = OVMT_DEFAULT;
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) vmtype = spec->vport_map_type;
switch (vmtype) {
case OVMT_CLEAR:
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
if (IsTileOnWater(tile) && GetObjectGroundType(tile) != OBJECT_GROUND_SHORE) {
t = MP_WATER;
} else {
switch (GetObjectGroundType(tile)) {
case OBJECT_GROUND_GRASS:
if (GetObjectGroundDensity(tile) < 3) return MKCOLOUR_XXXX(PC_BARE_LAND);
if (GetTropicZone(tile) == TROPICZONE_RAINFOREST) return MKCOLOUR_XXXX(PC_RAINFOREST);
return _vegetation_clear_bits[CLEAR_GRASS];
case OBJECT_GROUND_SNOW_DESERT:
return _vegetation_clear_bits[_settings_game.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW];
case OBJECT_GROUND_SHORE:
t = MP_WATER;
break;
default:
/* This should never be reached, just draw as normal as a fallback */
break;
}
}
} else {
return MKCOLOUR_XXXX(PC_BARE_LAND);
}
case OVMT_GRASS:
if (GetTropicZone(tile) == TROPICZONE_RAINFOREST) return MKCOLOUR_XXXX(PC_RAINFOREST);
return _vegetation_clear_bits[CLEAR_GRASS];
case OVMT_ROUGH:
return _vegetation_clear_bits[CLEAR_ROUGH];
case OVMT_ROCKS:
return _vegetation_clear_bits[CLEAR_ROCKS];
case OVMT_FIELDS:
return _vegetation_clear_bits[CLEAR_FIELDS];
case OVMT_SNOW:
return _vegetation_clear_bits[CLEAR_SNOW];
case OVMT_DESERT:
return _vegetation_clear_bits[CLEAR_DESERT];
case OVMT_TREES: {
const TreeGround tg = (TreeGround)GB(spec->vport_map_subtype, 0, 4);
if (tg == TREE_GROUND_SNOW_DESERT || tg == TREE_GROUND_ROUGH_SNOW) {
return (_settings_game.game_creation.landscape == LT_ARCTIC) ? MKCOLOUR_XYYX(PC_LIGHT_BLUE, PC_TREES) : MKCOLOUR_XYYX(PC_ORANGE, PC_TREES);
}
return (GetTropicZone(tile) == TROPICZONE_RAINFOREST) ? MKCOLOUR_XYYX(PC_RAINFOREST, PC_TREES) : MKCOLOUR_XYYX(PC_GRASS_LAND, PC_TREES);
}
case OVMT_HOUSE:
t = MP_HOUSE;
break;
case OVMT_WATER:
t = MP_WATER;
break;
default:
break;
}
return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
}
default:
return ApplyMask(MKCOLOUR_XXXX(PC_GRASS_LAND), &_smallmap_vehicles_andor[t]);
}

@ -926,6 +926,7 @@ class NIHObject : public NIHelper {
check_ctrl_flag(OBJECT_CTRL_FLAG_USE_LAND_GROUND, "OBJECT_CTRL_FLAG_USE_LAND_GROUND");
check_ctrl_flag(OBJECT_CTRL_FLAG_EDGE_FOUNDATION, "OBJECT_CTRL_FLAG_EDGE_FOUNDATION");
check_ctrl_flag(OBJECT_CTRL_FLAG_FLOOD_RESISTANT, "OBJECT_CTRL_FLAG_FLOOD_RESISTANT");
check_ctrl_flag(OBJECT_CTRL_FLAG_VPORT_MAP_TYPE, "OBJECT_CTRL_FLAG_VPORT_MAP_TYPE");
}
}
}

@ -121,7 +121,7 @@ static const DrawTileSprites _object_hq[] = {
#undef TILE_SPRITE_LINE
#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags) { GRFFilePropsBase<2>(), INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, MAX_DAY + 1, flags, OBJECT_CTRL_FLAG_NONE, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, height, 1, gen_amount, true }
#define M(name, size, build_cost_multiplier, clear_cost_multiplier, height, climate, gen_amount, flags) { GRFFilePropsBase<2>(), INVALID_OBJECT_CLASS, name, climate, size, build_cost_multiplier, clear_cost_multiplier, 0, MAX_DAY + 1, flags, OBJECT_CTRL_FLAG_NONE, {0, 0, 0, 0}, {0, 0, 0, 0}, 0, height, 1, gen_amount, true, OVMT_DEFAULT, 0 }
/* Climates
* T = Temperate

@ -109,6 +109,8 @@
#include "scope_info.h"
#include "scope.h"
#include "blitter/32bpp_base.hpp"
#include "object_map.h"
#include "newgrf_object.h"
#include <map>
#include <vector>
@ -2618,10 +2620,143 @@ static const ClearGround _treeground_to_clearground[5] = {
CLEAR_SNOW, // TREE_GROUND_ROUGH_SNOW, make it +1 if _settings_game.game_creation.landscape == LT_TROPIC
};
template <bool is_32bpp>
static inline uint32 ViewportMapGetColourVegetationTree(const TileIndex tile, const TreeGround tg, const uint td, const uint tc, const uint colour_index, Slope slope)
{
if (IsTransparencySet(TO_TREES)) {
ClearGround cg = _treeground_to_clearground[tg];
if (cg == CLEAR_SNOW && _settings_game.game_creation.landscape == LT_TROPIC) cg = CLEAR_DESERT;
uint32 ground_colour = _vp_map_vegetation_clear_colours[slope][cg][td];
if (IsInvisibilitySet(TO_TREES)) {
/* Like ground. */
return ground_colour;
}
/* Take ground and make it darker. */
if (is_32bpp) {
return Blitter_32bppBase::MakeTransparent(ground_colour, 192, 256).data;
} else {
/* 8bpp transparent snow trees give blue. Definitely don't want that. Prefer grey. */
if (cg == CLEAR_SNOW && td > 1) return GREY_SCALE(13 - tc);
return _pal2trsp_remap_ptr[ground_colour];
}
} else {
if (tg == TREE_GROUND_SNOW_DESERT || tg == TREE_GROUND_ROUGH_SNOW) {
return _vp_map_vegetation_clear_colours[colour_index ^ slope][_settings_game.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW][td];
} else {
const uint rnd = std::min<uint>(tc ^ (((tile & 3) ^ (TileY(tile) & 3)) * td), MAX_TREE_COUNT_BY_LANDSCAPE - 1);
return _vp_map_vegetation_tree_colours[slope][tg][rnd];
}
}
}
static bool ViewportMapGetColourVegetationCustomObject(uint32 &colour, const TileIndex tile, const uint colour_index, bool is_32bpp, bool show_slope)
{
ObjectViewportMapType vmtype = OVMT_DEFAULT;
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) vmtype = spec->vport_map_type;
auto do_clear_ground = [&](ClearGround cg, uint multi) -> bool {
Slope slope = SLOPE_FLAT;
if (show_slope) {
slope = GetTileSlope(tile);
extern Foundation GetFoundation_Object(TileIndex tile, Slope tileh);
ApplyFoundationToSlope(GetFoundation_Object(tile, slope), &slope);
slope &= SLOPE_ELEVATED;
}
colour = _vp_map_vegetation_clear_colours[slope][cg][multi];
return true;
};
auto do_water = [&](bool coast) -> bool {
if (is_32bpp) {
uint slope_index = 0;
if (!coast) GET_SLOPE_INDEX(slope_index);
colour = _vp_map_water_colour[slope_index];
return true;
}
colour = ApplyMask(MKCOLOUR_XXXX(GREY_SCALE(3)), &_smallmap_vehicles_andor[MP_WATER]);
colour = COLOUR_FROM_INDEX(colour);
return false;
};
switch (vmtype) {
case OVMT_CLEAR:
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
if (IsTileOnWater(tile) && GetObjectGroundType(tile) != OBJECT_GROUND_SHORE) {
return do_water(false);
} else {
switch (GetObjectGroundType(tile)) {
case OBJECT_GROUND_GRASS:
return do_clear_ground(CLEAR_GRASS, GetObjectGroundDensity(tile));
case OBJECT_GROUND_SNOW_DESERT:
return do_clear_ground(_settings_game.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW, GetObjectGroundDensity(tile));
case OBJECT_GROUND_SHORE:
return do_water(true);
default:
/* This should never be reached, just draw as clear as a fallback */
return do_clear_ground(CLEAR_GRASS, 0);
}
}
}
return do_clear_ground(CLEAR_GRASS, 0);
case OVMT_GRASS:
return do_clear_ground(CLEAR_GRASS, 3);
case OVMT_ROUGH:
return do_clear_ground(CLEAR_ROUGH, GB(TileX(tile) ^ TileY(tile), 4, 3));
case OVMT_ROCKS:
return do_clear_ground(CLEAR_ROCKS, TileHash(TileX(tile), TileY(tile)) & 1);
case OVMT_FIELDS:
return (colour_index & 1) ? do_clear_ground(CLEAR_GRASS, 1) : do_clear_ground(CLEAR_FIELDS, spec->vport_map_subtype & 7);
case OVMT_SNOW:
return do_clear_ground(CLEAR_SNOW, 3);
case OVMT_DESERT:
return do_clear_ground(CLEAR_DESERT, 3);
case OVMT_TREES: {
Slope slope = SLOPE_FLAT;
if (show_slope) {
slope = GetTileSlope(tile);
extern Foundation GetFoundation_Object(TileIndex tile, Slope tileh);
ApplyFoundationToSlope(GetFoundation_Object(tile, slope), &slope);
slope &= SLOPE_ELEVATED;
}
TreeGround tg = (TreeGround)GB(spec->vport_map_subtype, 0, 4);
if (tg > TREE_GROUND_ROUGH_SNOW) tg = TREE_GROUND_GRASS;
const uint td = std::min<uint>(GB(spec->vport_map_subtype, 4, 4), 3);
const uint tc = Clamp<uint>(GB(spec->vport_map_subtype, 8, 4), 1, 4);
if (is_32bpp) {
colour = ViewportMapGetColourVegetationTree<true>(tile, tg, td, tc, colour_index, slope);
} else {
colour = ViewportMapGetColourVegetationTree<false>(tile, tg, td, tc, colour_index, slope);
}
return true;
}
case OVMT_HOUSE:
colour = ApplyMask(MKCOLOUR_XXXX(GREY_SCALE(3)), &_smallmap_vehicles_andor[MP_HOUSE]);
colour = COLOUR_FROM_INDEX(colour);
return false;
case OVMT_WATER:
return do_water(false);
default:
return false;
}
}
template <bool is_32bpp, bool show_slope>
static inline uint32 ViewportMapGetColourVegetation(const TileIndex tile, TileType t, const uint colour_index)
{
uint32 colour;
auto set_default_colour = [&](TileType ttype) {
colour = ApplyMask(MKCOLOUR_XXXX(GREY_SCALE(3)), &_smallmap_vehicles_andor[ttype]);
colour = COLOUR_FROM_INDEX(colour);
};
switch (t) {
case MP_CLEAR: {
Slope slope = show_slope ? (Slope) (GetTileSlope(tile, nullptr) & 15) : SLOPE_FLAT;
@ -2641,33 +2776,17 @@ static inline uint32 ViewportMapGetColourVegetation(const TileIndex tile, TileTy
case MP_TREES: {
const TreeGround tg = GetTreeGround(tile);
const uint td = GetTreeDensity(tile);
const uint tc = GetTreeCount(tile);
Slope slope = show_slope ? (Slope) (GetTileSlope(tile, nullptr) & 15) : SLOPE_FLAT;
if (IsTransparencySet(TO_TREES)) {
ClearGround cg = _treeground_to_clearground[tg];
if (cg == CLEAR_SNOW && _settings_game.game_creation.landscape == LT_TROPIC) cg = CLEAR_DESERT;
uint32 ground_colour = _vp_map_vegetation_clear_colours[slope][cg][td];
if (IsInvisibilitySet(TO_TREES)) {
/* Like ground. */
return ground_colour;
}
return ViewportMapGetColourVegetationTree<is_32bpp>(tile, tg, td, tc, colour_index, slope);
}
/* Take ground and make it darker. */
if (is_32bpp) {
return Blitter_32bppBase::MakeTransparent(ground_colour, 192, 256).data;
} else {
/* 8bpp transparent snow trees give blue. Definitely don't want that. Prefer grey. */
if (cg == CLEAR_SNOW && td > 1) return GREY_SCALE(13 - GetTreeCount(tile));
return _pal2trsp_remap_ptr[ground_colour];
}
} else {
if (tg == TREE_GROUND_SNOW_DESERT || tg == TREE_GROUND_ROUGH_SNOW) {
return _vp_map_vegetation_clear_colours[colour_index ^ slope][_settings_game.game_creation.landscape == LT_TROPIC ? CLEAR_DESERT : CLEAR_SNOW][td];
} else {
const uint rnd = std::min<uint>(GetTreeCount(tile) ^ (((tile & 3) ^ (TileY(tile) & 3)) * td), MAX_TREE_COUNT_BY_LANDSCAPE - 1);
return _vp_map_vegetation_tree_colours[slope][tg][rnd];
}
case MP_OBJECT: {
set_default_colour(MP_OBJECT);
if (GetObjectHasViewportMapViewOverride(tile)) {
if (ViewportMapGetColourVegetationCustomObject(colour, tile, colour_index, is_32bpp, show_slope)) return colour;
}
break;
}
case MP_WATER:
@ -2676,11 +2795,13 @@ static inline uint32 ViewportMapGetColourVegetation(const TileIndex tile, TileTy
if (IsTileType(tile, MP_WATER) && GetWaterTileType(tile) != WATER_TILE_COAST) GET_SLOPE_INDEX(slope_index);
return _vp_map_water_colour[slope_index];
}
/* FALL THROUGH */
set_default_colour(t);
break;
default:
colour = ApplyMask(MKCOLOUR_XXXX(GREY_SCALE(3)), &_smallmap_vehicles_andor[t]);
colour = COLOUR_FROM_INDEX(colour);
set_default_colour(t);
break;
}
@ -2709,6 +2830,37 @@ static inline uint32 ViewportMapGetColourIndustries(const TileIndex tile, const
t2 = IsTileOnWater(tile) ? MP_WATER : MP_CLEAR;
}
if (t == MP_OBJECT && GetObjectHasViewportMapViewOverride(tile)) {
ObjectViewportMapType vmtype = OVMT_DEFAULT;
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) vmtype = spec->vport_map_type;
if (vmtype == OVMT_CLEAR && spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
if (IsTileOnWater(tile) && GetObjectGroundType(tile) != OBJECT_GROUND_SHORE) {
vmtype = OVMT_WATER;
}
}
switch (vmtype) {
case OVMT_DEFAULT:
break;
case OVMT_TREES:
t2 = MP_TREES;
break;
case OVMT_HOUSE:
t2 = MP_HOUSE;
break;
case OVMT_WATER:
t2 = MP_WATER;
break;
default:
t2 = MP_CLEAR;
break;
}
}
if (is_32bpp && t2 == MP_WATER) {
uint slope_index = 0;
if (t != MP_INDUSTRY && IsTileType(tile, MP_WATER) && GetWaterTileType(tile) != WATER_TILE_COAST) GET_SLOPE_INDEX(slope_index); ///< Ignore industry on water not shown on map.
@ -2791,9 +2943,38 @@ static inline uint32 ViewportMapGetColourRoutes(const TileIndex tile, TileType t
return IS32(PC_DARK_GREY);
case MP_HOUSE:
case MP_OBJECT:
return IS32(colour_index & 1 ? PC_DARK_RED : GREY_SCALE(3));
case MP_OBJECT: {
ObjectViewportMapType vmtype = OVMT_DEFAULT;
if (GetObjectHasViewportMapViewOverride(tile)) {
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_VPORT_MAP_TYPE) vmtype = spec->vport_map_type;
if (vmtype == OVMT_CLEAR && spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
if (IsTileOnWater(tile) && GetObjectGroundType(tile) != OBJECT_GROUND_SHORE) {
vmtype = OVMT_WATER;
}
}
}
switch (vmtype) {
case OVMT_DEFAULT:
case OVMT_HOUSE:
return IS32(colour_index & 1 ? PC_DARK_RED : GREY_SCALE(3));
case OVMT_WATER:
if (is_32bpp) {
return _vp_map_water_colour[0];
} else {
return PC_WATER;
}
default:
colour = COLOUR_FROM_INDEX(_heightmap_schemes[_settings_client.gui.smallmap_land_colour].height_colours[TileHeight(tile)]);
break;
}
break;
}
case MP_STATION:
switch (GetStationType(tile)) {
case STATION_RAIL: return IS32(PC_VERY_DARK_BROWN);

Loading…
Cancel
Save