OpenTTD Source  20241120-master-g6d3adc6169
vehicle_cmd.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "roadveh.h"
12 #include "news_func.h"
13 #include "airport.h"
14 #include "command_func.h"
15 #include "company_func.h"
16 #include "train.h"
17 #include "aircraft.h"
18 #include "newgrf_text.h"
19 #include "vehicle_func.h"
20 #include "string_func.h"
21 #include "depot_map.h"
22 #include "vehiclelist.h"
23 #include "engine_func.h"
24 #include "articulated_vehicles.h"
25 #include "autoreplace_gui.h"
26 #include "group.h"
27 #include "order_backup.h"
28 #include "ship.h"
29 #include "newgrf.h"
30 #include "company_base.h"
31 #include "core/random_func.hpp"
32 #include "vehicle_cmd.h"
33 #include "aircraft_cmd.h"
34 #include "autoreplace_cmd.h"
35 #include "group_cmd.h"
36 #include "order_cmd.h"
37 #include "roadveh_cmd.h"
38 #include "train_cmd.h"
39 #include "ship_cmd.h"
40 #include <sstream>
41 #include <iomanip>
42 
43 #include "table/strings.h"
44 
45 #include "safeguards.h"
46 
47 /* Tables used in vehicle_func.h to find the right error message for a certain vehicle type */
48 const StringID _veh_build_msg_table[] = {
49  STR_ERROR_CAN_T_BUY_TRAIN,
50  STR_ERROR_CAN_T_BUY_ROAD_VEHICLE,
51  STR_ERROR_CAN_T_BUY_SHIP,
52  STR_ERROR_CAN_T_BUY_AIRCRAFT,
53 };
54 
55 const StringID _veh_sell_msg_table[] = {
56  STR_ERROR_CAN_T_SELL_TRAIN,
57  STR_ERROR_CAN_T_SELL_ROAD_VEHICLE,
58  STR_ERROR_CAN_T_SELL_SHIP,
59  STR_ERROR_CAN_T_SELL_AIRCRAFT,
60 };
61 
62 const StringID _veh_refit_msg_table[] = {
63  STR_ERROR_CAN_T_REFIT_TRAIN,
64  STR_ERROR_CAN_T_REFIT_ROAD_VEHICLE,
65  STR_ERROR_CAN_T_REFIT_SHIP,
66  STR_ERROR_CAN_T_REFIT_AIRCRAFT,
67 };
68 
69 const StringID _send_to_depot_msg_table[] = {
70  STR_ERROR_CAN_T_SEND_TRAIN_TO_DEPOT,
71  STR_ERROR_CAN_T_SEND_ROAD_VEHICLE_TO_DEPOT,
72  STR_ERROR_CAN_T_SEND_SHIP_TO_DEPOT,
73  STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR,
74 };
75 
76 
87 std::tuple<CommandCost, VehicleID, uint, uint16_t, CargoArray> CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id)
88 {
89  /* Elementary check for valid location. */
90  if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
91 
92  VehicleType type = GetDepotVehicleType(tile);
93 
94  /* Validate the engine type. */
95  if (!IsEngineBuildable(eid, type, _current_company)) return { CommandCost(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE + type), INVALID_VEHICLE, 0, 0, {} };
96 
97  /* Validate the cargo type. */
98  if (cargo >= NUM_CARGO && IsValidCargoID(cargo)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
99 
100  const Engine *e = Engine::Get(eid);
102 
103  /* Engines without valid cargo should not be available */
104  CargoID default_cargo = e->GetDefaultCargoType();
105  if (!IsValidCargoID(default_cargo)) return { CMD_ERROR, INVALID_VEHICLE, 0, 0, {} };
106 
107  bool refitting = IsValidCargoID(cargo) && cargo != default_cargo;
108 
109  /* Check whether the number of vehicles we need to build can be built according to pool space. */
110  uint num_vehicles;
111  switch (type) {
112  case VEH_TRAIN: num_vehicles = (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + CountArticulatedParts(eid, false); break;
113  case VEH_ROAD: num_vehicles = 1 + CountArticulatedParts(eid, false); break;
114  case VEH_SHIP: num_vehicles = 1; break;
115  case VEH_AIRCRAFT: num_vehicles = e->u.air.subtype & AIR_CTOL ? 2 : 3; break;
116  default: NOT_REACHED(); // Safe due to IsDepotTile()
117  }
118  if (!Vehicle::CanAllocateItem(num_vehicles)) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0, {} };
119 
120  /* Check whether we can allocate a unit number. Autoreplace does not allocate
121  * an unit number as it will (always) reuse the one of the replaced vehicle
122  * and (train) wagons don't have an unit number in any scenario. */
123  UnitID unit_num = (flags & DC_QUERY_COST || flags & DC_AUTOREPLACE || (type == VEH_TRAIN && e->u.rail.railveh_type == RAILVEH_WAGON)) ? 0 : GetFreeUnitNumber(type);
124  if (unit_num == UINT16_MAX) return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE, 0, 0, {} };
125 
126  /* If we are refitting we need to temporarily purchase the vehicle to be able to
127  * test it. */
128  DoCommandFlag subflags = flags;
129  if (refitting && !(flags & DC_EXEC)) subflags |= DC_EXEC | DC_AUTOREPLACE;
130 
131  /* Vehicle construction needs random bits, so we have to save the random
132  * seeds to prevent desyncs. */
133  SavedRandomSeeds saved_seeds;
134  SaveRandomSeeds(&saved_seeds);
135 
136  Vehicle *v = nullptr;
137  switch (type) {
138  case VEH_TRAIN: value.AddCost(CmdBuildRailVehicle(subflags, tile, e, &v)); break;
139  case VEH_ROAD: value.AddCost(CmdBuildRoadVehicle(subflags, tile, e, &v)); break;
140  case VEH_SHIP: value.AddCost(CmdBuildShip (subflags, tile, e, &v)); break;
141  case VEH_AIRCRAFT: value.AddCost(CmdBuildAircraft (subflags, tile, e, &v)); break;
142  default: NOT_REACHED(); // Safe due to IsDepotTile()
143  }
144 
145  VehicleID veh_id = INVALID_VEHICLE;
146  uint refitted_capacity = 0;
147  uint16_t refitted_mail_capacity = 0;
148  CargoArray cargo_capacities{};
149  if (value.Succeeded()) {
150  if (subflags & DC_EXEC) {
151  v->unitnumber = unit_num;
152  v->value = value.GetCost();
153  veh_id = v->index;
154  }
155 
156  if (refitting) {
157  /* Refit only one vehicle. If we purchased an engine, it may have gained free wagons. */
158  CommandCost cc;
159  std::tie(cc, refitted_capacity, refitted_mail_capacity, cargo_capacities) = CmdRefitVehicle(flags, v->index, cargo, 0, false, false, 1);
160  value.AddCost(cc);
161  } else {
162  /* Fill in non-refitted capacities */
163  if (e->type == VEH_TRAIN || e->type == VEH_ROAD) {
164  cargo_capacities = GetCapacityOfArticulatedParts(eid);
165  refitted_capacity = cargo_capacities[default_cargo];
166  refitted_mail_capacity = 0;
167  } else {
168  refitted_capacity = e->GetDisplayDefaultCapacity(&refitted_mail_capacity);
169  cargo_capacities[default_cargo] = refitted_capacity;
170  CargoID mail = GetCargoIDByLabel(CT_MAIL);
171  if (IsValidCargoID(mail)) cargo_capacities[mail] = refitted_mail_capacity;
172  }
173  }
174 
175  if (flags & DC_EXEC) {
176  if (type == VEH_TRAIN && use_free_vehicles && !(flags & DC_AUTOREPLACE) && Train::From(v)->IsEngine()) {
177  /* Move any free wagons to the new vehicle. */
179  }
180 
184  if (IsLocalCompany()) {
185  InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the auto replace window (must be called before incrementing num_engines)
186  }
187  }
188 
189  if (subflags & DC_EXEC) {
192 
193  if (v->IsPrimaryVehicle()) {
195  if (!(subflags & DC_AUTOREPLACE)) OrderBackup::Restore(v, client_id);
196  }
197 
198  Company::Get(v->owner)->freeunits[v->type].UseID(v->unitnumber);
199  }
200 
201 
202  /* If we are not in DC_EXEC undo everything */
203  if (flags != subflags) {
205  }
206  }
207 
208  /* Only restore if we actually did some refitting */
209  if (flags != subflags) RestoreRandomSeeds(saved_seeds);
210 
211  return { value, veh_id, refitted_capacity, refitted_mail_capacity, cargo_capacities };
212 }
213 
223 CommandCost CmdSellVehicle(DoCommandFlag flags, VehicleID v_id, bool sell_chain, bool backup_order, ClientID client_id)
224 {
225  Vehicle *v = Vehicle::GetIfValid(v_id);
226  if (v == nullptr) return CMD_ERROR;
227 
228  Vehicle *front = v->First();
229 
230  CommandCost ret = CheckOwnership(front->owner);
231  if (ret.Failed()) return ret;
232 
233  if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED);
234 
235  if (!front->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type);
236 
237  /* Can we actually make the order backup, i.e. are there enough orders? */
238  if (backup_order &&
239  front->orders != nullptr &&
240  !front->orders->IsShared() &&
242  /* Only happens in exceptional cases when there aren't enough orders anyhow.
243  * Thus it should be safe to just drop the orders in that case. */
244  backup_order = false;
245  }
246 
247  if (v->type == VEH_TRAIN) {
248  ret = CmdSellRailWagon(flags, v, sell_chain, backup_order, client_id);
249  } else {
250  ret = CommandCost(EXPENSES_NEW_VEHICLES, -front->value);
251 
252  if (flags & DC_EXEC) {
253  if (front->IsPrimaryVehicle() && backup_order) OrderBackup::Backup(front, client_id);
254  delete front;
255  }
256  }
257 
258  return ret;
259 }
260 
270 static int GetRefitCostFactor(const Vehicle *v, EngineID engine_type, CargoID new_cid, uint8_t new_subtype, bool *auto_refit_allowed)
271 {
272  /* Prepare callback param with info about the new cargo type. */
273  const Engine *e = Engine::Get(engine_type);
274 
275  /* Is this vehicle a NewGRF vehicle? */
276  if (e->GetGRF() != nullptr) {
277  const CargoSpec *cs = CargoSpec::Get(new_cid);
278  uint32_t param1 = (cs->classes << 16) | (new_subtype << 8) | e->GetGRF()->cargo_map[new_cid];
279 
280  uint16_t cb_res = GetVehicleCallback(CBID_VEHICLE_REFIT_COST, param1, 0, engine_type, v);
281  if (cb_res != CALLBACK_FAILED) {
282  *auto_refit_allowed = HasBit(cb_res, 14);
283  int factor = GB(cb_res, 0, 14);
284  if (factor >= 0x2000) factor -= 0x4000; // Treat as signed integer.
285  return factor;
286  }
287  }
288 
289  *auto_refit_allowed = e->info.refit_cost == 0;
290  return (v == nullptr || v->cargo_type != new_cid) ? e->info.refit_cost : 0;
291 }
292 
302 static CommandCost GetRefitCost(const Vehicle *v, EngineID engine_type, CargoID new_cid, uint8_t new_subtype, bool *auto_refit_allowed)
303 {
304  ExpensesType expense_type;
305  const Engine *e = Engine::Get(engine_type);
306  Price base_price;
307  int cost_factor = GetRefitCostFactor(v, engine_type, new_cid, new_subtype, auto_refit_allowed);
308  switch (e->type) {
309  case VEH_SHIP:
310  base_price = PR_BUILD_VEHICLE_SHIP;
311  expense_type = EXPENSES_SHIP_RUN;
312  break;
313 
314  case VEH_ROAD:
315  base_price = PR_BUILD_VEHICLE_ROAD;
316  expense_type = EXPENSES_ROADVEH_RUN;
317  break;
318 
319  case VEH_AIRCRAFT:
320  base_price = PR_BUILD_VEHICLE_AIRCRAFT;
321  expense_type = EXPENSES_AIRCRAFT_RUN;
322  break;
323 
324  case VEH_TRAIN:
325  base_price = (e->u.rail.railveh_type == RAILVEH_WAGON) ? PR_BUILD_VEHICLE_WAGON : PR_BUILD_VEHICLE_TRAIN;
326  cost_factor <<= 1;
327  expense_type = EXPENSES_TRAIN_RUN;
328  break;
329 
330  default: NOT_REACHED();
331  }
332  if (cost_factor < 0) {
333  return CommandCost(expense_type, -GetPrice(base_price, -cost_factor, e->GetGRF(), -10));
334  } else {
335  return CommandCost(expense_type, GetPrice(base_price, cost_factor, e->GetGRF(), -10));
336  }
337 }
338 
340 struct RefitResult {
342  uint capacity;
344  uint8_t subtype;
345 };
346 
359 static std::tuple<CommandCost, uint, uint16_t, CargoArray> RefitVehicle(Vehicle *v, bool only_this, uint8_t num_vehicles, CargoID new_cid, uint8_t new_subtype, DoCommandFlag flags, bool auto_refit)
360 {
361  CommandCost cost(v->GetExpenseType(false));
362  uint total_capacity = 0;
363  uint total_mail_capacity = 0;
364  num_vehicles = num_vehicles == 0 ? UINT8_MAX : num_vehicles;
365  CargoArray cargo_capacities{};
366 
367  VehicleSet vehicles_to_refit;
368  if (!only_this) {
369  GetVehicleSet(vehicles_to_refit, v, num_vehicles);
370  /* In this case, we need to check the whole chain. */
371  v = v->First();
372  }
373 
374  std::vector<RefitResult> refit_result;
375 
377  uint8_t actual_subtype = new_subtype;
378  for (; v != nullptr; v = (only_this ? nullptr : v->Next())) {
379  /* Reset actual_subtype for every new vehicle */
380  if (!v->IsArticulatedPart()) actual_subtype = new_subtype;
381 
382  if (v->type == VEH_TRAIN && std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), v->index) == vehicles_to_refit.end() && !only_this) continue;
383 
384  const Engine *e = v->GetEngine();
385  if (!e->CanCarryCargo()) continue;
386 
387  /* If the vehicle is not refittable, or does not allow automatic refitting,
388  * count its capacity nevertheless if the cargo matches */
389  bool refittable = HasBit(e->info.refit_mask, new_cid) && (!auto_refit || HasBit(e->info.misc_flags, EF_AUTO_REFIT));
390  if (!refittable && v->cargo_type != new_cid) {
391  uint amount = e->DetermineCapacity(v, nullptr);
392  if (amount > 0) cargo_capacities[v->cargo_type] += amount;
393  continue;
394  }
395 
396  /* Determine best fitting subtype if requested */
397  if (actual_subtype == 0xFF) {
398  actual_subtype = GetBestFittingSubType(v, v, new_cid);
399  }
400 
401  /* Back up the vehicle's cargo type */
402  CargoID temp_cid = v->cargo_type;
403  uint8_t temp_subtype = v->cargo_subtype;
404  if (refittable) {
405  v->cargo_type = new_cid;
406  v->cargo_subtype = actual_subtype;
407  }
408 
409  uint16_t mail_capacity = 0;
410  uint amount = e->DetermineCapacity(v, &mail_capacity);
411  total_capacity += amount;
412  /* mail_capacity will always be zero if the vehicle is not an aircraft. */
413  total_mail_capacity += mail_capacity;
414 
415  cargo_capacities[new_cid] += amount;
416  CargoID mail = GetCargoIDByLabel(CT_MAIL);
417  if (IsValidCargoID(mail)) cargo_capacities[mail] += mail_capacity;
418 
419  if (!refittable) continue;
420 
421  /* Restore the original cargo type */
422  v->cargo_type = temp_cid;
423  v->cargo_subtype = temp_subtype;
424 
425  bool auto_refit_allowed;
426  CommandCost refit_cost = GetRefitCost(v, v->engine_type, new_cid, actual_subtype, &auto_refit_allowed);
427  if (auto_refit && (flags & DC_QUERY_COST) == 0 && !auto_refit_allowed) {
428  /* Sorry, auto-refitting not allowed, subtract the cargo amount again from the total.
429  * When querrying cost/capacity (for example in order refit GUI), we always assume 'allowed'.
430  * It is not predictable. */
431  total_capacity -= amount;
432  total_mail_capacity -= mail_capacity;
433 
434  if (v->cargo_type == new_cid) {
435  /* Add the old capacity nevertheless, if the cargo matches */
436  total_capacity += v->cargo_cap;
437  if (v->type == VEH_AIRCRAFT) total_mail_capacity += v->Next()->cargo_cap;
438  }
439  continue;
440  }
441  cost.AddCost(refit_cost);
442 
443  /* Record the refitting.
444  * Do not execute the refitting immediately, so DetermineCapacity and GetRefitCost do the same in test and exec run.
445  * (weird NewGRFs)
446  * Note:
447  * - If the capacity of vehicles depends on other vehicles in the chain, the actual capacity is
448  * set after RefitVehicle() via ConsistChanged() and friends. The estimation via _returned_refit_capacity will be wrong.
449  * - We have to call the refit cost callback with the pre-refit configuration of the chain because we want refit and
450  * autorefit to behave the same, and we need its result for auto_refit_allowed.
451  */
452  refit_result.push_back({v, amount, mail_capacity, actual_subtype});
453  }
454 
455  if (flags & DC_EXEC) {
456  /* Store the result */
457  for (RefitResult &result : refit_result) {
458  Vehicle *u = result.v;
459  u->refit_cap = (u->cargo_type == new_cid) ? std::min<uint16_t>(result.capacity, u->refit_cap) : 0;
460  if (u->cargo.TotalCount() > u->refit_cap) u->cargo.Truncate(u->cargo.TotalCount() - u->refit_cap);
461  u->cargo_type = new_cid;
462  u->cargo_cap = result.capacity;
463  u->cargo_subtype = result.subtype;
464  if (u->type == VEH_AIRCRAFT) {
465  Vehicle *w = u->Next();
466  assert(w != nullptr);
467  w->refit_cap = std::min<uint16_t>(w->refit_cap, result.mail_capacity);
468  w->cargo_cap = result.mail_capacity;
469  if (w->cargo.TotalCount() > w->refit_cap) w->cargo.Truncate(w->cargo.TotalCount() - w->refit_cap);
470  }
471  }
472  }
473 
474  refit_result.clear();
475  return { cost, total_capacity, total_mail_capacity, cargo_capacities };
476 }
477 
490 std::tuple<CommandCost, uint, uint16_t, CargoArray> CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, uint8_t new_subtype, bool auto_refit, bool only_this, uint8_t num_vehicles)
491 {
492  Vehicle *v = Vehicle::GetIfValid(veh_id);
493  if (v == nullptr) return { CMD_ERROR, 0, 0, {} };
494 
495  /* Don't allow disasters and sparks and such to be refitted.
496  * We cannot check for IsPrimaryVehicle as autoreplace also refits in free wagon chains. */
497  if (!IsCompanyBuildableVehicleType(v->type)) return { CMD_ERROR, 0, 0, {} };
498 
499  Vehicle *front = v->First();
500 
501  CommandCost ret = CheckOwnership(front->owner);
502  if (ret.Failed()) return { ret, 0, 0, {} };
503 
504  bool free_wagon = v->type == VEH_TRAIN && Train::From(front)->IsFreeWagon(); // used by autoreplace/renew
505 
506  /* Don't allow shadows and such to be refitted. */
507  if (v != front && (v->type == VEH_SHIP || v->type == VEH_AIRCRAFT)) return { CMD_ERROR, 0, 0, {} };
508 
509  /* Allow auto-refitting only during loading and normal refitting only in a depot. */
510  if ((flags & DC_QUERY_COST) == 0 && // used by the refit GUI, including the order refit GUI.
511  !free_wagon && // used by autoreplace/renew
512  (!auto_refit || !front->current_order.IsType(OT_LOADING)) && // refit inside stations
513  !front->IsStoppedInDepot()) { // refit inside depots
514  return { CommandCost(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type), 0, 0, {} };
515  }
516 
517  if (front->vehstatus & VS_CRASHED) return { CommandCost(STR_ERROR_VEHICLE_IS_DESTROYED), 0, 0, {} };
518 
519  /* Check cargo */
520  if (new_cid >= NUM_CARGO) return { CMD_ERROR, 0, 0, {} };
521 
522  /* For ships and aircraft there is always only one. */
523  only_this |= front->type == VEH_SHIP || front->type == VEH_AIRCRAFT;
524 
525  auto [cost, refit_capacity, mail_capacity, cargo_capacities] = RefitVehicle(v, only_this, num_vehicles, new_cid, new_subtype, flags, auto_refit);
526 
527  if (flags & DC_EXEC) {
528  /* Update the cached variables */
529  switch (v->type) {
530  case VEH_TRAIN:
531  Train::From(front)->ConsistChanged(auto_refit ? CCF_AUTOREFIT : CCF_REFIT);
532  break;
533  case VEH_ROAD:
534  RoadVehUpdateCache(RoadVehicle::From(front), auto_refit);
535  if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) RoadVehicle::From(front)->CargoChanged();
536  break;
537 
538  case VEH_SHIP:
540  Ship::From(v)->UpdateCache();
541  break;
542 
543  case VEH_AIRCRAFT:
546  break;
547 
548  default: NOT_REACHED();
549  }
550  front->MarkDirty();
551 
552  if (!free_wagon) {
555  }
557  } else {
558  /* Always invalidate the cache; querycost might have filled it. */
560  }
561 
562  return { cost, refit_capacity, mail_capacity, cargo_capacities };
563 }
564 
572 CommandCost CmdStartStopVehicle(DoCommandFlag flags, VehicleID veh_id, bool evaluate_startstop_cb)
573 {
574  /* Disable the effect of p2 bit 0, when DC_AUTOREPLACE is not set */
575  if ((flags & DC_AUTOREPLACE) == 0) evaluate_startstop_cb = true;
576 
577  Vehicle *v = Vehicle::GetIfValid(veh_id);
578  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
579 
580  CommandCost ret = CheckOwnership(v->owner);
581  if (ret.Failed()) return ret;
582 
583  if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED);
584 
585  switch (v->type) {
586  case VEH_TRAIN:
587  if ((v->vehstatus & VS_STOPPED) && Train::From(v)->gcache.cached_power == 0) return_cmd_error(STR_ERROR_TRAIN_START_NO_POWER);
588  break;
589 
590  case VEH_SHIP:
591  case VEH_ROAD:
592  break;
593 
594  case VEH_AIRCRAFT: {
595  Aircraft *a = Aircraft::From(v);
596  /* cannot stop airplane when in flight, or when taking off / landing */
597  if (a->state >= STARTTAKEOFF && a->state < TERM7) return_cmd_error(STR_ERROR_AIRCRAFT_IS_IN_FLIGHT);
598  if (HasBit(a->flags, VAF_HELI_DIRECT_DESCENT)) return_cmd_error(STR_ERROR_AIRCRAFT_IS_IN_FLIGHT);
599  break;
600  }
601 
602  default: return CMD_ERROR;
603  }
604 
605  if (evaluate_startstop_cb) {
606  /* Check if this vehicle can be started/stopped. Failure means 'allow'. */
607  uint16_t callback = GetVehicleCallback(CBID_VEHICLE_START_STOP_CHECK, 0, 0, v->engine_type, v);
608  StringID error = STR_NULL;
609  if (callback != CALLBACK_FAILED) {
610  if (v->GetGRF()->grf_version < 8) {
611  /* 8 bit result 0xFF means 'allow' */
612  if (callback < 0x400 && GB(callback, 0, 8) != 0xFF) error = GetGRFStringID(v->GetGRFID(), 0xD000 + callback);
613  } else {
614  if (callback < 0x400) {
615  error = GetGRFStringID(v->GetGRFID(), 0xD000 + callback);
616  } else {
617  switch (callback) {
618  case 0x400: // allow
619  break;
620 
621  default: // unknown reason -> disallow
622  error = STR_ERROR_INCOMPATIBLE_RAIL_TYPES;
623  break;
624  }
625  }
626  }
627  }
628  if (error != STR_NULL) return_cmd_error(error);
629  }
630 
631  if (flags & DC_EXEC) {
632  if (v->IsStoppedInDepot() && (flags & DC_AUTOREPLACE) == 0) DeleteVehicleNews(veh_id, STR_NEWS_TRAIN_IS_WAITING + v->type);
633 
634  v->vehstatus ^= VS_STOPPED;
635  if (v->type != VEH_TRAIN) v->cur_speed = 0; // trains can stop 'slowly'
636 
637  /* Unbunching data is no longer valid. */
639 
640  v->MarkDirty();
645  }
646  return CommandCost();
647 }
648 
658 CommandCost CmdMassStartStopVehicle(DoCommandFlag flags, TileIndex tile, bool do_start, bool vehicle_list_window, const VehicleListIdentifier &vli)
659 {
660  VehicleList list;
661 
662  if (!vli.Valid()) return CMD_ERROR;
664 
665  if (vehicle_list_window) {
666  if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR;
667  } else {
668  if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
669  /* Get the list of vehicles in the depot */
670  BuildDepotVehicleList(vli.vtype, tile, &list, nullptr);
671  }
672 
673  for (const Vehicle *v : list) {
674  if (!!(v->vehstatus & VS_STOPPED) != do_start) continue;
675 
676  if (!vehicle_list_window && !v->IsChainInDepot()) continue;
677 
678  /* Just try and don't care if some vehicle's can't be stopped. */
679  Command<CMD_START_STOP_VEHICLE>::Do(flags, v->index, false);
680  }
681 
682  return CommandCost();
683 }
684 
693 {
694  VehicleList list;
695 
697 
698  if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR;
699  if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
700 
701  /* Get the list of vehicles in the depot */
702  BuildDepotVehicleList(vehicle_type, tile, &list, &list);
703 
704  CommandCost last_error = CMD_ERROR;
705  bool had_success = false;
706  for (const Vehicle *v : list) {
707  CommandCost ret = Command<CMD_SELL_VEHICLE>::Do(flags, v->index, true, false, INVALID_CLIENT_ID);
708  if (ret.Succeeded()) {
709  cost.AddCost(ret);
710  had_success = true;
711  } else {
712  last_error = ret;
713  }
714  }
715 
716  return had_success ? cost : last_error;
717 }
718 
727 {
728  VehicleList list;
730 
731  if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR;
732  if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR;
733 
734  /* Get the list of vehicles in the depot */
735  BuildDepotVehicleList(vehicle_type, tile, &list, &list, true);
736 
737  for (const Vehicle *v : list) {
738  /* Ensure that the vehicle completely in the depot */
739  if (!v->IsChainInDepot()) continue;
740 
741  CommandCost ret = Command<CMD_AUTOREPLACE_VEHICLE>::Do(flags, v->index);
742 
743  if (ret.Succeeded()) cost.AddCost(ret);
744  }
745  return cost;
746 }
747 
753 bool IsUniqueVehicleName(const std::string &name)
754 {
755  for (const Vehicle *v : Vehicle::Iterate()) {
756  if (!v->name.empty() && v->name == name) return false;
757  }
758 
759  return true;
760 }
761 
767 static void CloneVehicleName(const Vehicle *src, Vehicle *dst)
768 {
769  std::string buf;
770 
771  /* Find the position of the first digit in the last group of digits. */
772  size_t number_position;
773  for (number_position = src->name.length(); number_position > 0; number_position--) {
774  /* The design of UTF-8 lets this work simply without having to check
775  * for UTF-8 sequences. */
776  if (src->name[number_position - 1] < '0' || src->name[number_position - 1] > '9') break;
777  }
778 
779  /* Format buffer and determine starting number. */
780  long num;
781  uint8_t padding = 0;
782  if (number_position == src->name.length()) {
783  /* No digit at the end, so start at number 2. */
784  buf = src->name;
785  buf += " ";
786  number_position = buf.length();
787  num = 2;
788  } else {
789  /* Found digits, parse them and start at the next number. */
790  buf = src->name.substr(0, number_position);
791 
792  auto num_str = src->name.substr(number_position);
793  padding = (uint8_t)num_str.length();
794 
795  std::istringstream iss(num_str);
796  iss >> num;
797  num++;
798  }
799 
800  /* Check if this name is already taken. */
801  for (int max_iterations = 1000; max_iterations > 0; max_iterations--, num++) {
802  std::ostringstream oss;
803 
804  /* Attach the number to the temporary name. */
805  oss << buf << std::setw(padding) << std::setfill('0') << std::internal << num;
806 
807  /* Check the name is unique. */
808  auto new_name = oss.str();
809  if (IsUniqueVehicleName(new_name)) {
810  dst->name = new_name;
811  break;
812  }
813  }
814 
815  /* All done. If we didn't find a name, it'll just use its default. */
816 }
817 
826 std::tuple<CommandCost, VehicleID> CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders)
827 {
829 
830  Vehicle *v = Vehicle::GetIfValid(veh_id);
831  if (v == nullptr || !v->IsPrimaryVehicle()) return { CMD_ERROR, INVALID_VEHICLE };
832  Vehicle *v_front = v;
833  Vehicle *w = nullptr;
834  Vehicle *w_front = nullptr;
835  Vehicle *w_rear = nullptr;
836 
837  /*
838  * v_front is the front engine in the original vehicle
839  * v is the car/vehicle of the original vehicle that is currently being copied
840  * w_front is the front engine of the cloned vehicle
841  * w is the car/vehicle currently being cloned
842  * w_rear is the rear end of the cloned train. It's used to add more cars and is only used by trains
843  */
844 
845  CommandCost ret = CheckOwnership(v->owner);
846  if (ret.Failed()) return { ret, INVALID_VEHICLE };
847 
848  if (v->type == VEH_TRAIN && (!v->IsFrontEngine() || Train::From(v)->crash_anim_pos >= 4400)) return { CMD_ERROR, INVALID_VEHICLE };
849 
850  /* check that we can allocate enough vehicles */
851  if (!(flags & DC_EXEC)) {
852  int veh_counter = 0;
853  do {
854  veh_counter++;
855  } while ((v = v->Next()) != nullptr);
856 
857  if (!Vehicle::CanAllocateItem(veh_counter)) {
858  return { CommandCost(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME), INVALID_VEHICLE };
859  }
860  }
861 
862  v = v_front;
863 
864  VehicleID new_veh_id = INVALID_VEHICLE;
865  do {
866  if (v->type == VEH_TRAIN && Train::From(v)->IsRearDualheaded()) {
867  /* we build the rear ends of multiheaded trains with the front ones */
868  continue;
869  }
870 
871  /* In case we're building a multi headed vehicle and the maximum number of
872  * vehicles is almost reached (e.g. max trains - 1) not all vehicles would
873  * be cloned. When the non-primary engines were build they were seen as
874  * 'new' vehicles whereas they would immediately be joined with a primary
875  * engine. This caused the vehicle to be not build as 'the limit' had been
876  * reached, resulting in partially build vehicles and such. */
877  DoCommandFlag build_flags = flags;
878  if ((flags & DC_EXEC) && !v->IsPrimaryVehicle()) build_flags |= DC_AUTOREPLACE;
879 
880  CommandCost cost;
881  std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) = Command<CMD_BUILD_VEHICLE>::Do(build_flags, tile, v->engine_type, false, INVALID_CARGO, INVALID_CLIENT_ID);
882 
883  if (cost.Failed()) {
884  /* Can't build a part, then sell the stuff we already made; clear up the mess */
885  if (w_front != nullptr) Command<CMD_SELL_VEHICLE>::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID);
886  return { cost, INVALID_VEHICLE };
887  }
888 
889  total_cost.AddCost(cost);
890 
891  if (flags & DC_EXEC) {
892  w = Vehicle::Get(new_veh_id);
893 
894  if (v->type == VEH_TRAIN && HasBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION)) {
896  }
897 
898  if (v->type == VEH_TRAIN && !v->IsFrontEngine()) {
899  /* this s a train car
900  * add this unit to the end of the train */
901  CommandCost result = Command<CMD_MOVE_RAIL_VEHICLE>::Do(flags, w->index, w_rear->index, true);
902  if (result.Failed()) {
903  /* The train can't be joined to make the same consist as the original.
904  * Sell what we already made (clean up) and return an error. */
905  Command<CMD_SELL_VEHICLE>::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID);
906  Command<CMD_SELL_VEHICLE>::Do(flags, w->index, true, false, INVALID_CLIENT_ID);
907  return { result, INVALID_VEHICLE }; // return error and the message returned from CMD_MOVE_RAIL_VEHICLE
908  }
909  } else {
910  /* this is a front engine or not a train. */
911  w_front = w;
913  w->SetServiceIntervalIsCustom(v->ServiceIntervalIsCustom());
914  w->SetServiceIntervalIsPercent(v->ServiceIntervalIsPercent());
915  }
916  w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
917  }
918  } while (v->type == VEH_TRAIN && (v = v->GetNextVehicle()) != nullptr);
919 
920  if ((flags & DC_EXEC) && v_front->type == VEH_TRAIN) {
921  /* for trains this needs to be the front engine due to the callback function */
922  new_veh_id = w_front->index;
923  }
924 
925  if (flags & DC_EXEC) {
926  /* Cloned vehicles belong to the same group */
927  Command<CMD_ADD_VEHICLE_GROUP>::Do(flags, v_front->group_id, w_front->index, false, VehicleListIdentifier{});
928  }
929 
930 
931  /* Take care of refitting. */
932  w = w_front;
933  v = v_front;
934 
935  /* Both building and refitting are influenced by newgrf callbacks, which
936  * makes it impossible to accurately estimate the cloning costs. In
937  * particular, it is possible for engines of the same type to be built with
938  * different numbers of articulated parts, so when refitting we have to
939  * loop over real vehicles first, and then the articulated parts of those
940  * vehicles in a different loop. */
941  do {
942  do {
943  if (flags & DC_EXEC) {
944  assert(w != nullptr);
945 
946  /* Find out what's the best sub type */
947  uint8_t subtype = GetBestFittingSubType(v, w, v->cargo_type);
948  if (w->cargo_type != v->cargo_type || w->cargo_subtype != subtype) {
949  CommandCost cost = std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(flags, w->index, v->cargo_type, subtype, false, true, 0));
950  if (cost.Succeeded()) total_cost.AddCost(cost);
951  }
952 
953  if (w->IsGroundVehicle() && w->HasArticulatedPart()) {
954  w = w->GetNextArticulatedPart();
955  } else {
956  break;
957  }
958  } else {
959  const Engine *e = v->GetEngine();
960  CargoID initial_cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : INVALID_CARGO);
961 
962  if (v->cargo_type != initial_cargo && IsValidCargoID(initial_cargo)) {
963  bool dummy;
964  total_cost.AddCost(GetRefitCost(nullptr, v->engine_type, v->cargo_type, v->cargo_subtype, &dummy));
965  }
966  }
967 
968  if (v->IsGroundVehicle() && v->HasArticulatedPart()) {
969  v = v->GetNextArticulatedPart();
970  } else {
971  break;
972  }
973  } while (v != nullptr);
974 
975  if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = w->GetNextVehicle();
976  } while (v->type == VEH_TRAIN && (v = v->GetNextVehicle()) != nullptr);
977 
978  if (flags & DC_EXEC) {
979  /*
980  * Set the orders of the vehicle. Cannot do it earlier as we need
981  * the vehicle refitted before doing this, otherwise the moved
982  * cargo types might not match (passenger vs non-passenger)
983  */
984  CommandCost result = Command<CMD_CLONE_ORDER>::Do(flags, (share_orders ? CO_SHARE : CO_COPY), w_front->index, v_front->index);
985  if (result.Failed()) {
986  /* The vehicle has already been bought, so now it must be sold again. */
987  Command<CMD_SELL_VEHICLE>::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID);
988  return { result, INVALID_VEHICLE };
989  }
990 
991  /* Now clone the vehicle's name, if it has one. */
992  if (!v_front->name.empty()) CloneVehicleName(v_front, w_front);
993 
994  /* Since we can't estimate the cost of cloning a vehicle accurately we must
995  * check whether the company has enough money manually. */
996  if (!CheckCompanyHasMoney(total_cost)) {
997  /* The vehicle has already been bought, so now it must be sold again. */
998  Command<CMD_SELL_VEHICLE>::Do(flags, w_front->index, true, false, INVALID_CLIENT_ID);
999  return { total_cost, INVALID_VEHICLE };
1000  }
1001  }
1002 
1003  return { total_cost, new_veh_id };
1004 }
1005 
1014 {
1015  VehicleList list;
1016 
1017  if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR;
1018 
1019  /* Send all the vehicles to a depot */
1020  bool had_success = false;
1021  for (uint i = 0; i < list.size(); i++) {
1022  const Vehicle *v = list[i];
1024 
1025  if (ret.Succeeded()) {
1026  had_success = true;
1027 
1028  /* Return 0 if DC_EXEC is not set this is a valid goto depot command)
1029  * In this case we know that at least one vehicle can be sent to a depot
1030  * and we will issue the command. We can now safely quit the loop, knowing
1031  * it will succeed at least once. With DC_EXEC we really need to send them to the depot */
1032  if (!(flags & DC_EXEC)) break;
1033  }
1034  }
1035 
1036  return had_success ? CommandCost() : CMD_ERROR;
1037 }
1038 
1048 {
1049  if (HasFlag(depot_cmd, DepotCommand::MassSend)) {
1050  /* Mass goto depot requested */
1051  if (!vli.Valid()) return CMD_ERROR;
1052  return SendAllVehiclesToDepot(flags, HasFlag(depot_cmd, DepotCommand::Service), vli);
1053  }
1054 
1055  Vehicle *v = Vehicle::GetIfValid(veh_id);
1056  if (v == nullptr) return CMD_ERROR;
1057  if (!v->IsPrimaryVehicle()) return CMD_ERROR;
1058 
1059  return v->SendToDepot(flags, depot_cmd);
1060 }
1061 
1069 CommandCost CmdRenameVehicle(DoCommandFlag flags, VehicleID veh_id, const std::string &text)
1070 {
1071  Vehicle *v = Vehicle::GetIfValid(veh_id);
1072  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1073 
1074  CommandCost ret = CheckOwnership(v->owner);
1075  if (ret.Failed()) return ret;
1076 
1077  bool reset = text.empty();
1078 
1079  if (!reset) {
1081  if (!(flags & DC_AUTOREPLACE) && !IsUniqueVehicleName(text)) return_cmd_error(STR_ERROR_NAME_MUST_BE_UNIQUE);
1082  }
1083 
1084  if (flags & DC_EXEC) {
1085  if (reset) {
1086  v->name.clear();
1087  } else {
1088  v->name = text;
1089  }
1092  }
1093 
1094  return CommandCost();
1095 }
1096 
1097 
1107 CommandCost CmdChangeServiceInt(DoCommandFlag flags, VehicleID veh_id, uint16_t serv_int, bool is_custom, bool is_percent)
1108 {
1109  Vehicle *v = Vehicle::GetIfValid(veh_id);
1110  if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR;
1111 
1112  CommandCost ret = CheckOwnership(v->owner);
1113  if (ret.Failed()) return ret;
1114 
1115  const Company *company = Company::Get(v->owner);
1116  is_percent = is_custom ? is_percent : company->settings.vehicle.servint_ispercent;
1117 
1118  if (is_custom) {
1119  if (serv_int != GetServiceIntervalClamped(serv_int, is_percent)) return CMD_ERROR;
1120  } else {
1121  serv_int = CompanyServiceInterval(company, v->type);
1122  }
1123 
1124  if (flags & DC_EXEC) {
1125  v->SetServiceInterval(serv_int);
1126  v->SetServiceIntervalIsCustom(is_custom);
1127  v->SetServiceIntervalIsPercent(is_percent);
1129  }
1130 
1131  return CommandCost();
1132 }
Base for aircraft.
@ VAF_HELI_DIRECT_DESCENT
The helicopter is descending directly at its destination (helipad or in front of hangar)
Definition: aircraft.h:45
void UpdateAircraftCache(Aircraft *v, bool update_range=false)
Update cached values of an aircraft.
CommandCost CmdBuildAircraft(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build an aircraft.
Command definitions related to aircraft.
Various declarations for airports.
@ STARTTAKEOFF
Airplane has arrived at a runway for take-off.
Definition: airport.h:72
@ TERM7
Heading for terminal 7.
Definition: airport.h:80
CargoArray GetCapacityOfArticulatedParts(EngineID engine)
Get the capacity of the parts of a given engine.
uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
Count the number of articulated parts of an engine.
Functions related to articulated vehicles.
Command definitions related to autoreplace.
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
Functions related to the autoreplace GUIs.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
constexpr static debug_inline uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
bool IsValidCargoID(CargoID t)
Test whether cargo type is not INVALID_CARGO.
Definition: cargo_type.h:107
static const CargoID NUM_CARGO
Maximum number of cargo types in a game.
Definition: cargo_type.h:74
Common return value for all commands.
Definition: command_type.h:23
bool Succeeded() const
Did this command succeed?
Definition: command_type.h:162
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Definition: command_type.h:63
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:83
bool Failed() const
Did this command fail?
Definition: command_type.h:171
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
uint TotalCount() const
Returns sum of cargo, including reserved cargo.
Definition: cargopacket.h:443
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:28
#define return_cmd_error(errcode)
Returns from a function with a specific StringID as error.
Definition: command_func.h:38
DoCommandFlag
List of flags for a command.
Definition: command_type.h:374
@ DC_AUTOREPLACE
autoreplace/autorenew is in progress, this shall disable vehicle limits when building,...
Definition: command_type.h:383
@ DC_QUERY_COST
query cost only, don't build.
Definition: command_type.h:378
@ DC_EXEC
execute the given command
Definition: command_type.h:376
Definition of stuff that is very close to a company, like the company struct itself.
int CompanyServiceInterval(const Company *c, VehicleType type)
Get the service interval for the given company and vehicle type.
bool CheckCompanyHasMoney(CommandCost &cost)
Verify whether the company can pay the bill.
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:53
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
Definition: company_func.h:47
Map related accessors for depots.
bool IsDepotTile(Tile tile)
Is the given tile a tile with a depot on it?
Definition: depot_map.h:41
VehicleType GetDepotVehicleType(Tile t)
Get the type of vehicles that can use a depot.
Definition: depot_map.h:65
bool do_start
flag for starting playback of next_file at next opportunity
Definition: dmusic.cpp:127
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:969
ExpensesType
Types of expenses.
Definition: economy_type.h:172
@ EXPENSES_ROADVEH_RUN
Running costs road vehicles.
Definition: economy_type.h:176
@ EXPENSES_TRAIN_RUN
Running costs trains.
Definition: economy_type.h:175
@ EXPENSES_AIRCRAFT_RUN
Running costs aircraft.
Definition: economy_type.h:177
@ EXPENSES_SHIP_RUN
Running costs ships.
Definition: economy_type.h:178
@ EXPENSES_NEW_VEHICLES
New vehicles.
Definition: economy_type.h:174
Price
Enumeration of all base prices for use with Prices.
Definition: economy_type.h:89
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
Check if an engine is buildable.
Definition: engine.cpp:1218
Functions related to engines.
@ RAILVEH_WAGON
simple wagon, not motorized
Definition: engine_type.h:29
@ RAILVEH_MULTIHEAD
indicates a combination of two locomotives
Definition: engine_type.h:28
uint16_t EngineID
Unique identification number of an engine.
Definition: engine_type.h:21
@ AIR_CTOL
Conventional Take Off and Landing, i.e. planes.
Definition: engine_type.h:95
@ EF_AUTO_REFIT
Automatic refitting is allowed.
Definition: engine_type.h:173
constexpr debug_inline bool HasFlag(const T x, const T y)
Checks if a value in a bitset enum is set.
Definition: enum_type.hpp:58
Base class for groups and group functions.
Command definitions related to engine groups.
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1529
virtual void MarkDirty()
Marks the vehicles to be redrawn and updates cached variables.
Definition: vehicle_base.h:407
ClientID
'Unique' identifier to be given to clients
Definition: network_type.h:49
@ INVALID_CLIENT_ID
Client is not part of anything.
Definition: network_type.h:50
Base for the NewGRF implementation.
@ CBID_VEHICLE_REFIT_COST
Called to determine the cost factor for refitting a vehicle.
@ CBID_VEHICLE_START_STOP_CHECK
Called when the company (or AI) tries to start or stop a vehicle.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
StringID GetGRFStringID(uint32_t grfid, StringID stringid)
Returns the index for this stringid associated with its grfID.
Header of Action 04 "universal holder" structure and functions.
Functions related to news.
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:930
Functions related to order backups.
uint16_t GetServiceIntervalClamped(int interval, bool ispercent)
Clamp the service interval to the correct min/max.
Definition: order_cmd.cpp:1901
Command definitions related to orders.
Pseudo random number generator.
void SaveRandomSeeds(SavedRandomSeeds *storage)
Saves the current seeds.
Definition: random_func.hpp:55
void RestoreRandomSeeds(const SavedRandomSeeds &storage)
Restores previously saved seeds.
Definition: random_func.hpp:65
Road vehicle states.
void RoadVehUpdateCache(RoadVehicle *v, bool same_length=false)
Update the cache of a road vehicle.
CommandCost CmdBuildRoadVehicle(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a road vehicle.
Command definitions related to road vehicles.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:57
Base for ships.
CommandCost CmdBuildShip(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a ship.
Definition: ship_cmd.cpp:895
Command definitions related to ships.
Definition of base types and functions in a cross-platform compatible way.
size_t Utf8StringLength(const char *s)
Get the length of an UTF-8 encoded string in number of characters and thus not the number of bytes th...
Definition: string.cpp:359
Functions related to low-level strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
uint8_t subtype
Type of aircraft.
Definition: engine_type.h:104
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:72
uint8_t state
State of the airport.
Definition: aircraft.h:77
uint8_t flags
Aircraft flags.
Definition: aircraft.h:81
std::string name
Name of vehicle.
Definition: base_consist.h:18
uint16_t service_interval
The interval for (automatic) servicing; either in days or %.
Definition: base_consist.h:29
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:51
Class for storing amounts of cargo.
Definition: cargo_type.h:114
Specification of a cargo type.
Definition: cargotype.h:71
CargoClasses classes
Classes of this cargo type.
Definition: cargotype.h:78
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Definition: cargotype.h:134
CompanySettings settings
settings specific for each company
Definition: company_base.h:122
VehicleDefaultSettings vehicle
default settings for vehicles
uint8_t misc_flags
Miscellaneous flags.
Definition: engine_type.h:155
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:96
Money GetCost() const
Return how much a new engine costs.
Definition: engine.cpp:318
uint DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity=nullptr) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:201
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition: engine_base.h:56
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:167
uint GetDisplayDefaultCapacity(uint16_t *mail_capacity=nullptr) const
Determines the default cargo capacity of an engine for display purposes.
Definition: engine_base.h:116
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition: engine.cpp:168
std::array< uint8_t, NUM_CARGO > cargo_map
Inverse cargo translation table (CargoID -> local ID)
Definition: newgrf.h:131
VehicleSettings vehicle
options for vehicles
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition: group_cmd.cpp:133
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
Definition: group_cmd.cpp:158
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
Definition: group_cmd.cpp:221
static void Restore(Vehicle *v, uint32_t user)
Restore the data of this order to the given vehicle.
static void Backup(const Vehicle *v, uint32_t user)
Create an order backup for the given vehicle.
VehicleOrderID GetNumOrders() const
Get number of orders in the order list.
Definition: order_base.h:319
bool IsShared() const
Is this a shared order list?
Definition: order_base.h:338
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:70
Tindex index
Index of this pool item.
Definition: pool_type.hpp:238
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:339
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition: pool_type.hpp:309
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:350
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:388
Helper structure for RefitVehicle()
uint capacity
New capacity of vehicle.
Vehicle * v
Vehicle to refit.
uint mail_capacity
New mail capacity of aircraft.
uint8_t subtype
cargo subtype to refit to
Stores the state of all random number generators.
Definition: random_func.hpp:46
void UpdateCache()
Update the caches of this ship.
Definition: ship_cmd.cpp:232
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
bool servint_ispercent
service intervals are in percents
The information about a vehicle list.
Definition: vehiclelist.h:28
VehicleType vtype
The vehicle type associated with this list.
Definition: vehiclelist.h:30
uint8_t roadveh_acceleration_model
realistic acceleration for road vehicles
Vehicle data structure.
Definition: vehicle_base.h:244
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:323
Vehicle * GetNextArticulatedPart() const
Get the next part of an articulated engine.
Definition: vehicle_base.h:973
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:747
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
Definition: vehicle_base.h:560
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:341
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition: vehicle_base.h:645
uint16_t cargo_cap
total capacity
Definition: vehicle_base.h:344
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition: vehicle_base.h:963
GroupID group_id
Index of group Pool array.
Definition: vehicle_base.h:366
CommandCost SendToDepot(DoCommandFlag flags, DepotCommand command)
Send this vehicle to the depot using the given command(s).
Definition: vehicle.cpp:2583
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition: vehicle_base.h:954
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:632
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition: vehicle_base.h:945
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:356
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:342
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:757
OrderList * orders
Pointer to the order list for this vehicle.
Definition: vehicle_base.h:359
Money value
Value of the vehicle.
Definition: vehicle_base.h:275
uint16_t refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:345
uint8_t vehstatus
Status.
Definition: vehicle_base.h:354
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition: vehicle.cpp:767
virtual ExpensesType GetExpenseType([[maybe_unused]] bool income) const
Sets the expense type associated to this vehicle type.
Definition: vehicle_base.h:466
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition: vehicle_base.h:477
uint16_t cur_speed
current speed
Definition: vehicle_base.h:328
uint8_t cargo_subtype
Used for livery refits (NewGRF variations)
Definition: vehicle_base.h:343
Vehicle * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
debug_inline bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition: vehicle_base.h:515
TileIndex tile
Current tile index.
Definition: vehicle_base.h:264
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle)
Definition: vehicle_base.h:504
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:309
UnitID unitnumber
unit number, for display purposes only
Definition: vehicle_base.h:326
bool IsTileOwner(Tile tile, Owner owner)
Checks if a tile belongs to the given owner.
Definition: tile_map.h:214
Base for the train class.
@ VRF_REVERSE_DIRECTION
Reverse the visible direction of the vehicle.
Definition: train.h:28
void NormalizeTrainVehInDepot(const Train *u)
Move all free vehicles in the depot to the train.
Definition: train_cmd.cpp:693
@ CCF_AUTOREFIT
Valid changes for autorefitting in stations.
Definition: train.h:50
@ CCF_REFIT
Valid changes for refitting in a depot.
Definition: train.h:51
CommandCost CmdBuildRailVehicle(DoCommandFlag flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build a railroad vehicle.
Definition: train_cmd.cpp:750
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, bool sell_chain, bool backup_order, ClientID user)
Sell a (single) train wagon/engine.
Definition: train_cmd.cpp:1391
Command definitions related to trains.
uint16_t UnitID
Type for the company global vehicle unit number.
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition: vehicle.cpp:3218
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition: vehicle.cpp:1895
@ VS_STOPPED
Vehicle is stopped by the player.
Definition: vehicle_base.h:34
@ VS_CRASHED
Vehicle is crashed.
Definition: vehicle_base.h:40
CommandCost CmdSendVehicleToDepot(DoCommandFlag flags, VehicleID veh_id, DepotCommand depot_cmd, const VehicleListIdentifier &vli)
Send a vehicle to the depot.
static void CloneVehicleName(const Vehicle *src, Vehicle *dst)
Clone the custom name of a vehicle, adding or incrementing a number.
static int GetRefitCostFactor(const Vehicle *v, EngineID engine_type, CargoID new_cid, uint8_t new_subtype, bool *auto_refit_allowed)
Helper to run the refit cost callback.
bool IsUniqueVehicleName(const std::string &name)
Test if a name is unique among vehicle names.
static std::tuple< CommandCost, uint, uint16_t, CargoArray > RefitVehicle(Vehicle *v, bool only_this, uint8_t num_vehicles, CargoID new_cid, uint8_t new_subtype, DoCommandFlag flags, bool auto_refit)
Refits a vehicle (chain).
CommandCost CmdSellVehicle(DoCommandFlag flags, VehicleID v_id, bool sell_chain, bool backup_order, ClientID client_id)
Sell a vehicle.
static CommandCost SendAllVehiclesToDepot(DoCommandFlag flags, bool service, const VehicleListIdentifier &vli)
Send all vehicles of type to depots.
std::tuple< CommandCost, uint, uint16_t, CargoArray > CmdRefitVehicle(DoCommandFlag flags, VehicleID veh_id, CargoID new_cid, uint8_t new_subtype, bool auto_refit, bool only_this, uint8_t num_vehicles)
Refits a vehicle to the specified cargo type.
CommandCost CmdRenameVehicle(DoCommandFlag flags, VehicleID veh_id, const std::string &text)
Give a custom name to your vehicle.
std::tuple< CommandCost, VehicleID, uint, uint16_t, CargoArray > CmdBuildVehicle(DoCommandFlag flags, TileIndex tile, EngineID eid, bool use_free_vehicles, CargoID cargo, ClientID client_id)
Build a vehicle.
Definition: vehicle_cmd.cpp:87
static CommandCost GetRefitCost(const Vehicle *v, EngineID engine_type, CargoID new_cid, uint8_t new_subtype, bool *auto_refit_allowed)
Learn the price of refitting a certain engine.
CommandCost CmdStartStopVehicle(DoCommandFlag flags, VehicleID veh_id, bool evaluate_startstop_cb)
Start/Stop a vehicle.
CommandCost CmdDepotSellAllVehicles(DoCommandFlag flags, TileIndex tile, VehicleType vehicle_type)
Sells all vehicles in a depot.
CommandCost CmdDepotMassAutoReplace(DoCommandFlag flags, TileIndex tile, VehicleType vehicle_type)
Autoreplace all vehicles in the depot.
std::tuple< CommandCost, VehicleID > CmdCloneVehicle(DoCommandFlag flags, TileIndex tile, VehicleID veh_id, bool share_orders)
Clone a vehicle.
CommandCost CmdChangeServiceInt(DoCommandFlag flags, VehicleID veh_id, uint16_t serv_int, bool is_custom, bool is_percent)
Change the service interval of a vehicle.
CommandCost CmdMassStartStopVehicle(DoCommandFlag flags, TileIndex tile, bool do_start, bool vehicle_list_window, const VehicleListIdentifier &vli)
Starts or stops a lot of vehicles.
Command definitions for vehicles.
Functions related to vehicles.
uint8_t GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoID dest_cargo_type)
Get the best fitting subtype when 'cloning'/'replacing' v_from with v_for.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition: vehicle_func.h:91
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition: vehicle_gui.h:97
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
@ VEH_ROAD
Road vehicle type.
Definition: vehicle_type.h:25
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition: vehicle_type.h:27
@ VEH_SHIP
Ship vehicle type.
Definition: vehicle_type.h:26
@ VEH_TRAIN
Train vehicle type.
Definition: vehicle_type.h:24
uint32_t VehicleID
The type all our vehicle IDs have.
Definition: vehicle_type.h:16
static const uint MAX_LENGTH_VEHICLE_NAME_CHARS
The maximum length of a vehicle name in characters including '\0'.
Definition: vehicle_type.h:66
static const VehicleID INVALID_VEHICLE
Constant representing a non-existing vehicle.
Definition: vehicle_type.h:54
DepotCommand
Flags for goto depot commands.
Definition: vehicle_type.h:57
@ None
No special flags.
@ MassSend
Tells that it's a mass send to depot command (type in VLW flag)
@ DontCancel
Don't cancel current goto depot command if any.
@ Service
The vehicle will leave the depot right after arrival (service only)
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli)
Generate a list of vehicles based on window type.
void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engines, VehicleList *wagons, bool individual_wagons)
Generate a list of vehicles inside a depot.
Functions and type for generating vehicle lists.
std::vector< const Vehicle * > VehicleList
A list of vehicles.
Definition: vehiclelist.h:54
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3119
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition: window.cpp:3211
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3106
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3093
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition: window.cpp:3228
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition: window_type.h:351
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition: window_type.h:200
@ WC_COMPANY
Company view; Window numbers:
Definition: window_type.h:369
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition: window_type.h:339