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 #include "company_base.h"
00025
00026 #include "table/strings.h"
00027
00034 static void PaySharingFee(Vehicle *v, Owner infra_owner, Money cost)
00035 {
00036 Company *c = Company::Get(v->owner);
00037 if (!_settings_game.economy.sharing_payment_in_debt) {
00038
00039 cost = min(cost, (c->money - c->current_loan) << 8);
00040 if (cost <= 0) return;
00041 }
00042 v->profit_this_year -= cost;
00043 SubtractMoneyFromCompanyFract(v->owner, CommandCost(EXPENSES_SHARING_COST, cost));
00044 SubtractMoneyFromCompanyFract(infra_owner, CommandCost(EXPENSES_SHARING_INC, -cost));
00045 }
00046
00052 void PayStationSharingFee(Vehicle *v, const Station *st)
00053 {
00054 if (v->owner == st->owner || st->owner == OWNER_NONE || v->type == VEH_TRAIN) return;
00055 Money cost = _settings_game.economy.sharing_fee[v->type];
00056 PaySharingFee(v, st->owner, (cost << 8) / DAY_TICKS);
00057 }
00058
00063 void PayDailyTrackSharingFee(Train *v)
00064 {
00065 Owner owner = GetTileOwner(v->tile);
00066 if (owner == v->owner) return;
00067 Money cost = _settings_game.economy.sharing_fee[VEH_TRAIN] << 8;
00068
00069 cost = cost * v->gcache.cached_weight / 1000;
00070
00071 cost = cost * v->running_ticks / DAY_TICKS;
00072 if (cost != 0) PaySharingFee(v, owner, cost);
00073 }
00074
00081 static bool VehiclePositionIsAllowed(const Vehicle *v, Owner owner = INVALID_OWNER)
00082 {
00083 switch (v->type) {
00084 case VEH_TRAIN:
00085 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00086 if (!IsInfraTileUsageAllowed(VEH_TRAIN, v->owner, u->tile) || GetTileOwner(u->tile) == owner) return false;
00087 }
00088 return true;
00089 case VEH_ROAD:
00090 for (const Vehicle *u = v; u != NULL; u = u->Next()) {
00091 if (IsRoadDepotTile(u->tile) || IsStandardRoadStopTile(u->tile)) {
00092 if (!IsInfraTileUsageAllowed(VEH_ROAD, v->owner, u->tile) || GetTileOwner(u->tile) == owner) return false;
00093 }
00094 }
00095 return true;
00096 case VEH_SHIP:
00097 if (IsShipDepotTile(v->tile) && v->IsStoppedInDepot()) {
00098 if (!IsInfraTileUsageAllowed(VEH_SHIP, v->owner, v->tile) || GetTileOwner(v->tile) == owner) return false;
00099 }
00100 return true;
00101 case VEH_AIRCRAFT: {
00102 const Aircraft *a = Aircraft::From(v);
00103 if (a->state != FLYING && Station::IsValidID(a->targetairport)) {
00104 Owner station_owner = Station::Get(a->targetairport)->owner;
00105 if (!IsInfraUsageAllowed(VEH_AIRCRAFT, a->owner, station_owner) || station_owner == owner) return false;
00106 }
00107 return true;
00108 }
00109 default: return true;
00110 }
00111 }
00112
00121 static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owner owner = INVALID_OWNER)
00122 {
00123 Owner dest_owner;
00124 switch (order->GetType()) {
00125 case OT_GOTO_STATION:
00126 case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break;
00127 case OT_GOTO_DEPOT: dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break;
00128 case OT_LOADING: dest_owner = Station::Get(v->last_station_visited)->owner; break;
00129 default: return true;
00130 }
00131 return dest_owner != owner && IsInfraUsageAllowed(v->type, v->owner, dest_owner);
00132 }
00133
00139 static void RemoveAndSellVehicle(Vehicle *v, bool give_money)
00140 {
00141 assert(v->Previous() == NULL);
00142
00143 if (give_money) {
00144
00145 Money value = 0;
00146 for (Vehicle *u = v->First(); u != NULL; u = u->Next()) {
00147 value += v->value;
00148 }
00149 CompanyID old = _current_company;
00150 _current_company = v->owner;
00151 SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -value));
00152 _current_company = old;
00153 }
00154
00155
00156 if (_settings_game.economy.infrastructure_sharing[VEH_TRAIN] && v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
00157 DeleteVisibleTrain(Train::From(v));
00158 } else {
00159 delete v;
00160 }
00161 }
00162
00166 static void FixAllReservations()
00167 {
00168
00169 assert(!_settings_game.economy.infrastructure_sharing[VEH_TRAIN]);
00170 Train *v;
00171 FOR_ALL_TRAINS(v) {
00172 if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0) continue;
00173
00174
00175
00176
00177
00178 PBSTileInfo end_tile_info = FollowTrainReservation(v);
00179
00180
00181 TileIndex next_tile = end_tile_info.tile + TileOffsByDiagDir(TrackdirToExitdir(end_tile_info.trackdir));
00182
00183 if (GetReservedTrackbits(next_tile) == TRACK_BIT_NONE) continue;
00184
00185
00186 _settings_game.economy.infrastructure_sharing[VEH_TRAIN] = true;
00187 PBSTileInfo end_tile_info2 = FollowTrainReservation(v);
00188
00189 if (end_tile_info.tile != end_tile_info2.tile || end_tile_info.trackdir != end_tile_info2.trackdir) {
00190 FreeTrainTrackReservation(v);
00191 _settings_game.economy.infrastructure_sharing[VEH_TRAIN] = false;
00192 TryPathReserve(v, true);
00193 } else {
00194 _settings_game.economy.infrastructure_sharing[VEH_TRAIN] = false;
00195 }
00196 }
00197 }
00198
00206 bool CheckSharingChangePossible(VehicleType type)
00207 {
00208 if (type != VEH_AIRCRAFT) YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
00209
00210 if (_settings_game.economy.infrastructure_sharing[type]) return true;
00211
00212 StringID error_message = STR_NULL;
00213 Vehicle *v;
00214 FOR_ALL_VEHICLES(v) {
00215 if (type != v->type) continue;
00216 if (v->Previous() != NULL) continue;
00217
00218
00219 if (!VehiclePositionIsAllowed(v)) {
00220 error_message = STR_CONFIG_SETTING_SHARING_USED_BY_VEHICLES;
00221
00222 break;
00223 }
00224
00225
00226 if (!OrderDestinationIsAllowed(&v->current_order, v)) {
00227 error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
00228 }
00229
00230
00231 if (v->FirstShared() != v) continue;
00232 Order *o;
00233 FOR_VEHICLE_ORDERS(v, o) {
00234 if (!OrderDestinationIsAllowed(o, v)) {
00235 error_message = STR_CONFIG_SETTING_SHARING_ORDERS_TO_OTHERS;
00236 }
00237 }
00238 }
00239
00240 if (error_message != STR_NULL) {
00241 ShowErrorMessage(error_message, INVALID_STRING_ID, WL_ERROR);
00242 return false;
00243 }
00244
00245 if (type == VEH_TRAIN) FixAllReservations();
00246
00247 return true;
00248 }
00249
00256 void HandleSharingCompanyDeletion(Owner owner)
00257 {
00258 YapfNotifyTrackLayoutChange(INVALID_TILE, INVALID_TRACK);
00259
00260 Vehicle *v;
00261 FOR_ALL_VEHICLES(v) {
00262 if (!IsCompanyBuildableVehicleType(v) || v->Previous() != NULL) continue;
00263
00264 if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
00265 RemoveAndSellVehicle(v, v->owner != owner);
00266 continue;
00267 }
00268
00269 if (!OrderDestinationIsAllowed(&v->current_order, v, owner)) {
00270 if (v->current_order.IsType(OT_LOADING)) {
00271 v->LeaveStation();
00272 } else {
00273 v->current_order.MakeDummy();
00274 }
00275 SetWindowDirty(WC_VEHICLE_VIEW, v->index);
00276 }
00277
00278
00279 if (v->FirstShared() != v) continue;
00280
00281 Order *o;
00282 int id = -1;
00283 FOR_VEHICLE_ORDERS(v, o) {
00284 id++;
00285 if (OrderDestinationIsAllowed(o, v, owner)) continue;
00286
00287 o->MakeDummy();
00288 for (const Vehicle *w = v; w != NULL; w = w->NextShared()) {
00289
00290 InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8));
00291 InvalidateVehicleOrder(w, (id << 8) | INVALID_VEH_ORDER_ID);
00292 }
00293 }
00294 }
00295 }
00296
00302 void UpdateAllBlockSignals(Owner owner)
00303 {
00304 Owner last_owner = INVALID_OWNER;
00305 TileIndex tile = 0;
00306 do {
00307 if (IsTileType(tile, MP_RAILWAY) && HasSignals(tile)) {
00308 Owner track_owner = GetTileOwner(tile);
00309 if (owner != INVALID_OWNER && track_owner != owner) continue;
00310
00311 if (!IsOneSignalBlock(track_owner, last_owner)) {
00312
00313
00314 UpdateSignalsInBuffer();
00315 last_owner = track_owner;
00316 }
00317 TrackBits bits = GetTrackBits(tile);
00318 do {
00319 Track track = RemoveFirstTrack(&bits);
00320 if (HasSignalOnTrack(tile, track)) {
00321 AddTrackToSignalBuffer(tile, track, track_owner);
00322 }
00323 } while (bits != TRACK_BIT_NONE);
00324 } else if (IsLevelCrossingTile(tile) && (owner == INVALID_OWNER || GetTileOwner(tile) == owner)) {
00325 UpdateLevelCrossing(tile);
00326 }
00327 } while (++tile != MapSize());
00328
00329 UpdateSignalsInBuffer();
00330 }