예제 #1
0
/**
 * Change/update a particular timetable entry.
 * @param v            The vehicle to change the timetable of.
 * @param order_number The index of the timetable in the order list.
 * @param val          The new data of the timetable entry.
 * @param mtf          Which part of the timetable entry to change.
 * @param timetabled   If the new value is explicitly timetabled.
 */
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val, ModifyTimetableFlags mtf, bool timetabled)
{
    Order *order = v->GetOrder(order_number);
    int total_delta = 0;
    int timetable_delta = 0;

    switch (mtf) {
    case MTF_WAIT_TIME:
        total_delta = val - order->GetWaitTime();
        timetable_delta = (timetabled ? val : 0) - order->GetTimetabledWait();
        order->SetWaitTime(val);
        order->SetWaitTimetabled(timetabled);
        break;

    case MTF_TRAVEL_TIME:
        total_delta = val - order->GetTravelTime();
        timetable_delta = (timetabled ? val : 0) - order->GetTimetabledTravel();
        order->SetTravelTime(val);
        order->SetTravelTimetabled(timetabled);
        break;

    case MTF_TRAVEL_SPEED:
        order->SetMaxSpeed(val);
        break;

    default:
        NOT_REACHED();
    }
    v->orders.list->UpdateTotalDuration(total_delta);
    v->orders.list->UpdateTimetableDuration(timetable_delta);

    for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
        if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
            switch (mtf) {
            case MTF_WAIT_TIME:
                v->current_order.SetWaitTime(val);
                v->current_order.SetWaitTimetabled(timetabled);
                break;

            case MTF_TRAVEL_TIME:
                v->current_order.SetTravelTime(val);
                v->current_order.SetTravelTimetabled(timetabled);
                break;

            case MTF_TRAVEL_SPEED:
                v->current_order.SetMaxSpeed(val);
                break;

            default:
                NOT_REACHED();
            }
        }
        SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
    }
}
예제 #2
0
/**
 * Change timetable data of an order.
 * @param tile Not used.
 * @param flags Operation to perform.
 * @param p1 Various bitstuffed elements
 * - p1 = (bit  0-19) - Vehicle with the orders to change.
 * - p1 = (bit 20-27) - Order index to modify.
 * - p1 = (bit 28-29) - Timetable data to change (@see ModifyTimetableFlags)
 * @param p2 The amount of time to wait.
 * - p2 = (bit  0-15) - The data to modify as specified by p1 bits 28-29.
 *                      0 to clear times, UINT16_MAX to clear speed limit.
 * @param text unused
 * @return the cost of this operation or an error
 */
CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
    VehicleID veh = GB(p1, 0, 20);

    Vehicle *v = Vehicle::GetIfValid(veh);
    if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;

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

    VehicleOrderID order_number = GB(p1, 20, 8);
    Order *order = v->GetOrder(order_number);
    if (order == NULL || order->IsType(OT_IMPLICIT)) return CMD_ERROR;

    ModifyTimetableFlags mtf = Extract<ModifyTimetableFlags, 28, 2>(p1);
    if (mtf >= MTF_END) return CMD_ERROR;

    int wait_time   = order->GetWaitTime();
    int travel_time = order->GetTravelTime();
    int max_speed   = order->GetMaxSpeed();
    switch (mtf) {
    case MTF_WAIT_TIME:
        wait_time = GB(p2, 0, 16);
        break;

    case MTF_TRAVEL_TIME:
        travel_time = GB(p2, 0, 16);
        break;

    case MTF_TRAVEL_SPEED:
        max_speed = GB(p2, 0, 16);
        if (max_speed == 0) max_speed = UINT16_MAX; // Disable speed limit.
        break;

    default:
        NOT_REACHED();
    }

    if (wait_time != order->GetWaitTime()) {
        switch (order->GetType()) {
        case OT_GOTO_STATION:
            if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_ERROR_TIMETABLE_NOT_STOPPING_HERE);
            break;

        case OT_CONDITIONAL:
            break;

        default:
            return_cmd_error(STR_ERROR_TIMETABLE_ONLY_WAIT_AT_STATIONS);
        }
    }

    if (travel_time != order->GetTravelTime() && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
    if (max_speed != order->GetMaxSpeed() && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;

    if (flags & DC_EXEC) {
        switch (mtf) {
        case MTF_WAIT_TIME:
            /* Set time if changing the value or confirming an estimated time as timetabled. */
            if (wait_time != order->GetWaitTime() || (wait_time > 0 && !order->IsWaitTimetabled())) {
                ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME, wait_time > 0);
            }
            break;

        case MTF_TRAVEL_TIME:
            /* Set time if changing the value or confirming an estimated time as timetabled. */
            if (travel_time != order->GetTravelTime() || (travel_time > 0 && !order->IsTravelTimetabled())) {
                ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME, travel_time > 0);
            }
            break;

        case MTF_TRAVEL_SPEED:
            if (max_speed != order->GetMaxSpeed()) {
                ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED, max_speed != UINT16_MAX);
            }
            break;

        default:
            break;
        }
    }

    return CommandCost();
}