File diff r20251:8c2b509af318 → r20252:76a6f1c78ce7
src/order_cmd.cpp
Show inline comments
 
@@ -20,6 +20,7 @@
 
#include "vehicle_func.h"
 
#include "depot_base.h"
 
#include "core/pool_func.hpp"
 
#include "core/random_func.hpp"
 
#include "aircraft.h"
 
#include "roadveh.h"
 
#include "station_base.h"
 
@@ -350,6 +351,87 @@ Order *OrderList::GetOrderAt(int index) 
 
}
 

	
 
/**
 
 * Get the next order which will make the given vehicle stop at a station
 
 * or refit at a depot if its state doesn't change.
 
 * @param v The vehicle in question.
 
 * @param next The order to start looking at.
 
 * @param hops The number of orders we have already looked at.
 
 * @return Either an order or NULL if the vehicle won't stop anymore.
 
 */
 
const Order *OrderList::GetNextStoppingOrder(const Vehicle *v, const Order *next, uint hops) const
 
{
 
	if (hops > this->GetNumOrders() || next == NULL) return NULL;
 

	
 
	if (next->IsType(OT_CONDITIONAL)) {
 
		if (next->GetConditionVariable() == OCV_LOAD_PERCENTAGE) {
 
			/* If the condition is based on load percentage we can't
 
			 * tell what it will do. So we choose randomly. */
 
			const Order *skip_to = this->GetNextStoppingOrder(v,
 
					this->GetOrderAt(next->GetConditionSkipToOrder()),
 
					hops + 1);
 
			const Order *advance = this->GetNextStoppingOrder(v,
 
					this->GetNext(next), hops + 1);
 
			if (advance == NULL) return skip_to;
 
			if (skip_to == NULL) return advance;
 
			return RandomRange(2) == 0 ? skip_to : advance;
 
		}
 
		/* Otherwise we're optimistic and expect that the
 
		 * condition value won't change until it's evaluated. */
 
		VehicleOrderID skip_to = ProcessConditionalOrder(next, v);
 
		if (skip_to != INVALID_VEH_ORDER_ID) {
 
			return this->GetNextStoppingOrder(v, this->GetOrderAt(skip_to),
 
					hops + 1);
 
		}
 
		return this->GetNextStoppingOrder(v, this->GetNext(next), hops + 1);
 
	}
 

	
 
	if (next->IsType(OT_GOTO_DEPOT)) {
 
		if (next->GetDepotActionType() == ODATFB_HALT) return NULL;
 
		if (next->IsRefit()) return next;
 
	}
 

	
 
	if (!next->CanLoadOrUnload()) {
 
		return this->GetNextStoppingOrder(v, this->GetNext(next), hops + 1);
 
	}
 

	
 
	return next;
 
}
 

	
 
/**
 
 * Recursively determine the next deterministic station to stop at.
 
 * @param v The vehicle we're looking at.
 
 * @return Next stoppping station or INVALID_STATION.
 
 */
 
StationID OrderList::GetNextStoppingStation(const Vehicle *v) const
 
{
 

	
 
	const Order *next = this->GetOrderAt(v->cur_implicit_order_index);
 
	if (next == NULL) {
 
		next = this->GetFirstOrder();
 
		if (next == NULL) return INVALID_STATION;
 
	} else {
 
		/* GetNext never returns NULL if there is a valid station in the list.
 
		 * As the given "next" is already valid and a station in the list, we
 
		 * don't have to check for NULL here.
 
		 */
 
		next = this->GetNext(next);
 
		assert(next != NULL);
 
	}
 

	
 
	uint hops = 0;
 
	do {
 
		next = this->GetNextStoppingOrder(v, next, ++hops);
 
		/* Don't return a next stop if the vehicle has to unload everything. */
 
		if (next == NULL || (next->GetDestination() == v->last_station_visited &&
 
				(next->GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) == 0)) {
 
			return INVALID_STATION;
 
		}
 
	} while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);
 

	
 
	return next->GetDestination();
 
}
 

	
 
/**
 
 * Insert a new order into the order chain.
 
 * @param new_order is the order to insert into the chain.
 
 * @param index is the position where the order is supposed to be inserted.
 
@@ -1044,11 +1126,11 @@ CommandCost CmdSkipToOrder(TileIndex til
 
	if (ret.Failed()) return ret;
 

	
 
	if (flags & DC_EXEC) {
 
		if (v->current_order.IsType(OT_LOADING)) v->LeaveStation();
 

	
 
		v->cur_implicit_order_index = v->cur_real_order_index = sel_ord;
 
		v->UpdateRealOrderIndex();
 

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

	
 
		InvalidateVehicleOrder(v, VIWD_MODIFY_ORDERS);
 
	}
 

	
 
@@ -2122,3 +2204,23 @@ bool Order::ShouldStopAtStation(const Ve
 
			/* Finally do stop when there is no non-stop flag set for this type of station. */
 
			!(this->GetNonStopType() & (is_dest_station ? ONSF_NO_STOP_AT_DESTINATION_STATION : ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS));
 
}
 

	
 
bool Order::CanLoadOrUnload() const
 
{
 
	return (this->IsType(OT_GOTO_STATION) || this->IsType(OT_IMPLICIT)) &&
 
			(this->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0 &&
 
			((this->GetLoadType() & OLFB_NO_LOAD) == 0 ||
 
			(this->GetUnloadType() & OUFB_NO_UNLOAD) == 0);
 
}
 

	
 
/**
 
 * A vehicle can leave the current station with cargo if:
 
 * 1. it can load cargo here OR
 
 * 2a. it could leave the last station with cargo AND
 
 * 2b. it doesn't have to unload all cargo here.
 
 */
 
bool Order::CanLeaveWithCargo(bool has_cargo) const
 
{
 
	return (this->GetLoadType() & OLFB_NO_LOAD) == 0 || (has_cargo &&
 
			(this->GetUnloadType() & (OUFB_UNLOAD | OUFB_TRANSFER)) == 0);
 
}