mirror of https://github.com/OpenTTD/OpenTTD
(svn r18404) -Codechange: link drive through stops better together
-Feature: make penalty for road stop occupancy user configurable -Fix [FS#1944]: road vehicles would not pick an empty drive through stop. Now they will *if* the penalty for driving around is less than the occupancy penalty -Fix [FS#1495]: long (articulated) road vehicles could block loading of others when the following road vehicle already got 'permission' to go to the next bay even when it could not reach it -Change: improve the throughput of the drive through road stops by letting them stop closer togetherrelease/1.0
parent
65b3e38bea
commit
fac2f8ce1a
|
@ -1096,6 +1096,16 @@ void StateGameLoop()
|
||||||
CallWindowTickEvent();
|
CallWindowTickEvent();
|
||||||
NewsLoop();
|
NewsLoop();
|
||||||
} else {
|
} else {
|
||||||
|
/* Temporary strict checking of the road stop cache entries */
|
||||||
|
const RoadStop *rs;
|
||||||
|
FOR_ALL_ROADSTOPS(rs) {
|
||||||
|
if (IsStandardRoadStopTile(rs->xy)) continue;
|
||||||
|
|
||||||
|
assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW));
|
||||||
|
rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs);
|
||||||
|
rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs);
|
||||||
|
}
|
||||||
|
|
||||||
if (_debug_desync_level > 1) {
|
if (_debug_desync_level > 1) {
|
||||||
Vehicle *v;
|
Vehicle *v;
|
||||||
FOR_ALL_VEHICLES(v) {
|
FOR_ALL_VEHICLES(v) {
|
||||||
|
|
|
@ -21,12 +21,12 @@
|
||||||
#include "timetable.h"
|
#include "timetable.h"
|
||||||
#include "vehicle_func.h"
|
#include "vehicle_func.h"
|
||||||
#include "depot_base.h"
|
#include "depot_base.h"
|
||||||
#include "roadstop_base.h"
|
|
||||||
#include "core/pool_func.hpp"
|
#include "core/pool_func.hpp"
|
||||||
#include "aircraft.h"
|
#include "aircraft.h"
|
||||||
#include "roadveh.h"
|
#include "roadveh.h"
|
||||||
#include "station_base.h"
|
#include "station_base.h"
|
||||||
#include "waypoint_base.h"
|
#include "waypoint_base.h"
|
||||||
|
#include "roadstop_base.h"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
|
|
@ -351,10 +351,21 @@ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
|
||||||
|
|
||||||
case MP_STATION: {
|
case MP_STATION: {
|
||||||
cost = NPF_TILE_LENGTH;
|
cost = NPF_TILE_LENGTH;
|
||||||
/* Increase the cost for drive-through road stops */
|
const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
||||||
if (IsDriveThroughStopTile(tile)) cost += _settings_game.pf.npf.npf_road_drive_through_penalty;
|
if (IsDriveThroughStopTile(tile)) {
|
||||||
RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
/* Increase the cost for drive-through road stops */
|
||||||
cost += 8 * NPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
|
cost += _settings_game.pf.npf.npf_road_drive_through_penalty;
|
||||||
|
DiagDirection dir = TrackdirToExitdir(current->direction);
|
||||||
|
if (!RoadStop::IsDriveThroughRoadStopContinuation(tile, tile - TileOffsByDiagDir(dir))) {
|
||||||
|
/* When we're the first road stop in a 'queue' of them we increase
|
||||||
|
* cost based on the fill percentage of the whole queue. */
|
||||||
|
const RoadStop::Entry *entry = rs->GetEntry(dir);
|
||||||
|
cost += entry->GetOccupied() * _settings_game.pf.npf.npf_road_dt_occupied_penalty / entry->GetLength();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Increase cost for filled road stops */
|
||||||
|
cost += _settings_game.pf.npf.npf_road_bay_occupied_penalty * (!rs->IsFreeBay(0) + !rs->IsFreeBay(1)) / 2;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -66,9 +66,21 @@ protected:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MP_STATION: {
|
case MP_STATION: {
|
||||||
if (IsDriveThroughStopTile(tile)) cost += Yapf().PfGetSettings().road_stop_penalty;
|
const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
||||||
RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
if (IsDriveThroughStopTile(tile)) {
|
||||||
cost += 8 * YAPF_TILE_LENGTH * ((!rs->IsFreeBay(0)) + (!rs->IsFreeBay(1)));
|
/* Increase the cost for drive-through road stops */
|
||||||
|
cost += Yapf().PfGetSettings().road_stop_penalty;
|
||||||
|
DiagDirection dir = TrackdirToExitdir(trackdir);
|
||||||
|
if (!RoadStop::IsDriveThroughRoadStopContinuation(tile, tile - TileOffsByDiagDir(dir))) {
|
||||||
|
/* When we're the first road stop in a 'queue' of them we increase
|
||||||
|
* cost based on the fill percentage of the whole queue. */
|
||||||
|
const RoadStop::Entry *entry = rs->GetEntry(dir);
|
||||||
|
cost += entry->GetOccupied() * Yapf().PfGetSettings().road_stop_occupied_penalty / entry->GetLength();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* Increase cost for filled road stops */
|
||||||
|
cost += Yapf().PfGetSettings().road_stop_bay_occupied_penalty * (!rs->IsFreeBay(0) + !rs->IsFreeBay(1)) / 2;
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
302
src/roadstop.cpp
302
src/roadstop.cpp
|
@ -14,6 +14,8 @@
|
||||||
#include "core/pool_func.hpp"
|
#include "core/pool_func.hpp"
|
||||||
#include "roadstop_base.h"
|
#include "roadstop_base.h"
|
||||||
#include "station_base.h"
|
#include "station_base.h"
|
||||||
|
#include "vehicle_func.h"
|
||||||
|
#include "landscape.h"
|
||||||
|
|
||||||
RoadStopPool _roadstop_pool("RoadStop");
|
RoadStopPool _roadstop_pool("RoadStop");
|
||||||
INSTANTIATE_POOL_METHODS(RoadStop)
|
INSTANTIATE_POOL_METHODS(RoadStop)
|
||||||
|
@ -23,6 +25,12 @@ INSTANTIATE_POOL_METHODS(RoadStop)
|
||||||
*/
|
*/
|
||||||
RoadStop::~RoadStop()
|
RoadStop::~RoadStop()
|
||||||
{
|
{
|
||||||
|
/* When we are the head we need to free the entries */
|
||||||
|
if (HasBit(this->status, RSSFB_BASE_ENTRY)) {
|
||||||
|
delete this->east;
|
||||||
|
delete this->west;
|
||||||
|
}
|
||||||
|
|
||||||
if (CleaningPool()) return;
|
if (CleaningPool()) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,19 +54,175 @@ RoadStop *RoadStop::GetNextRoadStop(const RoadVehicle *v) const
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join this road stop to another 'base' road stop if possible;
|
||||||
|
* fill all necessary data to become an actual drive through road stop.
|
||||||
|
* Also update the length etc.
|
||||||
|
*/
|
||||||
|
void RoadStop::MakeDriveThrough()
|
||||||
|
{
|
||||||
|
assert(this->east == NULL && this->west == NULL);
|
||||||
|
|
||||||
|
RoadStopType rst = GetRoadStopType(this->xy);
|
||||||
|
DiagDirection dir = GetRoadStopDir(this->xy);
|
||||||
|
/* Use absolute so we always go towards the nortern tile */
|
||||||
|
TileIndexDiff offset = abs(TileOffsByDiagDir(dir));
|
||||||
|
|
||||||
|
/* Information about the tile north of us */
|
||||||
|
TileIndex north_tile = this->xy - offset;
|
||||||
|
bool north = IsDriveThroughRoadStopContinuation(this->xy, north_tile);
|
||||||
|
RoadStop *rs_north = north ? RoadStop::GetByTile(north_tile, rst) : NULL;
|
||||||
|
|
||||||
|
/* Information about the tile south of us */
|
||||||
|
TileIndex south_tile = this->xy + offset;
|
||||||
|
bool south = IsDriveThroughRoadStopContinuation(this->xy, south_tile);
|
||||||
|
RoadStop *rs_south = south ? RoadStop::GetByTile(south_tile, rst) : NULL;
|
||||||
|
|
||||||
|
/* Amount of road stops that will be added to the 'northern' head */
|
||||||
|
int added = 1;
|
||||||
|
if (north && rs_north->east != NULL) { // (east != NULL) == (west != NULL)
|
||||||
|
/* There is a more nothern one, so this can join them */
|
||||||
|
this->east = rs_north->east;
|
||||||
|
this->west = rs_north->west;
|
||||||
|
|
||||||
|
if (south && rs_south->east != NULL) { // (east != NULL) == (west != NULL)
|
||||||
|
/* There more southern tiles too, they must 'join' us too */
|
||||||
|
ClrBit(rs_south->status, RSSFB_BASE_ENTRY);
|
||||||
|
this->east->occupied += rs_south->east->occupied;
|
||||||
|
this->west->occupied += rs_south->west->occupied;
|
||||||
|
|
||||||
|
/* Free the now unneeded entry structs */
|
||||||
|
delete rs_south->east;
|
||||||
|
delete rs_south->west;
|
||||||
|
|
||||||
|
/* Make all 'children' of the southern tile take the new master */
|
||||||
|
for (; IsDriveThroughRoadStopContinuation(this->xy, south_tile); south_tile += offset) {
|
||||||
|
rs_south = RoadStop::GetByTile(south_tile, rst);
|
||||||
|
if (rs_south->east == NULL) break;
|
||||||
|
rs_south->east = rs_north->east;
|
||||||
|
rs_south->west = rs_north->west;
|
||||||
|
added++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (south && rs_south->east != NULL) { // (east != NULL) == (west != NULL)
|
||||||
|
/* There is one to the south, but not to the north... so we become 'parent' */
|
||||||
|
this->east = rs_south->east;
|
||||||
|
this->west = rs_south->west;
|
||||||
|
SetBit(this->status, RSSFB_BASE_ENTRY);
|
||||||
|
ClrBit(rs_south->status, RSSFB_BASE_ENTRY);
|
||||||
|
} else {
|
||||||
|
/* We are the only... so we are automatically the master */
|
||||||
|
this->east = new Entry();
|
||||||
|
this->west = new Entry();
|
||||||
|
SetBit(this->status, RSSFB_BASE_ENTRY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now update the lengths */
|
||||||
|
added *= TILE_SIZE;
|
||||||
|
this->east->length += added;
|
||||||
|
this->west->length += added;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare for removal of this stop; update other neighbouring stops
|
||||||
|
* if needed. Also update the length etc.
|
||||||
|
*/
|
||||||
|
void RoadStop::ClearDriveThrough()
|
||||||
|
{
|
||||||
|
assert(this->east != NULL && this->west != NULL);
|
||||||
|
|
||||||
|
RoadStopType rst = GetRoadStopType(this->xy);
|
||||||
|
DiagDirection dir = GetRoadStopDir(this->xy);
|
||||||
|
/* Use absolute so we always go towards the nortern tile */
|
||||||
|
TileIndexDiff offset = abs(TileOffsByDiagDir(dir));
|
||||||
|
|
||||||
|
/* Information about the tile north of us */
|
||||||
|
TileIndex north_tile = this->xy - offset;
|
||||||
|
bool north = IsDriveThroughRoadStopContinuation(this->xy, north_tile);
|
||||||
|
RoadStop *rs_north = north ? RoadStop::GetByTile(north_tile, rst) : NULL;
|
||||||
|
|
||||||
|
/* Information about the tile south of us */
|
||||||
|
TileIndex south_tile = this->xy + offset;
|
||||||
|
bool south = IsDriveThroughRoadStopContinuation(this->xy, south_tile);
|
||||||
|
RoadStop *rs_south = south ? RoadStop::GetByTile(south_tile, rst) : NULL;
|
||||||
|
|
||||||
|
/* Must only be cleared after we determined which neighbours are
|
||||||
|
* part of our little entry 'queue' */
|
||||||
|
DoClearSquare(this->xy);
|
||||||
|
|
||||||
|
if (north) {
|
||||||
|
/* There is a tile to the north, so we can't clear ourselves. */
|
||||||
|
if (south) {
|
||||||
|
/* There are more southern tiles too, they must be split;
|
||||||
|
* first make the new southern 'base' */
|
||||||
|
SetBit(rs_south->status, RSSFB_BASE_ENTRY);
|
||||||
|
rs_south->east = new Entry();
|
||||||
|
rs_south->west = new Entry();
|
||||||
|
|
||||||
|
/* Keep track of the base because we need it later on */
|
||||||
|
RoadStop *rs_south_base = rs_south;
|
||||||
|
TileIndex base_tile = south_tile;
|
||||||
|
|
||||||
|
/* Make all (even more) southern stops part of the new entry queue */
|
||||||
|
for (south_tile += offset; IsDriveThroughRoadStopContinuation(base_tile, south_tile); south_tile += offset) {
|
||||||
|
rs_south = RoadStop::GetByTile(south_tile, rst);
|
||||||
|
rs_south->east = rs_south_base->east;
|
||||||
|
rs_south->west = rs_south_base->west;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the other end; the northern most tile */
|
||||||
|
for (; IsDriveThroughRoadStopContinuation(base_tile, north_tile); north_tile -= offset) {
|
||||||
|
rs_north = RoadStop::GetByTile(north_tile, rst);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We have to rebuild the entries because we cannot easily determine
|
||||||
|
* how full each part is. So instead of keeping and maintaining a list
|
||||||
|
* of vehicles and using that to 'rebuild' the occupied state we just
|
||||||
|
* rebuild it from scratch as that removes lots of maintainance code
|
||||||
|
* for the vehicle list and it's faster in real games as long as you
|
||||||
|
* do not keep split and merge road stop every tick by the millions. */
|
||||||
|
rs_south_base->east->Rebuild(rs_south_base);
|
||||||
|
rs_south_base->west->Rebuild(rs_south_base);
|
||||||
|
|
||||||
|
assert(HasBit(rs_north->status, RSSFB_BASE_ENTRY));
|
||||||
|
rs_north->east->Rebuild(rs_north);
|
||||||
|
rs_north->west->Rebuild(rs_north);
|
||||||
|
} else {
|
||||||
|
/* Only we left, so simple update the length. */
|
||||||
|
rs_north->east->length -= TILE_SIZE;
|
||||||
|
rs_north->west->length -= TILE_SIZE;
|
||||||
|
}
|
||||||
|
} else if (south) {
|
||||||
|
/* There is only something to the south. Hand over the base entry */
|
||||||
|
SetBit(rs_south->status, RSSFB_BASE_ENTRY);
|
||||||
|
rs_south->east->length -= TILE_SIZE;
|
||||||
|
rs_south->west->length -= TILE_SIZE;
|
||||||
|
} else {
|
||||||
|
/* We were the last */
|
||||||
|
delete this->east;
|
||||||
|
delete this->west;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we don't get used for something 'incorrect' */
|
||||||
|
ClrBit(this->status, RSSFB_BASE_ENTRY);
|
||||||
|
this->east = NULL;
|
||||||
|
this->west = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Leave the road stop
|
* Leave the road stop
|
||||||
* @param rv the vehicle that leaves the stop
|
* @param rv the vehicle that leaves the stop
|
||||||
*/
|
*/
|
||||||
void RoadStop::Leave(RoadVehicle *rv)
|
void RoadStop::Leave(RoadVehicle *rv)
|
||||||
{
|
{
|
||||||
/* Vehicle is leaving a road stop tile, mark bay as free
|
if (IsStandardRoadStopTile(rv->tile)) {
|
||||||
* For drive-through stops, only do it if the vehicle stopped here */
|
/* Vehicle is leaving a road stop tile, mark bay as free */
|
||||||
if (IsStandardRoadStopTile(rv->tile) || HasBit(rv->state, RVS_IS_STOPPING)) {
|
|
||||||
this->FreeBay(HasBit(rv->state, RVS_USING_SECOND_BAY));
|
this->FreeBay(HasBit(rv->state, RVS_USING_SECOND_BAY));
|
||||||
ClrBit(rv->state, RVS_IS_STOPPING);
|
this->SetEntranceBusy(false);
|
||||||
|
} else {
|
||||||
|
/* Otherwise just leave the drive through's entry cache. */
|
||||||
|
this->GetEntry(DirToDiagDir(rv->direction))->Leave(rv);
|
||||||
}
|
}
|
||||||
if (IsStandardRoadStopTile(rv->tile)) this->SetEntranceBusy(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -85,19 +249,8 @@ bool RoadStop::Enter(RoadVehicle *rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */
|
/* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */
|
||||||
byte side = ((DirToDiagDir(rv->direction) == ReverseDiagDir(GetRoadStopDir(this->xy))) == (rv->overtaking == 0)) ? 0 : 1;
|
this->GetEntry(DirToDiagDir(rv->direction))->Enter(rv);
|
||||||
|
|
||||||
if (!this->IsFreeBay(side)) return false;
|
|
||||||
|
|
||||||
/* Check if the vehicle is stopping at this road stop */
|
|
||||||
if (GetRoadStopType(this->xy) == (rv->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK) &&
|
|
||||||
rv->current_order.ShouldStopAtStation(rv, GetStationIndex(this->xy))) {
|
|
||||||
SetBit(rv->state, RVS_IS_STOPPING);
|
|
||||||
this->AllocateDriveThroughBay(side);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indicate if vehicle is using second bay. */
|
|
||||||
if (side == 1) SetBit(rv->state, RVS_USING_SECOND_BAY);
|
|
||||||
/* Indicate a drive-through stop */
|
/* Indicate a drive-through stop */
|
||||||
SetBit(rv->state, RVS_IN_DT_ROAD_STOP);
|
SetBit(rv->state, RVS_IN_DT_ROAD_STOP);
|
||||||
return true;
|
return true;
|
||||||
|
@ -120,6 +273,121 @@ bool RoadStop::Enter(RoadVehicle *rv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leave the road stop
|
||||||
|
* @param rv the vehicle that leaves the stop
|
||||||
|
*/
|
||||||
|
void RoadStop::Entry::Leave(const RoadVehicle *rv)
|
||||||
|
{
|
||||||
|
this->occupied -= rv->rcache.cached_veh_length;
|
||||||
|
assert(this->occupied >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter the road stop
|
||||||
|
* @param rv the vehicle that enters the stop
|
||||||
|
*/
|
||||||
|
void RoadStop::Entry::Enter(const RoadVehicle *rv)
|
||||||
|
{
|
||||||
|
assert(this->occupied < this->length);
|
||||||
|
this->occupied += rv->rcache.cached_veh_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the 'next' tile is still part of the road same drive through
|
||||||
|
* stop 'rs' in the same direction for the same vehicle.
|
||||||
|
* @param rs the road stop tile to check against
|
||||||
|
* @param next the 'next' tile to check
|
||||||
|
* @return true if the 'next' tile is part of the road stop at 'next'.
|
||||||
|
*/
|
||||||
|
/* static */ bool RoadStop::IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next)
|
||||||
|
{
|
||||||
|
return IsTileType(next, MP_STATION) &&
|
||||||
|
GetStationIndex(next) == GetStationIndex(rs) &&
|
||||||
|
GetStationType(next) == GetStationType(rs) &&
|
||||||
|
GetRoadStopDir(next) == GetRoadStopDir(rs) &&
|
||||||
|
IsDriveThroughStopTile(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::list<const RoadVehicle *> RVList; ///< A list of road vehicles
|
||||||
|
|
||||||
|
/** Helper for finding RVs in a road stop. */
|
||||||
|
struct RoadStopEntryRebuilderHelper {
|
||||||
|
RVList vehicles; ///< The list of vehicles to possibly add to.
|
||||||
|
DiagDirection dir; ///< The direction the vehicle has to face to be added.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add road vehicles to the station's list if needed.
|
||||||
|
* @param v the found vehicle
|
||||||
|
* @param data the extra data used to make our decision
|
||||||
|
* @return always NULL
|
||||||
|
*/
|
||||||
|
Vehicle *FindVehiclesInRoadStop(Vehicle *v, void *data)
|
||||||
|
{
|
||||||
|
RoadStopEntryRebuilderHelper *rserh = (RoadStopEntryRebuilderHelper*)data;
|
||||||
|
/* Not a RV or not in the right direction or crashed :( */
|
||||||
|
if (v->type != VEH_ROAD || DirToDiagDir(v->direction) != rserh->dir || !v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) return NULL;
|
||||||
|
|
||||||
|
RoadVehicle *rv = RoadVehicle::From(v);
|
||||||
|
/* Don't add ones not in a road stop */
|
||||||
|
if (rv->state < RVSB_IN_ROAD_STOP) return NULL;
|
||||||
|
|
||||||
|
/* Do not add duplicates! */
|
||||||
|
for (RVList::iterator it = rserh->vehicles.begin(); it != rserh->vehicles.end(); it++) {
|
||||||
|
if (rv == *it) return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rserh->vehicles.push_back(rv);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rebuild, from scratch, the vehicles and other metadata on this stop.
|
||||||
|
* @param rs the roadstop this entry is part of
|
||||||
|
* @param side the side of the road stop to look at
|
||||||
|
*/
|
||||||
|
void RoadStop::Entry::Rebuild(const RoadStop *rs, int side)
|
||||||
|
{
|
||||||
|
assert(HasBit(rs->status, RSSFB_BASE_ENTRY));
|
||||||
|
|
||||||
|
DiagDirection dir = GetRoadStopDir(rs->xy);
|
||||||
|
if (side == -1) side = (rs->east == this);
|
||||||
|
|
||||||
|
RoadStopEntryRebuilderHelper rserh;
|
||||||
|
rserh.dir = side ? dir : ReverseDiagDir(dir);
|
||||||
|
|
||||||
|
this->length = 0;
|
||||||
|
TileIndexDiff offset = abs(TileOffsByDiagDir(dir));
|
||||||
|
for (TileIndex tile = rs->xy; IsDriveThroughRoadStopContinuation(rs->xy, tile); tile += offset) {
|
||||||
|
this->length += TILE_SIZE;
|
||||||
|
FindVehicleOnPos(tile, &rserh, FindVehiclesInRoadStop);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->occupied = 0;
|
||||||
|
for (RVList::iterator it = rserh.vehicles.begin(); it != rserh.vehicles.end(); it++) {
|
||||||
|
this->occupied += (*it)->rcache.cached_veh_length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the integrity of the data in this struct.
|
||||||
|
* @param rs the roadstop this entry is part of
|
||||||
|
*/
|
||||||
|
void RoadStop::Entry::CheckIntegrity(const RoadStop *rs) const
|
||||||
|
{
|
||||||
|
if (!HasBit(rs->status, RSSFB_BASE_ENTRY)) return;
|
||||||
|
|
||||||
|
/* The tile 'before' the road stop must not be part of this 'line' */
|
||||||
|
assert(!IsDriveThroughRoadStopContinuation(rs->xy, rs->xy - abs(TileOffsByDiagDir(GetRoadStopDir(rs->xy)))));
|
||||||
|
|
||||||
|
Entry temp;
|
||||||
|
temp.Rebuild(rs, rs->east == this);
|
||||||
|
if (temp.length != this->length || temp.occupied != this->occupied) NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void InitializeRoadStops()
|
void InitializeRoadStops()
|
||||||
{
|
{
|
||||||
_roadstop_pool.CleanPool();
|
_roadstop_pool.CleanPool();
|
||||||
|
|
|
@ -25,9 +25,46 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> {
|
||||||
RSSFB_BAY0_FREE = 0, ///< Non-zero when bay 0 is free
|
RSSFB_BAY0_FREE = 0, ///< Non-zero when bay 0 is free
|
||||||
RSSFB_BAY1_FREE = 1, ///< Non-zero when bay 1 is free
|
RSSFB_BAY1_FREE = 1, ///< Non-zero when bay 1 is free
|
||||||
RSSFB_BAY_COUNT = 2, ///< Max. number of bays
|
RSSFB_BAY_COUNT = 2, ///< Max. number of bays
|
||||||
|
RSSFB_BASE_ENTRY = 6, ///< Non-zero when the entries on this road stop are the primary, i.e. the ones to delete
|
||||||
RSSFB_ENTRY_BUSY = 7, ///< Non-zero when roadstop entry is busy
|
RSSFB_ENTRY_BUSY = 7, ///< Non-zero when roadstop entry is busy
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Container for each entry point of a drive through road stop */
|
||||||
|
struct Entry {
|
||||||
|
private:
|
||||||
|
int length; ///< The length of the stop in tile 'units'
|
||||||
|
int occupied; ///< The amount of occupied stop in tile 'units'
|
||||||
|
|
||||||
|
public:
|
||||||
|
friend class RoadStop; ///< Oh yeah, the road stop may play with me.
|
||||||
|
|
||||||
|
/** Create an entry */
|
||||||
|
Entry() : length(0), occupied(0) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the length of this drive through stop.
|
||||||
|
* @return the length in tile units.
|
||||||
|
*/
|
||||||
|
FORCEINLINE int GetLength() const
|
||||||
|
{
|
||||||
|
return this->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of occupied space in this drive through stop.
|
||||||
|
* @return the occupied space in tile units.
|
||||||
|
*/
|
||||||
|
FORCEINLINE int GetOccupied() const
|
||||||
|
{
|
||||||
|
return this->occupied;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Leave(const RoadVehicle *rv);
|
||||||
|
void Enter(const RoadVehicle *rv);
|
||||||
|
void CheckIntegrity(const RoadStop *rs) const;
|
||||||
|
void Rebuild(const RoadStop *rs, int side = -1);
|
||||||
|
};
|
||||||
|
|
||||||
static const uint LIMIT = 16; ///< The maximum amount of roadstops that are allowed at a single station
|
static const uint LIMIT = 16; ///< The maximum amount of roadstops that are allowed at a single station
|
||||||
|
|
||||||
TileIndex xy; ///< Position on the map
|
TileIndex xy; ///< Position on the map
|
||||||
|
@ -80,6 +117,29 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> {
|
||||||
SB(this->status, RSSFB_ENTRY_BUSY, 1, busy);
|
SB(this->status, RSSFB_ENTRY_BUSY, 1, busy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the drive through road stop entry struct for the given direction.
|
||||||
|
* @param direction the direciton to get the entry for
|
||||||
|
* @return the entry
|
||||||
|
*/
|
||||||
|
FORCEINLINE const Entry *GetEntry(DiagDirection dir) const
|
||||||
|
{
|
||||||
|
return HasBit((int)dir, 1) ? this->west : this->east;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the drive through road stop entry struct for the given direction.
|
||||||
|
* @param direction the direciton to get the entry for
|
||||||
|
* @return the entry
|
||||||
|
*/
|
||||||
|
FORCEINLINE Entry *GetEntry(DiagDirection dir)
|
||||||
|
{
|
||||||
|
return HasBit((int)dir, 1) ? this->west : this->east;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeDriveThrough();
|
||||||
|
void ClearDriveThrough();
|
||||||
|
|
||||||
void Leave(RoadVehicle *rv);
|
void Leave(RoadVehicle *rv);
|
||||||
bool Enter(RoadVehicle *rv);
|
bool Enter(RoadVehicle *rv);
|
||||||
|
|
||||||
|
@ -87,7 +147,12 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> {
|
||||||
|
|
||||||
static RoadStop *GetByTile(TileIndex tile, RoadStopType type);
|
static RoadStop *GetByTile(TileIndex tile, RoadStopType type);
|
||||||
|
|
||||||
|
static bool IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Entry *east; ///< The vehicles that entered from the east
|
||||||
|
Entry *west; ///< The vehicles that entered from the west
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a bay
|
* Allocates a bay
|
||||||
* @return the allocated bay number
|
* @return the allocated bay number
|
||||||
|
|
|
@ -39,7 +39,6 @@ enum RoadVehicleStates {
|
||||||
|
|
||||||
/* Bit numbers */
|
/* Bit numbers */
|
||||||
RVS_USING_SECOND_BAY = 1, ///< Only used while in a road stop
|
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
|
RVS_DRIVE_SIDE = 4, ///< Only used when retrieving move data
|
||||||
RVS_IN_ROAD_STOP = 5, ///< The vehicle is in a road stop
|
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
|
RVS_IN_DT_ROAD_STOP = 6, ///< The vehicle is in a drive-through road stop
|
||||||
|
@ -70,7 +69,7 @@ enum {
|
||||||
RVC_START_FRAME_AFTER_LONG_TRAM = 21,
|
RVC_START_FRAME_AFTER_LONG_TRAM = 21,
|
||||||
RVC_TURN_AROUND_START_FRAME_SHORT_TRAM = 16,
|
RVC_TURN_AROUND_START_FRAME_SHORT_TRAM = 16,
|
||||||
/* Stop frame for a vehicle in a drive-through stop */
|
/* Stop frame for a vehicle in a drive-through stop */
|
||||||
RVC_DRIVE_THROUGH_STOP_FRAME = 7,
|
RVC_DRIVE_THROUGH_STOP_FRAME = 11,
|
||||||
RVC_DEPOT_STOP_FRAME = 11,
|
RVC_DEPOT_STOP_FRAME = 11,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -463,18 +463,14 @@ void RoadVehicle::UpdateDeltaXY(Direction direction)
|
||||||
this->z_extent = 6;
|
this->z_extent = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearCrashedStation(RoadVehicle *v)
|
|
||||||
{
|
|
||||||
RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void DeleteLastRoadVeh(RoadVehicle *v)
|
static void DeleteLastRoadVeh(RoadVehicle *v)
|
||||||
{
|
{
|
||||||
Vehicle *u = v;
|
Vehicle *u = v;
|
||||||
for (; v->Next() != NULL; v = v->Next()) u = v;
|
for (; v->Next() != NULL; v = v->Next()) u = v;
|
||||||
u->SetNext(NULL);
|
u->SetNext(NULL);
|
||||||
|
|
||||||
if (IsTileType(v->tile, MP_STATION)) ClearCrashedStation(v);
|
/* Only leave the road stop when we're really gone. */
|
||||||
|
if (IsInsideMM(v->state, RVSB_IN_ROAD_STOP, RVSB_IN_ROAD_STOP_END)) RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
|
||||||
|
|
||||||
delete v;
|
delete v;
|
||||||
}
|
}
|
||||||
|
@ -540,7 +536,14 @@ static Vehicle *EnumCheckRoadVehCrashTrain(Vehicle *v, void *data)
|
||||||
uint RoadVehicle::Crash(bool flooded)
|
uint RoadVehicle::Crash(bool flooded)
|
||||||
{
|
{
|
||||||
uint pass = Vehicle::Crash(flooded);
|
uint pass = Vehicle::Crash(flooded);
|
||||||
if (this->IsRoadVehFront()) pass += 1; // driver
|
if (this->IsRoadVehFront()) {
|
||||||
|
pass += 1; // driver
|
||||||
|
|
||||||
|
/* If we're in a drive through road stop we ought to leave it */
|
||||||
|
if (IsInsideMM(this->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
|
||||||
|
RoadStop::GetByTile(this->tile, GetRoadStopType(this->tile))->Leave(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
|
this->crashed_ctr = flooded ? 2000 : 1; // max 2220, disappear pretty fast when flooded
|
||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
@ -1413,6 +1416,17 @@ again:
|
||||||
/* There is a vehicle in front overtake it if possible */
|
/* There is a vehicle in front overtake it if possible */
|
||||||
if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
|
if (v->overtaking == 0) RoadVehCheckOvertake(v, u);
|
||||||
if (v->overtaking == 0) v->cur_speed = u->cur_speed;
|
if (v->overtaking == 0) v->cur_speed = u->cur_speed;
|
||||||
|
|
||||||
|
/* In case an RV is stopped in a road stop, why not try to load? */
|
||||||
|
if (v->cur_speed == 0 && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END) &&
|
||||||
|
v->current_order.ShouldStopAtStation(v, GetStationIndex(v->tile)) &&
|
||||||
|
v->owner == GetTileOwner(v->tile) && !v->current_order.IsType(OT_LEAVESTATION) &&
|
||||||
|
GetRoadStopType(v->tile) == (v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK)) {
|
||||||
|
Station *st = Station::GetByTile(v->tile);
|
||||||
|
v->last_station_visited = st->index;
|
||||||
|
RoadVehArrivesAt(v, st);
|
||||||
|
v->BeginLoading();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1455,20 +1469,12 @@ again:
|
||||||
|
|
||||||
if (IsDriveThroughStopTile(v->tile)) {
|
if (IsDriveThroughStopTile(v->tile)) {
|
||||||
TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
|
TileIndex next_tile = TILE_ADD(v->tile, TileOffsByDir(v->direction));
|
||||||
RoadStopType type = v->IsBus() ? ROADSTOP_BUS : ROADSTOP_TRUCK;
|
|
||||||
|
|
||||||
/* Check if next inline bay is free */
|
/* Check if next inline bay is free */
|
||||||
if (IsDriveThroughStopTile(next_tile) && (GetRoadStopType(next_tile) == type) && GetStationIndex(v->tile) == GetStationIndex(next_tile)) {
|
if (RoadStop::IsDriveThroughRoadStopContinuation(v->tile, next_tile)) {
|
||||||
RoadStop *rs_n = RoadStop::GetByTile(next_tile, type);
|
v->frame++;
|
||||||
|
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false));
|
||||||
if (rs_n->IsFreeBay(HasBit(v->state, RVS_USING_SECOND_BAY))) {
|
return true;
|
||||||
/* Bay in next stop along is free - use it */
|
|
||||||
v->dest_tile = rs_n->xy;
|
|
||||||
|
|
||||||
v->frame++;
|
|
||||||
RoadZPosAffectSpeed(v, SetRoadVehPosition(v, x, y, false));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1360,7 +1360,7 @@ bool AfterLoadGame()
|
||||||
RoadVehicle *rv;
|
RoadVehicle *rv;
|
||||||
FOR_ALL_ROADVEHICLES(rv) {
|
FOR_ALL_ROADVEHICLES(rv) {
|
||||||
if (rv->state == 250 || rv->state == 251) {
|
if (rv->state == 250 || rv->state == 251) {
|
||||||
SetBit(rv->state, RVS_IS_STOPPING);
|
SetBit(rv->state, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1959,6 +1959,8 @@ bool AfterLoadGame()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Road stops is 'only' updating some caches */
|
||||||
|
AfterLoadRoadStops();
|
||||||
AfterLoadLabelMaps();
|
AfterLoadLabelMaps();
|
||||||
|
|
||||||
GamelogPrintDebug(1);
|
GamelogPrintDebug(1);
|
||||||
|
|
|
@ -190,7 +190,7 @@ void FixOldVehicles()
|
||||||
if (v->type == VEH_ROAD) {
|
if (v->type == VEH_ROAD) {
|
||||||
RoadVehicle *rv = RoadVehicle::From(v);
|
RoadVehicle *rv = RoadVehicle::From(v);
|
||||||
if (rv->state != RVSB_IN_DEPOT && rv->state != RVSB_WORMHOLE) {
|
if (rv->state != RVSB_IN_DEPOT && rv->state != RVSB_WORMHOLE) {
|
||||||
ClrBit(rv->state, RVS_IS_STOPPING);
|
ClrBit(rv->state, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
|
|
||||||
#include "saveload_internal.h"
|
#include "saveload_internal.h"
|
||||||
|
|
||||||
extern const uint16 SAVEGAME_VERSION = 129;
|
extern const uint16 SAVEGAME_VERSION = 130;
|
||||||
|
|
||||||
SavegameType _savegame_type; ///< type of savegame we are loading
|
SavegameType _savegame_type; ///< type of savegame we are loading
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ const SaveLoad *GetBaseStationDescription();
|
||||||
|
|
||||||
void AfterLoadVehicles(bool part_of_load);
|
void AfterLoadVehicles(bool part_of_load);
|
||||||
void AfterLoadStations();
|
void AfterLoadStations();
|
||||||
|
void AfterLoadRoadStops();
|
||||||
void AfterLoadLabelMaps();
|
void AfterLoadLabelMaps();
|
||||||
void UpdateHousesAndTowns();
|
void UpdateHousesAndTowns();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../roadstop_base.h"
|
#include "../roadstop_base.h"
|
||||||
#include "../vehicle_base.h"
|
#include "../vehicle_base.h"
|
||||||
#include "../newgrf_station.h"
|
#include "../newgrf_station.h"
|
||||||
|
#include "../station_map.h"
|
||||||
|
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
@ -108,6 +109,25 @@ void AfterLoadStations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Re)building of road stop caches after loading a savegame.
|
||||||
|
*/
|
||||||
|
void AfterLoadRoadStops()
|
||||||
|
{
|
||||||
|
/* First construct the drive through entries */
|
||||||
|
RoadStop *rs;
|
||||||
|
FOR_ALL_ROADSTOPS(rs) {
|
||||||
|
if (IsDriveThroughStopTile(rs->xy)) rs->MakeDriveThrough();
|
||||||
|
}
|
||||||
|
/* And then rebuild the data in those entries */
|
||||||
|
FOR_ALL_ROADSTOPS(rs) {
|
||||||
|
if (!HasBit(rs->status, RoadStop::RSSFB_BASE_ENTRY)) continue;
|
||||||
|
|
||||||
|
rs->GetEntry(DIAGDIR_NE)->Rebuild(rs);
|
||||||
|
rs->GetEntry(DIAGDIR_NW)->Rebuild(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static const SaveLoad _roadstop_desc[] = {
|
static const SaveLoad _roadstop_desc[] = {
|
||||||
SLE_VAR(RoadStop, xy, SLE_UINT32),
|
SLE_VAR(RoadStop, xy, SLE_UINT32),
|
||||||
SLE_CONDNULL(1, 0, 44),
|
SLE_CONDNULL(1, 0, 44),
|
||||||
|
|
|
@ -223,6 +223,8 @@ struct NPFSettings {
|
||||||
uint32 npf_road_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_crossing_penalty; ///< the penalty for level crossings
|
||||||
uint32 npf_road_drive_through_penalty; ///< the penalty for going through a drive-through road stop
|
uint32 npf_road_drive_through_penalty; ///< the penalty for going through a drive-through road stop
|
||||||
|
uint32 npf_road_dt_occupied_penalty; ///< the penalty multiplied by the fill percentage of a drive-through road stop
|
||||||
|
uint32 npf_road_bay_occupied_penalty; ///< the penalty multiplied by the fill percentage of a road bay
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Settings related to the yet another pathfinder. */
|
/** Settings related to the yet another pathfinder. */
|
||||||
|
@ -236,6 +238,8 @@ struct YAPFSettings {
|
||||||
uint32 road_curve_penalty; ///< penalty for curves
|
uint32 road_curve_penalty; ///< penalty for curves
|
||||||
uint32 road_crossing_penalty; ///< penalty for level crossing
|
uint32 road_crossing_penalty; ///< penalty for level crossing
|
||||||
uint32 road_stop_penalty; ///< penalty for going through a drive-through road stop
|
uint32 road_stop_penalty; ///< penalty for going through a drive-through road stop
|
||||||
|
uint32 road_stop_occupied_penalty; ///< penalty multiplied by the fill percentage of a drive-through road stop
|
||||||
|
uint32 road_stop_bay_occupied_penalty; ///< penalty multiplied by the fill percentage of a road bay
|
||||||
bool rail_firstred_twoway_eol; ///< treat first red two-way signal as dead end
|
bool rail_firstred_twoway_eol; ///< treat first red two-way signal as dead end
|
||||||
uint32 rail_firstred_penalty; ///< penalty for first red signal
|
uint32 rail_firstred_penalty; ///< penalty for first red signal
|
||||||
uint32 rail_firstred_exit_penalty; ///< penalty for first red exit signal
|
uint32 rail_firstred_exit_penalty; ///< penalty for first red exit signal
|
||||||
|
|
|
@ -1638,6 +1638,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||||
RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
|
RoadStopType rs_type = type ? ROADSTOP_TRUCK : ROADSTOP_BUS;
|
||||||
if (is_drive_through) {
|
if (is_drive_through) {
|
||||||
MakeDriveThroughRoadStop(tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts, (Axis)p1);
|
MakeDriveThroughRoadStop(tile, st->owner, road_owner, tram_owner, st->index, rs_type, rts, (Axis)p1);
|
||||||
|
road_stop->MakeDriveThrough();
|
||||||
} else {
|
} else {
|
||||||
MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
|
MakeRoadStop(tile, st->owner, st->index, rs_type, rts, (DiagDirection)p1);
|
||||||
}
|
}
|
||||||
|
@ -1721,6 +1722,13 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||||
pred->next = cur_stop->next;
|
pred->next = cur_stop->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsDriveThroughStopTile(tile)) {
|
||||||
|
/* Clears the tile for us */
|
||||||
|
cur_stop->ClearDriveThrough();
|
||||||
|
} else {
|
||||||
|
DoClearSquare(tile);
|
||||||
|
}
|
||||||
|
|
||||||
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
|
||||||
delete cur_stop;
|
delete cur_stop;
|
||||||
|
|
||||||
|
@ -1733,7 +1741,6 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DoClearSquare(tile);
|
|
||||||
st->rect.AfterRemoveTile(st, tile);
|
st->rect.AfterRemoveTile(st, tile);
|
||||||
|
|
||||||
st->UpdateVirtCoord();
|
st->UpdateVirtCoord();
|
||||||
|
|
|
@ -473,6 +473,8 @@ const SettingDesc _settings[] = {
|
||||||
SDT_VAR(GameSettings, pf.npf.npf_road_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL),
|
SDT_VAR(GameSettings, pf.npf.npf_road_curve_penalty, SLE_UINT, 0, 0, 1, 0, 100000, 0, STR_NULL, NULL),
|
||||||
SDT_VAR(GameSettings, pf.npf.npf_crossing_penalty, SLE_UINT, 0, 0, ( 3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
SDT_VAR(GameSettings, pf.npf.npf_crossing_penalty, SLE_UINT, 0, 0, ( 3 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
||||||
SDT_CONDVAR(GameSettings, pf.npf.npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, ( 8 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
SDT_CONDVAR(GameSettings, pf.npf.npf_road_drive_through_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, ( 8 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
||||||
|
SDT_CONDVAR(GameSettings, pf.npf.npf_road_dt_occupied_penalty, SLE_UINT,130, SL_MAX_VERSION, 0, 0, ( 8 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
||||||
|
SDT_CONDVAR(GameSettings, pf.npf.npf_road_bay_occupied_penalty, SLE_UINT,130, SL_MAX_VERSION, 0, 0, ( 15 * NPF_TILE_LENGTH), 0, 100000, 0, STR_NULL, NULL),
|
||||||
|
|
||||||
|
|
||||||
SDT_CONDBOOL(GameSettings, pf.yapf.disable_node_optimization, 28, SL_MAX_VERSION, 0, 0, false, STR_NULL, NULL),
|
SDT_CONDBOOL(GameSettings, pf.yapf.disable_node_optimization, 28, SL_MAX_VERSION, 0, 0, false, STR_NULL, NULL),
|
||||||
|
@ -504,6 +506,8 @@ const SettingDesc _settings[] = {
|
||||||
SDT_CONDVAR(GameSettings, pf.yapf.road_curve_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
SDT_CONDVAR(GameSettings, pf.yapf.road_curve_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 1 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||||
SDT_CONDVAR(GameSettings, pf.yapf.road_crossing_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
SDT_CONDVAR(GameSettings, pf.yapf.road_crossing_penalty, SLE_UINT, 33, SL_MAX_VERSION, 0, 0, 3 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||||
SDT_CONDVAR(GameSettings, pf.yapf.road_stop_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
SDT_CONDVAR(GameSettings, pf.yapf.road_stop_penalty, SLE_UINT, 47, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||||
|
SDT_CONDVAR(GameSettings, pf.yapf.road_stop_occupied_penalty, SLE_UINT,130, SL_MAX_VERSION, 0, 0, 8 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||||
|
SDT_CONDVAR(GameSettings, pf.yapf.road_stop_bay_occupied_penalty, SLE_UINT,130, SL_MAX_VERSION, 0, 0, 15 * YAPF_TILE_LENGTH, 0, 1000000, 0, STR_NULL, NULL),
|
||||||
|
|
||||||
SDT_CONDVAR(GameSettings, game_creation.land_generator, SLE_UINT8, 30, SL_MAX_VERSION, 0,MS, 1, 0, 1, 0, STR_CONFIG_SETTING_LAND_GENERATOR, NULL),
|
SDT_CONDVAR(GameSettings, game_creation.land_generator, SLE_UINT8, 30, SL_MAX_VERSION, 0,MS, 1, 0, 1, 0, STR_CONFIG_SETTING_LAND_GENERATOR, NULL),
|
||||||
SDT_CONDVAR(GameSettings, game_creation.oil_refinery_limit, SLE_UINT8, 30, SL_MAX_VERSION, 0, 0, 32, 12, 48, 0, STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE, NULL),
|
SDT_CONDVAR(GameSettings, game_creation.oil_refinery_limit, SLE_UINT8, 30, SL_MAX_VERSION, 0, 0, 32, 12, 48, 0, STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE, NULL),
|
||||||
|
|
Loading…
Reference in New Issue