mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-05 22:04:57 +00:00
(svn r8735) -Feature: drive-through road stops made possible by the hard work of mart3p.
This commit is contained in:
parent
39b73119ca
commit
0e8f006dc1
BIN
bin/data/roadstops.grf
Normal file
BIN
bin/data/roadstops.grf
Normal file
Binary file not shown.
@ -45,6 +45,7 @@ DEF_COMMAND(CmdRenameWaypoint);
|
||||
DEF_COMMAND(CmdRemoveTrainWaypoint);
|
||||
|
||||
DEF_COMMAND(CmdBuildRoadStop);
|
||||
DEF_COMMAND(CmdRemoveRoadStop);
|
||||
|
||||
DEF_COMMAND(CmdBuildLongRoad);
|
||||
DEF_COMMAND(CmdRemoveLongRoad);
|
||||
@ -188,7 +189,7 @@ static const Command _command_proc_table[] = {
|
||||
{NULL, 0}, /* 19 */
|
||||
{NULL, 0}, /* 20 */
|
||||
{CmdBuildRoadStop, 0}, /* 21 */
|
||||
{NULL, 0}, /* 22 */
|
||||
{CmdRemoveRoadStop, 0}, /* 22 */
|
||||
{CmdBuildLongRoad, 0}, /* 23 */
|
||||
{CmdRemoveLongRoad, 0}, /* 24 */
|
||||
{CmdBuildRoad, 0}, /* 25 */
|
||||
|
@ -27,6 +27,7 @@ enum {
|
||||
CMD_REMOVE_TRAIN_WAYPOINT = 18,
|
||||
|
||||
CMD_BUILD_ROAD_STOP = 21,
|
||||
CMD_REMOVE_ROAD_STOP = 22,
|
||||
CMD_BUILD_LONG_ROAD = 23,
|
||||
CMD_REMOVE_LONG_ROAD = 24,
|
||||
CMD_BUILD_ROAD = 25,
|
||||
|
@ -387,6 +387,9 @@ static void LoadSpriteTables(void)
|
||||
assert(load_index == SPR_AIRPORTX_BASE);
|
||||
load_index += LoadGrfFile("airports.grf", load_index, i++);
|
||||
|
||||
assert(load_index == SPR_ROADSTOP_BASE);
|
||||
load_index += LoadGrfFile("roadstops.grf", load_index, i++);
|
||||
|
||||
/* Initialize the unicode to sprite mapping table */
|
||||
InitializeUnicodeGlyphMap();
|
||||
|
||||
|
@ -1041,6 +1041,7 @@ STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Allow b
|
||||
STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Nonuniform stations: {ORANGE}{STRING1}
|
||||
STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL :{LTBLUE}New global pathfinding (NPF, overrides NTP): {ORANGE}{STRING1}
|
||||
STR_CONFIG_PATCHES_FREIGHT_TRAINS :{LTBLUE}Weight multiplier for freight to simulate heavy trains: {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD :{LTBLUE}Allow drive-through road stops on town owned roads: {ORANGE}{STRING}
|
||||
|
||||
STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Always allow small airports: {ORANGE}{STRING1}
|
||||
|
||||
@ -1584,6 +1585,8 @@ STR_1815_ROAD_WITH_STREETLIGHTS :Road with stree
|
||||
STR_1816_TREE_LINED_ROAD :Tree-lined road
|
||||
STR_1817_ROAD_VEHICLE_DEPOT :Road vehicle depot
|
||||
STR_1818_ROAD_RAIL_LEVEL_CROSSING :Road/rail level crossing
|
||||
STR_CAN_T_REMOVE_BUS_STATION :{WHITE}Can't remove bus station...
|
||||
STR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}Can't remove lorry station...
|
||||
|
||||
##id 0x2000
|
||||
STR_2000_TOWNS :{WHITE}Towns
|
||||
|
@ -1107,6 +1107,7 @@ STR_CONFIG_PATCHES_BRIBE :{LTBLUE}Önkorm
|
||||
STR_CONFIG_PATCHES_NONUNIFORM_STATIONS :{LTBLUE}Különböző vágánytípusok engedélyezése egy állomáson: {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_NEW_PATHFINDING_ALL :{LTBLUE}Új útvonalkereső (NPF, felülbírálja az NTP-t): {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_FREIGHT_TRAINS :{LTBLUE}Tömegszorzó tehervonatoknak (szimulációs célból): {ORANGE}{STRING}
|
||||
STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD :{LTBLUE}Áthajtható állomások engedélyezése városi utakra: {ORANGE}{STRING}
|
||||
|
||||
STR_CONFIG_PATCHES_SMALL_AIRPORTS :{LTBLUE}Mindig engedélyezze a kis repülőtereket: {ORANGE}{STRING}
|
||||
|
||||
@ -1650,6 +1651,8 @@ STR_1815_ROAD_WITH_STREETLIGHTS :Út lámpákkal
|
||||
STR_1816_TREE_LINED_ROAD :Fával szegélyezett út
|
||||
STR_1817_ROAD_VEHICLE_DEPOT :Garázs
|
||||
STR_1818_ROAD_RAIL_LEVEL_CROSSING :Út/vasút kereszteződés
|
||||
STR_CAN_T_REMOVE_BUS_STATION :{WHITE}Nem távolíthatod el ezt a buszmegállót...
|
||||
STR_CAN_T_REMOVE_TRUCK_STATION :{WHITE}Nem távolíthatod el ezt a teherautó megállót...
|
||||
|
||||
##id 0x2000
|
||||
STR_2000_TOWNS :{WHITE}Városok
|
||||
|
14
src/npf.cpp
14
src/npf.cpp
@ -279,6 +279,12 @@ static int32 NPFRoadPathCost(AyStar* as, AyStarNode* current, OpenListNode* pare
|
||||
if (IsLevelCrossing(tile)) cost += _patches.npf_crossing_penalty;
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
cost = NPF_TILE_LENGTH;
|
||||
/* Increase the cost for drive-through road stops */
|
||||
if (IsDriveThroughStopTile(tile)) cost += _patches.npf_road_drive_through_penalty;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -453,7 +459,7 @@ static bool VehicleMayEnterTile(Owner owner, TileIndex tile, DiagDirection enter
|
||||
if (IsTileType(tile, MP_RAILWAY) || /* Rail tile (also rail depot) */
|
||||
IsRailwayStationTile(tile) || /* Rail station tile */
|
||||
IsTileDepotType(tile, TRANSPORT_ROAD) || /* Road depot tile */
|
||||
IsRoadStopTile(tile) || /* Road station tile */
|
||||
IsStandardRoadStopTile(tile) || /* Road station tile (but not drive-through stops) */
|
||||
IsTileDepotType(tile, TRANSPORT_WATER)) { /* Water depot tile */
|
||||
return IsTileOwner(tile, owner); /* You need to own these tiles entirely to use them */
|
||||
}
|
||||
@ -529,8 +535,8 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
|
||||
} else if (IsBridgeTile(src_tile) && GetBridgeRampDirection(src_tile) == src_exitdir) {
|
||||
dst_tile = GetOtherBridgeEnd(src_tile);
|
||||
override_dst_check = true;
|
||||
} else if (type != TRANSPORT_WATER && (IsRoadStopTile(src_tile) || IsTileDepotType(src_tile, type))) {
|
||||
/* This is a road station or a train or road depot. We can enter and exit
|
||||
} else if (type != TRANSPORT_WATER && (IsStandardRoadStopTile(src_tile) || IsTileDepotType(src_tile, type))) {
|
||||
/* This is a road station (non drive-through) or a train or road depot. We can enter and exit
|
||||
* those from one side only. Trackdirs don't support that (yet), so we'll
|
||||
* do this here. */
|
||||
|
||||
@ -599,7 +605,7 @@ static void NPFFollowTrack(AyStar* aystar, OpenListNode* current)
|
||||
}
|
||||
|
||||
/* Determine available tracks */
|
||||
if (type != TRANSPORT_WATER && (IsRoadStopTile(dst_tile) || IsTileDepotType(dst_tile, type))){
|
||||
if (type != TRANSPORT_WATER && (IsStandardRoadStopTile(dst_tile) || IsTileDepotType(dst_tile, type))){
|
||||
/* Road stations and road and train depots return 0 on GTTS, so we have to do this by hand... */
|
||||
DiagDirection exitdir;
|
||||
if (IsRoadStopTile(dst_tile)) {
|
||||
|
@ -296,7 +296,7 @@ static void TPFMode1(TrackPathFinder* tpf, TileIndex tile, DiagDirection directi
|
||||
if (tpf->tracktype == TRANSPORT_ROAD) {
|
||||
// road stops and depots now have a track (r4419)
|
||||
// don't enter road stop from the back
|
||||
if (IsRoadStopTile(tile) && ReverseDiagDir(GetRoadStopDir(tile)) != direction) return;
|
||||
if (IsStandardRoadStopTile(tile) && ReverseDiagDir(GetRoadStopDir(tile)) != direction) return;
|
||||
// don't enter road depot from the back
|
||||
if (IsTileDepotType(tile, TRANSPORT_ROAD) && ReverseDiagDir(GetRoadDepotDirection(tile)) != direction) return;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "sound.h"
|
||||
#include "command.h"
|
||||
#include "variables.h"
|
||||
#include "station_map.h"
|
||||
//needed for catchments
|
||||
#include "station.h"
|
||||
|
||||
@ -83,7 +84,7 @@ void CcRoadDepot(bool success, TileIndex tile, uint32 p1, uint32 p2)
|
||||
if (success) {
|
||||
SndPlayTileFx(SND_1F_SPLAT, tile);
|
||||
ResetObjectToPlace();
|
||||
BuildRoadOutsideStation(tile, (DiagDirection)p1);
|
||||
if (!HASBIT(p2, 1)) BuildRoadOutsideStation(tile, (DiagDirection)p1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,14 +93,45 @@ static void PlaceRoad_Depot(TileIndex tile)
|
||||
DoCommandP(tile, _road_depot_orientation, 0, CcRoadDepot, CMD_BUILD_ROAD_DEPOT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1807_CAN_T_BUILD_ROAD_VEHICLE));
|
||||
}
|
||||
|
||||
static void PlaceRoadStop(TileIndex tile, uint32 p2, uint32 cmd)
|
||||
{
|
||||
uint32 p1 = _road_station_picker_orientation;
|
||||
|
||||
if (p1 >= DIAGDIR_END) {
|
||||
SETBIT(p2, 1); // It's a drive-through stop
|
||||
p1 -= DIAGDIR_END; // Adjust picker result to actual direction
|
||||
|
||||
/* Only allow building over a road if its a straight road,
|
||||
* facing the right direction and it belongs to the player */
|
||||
if ((IsTileType(tile, MP_STREET) &&
|
||||
GetRoadTileType(tile) == ROAD_TILE_NORMAL &&
|
||||
(IsTileOwner(tile, _current_player) || (_patches.road_stop_on_town_road && IsTileOwner(tile, OWNER_TOWN))) &&
|
||||
!(GetRoadBits(tile) & ((DiagDirection)p1 == DIAGDIR_NE ? ROAD_Y : ROAD_X)))) {
|
||||
|
||||
cmd ^= CMD_AUTO;
|
||||
SETBIT(p2, 2); // We're building over an existing road
|
||||
if (IsTileOwner(tile, OWNER_TOWN)) SETBIT(p2, 3); // It's a town owned road
|
||||
}
|
||||
}
|
||||
DoCommandP(tile, p1, p2, CcRoadDepot, cmd);
|
||||
}
|
||||
|
||||
static void PlaceRoad_BusStation(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _road_station_picker_orientation, RoadStop::BUS, CcRoadDepot, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION));
|
||||
if (_remove_button_clicked) {
|
||||
DoCommandP(tile, 0, RoadStop::BUS, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_BUS_STATION));
|
||||
} else {
|
||||
PlaceRoadStop(tile, RoadStop::BUS, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1808_CAN_T_BUILD_BUS_STATION));
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceRoad_TruckStation(TileIndex tile)
|
||||
{
|
||||
DoCommandP(tile, _road_station_picker_orientation, RoadStop::TRUCK, CcRoadDepot, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION));
|
||||
if (_remove_button_clicked) {
|
||||
DoCommandP(tile, 0, RoadStop::TRUCK, CcPlaySound1D, CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_CAN_T_REMOVE_TRUCK_STATION));
|
||||
} else {
|
||||
PlaceRoadStop(tile, RoadStop::TRUCK, CMD_BUILD_ROAD_STOP | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_1809_CAN_T_BUILD_TRUCK_STATION));
|
||||
}
|
||||
}
|
||||
|
||||
static void PlaceRoad_DemolishArea(TileIndex tile)
|
||||
@ -195,7 +227,7 @@ static void BuildRoadToolbWndProc(Window *w, WindowEvent *e)
|
||||
case WE_CREATE: DisableWindowWidget(w, RTW_REMOVE); break;
|
||||
|
||||
case WE_PAINT:
|
||||
if (IsWindowWidgetLowered(w, RTW_ROAD_X) || IsWindowWidgetLowered(w, RTW_ROAD_Y)) {
|
||||
if (IsWindowWidgetLowered(w, RTW_ROAD_X) || IsWindowWidgetLowered(w, RTW_ROAD_Y) || IsWindowWidgetLowered(w, RTW_BUS_STATION) || IsWindowWidgetLowered(w, RTW_TRUCK_STATION)) {
|
||||
EnableWindowWidget(w, RTW_REMOVE);
|
||||
}
|
||||
DrawWindowWidgets(w);
|
||||
@ -428,7 +460,7 @@ static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
|
||||
switch (e->event) {
|
||||
case WE_CREATE:
|
||||
LowerWindowWidget(w, _road_station_picker_orientation + 3);
|
||||
LowerWindowWidget(w, _station_show_coverage + 7);
|
||||
LowerWindowWidget(w, _station_show_coverage + 9);
|
||||
break;
|
||||
|
||||
case WE_PAINT: {
|
||||
@ -445,13 +477,18 @@ static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
|
||||
SetTileSelectSize(1, 1);
|
||||
}
|
||||
|
||||
image = (w->window_class == WC_BUS_STATION) ? 0x47 : 0x43;
|
||||
image = (w->window_class == WC_BUS_STATION) ? GFX_BUS_BASE : GFX_TRUCK_BASE;
|
||||
|
||||
StationPickerDrawSprite(103, 35, RAILTYPE_BEGIN, image);
|
||||
StationPickerDrawSprite(103, 85, RAILTYPE_BEGIN, image+1);
|
||||
StationPickerDrawSprite(35, 85, RAILTYPE_BEGIN, image+2);
|
||||
StationPickerDrawSprite(35, 35, RAILTYPE_BEGIN, image+3);
|
||||
|
||||
image = (w->window_class == WC_BUS_STATION) ? GFX_BUS_BASE_EXT : GFX_TRUCK_BASE_EXT;
|
||||
|
||||
StationPickerDrawSprite(171, 35, RAILTYPE_BEGIN, image);
|
||||
StationPickerDrawSprite(171, 85, RAILTYPE_BEGIN, image + 1);
|
||||
|
||||
DrawStationCoverageAreaText(2, 146,
|
||||
((w->window_class == WC_BUS_STATION) ? (1<<CT_PASSENGERS) : ~(1<<CT_PASSENGERS)),
|
||||
3);
|
||||
@ -460,17 +497,17 @@ static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
|
||||
|
||||
case WE_CLICK: {
|
||||
switch (e->we.click.widget) {
|
||||
case 3: case 4: case 5: case 6:
|
||||
case 3: case 4: case 5: case 6: case 7: case 8:
|
||||
RaiseWindowWidget(w, _road_station_picker_orientation + 3);
|
||||
_road_station_picker_orientation = (DiagDirection)(e->we.click.widget - 3);
|
||||
LowerWindowWidget(w, _road_station_picker_orientation + 3);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
case 7: case 8:
|
||||
RaiseWindowWidget(w, _station_show_coverage + 7);
|
||||
_station_show_coverage = (e->we.click.widget != 7);
|
||||
LowerWindowWidget(w, _station_show_coverage + 7);
|
||||
case 9: case 10:
|
||||
RaiseWindowWidget(w, _station_show_coverage + 9);
|
||||
_station_show_coverage = (e->we.click.widget != 9);
|
||||
LowerWindowWidget(w, _station_show_coverage + 9);
|
||||
SndPlayFx(SND_15_BEEP);
|
||||
SetWindowDirty(w);
|
||||
break;
|
||||
@ -494,12 +531,14 @@ static void RoadStationPickerWndProc(Window *w, WindowEvent *e)
|
||||
|
||||
static const Widget _bus_station_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_3042_BUS_STATION_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 176, 0x0, STR_NULL},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 206, 0, 13, STR_3042_BUS_STATION_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 206, 14, 176, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 139, 204, 17, 66, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 139, 204, 69, 118, 0x0, STR_3051_SELECT_BUS_STATION_ORIENTATION},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 10, 69, 133, 144, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 70, 129, 133, 144, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 139, 120, 133, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
|
||||
@ -507,7 +546,7 @@ static const Widget _bus_station_picker_widgets[] = {
|
||||
};
|
||||
|
||||
static const WindowDesc _bus_station_picker_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 140, 177,
|
||||
WDP_AUTO, WDP_AUTO, 207, 177,
|
||||
WC_BUS_STATION, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_bus_station_picker_widgets,
|
||||
@ -521,12 +560,14 @@ static void ShowBusStationPicker(void)
|
||||
|
||||
static const Widget _truck_station_picker_widgets[] = {
|
||||
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 139, 0, 13, STR_3043_TRUCK_STATION_ORIENT, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 139, 14, 176, 0x0, STR_NULL},
|
||||
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 206, 0, 13, STR_3043_TRUCK_STATION_ORIENT, STR_018C_WINDOW_TITLE_DRAG_THIS},
|
||||
{ WWT_PANEL, RESIZE_NONE, 7, 0, 206, 14, 176, 0x0, STR_NULL},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 71, 136, 17, 66, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 71, 136, 69, 118, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 68, 69, 118, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 3, 68, 17, 66, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 139, 204, 17, 66, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_PANEL, RESIZE_NONE, 14, 139, 204, 69, 118, 0x0, STR_3052_SELECT_TRUCK_LOADING_BAY},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 10, 69, 133, 144, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
|
||||
{ WWT_TEXTBTN, RESIZE_NONE, 14, 70, 129, 133, 144, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
|
||||
{ WWT_LABEL, RESIZE_NONE, 7, 0, 139, 120, 133, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
|
||||
@ -534,7 +575,7 @@ static const Widget _truck_station_picker_widgets[] = {
|
||||
};
|
||||
|
||||
static const WindowDesc _truck_station_picker_desc = {
|
||||
WDP_AUTO, WDP_AUTO, 140, 177,
|
||||
WDP_AUTO, WDP_AUTO, 207, 177,
|
||||
WC_TRUCK_STATION, WC_BUILD_TOOLBAR,
|
||||
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
|
||||
_truck_station_picker_widgets,
|
||||
|
@ -24,6 +24,7 @@ RoadBits GetAnyRoadBits(TileIndex tile)
|
||||
|
||||
case MP_STATION:
|
||||
if (!IsRoadStopTile(tile)) return ROAD_NONE;
|
||||
if (IsDriveThroughStopTile(tile)) return (GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y;
|
||||
return DiagDirToRoadBits(GetRoadStopDir(tile));
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
@ -45,7 +46,7 @@ TrackBits GetAnyRoadTrackBits(TileIndex tile)
|
||||
uint32 r;
|
||||
|
||||
// Don't allow local authorities to build roads through road depots or road stops.
|
||||
if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || IsTileType(tile, MP_STATION)) {
|
||||
if ((IsTileType(tile, MP_STREET) && IsTileDepotType(tile, TRANSPORT_ROAD)) || (IsTileType(tile, MP_STATION) && !IsDriveThroughStopTile(tile))) {
|
||||
return TRACK_BIT_NONE;
|
||||
}
|
||||
|
||||
|
@ -1080,7 +1080,8 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
|
||||
/* Road depot owned by another player or with the wrong orientation */
|
||||
trackdirs = TRACKDIR_BIT_NONE;
|
||||
}
|
||||
} else if (IsTileType(tile, MP_STATION) && IsRoadStopTile(tile)) {
|
||||
} else if (IsTileType(tile, MP_STATION) && IsStandardRoadStopTile(tile)) {
|
||||
/* Standard road stop (drive-through stops are treated as normal road) */
|
||||
if (!IsTileOwner(tile, v->owner) || GetRoadStopDir(tile) == enterdir) {
|
||||
/* different station owner or wrong orientation */
|
||||
trackdirs = TRACKDIR_BIT_NONE;
|
||||
@ -1093,7 +1094,7 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
|
||||
trackdirs = TRACKDIR_BIT_NONE;
|
||||
} else {
|
||||
/* Proper station type, check if there is free loading bay */
|
||||
if (!_patches.roadveh_queue &&
|
||||
if (!_patches.roadveh_queue && IsStandardRoadStopTile(tile) &&
|
||||
!GetRoadStopByTile(tile, rstype)->HasFreeBay()) {
|
||||
/* Station is full and RV queuing is off */
|
||||
trackdirs = TRACKDIR_BIT_NONE;
|
||||
@ -1167,7 +1168,8 @@ static Trackdir RoadFindPathToDest(Vehicle* v, TileIndex tile, DiagDirection ent
|
||||
goto do_it;
|
||||
}
|
||||
} else if (IsTileType(desttile, MP_STATION)) {
|
||||
if (IsRoadStop(desttile)) {
|
||||
/* For drive-through stops we can head for the actual station tile */
|
||||
if (IsStandardRoadStopTile(desttile)) {
|
||||
dir = GetRoadStopDir(desttile);
|
||||
do_it:;
|
||||
/* When we are heading for a depot or station, we just
|
||||
@ -1242,9 +1244,11 @@ enum {
|
||||
/* Start frames for when a vehicle enters a tile/changes its state.
|
||||
* The start frame is different for vehicles that turned around or
|
||||
* are leaving the depot as the do not start at the edge of the tile */
|
||||
RVC_DEFAULT_START_FRAME = 0,
|
||||
RVC_TURN_AROUND_START_FRAME = 1,
|
||||
RVC_DEPOT_START_FRAME = 6
|
||||
RVC_DEFAULT_START_FRAME = 0,
|
||||
RVC_TURN_AROUND_START_FRAME = 1,
|
||||
RVC_DEPOT_START_FRAME = 6,
|
||||
/* Stop frame for a vehicle in a drive-through stop */
|
||||
RVC_DRIVE_THROUGH_STOP_FRAME = 7
|
||||
};
|
||||
|
||||
typedef struct RoadDriveEntry {
|
||||
@ -1376,8 +1380,12 @@ static void RoadVehController(Vehicle *v)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get move position data for next frame */
|
||||
rd = _road_drive_data[(v->u.road.state + (_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
|
||||
/* Get move position data for next frame.
|
||||
* For a drive-through road stop use 'straight road' move data.
|
||||
* In this case v->u.road.state is masked to give the road stop entry direction. */
|
||||
rd = _road_drive_data[(
|
||||
(HASBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP) ? v->u.road.state & RVSB_ROAD_STOP_TRACKDIR_MASK : v->u.road.state) +
|
||||
(_opt.road_side << RVS_DRIVE_SIDE)) ^ v->u.road.overtaking][v->u.road.frame + 1];
|
||||
|
||||
if (rd.x & RDE_NEXT_TILE) {
|
||||
TileIndex tile = v->tile + TileOffsByDiagDir(rd.x & 3);
|
||||
@ -1417,8 +1425,8 @@ again:
|
||||
goto again;
|
||||
}
|
||||
|
||||
if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
|
||||
if (IsReversingRoadTrackdir(dir)) {
|
||||
if (IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) && IsTileType(v->tile, MP_STATION)) {
|
||||
if (IsReversingRoadTrackdir(dir) && IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) {
|
||||
/* New direction is trying to turn vehicle around.
|
||||
* We can't turn at the exit of a road stop so wait.*/
|
||||
v->cur_speed = 0;
|
||||
@ -1427,9 +1435,13 @@ again:
|
||||
if (IsRoadStop(v->tile)) {
|
||||
RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
|
||||
|
||||
/* Vehicle is leaving a road stop tile, mark bay as free */
|
||||
rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY));
|
||||
rs->SetEntranceBusy(false);
|
||||
/* Vehicle is leaving a road stop tile, mark bay as free
|
||||
* For drive-through stops, only do it if the vehicle stopped here */
|
||||
if (IsStandardRoadStopTile(v->tile) || HASBIT(v->u.road.state, RVS_IS_STOPPING)) {
|
||||
rs->FreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY));
|
||||
CLRBIT(v->u.road.state, RVS_IS_STOPPING);
|
||||
}
|
||||
if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1523,8 +1535,18 @@ again:
|
||||
}
|
||||
}
|
||||
|
||||
if (v->u.road.state >= RVSB_IN_ROAD_STOP &&
|
||||
_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) {
|
||||
/* If the vehicle is in a normal road stop and the frame equals the stop frame OR
|
||||
* if the vehicle is in a drive-through road stop and this is the destination station
|
||||
* and it's the correct type of stop (bus or truck) and the frame equals the stop frame...
|
||||
* (the station test and stop type test ensure that other vehicles, using the road stop as
|
||||
* a through route, do not stop) */
|
||||
if ((IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END) &&
|
||||
_road_veh_data_1[v->u.road.state - RVSB_IN_ROAD_STOP + (_opt.road_side << RVS_DRIVE_SIDE)] == v->u.road.frame) ||
|
||||
(IS_BYTE_INSIDE(v->u.road.state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
|
||||
v->current_order.dest == GetStationIndex(v->tile) &&
|
||||
GetRoadStopType(v->tile) == ((v->cargo_type == CT_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
|
||||
v->u.road.frame == RVC_DRIVE_THROUGH_STOP_FRAME)) {
|
||||
|
||||
RoadStop *rs = GetRoadStopByTile(v->tile, GetRoadStopType(v->tile));
|
||||
Station* st = GetStationByTile(v->tile);
|
||||
|
||||
@ -1536,6 +1558,31 @@ again:
|
||||
/* Vehicle has arrived at a bay in a road stop */
|
||||
Order old_order;
|
||||
|
||||
if (IsDriveThroughStopTile(v->tile)) {
|
||||
TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
|
||||
RoadStop::Type type = (v->cargo_type == CT_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK;
|
||||
|
||||
assert(HASBIT(v->u.road.state, RVS_IS_STOPPING));
|
||||
|
||||
/* Check if next inline bay is free */
|
||||
if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type)) {
|
||||
RoadStop *rs_n = GetRoadStopByTile(next_tile, type);
|
||||
|
||||
if (rs_n->IsFreeBay(HASBIT(v->u.road.state, RVS_USING_SECOND_BAY))) {
|
||||
/* Bay in next stop along is free - use it */
|
||||
ClearSlot(v);
|
||||
rs_n->num_vehicles++;
|
||||
v->u.road.slot = rs_n;
|
||||
v->dest_tile = rs_n->xy;
|
||||
v->u.road.slot_age = 14;
|
||||
|
||||
v->u.road.frame++;
|
||||
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rs->SetEntranceBusy(false);
|
||||
|
||||
v->last_station_visited = GetStationIndex(v->tile);
|
||||
@ -1573,7 +1620,7 @@ again:
|
||||
ClearSlot(v);
|
||||
}
|
||||
|
||||
rs->SetEntranceBusy(true);
|
||||
if (IsStandardRoadStopTile(v->tile)) rs->SetEntranceBusy(true);
|
||||
|
||||
if (rs == v->u.road.slot) {
|
||||
/* We are leaving the correct station */
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "variables.h"
|
||||
#include <setjmp.h>
|
||||
|
||||
extern const uint16 SAVEGAME_VERSION = 46;
|
||||
extern const uint16 SAVEGAME_VERSION = 47;
|
||||
uint16 _sl_version; /// the major savegame version identifier
|
||||
byte _sl_minor_version; /// the minor savegame version, DO NOT USE!
|
||||
|
||||
|
@ -1340,6 +1340,7 @@ const SettingDesc _patch_settings[] = {
|
||||
SDT_BOOL(Patches, serviceathelipad, 0, 0, true, STR_CONFIG_PATCHES_SERVICEATHELIPAD, NULL),
|
||||
SDT_BOOL(Patches, modified_catchment, 0, 0, true, STR_CONFIG_PATCHES_CATCHMENT, NULL),
|
||||
SDT_CONDBOOL(Patches, gradual_loading, 40, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_GRADUAL_LOADING, NULL),
|
||||
SDT_CONDBOOL(Patches, road_stop_on_town_road, 47, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_STOP_ON_TOWN_ROAD, NULL),
|
||||
|
||||
/***************************************************************************/
|
||||
/* Economy section of the GUI-configure patches window */
|
||||
@ -1431,6 +1432,8 @@ const SettingDesc _patch_settings[] = {
|
||||
SDT_VAR(Patches, npf_road_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL),
|
||||
/* This is the penalty for level crossings, for both road and rail vehicles */
|
||||
SDT_VAR(Patches, npf_crossing_penalty, SLE_UINT, 0, 0, (3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
||||
/* This is the penalty for drive-through road, stops. */
|
||||
SDT_CONDVAR (Patches, npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * NPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||
|
||||
|
||||
// The maximum number of nodes to search
|
||||
@ -1464,6 +1467,7 @@ const SettingDesc _patch_settings[] = {
|
||||
SDT_CONDVAR (Patches, yapf.road_slope_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 2 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||
SDT_CONDVAR (Patches, yapf.road_curve_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||
SDT_CONDVAR (Patches, yapf.road_crossing_penalty , SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||
SDT_CONDVAR (Patches, yapf.road_stop_penalty , SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||
|
||||
/***************************************************************************/
|
||||
/* Terrain genation related patch options */
|
||||
|
@ -599,6 +599,7 @@ static const char *_patches_stations[] = {
|
||||
"serviceathelipad",
|
||||
"modified_catchment",
|
||||
"gradual_loading",
|
||||
"road_stop_on_town_road",
|
||||
};
|
||||
|
||||
static const char *_patches_economy[] = {
|
||||
|
@ -502,6 +502,13 @@ bool RoadStop::HasFreeBay() const
|
||||
return GB(status, 0, MAX_BAY_COUNT) != 0;
|
||||
}
|
||||
|
||||
/** Checks whether the given bay is free in this road stop */
|
||||
bool RoadStop::IsFreeBay(uint nr) const
|
||||
{
|
||||
assert(nr < MAX_BAY_COUNT);
|
||||
return HASBIT(status, nr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a bay
|
||||
* @return the allocated bay number
|
||||
@ -519,6 +526,16 @@ uint RoadStop::AllocateBay()
|
||||
return bay_nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a bay in a drive-through road stop
|
||||
* @param nr the number of the bay to allocate
|
||||
*/
|
||||
void RoadStop::AllocateDriveThroughBay(uint nr)
|
||||
{
|
||||
assert(nr < MAX_BAY_COUNT);
|
||||
CLRBIT(status, nr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Frees the given bay
|
||||
* @param nr the number of the bay to free
|
||||
|
@ -66,7 +66,9 @@ struct RoadStop {
|
||||
|
||||
/* For accessing status */
|
||||
bool HasFreeBay() const;
|
||||
bool IsFreeBay(uint nr) const;
|
||||
uint AllocateBay();
|
||||
void AllocateDriveThroughBay(uint nr);
|
||||
void FreeBay(uint nr);
|
||||
bool IsEntranceBusy() const;
|
||||
void SetEntranceBusy(bool busy);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "date.h"
|
||||
#include "helpers.hpp"
|
||||
#include "misc/autoptr.hpp"
|
||||
#include "road.h"
|
||||
|
||||
/**
|
||||
* Called if a new block is added to the station-pool
|
||||
@ -1247,7 +1248,10 @@ static RoadStop **FindRoadStopSpot(bool truck_station, Station* st)
|
||||
/** Build a bus or truck stop
|
||||
* @param tile tile to build the stop at
|
||||
* @param p1 entrance direction (DiagDirection)
|
||||
* @param p2 0 for Bus stops, 1 for truck stops
|
||||
* @param p2 bit 0: 0 for Bus stops, 1 for truck stops
|
||||
* bit 1: 0 for normal, 1 for drive-through
|
||||
* bit 2: 0 for normal, 1 for build over road
|
||||
* bit 3: 0 for player owned road, 1 for town owned road
|
||||
*/
|
||||
int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
@ -1255,19 +1259,29 @@ int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
RoadStop *road_stop;
|
||||
int32 cost;
|
||||
int32 ret;
|
||||
bool type = !!p2;
|
||||
bool type = HASBIT(p2, 0);
|
||||
bool is_drive_through = HASBIT(p2, 1);
|
||||
Owner cur_owner = _current_player;
|
||||
|
||||
/* Saveguard the parameters */
|
||||
if (!IsValidDiagDirection((DiagDirection)p1)) return CMD_ERROR;
|
||||
/* If it is a drive-through stop check for valid axis */
|
||||
if (is_drive_through && !IsValidAxis((Axis)p1)) return CMD_ERROR;
|
||||
/* If overbuilding a road check tile is a valid road tile */
|
||||
if (HASBIT(p2, 2) && !(IsTileType(tile, MP_STREET) && GetRoadTileType(tile) == ROAD_TILE_NORMAL)) return CMD_ERROR;
|
||||
/* If overbuilding a town road,check tile is town owned and patch setting is enabled */
|
||||
if (HASBIT(p2, 3) && !(_patches.road_stop_on_town_road && IsTileOwner(tile, OWNER_TOWN))) return CMD_ERROR;
|
||||
|
||||
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
|
||||
|
||||
if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
|
||||
return CMD_ERROR;
|
||||
|
||||
ret = CheckFlatLandBelow(tile, 1, 1, flags, 1 << p1, NULL);
|
||||
if (is_drive_through & HASBIT(p2, 3)) _current_player = OWNER_TOWN;
|
||||
ret = CheckFlatLandBelow(tile, 1, 1, flags, is_drive_through ? 5 << p1 : 1 << p1, NULL);
|
||||
_current_player = cur_owner;
|
||||
if (CmdFailed(ret)) return ret;
|
||||
cost = ret;
|
||||
cost = HASBIT(p2, 2) ? 0 : ret; // Don't add cost of clearing road when overbuilding
|
||||
|
||||
st = GetStationAround(tile, 1, 1, INVALID_STATION);
|
||||
if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
|
||||
@ -1333,7 +1347,8 @@ int32 CmdBuildRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
|
||||
st->rect.BeforeAddTile(tile, StationRect::ADD_TRY);
|
||||
|
||||
MakeRoadStop(tile, st->owner, st->index, type ? RoadStop::TRUCK : RoadStop::BUS, (DiagDirection)p1);
|
||||
MakeRoadStop(tile, st->owner, st->index, type ? RoadStop::TRUCK : RoadStop::BUS, is_drive_through, (DiagDirection)p1);
|
||||
if (is_drive_through & HASBIT(p2, 3)) SetStopBuiltOnTownRoad(tile);
|
||||
|
||||
UpdateStationVirtCoordDirty(st);
|
||||
UpdateStationAcceptance(st, false);
|
||||
@ -1395,7 +1410,44 @@ static int32 RemoveRoadStop(Station *st, uint32 flags, TileIndex tile)
|
||||
return (is_truck) ? _price.remove_truck_station : _price.remove_bus_station;
|
||||
}
|
||||
|
||||
/** Remove a bus or truck stop
|
||||
* @param tile tile to remove the stop from
|
||||
* @param p1 not used
|
||||
* @param p2 bit 0: 0 for Bus stops, 1 for truck stops
|
||||
*/
|
||||
int32 CmdRemoveRoadStop(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
Station* st;
|
||||
bool is_drive_through;
|
||||
bool is_towns_road = false;
|
||||
RoadBits road_bits;
|
||||
int32 ret;
|
||||
|
||||
/* Make sure the specified tile is a road stop of the correct type */
|
||||
if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile) || (uint32)GetRoadStopType(tile) != p2) return CMD_ERROR;
|
||||
st = GetStationByTile(tile);
|
||||
/* Save the stop info before it is removed */
|
||||
is_drive_through = IsDriveThroughStopTile(tile);
|
||||
road_bits = GetAnyRoadBits(tile);
|
||||
if (is_drive_through) is_towns_road = GetStopBuiltOnTownRoad(tile);
|
||||
|
||||
ret = RemoveRoadStop(st, flags, tile);
|
||||
|
||||
/* If the stop was a drive-through stop replace the road */
|
||||
if ((flags & DC_EXEC) && !CmdFailed(ret) && is_drive_through) {
|
||||
uint index = 0;
|
||||
Owner cur_owner = _current_player;
|
||||
|
||||
if (is_towns_road) {
|
||||
index = ClosestTownFromTile(tile, _patches.dist_local_authority)->index;
|
||||
_current_player = OWNER_TOWN;
|
||||
}
|
||||
DoCommand(tile, road_bits, index, DC_EXEC, CMD_BUILD_ROAD);
|
||||
_current_player = cur_owner;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// FIXME -- need to move to its corresponding Airport variable
|
||||
// Country Airfield (small)
|
||||
@ -2227,6 +2279,27 @@ static uint32 VehicleEnter_Station(Vehicle *v, TileIndex tile, int x, int y)
|
||||
/* Attempt to allocate a parking bay in a road stop */
|
||||
RoadStop *rs = GetRoadStopByTile(tile, GetRoadStopType(tile));
|
||||
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
/* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */
|
||||
byte side = ((DirToDiagDir(v->direction) == ReverseDiagDir(GetRoadStopDir(tile))) == (v->u.road.overtaking == 0)) ? 0 : 1;
|
||||
|
||||
if (!rs->IsFreeBay(side)) return VETSB_CANNOT_ENTER;
|
||||
|
||||
/* Check if the vehicle is stopping at this road stop */
|
||||
if (GetRoadStopType(tile) == ((v->cargo_type == CT_PASSENGERS) ? RoadStop::BUS : RoadStop::TRUCK) &&
|
||||
v->current_order.dest == GetStationIndex(tile)) {
|
||||
SETBIT(v->u.road.state, RVS_IS_STOPPING);
|
||||
rs->AllocateDriveThroughBay(side);
|
||||
}
|
||||
|
||||
/* Indicate if vehicle is using second bay. */
|
||||
if (side == 1) SETBIT(v->u.road.state, RVS_USING_SECOND_BAY);
|
||||
/* Indicate a drive-through stop */
|
||||
SETBIT(v->u.road.state, RVS_IN_DT_ROAD_STOP);
|
||||
return VETSB_CONTINUE;
|
||||
}
|
||||
|
||||
/* For normal (non drive-through) road stops */
|
||||
/* Check if station is busy or if there are no free bays. */
|
||||
if (rs->IsEntranceBusy() || !rs->HasFreeBay()) return VETSB_CANNOT_ENTER;
|
||||
|
||||
@ -2693,7 +2766,13 @@ static int32 ClearTile_Station(TileIndex tile, byte flags)
|
||||
case STATION_RAIL: return RemoveRailroadStation(st, tile, flags);
|
||||
case STATION_AIRPORT: return RemoveAirport(st, flags);
|
||||
case STATION_TRUCK:
|
||||
case STATION_BUS: return RemoveRoadStop(st, flags, tile);
|
||||
if (IsDriveThroughStopTile(tile) && GetStopBuiltOnTownRoad(tile))
|
||||
return_cmd_error(STR_3047_MUST_DEMOLISH_TRUCK_STATION);
|
||||
return RemoveRoadStop(st, flags, tile);
|
||||
case STATION_BUS:
|
||||
if (IsDriveThroughStopTile(tile) && GetStopBuiltOnTownRoad(tile))
|
||||
return_cmd_error(STR_3046_MUST_DEMOLISH_BUS_STATION);
|
||||
return RemoveRoadStop(st, flags, tile);
|
||||
case STATION_BUOY: return RemoveBuoy(st, flags);
|
||||
case STATION_DOCK: return RemoveDock(st, flags);
|
||||
default: break;
|
||||
|
@ -42,7 +42,9 @@ enum {
|
||||
GFX_RADAR_DISTRICTWE_LAST = 156,
|
||||
GFX_WINDSACK_INTERCON_FIRST = 164,
|
||||
GFX_WINDSACK_INTERCON_LAST = 167,
|
||||
GFX_BASE_END = 168
|
||||
GFX_TRUCK_BASE_EXT = 168,
|
||||
GFX_BUS_BASE_EXT = 170,
|
||||
GFX_BASE_END = 172
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -51,7 +53,9 @@ enum {
|
||||
TRUCK_SIZE = GFX_BUS_BASE - GFX_TRUCK_BASE,
|
||||
BUS_SIZE = GFX_OILRIG_BASE - GFX_BUS_BASE,
|
||||
DOCK_SIZE_TOTAL = GFX_BUOY_BASE - GFX_DOCK_BASE,
|
||||
AIRPORT_SIZE_EXTENDED = GFX_BASE_END - GFX_AIRPORT_BASE_EXTENDED
|
||||
AIRPORT_SIZE_EXTENDED = GFX_TRUCK_BASE_EXT - GFX_AIRPORT_BASE_EXTENDED,
|
||||
TRUCK_SIZE_EXT = GFX_BUS_BASE_EXT - GFX_TRUCK_BASE_EXT,
|
||||
BUS_SIZE_EXT = GFX_BASE_END - GFX_BUS_BASE_EXT,
|
||||
};
|
||||
|
||||
typedef enum HangarTiles {
|
||||
@ -125,12 +129,14 @@ static inline bool IsAirport(TileIndex t)
|
||||
|
||||
static inline bool IsTruckStop(TileIndex t)
|
||||
{
|
||||
return IS_BYTE_INSIDE(GetStationGfx(t), GFX_TRUCK_BASE, GFX_TRUCK_BASE + TRUCK_SIZE);
|
||||
return (IS_BYTE_INSIDE(GetStationGfx(t), GFX_TRUCK_BASE, GFX_TRUCK_BASE + TRUCK_SIZE)) ||
|
||||
(IS_BYTE_INSIDE(GetStationGfx(t), GFX_TRUCK_BASE_EXT, GFX_TRUCK_BASE_EXT + TRUCK_SIZE_EXT));
|
||||
}
|
||||
|
||||
static inline bool IsBusStop(TileIndex t)
|
||||
{
|
||||
return IS_BYTE_INSIDE(GetStationGfx(t), GFX_BUS_BASE, GFX_BUS_BASE + BUS_SIZE);
|
||||
return (IS_BYTE_INSIDE(GetStationGfx(t), GFX_BUS_BASE, GFX_BUS_BASE + BUS_SIZE)) ||
|
||||
(IS_BYTE_INSIDE(GetStationGfx(t), GFX_BUS_BASE_EXT, GFX_BUS_BASE_EXT + BUS_SIZE_EXT));
|
||||
}
|
||||
|
||||
static inline bool IsRoadStop(TileIndex t)
|
||||
@ -143,13 +149,44 @@ static inline bool IsRoadStopTile(TileIndex t)
|
||||
return IsTileType(t, MP_STATION) && IsRoadStop(t);
|
||||
}
|
||||
|
||||
static inline bool IsStandardRoadStopTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_STATION) &&
|
||||
(IS_BYTE_INSIDE(GetStationGfx(t), GFX_TRUCK_BASE, GFX_TRUCK_BASE + TRUCK_SIZE) ||
|
||||
IS_BYTE_INSIDE(GetStationGfx(t), GFX_BUS_BASE, GFX_BUS_BASE + BUS_SIZE));
|
||||
}
|
||||
|
||||
static inline bool IsDriveThroughStopTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_STATION) &&
|
||||
(IS_BYTE_INSIDE(GetStationGfx(t), GFX_TRUCK_BASE_EXT, GFX_TRUCK_BASE_EXT + TRUCK_SIZE_EXT) ||
|
||||
IS_BYTE_INSIDE(GetStationGfx(t), GFX_BUS_BASE_EXT, GFX_BUS_BASE_EXT + BUS_SIZE_EXT));
|
||||
}
|
||||
|
||||
static inline bool GetStopBuiltOnTownRoad(TileIndex t)
|
||||
{
|
||||
assert(IsDriveThroughStopTile(t));
|
||||
return HASBIT(_m[t].m6, 3);
|
||||
}
|
||||
|
||||
static inline void SetStopBuiltOnTownRoad(TileIndex t)
|
||||
{
|
||||
assert(IsDriveThroughStopTile(t));
|
||||
SETBIT(_m[t].m6, 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the direction the road stop entrance points towards.
|
||||
*/
|
||||
static inline DiagDirection GetRoadStopDir(TileIndex t)
|
||||
{
|
||||
StationGfx gfx = GetStationGfx(t);
|
||||
assert(IsRoadStopTile(t));
|
||||
return (DiagDirection)((GetStationGfx(t) - GFX_TRUCK_BASE) & 3);
|
||||
if (gfx < GFX_TRUCK_BASE_EXT) {
|
||||
return (DiagDirection)((gfx - GFX_TRUCK_BASE) & 3);
|
||||
} else {
|
||||
return (DiagDirection)((gfx - GFX_TRUCK_BASE_EXT) & 1);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool IsOilRig(TileIndex t)
|
||||
@ -275,9 +312,13 @@ static inline void MakeRailStation(TileIndex t, Owner o, StationID sid, Axis a,
|
||||
SetRailType(t, rt);
|
||||
}
|
||||
|
||||
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, DiagDirection d)
|
||||
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStop::Type rst, bool is_drive_through, DiagDirection d)
|
||||
{
|
||||
MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE : GFX_TRUCK_BASE) + d);
|
||||
if (is_drive_through) {
|
||||
MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE_EXT : GFX_TRUCK_BASE_EXT) + d);
|
||||
} else {
|
||||
MakeStation(t, o, sid, (rst == RoadStop::BUS ? GFX_BUS_BASE : GFX_TRUCK_BASE) + d);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void MakeAirport(TileIndex t, Owner o, StationID sid, byte section)
|
||||
|
@ -117,6 +117,16 @@ enum Sprites {
|
||||
SPR_GRASS_RIGHT = SPR_AIRPORTX_BASE + 13,
|
||||
SPR_GRASS_LEFT = SPR_AIRPORTX_BASE + 14,
|
||||
|
||||
SPR_ROADSTOP_BASE = SPR_AIRPORTX_BASE + 15, // The sprites used for drive-through road stops
|
||||
SPR_BUS_STOP_DT_Y_W = SPR_ROADSTOP_BASE,
|
||||
SPR_BUS_STOP_DT_Y_E = SPR_ROADSTOP_BASE + 1,
|
||||
SPR_BUS_STOP_DT_X_W = SPR_ROADSTOP_BASE + 2,
|
||||
SPR_BUS_STOP_DT_X_E = SPR_ROADSTOP_BASE + 3,
|
||||
SPR_TRUCK_STOP_DT_Y_W = SPR_ROADSTOP_BASE + 4,
|
||||
SPR_TRUCK_STOP_DT_Y_E = SPR_ROADSTOP_BASE + 5,
|
||||
SPR_TRUCK_STOP_DT_X_W = SPR_ROADSTOP_BASE + 6,
|
||||
SPR_TRUCK_STOP_DT_X_E = SPR_ROADSTOP_BASE + 7,
|
||||
|
||||
/* Manager face sprites */
|
||||
SPR_GRADIENT = 874, // background gradient behind manager face
|
||||
|
||||
@ -295,6 +305,10 @@ enum Sprites {
|
||||
SPR_PYLON_NS_W = SPR_ELRAIL_BASE + 37,
|
||||
SPR_PYLON_NS_E = SPR_ELRAIL_BASE + 38,
|
||||
|
||||
/* sprites for roads */
|
||||
SPR_ROAD_PAVED_STRAIGHT_Y = 1313,
|
||||
SPR_ROAD_PAVED_STRAIGHT_X = 1314,
|
||||
|
||||
/* sprites for airports and airfields*/
|
||||
/* Small airports are AIRFIELD, everything else is AIRPORT */
|
||||
SPR_HELIPORT = 2633,
|
||||
|
@ -959,6 +959,34 @@ static const DrawTileSeqStruct _station_display_datas_0163[] = {
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
// drive-through truck stop X
|
||||
static const DrawTileSeqStruct _station_display_datas_0168[] = {
|
||||
{ 1, 0, 0, 14, 3, 10, SPR_TRUCK_STOP_DT_X_W | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
{ 1, 13, 0, 14, 1, 10, SPR_TRUCK_STOP_DT_X_E | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
// drive-through truck stop Y
|
||||
static const DrawTileSeqStruct _station_display_datas_0169[] = {
|
||||
{ 13, 1, 0, 1, 14, 10, SPR_TRUCK_STOP_DT_Y_W | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
{ 0, 1, 0, 3, 14, 10, SPR_TRUCK_STOP_DT_Y_E | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
// drive-through bus stop X
|
||||
static const DrawTileSeqStruct _station_display_datas_0170[] = {
|
||||
{ 5, 0, 0, 8, 3, 10, SPR_BUS_STOP_DT_X_W | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
{ 5, 14, 0, 8, 1, 10, SPR_BUS_STOP_DT_X_E | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
// drive-through bus stop Y
|
||||
static const DrawTileSeqStruct _station_display_datas_0171[] = {
|
||||
{ 13, 5, 0, 1, 8, 10, SPR_BUS_STOP_DT_Y_W | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
{ 0, 5, 0, 3, 8, 10, SPR_BUS_STOP_DT_Y_E | (1 << PALETTE_MODIFIER_COLOR), PAL_NONE },
|
||||
TILE_SEQ_END()
|
||||
};
|
||||
|
||||
static const DrawTileSprites _station_display_datas[] = {
|
||||
{ SPR_RAIL_TRACK_X, PAL_NONE, _station_display_datas_0 },
|
||||
{ SPR_RAIL_TRACK_Y, PAL_NONE, _station_display_datas_1 },
|
||||
@ -1128,4 +1156,8 @@ static const DrawTileSprites _station_display_datas[] = {
|
||||
{ SPR_FLAT_GRASS_TILE, PAL_NONE, _station_display_datas_59 },
|
||||
{ SPR_FLAT_GRASS_TILE, PAL_NONE, _station_display_datas_60 },
|
||||
{ SPR_FLAT_GRASS_TILE, PAL_NONE, _station_display_datas_61 },
|
||||
{ SPR_ROAD_PAVED_STRAIGHT_X, PAL_NONE, _station_display_datas_0168 },
|
||||
{ SPR_ROAD_PAVED_STRAIGHT_Y, PAL_NONE, _station_display_datas_0169 },
|
||||
{ SPR_ROAD_PAVED_STRAIGHT_X, PAL_NONE, _station_display_datas_0170 },
|
||||
{ SPR_ROAD_PAVED_STRAIGHT_Y, PAL_NONE, _station_display_datas_0171 }
|
||||
};
|
||||
|
@ -166,6 +166,7 @@ typedef struct Patches {
|
||||
bool autosave_on_exit; // save an autosave when you quit the game, but do not ask "Do you really want to quit?"
|
||||
byte max_num_autosaves; // controls how many autosavegames are made before the game starts to overwrite (names them 0 to max_num_autosaves - 1)
|
||||
bool extra_dynamite; // extra dynamite
|
||||
bool road_stop_on_town_road; // allow building of drive-through road stops on town owned roads
|
||||
|
||||
bool never_expire_vehicles; // never expire vehicles
|
||||
byte extend_vehicle_life; // extend vehicle life by this many years
|
||||
@ -211,6 +212,7 @@ typedef struct Patches {
|
||||
uint32 npf_water_curve_penalty; /* The penalty for curves */
|
||||
uint32 npf_road_curve_penalty; /* The penalty for curves */
|
||||
uint32 npf_crossing_penalty; /* The penalty for level crossings */
|
||||
uint32 npf_road_drive_through_penalty; /* The penalty for going through a drive-through road stop */
|
||||
|
||||
bool population_in_label; // Show the population of a town in his label?
|
||||
|
||||
|
@ -2756,9 +2756,11 @@ Trackdir GetVehicleTrackdir(const Vehicle* v)
|
||||
if (IsRoadVehInDepot(v)) /* We'll assume the road vehicle is facing outwards */
|
||||
return DiagdirToDiagTrackdir(GetRoadDepotDirection(v->tile));
|
||||
|
||||
if (IsRoadStopTile(v->tile)) /* We'll assume the road vehicle is facing outwards */
|
||||
if (IsStandardRoadStopTile(v->tile)) /* We'll assume the road vehicle is facing outwards */
|
||||
return DiagdirToDiagTrackdir(GetRoadStopDir(v->tile)); /* Road vehicle in a station */
|
||||
|
||||
if (IsDriveThroughStopTile(v->tile)) return DiagdirToDiagTrackdir(DirToDiagDir(v->direction));
|
||||
|
||||
/* If vehicle's state is a valid track direction (vehicle is not turning around) return it */
|
||||
if (!IsReversingRoadTrackdir((Trackdir)v->u.road.state)) return (Trackdir)v->u.road.state;
|
||||
|
||||
|
@ -45,14 +45,18 @@ enum RoadVehicleStates {
|
||||
|
||||
/* Bit numbers */
|
||||
RVS_USING_SECOND_BAY = 1, ///< Only used while in a road stop
|
||||
RVS_IS_STOPPING = 2, ///< Only used for drive-through stops. Vehicle will stop here
|
||||
RVS_DRIVE_SIDE = 4, ///< Only used when retrieving move data and for turning vehicles
|
||||
RVS_IN_ROAD_STOP = 5, ///< The vehicle is in a road stop
|
||||
RVS_IN_DT_ROAD_STOP = 6, ///< The vehicle is in a drive-through road stop
|
||||
|
||||
/* Bit sets of the above specified bits */
|
||||
RVSB_USING_SECOND_BAY = 1 << RVS_USING_SECOND_BAY, ///< Only used while in a road stop
|
||||
RVSB_DRIVE_SIDE = 1 << RVS_DRIVE_SIDE, ///< Only used when retrieving move data and for turning vehicles
|
||||
RVSB_IN_ROAD_STOP = 1 << RVS_IN_ROAD_STOP, ///< The vehicle is in a road stop
|
||||
RVSB_IN_ROAD_STOP_END = RVSB_IN_ROAD_STOP + TRACKDIR_END,
|
||||
RVSB_IN_DT_ROAD_STOP = 1 << RVS_IN_DT_ROAD_STOP, ///< The vehicle is in a drive-through road stop
|
||||
RVSB_IN_DT_ROAD_STOP_END = RVSB_IN_DT_ROAD_STOP + TRACKDIR_END,
|
||||
|
||||
RVSB_TRACKDIR_MASK = 0x0F, ///< The mask used to extract track dirs
|
||||
RVSB_ROAD_STOP_TRACKDIR_MASK = 0x09 ///< Only bits 0 and 3 are used to encode the trackdir for road stops
|
||||
|
@ -121,8 +121,8 @@ protected:
|
||||
/** return true if we can leave m_old_tile in m_exitdir */
|
||||
FORCEINLINE bool CanExitOldTile()
|
||||
{
|
||||
// road stop can be left at one direction only
|
||||
if (IsRoadTT() && IsRoadStopTile(m_old_tile)) {
|
||||
// road stop can be left at one direction only unless it's a drive-through stop
|
||||
if (IsRoadTT() && IsStandardRoadStopTile(m_old_tile)) {
|
||||
DiagDirection exitdir = GetRoadStopDir(m_old_tile);
|
||||
if (exitdir != m_exitdir)
|
||||
return false;
|
||||
@ -140,8 +140,8 @@ protected:
|
||||
/** return true if we can enter m_new_tile from m_exitdir */
|
||||
FORCEINLINE bool CanEnterNewTile()
|
||||
{
|
||||
if (IsRoadTT() && IsRoadStopTile(m_new_tile)) {
|
||||
// road stop can be entered from one direction only
|
||||
if (IsRoadTT() && IsStandardRoadStopTile(m_new_tile)) {
|
||||
// road stop can be entered from one direction only unless it's a drive-through stop
|
||||
DiagDirection exitdir = GetRoadStopDir(m_new_tile);
|
||||
if (ReverseDiagDir(exitdir) != m_exitdir)
|
||||
return false;
|
||||
|
@ -51,6 +51,10 @@ protected:
|
||||
if (IsLevelCrossing(tile))
|
||||
cost += Yapf().PfGetSettings().road_crossing_penalty;
|
||||
break;
|
||||
case MP_STATION:
|
||||
if (IsDriveThroughStopTile(tile))
|
||||
cost += Yapf().PfGetSettings().road_stop_penalty;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
@ -76,6 +80,10 @@ public:
|
||||
// base tile cost depending on distance between edges
|
||||
segment_cost += Yapf().OneTileCost(tile, trackdir);
|
||||
|
||||
const Vehicle* v = Yapf().GetVehicle();
|
||||
// we have reached the vehicle's destination - segment should end here to avoid target skipping
|
||||
if (v->current_order.type == OT_GOTO_STATION && tile == v->dest_tile) break;
|
||||
|
||||
// stop if we have just entered the depot
|
||||
if (IsTileDepotType(tile, TRANSPORT_ROAD) && trackdir == DiagdirToDiagTrackdir(ReverseDiagDir(GetRoadDepotDirection(tile)))) {
|
||||
// next time we will reverse and leave the depot
|
||||
@ -103,7 +111,6 @@ public:
|
||||
// add min/max speed penalties
|
||||
int min_speed = 0;
|
||||
int max_speed = F.GetSpeedLimit(&min_speed);
|
||||
const Vehicle* v = Yapf().GetVehicle();
|
||||
if (max_speed < v->max_speed) segment_cost += 1 * (v->max_speed - max_speed);
|
||||
if (min_speed > v->max_speed) segment_cost += 10 * (min_speed - v->max_speed);
|
||||
|
||||
|
@ -39,6 +39,7 @@ YS_DEF_BEGIN
|
||||
YS_DEF(uint32, road_slope_penalty) ///< penalty for up-hill slope
|
||||
YS_DEF(uint32, road_curve_penalty) ///< penalty for curves
|
||||
YS_DEF(uint32, road_crossing_penalty) ///< penalty for level crossing
|
||||
YS_DEF(uint32, road_stop_penalty) ///< penalty for going through a drive-through road stop
|
||||
YS_DEF(bool , rail_firstred_twoway_eol) ///< treat first red two-way signal as dead end
|
||||
YS_DEF(uint32, rail_firstred_penalty) ///< penalty for first red signal
|
||||
YS_DEF(uint32, rail_firstred_exit_penalty) ///< penalty for first red exit signal
|
||||
|
Loading…
Reference in New Issue
Block a user