Add road/tram type properties to set road vehicle collision mode
This commit is contained in:
@@ -178,6 +178,19 @@
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>roadtype_collision_mode</td><td>ROADTYPE_COLLISION_MODE_XXX</td>
|
||||
<td>
|
||||
Sets the road vehicle collision mode for road vehicles of this road type.
|
||||
<dl>
|
||||
<dt>NORMAL</dt>
|
||||
<dd>Normal road vehicle collision rules (this is the default)</dd>
|
||||
<dt>NONE</dt>
|
||||
<dd>Do not collide at all with other road vehicles</dd>
|
||||
<dt>ELEVATED</dt>
|
||||
<dd>Collide only with other elevated road vehicles</dd>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 id="tramtype-properties"><a href="https://newgrf-specs.tt-wiki.net/wiki/NML:Tramtypes#Tramtype_properties">Tramtype properties</a></h3>
|
||||
<table>
|
||||
@@ -192,6 +205,19 @@
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>tramtype_collision_mode</td><td>TRAMTYPE_COLLISION_MODE_XXX</td>
|
||||
<td>
|
||||
Sets the road vehicle collision mode for road vehicles of this tram type.
|
||||
<dl>
|
||||
<dt>NORMAL</dt>
|
||||
<dd>Normal road vehicle collision rules (this is the default)</dd>
|
||||
<dt>NONE</dt>
|
||||
<dd>Do not collide at all with other road vehicles</dd>
|
||||
<dt>ELEVATED</dt>
|
||||
<dd>Collide only with other elevated road vehicles</dd>
|
||||
</dl>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<h3 id="object-ids"><a href="https://newgrf-specs.tt-wiki.net/wiki/NML:Objects#Object_IDs">Object IDs</a></h3>
|
||||
<p>
|
||||
|
@@ -330,6 +330,18 @@
|
||||
</table>
|
||||
</p>
|
||||
<p>This is indicated by the feature name: <font face="monospace">action0_roadtype_extra_flags</font>, version 1</p>
|
||||
<h4 id="roadtype_collision_mode">Road vehicle collision mode (mappable property: roadtype_collision_mode)</h4>
|
||||
<p>This property sets the road vehicle collision mode for road vehicles of this road/tram type.<br />
|
||||
The property length is 1 byte. The format is:
|
||||
<table>
|
||||
<tr><th>Value</th><th>Meaning</th></tr>
|
||||
<tr><td>0</td><td>Normal: Normal road vehicle collision rules (this is the default)</td></tr>
|
||||
<tr><td>1</td><td>None: Do not collide at all with other road vehicles</td></tr>
|
||||
<tr><td>2</td><td>Elevated: Collide only with other elevated road vehicles</td></tr>
|
||||
</table>
|
||||
Unknown values are ignored. More values may be added in future.
|
||||
</p>
|
||||
<p>This is indicated by the feature name: <font face="monospace">action0_roadtype_collision_mode</font>, version 1</p>
|
||||
<br />
|
||||
<h3 id="a0globalsettings"><a href="https://newgrf-specs.tt-wiki.net/wiki/Action0/Global_Settings">Action 0 - Global Settings</a></h3>
|
||||
<h4 id="global_extra_station_names">Extra station names (mappable property: global_extra_station_names)</h4>
|
||||
|
@@ -4813,6 +4813,13 @@ static ChangeInfoResult RoadTypeChangeInfo(uint id, int numinfo, int prop, const
|
||||
rti->extra_flags = (RoadTypeExtraFlags)buf->ReadByte();
|
||||
break;
|
||||
|
||||
case A0RPI_ROADTYPE_COLLISION_MODE: {
|
||||
if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
|
||||
uint8 collision_mode = buf->ReadByte();
|
||||
if (collision_mode < RTCM_END) rti->collision_mode = (RoadTypeCollisionMode)collision_mode;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
ret = HandleAction0PropertyDefault(buf, prop);
|
||||
break;
|
||||
@@ -4906,6 +4913,10 @@ static ChangeInfoResult RoadTypeReserveInfo(uint id, int numinfo, int prop, cons
|
||||
buf->Skip(buf->ReadExtendedByte());
|
||||
break;
|
||||
|
||||
case A0RPI_ROADTYPE_COLLISION_MODE:
|
||||
buf->Skip(buf->ReadExtendedByte());
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = HandleAction0PropertyDefault(buf, prop);
|
||||
break;
|
||||
@@ -11427,6 +11438,7 @@ static void AfterLoadGRFs()
|
||||
/* Set up custom rail types */
|
||||
InitRailTypes();
|
||||
InitRoadTypes();
|
||||
InitRoadTypesCaches();
|
||||
|
||||
for (Engine *e : Engine::IterateType(VEH_ROAD)) {
|
||||
if (_gted[e->index].rv_max_speed != 0) {
|
||||
|
@@ -39,6 +39,7 @@ extern const GRFFeatureInfo _grf_feature_list[] = {
|
||||
GRFFeatureInfo("action0_railtype_recolour", 1),
|
||||
GRFFeatureInfo("action0_railtype_extra_aspects", 1),
|
||||
GRFFeatureInfo("action0_roadtype_extra_flags", 1),
|
||||
GRFFeatureInfo("action0_roadtype_collision_mode", 1),
|
||||
GRFFeatureInfo("varaction2_railtype_signal_context", 1),
|
||||
GRFFeatureInfo("action0_global_extra_station_names", 2),
|
||||
GRFFeatureInfo("action0_global_default_object_generate_amount", 1),
|
||||
@@ -83,7 +84,9 @@ extern const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
|
||||
GRFPropertyMapDefinition(GSF_RAILTYPES, A0RPI_RAILTYPE_ENABLE_SIGNAL_RECOLOUR, "railtype_enable_signal_recolour"),
|
||||
GRFPropertyMapDefinition(GSF_RAILTYPES, A0RPI_RAILTYPE_EXTRA_ASPECTS, "railtype_extra_aspects"),
|
||||
GRFPropertyMapDefinition(GSF_ROADTYPES, A0RPI_ROADTYPE_EXTRA_FLAGS, "roadtype_extra_flags"),
|
||||
GRFPropertyMapDefinition(GSF_ROADTYPES, A0RPI_ROADTYPE_COLLISION_MODE, "roadtype_collision_mode"),
|
||||
GRFPropertyMapDefinition(GSF_TRAMTYPES, A0RPI_ROADTYPE_EXTRA_FLAGS, "roadtype_extra_flags"),
|
||||
GRFPropertyMapDefinition(GSF_TRAMTYPES, A0RPI_ROADTYPE_COLLISION_MODE, "roadtype_collision_mode"),
|
||||
GRFPropertyMapDefinition(GSF_GLOBALVAR, A0RPI_GLOBALVAR_EXTRA_STATION_NAMES, "global_extra_station_names"),
|
||||
GRFPropertyMapDefinition(GSF_GLOBALVAR, A0RPI_GLOBALVAR_EXTRA_STATION_NAMES_PROBABILITY, "global_extra_station_names_probability"),
|
||||
GRFPropertyMapDefinition(GSF_GLOBALVAR, A0RPI_GLOBALVAR_LIGHTHOUSE_GENERATE_AMOUNT, "global_lighthouse_generate_amount"),
|
||||
|
@@ -26,6 +26,7 @@ enum Action0RemapPropertyIds {
|
||||
A0RPI_RAILTYPE_ENABLE_SIGNAL_RECOLOUR,
|
||||
A0RPI_RAILTYPE_EXTRA_ASPECTS,
|
||||
A0RPI_ROADTYPE_EXTRA_FLAGS,
|
||||
A0RPI_ROADTYPE_COLLISION_MODE,
|
||||
A0RPI_GLOBALVAR_EXTRA_STATION_NAMES,
|
||||
A0RPI_GLOBALVAR_EXTRA_STATION_NAMES_PROBABILITY,
|
||||
A0RPI_GLOBALVAR_LIGHTHOUSE_GENERATE_AMOUNT,
|
||||
|
15
src/road.h
15
src/road.h
@@ -62,6 +62,14 @@ enum RoadTypeExtraFlags {
|
||||
};
|
||||
DECLARE_ENUM_AS_BIT_SET(RoadTypeExtraFlags)
|
||||
|
||||
enum RoadTypeCollisionMode : uint8 {
|
||||
RTCM_NORMAL = 0,
|
||||
RTCM_NONE,
|
||||
RTCM_ELEVATED,
|
||||
|
||||
RTCM_END,
|
||||
};
|
||||
|
||||
struct SpriteGroup;
|
||||
|
||||
/** Sprite groups for a roadtype. */
|
||||
@@ -140,6 +148,11 @@ public:
|
||||
*/
|
||||
RoadTypeExtraFlags extra_flags;
|
||||
|
||||
/**
|
||||
* Collision mode
|
||||
*/
|
||||
RoadTypeCollisionMode collision_mode;
|
||||
|
||||
/**
|
||||
* Cost multiplier for building this road type
|
||||
*/
|
||||
@@ -316,10 +329,12 @@ RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels = t
|
||||
|
||||
void ResetRoadTypes();
|
||||
void InitRoadTypes();
|
||||
void InitRoadTypesCaches();
|
||||
RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt);
|
||||
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt);
|
||||
|
||||
extern std::vector<RoadType> _sorted_roadtypes;
|
||||
extern RoadTypes _roadtypes_hidden_mask;
|
||||
extern std::array<RoadTypes, RTCM_END> _collision_mode_roadtypes;
|
||||
|
||||
#endif /* ROAD_H */
|
||||
|
@@ -51,6 +51,7 @@ typedef std::vector<RoadVehicle *> RoadVehicleList;
|
||||
RoadTypeInfo _roadtypes[ROADTYPE_END];
|
||||
std::vector<RoadType> _sorted_roadtypes;
|
||||
RoadTypes _roadtypes_hidden_mask;
|
||||
std::array<RoadTypes, RTCM_END> _collision_mode_roadtypes;
|
||||
|
||||
/**
|
||||
* Bitmap of road/tram types.
|
||||
@@ -72,7 +73,7 @@ void ResetRoadTypes()
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, {}, {}, 0, {}, {} },
|
||||
ROADTYPES_NONE, ROTFB_NONE, RXTFB_NONE, 0, 0, 0, 0,
|
||||
ROADTYPES_NONE, ROTFB_NONE, RXTFB_NONE, RTCM_NORMAL, 0, 0, 0, 0,
|
||||
RoadTypeLabelList(), 0, 0, ROADTYPES_NONE, ROADTYPES_NONE, 0,
|
||||
{}, {} };
|
||||
for (; i < lengthof(_roadtypes); i++) _roadtypes[i] = empty_roadtype;
|
||||
@@ -134,6 +135,16 @@ void InitRoadTypes()
|
||||
std::sort(_sorted_roadtypes.begin(), _sorted_roadtypes.end(), CompareRoadTypes);
|
||||
}
|
||||
|
||||
void InitRoadTypesCaches()
|
||||
{
|
||||
std::fill(_collision_mode_roadtypes.begin(), _collision_mode_roadtypes.end(), ROADTYPES_NONE);
|
||||
|
||||
for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
|
||||
const RoadTypeInfo &rti = _roadtypes[rt];
|
||||
SetBit(_collision_mode_roadtypes[rti.collision_mode], rt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new road type label
|
||||
*/
|
||||
@@ -149,6 +160,7 @@ RoadType AllocateRoadType(RoadTypeLabel label, RoadTramType rtt)
|
||||
rti->alternate_labels.clear();
|
||||
rti->flags = ROTFB_NONE;
|
||||
rti->extra_flags = RXTFB_NONE;
|
||||
rti->collision_mode = RTCM_NORMAL;
|
||||
rti->introduction_date = INVALID_DATE;
|
||||
|
||||
/* Make us compatible with ourself. */
|
||||
|
@@ -681,6 +681,7 @@ struct RoadVehFindData {
|
||||
Vehicle *best;
|
||||
uint best_diff;
|
||||
Direction dir;
|
||||
RoadTypeCollisionMode collision_mode;
|
||||
};
|
||||
|
||||
static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
||||
@@ -697,6 +698,7 @@ static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
||||
abs(v->z_pos - rvf->veh->z_pos) < 6 &&
|
||||
v->direction == rvf->dir &&
|
||||
rvf->veh->First() != v->First() &&
|
||||
HasBit(_collision_mode_roadtypes[rvf->collision_mode], RoadVehicle::From(v)->roadtype) &&
|
||||
(dist_x[v->direction] >= 0 || (x_diff > dist_x[v->direction] && x_diff <= 0)) &&
|
||||
(dist_x[v->direction] <= 0 || (x_diff < dist_x[v->direction] && x_diff >= 0)) &&
|
||||
(dist_y[v->direction] >= 0 || (y_diff > dist_y[v->direction] && y_diff <= 0)) &&
|
||||
@@ -714,16 +716,19 @@ static Vehicle *EnumCheckRoadVehClose(Vehicle *v, void *data)
|
||||
|
||||
static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction dir, bool update_blocked_ctr = true)
|
||||
{
|
||||
RoadVehFindData rvf;
|
||||
RoadVehicle *front = v->First();
|
||||
RoadTypeCollisionMode collision_mode = GetRoadTypeInfo(v->roadtype)->collision_mode;
|
||||
if (collision_mode == RTCM_NONE) return nullptr;
|
||||
|
||||
RoadVehicle *front = v->First();
|
||||
if (front->reverse_ctr != 0) return nullptr;
|
||||
|
||||
RoadVehFindData rvf;
|
||||
rvf.x = x;
|
||||
rvf.y = y;
|
||||
rvf.dir = dir;
|
||||
rvf.veh = v;
|
||||
rvf.best_diff = UINT_MAX;
|
||||
rvf.collision_mode = collision_mode;
|
||||
|
||||
if (front->state == RVSB_WORMHOLE) {
|
||||
FindVehicleOnPos(v->tile, VEH_ROAD, &rvf, EnumCheckRoadVehClose);
|
||||
@@ -845,6 +850,7 @@ struct OvertakeData {
|
||||
Trackdir trackdir;
|
||||
int tunnelbridge_min;
|
||||
int tunnelbridge_max;
|
||||
RoadTypeCollisionMode collision_mode;
|
||||
};
|
||||
|
||||
static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
|
||||
@@ -852,6 +858,7 @@ static Vehicle *EnumFindVehBlockingOvertake(Vehicle *v, void *data)
|
||||
const OvertakeData *od = (OvertakeData*)data;
|
||||
|
||||
if (v->First() == od->u || v->First() == od->v) return nullptr;
|
||||
if (!HasBit(_collision_mode_roadtypes[od->collision_mode], RoadVehicle::From(v)->roadtype)) return nullptr;
|
||||
if (RoadVehicle::From(v)->overtaking != 0 || v->direction != od->v->direction) return v;
|
||||
|
||||
/* Check if other vehicle is behind */
|
||||
@@ -896,6 +903,7 @@ static Vehicle *EnumFindVehBlockingOvertakeBehind(Vehicle *v, void *data)
|
||||
const OvertakeData *od = (OvertakeData*)data;
|
||||
|
||||
if (v->First() == od->u || v->First() == od->v) return nullptr;
|
||||
if (!HasBit(_collision_mode_roadtypes[od->collision_mode], RoadVehicle::From(v)->roadtype)) return nullptr;
|
||||
if (RoadVehicle::From(v)->overtaking != 0 && TileVirtXY(v->x_pos, v->y_pos) == od->tile) return v;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1040,6 +1048,7 @@ static void RoadVehCheckOvertake(RoadVehicle *v, RoadVehicle *u)
|
||||
od.v = v;
|
||||
od.u = u;
|
||||
od.trackdir = DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
|
||||
od.collision_mode = GetRoadTypeInfo(v->roadtype)->collision_mode;
|
||||
|
||||
/* Are the current and the next tile suitable for overtaking?
|
||||
* - Does the track continue along od.trackdir
|
||||
@@ -1447,6 +1456,7 @@ struct FinishOvertakeData {
|
||||
int min_coord;
|
||||
int max_coord;
|
||||
uint8 not_road_pos;
|
||||
RoadTypeCollisionMode collision_mode;
|
||||
};
|
||||
|
||||
static Vehicle *EnumFindVehBlockingFinishOvertake(Vehicle *v, void *data)
|
||||
@@ -1454,6 +1464,7 @@ static Vehicle *EnumFindVehBlockingFinishOvertake(Vehicle *v, void *data)
|
||||
const FinishOvertakeData *od = (FinishOvertakeData*)data;
|
||||
|
||||
if (v->First() == od->v) return nullptr;
|
||||
if (!HasBit(_collision_mode_roadtypes[od->collision_mode], RoadVehicle::From(v)->roadtype)) return nullptr;
|
||||
|
||||
/* Check if other vehicle is behind */
|
||||
switch (DirToDiagDir(v->direction)) {
|
||||
@@ -1484,6 +1495,8 @@ static void RoadVehCheckFinishOvertake(RoadVehicle *v)
|
||||
FinishOvertakeData od;
|
||||
od.direction = v->direction;
|
||||
od.v = v;
|
||||
od.collision_mode = GetRoadTypeInfo(v->roadtype)->collision_mode;
|
||||
|
||||
const RoadVehicle *last = v->Last();
|
||||
const int front_margin = 10;
|
||||
const int back_margin = 10;
|
||||
|
@@ -4270,6 +4270,8 @@ void ReloadNewGRFData()
|
||||
|
||||
UpdateExtraAspectsVariable();
|
||||
|
||||
InitRoadTypesCaches();
|
||||
|
||||
ReInitAllWindows(false);
|
||||
|
||||
/* Update company statistics. */
|
||||
|
@@ -1795,6 +1795,8 @@ class NIHRoadType : public NIHelper {
|
||||
HasBit(rti->extra_flags, RXTF_NOT_AVAILABLE_AI_GS) ? 's' : '-',
|
||||
HasBit(rti->extra_flags, RXTF_NO_TOWN_MODIFICATION) ? 't' : '-');
|
||||
output.print(buffer);
|
||||
seprintf(buffer, lastof(buffer), " Collision mode: %u", rti->collision_mode);
|
||||
output.print(buffer);
|
||||
seprintf(buffer, lastof(buffer), " Powered: 0x" OTTD_PRINTFHEX64, rti->powered_roadtypes);
|
||||
output.print(buffer);
|
||||
PrintTypeLabels(buffer, lastof(buffer), rti->label, (const uint32*) rti->alternate_labels.data(), rti->alternate_labels.size(), output.print);
|
||||
|
@@ -66,6 +66,9 @@ static const RoadTypeInfo _original_roadtypes[] = {
|
||||
/* extra flags */
|
||||
RXTFB_NONE,
|
||||
|
||||
/* collision mode */
|
||||
RTCM_NORMAL,
|
||||
|
||||
/* cost multiplier */
|
||||
8,
|
||||
|
||||
@@ -149,6 +152,9 @@ static const RoadTypeInfo _original_roadtypes[] = {
|
||||
/* extra flags */
|
||||
RXTFB_NONE,
|
||||
|
||||
/* collision mode */
|
||||
RTCM_NORMAL,
|
||||
|
||||
/* cost multiplier */
|
||||
16,
|
||||
|
||||
|
Reference in New Issue
Block a user