(svn r13752) -Fix [FS#2130]: correctly restore conditional orders when they are put 'into' backup.
authorrubidium
Sun, 20 Jul 2008 07:41:43 +0000
changeset 9665 dd6c07db9d32
parent 9664 469dad45a4d3
child 9666 fa2ee5ae35b5
(svn r13752) -Fix [FS#2130]: correctly restore conditional orders when they are put 'into' backup.
src/order_cmd.cpp
src/order_type.h
src/timetable_cmd.cpp
src/timetable_gui.cpp
--- a/src/order_cmd.cpp	Sat Jul 19 20:24:41 2008 +0000
+++ b/src/order_cmd.cpp	Sun Jul 20 07:41:43 2008 +0000
@@ -375,8 +375,8 @@
 			/* 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 @@
 		}
 
 		case OT_GOTO_WAYPOINT: {
-
 			if (v->type != VEH_TRAIN) return CMD_ERROR;
 
 			if (!IsValidWaypointID(new_order.GetDestination())) return CMD_ERROR;
@@ -453,11 +452,30 @@
 		}
 
 		case OT_CONDITIONAL: {
-			if (!IsPlayerBuildableVehicleType(v)) return CMD_ERROR;
+			VehicleOrderID skip_to = new_order.GetConditionSkipToOrder();
+			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;}
 
-			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;
+			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 @@
 					break;
 			}
 			break;
+
+		case MOF_COND_DESTINATION:
+			if (data >= v->num_orders) return CMD_ERROR;
+			break;
 	}
 
 	if (flags & DC_EXEC) {
@@ -997,6 +1019,10 @@
 				order->SetConditionValue(data);
 				break;
 
+			case MOF_COND_DESTINATION:
+				order->SetConditionSkipToOrder(data);
+				break;
+
 			default: NOT_REACHED();
 		}
 
@@ -1280,15 +1306,31 @@
 		 *  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;
 			}
 		}
--- a/src/order_type.h	Sat Jul 19 20:24:41 2008 +0000
+++ b/src/order_type.h	Sun Jul 20 07:41:43 2008 +0000
@@ -126,6 +126,7 @@
 	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
 };
 
--- a/src/timetable_cmd.cpp	Sat Jul 19 20:24:41 2008 +0000
+++ b/src/timetable_cmd.cpp	Sun Jul 20 07:41:43 2008 +0000
@@ -68,16 +68,36 @@
 
 	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();
--- a/src/timetable_gui.cpp	Sat Jul 19 20:24:41 2008 +0000
+++ b/src/timetable_gui.cpp	Sun Jul 20 07:41:43 2008 +0000
@@ -86,7 +86,7 @@
 		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 {