Changeset - r17184:a6dd7165a9b8
[Not reviewed]
master
0 17 0
frosch - 14 years ago 2011-01-31 20:44:15
frosch@openttd.org
(svn r21933) -Codechange: Split cur_order_index into cur_auto_order_index and cur_real_order_index to keep track of the current real order in an unambiguous way.
-Fix [FS#4440]: Automatic orders behave now stable wrt. service orders and are not added or removed depending on the need of servicing.
-Fix: Various other issues with automatic orders, e.g. vehicles getting stuck with "no orders" when there are automatic orders at the end of the order list.
17 files changed with 242 insertions and 97 deletions:
0 comments (0 inline, 0 general)
src/ai/api/ai_order.cpp
Show inline comments
 
@@ -132,7 +132,7 @@ static const Order *ResolveOrder(Vehicle
 
	if (!AIVehicle::IsValidVehicle(vehicle_id)) return ORDER_INVALID;
 

	
 
	if (order_position == ORDER_CURRENT) {
 
		int cur_order_pos = ::Vehicle::Get(vehicle_id)->cur_order_index;
 
		int cur_order_pos = ::Vehicle::Get(vehicle_id)->cur_real_order_index;
 
		const Order *order = ::Vehicle::Get(vehicle_id)->GetOrder(0);
 
		if (order == NULL) return ORDER_INVALID;
 
		int num_automatic_orders = 0;
src/newgrf_engine.cpp
Show inline comments
 
@@ -690,7 +690,7 @@ static uint32 VehicleGetVariable(const R
 
		case 0x0A: return v->current_order.MapOldOrder();
 
		case 0x0B: return v->current_order.GetDestination();
 
		case 0x0C: return v->GetNumOrders();
 
		case 0x0D: return v->cur_order_index;
 
		case 0x0D: return v->cur_real_order_index;
 
		case 0x10:
 
		case 0x11: {
 
			uint ticks;
src/order_backup.cpp
Show inline comments
 
@@ -44,7 +44,7 @@ OrderBackup::OrderBackup(const Vehicle *
 
{
 
	this->user             = user;
 
	this->tile             = v->tile;
 
	this->orderindex       = v->cur_order_index;
 
	this->orderindex       = v->cur_auto_order_index;
 
	this->group            = v->group_id;
 
	this->service_interval = v->service_interval;
 

	
 
@@ -87,7 +87,10 @@ void OrderBackup::DoRestore(Vehicle *v)
 
	}
 

	
 
	uint num_orders = v->GetNumOrders();
 
	if (num_orders != 0) v->cur_order_index = this->orderindex % num_orders;
 
	if (num_orders != 0) {
 
		v->cur_real_order_index = v->cur_auto_order_index = this->orderindex % num_orders;
 
		v->UpdateRealOrderIndex();
 
	}
 
	v->service_interval = this->service_interval;
 

	
 
	/* Restore vehicle group */
src/order_cmd.cpp
Show inline comments
 
@@ -824,12 +824,21 @@ void InsertOrder(Vehicle *v, Order *new_
 
		assert(v->orders.list == u->orders.list);
 

	
 
		/* If there is added an order before the current one, we need
 
		 * to update the selected order */
 
		if (sel_ord <= u->cur_order_index) {
 
			uint cur = u->cur_order_index + 1;
 
		 * to update the selected order. We do not change automatic/real order indices though.
 
		 * If the new order is between the current auto order and real order, the auto order will
 
		 * later skip the inserted order. */
 
		if (sel_ord <= u->cur_real_order_index) {
 
			uint cur = u->cur_real_order_index + 1;
 
			/* Check if we don't go out of bound */
 
			if (cur < u->GetNumOrders()) {
 
				u->cur_order_index = cur;
 
				u->cur_real_order_index = cur;
 
			}
 
		}
 
		if (sel_ord <= u->cur_auto_order_index) {
 
			uint cur = u->cur_auto_order_index + 1;
 
			/* Check if we don't go out of bound */
 
			if (cur < u->GetNumOrders()) {
 
				u->cur_auto_order_index = cur;
 
			}
 
		}
 
		/* Update any possible open window of the vehicle */
 
@@ -917,14 +926,31 @@ void DeleteOrder(Vehicle *v, VehicleOrde
 

	
 
		/* NON-stop flag is misused to see if a train is in a station that is
 
		 * on his order list or not */
 
		if (sel_ord == u->cur_order_index && u->current_order.IsType(OT_LOADING)) {
 
		if (sel_ord == u->cur_real_order_index && u->current_order.IsType(OT_LOADING)) {
 
			u->current_order.SetNonStopType(ONSF_STOP_EVERYWHERE);
 
			/* When full loading, "cancel" that order so the vehicle doesn't
 
			 * stay indefinitely at this station anymore. */
 
			if (u->current_order.GetLoadType() & OLFB_FULL_LOAD) u->current_order.SetLoadType(OLF_LOAD_IF_POSSIBLE);
 
		}
 

	
 
		if (sel_ord < u->cur_order_index) u->cur_order_index--;
 
		if (sel_ord < u->cur_real_order_index) {
 
			u->cur_real_order_index--;
 
		} else if (sel_ord == u->cur_real_order_index) {
 
			u->UpdateRealOrderIndex();
 
		}
 

	
 
		if (sel_ord < u->cur_auto_order_index) {
 
			u->cur_auto_order_index--;
 
		} else if (sel_ord == u->cur_auto_order_index) {
 
			/* Make sure the index is valid */
 
			if (u->cur_auto_order_index >= u->GetNumOrders()) u->cur_auto_order_index = 0;
 

	
 
			/* Skip non-automatic orders for the auto-order-index (e.g. if the current auto order was deleted */
 
			while (u->cur_auto_order_index != u->cur_real_order_index && !u->GetOrder(u->cur_auto_order_index)->IsType(OT_AUTOMATIC)) {
 
				u->cur_auto_order_index++;
 
				if (u->cur_auto_order_index >= u->GetNumOrders()) u->cur_auto_order_index = 0;
 
			}
 
		}
 

	
 
		/* Update any possible open window of the vehicle */
 
		InvalidateVehicleOrder(u, sel_ord | (INVALID_VEH_ORDER_ID << 8));
 
@@ -965,13 +991,14 @@ CommandCost CmdSkipToOrder(TileIndex til
 

	
 
	Vehicle *v = Vehicle::GetIfValid(veh_id);
 

	
 
	if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
 
	if (v == NULL || !v->IsPrimaryVehicle() || sel_ord == v->cur_auto_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR;
 

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

	
 
	if (flags & DC_EXEC) {
 
		v->cur_order_index = sel_ord;
 
		v->cur_auto_order_index = v->cur_real_order_index = sel_ord;
 
		v->UpdateRealOrderIndex();
 

	
 
		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
 

	
 
@@ -1027,13 +1054,36 @@ CommandCost CmdMoveOrder(TileIndex tile,
 
		DeleteOrderWarnings(u);
 

	
 
		for (; u != NULL; u = u->NextShared()) {
 
			/* Update the current order */
 
			if (u->cur_order_index == moving_order) {
 
				u->cur_order_index = target_order;
 
			} else if (u->cur_order_index > moving_order && u->cur_order_index <= target_order) {
 
				u->cur_order_index--;
 
			} else if (u->cur_order_index < moving_order && u->cur_order_index >= target_order) {
 
				u->cur_order_index++;
 
			/* Update the current order.
 
			 * There are multiple ways to move orders, which result in cur_auto_order_index
 
			 * and cur_real_order_index to not longer make any sense. E.g. moving another
 
			 * real order between them.
 
			 *
 
			 * Basically one could choose to preserve either of them, but not both.
 
			 * While both ways are suitable in this or that case from a human point of view, neither
 
			 * of them makes really sense.
 
			 * However, from an AI point of view, preserving cur_real_order_index is the most
 
			 * predictable and transparent behaviour.
 
			 *
 
			 * With that decision it basically does not matter what we do to cur_auto_order_index.
 
			 * If we change orders between the auto- and real-index, the auto orders are mostly likely
 
			 * completely out-dated anyway. So, keep it simple and just keep cur_auto_order_index as well.
 
			 * The worst which can happen is that a lot of automatic orders are removed when reaching current_order.
 
			 */
 
			if (u->cur_real_order_index == moving_order) {
 
				u->cur_real_order_index = target_order;
 
			} else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) {
 
				u->cur_real_order_index--;
 
			} else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) {
 
				u->cur_real_order_index++;
 
			}
 

	
 
			if (u->cur_auto_order_index == moving_order) {
 
				u->cur_auto_order_index = target_order;
 
			} else if (u->cur_auto_order_index > moving_order && u->cur_auto_order_index <= target_order) {
 
				u->cur_auto_order_index--;
 
			} else if (u->cur_auto_order_index < moving_order && u->cur_auto_order_index >= target_order) {
 
				u->cur_auto_order_index++;
 
			}
 

	
 
			assert(v->orders.list == u->orders.list);
 
@@ -1289,7 +1339,7 @@ CommandCost CmdModifyOrder(TileIndex til
 
			 * so do not care and those orders should not be active
 
			 * when this function is called.
 
			 */
 
			if (sel_ord == u->cur_order_index &&
 
			if (sel_ord == u->cur_real_order_index &&
 
					(u->current_order.IsType(OT_GOTO_STATION) || u->current_order.IsType(OT_LOADING)) &&
 
					u->current_order.GetLoadType() != order->GetLoadType()) {
 
				u->current_order.SetLoadType(order->GetLoadType());
 
@@ -1468,7 +1518,7 @@ CommandCost CmdOrderRefit(TileIndex tile
 
			InvalidateVehicleOrder(u, -2);
 

	
 
			/* If the vehicle already got the current depot set as current order, then update current order as well */
 
			if (u->cur_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
 
			if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
 
				u->current_order.SetRefit(cargo, subtype);
 
			}
 
		}
 
@@ -1742,7 +1792,7 @@ bool UpdateOrderDest(Vehicle *v, const O
 
		case OT_GOTO_DEPOT:
 
			if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
 
				UpdateVehicleTimetable(v, true);
 
				v->IncrementOrderIndex();
 
				v->IncrementRealOrderIndex();
 
				break;
 
			}
 

	
 
@@ -1771,7 +1821,7 @@ bool UpdateOrderDest(Vehicle *v, const O
 
				}
 

	
 
				UpdateVehicleTimetable(v, true);
 
				v->IncrementOrderIndex();
 
				v->IncrementRealOrderIndex();
 
			} else {
 
				if (v->type != VEH_AIRCRAFT) {
 
					v->dest_tile = Depot::Get(order->GetDestination())->xy;
 
@@ -1787,12 +1837,15 @@ bool UpdateOrderDest(Vehicle *v, const O
 
		case OT_CONDITIONAL: {
 
			VehicleOrderID next_order = ProcessConditionalOrder(order, v);
 
			if (next_order != INVALID_VEH_ORDER_ID) {
 
				/* Jump to next_order. cur_auto_order_index becomes exactly that order,
 
				 * cur_real_order_index might come after next_order. */
 
				UpdateVehicleTimetable(v, false);
 
				v->cur_order_index = next_order;
 
				v->current_order_time += v->GetOrder(next_order)->travel_time;
 
				v->cur_auto_order_index = v->cur_real_order_index = next_order;
 
				v->UpdateRealOrderIndex();
 
				v->current_order_time += v->GetOrder(v->cur_real_order_index)->travel_time;
 
			} else {
 
				UpdateVehicleTimetable(v, true);
 
				v->IncrementOrderIndex();
 
				v->IncrementRealOrderIndex();
 
			}
 
			break;
 
		}
 
@@ -1802,18 +1855,22 @@ bool UpdateOrderDest(Vehicle *v, const O
 
			return false;
 
	}
 

	
 
	assert(v->cur_order_index < v->GetNumOrders());
 
	assert(v->cur_auto_order_index < v->GetNumOrders());
 
	assert(v->cur_real_order_index < v->GetNumOrders());
 

	
 
	/* Get the current order */
 
	order = v->GetNextManualOrder(v->cur_order_index);
 
	order = v->GetOrder(v->cur_real_order_index);
 
	if (order->IsType(OT_AUTOMATIC)) {
 
		assert(v->GetNumManualOrders() == 0);
 
		order = NULL;
 
	}
 

	
 
	if (order == NULL) {
 
		order = v->GetNextManualOrder(0);
 
		if (order == NULL) {
 
			v->current_order.Free();
 
			v->dest_tile = 0;
 
			return false;
 
		}
 
		v->current_order.Free();
 
		v->dest_tile = 0;
 
		return false;
 
	}
 

	
 
	v->current_order = *order;
 
	return UpdateOrderDest(v, order, conditional_depth + 1);
 
}
 
@@ -1863,13 +1920,17 @@ bool ProcessOrders(Vehicle *v)
 
		 * visited station will cause the vehicle to still stop. */
 
		v->last_station_visited = v->current_order.GetDestination();
 
		UpdateVehicleTimetable(v, true);
 
		v->IncrementOrderIndex();
 
		v->IncrementAutoOrderIndex();
 
	}
 

	
 
	/* Get the current order */
 
	if (v->cur_order_index >= v->GetNumOrders()) v->cur_order_index = 0;
 
	v->UpdateRealOrderIndex();
 

	
 
	const Order *order = v->GetNextManualOrder(v->cur_order_index);
 
	const Order *order = v->GetOrder(v->cur_real_order_index);
 
	if (order->IsType(OT_AUTOMATIC)) {
 
		assert(v->GetNumManualOrders() == 0);
 
		order = NULL;
 
	}
 

	
 
	/* If no order, do nothing. */
 
	if (order == NULL || (v->type == VEH_AIRCRAFT && !CheckForValidOrders(v))) {
src/order_gui.cpp
Show inline comments
 
@@ -195,8 +195,11 @@ void DrawOrderString(const Vehicle *v, c
 

	
 
	SpriteID sprite = rtl ? SPR_ARROW_LEFT : SPR_ARROW_RIGHT;
 
	Dimension sprite_size = GetSpriteSize(sprite);
 
	if (v->cur_order_index == order_index) {
 
		DrawSprite(sprite, PAL_NONE, rtl ? right - sprite_size.width : left, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
 
	if (v->cur_real_order_index == order_index) {
 
		DrawSprite(sprite, PAL_NONE, rtl ? right -     sprite_size.width : left,                     y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
 
		DrawSprite(sprite, PAL_NONE, rtl ? right - 2 * sprite_size.width : left + sprite_size.width, y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
 
	} else if (v->cur_auto_order_index == order_index) {
 
		DrawSprite(sprite, PAL_NONE, rtl ? right -     sprite_size.width : left,                     y + ((int)FONT_HEIGHT_NORMAL - (int)sprite_size.height) / 2);
 
	}
 

	
 
	TextColour colour = TC_BLACK;
 
@@ -207,7 +210,7 @@ void DrawOrderString(const Vehicle *v, c
 
	}
 

	
 
	SetDParam(0, order_index + 1);
 
	DrawString(left, rtl ? right - sprite_size.width - 3 : middle, y, STR_ORDER_INDEX, colour, SA_RIGHT | SA_FORCE);
 
	DrawString(left, rtl ? right - 2 * sprite_size.width - 3 : middle, y, STR_ORDER_INDEX, colour, SA_RIGHT | SA_FORCE);
 

	
 
	SetDParam(5, STR_EMPTY);
 

	
 
@@ -684,10 +687,10 @@ private:
 
	void OrderClick_Skip(int i)
 
	{
 
		/* Don't skip when there's nothing to skip */
 
		if (_ctrl_pressed && this->vehicle->cur_order_index == this->OrderGetSel()) return;
 
		if (_ctrl_pressed && this->vehicle->cur_auto_order_index == this->OrderGetSel()) return;
 
		if (this->vehicle->GetNumOrders() <= 1) return;
 

	
 
		DoCommandP(this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_order_index + 1) % this->vehicle->GetNumOrders()),
 
		DoCommandP(this->vehicle->tile, this->vehicle->index, _ctrl_pressed ? this->OrderGetSel() : ((this->vehicle->cur_auto_order_index + 1) % this->vehicle->GetNumOrders()),
 
				CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER));
 
	}
 

	
 
@@ -1026,7 +1029,7 @@ public:
 

	
 
		bool rtl = _current_text_dir == TD_RTL;
 
		SetDParam(0, 99);
 
		int index_column_width = GetStringBoundingBox(STR_ORDER_INDEX).width + GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + 3;
 
		int index_column_width = GetStringBoundingBox(STR_ORDER_INDEX).width + 2 * GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + 3;
 
		int middle = rtl ? r.right - WD_FRAMETEXT_RIGHT - index_column_width : r.left + WD_FRAMETEXT_LEFT + index_column_width;
 

	
 
		int y = r.top + WD_FRAMERECT_TOP;
src/roadveh_cmd.cpp
Show inline comments
 
@@ -525,7 +525,7 @@ TileIndex RoadVehicle::GetOrderStationLo
 
	const Station *st = Station::Get(station);
 
	if (!CanVehicleUseStation(this, st)) {
 
		/* There is no stop left at the station, so don't even TRY to go there */
 
		this->IncrementOrderIndex();
 
		this->IncrementRealOrderIndex();
 
		return 0;
 
	}
 

	
src/saveload/afterload.cpp
Show inline comments
 
@@ -2536,6 +2536,14 @@ bool AfterLoadGame()
 
			 * it should have set v->z_pos correctly. */
 
			assert(v->tile != TileVirtXY(v->x_pos, v->y_pos) || v->z_pos == GetSlopeZ(v->x_pos, v->y_pos));
 
		}
 

	
 
		/* Fill Vehicle::cur_real_order_index */
 
		FOR_ALL_VEHICLES(v) {
 
			if (!v->IsPrimaryVehicle()) continue;
 

	
 
			v->cur_real_order_index = v->cur_auto_order_index;
 
			v->UpdateRealOrderIndex();
 
		}
 
	}
 

	
 
	/* Road stops is 'only' updating some caches */
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -1138,7 +1138,7 @@ static const OldChunks vehicle_chunk[] =
 
	OCL_VAR ( OC_UINT16,   1, &_old_order ),
 

	
 
	OCL_NULL ( 1 ), ///< num_orders, now calculated
 
	OCL_SVAR(  OC_UINT8, Vehicle, cur_order_index ),
 
	OCL_SVAR(  OC_UINT8, Vehicle, cur_auto_order_index ),
 
	OCL_SVAR(   OC_TILE, Vehicle, dest_tile ),
 
	OCL_SVAR( OC_UINT16, Vehicle, load_unload_ticks ),
 
	OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Vehicle, date_of_last_service ),
src/saveload/saveload.cpp
Show inline comments
 
@@ -222,8 +222,9 @@
 
 *  155   21453
 
 *  156   21728
 
 *  157   21862
 
 *  158   21933
 
 */
 
extern const uint16 SAVEGAME_VERSION = 157; ///< Current savegame version of OpenTTD.
 
extern const uint16 SAVEGAME_VERSION = 158; ///< Current savegame version of OpenTTD.
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -487,7 +487,8 @@ const SaveLoad *GetVehicleDescription(Ve
 
		     SLE_VAR(Vehicle, tick_counter,          SLE_UINT8),
 
		 SLE_CONDVAR(Vehicle, running_ticks,         SLE_UINT8,                   88, SL_MAX_VERSION),
 

	
 
		     SLE_VAR(Vehicle, cur_order_index,       SLE_UINT8),
 
		     SLE_VAR(Vehicle, cur_auto_order_index,  SLE_UINT8),
 
		 SLE_CONDVAR(Vehicle, cur_real_order_index,  SLE_UINT8,                  158, SL_MAX_VERSION),
 
		/* num_orders is now part of OrderList and is not saved but counted */
 
		SLE_CONDNULL(1,                                                            0, 104),
 

	
src/ship_cmd.cpp
Show inline comments
 
@@ -234,7 +234,7 @@ TileIndex Ship::GetOrderStationLocation(
 
	if (st->dock_tile != INVALID_TILE) {
 
		return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
 
	} else {
 
		this->IncrementOrderIndex();
 
		this->IncrementRealOrderIndex();
 
		return 0;
 
	}
 
}
 
@@ -480,7 +480,7 @@ static void ShipController(Ship *v)
 
						/* We got within 3 tiles of our target buoy, so let's skip to our
 
						 * next order */
 
						UpdateVehicleTimetable(v, true);
 
						v->IncrementOrderIndex();
 
						v->IncrementRealOrderIndex();
 
						v->current_order.MakeDummy();
 
					} else {
 
						/* Non-buoy orders really need to reach the tile */
 
@@ -500,7 +500,7 @@ static void ShipController(Ship *v)
 
									v->BeginLoading();
 
								} else { // leave stations without docks right aways
 
									v->current_order.MakeLeaveStation();
 
									v->IncrementOrderIndex();
 
									v->IncrementRealOrderIndex();
 
								}
 
							}
 
						}
src/timetable_cmd.cpp
Show inline comments
 
@@ -33,7 +33,7 @@ static void ChangeTimetable(Vehicle *v, 
 
	v->orders.list->UpdateOrderTimetable(delta);
 

	
 
	for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
 
		if (v->cur_order_index == order_number && v->current_order.Equals(*order)) {
 
		if (v->cur_real_order_index == order_number && v->current_order.Equals(*order)) {
 
			if (is_journey) {
 
				v->current_order.travel_time = time;
 
			} else {
 
@@ -248,7 +248,7 @@ void UpdateVehicleTimetable(Vehicle *v, 
 
	bool just_started = false;
 

	
 
	/* This vehicle is arriving at the first destination in the timetable. */
 
	if (v->cur_order_index == first_manual_order && travelling) {
 
	if (v->cur_real_order_index == first_manual_order && travelling) {
 
		/* If the start date hasn't been set, or it was set automatically when
 
		 * the vehicle last arrived at the first destination, update it to the
 
		 * current time. Otherwise set the late counter appropriately to when
 
@@ -288,10 +288,10 @@ void UpdateVehicleTimetable(Vehicle *v, 
 
			 * processing of different orders when filling the timetable. */
 
			time_taken = CeilDiv(max(time_taken, 1U), DAY_TICKS) * DAY_TICKS;
 

	
 
			ChangeTimetable(v, v->cur_order_index, time_taken, travelling);
 
			ChangeTimetable(v, v->cur_real_order_index, time_taken, travelling);
 
		}
 

	
 
		if (v->cur_order_index == first_manual_order && travelling) {
 
		if (v->cur_real_order_index == first_manual_order && travelling) {
 
			/* If we just started we would have returned earlier and have not reached
 
			 * this code. So obviously, we have completed our round: So turn autofill
 
			 * off again. */
src/timetable_gui.cpp
Show inline comments
 
@@ -206,7 +206,7 @@ struct TimetableWindow : Window {
 
		bool travelling = (!v->current_order.IsType(OT_LOADING) || v->current_order.GetNonStopType() == ONSF_STOP_EVERYWHERE);
 
		Ticks start_time = _date_fract - v->current_order_time;
 

	
 
		FillTimetableArrivalDepartureTable(v, v->cur_order_index % v->GetNumOrders(), travelling, table, start_time);
 
		FillTimetableArrivalDepartureTable(v, v->cur_real_order_index % v->GetNumOrders(), travelling, table, start_time);
 

	
 
		return (travelling && v->lateness_counter < 0);
 
	}
 
@@ -425,7 +425,7 @@ struct TimetableWindow : Window {
 
				if (total_time <= 0 || v->GetNumOrders() <= 1 || !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) break;
 

	
 
				TimetableArrivalDeparture *arr_dep = AllocaM(TimetableArrivalDeparture, v->GetNumOrders());
 
				const VehicleOrderID cur_order = v->cur_order_index % v->GetNumOrders();
 
				const VehicleOrderID cur_order = v->cur_real_order_index % v->GetNumOrders();
 

	
 
				VehicleOrderID earlyID = BuildArrivalDepartureList(v, arr_dep) ? cur_order : (VehicleOrderID)INVALID_VEH_ORDER_ID;
 

	
src/train_cmd.cpp
Show inline comments
 
@@ -2291,7 +2291,7 @@ public:
 
		old_order(_v->current_order),
 
		old_dest_tile(_v->dest_tile),
 
		old_last_station_visited(_v->last_station_visited),
 
		index(_v->cur_order_index)
 
		index(_v->cur_real_order_index)
 
	{
 
	}
 

	
 
@@ -2348,7 +2348,7 @@ public:
 
			/* Don't increment inside the while because otherwise conditional
 
			 * orders can lead to an infinite loop. */
 
			++this->index;
 
		} while (this->index != this->v->cur_order_index);
 
		} while (this->index != this->v->cur_real_order_index);
 

	
 
		return false;
 
	}
 
@@ -2602,7 +2602,7 @@ TileIndex Train::GetOrderStationLocation
 
	const Station *st = Station::Get(station);
 
	if (!(st->facilities & FACIL_TRAIN)) {
 
		/* The destination station has no trainstation tiles. */
 
		this->IncrementOrderIndex();
 
		this->IncrementRealOrderIndex();
 
		return 0;
 
	}
 

	
src/vehicle.cpp
Show inline comments
 
@@ -1266,7 +1266,7 @@ void VehicleEnterDepot(Vehicle *v)
 
	if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
		const Order *real_order = v->GetNextManualOrder(v->cur_order_index);
 
		const Order *real_order = v->GetOrder(v->cur_real_order_index);
 
		Order t = v->current_order;
 
		v->current_order.MakeDummy();
 

	
 
@@ -1303,7 +1303,7 @@ void VehicleEnterDepot(Vehicle *v)
 
			/* Part of orders */
 
			v->DeleteUnreachedAutoOrders();
 
			UpdateVehicleTimetable(v, true);
 
			v->IncrementOrderIndex();
 
			v->IncrementAutoOrderIndex();
 
		}
 
		if (t.GetDepotActionType() & ODATFB_HALT) {
 
			/* Vehicles are always stopped on entering depots. Do not restart this one. */
 
@@ -1797,11 +1797,25 @@ uint GetVehicleCapacity(const Vehicle *v
 
 */
 
void Vehicle::DeleteUnreachedAutoOrders()
 
{
 
	const Order *order = this->GetOrder(this->cur_order_index);
 
	while (order != NULL && order->IsType(OT_AUTOMATIC)) {
 
		/* Delete order effectively deletes order, so get the next before deleting it. */
 
		order = order->next;
 
		DeleteOrder(this, this->cur_order_index);
 
	const Order *order = this->GetOrder(this->cur_auto_order_index);
 
	while (order != NULL) {
 
		if (this->cur_auto_order_index == this->cur_real_order_index) break;
 

	
 
		if (order->IsType(OT_AUTOMATIC)) {
 
			/* Delete order effectively deletes order, so get the next before deleting it. */
 
			order = order->next;
 
			DeleteOrder(this, this->cur_auto_order_index);
 
		} else {
 
			/* Skip non-automatic orders, e.g. service-orders */
 
			order = order->next;
 
			this->cur_auto_order_index++;
 
		}
 

	
 
		/* Wrap around */
 
		if (order == NULL) {
 
			order = this->GetOrder(0);
 
			this->cur_auto_order_index = 0;
 
		}
 
	}
 
}
 

	
 
@@ -1817,7 +1831,7 @@ void Vehicle::BeginLoading()
 
			this->current_order.GetDestination() == this->last_station_visited) {
 
		this->DeleteUnreachedAutoOrders();
 

	
 
		/* Now cur_order_index points to the destination station, and we can start loading */
 
		/* Now both order indices point to the destination station, and we can start loading */
 
		this->current_order.MakeLoading(true);
 
		UpdateVehicleTimetable(this, true);
 

	
 
@@ -1832,14 +1846,14 @@ void Vehicle::BeginLoading()
 
		/* We weren't scheduled to stop here. Insert an automatic order
 
		 * to show that we are stopping here, but only do that if the order
 
		 * list isn't empty. */
 
		Order *in_list = this->GetOrder(this->cur_order_index);
 
		Order *in_list = this->GetOrder(this->cur_auto_order_index);
 
		if (in_list != NULL && this->orders.list->GetNumOrders() < MAX_VEH_ORDER_ID &&
 
				(!in_list->IsType(OT_AUTOMATIC) ||
 
				in_list->GetDestination() != this->last_station_visited)) {
 
			Order *auto_order = new Order();
 
			auto_order->MakeAutomatic(this->last_station_visited);
 
			InsertOrder(this, auto_order, this->cur_order_index);
 
			if (this->cur_order_index > 0) --this->cur_order_index;
 
			InsertOrder(this, auto_order, this->cur_auto_order_index);
 
			if (this->cur_auto_order_index > 0) --this->cur_auto_order_index;
 
		}
 
		this->current_order.MakeLoading(false);
 
	}
 
@@ -1913,7 +1927,7 @@ void Vehicle::HandleLoading(bool mode)
 
		default: return;
 
	}
 

	
 
	this->IncrementOrderIndex();
 
	this->IncrementAutoOrderIndex();
 
}
 

	
 
/**
 
@@ -1948,7 +1962,7 @@ CommandCost Vehicle::SendToDepot(DoComma
 
		if (flags & DC_EXEC) {
 
			/* If the orders to 'goto depot' are in the orders list (forced servicing),
 
			 * then skip to the next order; effectively cancelling this forced service */
 
			if (this->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) this->IncrementOrderIndex();
 
			if (this->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) this->IncrementRealOrderIndex();
 

	
 
			this->current_order.MakeDummy();
 
			SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, VVW_WIDGET_START_STOP_VEH);
 
@@ -2261,20 +2275,6 @@ void Vehicle::RemoveFromShared()
 
	this->previous_shared = NULL;
 
}
 

	
 
/**
 
 * Get the next manual (not OT_AUTOMATIC) order after the one at the given index.
 
 * @param index The index to start searching at.
 
 * @return The next manual order at or after index or NULL if there is none.
 
 */
 
Order *Vehicle::GetNextManualOrder(int index) const
 
{
 
	Order *order = this->GetOrder(index);
 
	while (order != NULL && order->IsType(OT_AUTOMATIC)) {
 
		order = order->next;
 
	}
 
	return order;
 
}
 

	
 
void VehiclesYearlyLoop()
 
{
 
	Vehicle *v;
src/vehicle_base.h
Show inline comments
 
@@ -222,7 +222,8 @@ public:
 

	
 
	byte vehstatus;                     ///< Status
 
	Order current_order;                ///< The current order (+ status, like: loading)
 
	VehicleOrderID cur_order_index;     ///< The index to the current order
 
	VehicleOrderID cur_real_order_index;///< The index to the current real (non-automatic) order
 
	VehicleOrderID cur_auto_order_index;///< The index to the current automatic order
 

	
 
	union {
 
		OrderList *list;            ///< Pointer to the order list for this vehicle
 
@@ -549,7 +550,8 @@ public:
 
	{
 
		this->unitnumber = src->unitnumber;
 

	
 
		this->cur_order_index = src->cur_order_index;
 
		this->cur_real_order_index = src->cur_real_order_index;
 
		this->cur_auto_order_index = src->cur_auto_order_index;
 
		this->current_order = src->current_order;
 
		this->dest_tile  = src->dest_tile;
 

	
 
@@ -599,15 +601,83 @@ public:
 
	void UpdateVisualEffect(bool allow_power_change = true);
 
	void ShowVisualEffect() const;
 

	
 
private:
 
	/**
 
	 * Increments cur_order_index, keeps care of the wrap-around and invalidates the GUI.
 
	 * Advance cur_real_order_index to the next real order.
 
	 * cur_auto_order_index is not touched.
 
	 */
 
	void SkipToNextRealOrderIndex()
 
	{
 
		if (this->GetNumManualOrders() > 0) {
 
			/* Advance to next real order */
 
			do {
 
				this->cur_real_order_index++;
 
				if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
 
			} while (this->GetOrder(this->cur_real_order_index)->IsType(OT_AUTOMATIC));
 
		} else {
 
			this->cur_real_order_index = 0;
 
		}
 
	}
 

	
 
public:
 
	/**
 
	 * Increments cur_auto_order_index, keeps care of the wrap-around and invalidates the GUI.
 
	 * cur_real_order_index is incremented as well, if needed.
 
	 * Note: current_order is not invalidated.
 
	 */
 
	void IncrementOrderIndex()
 
	void IncrementAutoOrderIndex()
 
	{
 
		if (this->cur_auto_order_index == this->cur_real_order_index) {
 
			/* Increment real order index as well */
 
			this->SkipToNextRealOrderIndex();
 
		}
 

	
 
		assert(this->cur_real_order_index == 0 || this->cur_real_order_index < this->GetNumOrders());
 

	
 
		/* Advance to next automatic order */
 
		do {
 
			this->cur_auto_order_index++;
 
			if (this->cur_auto_order_index >= this->GetNumOrders()) this->cur_auto_order_index = 0;
 
		} while (this->cur_auto_order_index != this->cur_real_order_index && !this->GetOrder(this->cur_auto_order_index)->IsType(OT_AUTOMATIC));
 

	
 
		InvalidateVehicleOrder(this, 0);
 
	}
 

	
 
	/**
 
	 * Advanced cur_real_order_index to the next real order, keeps care of the wrap-around and invalidates the GUI.
 
	 * cur_auto_order_index is incremented as well, if it was equal to cur_real_order_index, i.e. cur_real_order_index is skipped
 
	 * but not any automatic orders.
 
	 * Note: current_order is not invalidated.
 
	 */
 
	void IncrementRealOrderIndex()
 
	{
 
		this->cur_order_index++;
 
		if (this->cur_order_index >= this->GetNumOrders()) this->cur_order_index = 0;
 
		InvalidateVehicleOrder(this, 0);
 
		if (this->cur_auto_order_index == this->cur_real_order_index) {
 
			/* Increment both real and auto order */
 
			this->IncrementAutoOrderIndex();
 
		} else {
 
			/* Increment real order only */
 
			this->SkipToNextRealOrderIndex();
 
			InvalidateVehicleOrder(this, 0);
 
		}
 
	}
 

	
 
	/**
 
	 * Skip automatic orders until cur_real_order_index is a non-automatic order.
 
	 */
 
	void UpdateRealOrderIndex()
 
	{
 
		/* Make sure the index is valid */
 
		if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
 

	
 
		if (this->GetNumManualOrders() > 0) {
 
			/* Advance to next real order */
 
			while (this->GetOrder(this->cur_real_order_index)->IsType(OT_AUTOMATIC)) {
 
				this->cur_real_order_index++;
 
				if (this->cur_real_order_index >= this->GetNumOrders()) this->cur_real_order_index = 0;
 
			}
 
		} else {
 
			this->cur_real_order_index = 0;
 
		}
 
	}
 

	
 
	/**
 
@@ -620,8 +690,6 @@ public:
 
		return (this->orders.list == NULL) ? NULL : this->orders.list->GetOrderAt(index);
 
	}
 

	
 
	Order *GetNextManualOrder(int index) const;
 

	
 
	/**
 
	 * Returns the last order of a vehicle, or NULL if it doesn't exists
 
	 * @return last order of a vehicle, if available
src/vehicle_gui.cpp
Show inline comments
 
@@ -1187,7 +1187,7 @@ static void DrawSmallOrderList(const Veh
 
	VehicleOrderID oid = start;
 

	
 
	do {
 
		if (oid == v->cur_order_index) DrawString(left, right, y, STR_TINY_RIGHT_ARROW, TC_BLACK);
 
		if (oid == v->cur_real_order_index) DrawString(left, right, y, STR_TINY_RIGHT_ARROW, TC_BLACK);
 

	
 
		if (order->IsType(OT_GOTO_STATION)) {
 
			SetDParam(0, order->GetDestination());
 
@@ -1294,7 +1294,7 @@ void BaseVehicleListWindow::DrawVehicleL
 
			DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK);
 
		}
 

	
 
		if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_order_index);
 
		if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, v->cur_real_order_index);
 

	
 
		if (v->IsInDepot()) {
 
			str = STR_BLUE_COMMA;
0 comments (0 inline, 0 general)