/** * Sells all vehicles in a depot * @param tile Tile of the depot where the depot is * @param flags type of operation * @param p1 Vehicle type * @param p2 unused * @param text unused * @return the cost of this operation or an error */ CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; CommandCost cost(EXPENSES_NEW_VEHICLES); VehicleType vehicle_type = Extract<VehicleType, 0, 3>(p1); if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; uint sell_command = GetCmdSellVeh(vehicle_type); /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list); CommandCost last_error = CMD_ERROR; bool had_success = false; for (uint i = 0; i < list.Length(); i++) { CommandCost ret = DoCommand(tile, list[i]->index | (1 << 20), 0, flags, sell_command); if (ret.Succeeded()) { cost.AddCost(ret); had_success = true; } else { last_error = ret; } } return had_success ? cost : last_error; }
/** * Starts or stops a lot of vehicles * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots) * @param flags type of operation * @param p1 bitmask * - bit 0 set = start vehicles, unset = stop vehicles * - bit 1 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case * @param p2 packed VehicleListIdentifier * @param text unused * @return the cost of this operation or an error */ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; bool do_start = HasBit(p1, 0); bool vehicle_list_window = HasBit(p1, 1); VehicleListIdentifier vli; if (!vli.Unpack(p2)) return CMD_ERROR; if (!IsCompanyBuildableVehicleType(vli.vtype)) return CMD_ERROR; if (vehicle_list_window) { if (!GenerateVehicleSortList(&list, vli)) return CMD_ERROR; } else { /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vli.vtype, tile, &list, NULL); } for (uint i = 0; i < list.Length(); i++) { const Vehicle *v = list[i]; if (!!(v->vehstatus & VS_STOPPED) != do_start) continue; if (!vehicle_list_window && !v->IsChainInDepot()) continue; /* Just try and don't care if some vehicle's can't be stopped. */ DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE); } return CommandCost(); }
/** Autoreplace all vehicles in the depot * Note: this command can make incorrect cost estimations * Luckily the final price can only drop, not increase. This is due to the fact that * estimation can't predict wagon removal so it presumes worst case which is no income from selling wagons. * @param tile Tile of the depot where the vehicles are * @param flags type of operation * @param p1 Type of vehicle * @param p2 If bit 0 is set, then either replace all or nothing (instead of replacing until money runs out) * @param text unused * @return the cost of this operation or an error */ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); bool all_or_nothing = HasBit(p2, 0); if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list, true); bool did_something = false; for (uint i = 0; i < list.Length(); i++) { const Vehicle *v = list[i]; /* Ensure that the vehicle completely in the depot */ if (!v->IsInDepot()) continue; CommandCost ret = DoCommand(0, v->index, 0, flags, CMD_AUTOREPLACE_VEHICLE); if (CmdSucceeded(ret)) { did_something = true; cost.AddCost(ret); } else { if (ret.GetErrorMessage() != STR_ERROR_AUTOREPLACE_NOTHING_TO_DO && all_or_nothing) { /* We failed to replace a vehicle even though we set all or nothing. * We should never reach this if DC_EXEC is set since then it should * have failed the estimation guess. */ assert(!(flags & DC_EXEC)); /* Now we will have to return an error. */ return CMD_ERROR; } } } if (!did_something) { /* Either we didn't replace anything or something went wrong. * Either way we want to return an error and not execute this command. */ cost = CMD_ERROR; } return cost; }
/** Sells all vehicles in a depot * @param tile Tile of the depot where the depot is * @param flags type of operation * @param p1 Vehicle type * @param p2 unused * @param text unused * @return the cost of this operation or an error */ CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; CommandCost cost(EXPENSES_NEW_VEHICLES); VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); uint sell_command = GetCmdSellVeh(vehicle_type); /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list); for (uint i = 0; i < list.Length(); i++) { CommandCost ret = DoCommand(tile, list[i]->index, 1, flags, sell_command); if (CmdSucceeded(ret)) cost.AddCost(ret); } if (cost.GetCost() == 0) return CMD_ERROR; // no vehicles to sell return cost; }
/** Starts or stops a lot of vehicles * @param tile Tile of the depot where the vehicles are started/stopped (only used for depots) * @param flags type of operation * @param p1 Station/Order/Depot ID (only used for vehicle list windows) * @param p2 bitmask * - bit 0-4 Vehicle type * - bit 5 false = start vehicles, true = stop vehicles * - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case * - bit 8-11 Vehicle List Window type (ignored unless bit 1 is set) * @param text unused * @return the cost of this operation or an error */ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; CommandCost return_value = CMD_ERROR; VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5); bool start_stop = HasBit(p2, 5); bool vehicle_list_window = HasBit(p2, 6); if (vehicle_list_window) { uint32 id = p1; uint16 window_type = p2 & VLW_MASK; GenerateVehicleSortList(&list, vehicle_type, _current_company, id, window_type); } else { /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, NULL); } for (uint i = 0; i < list.Length(); i++) { const Vehicle *v = list[i]; if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue; if (!vehicle_list_window) { if (vehicle_type == VEH_TRAIN) { if (!Train::From(v)->IsInDepot()) continue; } else { if (!(v->vehstatus & VS_HIDDEN)) continue; } } CommandCost ret = DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE); if (CmdSucceeded(ret)) { return_value = CommandCost(); /* We know that the command is valid for at least one vehicle. * If we haven't set DC_EXEC, then there is no point in continueing because it will be valid */ if (!(flags & DC_EXEC)) break; } } return return_value; }
/** * Autoreplace all vehicles in the depot * @param tile Tile of the depot where the vehicles are * @param flags type of operation * @param p1 Type of vehicle * @param p2 unused * @param text unused * @return the cost of this operation or an error */ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); VehicleType vehicle_type = Extract<VehicleType, 0, 3>(p1); if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list, true); for (uint i = 0; i < list.Length(); i++) { const Vehicle *v = list[i]; /* Ensure that the vehicle completely in the depot */ if (!v->IsChainInDepot()) continue; CommandCost ret = DoCommand(0, v->index, 0, flags, CMD_AUTOREPLACE_VEHICLE); if (ret.Succeeded()) cost.AddCost(ret); } return cost; }