23 #include "table/strings.h"
42 return (available_cargoes_a == 0 || available_cargoes_b == 0 || (available_cargoes_a & available_cargoes_b) != 0);
57 if (from == to)
return false;
101 assert(v == NULL || v->
First() == v);
103 for (
Vehicle *src = v; src != NULL; src = src->
Next()) {
107 if (src->cargo.TotalCount() <= src->cargo_cap)
continue;
110 uint to_spread = src->cargo.TotalCount() - src->cargo_cap;
111 for (
Vehicle *dest = v; dest != NULL && to_spread != 0; dest = dest->
Next()) {
113 if (dest->cargo.TotalCount() >= dest->cargo_cap || dest->cargo_type != src->cargo_type)
continue;
115 uint amount =
min(to_spread, dest->cargo_cap - dest->cargo.TotalCount());
116 src->cargo.Shift(amount, &dest->cargo);
121 if (src->cargo_cap < src->cargo.TotalCount()) src->cargo.Truncate(src->cargo.TotalCount() - src->cargo_cap);
138 for (
Vehicle *src = old_veh; src != NULL; src = src->
Next()) {
142 src = src->GetLastEnginePart();
145 if (src->cargo_type >=
NUM_CARGO || src->cargo.TotalCount() == 0)
continue;
152 dest = dest->GetLastEnginePart();
155 if (dest->cargo_type != src->cargo_type)
continue;
157 uint amount =
min(src->cargo.TotalCount(), dest->cargo_cap - dest->cargo.TotalCount());
158 if (amount <= 0)
continue;
160 src->cargo.Shift(amount, &dest->cargo);
182 FOR_VEHICLE_ORDERS(u, o) {
186 if (!
HasBit(union_refit_mask_a, cargo_type))
continue;
187 if (!
HasBit(union_refit_mask_b, cargo_type))
return false;
204 uint32 available_cargo_types, union_mask;
220 for (v = v->
First(); v != NULL; v = v->
Next()) {
255 bool replace_when_old;
290 if (cost.
Failed())
return cost;
299 if (cost.
Failed())
return cost;
302 *new_vehicle = new_veh;
364 cost.
AddCost(CmdStartStopVehicle(new_head,
true));
403 if (cost.Succeeded() && new_v != NULL) {
404 *nothing_to_do =
false;
418 *single_unit = new_v;
422 cost.AddCost(
DoCommand(0, old_v->
index, 0, flags, GetCmdSellVeh(old_v)));
425 if ((flags & DC_EXEC) == 0) {
455 Train **old_vehs = CallocT<Train *>(num_units);
456 Train **new_vehs = CallocT<Train *>(num_units);
457 Money *new_costs = MallocT<Money>(num_units);
464 assert(i < num_units);
469 if (cost.Failed())
break;
472 if (new_vehs[i] != NULL) *nothing_to_do =
false;
474 Train *new_head = (new_vehs[0] != NULL ? new_vehs[0] : old_vehs[0]);
477 if (cost.Succeeded()) {
482 assert(
Train::From(new_head)->GetNextUnit() == NULL);
488 Train *last_engine = NULL;
489 if (cost.Succeeded()) {
490 for (
int i = num_units - 1; i > 0; i--) {
491 Train *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]);
495 if (new_vehs[i] != NULL) {
502 if (last_engine == NULL) last_engine = append;
504 if (cost.Failed())
break;
506 if (last_engine == NULL) last_engine = new_head;
515 if (cost.Succeeded()) {
516 for (
int i = num_units - 1; i > 0; i--) {
517 assert(last_engine != NULL);
518 Vehicle *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]);
533 if (cost.Failed())
break;
536 assert(append == last_engine);
543 if (cost.Succeeded() && wagon_removal) {
545 for (
int i = 1; i < num_units; i++) {
547 if (wagon == NULL)
continue;
548 if (wagon->
First() == new_head)
break;
559 cost.AddCost(-new_costs[i]);
566 if (cost.Succeeded()) {
568 if ((flags &
DC_EXEC) != 0 && new_head != old_head) {
573 for (
int i = 0; i < num_units; i++) {
577 if (w->
First() == new_head)
continue;
579 if ((flags & DC_EXEC) != 0)
TransferCargo(w, new_head,
true);
585 if ((flags & DC_EXEC) != 0) {
587 if (i == 0) old_head = NULL;
602 assert(
Train::From(old_head)->GetNextUnit() == NULL);
604 for (
int i = num_units - 1; i > 0; i--) {
613 for (
int i = num_units - 1; i >= 0; i--) {
614 if (new_vehs[i] != NULL) {
615 DoCommand(0, new_vehs[i]->index, 0, DC_EXEC, GetCmdSellVeh(new_vehs[i]));
630 if (cost.Succeeded() && new_head != NULL) {
631 *nothing_to_do =
false;
636 if (cost.Succeeded()) {
644 cost.AddCost(
DoCommand(0, old_head->
index, 0, flags, GetCmdSellVeh(old_head)));
649 DoCommand(0, new_head->
index, 0, DC_EXEC, GetCmdSellVeh(new_head));
673 if (ret.
Failed())
return ret;
678 bool free_wagon =
false;
693 bool any_replacements =
false;
697 if (cost.
Failed())
return cost;
703 bool nothing_to_do =
true;
705 if (any_replacements) {
709 if (!was_stopped) cost.
AddCost(CmdStartStopVehicle(v,
true));
710 if (cost.
Failed())
return cost;
731 ret =
ReplaceChain(&v, flags, wagon_removal, ¬hing_to_do);
737 if (!was_stopped) cost.
AddCost(CmdStartStopVehicle(v,
false));