From fda061d8c89696b847c920574c5a3853e514580a Mon Sep 17 00:00:00 2001 From: funkyfranky <> Date: Tue, 10 Jul 2018 23:47:12 +0200 Subject: [PATCH 1/5] Improved GroundOnRoad functions --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 6 +- Moose Development/Moose/Core/Point.lua | 52 +++++++++++---- .../Moose/Wrapper/Controllable.lua | 63 ++++++++++++++----- 3 files changed, 89 insertions(+), 32 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index a2d086683..7f4f34a3e 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -604,7 +604,7 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate ) if Coordinate then self.RoutePickup = true - local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" ) + local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast", true ) local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self ) @@ -635,7 +635,7 @@ function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate ) self.RouteDeploy = true - local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" ) + local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast", true ) local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self ) @@ -661,7 +661,7 @@ function AI_CARGO_APC:onafterHome( APC, From, Event, To, Coordinate ) self.RouteHome = true - local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast" ) + local Waypoints = APC:TaskGroundOnRoad( Coordinate, APC:GetSpeedMax()*0.5, "Line abreast", true ) self:F({Waypoints = Waypoints}) local Waypoint = Waypoints[#Waypoints] diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 97bc09215..3b88ab74b 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -1184,29 +1184,55 @@ do -- COORDINATE end --- Returns a table of coordinates to a destination using only roads. - -- The first point is the closest point on road of the given coordinate. The last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path. + -- The first point is the closest point on road of the given coordinate. + -- By default, the last point is the closest point on road of the ToCoord. Hence, the coordinate itself and the final ToCoord are not necessarily included in the path. -- @param #COORDINATE self -- @param #COORDINATE ToCoord Coordinate of destination. - -- @return #table Table of coordinates on road. If no path on road can be found, nil is returned. - function COORDINATE:GetPathOnRoad(ToCoord) + -- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path. + -- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints. + -- @return #number The length of the total path. + function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints) -- DCS API function returning a table of vec2. local path = land.findPathOnRoads("roads", self.x, self.z, ToCoord.x, ToCoord.z) + -- Array holding the path coordinates. local Path={} + local Way=0 - if path then - --Path[#Path+1]=self - for i, v in ipairs(path) do - Path[#Path+1]=COORDINATE:NewFromVec2(v) - end - --Path[#Path+1]=ToCoord - else - -- There are cases where no path on road can be found. - return nil + -- Include currrent position. + if IncludeEndpoints then + Path[1]=self end - return Path + -- Check that DCS routine actually returned a path. There are situations where this is not the case. + if path then + + -- Include all points on road. + for _,_vec2 in ipairs(path) do + Path[#Path+1]=COORDINATE:NewFromVec2(_vec2) + end + + else + self:E("Path is nil. No valid path on road could be found.") + end + + -- Include end point, which might not be on road. + if IncludeEndpoints then + Path[#Path+1]=ToCoord + end + + -- Sum up distances. + if #Path>=2 then + for i=1,#Path-1 do + Way=Way+Path[i+1]:Get2DDistance(Path[i]) + end + else + -- There are cases where no path on road can be found. + return nil,nil + end + + return Path, Way end --- Gets the surface type at the coordinate. diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 3199393b4..eef142020 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1990,8 +1990,9 @@ do -- Route methods -- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. -- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road". + -- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer. -- @return Task - function CONTROLLABLE:TaskGroundOnRoad( ToCoordinate, Speed, OffRoadFormation ) + function CONTROLLABLE:TaskGroundOnRoad( ToCoordinate, Speed, OffRoadFormation, Shortcut ) self:F2({ToCoordinate=ToCoordinate, Speed=Speed, OffRoadFormation=OffRoadFormation}) -- Defaults. @@ -2001,26 +2002,56 @@ do -- Route methods -- Current coordinate. local FromCoordinate = self:GetCoordinate() - -- First point on road. - local FromOnRoad = FromCoordinate:GetClosestPointToRoad() + -- Get path and path length on road including the end points (From and To). + local PathOnRoad, LengthOnRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, true) + + -- Calculate the direct distance between the initial and final points. + local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate) + + env.info(string.format("FF length on road = %.1f", LengthOnRoad/1000)) + env.info(string.format("FF length directly = %.1f", LengthDirect/1000)) + env.info(string.format("FF length fraction = %.1f", LengthOnRoad/LengthDirect)) - -- Last Point on road. - local ToOnRoad = ToCoordinate:GetClosestPointToRoad() - -- Route, ground waypoints along road. local route={} - -- Create waypoints. - table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) - table.insert(route, FromOnRoad:WaypointGround(Speed, "On Road")) - table.insert(route, ToOnRoad:WaypointGround(Speed, "On Road")) - - -- Add the final coordinate because the final might not be on the road. - local dist=ToCoordinate:Get2DDistance(ToOnRoad) - if dist>10 then - table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) - end + -- Length on road is 10 times longer than direct route. + local LongRoad=LengthOnRoad and (LengthOnRoad > LengthDirect*10) + -- Check if a valid path on road could be found. + if PathOnRoad then + + -- Check whether the road is very long compared to direct path. + if LongRoad and Shortcut then + env.info(string.format("FF longroad and shortcut")) + -- Road is long ==> we take the short cut. + table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) + table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) + + else + env.info(string.format("FF longroad and shortcut else")) + -- Create waypoints. + table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) + table.insert(route, PathOnRoad[2]:WaypointGround(Speed, "On Road")) + table.insert(route, PathOnRoad[#PathOnRoad-1]:WaypointGround(Speed, "On Road")) + + -- Add the final coordinate because the final might not be on the road. + local dist=ToCoordinate:Get2DDistance(PathOnRoad[#PathOnRoad-1]) + if dist>10 then + env.info(string.format("FF longroad and shortcut else dist>10")) + table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) + end + + end + + else + + -- No path on road could be found (can happen!) ==> Route group directly from A to B. + table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) + table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) + + end + return route end From 258e3d29213f850078742fe2cf776fafc2662da0 Mon Sep 17 00:00:00 2001 From: funkyfranky <> Date: Wed, 11 Jul 2018 23:27:44 +0200 Subject: [PATCH 2/5] CARGO_GROUP - Fixed issue that units are spawned on top of each other on unboarding. --- Moose Development/Moose/Cargo/CargoGroup.lua | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index de8b08e6d..69787e721 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -364,9 +364,11 @@ do -- CARGO_GROUP -- @param #string From -- @param #string To function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - --self:F( {From, Event, To, ToPointVec2, NearRadius } ) + self:F( {From, Event, To, ToPointVec2, NearRadius } ) NearRadius = NearRadius or 25 + + env.info("FF onenterunboarding") local Timer = 1 @@ -381,7 +383,14 @@ do -- CARGO_GROUP --- @param Cargo.Cargo#CARGO Cargo function( Cargo, NearRadius ) if not Cargo:IsDestroyed() then - Cargo:__UnBoard( Timer, ToPointVec2, NearRadius ) + env.info("FF blubblub") + local ToVec=nil + if ToPointVec2==nil then + ToVec=self.CargoCarrier:GetPointVec2():GetRandomPointVec2InRadius(2*NearRadius, NearRadius) + else + ToVec=ToPointVec2 + end + Cargo:__UnBoard( Timer, ToVec, NearRadius ) Timer = Timer + 3 end end, { NearRadius } From 72343bce2913885f6dfa5b8e1fced782b2e445a5 Mon Sep 17 00:00:00 2001 From: funkyfranky <> Date: Thu, 12 Jul 2018 23:23:00 +0200 Subject: [PATCH 3/5] Improved TaskOnRoad logic - direct route if path length on route is less than 5% --- Moose Development/Moose/Core/Point.lua | 1 + .../Moose/Wrapper/Controllable.lua | 23 +++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 3b88ab74b..e3c478b14 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -1211,6 +1211,7 @@ do -- COORDINATE -- Include all points on road. for _,_vec2 in ipairs(path) do Path[#Path+1]=COORDINATE:NewFromVec2(_vec2) + --COORDINATE:NewFromVec2(_vec2):SmokeGreen() end else diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index eef142020..8db384482 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1990,7 +1990,7 @@ do -- Route methods -- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. -- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road". - -- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer. + -- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer or path on road is less than 5% of total path. -- @return Task function CONTROLLABLE:TaskGroundOnRoad( ToCoordinate, Speed, OffRoadFormation, Shortcut ) self:F2({ToCoordinate=ToCoordinate, Speed=Speed, OffRoadFormation=OffRoadFormation}) @@ -2005,18 +2005,27 @@ do -- Route methods -- Get path and path length on road including the end points (From and To). local PathOnRoad, LengthOnRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, true) + -- Get the length only(!) on the road. + local _,LengthRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, false) + + -- Off road part of the rout: Total=OffRoad+OnRoad. + local LengthOffRoad=LengthOnRoad-LengthRoad + -- Calculate the direct distance between the initial and final points. local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate) - env.info(string.format("FF length on road = %.1f", LengthOnRoad/1000)) - env.info(string.format("FF length directly = %.1f", LengthDirect/1000)) - env.info(string.format("FF length fraction = %.1f", LengthOnRoad/LengthDirect)) + env.info(string.format("FF length on road = %.1f km", LengthOnRoad/1000)) + env.info(string.format("FF length directly = %.1f km", LengthDirect/1000)) + env.info(string.format("FF length fraction = %.1f km", LengthOnRoad/LengthDirect)) + env.info(string.format("FF length only road = %.1f km", LengthRoad/1000)) + env.info(string.format("FF length off road = %.1f km", LengthOffRoad/1000)) + env.info(string.format("FF percent on road = %.1f", LengthRoad/LengthOnRoad*100)) -- Route, ground waypoints along road. local route={} - - -- Length on road is 10 times longer than direct route. - local LongRoad=LengthOnRoad and (LengthOnRoad > LengthDirect*10) + + -- Length on road is 10 times longer than direct route or path on road is very short (<5% of total path). + local LongRoad=LengthOnRoad and ((LengthOnRoad > LengthDirect*10) or (LengthRoad/LengthOnRoad*100<5)) -- Check if a valid path on road could be found. if PathOnRoad then From c60bb29303b8e361d9a0849e027736c329c9ec0e Mon Sep 17 00:00:00 2001 From: funkyfranky <> Date: Tue, 17 Jul 2018 22:19:25 +0200 Subject: [PATCH 4/5] Minor fixes Task_A2G: fixt GetAlt() AI_Formation: fixed comma in equation --- Moose Development/Moose/AI/AI_Formation.lua | 2 +- Moose Development/Moose/Tasking/Task_A2G.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Formation.lua b/Moose Development/Moose/AI/AI_Formation.lua index af5805bb4..8be01bd23 100644 --- a/Moose Development/Moose/AI/AI_Formation.lua +++ b/Moose Development/Moose/AI/AI_Formation.lua @@ -968,7 +968,7 @@ function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1 local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T local Position = math.cos( Alpha_R ) local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5 - local Distance = GD * Position + - CS * 0,5 + local Distance = GD * Position + - CS * 0.5 -- Calculate the group direction vector local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z } diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index 637f1fdc4..634234654 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -148,7 +148,7 @@ do -- TASK_A2G local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT if TargetUnit then local Coordinate = TargetUnit:GetPointVec3() - self:T( { TargetCoordinate = Coordinate, Coordinate:GetX(), Coordinate:GetAlt(), Coordinate:GetZ() } ) + self:T( { TargetCoordinate = Coordinate, Coordinate:GetX(), Coordinate:GetY(), Coordinate:GetZ() } ) Task:SetTargetCoordinate( Coordinate, TaskUnit ) end self:__RouteToTargetPoint( 0.1 ) From 6aa30f91e6ff5b7b8f29471c23bbfdadd1b01931 Mon Sep 17 00:00:00 2001 From: funkyfranky <> Date: Wed, 18 Jul 2018 17:41:21 +0200 Subject: [PATCH 5/5] Debug output --- Moose Development/Moose/Cargo/CargoGroup.lua | 3 --- .../Moose/Wrapper/Controllable.lua | 18 +++++++++--------- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index 69787e721..3fa26e9ab 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -367,8 +367,6 @@ do -- CARGO_GROUP self:F( {From, Event, To, ToPointVec2, NearRadius } ) NearRadius = NearRadius or 25 - - env.info("FF onenterunboarding") local Timer = 1 @@ -383,7 +381,6 @@ do -- CARGO_GROUP --- @param Cargo.Cargo#CARGO Cargo function( Cargo, NearRadius ) if not Cargo:IsDestroyed() then - env.info("FF blubblub") local ToVec=nil if ToPointVec2==nil then ToVec=self.CargoCarrier:GetPointVec2():GetRandomPointVec2InRadius(2*NearRadius, NearRadius) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 8db384482..df8767019 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -2014,12 +2014,13 @@ do -- Route methods -- Calculate the direct distance between the initial and final points. local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate) - env.info(string.format("FF length on road = %.1f km", LengthOnRoad/1000)) - env.info(string.format("FF length directly = %.1f km", LengthDirect/1000)) - env.info(string.format("FF length fraction = %.1f km", LengthOnRoad/LengthDirect)) - env.info(string.format("FF length only road = %.1f km", LengthRoad/1000)) - env.info(string.format("FF length off road = %.1f km", LengthOffRoad/1000)) - env.info(string.format("FF percent on road = %.1f", LengthRoad/LengthOnRoad*100)) + -- Debug info. + self:T(string.format("Length on road = %.3f km", LengthOnRoad/1000)) + self:T(string.format("Length directly = %.3f km", LengthDirect/1000)) + self:T(string.format("Length fraction = %.3f km", LengthOnRoad/LengthDirect)) + self:T(string.format("Length only road = %.3f km", LengthRoad/1000)) + self:T(string.format("Length off road = %.3f km", LengthOffRoad/1000)) + self:T(string.format("Percent on road = %.1f", LengthRoad/LengthOnRoad*100)) -- Route, ground waypoints along road. local route={} @@ -2032,13 +2033,13 @@ do -- Route methods -- Check whether the road is very long compared to direct path. if LongRoad and Shortcut then - env.info(string.format("FF longroad and shortcut")) + -- Road is long ==> we take the short cut. table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) else - env.info(string.format("FF longroad and shortcut else")) + -- Create waypoints. table.insert(route, FromCoordinate:WaypointGround(Speed, OffRoadFormation)) table.insert(route, PathOnRoad[2]:WaypointGround(Speed, "On Road")) @@ -2047,7 +2048,6 @@ do -- Route methods -- Add the final coordinate because the final might not be on the road. local dist=ToCoordinate:Get2DDistance(PathOnRoad[#PathOnRoad-1]) if dist>10 then - env.info(string.format("FF longroad and shortcut else dist>10")) table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) end