mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-08-12 17:19:09 +00:00
(svn r12667) -Feature: conditional 'skip/jump' orders.
This commit is contained in:
@@ -93,6 +93,13 @@ void Order::MakeDummy()
|
||||
this->flags = 0;
|
||||
}
|
||||
|
||||
void Order::MakeConditional(VehicleOrderID order)
|
||||
{
|
||||
this->type = OT_CONDITIONAL;
|
||||
this->flags = 0;
|
||||
this->dest = order;
|
||||
}
|
||||
|
||||
void Order::SetRefit(CargoID cargo, byte subtype)
|
||||
{
|
||||
this->refit_cargo = cargo;
|
||||
@@ -427,6 +434,14 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
break;
|
||||
}
|
||||
|
||||
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;
|
||||
} break;
|
||||
|
||||
default: return CMD_ERROR;
|
||||
}
|
||||
|
||||
@@ -512,6 +527,22 @@ CommandCost CmdInsertOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
InvalidateVehicleOrder(u);
|
||||
}
|
||||
|
||||
/* As we insert an order, the order to skip to will be 'wrong'. */
|
||||
VehicleOrderID cur_order_id = 0;
|
||||
Order *order;
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->IsType(OT_CONDITIONAL)) {
|
||||
VehicleOrderID order_id = order->GetConditionSkipToOrder();
|
||||
if (order_id >= sel_ord) {
|
||||
order->SetConditionSkipToOrder(order_id + 1);
|
||||
}
|
||||
if (order_id == cur_order_id) {
|
||||
order->SetConditionSkipToOrder((order_id + 1) % v->num_orders);
|
||||
}
|
||||
}
|
||||
cur_order_id++;
|
||||
}
|
||||
|
||||
/* Make sure to rebuild the whole list */
|
||||
RebuildVehicleLists();
|
||||
}
|
||||
@@ -625,6 +656,21 @@ CommandCost CmdDeleteOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
InvalidateVehicleOrder(u);
|
||||
}
|
||||
|
||||
/* As we delete an order, the order to skip to will be 'wrong'. */
|
||||
VehicleOrderID cur_order_id = 0;
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->IsType(OT_CONDITIONAL)) {
|
||||
VehicleOrderID order_id = order->GetConditionSkipToOrder();
|
||||
if (order_id >= sel_ord) {
|
||||
order->SetConditionSkipToOrder(max(order_id - 1, 0));
|
||||
}
|
||||
if (order_id == cur_order_id) {
|
||||
order->SetConditionSkipToOrder((order_id + 1) % v->num_orders);
|
||||
}
|
||||
}
|
||||
cur_order_id++;
|
||||
}
|
||||
|
||||
RebuildVehicleLists();
|
||||
}
|
||||
|
||||
@@ -746,6 +792,22 @@ CommandCost CmdMoveOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
InvalidateVehicleOrder(u);
|
||||
}
|
||||
|
||||
/* As we move an order, the order to skip to will be 'wrong'. */
|
||||
Order *order;
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
if (order->IsType(OT_CONDITIONAL)) {
|
||||
VehicleOrderID order_id = order->GetConditionSkipToOrder();
|
||||
if (order_id == moving_order) {
|
||||
order_id = target_order;
|
||||
} else if(order_id > moving_order && order_id <= target_order) {
|
||||
order_id--;
|
||||
} else if(order_id < moving_order && order_id >= target_order) {
|
||||
order_id++;
|
||||
}
|
||||
order->SetConditionSkipToOrder(order_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure to rebuild the whole list */
|
||||
RebuildVehicleLists();
|
||||
}
|
||||
@@ -762,16 +824,17 @@ CommandCost CmdMoveOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
* the order will be inserted before that one
|
||||
* only the first 8 bits used currently (bit 16 - 23) (max 255)
|
||||
* @param p2 various bitstuffed elements
|
||||
* - p2 = (bit 0 - 1) - what data to modify (@see ModifyOrderFlags)
|
||||
* - p2 = (bit 2 - 5) - the data to modify
|
||||
* - p2 = (bit 0 - 3) - what data to modify (@see ModifyOrderFlags)
|
||||
* - p2 = (bit 4 - 15) - the data to modify
|
||||
*/
|
||||
CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
{
|
||||
VehicleOrderID sel_ord = GB(p1, 16, 16); // XXX - automatically truncated to 8 bits.
|
||||
VehicleID veh = GB(p1, 0, 16);
|
||||
ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 2);
|
||||
uint8 data = GB(p2, 2, 4);
|
||||
ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 4);
|
||||
uint16 data = GB(p2, 4, 11);
|
||||
|
||||
if (mof >= MOF_END) return CMD_ERROR;
|
||||
if (!IsValidVehicleID(veh)) return CMD_ERROR;
|
||||
|
||||
Vehicle *v = GetVehicle(veh);
|
||||
@@ -783,22 +846,28 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
Order *order = GetVehicleOrder(v, sel_ord);
|
||||
switch (order->GetType()) {
|
||||
case OT_GOTO_STATION:
|
||||
if (mof == MOF_DEPOT_ACTION || GetStation(order->GetDestination())->IsBuoy()) return CMD_ERROR;
|
||||
if (mof == MOF_COND_VARIABLE || mof == MOF_COND_COMPARATOR || mof == MOF_DEPOT_ACTION || mof == MOF_COND_VALUE || GetStation(order->GetDestination())->IsBuoy()) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case OT_GOTO_DEPOT:
|
||||
if (mof == MOF_UNLOAD || mof == MOF_LOAD) return CMD_ERROR;
|
||||
if (mof != MOF_NON_STOP && mof != MOF_DEPOT_ACTION) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case OT_GOTO_WAYPOINT:
|
||||
if (mof != MOF_NON_STOP) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case OT_CONDITIONAL:
|
||||
if (mof != MOF_COND_VARIABLE && mof != MOF_COND_COMPARATOR && mof != MOF_COND_VALUE) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CMD_ERROR;
|
||||
}
|
||||
|
||||
switch (mof) {
|
||||
default: NOT_REACHED();
|
||||
|
||||
case MOF_NON_STOP:
|
||||
if (data >= ONSF_END) return CMD_ERROR;
|
||||
if (data == order->GetNonStopType()) return CMD_ERROR;
|
||||
@@ -819,6 +888,36 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
case MOF_DEPOT_ACTION:
|
||||
if (data != 0) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case MOF_COND_VARIABLE:
|
||||
if (data >= OCV_END) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
case MOF_COND_COMPARATOR:
|
||||
if (data >= OCC_END) return CMD_ERROR;
|
||||
switch (order->GetConditionVariable()) {
|
||||
case OCV_REQUIRES_SERVICE:
|
||||
if (data != OCC_IS_TRUE && data != OCC_IS_FALSE) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (data == OCC_IS_TRUE || data == OCC_IS_FALSE) return CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case MOF_COND_VALUE:
|
||||
switch (order->GetConditionVariable()) {
|
||||
case OCV_LOAD_PERCENTAGE:
|
||||
case OCV_RELIABILITY:
|
||||
if (data > 100) return CMD_ERROR;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (data > 2047) return CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
@@ -846,6 +945,33 @@ CommandCost CmdModifyOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
||||
order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() ^ ODTFB_SERVICE));
|
||||
break;
|
||||
|
||||
case MOF_COND_VARIABLE: {
|
||||
order->SetConditionVariable((OrderConditionVariable)data);
|
||||
|
||||
OrderConditionComparator occ = order->GetConditionComparator();
|
||||
switch (order->GetConditionVariable()) {
|
||||
case OCV_REQUIRES_SERVICE:
|
||||
if (occ != OCC_IS_TRUE && occ != OCC_IS_FALSE) order->SetConditionComparator(OCC_IS_TRUE);
|
||||
break;
|
||||
|
||||
case OCV_LOAD_PERCENTAGE:
|
||||
case OCV_RELIABILITY:
|
||||
if (order->GetConditionValue() > 100) order->SetConditionValue(100);
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
if (occ == OCC_IS_TRUE || occ == OCC_IS_FALSE) order->SetConditionComparator(OCC_EQUALS);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case MOF_COND_COMPARATOR:
|
||||
order->SetConditionComparator((OrderConditionComparator)data);
|
||||
break;
|
||||
|
||||
case MOF_COND_VALUE:
|
||||
order->SetConditionValue(data);
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
|
||||
@@ -1416,6 +1542,24 @@ static bool CheckForValidOrders(const Vehicle *v)
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the variable and value based on the given comparator.
|
||||
*/
|
||||
static bool OrderConditionCompare(OrderConditionComparator occ, int variable, int value)
|
||||
{
|
||||
switch (occ) {
|
||||
case OCC_EQUALS: return variable == value;
|
||||
case OCC_NOT_EQUALS: return variable != value;
|
||||
case OCC_LESS_THAN: return variable < value;
|
||||
case OCC_LESS_EQUALS: return variable <= value;
|
||||
case OCC_MORE_THAN: return variable > value;
|
||||
case OCC_MORE_EQUALS: return variable >= value;
|
||||
case OCC_IS_TRUE: return variable != 0;
|
||||
case OCC_IS_FALSE: return variable == 0;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the orders of a vehicle and determine the next place
|
||||
* to go to if needed.
|
||||
@@ -1551,6 +1695,27 @@ bool ProcessOrders(Vehicle *v)
|
||||
v->dest_tile = GetWaypoint(order->GetDestination())->xy;
|
||||
break;
|
||||
|
||||
case OT_CONDITIONAL: {
|
||||
bool skip_order = false;
|
||||
OrderConditionComparator occ = order->GetConditionComparator();
|
||||
uint16 value = order->GetConditionValue();
|
||||
|
||||
switch (order->GetConditionVariable()) {
|
||||
case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
|
||||
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16, value); break;
|
||||
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(), value); break;
|
||||
case OCV_AGE: skip_order = OrderConditionCompare(occ, v->age / 366, value); break;
|
||||
case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(), value); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
UpdateVehicleTimetable(v, true);
|
||||
if (skip_order) {
|
||||
v->cur_order_index = order->GetConditionSkipToOrder();
|
||||
} else {
|
||||
v->cur_order_index++;
|
||||
}
|
||||
} return false;
|
||||
|
||||
default:
|
||||
v->dest_tile = 0;
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user