00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "infrastructure_func.h"
00014 #include "train.h"
00015 #include "aircraft.h"
00016 #include "vehicle_func.h"
00017 #include "station_base.h"
00018 #include "depot_base.h"
00019 #include "pbs.h"
00020 #include "signal_func.h"
00021 #include "window_func.h"
00022 #include "gui.h"
00023 #include "pathfinder/yapf/yapf_cache.h"
00024
00025 #include "table/strings.h"
00026
00033 static void PaySharingFee(Vehicle *v, Owner infra_owner, Money cost)
00034 {
00035 Company *c = Company::Get(v->owner);
00036 if (!_settings_game.sharing.payment_in_debt) {
00037
00038 cost = min(cost, (c->money - c->current_loan) << 8);
00039 if (cost <= 0) return;
00040 }
00041 v->profit_this_year -= cost;
00042 SubtractMoneyFromCompanyFract(v->owner, CommandCost(v->GetExpenseType(false), cost));
00043 SubtractMoneyFromCompanyFract(infra_owner, CommandCost(v->GetExpenseType(true), -cost));
00044 }
00045
00051 void PayStationSharingFee(Vehicle *v, const Station *st)
00052 {
00053 if (v->owner == st->owner || st->owner == OWNER_NONE || v->type == VEH_TRAIN) return;
00054 Money cost;
00055 switch (v->type) {
00056 case VEH_ROAD: cost = _settings_game.sharing.fee_road; break;
00057 case VEH_SHIP: cost = _settings_game.sharing.fee_water; break;
00058 case VEH_AIRCRAFT: cost = _settings_game.sharing.fee_air; break;
00059 default: NOT_REACHED();
00060 }
00061 PaySharingFee(v, st->owner, (cost << 8) / DAY_TICKS);
00062 }
00063
00068 void PayDailyTrackSharingFee(Train *v)
00069 {
00070 Owner owner = GetTileOwner(v->tile);
00071 if (owner == v->owner) return;
00072 Money cost = _settings_game.sharing.fee_rail << 8;
00073
00074 cost = cost * v->tcache.cached_weight / 1000;
00075
00076 cost = cost * v->running_ticks / DAY_TICKS;
00077 if (cost != 0) PaySharingFee(v, owner, cost);
00078 }
00079
00086 static bool VehiclePositionIsAllowed(const Vehicle *v, Owner owner = INVALID_OWNER)
00087 {
00088 switch (v->type) {
00089 case VEH_TRAIN:
00090 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00091 if (!IsInfraUsageAllowed(GetTileOwner(u->tile), v->owner, VEH_TRAIN) || GetTileOwner(u->tile) == owner) return false;
00092 }
00093 return true;
00094 case VEH_ROAD:
00095 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00096 if (IsRoadDepotTile(u->tile) || IsStandardRoadStopTile(u->tile)) {
00097 if (!IsInfraUsageAllowed(GetTileOwner(u->tile), v->owner, VEH_ROAD) || GetTileOwner(u->tile) == owner) return false;
00098 }
00099 }
00100 return true;
00101 case VEH_SHIP:
00102 if (IsShipDepotTile(v->tile) && v->IsStoppedInDepot()) {
00103 return IsInfraUsageAllowed(GetTileOwner(v->tile), v->owner, VEH_SHIP) && GetTileOwner(v->tile) != owner;
00104 }
00105 return true;
00106 case VEH_AIRCRAFT: {
00107 const Aircraft *a = Aircraft::From(v);
00108 if (a->state != FLYING && Station::IsValidID(a->targetairport)) {
00109 Owner station_owner = Station::Get(a->targetairport)->owner;
00110 return IsInfraUsageAllowed(station_owner, a->owner, VEH_AIRCRAFT) && station_owner != owner;
00111 }
00112 return true;
00113 }
00114 default: return true;
00115 }
00116 }
00117
00126 static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owner owner = INVALID_OWNER)
00127 {
00128 Owner dest_owner;
00129 switch (order->GetType()) {
00130 case OT_GOTO_STATION:
00131 case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
00132 case OT_GOTO_DEPOT: dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
00133 case OT_LOADING: dest_owner = Station::Get(v->last_station_visited)->owner; break;
00134 default: return true;
00135 }
00136 return dest_owner != owner && IsInfraUsageAllowed(dest_owner, v->owner, v->type);
00137 }
00138
00144 static void RemoveAndSellVehicle(Vehicle *v, bool give_money)
00145 {
00146 assert(v->Previous() == NULL);
00147
00148 if (give_money) {
00149
00150 Money value = 0;
00151 for (Vehicle *u = v->First(); u != NULL; u = u->Next()) {
00152 value += v->value;
00153 }
00154 CompanyID old = _current_company;
00155 _current_company = v->owner;
00156 SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -value));
00157 _current_company = old;
00158 }
00159
00160
00161 if (_settings_game.sharing.sharing_rail && v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
00162 DeleteVisibleTrain(Train::From(v));
00163 } else {
00164 delete v;
00165 }
00166 }
00167
00171 static void FixAllReservations()
00172 {
00173
00174 assert(!_settings_game.sharing.sharing_rail);
00175 Train *v;
00176 FOR_ALL_TRAINS(v) {
00177 if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) continue;
00178
00179
00180
00181
00182
00183 PBSTileInfo end_tile_info = FollowTrainReservation(v);
00184
00185
00186 TileIndex next_tile = end_tile_info.tile + TileOffsByDiagDir(TrackdirToExitdir(end_tile_info.trackdir));
00187
00188 if (GetReservedTrackbits(next_tile) == TRACK_BIT_NONE) continue;
00189
00190
00191 _settings_game.sharing.sharing_rail = true;
00192 PBSTileInfo end_tile_info2 = FollowTrainReservation(v);
00193
00194 if (end_tile_info.tile != end_tile_info2.tile || end_tile_info.trackdir != end_tile_info2.trackdir) {
00195 FreeTrainTrackReservation(v);
00196 _settings_game.sharing.sharing_rail = false;
00197 TryPathReserve(v, true);
00198 } else {
00199 _settings_game.sharing.sharing_rail = false;
00200 }
00201 }
00202 }
00203
00211 bool CheckSharingChangePossible(VehicleType type)
00212 {
00213 if (type != VEH_AIRCRAFT) YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
00214
00215 if (GetSharingSetting(type)) return true;
00216
00217 StringID error_message = STR_NULL;
00218 Vehicle *v;
00219 FOR_ALL_VEHICLES(v) {
00220 if (type != v->type) continue;
00221 if (v->Previous() != NULL) continue;
00222
00223
00224 if (!VehiclePositionIsAllowed(v)) {
00225 error_message = STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES;
00226
00227 break;
00228 }
00229
00230
00231 if (!OrderDestinationIsAllowed(&v->current_order, v)) {
00232 error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
00233 }
00234
00235
00236 if (v->FirstShared() != v) continue;
00237 Order *o;
00238 FOR_VEHICLE_ORDERS(v, o) {
00239 if (!OrderDestinationIsAllowed(o, v)) {
00240 error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
00241 }
00242 }
00243 }
00244
00245 if (error_message != STR_NULL) {
00246 ShowErrorMessage(error_message, INVALID_STRING_ID, 0, 0);
00247 return false;
00248 }
00249
00250 if (type == VEH_TRAIN) FixAllReservations();
00251
00252 return true;
00253 }
00254
00261 void HandleSharingCompanyDeletion(Owner owner)
00262 {
00263 YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
00264
00265 Vehicle *v;
00266 FOR_ALL_VEHICLES(v) {
00267 if (!IsCompanyBuildableVehicleType(v) || v->Previous() != NULL) continue;
00268
00269 if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
00270 RemoveAndSellVehicle(v, v->owner != owner);
00271 continue;
00272 }
00273
00274 if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
00275 if (v->current_order.IsType(OT_LOADING)) {
00276 v->LeaveStation();
00277 } else {
00278 v->current_order.MakeDummy();
00279 }
00280 SetWindowDirty(WC_VEHICLE_VIEW, v->index);
00281 }
00282
00283
00284 if (v->FirstShared() != v) continue;
00285
00286 Order *o;
00287 int id = -1;
00288 FOR_VEHICLE_ORDERS(v, o) {
00289 id++;
00290 if (OrderDestinationIsAllowed(o, v, owner)) continue;
00291
00292 o->MakeDummy();
00293 for (const Vehicle *w = v; w != NULL; w = w->NextShared()) {
00294
00295 InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
00296 InvalidateVehicleOrder(w, (id << 8) | INVALID_VEH_ORDER_ID);
00297 }
00298 }
00299 }
00300 }
00301
00307 void UpdateAllBlockSignals(Owner owner)
00308 {
00309 Owner last_owner = INVALID_OWNER;
00310 TileIndex tile = 0;
00311 do {
00312 if (IsTileType(tile, MP_RAILWAY) && HasSignals(tile)) {
00313 Owner track_owner = GetTileOwner(tile);
00314 if (owner != INVALID_OWNER && track_owner != owner) continue;
00315
00316 if (!IsOneSignalBlock(track_owner, last_owner)) {
00317
00318
00319 UpdateSignalsInBuffer();
00320 last_owner = track_owner;
00321 }
00322 TrackBits bits = GetTrackBits(tile);
00323 do {
00324 Track track = RemoveFirstTrack(&bits);
00325 if (HasSignalOnTrack(tile, track)) {
00326 AddTrackToSignalBuffer(tile, track, track_owner);
00327 }
00328 } while (bits != TRACK_BIT_NONE);
00329 } else if (IsLevelCrossingTile(tile) && (owner == INVALID_OWNER || GetTileOwner(tile) == owner)) {
00330 UpdateLevelCrossing(tile);
00331 }
00332 } while (++tile != MapSize());
00333
00334 UpdateSignalsInBuffer();
00335 }