Progressing on the Escort positioning system.

This commit is contained in:
FlightControl
2016-03-31 10:07:59 +02:00
parent 6834a5f6ea
commit d4719be695
23 changed files with 11540 additions and 27 deletions

View File

@@ -14,9 +14,9 @@ local _TraceClass = {
--SPAWN = true,
--STAGE = true,
--ZONE = true,
GROUP = true,
--GROUP = true,
--UNIT = true,
CLIENT = true,
--CLIENT = true,
--CARGO = true,
--CARGO_GROUP = true,
--CARGO_PACKAGE = true,

View File

@@ -65,9 +65,48 @@ function CLIENT:Reset( ClientName )
self._Menus = {}
end
--- Checks for a client alive event and calls a function on a continuous basis.
-- @param #CLIENT self
-- @param #function CallBack Function.
function CLIENT:Alive( CallBack )
self:F()
self.ClientAlive = false
self.ClientCallBack = CallBack
self.AliveCheckFunction = routines.scheduleFunction( self._AliveCheckCallBack, { self }, timer.getTime() + 1, 1 )
end
--- Checks if client is alive and returns true or false.
-- @param #CLIENT self
-- @param #boolean Returns true if client is alive.
function CLIENT:IsAlive()
self:F()
local ClientDCSGroup = self:GetDCSGroup()
if ClientDCSGroup then
return true
end
return false
end
--- @param #CLIENT self
function CLIENT:_AliveCheckCallBack()
if self:IsAlive() then
if self.ClientAlive == false then
self.ClientCallBack( self )
self.ClientAlive = true
routines.removeFunction( self.AliveCheckFunction )
end
end
end
--- Return the DCSGroup of a Client.
-- This function is modified to deal with a couple of bugs in DCS 1.5.3
-- @return Group#Group
-- @return DCSGroup#Group
function CLIENT:GetDCSGroup()
self:F3()

View File

@@ -23,17 +23,20 @@ Include.File( "Zone" )
-- @field Client#CLIENT EscortClient
-- @field Group#GROUP EscortGroup
-- @field #string EscortName
-- @field #number FollowScheduler The id of the _FollowScheduler function.
ESCORT = {
ClassName = "ESCORT",
EscortName = nil, -- The Escort Name
EscortClient = nil,
EscortGroup = nil,
Targets = {}, -- The identified targets
FollowScheduler = nil,
}
--- MENUPARAM type
-- @type MENUPARAM
-- @field #ESCORT ParamSelf
-- @field #Distance ParamDistance
--- ESCORT class constructor for an AI group
-- @param self
@@ -56,7 +59,10 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName )
self.EscortMenuReportNavigation = MENU_CLIENT:New( self.EscortClient, "Navigation", self.EscortMenu )
self.EscortMenuHoldPosition = MENU_CLIENT_COMMAND:New( self.EscortClient, "Hold Position and Stay Low", self.EscortMenuReportNavigation, ESCORT._HoldPosition, { ParamSelf = self } )
self.EscortMenuJoinUpAndHoldPosition = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Hold Position NearBy", self.EscortMenuReportNavigation, ESCORT._HoldPositionNearBy, { ParamSelf = self } )
self.EscortMenuJoinUpAndFollow = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow", self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self } )
self.EscortMenuJoinUpAndFollow50Meters = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at 100", self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = 100 } )
self.EscortMenuJoinUpAndFollow100Meters = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at 200", self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = 200 } )
self.EscortMenuJoinUpAndFollow150Meters = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at 400", self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = 400 } )
self.EscortMenuJoinUpAndFollow200Meters = MENU_CLIENT_COMMAND:New( self.EscortClient, "Join-Up and Follow at 800", self.EscortMenuReportNavigation, ESCORT._JoinUpAndFollow, { ParamSelf = self, ParamDistance = 800 } )
-- Report Targets
self.EscortMenuReportNearbyTargets = MENU_CLIENT:New( self.EscortClient, "Report targets", self.EscortMenu )
@@ -91,7 +97,7 @@ function ESCORT:New( EscortClient, EscortGroup, EscortName )
self.EscortMenuCancelTask = MENU_CLIENT_COMMAND:New( self.EscortClient, "Cancel current task", self.EscortMenu, ESCORT._CancelCurrentTask, { ParamSelf = self, } )
self.ScanForTargetsFunction = routines.scheduleFunction( self._ScanForTargets, { self }, timer.getTime() + 1, 30 )
self.ScanForTargetsScheduler = routines.scheduleFunction( self._ScanForTargets, { self }, timer.getTime() + 1, 30 )
end
@@ -147,10 +153,16 @@ function ESCORT._JoinUpAndFollow( MenuParam )
local EscortGroup = MenuParam.ParamSelf.EscortGroup
local EscortClient = MenuParam.ParamSelf.EscortClient
local Distance = MenuParam.ParamDistance
if self.FollowScheduler then
routines.removeFunction( self.FollowScheduler )
end
self.CT1 = 0
self.GT1 = 0
self.FollowFunction = routines.scheduleFunction( self._Follower, { self }, timer.getTime() + 1, 1 )
EscortGroup:MessageToClient( "Rejoining and following orders ...", 10, EscortClient )
self.FollowScheduler = routines.scheduleFunction( self._FollowScheduler, { self, Distance }, timer.getTime() + 1, 1 )
EscortGroup:MessageToClient( "Rejoining and Following at " .. Distance .. "!", 30, EscortClient )
end
@@ -297,58 +309,79 @@ function ESCORT._CancelCurrentTask( MenuParam )
end
--- @param Escort#ESCORT self
function ESCORT:_Follower()
self:F()
function ESCORT:_FollowScheduler( FollowDistance )
self:F( { FollowDistance })
local ClientUnit = self.EscortClient:GetClientGroupUnit()
local GroupUnit = self.EscortGroup:GetUnit( 1 )
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
local ClientUnit = self.EscortClient:GetClientGroupUnit()
local GroupUnit = self.EscortGroup:GetUnit( 1 )
if self.EscortGroup:IsAlive() and ClientUnit:IsAlive() then
if self.CT1 == 0 and self.GT1 == 0 then
self.CV1 = ClientUnit:GetPositionVec3()
self.CT1 = timer.getTime()
self.GV1 = GroupUnit:GetPositionVec3()
self.GT1 = timer.getTime()
else
local CT1 = self.CT1
local CT2 = timer.getTime()
local CV1 = self.CV1
local CV2 = ClientUnit:GetPositionVec3()
self.CT1 = CT2
self.CV1 = CV2
local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5
local CT = CT2 - CT1
local CS = ( 3600 / CT ) * ( CD / 1000 )
self:T( { "Client:", CS, CD, CT, CV2, CV1, CT2, CT1 } )
self:T2( { "Client:", CS, CD, CT, CV2, CV1, CT2, CT1 } )
local GT1 = self.GT1
local GT2 = timer.getTime()
local GV1 = self.GV1
local GV2 = GroupUnit:GetPositionVec3()
self.GT1 = GT2
self.GV1 = GV2
local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5
local GT = GT2 - GT1
local GS = ( 3600 / GT ) * ( GD / 1000 )
self:T( { "Group:", GS, GD, GT, GV2, GV1, GT2, GT1 } )
self:T2( { "Group:", GS, GD, GT, GV2, GV1, GT2, GT1 } )
-- Measure distance between client and group
local D = ( ( CV2.x - GV2.x )^2 + ( CV2.y - GV2.y )^2 + ( CV2.z - GV2.z )^2 ) ^ 0.5 - 200
local CatchUpDistance = ( ( CV2.x - GV2.x )^2 + ( CV2.y - GV2.y )^2 + ( CV2.z - GV2.z )^2 ) ^ 0.5
local Distance = CatchUpDistance - FollowDistance
local S = ( 3600 / 30 ) * ( D / 1000 ) -- We use a 2 second buffer to adjust the speed
local A = ( CS - GS ) + S -- Accelleration required = Client Speed - Group Speed + Speed to overcome distance (with 10 second time buffer)
local Speed = A -- Final speed is the current Group speed + Accelleration
-- The calculation of the Speed would simulate that the group would take 30 seconds to overcome
-- the requested Distance).
local Time = 1600 / FollowDistance
local CatchUpSpeed = ( Distance / Time ) * ( CatchUpDistance / 1000 )
self:T( { "Speed:", S, A, Speed } )
-- Follow speed required = Client Speed - Group Speed + Speed to overcome distance.
local BreakSpeed = ( GS * ( ( 1 ) / Distance ) )
if BreakSpeed < 0 then
BreakSpeed = 0
end
if BreakSpeed > CS then
BreakSpeed = CS
end
local Speed = CS + CatchUpSpeed --- - BreakSpeed
if Speed < 0 then
Speed = 0
end
self:T( { "Client Speed, Client Time, Escort Speed, Speed, CatchUpSpeed, BreakSpeed, Distance, Time:", CS, CT, GS, Speed, CatchUpSpeed, BreakSpeed, Distance, Time } )
-- Now route the escort to the desired point with the desired speed.
self.EscortGroup:TaskRouteToVec3( CV2, Speed )
self.EscortGroup:TaskRouteToVec3( CV2, Speed / 3.6 ) -- DCS models speed in Mps (Miles per second)
end
else
routines.removeFunction( self.FollowFunction )
routines.removeFunction( self.FollowScheduler )
end
end
@@ -462,6 +495,6 @@ function ESCORT:_ScanForTargets()
end
else
routines.removeFunction( self.ScanForTargetsFunction )
routines.removeFunction( self.ScanForTargetsScheduler )
end
end

View File

@@ -592,6 +592,7 @@ function GROUP:TaskRouteToVec3( Point, Speed )
PointTo.alt = Point.y
PointTo.type = "Turning Point"
PointTo.speed = Speed
PointTo.speed_locked = true
local Points = { PointFrom, PointTo }

View File

@@ -102,6 +102,7 @@ function MENU_CLIENT:New( MenuClient, MenuText, ParentMenu )
end
local self = BASE:Inherit( self, MENU:New( MenuText, MenuParentPath ) )
self:F( { MenuClient, MenuText, ParentMenu } )
self.MenuClient = MenuClient
self.MenuClientGroupID = MenuClient:GetClientGroupID()