diff --git a/src/script/api/script_airport.cpp b/src/script/api/script_airport.cpp index 5ecaa390ee..6513a1d205 100644 --- a/src/script/api/script_airport.cpp +++ b/src/script/api/script_airport.cpp @@ -91,6 +91,7 @@ /* static */ SQInteger ScriptAirport::GetNumHangars(TileIndex tile) { + EnforceDeityOrCompanyModeValid(-1); if (!::IsValidTile(tile)) return -1; if (!::IsTileType(tile, MP_STATION)) return -1; @@ -103,6 +104,7 @@ /* static */ TileIndex ScriptAirport::GetHangarOfAirport(TileIndex tile) { + EnforceDeityOrCompanyModeValid(INVALID_TILE); if (!::IsValidTile(tile)) return INVALID_TILE; if (!::IsTileType(tile, MP_STATION)) return INVALID_TILE; if (GetNumHangars(tile) < 1) return INVALID_TILE; diff --git a/src/script/api/script_basestation.cpp b/src/script/api/script_basestation.cpp index fe5dc5d3d2..408543ae8a 100644 --- a/src/script/api/script_basestation.cpp +++ b/src/script/api/script_basestation.cpp @@ -21,6 +21,7 @@ /* static */ bool ScriptBaseStation::IsValidBaseStation(StationID station_id) { + EnforceDeityOrCompanyModeValid(false); const BaseStation *st = ::BaseStation::GetIfValid(station_id); return st != nullptr && (st->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity() || st->owner == OWNER_NONE); } diff --git a/src/script/api/script_bridge.cpp b/src/script/api/script_bridge.cpp index e34d14d18f..1ec873204e 100644 --- a/src/script/api/script_bridge.cpp +++ b/src/script/api/script_bridge.cpp @@ -72,6 +72,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance) /* static */ bool ScriptBridge::BuildBridge(ScriptVehicle::VehicleType vehicle_type, BridgeID bridge_id, TileIndex start, TileIndex end) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, start != end); EnforcePrecondition(false, ::IsValidTile(start) && ::IsValidTile(end)); EnforcePrecondition(false, TileX(start) == TileX(end) || TileY(start) == TileY(end)); @@ -95,6 +96,8 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance) /* static */ bool ScriptBridge::_BuildBridgeRoad1() { + EnforceDeityOrCompanyModeValid(false); + /* Build the piece of road on the 'start' side of the bridge */ TileIndex end = ScriptObject::GetCallbackVariable(0); TileIndex start = ScriptObject::GetCallbackVariable(1); @@ -107,6 +110,8 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance) /* static */ bool ScriptBridge::_BuildBridgeRoad2() { + EnforceDeityOrCompanyModeValid(false); + /* Build the piece of road on the 'end' side of the bridge */ TileIndex end = ScriptObject::GetCallbackVariable(0); TileIndex start = ScriptObject::GetCallbackVariable(1); diff --git a/src/script/api/script_depotlist.cpp b/src/script/api/script_depotlist.cpp index 6f86ade5f4..2e1dc6fc98 100644 --- a/src/script/api/script_depotlist.cpp +++ b/src/script/api/script_depotlist.cpp @@ -16,6 +16,7 @@ ScriptDepotList::ScriptDepotList(ScriptTile::TransportType transport_type) { + EnforceDeityOrCompanyModeValid_Void(); ::TileType tile_type; switch (transport_type) { default: return; diff --git a/src/script/api/script_engine.cpp b/src/script/api/script_engine.cpp index 2d59df5006..17845ae4fe 100644 --- a/src/script/api/script_engine.cpp +++ b/src/script/api/script_engine.cpp @@ -24,6 +24,7 @@ /* static */ bool ScriptEngine::IsValidEngine(EngineID engine_id) { + EnforceDeityOrCompanyModeValid(false); const Engine *e = ::Engine::GetIfValid(engine_id); if (e == nullptr || !e->IsEnabled()) return false; @@ -35,6 +36,7 @@ /* static */ bool ScriptEngine::IsBuildable(EngineID engine_id) { + EnforceDeityOrCompanyModeValid(false); const Engine *e = ::Engine::GetIfValid(engine_id); return e != nullptr && ::IsEngineBuildable(engine_id, e->type, ScriptObject::GetCompany()); } diff --git a/src/script/api/script_enginelist.cpp b/src/script/api/script_enginelist.cpp index 9a98d9cb9b..9ba725dfd0 100644 --- a/src/script/api/script_enginelist.cpp +++ b/src/script/api/script_enginelist.cpp @@ -15,6 +15,7 @@ ScriptEngineList::ScriptEngineList(ScriptVehicle::VehicleType vehicle_type) { + EnforceDeityOrCompanyModeValid_Void(); for (const Engine *e : Engine::IterateType((::VehicleType)vehicle_type)) { if (ScriptCompanyMode::IsDeity() || HasBit(e->company_avail, ScriptObject::GetCompany())) this->AddItem(e->index); } diff --git a/src/script/api/script_error.hpp b/src/script/api/script_error.hpp index 3b2ecc0ccf..f4adb84cec 100644 --- a/src/script/api/script_error.hpp +++ b/src/script/api/script_error.hpp @@ -62,6 +62,23 @@ #define EnforceDeityMode(returnval) \ EnforcePreconditionCustomError(returnval, ScriptCompanyMode::IsDeity(), ScriptError::ERR_PRECONDITION_INVALID_COMPANY) +/** + * Helper to enforce the precondition that the company mode is valid or that we are a deity. + * @param returnval The value to return on failure. + */ +#define EnforceDeityOrCompanyModeValid(returnval) \ + EnforcePreconditionCustomError(returnval, ScriptCompanyMode::IsDeity() || ScriptCompanyMode::IsValid(), ScriptError::ERR_PRECONDITION_INVALID_COMPANY) + +/** + * Helper to enforce the precondition that the company mode is valid or that we are a deity. + */ +#define EnforceDeityOrCompanyModeValid_Void() \ + if (!(ScriptCompanyMode::IsDeity() || ScriptCompanyMode::IsValid())) { \ + ScriptObject::SetLastError(ScriptError::ERR_PRECONDITION_INVALID_COMPANY); \ + return; \ + } + + /** * Class that handles all error related functions. * @api ai game diff --git a/src/script/api/script_game.cpp b/src/script/api/script_game.cpp index 3df6aef154..d338837f14 100644 --- a/src/script/api/script_game.cpp +++ b/src/script/api/script_game.cpp @@ -9,6 +9,7 @@ #include "../../stdafx.h" #include "script_game.hpp" +#include "script_error.hpp" #include "../../command_type.h" #include "../../settings_type.h" #include "../../network/network.h" diff --git a/src/script/api/script_gamesettings.cpp b/src/script/api/script_gamesettings.cpp index 00e88e8351..c8d99c36e6 100644 --- a/src/script/api/script_gamesettings.cpp +++ b/src/script/api/script_gamesettings.cpp @@ -33,6 +33,7 @@ /* static */ bool ScriptGameSettings::SetValue(const char *setting, SQInteger value) { + EnforceDeityOrCompanyModeValid(false); if (!IsValid(setting)) return false; const SettingDesc *sd = GetSettingFromName(setting); diff --git a/src/script/api/script_group.cpp b/src/script/api/script_group.cpp index a7f0417695..7f1542e37d 100644 --- a/src/script/api/script_group.cpp +++ b/src/script/api/script_group.cpp @@ -25,6 +25,7 @@ /* static */ bool ScriptGroup::IsValidGroup(GroupID group_id) { + EnforceDeityOrCompanyModeValid(false); const Group *g = ::Group::GetIfValid(group_id); return g != nullptr && g->owner == ScriptObject::GetCompany(); } diff --git a/src/script/api/script_grouplist.cpp b/src/script/api/script_grouplist.cpp index 569b44634c..11099ca67e 100644 --- a/src/script/api/script_grouplist.cpp +++ b/src/script/api/script_grouplist.cpp @@ -9,12 +9,14 @@ #include "../../stdafx.h" #include "script_grouplist.hpp" +#include "script_error.hpp" #include "../../group.h" #include "../../safeguards.h" ScriptGroupList::ScriptGroupList() { + EnforceDeityOrCompanyModeValid_Void(); for (const Group *g : Group::Iterate()) { if (g->owner == ScriptObject::GetCompany()) this->AddItem(g->index); } diff --git a/src/script/api/script_industrytype.cpp b/src/script/api/script_industrytype.cpp index 24289b9cbb..3d7073e40b 100644 --- a/src/script/api/script_industrytype.cpp +++ b/src/script/api/script_industrytype.cpp @@ -119,6 +119,7 @@ /* static */ bool ScriptIndustryType::BuildIndustry(IndustryType industry_type, TileIndex tile) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, CanBuildIndustry(industry_type)); EnforcePrecondition(false, ScriptMap::IsValidTile(tile)); @@ -129,6 +130,7 @@ /* static */ bool ScriptIndustryType::ProspectIndustry(IndustryType industry_type) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, CanProspectIndustry(industry_type)); uint32 seed = ScriptBase::Rand(); diff --git a/src/script/api/script_objecttype.cpp b/src/script/api/script_objecttype.cpp index 71d09a4097..7d74d9b8b8 100644 --- a/src/script/api/script_objecttype.cpp +++ b/src/script/api/script_objecttype.cpp @@ -39,6 +39,7 @@ /* static */ bool ScriptObjectType::BuildObject(ObjectType object_type, SQInteger view, TileIndex tile) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, IsValidObjectType(object_type)); EnforcePrecondition(false, view >= 0 && view < GetViews(object_type)); EnforcePrecondition(false, ScriptMap::IsValidTile(tile)); diff --git a/src/script/api/script_rail.cpp b/src/script/api/script_rail.cpp index 6643ce2781..e9bdbd0658 100644 --- a/src/script/api/script_rail.cpp +++ b/src/script/api/script_rail.cpp @@ -69,6 +69,7 @@ /* static */ bool ScriptRail::IsRailTypeAvailable(RailType rail_type) { + EnforceDeityOrCompanyModeValid(false); if ((::RailType)rail_type >= RAILTYPE_END) return false; return ScriptCompanyMode::IsDeity() || ::HasRailtypeAvail(ScriptObject::GetCompany(), (::RailType)rail_type); diff --git a/src/script/api/script_railtypelist.cpp b/src/script/api/script_railtypelist.cpp index a7ddf9b20c..cfc0b3b550 100644 --- a/src/script/api/script_railtypelist.cpp +++ b/src/script/api/script_railtypelist.cpp @@ -9,13 +9,14 @@ #include "../../stdafx.h" #include "script_railtypelist.hpp" -#include "script_companymode.hpp" +#include "script_error.hpp" #include "../../rail.h" #include "../../safeguards.h" ScriptRailTypeList::ScriptRailTypeList() { + EnforceDeityOrCompanyModeValid_Void(); for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) { if (ScriptCompanyMode::IsDeity() || ::HasRailtypeAvail(ScriptObject::GetCompany(), rt)) this->AddItem(rt); } diff --git a/src/script/api/script_road.cpp b/src/script/api/script_road.cpp index ea9a90e75b..2326247753 100644 --- a/src/script/api/script_road.cpp +++ b/src/script/api/script_road.cpp @@ -67,6 +67,7 @@ /* static */ bool ScriptRoad::IsRoadTypeAvailable(RoadType road_type) { + EnforceDeityOrCompanyModeValid(false); return (::RoadType)road_type < ROADTYPE_END && ::HasRoadTypeAvail(ScriptObject::GetCompany(), (::RoadType)road_type); } @@ -489,6 +490,7 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD /* static */ bool ScriptRoad::_BuildRoadInternal(TileIndex start, TileIndex end, bool one_way, bool full) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, start != end); EnforcePrecondition(false, ::IsValidTile(start)); EnforcePrecondition(false, ::IsValidTile(end)); diff --git a/src/script/api/script_roadtypelist.cpp b/src/script/api/script_roadtypelist.cpp index 7b54d8c99a..5d2ad8ae6a 100644 --- a/src/script/api/script_roadtypelist.cpp +++ b/src/script/api/script_roadtypelist.cpp @@ -15,6 +15,7 @@ ScriptRoadTypeList::ScriptRoadTypeList(ScriptRoad::RoadTramTypes rtts) { + EnforceDeityOrCompanyModeValid_Void(); for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) { if (!HasBit(rtts, GetRoadTramType(rt))) continue; if (ScriptCompanyMode::IsDeity() || ::HasRoadTypeAvail(ScriptObject::GetCompany(), rt)) this->AddItem(rt); diff --git a/src/script/api/script_sign.cpp b/src/script/api/script_sign.cpp index 269d3e69dc..01488b8953 100644 --- a/src/script/api/script_sign.cpp +++ b/src/script/api/script_sign.cpp @@ -21,6 +21,7 @@ /* static */ bool ScriptSign::IsValidSign(SignID sign_id) { + EnforceDeityOrCompanyModeValid(false); const Sign *si = ::Sign::GetIfValid(sign_id); return si != nullptr && (si->owner == ScriptObject::GetCompany() || si->owner == OWNER_DEITY); } @@ -36,6 +37,7 @@ { CCountedPtr counter(name); + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, IsValidSign(sign_id)); EnforcePrecondition(false, name != nullptr); const std::string &text = name->GetDecodedText(); @@ -63,6 +65,7 @@ /* static */ bool ScriptSign::RemoveSign(SignID sign_id) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, IsValidSign(sign_id)); return ScriptObject::Command::Do(sign_id, ""); } @@ -71,6 +74,7 @@ { CCountedPtr counter(name); + EnforceDeityOrCompanyModeValid(INVALID_SIGN); EnforcePrecondition(INVALID_SIGN, ::IsValidTile(location)); EnforcePrecondition(INVALID_SIGN, name != nullptr); const std::string &text = name->GetDecodedText(); diff --git a/src/script/api/script_station.cpp b/src/script/api/script_station.cpp index d7c3353647..a545b949ab 100644 --- a/src/script/api/script_station.cpp +++ b/src/script/api/script_station.cpp @@ -21,6 +21,7 @@ /* static */ bool ScriptStation::IsValidStation(StationID station_id) { + EnforceDeityOrCompanyModeValid(false); const Station *st = ::Station::GetIfValid(station_id); return st != nullptr && (st->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity() || st->owner == OWNER_NONE); } diff --git a/src/script/api/script_stationlist.cpp b/src/script/api/script_stationlist.cpp index 7b692483f1..5ccb6a0609 100644 --- a/src/script/api/script_stationlist.cpp +++ b/src/script/api/script_stationlist.cpp @@ -18,6 +18,7 @@ ScriptStationList::ScriptStationList(ScriptStation::StationType station_type) { + EnforceDeityOrCompanyModeValid_Void(); for (Station *st : Station::Iterate()) { if ((st->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity()) && (st->facilities & station_type) != 0) this->AddItem(st->index); } diff --git a/src/script/api/script_tile.cpp b/src/script/api/script_tile.cpp index 8dc1c65fcf..f292bfd647 100644 --- a/src/script/api/script_tile.cpp +++ b/src/script/api/script_tile.cpp @@ -25,6 +25,7 @@ /* static */ bool ScriptTile::IsBuildable(TileIndex tile) { + EnforceDeityOrCompanyModeValid(false); if (!::IsValidTile(tile)) return false; switch (::GetTileType(tile)) { @@ -277,6 +278,7 @@ /* static */ bool ScriptTile::DemolishTile(TileIndex tile) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, ::IsValidTile(tile)); return ScriptObject::Command::Do(tile); diff --git a/src/script/api/script_town.cpp b/src/script/api/script_town.cpp index 855dba6302..6bdd2283ff 100644 --- a/src/script/api/script_town.cpp +++ b/src/script/api/script_town.cpp @@ -281,6 +281,7 @@ { CCountedPtr counter(name); + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, ScriptCompanyMode::IsDeity() || _settings_game.economy.found_town != TF_FORBIDDEN); EnforcePrecondition(false, ::IsValidTile(tile)); EnforcePrecondition(false, size == TOWN_SIZE_SMALL || size == TOWN_SIZE_MEDIUM || size == TOWN_SIZE_LARGE) diff --git a/src/script/api/script_tunnel.cpp b/src/script/api/script_tunnel.cpp index cdbcb6df8b..0e1286c334 100644 --- a/src/script/api/script_tunnel.cpp +++ b/src/script/api/script_tunnel.cpp @@ -82,6 +82,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance) /* static */ bool ScriptTunnel::BuildTunnel(ScriptVehicle::VehicleType vehicle_type, TileIndex start) { + EnforceDeityOrCompanyModeValid(false); EnforcePrecondition(false, ::IsValidTile(start)); EnforcePrecondition(false, vehicle_type == ScriptVehicle::VT_RAIL || vehicle_type == ScriptVehicle::VT_ROAD); EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_RAIL || ScriptRail::IsRailTypeAvailable(ScriptRail::GetCurrentRailType())); @@ -99,6 +100,8 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance) /* static */ bool ScriptTunnel::_BuildTunnelRoad1() { + EnforceDeityOrCompanyModeValid(false); + /* Build the piece of road on the 'start' side of the tunnel */ TileIndex end = ScriptObject::GetCallbackVariable(0); TileIndex start = ScriptTunnel::GetOtherTunnelEnd(end); @@ -111,6 +114,8 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance) /* static */ bool ScriptTunnel::_BuildTunnelRoad2() { + EnforceDeityOrCompanyModeValid(false); + /* Build the piece of road on the 'end' side of the tunnel */ TileIndex end = ScriptObject::GetCallbackVariable(0); TileIndex start = ScriptTunnel::GetOtherTunnelEnd(end); diff --git a/src/script/api/script_vehicle.cpp b/src/script/api/script_vehicle.cpp index f308b6e064..144e5e3e29 100644 --- a/src/script/api/script_vehicle.cpp +++ b/src/script/api/script_vehicle.cpp @@ -30,6 +30,7 @@ /* static */ bool ScriptVehicle::IsValidVehicle(VehicleID vehicle_id) { + EnforceDeityOrCompanyModeValid(false); const Vehicle *v = ::Vehicle::GetIfValid(vehicle_id); return v != nullptr && (v->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity()) && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon())); } diff --git a/src/script/api/script_vehiclelist.cpp b/src/script/api/script_vehiclelist.cpp index d849ea186e..0687ac366c 100644 --- a/src/script/api/script_vehiclelist.cpp +++ b/src/script/api/script_vehiclelist.cpp @@ -20,6 +20,7 @@ ScriptVehicleList::ScriptVehicleList() { + EnforceDeityOrCompanyModeValid_Void(); for (const Vehicle *v : Vehicle::Iterate()) { if ((v->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity()) && (v->IsPrimaryVehicle() || (v->type == VEH_TRAIN && ::Train::From(v)->IsFreeWagon()))) this->AddItem(v->index); } @@ -27,6 +28,7 @@ ScriptVehicleList::ScriptVehicleList() ScriptVehicleList_Station::ScriptVehicleList_Station(StationID station_id) { + EnforceDeityOrCompanyModeValid_Void(); if (!ScriptBaseStation::IsValidBaseStation(station_id)) return; for (const Vehicle *v : Vehicle::Iterate()) { @@ -43,6 +45,7 @@ ScriptVehicleList_Station::ScriptVehicleList_Station(StationID station_id) ScriptVehicleList_Depot::ScriptVehicleList_Depot(TileIndex tile) { + EnforceDeityOrCompanyModeValid_Void(); if (!ScriptMap::IsValidTile(tile)) return; DestinationID dest; @@ -100,6 +103,7 @@ ScriptVehicleList_SharedOrders::ScriptVehicleList_SharedOrders(VehicleID vehicle ScriptVehicleList_Group::ScriptVehicleList_Group(GroupID group_id) { + EnforceDeityOrCompanyModeValid_Void(); if (!ScriptGroup::IsValidGroup((ScriptGroup::GroupID)group_id)) return; for (const Vehicle *v : Vehicle::Iterate()) { @@ -111,6 +115,7 @@ ScriptVehicleList_Group::ScriptVehicleList_Group(GroupID group_id) ScriptVehicleList_DefaultGroup::ScriptVehicleList_DefaultGroup(ScriptVehicle::VehicleType vehicle_type) { + EnforceDeityOrCompanyModeValid_Void(); if (vehicle_type < ScriptVehicle::VT_RAIL || vehicle_type > ScriptVehicle::VT_AIR) return; for (const Vehicle *v : Vehicle::Iterate()) { diff --git a/src/script/api/script_waypoint.cpp b/src/script/api/script_waypoint.cpp index 9b4f2de5a0..5f7bceaa61 100644 --- a/src/script/api/script_waypoint.cpp +++ b/src/script/api/script_waypoint.cpp @@ -17,6 +17,7 @@ /* static */ bool ScriptWaypoint::IsValidWaypoint(StationID waypoint_id) { + EnforceDeityOrCompanyModeValid(false); const Waypoint *wp = ::Waypoint::GetIfValid(waypoint_id); return wp != nullptr && (wp->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity() || wp->owner == OWNER_NONE); } diff --git a/src/script/api/script_waypointlist.cpp b/src/script/api/script_waypointlist.cpp index 92d684d450..5e1e1ca079 100644 --- a/src/script/api/script_waypointlist.cpp +++ b/src/script/api/script_waypointlist.cpp @@ -17,6 +17,7 @@ ScriptWaypointList::ScriptWaypointList(ScriptWaypoint::WaypointType waypoint_type) { + EnforceDeityOrCompanyModeValid_Void(); for (const Waypoint *wp : Waypoint::Iterate()) { if ((wp->facilities & waypoint_type) && (wp->owner == ScriptObject::GetCompany() || ScriptCompanyMode::IsDeity() || wp->owner == OWNER_NONE)) this->AddItem(wp->index);