From 909af50aaa1dcf4a79a320e12417b7dbce297345 Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 6 May 2009 22:31:52 +0000 Subject: [PATCH] (svn r16246) [0.7] -Backport from trunk: - Fix: [Squirrel] the traps variable wasn't restored, causing try/catch blocks to be 'forgotten' during a suspend (r16181) - Add: [NoAI] Two new error codes to AITile: ERR_AREA_ALREADY_FLAT and ERR_EXCAVATION_WOULD_DAMAGE (r16171) - Add: [NoAI] AITile::Get(Min|Max|Corner)Height (r16166) - Add: [NoAI] Several functions to AIOrder to check the what kind of order an order is [FS#2801] (r16165) - Fix: [NoAI] AIOrder::GetOrderDestination and AIOrder::GetOrderFlags didn't work on ORDER_CURRENT when the vehicle was loading/leaving in a station (r16165) - Fix: [NoAI] Change WAYPOINT_INVALID to 0xFFFF from -1 as that is the value the AIs got (due to casting) (r16150) --- bin/ai/regression/regression.nut | 28 ++- bin/ai/regression/regression.txt | 263 ++++++++++++++++-------- src/3rdparty/squirrel/squirrel/sqvm.cpp | 5 +- src/ai/ai_instance.cpp | 13 +- src/ai/api/ai_industry.hpp | 4 +- src/ai/api/ai_order.cpp | 69 +++++-- src/ai/api/ai_order.hpp | 38 ++++ src/ai/api/ai_order.hpp.sq | 60 +++--- src/ai/api/ai_tile.cpp | 26 ++- src/ai/api/ai_tile.hpp | 72 ++++++- src/ai/api/ai_tile.hpp.sq | 84 +++++--- src/ai/api/ai_vehicle.cpp | 7 + src/ai/api/ai_vehicle.hpp | 15 +- src/ai/api/ai_vehicle.hpp.sq | 83 ++++---- src/ai/api/ai_waypoint.hpp | 2 +- src/slope_type.h | 2 +- 16 files changed, 541 insertions(+), 230 deletions(-) diff --git a/bin/ai/regression/regression.nut b/bin/ai/regression/regression.nut index 02f2e55bfc..8b77879bd2 100644 --- a/bin/ai/regression/regression.nut +++ b/bin/ai/regression/regression.nut @@ -1189,7 +1189,7 @@ function Regression::TileList() print(""); print("--TileList--"); print(" Count(): " + list.Count()); - list.AddRectangle(41895 - 256 * 2, 256 * 2 + 41895 + 8); + list.AddRectangle(34436, 256 * 2 + 34436 + 8); print(" Count(): " + list.Count()); list.Valuate(AITile.GetHeight); @@ -1200,6 +1200,30 @@ function Regression::TileList() print(" " + i + " => " + list.GetValue(i)); } + list.Valuate(AITile.GetCornerHeight, AITile.CORNER_N); + print(" CornerHeight(North): done"); + print(" Count(): " + list.Count()); + print(" ListDump:"); + for (local i = list.Begin(); list.HasNext(); i = list.Next()) { + print(" " + i + " => " + list.GetValue(i)); + } + + list.Valuate(AITile.GetMinHeight); + print(" MinHeight(): done"); + print(" Count(): " + list.Count()); + print(" ListDump:"); + for (local i = list.Begin(); list.HasNext(); i = list.Next()) { + print(" " + i + " => " + list.GetValue(i)); + } + + list.Valuate(AITile.GetMaxHeight); + print(" MaxHeight(): done"); + print(" Count(): " + list.Count()); + print(" ListDump:"); + for (local i = list.Begin(); list.HasNext(); i = list.Next()) { + print(" " + i + " => " + list.GetValue(i)); + } + list.Valuate(AITile.GetSlope); list.KeepValue(0); print(" Slope(): done"); @@ -1210,6 +1234,8 @@ function Regression::TileList() print(" " + i + " => " + list.GetValue(i)); } + list.Clear(); + list.AddRectangle(41895 - 256 * 2, 256 * 2 + 41895 + 8); list.Valuate(AITile.IsBuildable); list.KeepValue(1); print(" Buildable(): done"); diff --git a/bin/ai/regression/regression.txt b/bin/ai/regression/regression.txt index c3c7931791..5a7c96d2a5 100644 --- a/bin/ai/regression/regression.txt +++ b/bin/ai/regression/regression.txt @@ -7366,125 +7366,178 @@ --TileList-- Count(): 0 - Count(): 45 + Count(): 27 Height(): done - Count(): 45 + Count(): 27 ListDump: - 42411 => 2 - 42410 => 2 - 42409 => 2 - 42408 => 2 - 42407 => 2 - 42154 => 2 - 42153 => 2 - 42152 => 2 - 42151 => 2 - 41898 => 2 - 41897 => 2 - 41896 => 2 - 41895 => 2 - 41642 => 2 - 41641 => 2 - 41640 => 2 - 41639 => 2 - 41386 => 2 - 41385 => 2 - 41384 => 2 - 41383 => 2 - 42415 => 1 - 42414 => 1 - 42413 => 1 - 42412 => 1 - 42159 => 1 - 42158 => 1 - 42157 => 1 - 42156 => 1 - 42155 => 1 - 41903 => 1 - 41902 => 1 - 41901 => 1 - 41900 => 1 - 41899 => 1 - 41647 => 1 - 41646 => 1 - 41645 => 1 - 41644 => 1 - 41643 => 1 - 41391 => 1 - 41390 => 1 - 41389 => 1 - 41388 => 1 - 41387 => 1 + 34956 => 4 + 34700 => 4 + 34444 => 4 + 34955 => 3 + 34954 => 3 + 34953 => 3 + 34699 => 3 + 34698 => 3 + 34697 => 3 + 34693 => 3 + 34692 => 3 + 34443 => 3 + 34442 => 3 + 34441 => 3 + 34439 => 3 + 34438 => 3 + 34437 => 3 + 34436 => 3 + 34952 => 2 + 34951 => 2 + 34950 => 2 + 34949 => 2 + 34948 => 2 + 34696 => 2 + 34695 => 2 + 34694 => 2 + 34440 => 2 + CornerHeight(North): done + Count(): 27 + ListDump: + 34956 => 4 + 34700 => 4 + 34444 => 4 + 34955 => 3 + 34954 => 3 + 34953 => 3 + 34699 => 3 + 34698 => 3 + 34697 => 3 + 34693 => 3 + 34692 => 3 + 34443 => 3 + 34442 => 3 + 34441 => 3 + 34439 => 3 + 34438 => 3 + 34437 => 3 + 34436 => 3 + 34952 => 2 + 34951 => 2 + 34950 => 2 + 34949 => 2 + 34948 => 2 + 34696 => 2 + 34695 => 2 + 34694 => 2 + 34440 => 2 + MinHeight(): done + Count(): 27 + ListDump: + 34956 => 4 + 34700 => 4 + 34444 => 4 + 34955 => 3 + 34954 => 3 + 34953 => 3 + 34699 => 3 + 34698 => 3 + 34697 => 3 + 34443 => 3 + 34442 => 3 + 34441 => 3 + 34436 => 3 + 34952 => 2 + 34951 => 2 + 34950 => 2 + 34949 => 2 + 34948 => 2 + 34696 => 2 + 34695 => 2 + 34694 => 2 + 34693 => 2 + 34692 => 2 + 34440 => 2 + 34439 => 2 + 34438 => 2 + 34437 => 2 + MaxHeight(): done + Count(): 27 + ListDump: + 34956 => 4 + 34955 => 4 + 34700 => 4 + 34699 => 4 + 34444 => 4 + 34443 => 4 + 34954 => 3 + 34953 => 3 + 34952 => 3 + 34951 => 3 + 34950 => 3 + 34949 => 3 + 34948 => 3 + 34698 => 3 + 34697 => 3 + 34696 => 3 + 34693 => 3 + 34692 => 3 + 34442 => 3 + 34441 => 3 + 34440 => 3 + 34439 => 3 + 34438 => 3 + 34437 => 3 + 34436 => 3 + 34695 => 2 + 34694 => 2 Slope(): done KeepValue(0): done - Count(): 38 + Count(): 12 ListDump: - 42415 => 0 - 42414 => 0 - 42413 => 0 - 42410 => 0 - 42409 => 0 - 42408 => 0 - 42407 => 0 - 42159 => 0 - 42158 => 0 - 42157 => 0 - 42156 => 0 - 42153 => 0 - 42152 => 0 - 42151 => 0 - 41903 => 0 - 41902 => 0 - 41901 => 0 - 41900 => 0 - 41899 => 0 - 41897 => 0 - 41896 => 0 - 41895 => 0 - 41647 => 0 - 41646 => 0 - 41645 => 0 - 41644 => 0 - 41643 => 0 - 41641 => 0 - 41640 => 0 - 41639 => 0 - 41391 => 0 - 41390 => 0 - 41389 => 0 - 41388 => 0 - 41387 => 0 - 41385 => 0 - 41384 => 0 - 41383 => 0 + 34956 => 0 + 34954 => 0 + 34953 => 0 + 34700 => 0 + 34698 => 0 + 34697 => 0 + 34695 => 0 + 34694 => 0 + 34444 => 0 + 34442 => 0 + 34441 => 0 + 34436 => 0 Buildable(): done KeepValue(1): done - Count(): 28 + Count(): 35 BuildableRectangle(3, 3) ListDump: 42415 => 1 42414 => 1 42413 => 1 + 42412 => 1 + 42411 => 1 42410 => 1 42159 => 1 42158 => 1 42157 => 1 42156 => 1 + 42155 => 1 + 42154 => 1 41903 => 1 41902 => 1 41901 => 1 41900 => 1 41899 => 1 + 41898 => 1 41647 => 1 41646 => 1 41645 => 1 41644 => 1 41643 => 1 + 41642 => 1 41641 => 1 41391 => 1 41390 => 1 41389 => 1 41388 => 1 41387 => 1 + 41386 => 1 41385 => 1 42153 => 0 41897 => 0 @@ -7496,26 +7549,33 @@ 42413 => 173 42158 => 173 41903 => 173 + 42412 => 172 42157 => 172 41902 => 172 41647 => 172 + 42411 => 171 42156 => 171 41901 => 171 41646 => 171 41391 => 171 42410 => 170 + 42155 => 170 41900 => 170 41645 => 170 41390 => 170 + 42154 => 169 41899 => 169 41644 => 169 41389 => 169 42153 => 168 + 41898 => 168 41643 => 168 41388 => 168 41897 => 167 + 41642 => 167 41387 => 167 41641 => 166 + 41386 => 166 41385 => 165 41384 => 164 DistanceSquareToTile(30000) ListDump: @@ -7532,17 +7592,24 @@ 42157 => 17834 41390 => 17812 41901 => 17741 + 42412 => 17680 41645 => 17650 42156 => 17585 41389 => 17561 41900 => 17492 + 42411 => 17433 41644 => 17401 + 42155 => 17338 41388 => 17312 41899 => 17245 42410 => 17188 41643 => 17154 + 42154 => 17093 41387 => 17065 + 41898 => 17000 + 41642 => 16909 42153 => 16850 + 41386 => 16820 41897 => 16757 41641 => 16666 41385 => 16577 @@ -7551,63 +7618,77 @@ 42415 => -1 42414 => -1 42413 => -1 + 42412 => -1 + 42411 => -1 42410 => -1 42159 => -1 42158 => -1 42157 => -1 42156 => -1 + 42155 => -1 + 42154 => -1 42153 => -1 41903 => -1 41902 => -1 41901 => -1 41900 => -1 41899 => -1 + 41898 => -1 41897 => -1 41647 => -1 41646 => -1 41645 => -1 41644 => -1 41643 => -1 + 41642 => -1 41641 => -1 41391 => -1 41390 => -1 41389 => -1 41388 => -1 41387 => -1 + 41386 => -1 41385 => -1 41384 => -1 GetClosestTown() ListDump: 42415 => 3 42414 => 3 42413 => 3 + 42412 => 3 + 42411 => 3 42410 => 3 42159 => 3 42158 => 3 42157 => 3 42156 => 3 + 42155 => 3 + 42154 => 3 42153 => 3 41903 => 3 41902 => 3 41901 => 3 41900 => 3 41899 => 3 + 41898 => 3 41897 => 3 41647 => 3 41646 => 3 41645 => 3 41644 => 3 41643 => 3 + 41642 => 3 41641 => 3 41391 => 3 41390 => 3 41389 => 3 41388 => 3 41387 => 3 + 41386 => 3 41385 => 3 41384 => 3 CargoAcceptance(): done KeepAboveValue(10): done - Count(): 9 + Count(): 15 ListDump: 41897 => 29 41385 => 26 @@ -7615,9 +7696,15 @@ 42153 => 25 41641 => 23 41899 => 17 + 41898 => 17 41387 => 17 + 41386 => 17 41643 => 14 + 41642 => 14 + 42411 => 13 42410 => 13 + 42155 => 13 + 42154 => 13 RoadTile(): done KeepValue(1): done Count(): 0 diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp index dbd9e9dd89..0cb66e9c11 100644 --- a/src/3rdparty/squirrel/squirrel/sqvm.cpp +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -83,7 +83,7 @@ SQVM::SQVM(SQSharedState *ss) _suspended = SQFalse; _suspended_target=-1; _suspended_root = SQFalse; - _suspended_traps=-1; + _suspended_traps=0; _foreignptr=NULL; _nnativecalls=0; _lasterror = _null_; @@ -688,6 +688,7 @@ bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQIn _suspended = SQFalse; break; case ET_RESUME_OPENTTD: + traps = _suspended_traps; _suspended = SQFalse; break; } @@ -698,7 +699,7 @@ exception_restore: for(;;) { DecreaseOps(1); - if (ShouldSuspend()) { _suspended = SQTrue; return true; } + if (ShouldSuspend()) { _suspended = SQTrue; _suspended_traps = traps; return true; } const SQInstruction &_i_ = *ci->_ip++; //dumpstack(_stackbase); diff --git a/src/ai/ai_instance.cpp b/src/ai/ai_instance.cpp index dcd68410b7..0ad34836ba 100644 --- a/src/ai/ai_instance.cpp +++ b/src/ai/ai_instance.cpp @@ -256,14 +256,15 @@ void AIInstance::Died() this->engine = NULL; ShowAIDebugWindow(_current_company); - if (strcmp(GetCompany(_current_company)->ai_info->GetMainScript(), "%_dummy") != 0) { - ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0); - } const AIInfo *info = AIConfig::GetConfig(_current_company)->GetInfo(); - if (info->GetURL() != NULL) { - AILog::Info("Please report the error to the following URL:"); - AILog::Info(info->GetURL()); + if (info != NULL) { + ShowErrorMessage(INVALID_STRING_ID, STR_AI_PLEASE_REPORT_CRASH, 0, 0); + + if (info->GetURL() != NULL) { + AILog::Info("Please report the error to the following URL:"); + AILog::Info(info->GetURL()); + } } } diff --git a/src/ai/api/ai_industry.hpp b/src/ai/api/ai_industry.hpp index bf93cd4669..da27ec9207 100644 --- a/src/ai/api/ai_industry.hpp +++ b/src/ai/api/ai_industry.hpp @@ -86,7 +86,9 @@ public: static TileIndex GetLocation(IndustryID industry_id); /** - * Get the number of stations around an industry. + * Get the number of stations around an industry. All stations that can + * service the industry are counted, your own stations but also your + * opponents stations. * @param industry_id The index of the industry. * @pre IsValidIndustry(industry_id). * @return The number of stations around an industry. diff --git a/src/ai/api/ai_order.cpp b/src/ai/api/ai_order.cpp index 5d1165eba2..576958ee76 100644 --- a/src/ai/api/ai_order.cpp +++ b/src/ai/api/ai_order.cpp @@ -46,6 +46,47 @@ static OrderType GetOrderTypeByTile(TileIndex t) return AIVehicle::IsValidVehicle(vehicle_id) && order_position >= 0 && (order_position < ::GetVehicle(vehicle_id)->GetNumOrders() || order_position == ORDER_CURRENT); } +/** + * Get the current order the vehicle is executing. If the current order is in + * the order list, return the order from the orderlist. If the current order + * was a manual order, return the current order. + */ +static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition order_position) +{ + const Vehicle *v = ::GetVehicle(vehicle_id); + if (order_position == AIOrder::ORDER_CURRENT) { + const Order *order = &v->current_order; + if (order->GetType() == OT_GOTO_DEPOT && !(order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) return order; + order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position); + if (order_position == AIOrder::ORDER_INVALID) return NULL; + } + return ::GetVehicleOrder(v, order_position); +} + +/* static */ bool AIOrder::IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position) +{ + if (!IsValidVehicleOrder(vehicle_id, order_position)) return false; + + const Order *order = ::ResolveOrder(vehicle_id, order_position); + return order != NULL && order->GetType() == OT_GOTO_STATION; +} + +/* static */ bool AIOrder::IsGotoDepotOrder(VehicleID vehicle_id, OrderPosition order_position) +{ + if (!IsValidVehicleOrder(vehicle_id, order_position)) return false; + + const Order *order = ::ResolveOrder(vehicle_id, order_position); + return order != NULL && order->GetType() == OT_GOTO_DEPOT; +} + +/* static */ bool AIOrder::IsGotoWaypointOrder(VehicleID vehicle_id, OrderPosition order_position) +{ + if (!IsValidVehicleOrder(vehicle_id, order_position)) return false; + + const Order *order = ::ResolveOrder(vehicle_id, order_position); + return order != NULL && order->GetType() == OT_GOTO_WAYPOINT; +} + /* static */ bool AIOrder::IsConditionalOrder(VehicleID vehicle_id, OrderPosition order_position) { if (order_position == ORDER_CURRENT) return false; @@ -55,6 +96,16 @@ static OrderType GetOrderTypeByTile(TileIndex t) return order->GetType() == OT_CONDITIONAL; } +/* static */ bool AIOrder::IsCurrentOrderPartOfOrderList(VehicleID vehicle_id) +{ + if (AIVehicle::IsValidVehicle(vehicle_id)) return false; + if (GetOrderCount(vehicle_id) == 0) return false; + + const Order *order = &::GetVehicle(vehicle_id)->current_order; + if (order->GetType() != OT_GOTO_DEPOT) return true; + return (order->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) != 0; +} + /* static */ AIOrder::OrderPosition AIOrder::ResolveOrderPosition(VehicleID vehicle_id, OrderPosition order_position) { if (!AIVehicle::IsValidVehicle(vehicle_id)) return ORDER_INVALID; @@ -114,14 +165,9 @@ static OrderType GetOrderTypeByTile(TileIndex t) { if (!IsValidVehicleOrder(vehicle_id, order_position)) return INVALID_TILE; - const Order *order; + const Order *order = ::ResolveOrder(vehicle_id, order_position); + if (order == NULL || order->GetType() == OT_CONDITIONAL) return INVALID_TILE; const Vehicle *v = ::GetVehicle(vehicle_id); - if (order_position == ORDER_CURRENT) { - order = &v->current_order; - } else { - order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position); - if (order->GetType() == OT_CONDITIONAL) return INVALID_TILE; - } switch (order->GetType()) { case OT_GOTO_DEPOT: { @@ -163,13 +209,8 @@ static OrderType GetOrderTypeByTile(TileIndex t) { if (!IsValidVehicleOrder(vehicle_id, order_position)) return AIOF_INVALID; - const Order *order; - if (order_position == ORDER_CURRENT) { - order = &::GetVehicle(vehicle_id)->current_order; - } else { - order = ::GetVehicleOrder(GetVehicle(vehicle_id), order_position); - if (order->GetType() == OT_CONDITIONAL) return AIOF_INVALID; - } + const Order *order = ::ResolveOrder(vehicle_id, order_position); + if (order == NULL || order->GetType() == OT_CONDITIONAL) return AIOF_INVALID; AIOrderFlags order_flags = AIOF_NONE; order_flags |= (AIOrderFlags)order->GetNonStopType(); diff --git a/src/ai/api/ai_order.hpp b/src/ai/api/ai_order.hpp index 8a08b505a0..daf1a21d77 100644 --- a/src/ai/api/ai_order.hpp +++ b/src/ai/api/ai_order.hpp @@ -118,6 +118,33 @@ public: */ static bool IsValidVehicleOrder(VehicleID vehicle_id, OrderPosition order_position); + /** + * Checks whether the given order is a goto-station order. + * @param vehicle_id The vehicle to check. + * @param order_position The order index to check. + * @pre IsValidVehicleOrder(vehicle_id, order_position). + * @return True if and only if the order is a goto-station order. + */ + static bool IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position); + + /** + * Checks whether the given order is a goto-depot order. + * @param vehicle_id The vehicle to check. + * @param order_position The order index to check. + * @pre IsValidVehicleOrder(vehicle_id, order_position). + * @return True if and only if the order is a goto-depot order. + */ + static bool IsGotoDepotOrder(VehicleID vehicle_id, OrderPosition order_position); + + /** + * Checks whether the given order is a goto-waypoint order. + * @param vehicle_id The vehicle to check. + * @param order_position The order index to check. + * @pre IsValidVehicleOrder(vehicle_id, order_position). + * @return True if and only if the order is a goto-waypoint order. + */ + static bool IsGotoWaypointOrder(VehicleID vehicle_id, OrderPosition order_position); + /** * Checks whether the given order is a conditional order. * @param vehicle_id The vehicle to check. @@ -127,6 +154,17 @@ public: */ static bool IsConditionalOrder(VehicleID vehicle_id, OrderPosition order_position); + /** + * Checks whether the current order is part of the orderlist. + * @param vehicle_id The vehicle to check. + * @pre AIVehicle::IsValidVehicle(vehicle_id). + * @return True if and only if the current order is part of the order list. + * @note If the order is a non-'non-stop' order, and the vehicle is currently + * (un)loading at a station that is not the final destination, this function + * will still return true. + */ + static bool IsCurrentOrderPartOfOrderList(VehicleID vehicle_id); + /** * Resolves the given order index to the correct index for the given vehicle. * If the order index was ORDER_CURRENT it will be resolved to the index of diff --git a/src/ai/api/ai_order.hpp.sq b/src/ai/api/ai_order.hpp.sq index d2ac2ae8a4..a221fea65f 100644 --- a/src/ai/api/ai_order.hpp.sq +++ b/src/ai/api/ai_order.hpp.sq @@ -73,34 +73,38 @@ void SQAIOrder_Register(Squirrel *engine) { AIError::RegisterErrorMapString(AIOrder::ERR_ORDER_TOO_MANY, "ERR_ORDER_TOO_MANY"); AIError::RegisterErrorMapString(AIOrder::ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION, "ERR_ORDER_TOO_FAR_AWAY_FROM_PREVIOUS_DESTINATION"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsValidVehicleOrder, "IsValidVehicleOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsConditionalOrder, "IsConditionalOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ResolveOrderPosition, "ResolveOrderPosition", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AreOrderFlagsValid, "AreOrderFlagsValid", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsValidConditionalOrder, "IsValidConditionalOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCount, "GetOrderCount", 2, ".i"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderDestination, "GetOrderDestination", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderFlags, "GetOrderFlags", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderJumpTo, "GetOrderJumpTo", 3, ".ii"); - 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::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::AppendOrder, "AppendOrder", 4, ".iii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendConditionalOrder, "AppendConditionalOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertOrder, "InsertOrder", 5, ".iiii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertConditionalOrder, "InsertConditionalOrder", 4, ".iii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::RemoveOrder, "RemoveOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderFlags, "SetOrderFlags", 4, ".iii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ChangeOrder, "ChangeOrder", 4, ".iii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::MoveOrder, "MoveOrder", 4, ".iii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SkipToOrder, "SkipToOrder", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::CopyOrders, "CopyOrders", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ShareOrders, "ShareOrders", 3, ".ii"); - SQAIOrder.DefSQStaticMethod(engine, &AIOrder::UnshareOrders, "UnshareOrders", 2, ".i"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsValidVehicleOrder, "IsValidVehicleOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsGotoStationOrder, "IsGotoStationOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsGotoDepotOrder, "IsGotoDepotOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsGotoWaypointOrder, "IsGotoWaypointOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsConditionalOrder, "IsConditionalOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsCurrentOrderPartOfOrderList, "IsCurrentOrderPartOfOrderList", 2, ".i"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ResolveOrderPosition, "ResolveOrderPosition", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AreOrderFlagsValid, "AreOrderFlagsValid", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsValidConditionalOrder, "IsValidConditionalOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCount, "GetOrderCount", 2, ".i"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderDestination, "GetOrderDestination", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderFlags, "GetOrderFlags", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderJumpTo, "GetOrderJumpTo", 3, ".ii"); + 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::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::AppendOrder, "AppendOrder", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendConditionalOrder, "AppendConditionalOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertOrder, "InsertOrder", 5, ".iiii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertConditionalOrder, "InsertConditionalOrder", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::RemoveOrder, "RemoveOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderFlags, "SetOrderFlags", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ChangeOrder, "ChangeOrder", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::MoveOrder, "MoveOrder", 4, ".iii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SkipToOrder, "SkipToOrder", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::CopyOrders, "CopyOrders", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ShareOrders, "ShareOrders", 3, ".ii"); + SQAIOrder.DefSQStaticMethod(engine, &AIOrder::UnshareOrders, "UnshareOrders", 2, ".i"); SQAIOrder.PostRegister(engine); } diff --git a/src/ai/api/ai_tile.cpp b/src/ai/api/ai_tile.cpp index 8a04c17728..f5bf96f1a8 100644 --- a/src/ai/api/ai_tile.cpp +++ b/src/ai/api/ai_tile.cpp @@ -11,6 +11,7 @@ #include "../../water_map.h" #include "../../clear_map.h" #include "../../town.h" +#include "../../landscape.h" /* static */ bool AITile::IsBuildable(TileIndex tile) { @@ -132,11 +133,34 @@ /* static */ int32 AITile::GetHeight(TileIndex tile) { - if (!::IsValidTile(tile)) return false; + if (!::IsValidTile(tile)) return -1; return ::TileHeight(tile); } +/* static */ int32 AITile::GetMinHeight(TileIndex tile) +{ + if (!::IsValidTile(tile)) return -1; + + return ::GetTileZ(tile) / ::TILE_HEIGHT; +} + +/* static */ int32 AITile::GetMaxHeight(TileIndex tile) +{ + if (!::IsValidTile(tile)) return -1; + + return ::GetTileMaxZ(tile) / ::TILE_HEIGHT; +} + +/* static */ int32 AITile::GetCornerHeight(TileIndex tile, Corner corner) +{ + if (!::IsValidTile(tile) || !::IsValidCorner((::Corner)corner)) return -1; + + uint z; + ::Slope slope = ::GetTileSlope(tile, &z); + return (z + ::GetSlopeZInCorner(slope, (::Corner)corner)) / ::TILE_HEIGHT; +} + /* static */ AICompany::CompanyID AITile::GetOwner(TileIndex tile) { if (!::IsValidTile(tile)) return AICompany::COMPANY_INVALID; diff --git a/src/ai/api/ai_tile.hpp b/src/ai/api/ai_tile.hpp index 576bacf078..e1e20d5fa6 100644 --- a/src/ai/api/ai_tile.hpp +++ b/src/ai/api/ai_tile.hpp @@ -29,10 +29,28 @@ public: /** Tile can't be lowered any lower */ ERR_TILE_TOO_LOW, // [STR_1003_ALREADY_AT_SEA_LEVEL] + + /** The area was already flat */ + ERR_AREA_ALREADY_FLAT, // [STR_ALREADY_LEVELLED] + + /** There is a tunnel underneed */ + ERR_EXCAVATION_WOULD_DAMAGE, // [STR_1002_EXCAVATION_WOULD_DAMAGE] }; /** - * Enumeration for the slope-type (from slopes.h). + * Enumeration for corners of tiles. + */ + enum Corner { + CORNER_W = 0, //!< West corner + CORNER_S = 1, //!< South corner + CORNER_E = 2, //!< East corner + CORNER_N = 3, //!< North corner + + CORNER_INVALID = 0xFF, + }; + + /** + * Enumeration for the slope-type. * * This enumeration use the chars N, E, S, W corresponding the * direction North, East, South and West. The top corner of a tile @@ -41,18 +59,18 @@ public: enum Slope { /* Values are important, as they represent the internal state of the game. */ SLOPE_FLAT = 0x00, //!< A flat tile - SLOPE_W = 0x01, //!< The west corner of the tile is raised - SLOPE_S = 0x02, //!< The south corner of the tile is raised - SLOPE_E = 0x04, //!< The east corner of the tile is raised - SLOPE_N = 0x08, //!< The north corner of the tile is raised - SLOPE_STEEP = 0x10, //!< Indicates the slope is steep + SLOPE_W = 1 << CORNER_W, //!< The west corner of the tile is raised + SLOPE_S = 1 << CORNER_S, //!< The south corner of the tile is raised + SLOPE_E = 1 << CORNER_E, //!< The east corner of the tile is raised + SLOPE_N = 1 << CORNER_N, //!< The north corner of the tile is raised + SLOPE_STEEP = 0x10, //!< Indicates the slope is steep (The corner opposite of the not-raised corner is raised two times) SLOPE_NW = SLOPE_N | SLOPE_W, //!< North and west corner are raised SLOPE_SW = SLOPE_S | SLOPE_W, //!< South and west corner are raised SLOPE_SE = SLOPE_S | SLOPE_E, //!< South and east corner are raised SLOPE_NE = SLOPE_N | SLOPE_E, //!< North and east corner are raised SLOPE_EW = SLOPE_E | SLOPE_W, //!< East and west corner are raised SLOPE_NS = SLOPE_N | SLOPE_S, //!< North and south corner are raised - SLOPE_ELEVATED = SLOPE_N | SLOPE_E | SLOPE_S | SLOPE_W, //!< All corner are raised, similar to SLOPE_FLAT + SLOPE_ELEVATED = SLOPE_N | SLOPE_E | SLOPE_S | SLOPE_W, //!< Bit mask containing all 'simple' slopes. Does not appear as a slope. SLOPE_NWS = SLOPE_N | SLOPE_W | SLOPE_S, //!< North, west and south corner are raised SLOPE_WSE = SLOPE_W | SLOPE_S | SLOPE_E, //!< West, south and east corner are raised SLOPE_SEN = SLOPE_S | SLOPE_E | SLOPE_N, //!< South, east and north corner are raised @@ -129,6 +147,7 @@ public: /** * Check if a tile has a steep slope. + * Steep slopes are slopes with a height difference of 2 across one diagonal of the tile. * @param slope The slope to check on. * @pre slope != SLOPE_INVALID. * @return True if the slope is a steep slope. @@ -137,9 +156,11 @@ public: /** * Check if a tile has a halftile slope. + * Halftile slopes appear on top of halftile foundations. E.g. the slope you get when building a horizontal railtrack on the top of a SLOPE_N or SLOPE_STEEP_N. * @param slope The slope to check on. * @pre slope != SLOPE_INVALID. * @return True if the slope is a halftile slope. + * @note Currently there is no API function that would return or accept a halftile slope. */ static bool IsHalftileSlope(Slope slope); @@ -193,9 +214,10 @@ public: /** * Get the slope of a tile. + * This is the slope of the bare tile. A possible foundation on the tile does not influence this slope. * @param tile The tile to check on. * @pre AIMap::IsValidTile(tile). - * @return 0 means flat, others indicate internal state of slope. + * @return Bit mask encoding the slope. See #Slope for a description of the returned values. */ static Slope GetSlope(TileIndex tile); @@ -211,13 +233,43 @@ public: static Slope GetComplementSlope(Slope slope); /** - * Get the height of the tile. + * Get the height of the north corner of a tile. + * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height. + * @deprecated This function is deprecated and might be removed in future versions of the API. Use GetMinHeight(), GetMaxHeight() or GetCornerHeight() instead. * @param tile The tile to check on. * @pre AIMap::IsValidTile(tile). - * @return The height of the tile, ranging from 0 to 15. + * @return The height of the north corner of the tile, ranging from 0 to 15. */ static int32 GetHeight(TileIndex tile); + /** + * Get the minimal height on a tile. + * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height. + * @param tile The tile to check on. + * @pre AIMap::IsValidTile(tile). + * @return The height of the lowest corner of the tile, ranging from 0 to 15. + */ + static int32 GetMinHeight(TileIndex tile); + + /** + * Get the maximal height on a tile. + * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height. + * @param tile The tile to check on. + * @pre AIMap::IsValidTile(tile). + * @return The height of the highest corner of the tile, ranging from 0 to 15. + */ + static int32 GetMaxHeight(TileIndex tile); + + /** + * Get the height of a certain corner of a tile. + * The returned height is the height of the bare tile. A possible foundation on the tile does not influence this height. + * @param tile The tile to check on. + * @param corner The corner to query. + * @pre AIMap::IsValidTile(tile). + * @return The height of the lowest corner of the tile, ranging from 0 to 15. + */ + static int32 GetCornerHeight(TileIndex tile, Corner corner); + /** * Get the owner of the tile. * @param tile The tile to get the owner from. diff --git a/src/ai/api/ai_tile.hpp.sq b/src/ai/api/ai_tile.hpp.sq index 50bd9523fe..4ae901cafc 100644 --- a/src/ai/api/ai_tile.hpp.sq +++ b/src/ai/api/ai_tile.hpp.sq @@ -7,6 +7,8 @@ namespace SQConvert { /* Allow enums to be used as Squirrel parameters */ template <> AITile::ErrorMessages GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::ErrorMessages)tmp; } template <> int Return(HSQUIRRELVM vm, AITile::ErrorMessages res) { sq_pushinteger(vm, (int32)res); return 1; } + template <> AITile::Corner GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::Corner)tmp; } + template <> int Return(HSQUIRRELVM vm, AITile::Corner res) { sq_pushinteger(vm, (int32)res); return 1; } template <> AITile::Slope GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::Slope)tmp; } template <> int Return(HSQUIRRELVM vm, AITile::Slope res) { sq_pushinteger(vm, (int32)res); return 1; } template <> AITile::TransportType GetParam(ForceType, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AITile::TransportType)tmp; } @@ -25,42 +27,53 @@ void SQAITile_Register(Squirrel *engine) { SQAITile.PreRegister(engine); SQAITile.AddConstructor(engine, "x"); - SQAITile.DefSQConst(engine, AITile::ERR_TILE_BASE, "ERR_TILE_BASE"); - SQAITile.DefSQConst(engine, AITile::ERR_TILE_TOO_HIGH, "ERR_TILE_TOO_HIGH"); - SQAITile.DefSQConst(engine, AITile::ERR_TILE_TOO_LOW, "ERR_TILE_TOO_LOW"); - SQAITile.DefSQConst(engine, AITile::SLOPE_FLAT, "SLOPE_FLAT"); - SQAITile.DefSQConst(engine, AITile::SLOPE_W, "SLOPE_W"); - SQAITile.DefSQConst(engine, AITile::SLOPE_S, "SLOPE_S"); - SQAITile.DefSQConst(engine, AITile::SLOPE_E, "SLOPE_E"); - SQAITile.DefSQConst(engine, AITile::SLOPE_N, "SLOPE_N"); - SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP, "SLOPE_STEEP"); - SQAITile.DefSQConst(engine, AITile::SLOPE_NW, "SLOPE_NW"); - SQAITile.DefSQConst(engine, AITile::SLOPE_SW, "SLOPE_SW"); - SQAITile.DefSQConst(engine, AITile::SLOPE_SE, "SLOPE_SE"); - SQAITile.DefSQConst(engine, AITile::SLOPE_NE, "SLOPE_NE"); - SQAITile.DefSQConst(engine, AITile::SLOPE_EW, "SLOPE_EW"); - SQAITile.DefSQConst(engine, AITile::SLOPE_NS, "SLOPE_NS"); - SQAITile.DefSQConst(engine, AITile::SLOPE_ELEVATED, "SLOPE_ELEVATED"); - SQAITile.DefSQConst(engine, AITile::SLOPE_NWS, "SLOPE_NWS"); - SQAITile.DefSQConst(engine, AITile::SLOPE_WSE, "SLOPE_WSE"); - SQAITile.DefSQConst(engine, AITile::SLOPE_SEN, "SLOPE_SEN"); - SQAITile.DefSQConst(engine, AITile::SLOPE_ENW, "SLOPE_ENW"); - SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_W, "SLOPE_STEEP_W"); - SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_S, "SLOPE_STEEP_S"); - SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_E, "SLOPE_STEEP_E"); - SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_N, "SLOPE_STEEP_N"); - SQAITile.DefSQConst(engine, AITile::SLOPE_INVALID, "SLOPE_INVALID"); - SQAITile.DefSQConst(engine, AITile::TRANSPORT_RAIL, "TRANSPORT_RAIL"); - SQAITile.DefSQConst(engine, AITile::TRANSPORT_ROAD, "TRANSPORT_ROAD"); - SQAITile.DefSQConst(engine, AITile::TRANSPORT_WATER, "TRANSPORT_WATER"); - SQAITile.DefSQConst(engine, AITile::TRANSPORT_AIR, "TRANSPORT_AIR"); - SQAITile.DefSQConst(engine, AITile::TRANSPORT_INVALID, "TRANSPORT_INVALID"); + SQAITile.DefSQConst(engine, AITile::ERR_TILE_BASE, "ERR_TILE_BASE"); + SQAITile.DefSQConst(engine, AITile::ERR_TILE_TOO_HIGH, "ERR_TILE_TOO_HIGH"); + SQAITile.DefSQConst(engine, AITile::ERR_TILE_TOO_LOW, "ERR_TILE_TOO_LOW"); + SQAITile.DefSQConst(engine, AITile::ERR_AREA_ALREADY_FLAT, "ERR_AREA_ALREADY_FLAT"); + SQAITile.DefSQConst(engine, AITile::ERR_EXCAVATION_WOULD_DAMAGE, "ERR_EXCAVATION_WOULD_DAMAGE"); + SQAITile.DefSQConst(engine, AITile::CORNER_W, "CORNER_W"); + SQAITile.DefSQConst(engine, AITile::CORNER_S, "CORNER_S"); + SQAITile.DefSQConst(engine, AITile::CORNER_E, "CORNER_E"); + SQAITile.DefSQConst(engine, AITile::CORNER_N, "CORNER_N"); + SQAITile.DefSQConst(engine, AITile::CORNER_INVALID, "CORNER_INVALID"); + SQAITile.DefSQConst(engine, AITile::SLOPE_FLAT, "SLOPE_FLAT"); + SQAITile.DefSQConst(engine, AITile::SLOPE_W, "SLOPE_W"); + SQAITile.DefSQConst(engine, AITile::SLOPE_S, "SLOPE_S"); + SQAITile.DefSQConst(engine, AITile::SLOPE_E, "SLOPE_E"); + SQAITile.DefSQConst(engine, AITile::SLOPE_N, "SLOPE_N"); + SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP, "SLOPE_STEEP"); + SQAITile.DefSQConst(engine, AITile::SLOPE_NW, "SLOPE_NW"); + SQAITile.DefSQConst(engine, AITile::SLOPE_SW, "SLOPE_SW"); + SQAITile.DefSQConst(engine, AITile::SLOPE_SE, "SLOPE_SE"); + SQAITile.DefSQConst(engine, AITile::SLOPE_NE, "SLOPE_NE"); + SQAITile.DefSQConst(engine, AITile::SLOPE_EW, "SLOPE_EW"); + SQAITile.DefSQConst(engine, AITile::SLOPE_NS, "SLOPE_NS"); + SQAITile.DefSQConst(engine, AITile::SLOPE_ELEVATED, "SLOPE_ELEVATED"); + SQAITile.DefSQConst(engine, AITile::SLOPE_NWS, "SLOPE_NWS"); + SQAITile.DefSQConst(engine, AITile::SLOPE_WSE, "SLOPE_WSE"); + SQAITile.DefSQConst(engine, AITile::SLOPE_SEN, "SLOPE_SEN"); + SQAITile.DefSQConst(engine, AITile::SLOPE_ENW, "SLOPE_ENW"); + SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_W, "SLOPE_STEEP_W"); + SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_S, "SLOPE_STEEP_S"); + SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_E, "SLOPE_STEEP_E"); + SQAITile.DefSQConst(engine, AITile::SLOPE_STEEP_N, "SLOPE_STEEP_N"); + SQAITile.DefSQConst(engine, AITile::SLOPE_INVALID, "SLOPE_INVALID"); + SQAITile.DefSQConst(engine, AITile::TRANSPORT_RAIL, "TRANSPORT_RAIL"); + SQAITile.DefSQConst(engine, AITile::TRANSPORT_ROAD, "TRANSPORT_ROAD"); + SQAITile.DefSQConst(engine, AITile::TRANSPORT_WATER, "TRANSPORT_WATER"); + SQAITile.DefSQConst(engine, AITile::TRANSPORT_AIR, "TRANSPORT_AIR"); + SQAITile.DefSQConst(engine, AITile::TRANSPORT_INVALID, "TRANSPORT_INVALID"); - AIError::RegisterErrorMap(STR_1003_ALREADY_AT_SEA_LEVEL, AITile::ERR_TILE_TOO_HIGH); - AIError::RegisterErrorMap(STR_1003_ALREADY_AT_SEA_LEVEL, AITile::ERR_TILE_TOO_LOW); + AIError::RegisterErrorMap(STR_1003_ALREADY_AT_SEA_LEVEL, AITile::ERR_TILE_TOO_HIGH); + AIError::RegisterErrorMap(STR_1003_ALREADY_AT_SEA_LEVEL, AITile::ERR_TILE_TOO_LOW); + AIError::RegisterErrorMap(STR_ALREADY_LEVELLED, AITile::ERR_AREA_ALREADY_FLAT); + AIError::RegisterErrorMap(STR_1002_EXCAVATION_WOULD_DAMAGE, AITile::ERR_EXCAVATION_WOULD_DAMAGE); - AIError::RegisterErrorMapString(AITile::ERR_TILE_TOO_HIGH, "ERR_TILE_TOO_HIGH"); - AIError::RegisterErrorMapString(AITile::ERR_TILE_TOO_LOW, "ERR_TILE_TOO_LOW"); + AIError::RegisterErrorMapString(AITile::ERR_TILE_TOO_HIGH, "ERR_TILE_TOO_HIGH"); + AIError::RegisterErrorMapString(AITile::ERR_TILE_TOO_LOW, "ERR_TILE_TOO_LOW"); + AIError::RegisterErrorMapString(AITile::ERR_AREA_ALREADY_FLAT, "ERR_AREA_ALREADY_FLAT"); + AIError::RegisterErrorMapString(AITile::ERR_EXCAVATION_WOULD_DAMAGE, "ERR_EXCAVATION_WOULD_DAMAGE"); SQAITile.DefSQStaticMethod(engine, &AITile::IsBuildable, "IsBuildable", 2, ".i"); SQAITile.DefSQStaticMethod(engine, &AITile::IsBuildableRectangle, "IsBuildableRectangle", 4, ".iii"); @@ -78,6 +91,9 @@ void SQAITile_Register(Squirrel *engine) { SQAITile.DefSQStaticMethod(engine, &AITile::GetSlope, "GetSlope", 2, ".i"); SQAITile.DefSQStaticMethod(engine, &AITile::GetComplementSlope, "GetComplementSlope", 2, ".i"); SQAITile.DefSQStaticMethod(engine, &AITile::GetHeight, "GetHeight", 2, ".i"); + SQAITile.DefSQStaticMethod(engine, &AITile::GetMinHeight, "GetMinHeight", 2, ".i"); + SQAITile.DefSQStaticMethod(engine, &AITile::GetMaxHeight, "GetMaxHeight", 2, ".i"); + SQAITile.DefSQStaticMethod(engine, &AITile::GetCornerHeight, "GetCornerHeight", 3, ".ii"); SQAITile.DefSQStaticMethod(engine, &AITile::GetOwner, "GetOwner", 2, ".i"); SQAITile.DefSQStaticMethod(engine, &AITile::HasTransportType, "HasTransportType", 3, ".ii"); SQAITile.DefSQStaticMethod(engine, &AITile::GetCargoAcceptance, "GetCargoAcceptance", 6, ".iiiii"); diff --git a/src/ai/api/ai_vehicle.cpp b/src/ai/api/ai_vehicle.cpp index d0f62136f3..130ebe05ef 100644 --- a/src/ai/api/ai_vehicle.cpp +++ b/src/ai/api/ai_vehicle.cpp @@ -160,6 +160,13 @@ return AIObject::DoCommand(0, vehicle_id, 0, GetCmdSendToDepot(::GetVehicle(vehicle_id))); } +/* static */ bool AIVehicle::SendVehicleToDepotForServicing(VehicleID vehicle_id) +{ + EnforcePrecondition(false, IsValidVehicle(vehicle_id)); + + return AIObject::DoCommand(0, vehicle_id, DEPOT_SERVICE, GetCmdSendToDepot(::GetVehicle(vehicle_id))); +} + /* static */ bool AIVehicle::IsInDepot(VehicleID vehicle_id) { if (!IsValidVehicle(vehicle_id)) return false; diff --git a/src/ai/api/ai_vehicle.hpp b/src/ai/api/ai_vehicle.hpp index 43c993637d..ce73047878 100644 --- a/src/ai/api/ai_vehicle.hpp +++ b/src/ai/api/ai_vehicle.hpp @@ -422,14 +422,25 @@ public: static bool SellWagonChain(VehicleID vehicle_id, int wagon); /** - * Sends the given vehicle to a depot. + * Sends the given vehicle to a depot. If the vehicle has already been + * sent to a depot it continues with its normal orders instead. * @param vehicle_id The vehicle to send to a depot. * @pre IsValidVehicle(vehicle_id). * @exception AIVehicle::ERR_VEHICLE_CANNOT_SEND_TO_DEPOT - * @return True if and only if the vehicle has been sent to a depot. + * @return True if the current order was changed. */ static bool SendVehicleToDepot(VehicleID vehicle_id); + /** + * Sends the given vehicle to a depot for servicing. If the vehicle has + * already been sent to a depot it continues with its normal orders instead. + * @param vehicle_id The vehicle to send to a depot for servicing. + * @pre IsValidVehicle(vehicle_id). + * @exception AIVehicle::ERR_VEHICLE_CANNOT_SEND_TO_DEPOT + * @return True if the current order was changed. + */ + static bool SendVehicleToDepotForServicing(VehicleID vehicle_id); + /** * Starts or stops the given vehicle depending on the current state. * @param vehicle_id The vehicle to start/stop. diff --git a/src/ai/api/ai_vehicle.hpp.sq b/src/ai/api/ai_vehicle.hpp.sq index 797d134043..b56f6482f4 100644 --- a/src/ai/api/ai_vehicle.hpp.sq +++ b/src/ai/api/ai_vehicle.hpp.sq @@ -98,47 +98,48 @@ void SQAIVehicle_Register(Squirrel *engine) { AIError::RegisterErrorMapString(AIVehicle::ERR_VEHICLE_IN_FLIGHT, "ERR_VEHICLE_IN_FLIGHT"); AIError::RegisterErrorMapString(AIVehicle::ERR_VEHCILE_NO_POWER, "ERR_VEHCILE_NO_POWER"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsValidVehicle, "IsValidVehicle", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetNumWagons, "GetNumWagons", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SetName, "SetName", 3, ".is"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetName, "GetName", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetLocation, "GetLocation", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetEngineType, "GetEngineType", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetWagonEngineType, "GetWagonEngineType", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetUnitNumber, "GetUnitNumber", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetAge, "GetAge", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetWagonAge, "GetWagonAge", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetMaxAge, "GetMaxAge", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetAgeLeft, "GetAgeLeft", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCurrentSpeed, "GetCurrentSpeed", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetState, "GetState", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRunningCost, "GetRunningCost", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetProfitThisYear, "GetProfitThisYear", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetProfitLastYear, "GetProfitLastYear", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCurrentValue, "GetCurrentValue", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetVehicleType, "GetVehicleType", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRoadType, "GetRoadType", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsInDepot, "IsInDepot", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsStoppedInDepot, "IsStoppedInDepot", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::BuildVehicle, "BuildVehicle", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::CloneVehicle, "CloneVehicle", 4, ".iib"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::MoveWagon, "MoveWagon", 5, ".iiii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::MoveWagonChain, "MoveWagonChain", 5, ".iiii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRefitCapacity, "GetRefitCapacity", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::RefitVehicle, "RefitVehicle", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellVehicle, "SellVehicle", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellWagon, "SellWagon", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellWagonChain, "SellWagonChain", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SendVehicleToDepot, "SendVehicleToDepot", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::StartStopVehicle, "StartStopVehicle", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SkipToVehicleOrder, "SkipToVehicleOrder", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::ReverseVehicle, "ReverseVehicle", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCapacity, "GetCapacity", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetLength, "GetLength", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCargoLoad, "GetCargoLoad", 3, ".ii"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetGroupID, "GetGroupID", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsArticulated, "IsArticulated", 2, ".i"); - SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::HasSharedOrders, "HasSharedOrders", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsValidVehicle, "IsValidVehicle", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetNumWagons, "GetNumWagons", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SetName, "SetName", 3, ".is"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetName, "GetName", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetLocation, "GetLocation", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetEngineType, "GetEngineType", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetWagonEngineType, "GetWagonEngineType", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetUnitNumber, "GetUnitNumber", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetAge, "GetAge", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetWagonAge, "GetWagonAge", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetMaxAge, "GetMaxAge", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetAgeLeft, "GetAgeLeft", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCurrentSpeed, "GetCurrentSpeed", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetState, "GetState", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRunningCost, "GetRunningCost", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetProfitThisYear, "GetProfitThisYear", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetProfitLastYear, "GetProfitLastYear", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCurrentValue, "GetCurrentValue", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetVehicleType, "GetVehicleType", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRoadType, "GetRoadType", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsInDepot, "IsInDepot", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsStoppedInDepot, "IsStoppedInDepot", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::BuildVehicle, "BuildVehicle", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::CloneVehicle, "CloneVehicle", 4, ".iib"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::MoveWagon, "MoveWagon", 5, ".iiii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::MoveWagonChain, "MoveWagonChain", 5, ".iiii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetRefitCapacity, "GetRefitCapacity", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::RefitVehicle, "RefitVehicle", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellVehicle, "SellVehicle", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellWagon, "SellWagon", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SellWagonChain, "SellWagonChain", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SendVehicleToDepot, "SendVehicleToDepot", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SendVehicleToDepotForServicing, "SendVehicleToDepotForServicing", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::StartStopVehicle, "StartStopVehicle", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::SkipToVehicleOrder, "SkipToVehicleOrder", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::ReverseVehicle, "ReverseVehicle", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCapacity, "GetCapacity", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetLength, "GetLength", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetCargoLoad, "GetCargoLoad", 3, ".ii"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::GetGroupID, "GetGroupID", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::IsArticulated, "IsArticulated", 2, ".i"); + SQAIVehicle.DefSQStaticMethod(engine, &AIVehicle::HasSharedOrders, "HasSharedOrders", 2, ".i"); SQAIVehicle.PostRegister(engine); } diff --git a/src/ai/api/ai_waypoint.hpp b/src/ai/api/ai_waypoint.hpp index 69eacb10e6..9e1bec9110 100644 --- a/src/ai/api/ai_waypoint.hpp +++ b/src/ai/api/ai_waypoint.hpp @@ -16,7 +16,7 @@ public: static const char *GetClassName() { return "AIWaypoint"; } enum SpecialWaypointIDs { - WAYPOINT_INVALID = -1, //!< An invalid WaypointID. + WAYPOINT_INVALID = 0xFFFF, //!< An invalid WaypointID. }; /** diff --git a/src/slope_type.h b/src/slope_type.h index 2ba12bf383..469fd75b98 100644 --- a/src/slope_type.h +++ b/src/slope_type.h @@ -53,7 +53,7 @@ enum Slope { SLOPE_NE = SLOPE_N | SLOPE_E, ///< north and east corner are raised SLOPE_EW = SLOPE_E | SLOPE_W, ///< east and west corner are raised SLOPE_NS = SLOPE_N | SLOPE_S, ///< north and south corner are raised - SLOPE_ELEVATED = SLOPE_N | SLOPE_E | SLOPE_S | SLOPE_W, ///< all corner are raised, similar to SLOPE_FLAT + SLOPE_ELEVATED = SLOPE_N | SLOPE_E | SLOPE_S | SLOPE_W, ///< bit mask containing all 'simple' slopes SLOPE_NWS = SLOPE_N | SLOPE_W | SLOPE_S, ///< north, west and south corner are raised SLOPE_WSE = SLOPE_W | SLOPE_S | SLOPE_E, ///< west, south and east corner are raised SLOPE_SEN = SLOPE_S | SLOPE_E | SLOPE_N, ///< south, east and north corner are raised