/** * 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(); }
/** * Tries to reset the engine mapping to match the current NewGRF configuration. * This is only possible when there are currently no vehicles in the game. * @return false if resetting failed due to present vehicles. */ bool EngineOverrideManager::ResetToCurrentNewGRFConfig() { const Vehicle *v; FOR_ALL_VEHICLES(v) { if (IsCompanyBuildableVehicleType(v)) return false; } /* Reset the engines, they will get new EngineIDs */ _engine_mngr.ResetToDefaultMapping(); ReloadNewGRFData(); return true; }
/** * Create a new vehicle group. * @param tile unused * @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 CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleType vt = Extract<VehicleType, 0, 3>(p1); if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR; if (!Group::CanAllocateItem()) return CMD_ERROR; if (flags & DC_EXEC) { Group *g = new Group(_current_company); g->replace_protection = false; g->vehicle_type = vt; _new_group_id = g->index; InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack()); } return CommandCost(); }
/** * Create a new vehicle group. * @param tile unused * @param flags type of operation * @param p1 vehicle type * @param p2 parent groupid * @param text unused * @return the cost of this operation or an error */ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleType vt = Extract<VehicleType, 0, 3>(p1); if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR; if (!Group::CanAllocateItem()) return CMD_ERROR; const Group *pg = Group::GetIfValid(GB(p2, 0, 16)); if (pg != NULL) { if (pg->owner != _current_company) return CMD_ERROR; if (pg->vehicle_type != vt) return CMD_ERROR; } if (flags & DC_EXEC) { Group *g = new Group(_current_company); g->replace_protection = false; g->vehicle_type = vt; g->parent = INVALID_GROUP; if (pg == NULL) { const Company *c = Company::Get(_current_company); g->livery.colour1 = c->livery[LS_DEFAULT].colour1; g->livery.colour2 = c->livery[LS_DEFAULT].colour2; } else { g->parent = pg->index; g->livery.colour1 = pg->livery.colour1; g->livery.colour2 = pg->livery.colour2; } _new_group_id = g->index; InvalidateWindowData(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_GROUP_LIST, vt, _current_company).Pack()); InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type); } return CommandCost(); }
/** * 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; }
/** * Refits a vehicle to the specified cargo type. * @param tile unused * @param flags type of operation * @param p1 vehicle ID to refit * @param p2 various bitstuffed elements * - p2 = (bit 0-4) - New cargo type to refit to. * - p2 = (bit 6) - Automatic refitting. * - p2 = (bit 7) - Refit only this vehicle. Used only for cloning vehicles. * - p2 = (bit 8-15) - New cargo subtype to refit to. 0xFF means to try keeping the same subtype according to GetBestFittingSubType(). * - p2 = (bit 16-23) - Number of vehicles to refit (not counting articulated parts). Zero means all vehicles. * Only used if "refit only this vehicle" is false. * @param text unused * @return the cost of this operation or an error */ CommandCost CmdRefitVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { Vehicle *v = Vehicle::GetIfValid(p1); if (v == NULL) return CMD_ERROR; /* Don't allow disasters and sparks and such to be refitted. * We cannot check for IsPrimaryVehicle as autoreplace also refits in free wagon chains. */ if (!IsCompanyBuildableVehicleType(v->type)) return CMD_ERROR; Vehicle *front = v->First(); CommandCost ret = CheckOwnership(front->owner); if (ret.Failed()) return ret; bool auto_refit = HasBit(p2, 6); /* Don't allow shadows and such to be refitted. */ if (v != front && (v->type == VEH_SHIP || v->type == VEH_AIRCRAFT)) return CMD_ERROR; /* Allow auto-refitting only during loading and normal refitting only in a depot. */ if ((!auto_refit || !front->current_order.IsType(OT_LOADING)) && !front->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type); if (front->vehstatus & VS_CRASHED) return_cmd_error(STR_ERROR_VEHICLE_IS_DESTROYED); /* Check cargo */ CargoID new_cid = GB(p2, 0, 5); byte new_subtype = GB(p2, 8, 8); if (new_cid >= NUM_CARGO) return CMD_ERROR; /* For ships and aircrafts there is always only one. */ bool only_this = HasBit(p2, 7) || front->type == VEH_SHIP || front->type == VEH_AIRCRAFT; uint8 num_vehicles = GB(p2, 16, 8); CommandCost cost = RefitVehicle(v, only_this, num_vehicles, new_cid, new_subtype, flags, auto_refit); if (flags & DC_EXEC) { /* Update the cached variables */ switch (v->type) { case VEH_TRAIN: Train::From(front)->ConsistChanged(auto_refit); break; case VEH_ROAD: RoadVehUpdateCache(RoadVehicle::From(front), auto_refit); if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) RoadVehicle::From(front)->CargoChanged(); break; case VEH_SHIP: v->InvalidateNewGRFCacheOfChain(); v->colourmap = PAL_NONE; // invalidate vehicle colour map Ship::From(v)->UpdateCache(); break; case VEH_AIRCRAFT: v->InvalidateNewGRFCacheOfChain(); v->colourmap = PAL_NONE; // invalidate vehicle colour map UpdateAircraftCache(Aircraft::From(v), true); break; default: NOT_REACHED(); } InvalidateWindowData(WC_VEHICLE_DETAILS, front->index); SetWindowDirty(WC_VEHICLE_DEPOT, front->tile); InvalidateWindowClassesData(GetWindowClassForVehicleType(v->type), 0); } else { /* Always invalidate the cache; querycost might have filled it. */ v->InvalidateNewGRFCacheOfChain(); } return cost; }