Beispiel #1
0
/**
 * Set the start date of the timetable.
 * @param tile Not used.
 * @param flags Operation to perform.
 * @param p2 Various bitstuffed elements
 * - p2 = (bit 0-19) - Vehicle ID.
 * - p2 = (bit 20)   - Set to 1 to set timetable start for all vehicles sharing this order
 * @param p2 The timetable start date.
 * @param text Not used.
 * @return The error or cost of the operation.
 */
CommandCost CmdSetTimetableStart(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
    bool timetable_all = HasBit(p1, 20);
    Vehicle *v = Vehicle::GetIfValid(GB(p1, 0, 20));
    if (v == NULL || !v->IsPrimaryVehicle() || v->orders.list == NULL) return CMD_ERROR;

    CommandCost ret = CheckOwnership(v->owner);
    if (ret.Failed()) return ret;

    /* Don't let a timetable start more than 15 years into the future or 1 year in the past. */
    Date start_date = (Date)p2;
    if (start_date < 0 || start_date > MAX_DAY) return CMD_ERROR;
    if (start_date - _date > 15 * DAYS_IN_LEAP_YEAR) return CMD_ERROR;
    if (_date - start_date > DAYS_IN_LEAP_YEAR) return CMD_ERROR;
    if (timetable_all && !v->orders.list->IsCompleteTimetable()) return CMD_ERROR;

    if (flags & DC_EXEC) {
        SmallVector<Vehicle *, 8> vehs;

        if (timetable_all) {
            for (Vehicle *w = v->orders.list->GetFirstSharedVehicle(); w != NULL; w = w->NextShared()) {
                *vehs.Append() = w;
            }
        } else {
            *vehs.Append() = v;
        }

        int total_duration = v->orders.list->GetTimetableTotalDuration();
        int num_vehs = vehs.Length();

        if (num_vehs >= 2) {
            QSortT(vehs.Begin(), vehs.Length(), &VehicleTimetableSorter);
        }

        int base = vehs.FindIndex(v);

        for (Vehicle **viter = vehs.Begin(); viter != vehs.End(); viter++) {
            int idx = (viter - vehs.Begin()) - base;
            Vehicle *w = *viter;

            w->lateness_counter = 0;
            ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
            /* Do multiplication, then division to reduce rounding errors. */
            w->timetable_start = start_date + idx * total_duration / num_vehs / DAY_TICKS;
            SetWindowDirty(WC_VEHICLE_TIMETABLE, w->index);
        }

    }

    return CommandCost();
}