Add road/tram type properties to set road vehicle collision mode

pull/491/head
Jonathan G Rennison 1 year ago
parent 39d38ecf19
commit 3497d0dcdb

@ -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,

@ -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);
@ -741,7 +746,7 @@ static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction d
return nullptr;
}
if (update_blocked_ctr && ++front->blocked_ctr > 1480 && (!_settings_game.vehicle.roadveh_cant_quantum_tunnel)) return nullptr;
if (update_blocked_ctr && ++front->blocked_ctr > 1480 && (!_settings_game.vehicle.roadveh_cant_quantum_tunnel)) return nullptr;
RoadVehicle *rv = RoadVehicle::From(rvf.best);
if (rv != nullptr && front->IsRoadVehicleOnLevelCrossing() && (rv->First()->cur_speed == 0 || rv->First()->IsRoadVehicleStopped())) return nullptr;
@ -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,

Loading…
Cancel
Save