summaryrefslogtreecommitdiff
path: root/src/road.cpp
diff options
context:
space:
mode:
authorpeter1138 <peter1138@openttd.org>2019-04-06 07:46:15 +0100
committerMichael Lutz <michi@icosahedron.de>2019-05-01 21:36:27 +0200
commitc02ef3e4564b7b54d49f0827d2d7625cbc38f335 (patch)
tree1c0ee62b6ce55124b247daaafa42300bfaa932e7 /src/road.cpp
parent21edf67f89c60351d5a0d84625455aa296b6b950 (diff)
downloadopenttd-c02ef3e4564b7b54d49f0827d2d7625cbc38f335.tar.xz
Feature: Add NotRoadTypes (NRT)
Diffstat (limited to 'src/road.cpp')
-rw-r--r--src/road.cpp226
1 files changed, 206 insertions, 20 deletions
diff --git a/src/road.cpp b/src/road.cpp
index 3700629ef..8c9591ff1 100644
--- a/src/road.cpp
+++ b/src/road.cpp
@@ -19,6 +19,9 @@
#include "engine_base.h"
#include "date_func.h"
#include "landscape.h"
+#include "road.h"
+#include "road_func.h"
+#include "roadveh.h"
#include "safeguards.h"
@@ -72,7 +75,7 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
/* Always connective */
connective = true;
} else {
- const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, ROADTYPE_ROAD) | GetAnyRoadBits(neighbor_tile, ROADTYPE_TRAM);
+ const RoadBits neighbor_rb = GetAnyRoadBits(neighbor_tile, RTT_ROAD) | GetAnyRoadBits(neighbor_tile, RTT_TRAM);
/* Accept only connective tiles */
connective = (neighbor_rb & mirrored_rb) != ROAD_NONE;
@@ -102,53 +105,236 @@ RoadBits CleanUpRoadBits(const TileIndex tile, RoadBits org_rb)
}
/**
- * Finds out, whether given company has all given RoadTypes available
+ * Finds out, whether given company has a given RoadType available for construction.
* @param company ID of company
- * @param rts RoadTypes to test
- * @return true if company has all requested RoadTypes available
+ * @param roadtypet RoadType to test
+ * @return true if company has the requested RoadType available
*/
-bool HasRoadTypesAvail(const CompanyID company, const RoadTypes rts)
+bool HasRoadTypeAvail(const CompanyID company, RoadType roadtype)
{
- RoadTypes avail_roadtypes;
-
if (company == OWNER_DEITY || company == OWNER_TOWN || _game_mode == GM_EDITOR || _generating_world) {
- avail_roadtypes = ROADTYPES_ROAD;
+ return true; // TODO: should there be a proper check?
} else {
- Company *c = Company::GetIfValid(company);
+ const Company *c = Company::GetIfValid(company);
if (c == nullptr) return false;
- avail_roadtypes = (RoadTypes)c->avail_roadtypes | ROADTYPES_ROAD; // road is available for always for everybody
+ return HasBit(c->avail_roadtypes & ~_roadtypes_hidden_mask, roadtype);
}
- return (rts & ~avail_roadtypes) == 0;
+}
+
+static RoadTypes GetMaskForRoadTramType(RoadTramType rtt)
+{
+ return rtt == RTT_TRAM ? _roadtypes_type : ~_roadtypes_type;
+}
+
+/**
+ * Test if any buildable RoadType is available for a company.
+ * @param company the company in question
+ * @return true if company has any RoadTypes available
+ */
+bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
+{
+ return (Company::Get(company)->avail_roadtypes & ~_roadtypes_hidden_mask & GetMaskForRoadTramType(rtt)) != ROADTYPES_NONE;
}
/**
* Validate functions for rail building.
- * @param rt road type to check.
+ * @param roadtype road type to check.
* @return true if the current company may build the road.
*/
-bool ValParamRoadType(const RoadType rt)
+bool ValParamRoadType(RoadType roadtype)
{
- return HasRoadTypesAvail(_current_company, RoadTypeToRoadTypes(rt));
+ return roadtype != INVALID_ROADTYPE && HasRoadTypeAvail(_current_company, roadtype);
+}
+
+/**
+ * Add the road types that are to be introduced at the given date.
+ * @param rt Roadtype
+ * @param current The currently available roadtypes.
+ * @param date The date for the introduction comparisons.
+ * @return The road types that should be available when date
+ * introduced road types are taken into account as well.
+ */
+RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date)
+{
+ RoadTypes rts = current;
+
+ for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
+ const RoadTypeInfo *rti = GetRoadTypeInfo(rt);
+ /* Unused road type. */
+ if (rti->label == 0) continue;
+
+ /* Not date introduced. */
+ if (!IsInsideMM(rti->introduction_date, 0, MAX_DAY)) continue;
+
+ /* Not yet introduced at this date. */
+ if (rti->introduction_date > date) continue;
+
+ /* Have we introduced all required roadtypes? */
+ RoadTypes required = rti->introduction_required_roadtypes;
+ if ((rts & required) != required) continue;
+
+ rts |= rti->introduces_roadtypes;
+ }
+
+ /* When we added roadtypes we need to run this method again; the added
+ * roadtypes might enable more rail types to become introduced. */
+ return rts == current ? rts : AddDateIntroducedRoadTypes(rts, date);
}
/**
* Get the road types the given company can build.
- * @param company the company to get the roadtypes for.
+ * @param company the company to get the road types for.
+ * @param introduces If true, include road types introduced by other road types
* @return the road types.
*/
-RoadTypes GetCompanyRoadtypes(CompanyID company)
+RoadTypes GetCompanyRoadTypes(CompanyID company, bool introduces)
{
- RoadTypes rt = ROADTYPES_NONE;
+ RoadTypes rts = ROADTYPES_NONE;
- Engine *e;
+ const Engine *e;
FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
const EngineInfo *ei = &e->info;
if (HasBit(ei->climates, _settings_game.game_creation.landscape) &&
(HasBit(e->company_avail, company) || _date >= e->intro_date + DAYS_IN_YEAR)) {
- SetBit(rt, HasBit(ei->misc_flags, EF_ROAD_TRAM) ? ROADTYPE_TRAM : ROADTYPE_ROAD);
+ const RoadVehicleInfo *rvi = &e->u.road;
+ assert(rvi->roadtype < ROADTYPE_END);
+ if (introduces) {
+ rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
+ } else {
+ SetBit(rts, rvi->roadtype);
+ }
+ }
+ }
+
+ if (introduces) return AddDateIntroducedRoadTypes(rts, _date);
+ return rts;
+}
+
+/**
+ * Get list of road types, regardless of company availability.
+ * @param introduces If true, include road types introduced by other road types
+ * @return the road types.
+ */
+RoadTypes GetRoadTypes(bool introduces)
+{
+ RoadTypes rts = ROADTYPES_NONE;
+
+ const Engine *e;
+ FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+ const EngineInfo *ei = &e->info;
+ if (!HasBit(ei->climates, _settings_game.game_creation.landscape)) continue;
+
+ const RoadVehicleInfo *rvi = &e->u.road;
+ assert(rvi->roadtype < ROADTYPE_END);
+ if (introduces) {
+ rts |= GetRoadTypeInfo(rvi->roadtype)->introduces_roadtypes;
+ } else {
+ SetBit(rts, rvi->roadtype);
}
}
- return rt;
+ if (introduces) return AddDateIntroducedRoadTypes(rts, MAX_DAY);
+ return rts;
+}
+
+/**
+ * Get the road type for a given label.
+ * @param label the roadtype label.
+ * @param allow_alternate_labels Search in the alternate label lists as well.
+ * @return the roadtype.
+ */
+RoadType GetRoadTypeByLabel(RoadTypeLabel label, bool allow_alternate_labels)
+{
+ /* Loop through each road type until the label is found */
+ for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
+ const RoadTypeInfo *rti = GetRoadTypeInfo(r);
+ if (rti->label == label) return r;
+ }
+
+ if (allow_alternate_labels) {
+ /* Test if any road type defines the label as an alternate. */
+ for (RoadType r = ROADTYPE_BEGIN; r != ROADTYPE_END; r++) {
+ const RoadTypeInfo *rti = GetRoadTypeInfo(r);
+ if (std::find(rti->alternate_labels.begin(), rti->alternate_labels.end(), label) != rti->alternate_labels.end()) return r;
+ }
+ }
+
+ /* No matching label was found, so it is invalid */
+ return INVALID_ROADTYPE;
+}
+
+/**
+ * Returns the available RoadSubTypes for the provided RoadType
+ * If the given company is valid then will be returned a list of the available sub types at the current date, while passing
+ * a deity company will make all the sub types available
+ * @param rt the RoadType to filter
+ * @param c the company ID to check the roadtype against
+ * @param any_date whether to return only currently introduced roadtypes or also future ones
+ * @returns the existing RoadSubTypes
+ */
+RoadTypes ExistingRoadTypes(CompanyID c)
+{
+ /* Check only players which can actually own vehicles, editor and gamescripts are considered deities */
+ if (c < OWNER_END) {
+ const Company *company = Company::GetIfValid(c);
+ if (company != nullptr) return company->avail_roadtypes;
+ }
+
+ RoadTypes known_roadtypes = ROADTYPES_NONE;
+
+ /* Find used roadtypes */
+ Engine *e;
+ FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+ /* Check if the roadtype can be used in the current climate */
+ if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
+
+ /* Check whether available for all potential companies */
+ if (e->company_avail != (CompanyMask)-1) continue;
+
+ known_roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
+ }
+
+ /* Get the date introduced roadtypes as well. */
+ known_roadtypes = AddDateIntroducedRoadTypes(known_roadtypes, MAX_DAY);
+
+ return known_roadtypes;
+}
+
+/**
+ * Check whether we can build infrastructure for the given RoadType. This to disable building stations etc. when
+ * you are not allowed/able to have the RoadType yet.
+ * @param roadtype the roadtype to check this for
+ * @param company the company id to check this for
+ * @param any_date to check only existing vehicles or if it is possible to build them in the future
+ * @return true if there is any reason why you may build the infrastructure for the given roadtype
+ */
+bool CanBuildRoadTypeInfrastructure(RoadType roadtype, CompanyID company)
+{
+ if (_game_mode != GM_EDITOR && !Company::IsValidID(company)) return false;
+ if (!_settings_client.gui.disable_unsuitable_building) return true;
+ if (!HasAnyRoadTypesAvail(company, GetRoadTramType(roadtype))) return false;
+
+ RoadTypes roadtypes = ExistingRoadTypes(company);
+
+ /* Check if the filtered roadtypes does have the roadtype we are checking for
+ * and if we can build new ones */
+ if (_settings_game.vehicle.max_roadveh > 0 && HasBit(roadtypes, roadtype)) {
+ /* Can we actually build the vehicle type? */
+ const Engine *e;
+ FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
+ if (!HasBit(e->company_avail, company)) continue;
+ if (HasPowerOnRoad(e->u.road.roadtype, roadtype) || HasPowerOnRoad(roadtype, e->u.road.roadtype)) return true;
+ }
+ return false;
+ }
+
+ /* We should be able to build infrastructure when we have the actual vehicle type */
+ const Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->type == VEH_ROAD && (company == OWNER_DEITY || v->owner == company) &&
+ HasBit(roadtypes, RoadVehicle::From(v)->roadtype) && HasPowerOnRoad(RoadVehicle::From(v)->roadtype, roadtype)) return true;
+ }
+
+ return false;
}