diff --git a/bin/ai/regression/regression.nut b/bin/ai/regression/regression.nut index 763cc698d3..69019f04fb 100644 --- a/bin/ai/regression/regression.nut +++ b/bin/ai/regression/regression.nut @@ -920,6 +920,15 @@ function Regression::Order() print(" UnshareOrders(): " + AIOrder.UnshareOrders(13)); print(" AppendOrder(): " + AIOrder.AppendOrder(12, 33421, AIOrder.AIOF_NONE)); + print(" GetStopLocation(): " + AIOrder.GetStopLocation(13, 0)); + print(" BuildVehicle(): " + AIVehicle.BuildVehicle(23596, 8)); + print(" BuildRailStation(): " + AIRail.BuildRailStation(7958, AIRail.RAILTRACK_NE_SW, 1, 1, AIStation.STATION_NEW)); + print(" AppendOrder(): " + AIOrder.AppendOrder(20, 7958, AIOrder.AIOF_NONE)); + print(" GetOrderCount(): " + AIOrder.GetOrderCount(20)); + print(" GetStopLocation(): " + AIOrder.GetStopLocation(20, 0)); + print(" SetStopLocation(): " + AIOrder.SetStopLocation(20, 0, AIOrder.STOPLOCATION_MIDDLE)); + print(" GetStopLocation(): " + AIOrder.GetStopLocation(20, 0)); + local list = AIStationList_Vehicle(12); print(""); @@ -1024,6 +1033,7 @@ function Regression::Rail() print(" " + i + " => " + list.GetValue(i)); } print(" RemoveDepot(): " + AITile.DemolishTile(33411)); + print(" BuildRailDepot(): " + AIRail.BuildRailDepot(23596, 23597)); print(" Station"); print(" BuildRailStation(): " + AIRail.BuildRailStation(0, AIRail.RAILTRACK_NE_SW, 1, 1, AIStation.STATION_NEW)); diff --git a/bin/ai/regression/regression.txt b/bin/ai/regression/regression.txt index ae8d8e1756..be69ce3889 100644 --- a/bin/ai/regression/regression.txt +++ b/bin/ai/regression/regression.txt @@ -7179,6 +7179,7 @@ Depot distance from (0,0) ListDump: 33411 => 261 RemoveDepot(): true + BuildRailDepot(): true Station BuildRailStation(): false BuildRailStation(): true @@ -8565,6 +8566,14 @@ ShareOrders(): true UnshareOrders(): true AppendOrder(): true + GetStopLocation(): -1 + BuildVehicle(): 20 + BuildRailStation(): true + AppendOrder(): true + GetOrderCount(): 1 + GetStopLocation(): 2 + SetStopLocation(): true + GetStopLocation(): 1 --StationList_Vehicle-- Count(): 2 @@ -8591,9 +8600,11 @@ 4 => 0 --VehicleList_Station-- - Count(): 0 + Count(): 1 Location ListDump: + 20 => 23596 foreach(): + 20 => 23596 First Subsidy Test --Subsidy (0) -- diff --git a/src/ai/api/ai_changelog.hpp b/src/ai/api/ai_changelog.hpp index fc8b697c8f..813ca16692 100644 --- a/src/ai/api/ai_changelog.hpp +++ b/src/ai/api/ai_changelog.hpp @@ -26,6 +26,8 @@ * \li AIInfo::AICONFIG_INGAME * \li AIMarine::GetBuildCost * \li AIOrder::AIOF_GOTO_NEAREST_DEPOT + * \li AIOrder::GetStopLocation + * \li AIOrder::SetStopLocation * \li AIRail::RemoveRailStationTileRectangle * \li AIRail::RemoveRailWaypointTileRectangle * \li AIRail::GetBuildCost diff --git a/src/ai/api/ai_order.cpp b/src/ai/api/ai_order.cpp index 3e7ff11afa..cdc56ccf83 100644 --- a/src/ai/api/ai_order.cpp +++ b/src/ai/api/ai_order.cpp @@ -285,6 +285,16 @@ static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition or return value; } +/* static */ AIOrder::StopLocation AIOrder::GetStopLocation(VehicleID vehicle_id, OrderPosition order_position) +{ + if (!IsValidVehicleOrder(vehicle_id, order_position)) return STOPLOCATION_INVALID; + if (AIVehicle::GetVehicleType(vehicle_id) != AIVehicle::VT_RAIL) return STOPLOCATION_INVALID; + if (!IsGotoStationOrder(vehicle_id, order_position)) return STOPLOCATION_INVALID; + + const Order *order = Vehicle::Get(vehicle_id)->GetOrder(order_position); + return (AIOrder::StopLocation)order->GetStopLocation(); +} + /* static */ bool AIOrder::SetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to) { EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position)); @@ -322,6 +332,18 @@ static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition or return AIObject::DoCommand(0, vehicle_id | (order_position << 16), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER); } +/* static */ bool AIOrder::SetStopLocation(VehicleID vehicle_id, OrderPosition order_position, StopLocation stop_location) +{ + EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position)); + EnforcePrecondition(false, AIVehicle::GetVehicleType(vehicle_id) == AIVehicle::VT_RAIL); + EnforcePrecondition(false, IsGotoStationOrder(vehicle_id, order_position)); + EnforcePrecondition(false, stop_location >= STOPLOCATION_NEAR && stop_location <= STOPLOCATION_FAR); + + uint32 p1 = vehicle_id | (order_position << 16); + uint32 p2 = MOF_STOP_LOCATION | (stop_location << 4); + return AIObject::DoCommand(0, p1, p2, CMD_MODIFY_ORDER); +} + /* static */ bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags) { EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id)); diff --git a/src/ai/api/ai_order.hpp b/src/ai/api/ai_order.hpp index 53ce0d2617..fe0dcd826d 100644 --- a/src/ai/api/ai_order.hpp +++ b/src/ai/api/ai_order.hpp @@ -118,6 +118,14 @@ public: ORDER_INVALID = -1, //!< An invalid order. }; + /** Where to stop trains in a station that's longer then the train */ + enum StopLocation { + STOPLOCATION_NEAR, //!< Stop the train as soon as it's completely in the station + STOPLOCATION_MIDDLE, //!< Stop the train in the middle of the station + STOPLOCATION_FAR, //!< Stop the train at the far end of the station + STOPLOCATION_INVALID = -1, //!< An invalid stop location + }; + /** * Checks whether the given order id is valid for the given vehicle. * @param vehicle_id The vehicle to check the order index for. @@ -281,6 +289,17 @@ public: */ static int32 GetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position); + /** + * Gets the stoplocation of the given order for the given train. + * @param vehicle_id The vehicle to get the value for. + * @param order_position The order to get the value for. + * @pre IsValidVehicleOrder(vehicle_id, order_position). + * @pre AIVehicle::GetVehicleType(vehicle_id) == AIVehicle::VT_RAIL. + * @pre IsGotoStationOrder(vehicle_id, order_position). + * @return The relative position where the train will stop inside a station. + */ + static StopLocation GetStopLocation(VehicleID vehicle_id, OrderPosition order_position); + /** * Sets the OrderPosition to jump to if the check succeeds of the given order for the given vehicle. * @param vehicle_id The vehicle to set the OrderPosition for. @@ -329,6 +348,17 @@ public: */ static bool SetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position, int32 value); + /** + * Sets the stoplocation of the given order for the given train. + * @param vehicle_id The vehicle to get the value for. + * @param order_position The order to get the value for. + * @pre IsValidVehicleOrder(vehicle_id, order_position). + * @pre AIVehicle::GetVehicleType(vehicle_id) == AIVehicle::VT_RAIL. + * @pre IsGotoStationOrder(vehicle_id, order_position). + * @return Whether the order has been/can be changed. + */ + static bool SetStopLocation(VehicleID vehicle_id, OrderPosition order_position, StopLocation stop_location); + /** * Appends an order to the end of the vehicle's order list. * @param vehicle_id The vehicle to append the order to. diff --git a/src/ai/api/ai_order.hpp.sq b/src/ai/api/ai_order.hpp.sq index 53fa61e4ec..c6aa1c8736 100644 --- a/src/ai/api/ai_order.hpp.sq +++ b/src/ai/api/ai_order.hpp.sq @@ -23,6 +23,8 @@ namespace SQConvert { template <> int Return(HSQUIRRELVM vm, AIOrder::CompareFunction res) { sq_pushinteger(vm, (int32)res); return 1; } template <> AIOrder::OrderPosition GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIOrder::OrderPosition)tmp; } template <> int Return(HSQUIRRELVM vm, AIOrder::OrderPosition res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> AIOrder::StopLocation GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AIOrder::StopLocation)tmp; } + template <> int Return(HSQUIRRELVM vm, AIOrder::StopLocation res) { sq_pushinteger(vm, (int32)res); return 1; } /* Allow AIOrder to be used as Squirrel parameter */ template <> AIOrder *GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (AIOrder *)instance; } @@ -76,6 +78,10 @@ void SQAIOrder_Register(Squirrel *engine) SQAIOrder.DefSQConst(engine, AIOrder::CF_INVALID, "CF_INVALID"); SQAIOrder.DefSQConst(engine, AIOrder::ORDER_CURRENT, "ORDER_CURRENT"); SQAIOrder.DefSQConst(engine, AIOrder::ORDER_INVALID, "ORDER_INVALID"); + SQAIOrder.DefSQConst(engine, AIOrder::STOPLOCATION_NEAR, "STOPLOCATION_NEAR"); + SQAIOrder.DefSQConst(engine, AIOrder::STOPLOCATION_MIDDLE, "STOPLOCATION_MIDDLE"); + SQAIOrder.DefSQConst(engine, AIOrder::STOPLOCATION_FAR, "STOPLOCATION_FAR"); + SQAIOrder.DefSQConst(engine, AIOrder::STOPLOCATION_INVALID, "STOPLOCATION_INVALID"); AIError::RegisterErrorMap(STR_ERROR_NO_MORE_SPACE_FOR_ORDERS, AIOrder::ERR_ORDER_TOO_MANY); AIError::RegisterErrorMap(STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION, AIOrder::ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION); @@ -99,10 +105,12 @@ void SQAIOrder_Register(Squirrel *engine) SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCondition, "GetOrderCondition", 3, ".ii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCompareFunction, "GetOrderCompareFunction", 3, ".ii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCompareValue, "GetOrderCompareValue", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetStopLocation, "GetStopLocation", 3, ".ii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderJumpTo, "SetOrderJumpTo", 4, ".iii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCondition, "SetOrderCondition", 4, ".iii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCompareFunction, "SetOrderCompareFunction", 4, ".iii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCompareValue, "SetOrderCompareValue", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetStopLocation, "SetStopLocation", 4, ".iii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendOrder, "AppendOrder", 4, ".iii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendConditionalOrder, "AppendConditionalOrder", 3, ".ii"); SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertOrder, "InsertOrder", 5, ".iiii");