Add NewGRF object property for new edge foundation mode
This commit is contained in:
@@ -4301,6 +4301,14 @@ static ChangeInfoResult ObjectChangeInfo(uint id, int numinfo, int prop, const G
|
||||
SB(spec->ctrl_flags, OBJECT_CTRL_FLAG_USE_LAND_GROUND, 1, (buf->ReadByte() != 0 ? 1 : 0));
|
||||
break;
|
||||
|
||||
case A0RPI_OBJECT_EDGE_FOUNDATION_MODE:
|
||||
if (MappedPropertyLengthMismatch(buf, 4, mapping_entry)) break;
|
||||
SetBit(spec->ctrl_flags, OBJECT_CTRL_FLAG_EDGE_FOUNDATION);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
spec->edge_foundation[i] = buf->ReadByte();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = HandleAction0PropertyDefault(buf, prop);
|
||||
break;
|
||||
|
@@ -68,6 +68,7 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
|
||||
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR, "signals_enable_signal_recolour"),
|
||||
GRFPropertyMapDefinition(GSF_SIGNALS, A0RPI_SIGNALS_EXTRA_ASPECTS, "signals_extra_aspects"),
|
||||
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(),
|
||||
};
|
||||
|
||||
|
@@ -33,6 +33,7 @@ enum Action0RemapPropertyIds {
|
||||
A0RPI_SIGNALS_ENABLE_SIGNAL_RECOLOUR,
|
||||
A0RPI_SIGNALS_EXTRA_ASPECTS,
|
||||
A0RPI_OBJECT_USE_LAND_GROUND,
|
||||
A0RPI_OBJECT_EDGE_FOUNDATION_MODE,
|
||||
};
|
||||
|
||||
|
||||
|
@@ -418,7 +418,7 @@ uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, cons
|
||||
* @param group The group of sprites to draw.
|
||||
* @param spec Object spec to draw.
|
||||
*/
|
||||
static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *group, const ObjectSpec *spec)
|
||||
static void DrawTileLayout(TileInfo *ti, const TileLayoutSpriteGroup *group, const ObjectSpec *spec, int building_z_offset)
|
||||
{
|
||||
const DrawTileSprites *dts = group->ProcessRegisters(nullptr);
|
||||
PaletteID palette = ((spec->flags & OBJECT_FLAG_2CC_COLOUR) ? SPR_2CCMAP_BASE : PALETTE_RECOLOUR_START) + Object::GetByTile(ti->tile)->colour;
|
||||
@@ -455,7 +455,9 @@ static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *grou
|
||||
}
|
||||
}
|
||||
|
||||
if (building_z_offset) ti->z += building_z_offset;
|
||||
DrawNewGRFTileSeq(ti, dts, TO_STRUCTURES, 0, palette);
|
||||
if (building_z_offset) ti->z -= building_z_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -463,7 +465,7 @@ static void DrawTileLayout(const TileInfo *ti, const TileLayoutSpriteGroup *grou
|
||||
* @param ti Information about the tile to draw on.
|
||||
* @param spec Object spec to draw.
|
||||
*/
|
||||
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
|
||||
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec, int building_z_offset)
|
||||
{
|
||||
Object *o = Object::GetByTile(ti->tile);
|
||||
ObjectResolverObject object(spec, o, ti->tile);
|
||||
@@ -471,7 +473,7 @@ void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec)
|
||||
const SpriteGroup *group = object.Resolve();
|
||||
if (group == nullptr || group->type != SGT_TILELAYOUT) return;
|
||||
|
||||
DrawTileLayout(ti, (const TileLayoutSpriteGroup *)group, spec);
|
||||
DrawTileLayout(ti, (const TileLayoutSpriteGroup *)group, spec, building_z_offset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -43,9 +43,17 @@ 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.
|
||||
OBJECT_CTRL_FLAG_EDGE_FOUNDATION = 1 << 2, ///< Use edge foundation mode.
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(ObjectCtrlFlags)
|
||||
|
||||
enum ObjectEdgeFoundationFlags {
|
||||
/* Bits 0 and 1 use for edge DiagDirection */
|
||||
OBJECT_EF_FLAG_ADJUST_Z = 1 << 2, ///< Adjust sprite z position to z at edge.
|
||||
OBJECT_EF_FLAG_FOUNDATION_LOWER = 1 << 3, ///< If edge is lower than tile max z, add foundation.
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(ObjectEdgeFoundationFlags)
|
||||
|
||||
void ResetObjects();
|
||||
|
||||
/** Class IDs for objects. */
|
||||
@@ -75,6 +83,7 @@ struct ObjectSpec {
|
||||
Date end_of_life_date; ///< When can't this object be built anymore.
|
||||
ObjectFlags flags; ///< Flags/settings related to the object.
|
||||
ObjectCtrlFlags ctrl_flags; ///< Extra control flags.
|
||||
uint8 edge_foundation[4]; ///< Edge foundation flags
|
||||
AnimationInfo animation; ///< Information about the animation.
|
||||
uint16 callback_mask; ///< Bitmask of requested/allowed callbacks.
|
||||
uint8 height; ///< The height of this structure, in heightlevels; max MAX_TILE_HEIGHT.
|
||||
@@ -167,7 +176,7 @@ static const CargoID CT_PURCHASE_OBJECT = 1;
|
||||
|
||||
uint16 GetObjectCallback(CallbackID callback, uint32 param1, uint32 param2, const ObjectSpec *spec, Object *o, TileIndex tile, uint8 view = 0);
|
||||
|
||||
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec);
|
||||
void DrawNewObjectTile(TileInfo *ti, const ObjectSpec *spec, int building_z_offset);
|
||||
void DrawNewObjectTileInGUI(int x, int y, const ObjectSpec *spec, uint8 view);
|
||||
void AnimateNewObjectTile(TileIndex tile);
|
||||
uint8 GetNewObjectTileAnimationSpeed(TileIndex tile);
|
||||
|
@@ -517,13 +517,34 @@ static Foundation GetFoundation_Object(TileIndex tile, Slope tileh);
|
||||
|
||||
static void DrawTile_Object(TileInfo *ti, DrawTileProcParams params)
|
||||
{
|
||||
ObjectType type = GetObjectType(ti->tile);
|
||||
const Object *obj = Object::GetByTile(ti->tile);
|
||||
ObjectType type = obj->type;
|
||||
const ObjectSpec *spec = ObjectSpec::Get(type);
|
||||
|
||||
/* Fall back for when the object doesn't exist anymore. */
|
||||
if (!spec->enabled) type = OBJECT_TRANSMITTER;
|
||||
int building_z_offset = 0;
|
||||
|
||||
if ((spec->flags & OBJECT_FLAG_HAS_NO_FOUNDATION) == 0) DrawFoundation(ti, GetFoundation_Object(ti->tile, ti->tileh));
|
||||
/* Fall back for when the object doesn't exist anymore. */
|
||||
if (!spec->enabled) {
|
||||
type = OBJECT_TRANSMITTER;
|
||||
} else if ((spec->flags & OBJECT_FLAG_HAS_NO_FOUNDATION) == 0) {
|
||||
if (spec->ctrl_flags & OBJECT_CTRL_FLAG_EDGE_FOUNDATION) {
|
||||
uint8 flags = spec->edge_foundation[obj->view];
|
||||
DiagDirection edge = (DiagDirection)GB(flags, 0, 2);
|
||||
Slope incline = InclinedSlope(edge);
|
||||
if (IsSteepSlope(ti->tileh) || IsOddParity(incline & ti->tileh)) {
|
||||
/* Steep slope, or odd number of matching bits indicating that edge is not level */
|
||||
DrawFoundation(ti, GetFoundation_Object(ti->tile, ti->tileh));
|
||||
} else if (flags & OBJECT_EF_FLAG_FOUNDATION_LOWER && !(ti->tileh & incline)) {
|
||||
/* The edge is the lower edge of an inclined slope */
|
||||
DrawFoundation(ti, GetFoundation_Object(ti->tile, ti->tileh));
|
||||
} else if (flags & OBJECT_EF_FLAG_ADJUST_Z && ti->tileh & incline) {
|
||||
/* The edge is elevated relative to the lowest tile height, adjust z */
|
||||
building_z_offset = TILE_HEIGHT;
|
||||
}
|
||||
} else {
|
||||
DrawFoundation(ti, GetFoundation_Object(ti->tile, ti->tileh));
|
||||
}
|
||||
}
|
||||
|
||||
if (type < NEW_OBJECT_OFFSET) {
|
||||
const DrawTileSprites *dts = nullptr;
|
||||
@@ -564,7 +585,7 @@ static void DrawTile_Object(TileInfo *ti, DrawTileProcParams params)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DrawNewObjectTile(ti, spec);
|
||||
DrawNewObjectTile(ti, spec, building_z_offset);
|
||||
}
|
||||
|
||||
DrawBridgeMiddle(ti);
|
||||
@@ -1065,6 +1086,16 @@ static void ChangeTileOwner_Object(TileIndex tile, Owner old_owner, Owner new_ow
|
||||
}
|
||||
}
|
||||
|
||||
static int GetObjectEffectiveZ(TileIndex tile, const ObjectSpec *spec, int z, Slope tileh)
|
||||
{
|
||||
if ((spec->ctrl_flags & OBJECT_CTRL_FLAG_EDGE_FOUNDATION) && !(spec->flags & OBJECT_FLAG_HAS_NO_FOUNDATION)) {
|
||||
uint8 flags = spec->edge_foundation[Object::GetByTile(tile)->view];
|
||||
DiagDirection edge = (DiagDirection)GB(flags, 0, 2);
|
||||
if (!(flags & OBJECT_EF_FLAG_FOUNDATION_LOWER) && !(tileh & InclinedSlope(edge))) return z;
|
||||
}
|
||||
return z + GetSlopeMaxZ(tileh);
|
||||
}
|
||||
|
||||
static CommandCost TerraformTile_Object(TileIndex tile, DoCommandFlag flags, int z_new, Slope tileh_new)
|
||||
{
|
||||
ObjectType type = GetObjectType(tile);
|
||||
@@ -1080,10 +1111,11 @@ static CommandCost TerraformTile_Object(TileIndex tile, DoCommandFlag flags, int
|
||||
* - Allow autoslope by default.
|
||||
* - Disallow autoslope if callback succeeds and returns non-zero.
|
||||
*/
|
||||
Slope tileh_old = GetTileSlope(tile);
|
||||
/* TileMaxZ must not be changed. Slopes must not be steep. */
|
||||
if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
|
||||
int z_old;
|
||||
Slope tileh_old = GetTileSlope(tile, &z_old);
|
||||
const ObjectSpec *spec = ObjectSpec::Get(type);
|
||||
/* Object height must not be changed. Slopes must not be steep. */
|
||||
if (!IsSteepSlope(tileh_old) && !IsSteepSlope(tileh_new) && (GetObjectEffectiveZ(tile, spec, z_old, tileh_old) == GetObjectEffectiveZ(tile, spec, z_new, tileh_new))) {
|
||||
|
||||
/* Call callback 'disable autosloping for objects'. */
|
||||
if (HasBit(spec->callback_mask, CBM_OBJ_AUTOSLOPE)) {
|
||||
|
@@ -897,6 +897,7 @@ class NIHObject : public NIHelper {
|
||||
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_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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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, 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 }
|
||||
|
||||
/* Climates
|
||||
* T = Temperate
|
||||
|
Reference in New Issue
Block a user