Add NewGRF object property/flag to use land as object ground sprite
This handles variable ground densities, snow/desert, etc.
This commit is contained in:
@@ -1853,6 +1853,52 @@
|
|||||||
<li>m3: random bits</li>
|
<li>m3: random bits</li>
|
||||||
<li>m5: index into the array of objects, bits 16 to 23 (lower bits in m2)</li>
|
<li>m5: index into the array of objects, bits 16 to 23 (lower bits in m2)</li>
|
||||||
<li>m7: animation counter</li>
|
<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 bits 3..2: ground type (for objects using land ground sprites):
|
||||||
|
<table style="color: blue">
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>0</tt> </td>
|
||||||
|
<td align=left>bare land / grass</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>1</tt> </td>
|
||||||
|
<td align=left>snow or desert</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
|
<li style="color: blue">m4 bits 1..0: density (for objects using land ground sprites):
|
||||||
|
<table style="color: blue">
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>0</tt> </td>
|
||||||
|
<td>bare land</td>
|
||||||
|
<td>1/4 snow</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>1</tt> </td>
|
||||||
|
<td>1/3 grass</td>
|
||||||
|
<td>2/4 snow; </td>
|
||||||
|
<td>1/2 desert</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>2</tt> </td>
|
||||||
|
<td>2/3 grass</td>
|
||||||
|
<td>3/4 snow</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td nowrap valign=top><tt>3</tt> </td>
|
||||||
|
<td>full grass; </td>
|
||||||
|
<td>full snow; </td>
|
||||||
|
<td>full desert</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@@ -324,7 +324,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="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="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="used" title="Random bits">XXXX XXXX</span></td>
|
||||||
<td class="bits"><span class="free">OOOO OOOO</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">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="pool" title="Object index on pool (m2 + m5)">XXXX XXXX</span></td>
|
||||||
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
<td class="bits"><span class="free">OOOO OOOO</span></td>
|
||||||
<td class="bits"><span class="used" title="Animation counter">XXXX XXXX</span></td>
|
<td class="bits"><span class="used" title="Animation counter">XXXX XXXX</span></td>
|
||||||
|
@@ -4296,6 +4296,11 @@ static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, const G
|
|||||||
spec->generate_amount = buf->ReadByte();
|
spec->generate_amount = buf->ReadByte();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case A0RPI_OBJECT_USE_LAND_GROUND:
|
||||||
|
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
|
||||||
|
SB(spec->ctrl_flags, OBJECT_CTRL_FLAG_USE_LAND_GROUND, 1, (buf->ReadByte() != 0 ? 1 : 0));
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = HandleAction0PropertyDefault(buf, prop);
|
ret = HandleAction0PropertyDefault(buf, prop);
|
||||||
break;
|
break;
|
||||||
|
@@ -42,6 +42,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
|
|||||||
GRFFeatureInfo("action0_signals_recolour", 1),
|
GRFFeatureInfo("action0_signals_recolour", 1),
|
||||||
GRFFeatureInfo("action0_signals_extra_aspects", 1),
|
GRFFeatureInfo("action0_signals_extra_aspects", 1),
|
||||||
GRFFeatureInfo("action3_signals_custom_signal_sprites", 1),
|
GRFFeatureInfo("action3_signals_custom_signal_sprites", 1),
|
||||||
|
GRFFeatureInfo("action0_object_use_land_ground", 1),
|
||||||
GRFFeatureInfo(),
|
GRFFeatureInfo(),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
|
|||||||
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS, "signals_enable_restricted_signals"),
|
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS, "signals_enable_restricted_signals"),
|
||||||
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR, "signals_enable_signal_recolour"),
|
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR, "signals_enable_signal_recolour"),
|
||||||
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_EXTRA_ASPECTS, "signals_extra_aspects"),
|
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_EXTRA_ASPECTS, "signals_extra_aspects"),
|
||||||
|
GRFPropertyMapDefinition(GSF_OBJECTS, A0RPI_OBJECT_USE_LAND_GROUND, "object_use_land_ground"),
|
||||||
GRFPropertyMapDefinition(),
|
GRFPropertyMapDefinition(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -32,6 +32,7 @@ enum Action0RemapPropertyIds {
|
|||||||
A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS,
|
A0RPI_SIGNALS_ENABLE_RESTRICTED_SIGNALS,
|
||||||
A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR,
|
A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR,
|
||||||
A0RPI_SIGNALS_EXTRA_ASPECTS,
|
A0RPI_SIGNALS_EXTRA_ASPECTS,
|
||||||
|
A0RPI_OBJECT_USE_LAND_GROUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -20,6 +20,7 @@
|
|||||||
#include "tile_cmd.h"
|
#include "tile_cmd.h"
|
||||||
#include "town.h"
|
#include "town.h"
|
||||||
#include "water.h"
|
#include "water.h"
|
||||||
|
#include "clear_func.h"
|
||||||
#include "newgrf_animation_base.h"
|
#include "newgrf_animation_base.h"
|
||||||
|
|
||||||
#include "safeguards.h"
|
#include "safeguards.h"
|
||||||
@@ -425,7 +426,26 @@ static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *grou
|
|||||||
SpriteID image = dts->ground.sprite;
|
SpriteID image = dts->ground.sprite;
|
||||||
PaletteID pal = dts->ground.pal;
|
PaletteID pal = dts->ground.pal;
|
||||||
|
|
||||||
if (GB(image, 0, SPRITE_WIDTH) != 0) {
|
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
|
||||||
|
if (IsTileOnWater(ti->tile)) {
|
||||||
|
DrawWaterClassGround(ti);
|
||||||
|
} else {
|
||||||
|
switch (GetObjectGroundType(ti->tile)) {
|
||||||
|
case OBJECT_GROUND_GRASS:
|
||||||
|
DrawClearLandTile(ti, GetObjectGroundDensity(ti->tile));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OBJECT_GROUND_SNOW_DESERT:
|
||||||
|
DrawGroundSprite(GetSpriteIDForSnowDesert(ti->tileh, GetObjectGroundDensity(ti->tile)), PAL_NONE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* This should never be reached, just draw a black sprite to make the problem clear without being unnecessarily punitive */
|
||||||
|
DrawGroundSprite(SPR_FLAT_BARE_LAND + SlopeToSpriteOffset(ti->tileh), PALETTE_ALL_BLACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (GB(image, 0, SPRITE_WIDTH) != 0) {
|
||||||
/* If the ground sprite is the default flat water sprite, draw also canal/river borders
|
/* 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'. */
|
* Do not do this if the tile's WaterClass is 'land'. */
|
||||||
if ((image == SPR_FLAT_WATER_TILE || spec->flags & OBJECT_FLAG_DRAW_WATER) && IsTileOnWater(ti->tile)) {
|
if ((image == SPR_FLAT_WATER_TILE || spec->flags & OBJECT_FLAG_DRAW_WATER) && IsTileOnWater(ti->tile)) {
|
||||||
|
@@ -40,6 +40,12 @@ enum ObjectFlags {
|
|||||||
};
|
};
|
||||||
DECLARE_ENUM_AS_BIT_SET(ObjectFlags)
|
DECLARE_ENUM_AS_BIT_SET(ObjectFlags)
|
||||||
|
|
||||||
|
enum ObjectCtrlFlags {
|
||||||
|
OBJECT_CTRL_FLAG_NONE = 0, ///< Just nothing.
|
||||||
|
OBJECT_CTRL_FLAG_USE_LAND_GROUND = 1 << 0, ///< Use land for ground sprite.
|
||||||
|
};
|
||||||
|
DECLARE_ENUM_AS_BIT_SET(ObjectCtrlFlags)
|
||||||
|
|
||||||
void ResetObjects();
|
void ResetObjects();
|
||||||
|
|
||||||
/** Class IDs for objects. */
|
/** Class IDs for objects. */
|
||||||
@@ -68,6 +74,7 @@ struct ObjectSpec {
|
|||||||
Date introduction_date; ///< From when can this object be built.
|
Date introduction_date; ///< From when can this object be built.
|
||||||
Date end_of_life_date; ///< When can't this object be built anymore.
|
Date end_of_life_date; ///< When can't this object be built anymore.
|
||||||
ObjectFlags flags; ///< Flags/settings related to the object.
|
ObjectFlags flags; ///< Flags/settings related to the object.
|
||||||
|
ObjectCtrlFlags ctrl_flags; ///< Extra control flags.
|
||||||
AnimationInfo animation; ///< Information about the animation.
|
AnimationInfo animation; ///< Information about the animation.
|
||||||
uint16 callback_mask; ///< Bitmask of requested/allowed callbacks.
|
uint16 callback_mask; ///< Bitmask of requested/allowed callbacks.
|
||||||
uint8 height; ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
|
uint8 height; ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
|
||||||
|
@@ -126,6 +126,9 @@ void BuildObject(ObjectType type, TileIndex tile, CompanyID owner, Town *town, u
|
|||||||
bool remove = IsDockingTile(t);
|
bool remove = IsDockingTile(t);
|
||||||
MakeObject(t, owner, o->index, wc, Random());
|
MakeObject(t, owner, o->index, wc, Random());
|
||||||
if (remove) RemoveDockingTile(t);
|
if (remove) RemoveDockingTile(t);
|
||||||
|
if ((spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) && wc == WATER_CLASS_INVALID) {
|
||||||
|
SetObjectGroundTypeDensity(t, OBJECT_GROUND_GRASS, 0);
|
||||||
|
}
|
||||||
MarkTileDirtyByTile(t, VMDF_NOT_MAP_MODE);
|
MarkTileDirtyByTile(t, VMDF_NOT_MAP_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,6 +743,84 @@ static void GetTileDesc_Object(TileIndex tile, TileDesc *td)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Convert to or from snowy tiles. */
|
||||||
|
static void TileLoopObjectGroundAlps(TileIndex tile)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
if ((int)TileHeight(tile) < GetSnowLine() - 1) {
|
||||||
|
/* Fast path to avoid needing to check all 4 corners */
|
||||||
|
k = -1;
|
||||||
|
} else {
|
||||||
|
k = GetTileZ(tile) - GetSnowLine() + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (k < 0) {
|
||||||
|
/* Below the snow line, do nothing if no snow. */
|
||||||
|
if (GetObjectGroundType(tile) != OBJECT_GROUND_SNOW_DESERT) return;
|
||||||
|
} else {
|
||||||
|
/* At or above the snow line, make snow tile if needed. */
|
||||||
|
if (GetObjectGroundType(tile) != OBJECT_GROUND_SNOW_DESERT) {
|
||||||
|
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_SNOW_DESERT, 0);
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Update snow density. */
|
||||||
|
uint current_density = GetObjectGroundDensity(tile);
|
||||||
|
uint req_density = (k < 0) ? 0u : std::min<uint>(k, 3u);
|
||||||
|
|
||||||
|
if (current_density < req_density) {
|
||||||
|
SetObjectGroundDensity(tile, current_density + 1);
|
||||||
|
} else if (current_density > req_density) {
|
||||||
|
SetObjectGroundDensity(tile, current_density - 1);
|
||||||
|
} else {
|
||||||
|
/* Density at the required level. */
|
||||||
|
if (k >= 0) return;
|
||||||
|
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_GRASS, 3);
|
||||||
|
}
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if at least one surrounding tile is non-desert
|
||||||
|
* @param tile tile to check
|
||||||
|
* @return does this tile have at least one non-desert tile around?
|
||||||
|
*/
|
||||||
|
static inline bool NeighbourIsNormal(TileIndex tile)
|
||||||
|
{
|
||||||
|
for (DiagDirection dir = DIAGDIR_BEGIN; dir < DIAGDIR_END; dir++) {
|
||||||
|
TileIndex t = tile + TileOffsByDiagDir(dir);
|
||||||
|
if (!IsValidTile(t)) continue;
|
||||||
|
if (GetTropicZone(t) != TROPICZONE_DESERT) return true;
|
||||||
|
if (HasTileWaterClass(t) && GetWaterClass(t) == WATER_CLASS_SEA) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void TileLoopObjectGroundDesert(TileIndex tile)
|
||||||
|
{
|
||||||
|
/* Current desert level - 0 if it is not desert */
|
||||||
|
uint current = 0;
|
||||||
|
if (GetObjectGroundType(tile) == OBJECT_GROUND_SNOW_DESERT) current = GetObjectGroundDensity(tile);
|
||||||
|
|
||||||
|
/* Expected desert level - 0 if it shouldn't be desert */
|
||||||
|
uint expected = 0;
|
||||||
|
if (GetTropicZone(tile) == TROPICZONE_DESERT) {
|
||||||
|
expected = NeighbourIsNormal(tile) ? 1 : 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == expected) return;
|
||||||
|
|
||||||
|
if (expected == 0) {
|
||||||
|
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_GRASS, 3);
|
||||||
|
} else {
|
||||||
|
/* Transition from clear to desert is not smooth (after clearing desert tile) */
|
||||||
|
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_SNOW_DESERT, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
MarkTileDirtyByTile(tile);
|
||||||
|
}
|
||||||
|
|
||||||
static void TileLoop_Object(TileIndex tile)
|
static void TileLoop_Object(TileIndex tile)
|
||||||
{
|
{
|
||||||
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
|
const ObjectSpec *spec = ObjectSpec::GetByTile(tile);
|
||||||
@@ -749,7 +830,29 @@ static void TileLoop_Object(TileIndex tile)
|
|||||||
if (o->location.tile == tile) TriggerObjectAnimation(o, OAT_256_TICKS, spec);
|
if (o->location.tile == tile) TriggerObjectAnimation(o, OAT_256_TICKS, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTileOnWater(tile)) TileLoop_Water(tile);
|
if (IsTileOnWater(tile)) {
|
||||||
|
TileLoop_Water(tile);
|
||||||
|
} else if (spec->ctrl_flags & OBJECT_CTRL_FLAG_USE_LAND_GROUND) {
|
||||||
|
switch (_settings_game.game_creation.landscape) {
|
||||||
|
case LT_TROPIC: TileLoopObjectGroundDesert(tile); break;
|
||||||
|
case LT_ARCTIC: TileLoopObjectGroundAlps(tile); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetObjectGroundType(tile) == OBJECT_GROUND_GRASS && GetObjectGroundDensity(tile) != 3) {
|
||||||
|
if (_game_mode != GM_EDITOR) {
|
||||||
|
if (GetObjectGroundCounter(tile) < 7) {
|
||||||
|
AddObjectGroundCounter(tile, 1);
|
||||||
|
} else {
|
||||||
|
SetObjectGroundCounter(tile, 0);
|
||||||
|
SetObjectGroundDensity(tile, GetObjectGroundDensity(tile) + 1);
|
||||||
|
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SetObjectGroundTypeDensity(tile, OBJECT_GROUND_GRASS, 3);
|
||||||
|
MarkTileDirtyByTile(tile, VMDF_NOT_MAP_MODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsObjectType(tile, OBJECT_HQ)) return;
|
if (!IsObjectType(tile, OBJECT_HQ)) return;
|
||||||
|
|
||||||
|
@@ -13,6 +13,11 @@
|
|||||||
#include "water_map.h"
|
#include "water_map.h"
|
||||||
#include "object_type.h"
|
#include "object_type.h"
|
||||||
|
|
||||||
|
enum ObjectGround {
|
||||||
|
OBJECT_GROUND_GRASS = 0, ///< Grass or bare
|
||||||
|
OBJECT_GROUND_SNOW_DESERT = 1, ///< Snow or desert
|
||||||
|
};
|
||||||
|
|
||||||
ObjectType GetObjectType(TileIndex t);
|
ObjectType GetObjectType(TileIndex t);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,6 +67,93 @@ static inline byte GetObjectRandomBits(TileIndex t)
|
|||||||
return _m[t].m3;
|
return _m[t].m3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ground type of ths tile.
|
||||||
|
* @param t The tile to get the ground type of.
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
* @return The ground type.
|
||||||
|
*/
|
||||||
|
static inline ObjectGround GetObjectGroundType(TileIndex t)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
return (ObjectGround)GB(_m[t].m4, 2, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ground density of this tile.
|
||||||
|
* Only meaningful for some ground types.
|
||||||
|
* @param t The tile to get the density of.
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
* @return the density
|
||||||
|
*/
|
||||||
|
static inline uint GetObjectGroundDensity(TileIndex t)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
return GB(_m[t].m4, 0, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ground density of this tile.
|
||||||
|
* Only meaningful for some ground types.
|
||||||
|
* @param t The tile to set the density of.
|
||||||
|
* @param d the new density
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
*/
|
||||||
|
static inline void SetObjectGroundDensity(TileIndex t, uint d)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
SB(_m[t].m4, 0, 2, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the counter used to advance to the next ground density type.
|
||||||
|
* @param t The tile to get the counter of.
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
* @return The value of the counter
|
||||||
|
*/
|
||||||
|
static inline uint GetObjectGroundCounter(TileIndex t)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
return GB(_m[t].m4, 5, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increments the counter used to advance to the next ground density type.
|
||||||
|
* @param t the tile to increment the counter of
|
||||||
|
* @param c the amount to increment the counter with
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
*/
|
||||||
|
static inline void AddObjectGroundCounter(TileIndex t, int c)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
_m[t].m4 += c << 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the counter used to advance to the next ground density type.
|
||||||
|
* @param t The tile to set the counter of.
|
||||||
|
* @param c The amount to set the counter to.
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
*/
|
||||||
|
static inline void SetObjectGroundCounter(TileIndex t, uint c)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
SB(_m[t].m4, 5, 3, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets ground type and density in one go, also sets the counter to 0
|
||||||
|
* @param t the tile to set the ground type and density for
|
||||||
|
* @param type the new ground type of the tile
|
||||||
|
* @param density the density of the ground tile
|
||||||
|
* @pre IsTileType(t, MP_OBJECT)
|
||||||
|
*/
|
||||||
|
static inline void SetObjectGroundTypeDensity(TileIndex t, ObjectGround type, uint density)
|
||||||
|
{
|
||||||
|
assert_tile(IsTileType(t, MP_OBJECT), t);
|
||||||
|
_m[t].m4 = 0 << 5 | type << 2 | density;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make an Object tile.
|
* Make an Object tile.
|
||||||
|
@@ -868,11 +868,15 @@ class NIHObject : public NIHelper {
|
|||||||
seprintf(buffer, lastof(buffer), " [%c] flags: 0x%X", output.flags & 1 ? '-' : '+', spec->flags);
|
seprintf(buffer, lastof(buffer), " [%c] flags: 0x%X", output.flags & 1 ? '-' : '+', spec->flags);
|
||||||
output.print(buffer);
|
output.print(buffer);
|
||||||
if (output.flags & 1) {
|
if (output.flags & 1) {
|
||||||
|
auto print = [&](const char *name) {
|
||||||
|
seprintf(buffer, lastof(buffer), " %s", name);
|
||||||
|
output.print(buffer);
|
||||||
|
};
|
||||||
auto check_flag = [&](ObjectFlags flag, const char *name) {
|
auto check_flag = [&](ObjectFlags flag, const char *name) {
|
||||||
if (spec->flags & flag) {
|
if (spec->flags & flag) print(name);
|
||||||
seprintf(buffer, lastof(buffer), " %s", name);
|
};
|
||||||
output.print(buffer);
|
auto check_ctrl_flag = [&](ObjectCtrlFlags flag, const char *name) {
|
||||||
}
|
if (spec->ctrl_flags & flag) print(name);
|
||||||
};
|
};
|
||||||
check_flag(OBJECT_FLAG_ONLY_IN_SCENEDIT, "OBJECT_FLAG_ONLY_IN_SCENEDIT");
|
check_flag(OBJECT_FLAG_ONLY_IN_SCENEDIT, "OBJECT_FLAG_ONLY_IN_SCENEDIT");
|
||||||
check_flag(OBJECT_FLAG_CANNOT_REMOVE, "OBJECT_FLAG_CANNOT_REMOVE");
|
check_flag(OBJECT_FLAG_CANNOT_REMOVE, "OBJECT_FLAG_CANNOT_REMOVE");
|
||||||
@@ -888,6 +892,7 @@ class NIHObject : public NIHelper {
|
|||||||
check_flag(OBJECT_FLAG_ALLOW_UNDER_BRIDGE, "OBJECT_FLAG_ALLOW_UNDER_BRIDGE");
|
check_flag(OBJECT_FLAG_ALLOW_UNDER_BRIDGE, "OBJECT_FLAG_ALLOW_UNDER_BRIDGE");
|
||||||
check_flag(OBJECT_FLAG_ANIM_RANDOM_BITS, "OBJECT_FLAG_ANIM_RANDOM_BITS");
|
check_flag(OBJECT_FLAG_ANIM_RANDOM_BITS, "OBJECT_FLAG_ANIM_RANDOM_BITS");
|
||||||
check_flag(OBJECT_FLAG_SCALE_BY_WATER, "OBJECT_FLAG_SCALE_BY_WATER");
|
check_flag(OBJECT_FLAG_SCALE_BY_WATER, "OBJECT_FLAG_SCALE_BY_WATER");
|
||||||
|
check_ctrl_flag(OBJECT_CTRL_FLAG_USE_LAND_GROUND, "OBJECT_CTRL_FLAG_USE_LAND_GROUND");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -121,7 +121,7 @@ static const DrawTileSprites _object_hq[] = {
|
|||||||
|
|
||||||
#undef TILE_SPRITE_LINE
|
#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, {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, height, 1, gen_amount, true }
|
||||||
|
|
||||||
/* Climates
|
/* Climates
|
||||||
* T = Temperate
|
* T = Temperate
|
||||||
|
Reference in New Issue
Block a user