From a6e314bbba071b8a8b12d13b8c1960903aae77f8 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 20 Jul 2008 07:41:43 +0000 Subject: (svn r13752) -Fix [FS#2130]: correctly restore conditional orders when they are put 'into' backup. --- src/order_cmd.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++-------- src/order_type.h | 1 + src/timetable_cmd.cpp | 32 +++++++++++++++++++++------ src/timetable_gui.cpp | 2 +- 4 files changed, 79 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index ac806225c..ffaa607a1 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -375,8 +375,8 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) /* Non stop not allowed for non-trains. */ if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR; - /* Full load and unload are mutual exclusive. */ - if ((new_order.GetLoadType() & OLFB_FULL_LOAD) && (new_order.GetUnloadType() & OUFB_UNLOAD)) return CMD_ERROR; + /* No load and no unload are mutual exclusive. */ + if ((new_order.GetLoadType() & OLFB_NO_LOAD) && (new_order.GetUnloadType() & OUFB_NO_UNLOAD)) return CMD_ERROR; /* Filter invalid load/unload types. */ switch (new_order.GetLoadType()) { @@ -437,7 +437,6 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) } case OT_GOTO_WAYPOINT: { - if (v->type != VEH_TRAIN) return CMD_ERROR; if (!IsValidWaypointID(new_order.GetDestination())) return CMD_ERROR; @@ -453,11 +452,30 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) } case OT_CONDITIONAL: { - if (!IsPlayerBuildableVehicleType(v)) return CMD_ERROR; - VehicleOrderID skip_to = new_order.GetConditionSkipToOrder(); - if (skip_to >= v->num_orders) return CMD_ERROR; - if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE) return CMD_ERROR; + if (skip_to != 0 && skip_to >= v->num_orders) {printf("%i: %i\n", skip_to, __LINE__); return CMD_ERROR;} // Always allow jumping to the first (even when there is no order). + if (new_order.GetConditionVariable() > OCV_END) {printf("%i\n", __LINE__); return CMD_ERROR;} + + OrderConditionComparator occ = new_order.GetConditionComparator(); + if (occ > OCC_END) {printf("%i\n", __LINE__); return CMD_ERROR;} + switch (new_order.GetConditionVariable()) { + case OCV_REQUIRES_SERVICE: + if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) {printf("%i\n", __LINE__); return CMD_ERROR;} + break; + + case OCV_UNCONDITIONALLY: + if (occ != OCC_EQUALS) {printf("%i\n", __LINE__); return CMD_ERROR;} + if (new_order.GetConditionValue() != 0) {printf("%i\n", __LINE__); return CMD_ERROR;} + break; + + case OCV_LOAD_PERCENTAGE: + case OCV_RELIABILITY: + if (new_order.GetConditionValue() > 100) {printf("%i\n", __LINE__); return CMD_ERROR;} + /* FALL THROUGH */ + default: + if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) {printf("%i\n", __LINE__); return CMD_ERROR;} + break; + } } break; default: return CMD_ERROR; @@ -938,6 +956,10 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) break; } break; + + case MOF_COND_DESTINATION: + if (data >= v->num_orders) return CMD_ERROR; + break; } if (flags & DC_EXEC) { @@ -997,6 +1019,10 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) order->SetConditionValue(data); break; + case MOF_COND_DESTINATION: + order->SetConditionSkipToOrder(data); + break; + default: NOT_REACHED(); } @@ -1280,15 +1306,31 @@ void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *bak) * in network the commands are queued before send, the second insert always * fails in test mode. By bypassing the test-mode, that no longer is a problem. */ for (uint i = 0; bak->order[i].IsValid(); i++) { - if (!DoCommandP(0, v->index + (i << 16), bak->order[i].Pack(), NULL, + Order o = bak->order[i]; + /* Conditional orders need to have their destination to be valid on insertion. */ + if (o.IsType(OT_CONDITIONAL)) o.SetConditionSkipToOrder(0); + + if (!DoCommandP(0, v->index + (i << 16), o.Pack(), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) { + printf("huh?\n"); break; } /* Copy timetable if enabled */ if (_settings_game.order.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25), - bak->order[i].wait_time << 16 | bak->order[i].travel_time, NULL, + o.wait_time << 16 | o.travel_time, NULL, CMD_CHANGE_TIMETABLE | CMD_NO_TEST_IF_IN_NETWORK)) { + printf("umh?\n"); + break; + } + } + + /* Fix the conditional orders' destination. */ + for (uint i = 0; bak->order[i].IsValid(); i++) { + if (!bak->order[i].IsType(OT_CONDITIONAL)) continue; + + if (!DoCommandP(0, v->index + (i << 16), MOF_LOAD | (bak->order[i].GetConditionSkipToOrder() << 4), NULL, + CMD_MODIFY_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) { break; } } diff --git a/src/order_type.h b/src/order_type.h index 1d01bdb74..01df949be 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -126,6 +126,7 @@ enum ModifyOrderFlags { MOF_COND_VARIABLE, ///< A conditional variable changes. MOF_COND_COMPARATOR, ///< A comparator changes. MOF_COND_VALUE, ///< The value to set the condition to. + MOF_COND_DESTINATION,///< Change the destination of a conditional order. MOF_END }; diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 98c13a609..03217a809 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -68,16 +68,36 @@ CommandCost CmdChangeTimetable(TileIndex tile, uint32 flags, uint32 p1, uint32 p bool packed_time = HasBit(p1, 25); bool is_journey = HasBit(p1, 24) || packed_time; - if (!is_journey) { - if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_CONDITIONAL)) return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS); - if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE); + + uint16 wait_time = 0; + uint16 travel_time = 0; + if (packed_time) { + travel_time = GB(p2, 0, 16); + wait_time = GB(p2, 16, 16);; + } else if (is_journey) { + travel_time = GB(p2, 0, 16); } else { - if (order->IsType(OT_CONDITIONAL)) return CMD_ERROR; + wait_time = GB(p2, 0, 16); } + if (wait_time != 0) { + switch (order->GetType()) { + case OT_GOTO_STATION: + if (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) return_cmd_error(STR_TIMETABLE_NOT_STOPPING_HERE); + break; + + case OT_CONDITIONAL: + break; + + default: return_cmd_error(STR_TIMETABLE_ONLY_WAIT_AT_STATIONS); + } + } + + if (travel_time != 0 && order->IsType(OT_CONDITIONAL)) return CMD_ERROR; + if (flags & DC_EXEC) { - ChangeTimetable(v, order_number, GB(p2, 0, 16), is_journey); - if (packed_time) ChangeTimetable(v, order_number, GB(p2, 16, 16), false); + if (wait_time != 0) ChangeTimetable(v, order_number, wait_time, false); + if (travel_time != 0) ChangeTimetable(v, order_number, travel_time, true); } return CommandCost(); diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp index f39aed8ed..38ce95e86 100644 --- a/src/timetable_gui.cpp +++ b/src/timetable_gui.cpp @@ -86,7 +86,7 @@ struct TimetableWindow : Window { if (v->owner == _local_player) { bool disable = true; if (selected != -1) { - const Order *order = GetVehicleOrder(v, (selected + 1) / 2); + const Order *order = GetVehicleOrder(v, ((selected + 1) / 2) % v->num_orders); if (selected % 2 == 1) { disable = order != NULL && order->IsType(OT_CONDITIONAL); } else { -- cgit v1.2.3-54-g00ecf