CONTROLLABLE:PatrolRouteRandom fix for Subs (#1536)

* CONTROLLABLE:PatrolRouteRandom fix for Subs

fixes issue #1535

* Update Controllable.lua

* Update Controllable.lua
This commit is contained in:
Applevangelist 2021-05-21 12:35:32 +02:00 committed by GitHub
parent 41b01a508d
commit 47d814e409
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -175,11 +175,8 @@
-- * @{#CONTROLLABLE.OptionKeepWeaponsOnThreat} -- * @{#CONTROLLABLE.OptionKeepWeaponsOnThreat}
-- --
-- ## 5.5) Air-2-Air missile attack range: -- ## 5.5) Air-2-Air missile attack range:
-- * @{#CONTROLLABLE.OptionAAAttackRange}(): Defines the usage of A2A missiles against possible targets. -- * @{#CONTROLLABLE.OptionAAAttackRange}(): Defines the usage of A2A missiles against possible targets .
-- --
-- ## 5.6) GROUND units attack range:
-- * @{#CONTROLLABLE.OptionEngageRange}(): Engage range limit in percent (a number between 0 and 100). Default 100. Defines the range at which a GROUND unit/group (e.g. a SAM site) is allowed to use its weapons automatically.
--
-- @field #CONTROLLABLE -- @field #CONTROLLABLE
CONTROLLABLE = { CONTROLLABLE = {
ClassName = "CONTROLLABLE", ClassName = "CONTROLLABLE",
@ -507,7 +504,7 @@ function CONTROLLABLE:TaskCombo( DCSTasks )
tasks = DCSTasks tasks = DCSTasks
} }
} }
return DCSTaskCombo return DCSTaskCombo
end end
@ -805,12 +802,12 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:CommandSetFrequency(Frequency, Modulation, Delay) function CONTROLLABLE:CommandSetFrequency(Frequency, Modulation, Delay)
local CommandSetFrequency = { local CommandSetFrequency = {
id = 'SetFrequency', id = 'SetFrequency',
params = { params = {
frequency = Frequency*1000000, frequency = Frequency*1000000,
modulation = Modulation or radio.modulation.AM, modulation = Modulation or radio.modulation.AM,
} }
} }
if Delay and Delay>0 then if Delay and Delay>0 then
@ -884,7 +881,7 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At
groupId = AttackGroup:GetID(), groupId = AttackGroup:GetID(),
weaponType = WeaponType or 1073741822, weaponType = WeaponType or 1073741822,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
attackQtyLimit = AttackQty and true or false, attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty or 1, attackQty = AttackQty or 1,
directionEnabled = Direction and true or false, directionEnabled = Direction and true or false,
direction = Direction and math.rad(Direction) or 0, direction = Direction and math.rad(Direction) or 0,
@ -924,7 +921,7 @@ function CONTROLLABLE:TaskAttackUnit(AttackUnit, GroupAttack, WeaponExpend, Atta
weaponType = WeaponType or 1073741822, weaponType = WeaponType or 1073741822,
} }
} }
return DCSTask return DCSTask
end end
@ -1088,7 +1085,7 @@ function CONTROLLABLE:TaskEmbarking(Coordinate, GroupSetForEmbarking, Duration,
-- Distribution -- Distribution
--local distribution={} --local distribution={}
--distribution[id]=gids --distribution[id]=gids
local groupID=self and self:GetID() local groupID=self and self:GetID()
local DCSTask = { local DCSTask = {
@ -1317,7 +1314,7 @@ function CONTROLLABLE:TaskLandAtVec2(Vec2, Duration)
duration = Duration, duration = Duration,
}, },
} }
return DCSTask return DCSTask
end end
@ -1432,7 +1429,7 @@ end
-- @param #number AmmoCount (optional) Quantity of ammunition to expand (omit to fire until ammunition is depleted). -- @param #number AmmoCount (optional) Quantity of ammunition to expand (omit to fire until ammunition is depleted).
-- @param #number WeaponType (optional) Enum for weapon type ID. This value is only required if you want the group firing to use a specific weapon, for instance using the task on a ship to force it to fire guided missiles at targets within cannon range. See http://wiki.hoggit.us/view/DCS_enum_weapon_flag -- @param #number WeaponType (optional) Enum for weapon type ID. This value is only required if you want the group firing to use a specific weapon, for instance using the task on a ship to force it to fire guided missiles at targets within cannon range. See http://wiki.hoggit.us/view/DCS_enum_weapon_flag
-- @param #number Altitude (Optional) Altitude in meters. -- @param #number Altitude (Optional) Altitude in meters.
-- @param #number ASL Altitude is above mean sea level. Default is above ground level. -- @param #number ASL Altitude is above mean sea level. Default is above ground level.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Altitude, ASL ) function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Altitude, ASL )
@ -1454,7 +1451,7 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Alti
DCSTask.params.expendQty = AmmoCount DCSTask.params.expendQty = AmmoCount
DCSTask.params.expendQtyEnabled = true DCSTask.params.expendQtyEnabled = true
end end
if Altitude then if Altitude then
DCSTask.params.altitude=Altitude DCSTask.params.altitude=Altitude
end end
@ -1462,7 +1459,7 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Alti
if WeaponType then if WeaponType then
DCSTask.params.weaponType=WeaponType DCSTask.params.weaponType=WeaponType
end end
--self:I(DCSTask) --self:I(DCSTask)
return DCSTask return DCSTask
@ -1482,6 +1479,7 @@ end
--- (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction. --- (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction.
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. -- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
-- If the task is assigned to the controllable lead unit will be a FAC. -- If the task is assigned to the controllable lead unit will be a FAC.
-- It's important to note that depending on the type of unit that is being assigned the task (AIR or GROUND), you must choose the correct type of callsign enumerator. For airborne controllables use CALLSIGN.Aircraft and for ground based use CALLSIGN.JTAC enumerators.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param Wrapper.Group#GROUP AttackGroup Target GROUP object. -- @param Wrapper.Group#GROUP AttackGroup Target GROUP object.
-- @param #number WeaponType Bitmask of weapon types, which are allowed to use. -- @param #number WeaponType Bitmask of weapon types, which are allowed to use.
@ -1489,7 +1487,7 @@ end
-- @param #boolean Datalink (Optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. -- @param #boolean Datalink (Optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.
-- @param #number Frequency Frequency in MHz used to communicate with the FAC. Default 133 MHz. -- @param #number Frequency Frequency in MHz used to communicate with the FAC. Default 133 MHz.
-- @param #number Modulation Modulation of radio for communication. Default 0=AM. -- @param #number Modulation Modulation of radio for communication. Default 0=AM.
-- @param #number CallsignName Callsign enumerator name of the FAC. -- @param #number CallsignName Callsign enumerator name of the FAC. (CALLSIGN.Aircraft.{name} for airborne controllables, CALLSIGN.JTACS.{name} for ground units)
-- @param #number CallsignNumber Callsign number, e.g. Axeman-**1**. -- @param #number CallsignNumber Callsign number, e.g. Axeman-**1**.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink, Frequency, Modulation, CallsignName, CallsignNumber ) function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink, Frequency, Modulation, CallsignName, CallsignNumber )
@ -1811,7 +1809,7 @@ function CONTROLLABLE:TaskFunction( FunctionString, ... )
-- DCS task. -- DCS task.
local DCSTask = self:TaskWrappedAction(self:CommandDoScript(table.concat( DCSScript ))) local DCSTask = self:TaskWrappedAction(self:CommandDoScript(table.concat( DCSScript )))
return DCSTask return DCSTask
end end
@ -1853,8 +1851,27 @@ do -- Patrol methods
-- Calculate the new Route. -- Calculate the new Route.
local FromCoord = PatrolGroup:GetCoordinate() local FromCoord = PatrolGroup:GetCoordinate()
local From = FromCoord:WaypointGround( 120 )
-- test for submarine
local depth = 0
local IsSub = false
if PatrolGroup:IsShip() then
local navalvec3 = FromCoord:GetVec3()
if navalvec3.y < 0 then
depth = navalvec3.y
IsSub = true
end
end
local Waypoint = Waypoints[1]
local Speed = Waypoint.speed or (20 / 3.6)
local From = FromCoord:WaypointGround( Speed )
if IsSub then
From = FromCoord:WaypointNaval( Speed, Waypoint.alt )
end
table.insert( Waypoints, 1, From ) table.insert( Waypoints, 1, From )
local TaskRoute = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRoute" ) local TaskRoute = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRoute" )
@ -1894,7 +1911,16 @@ do -- Patrol methods
if ToWaypoint then if ToWaypoint then
FromWaypoint = ToWaypoint FromWaypoint = ToWaypoint
end end
-- test for submarine
local depth = 0
local IsSub = false
if PatrolGroup:IsShip() then
local navalvec3 = FromCoord:GetVec3()
if navalvec3.y < 0 then
depth = navalvec3.y
IsSub = true
end
end
-- Loop until a waypoint has been found that is not the same as the current waypoint. -- Loop until a waypoint has been found that is not the same as the current waypoint.
-- Otherwise the object zon't move or drive in circles and the algorithm would not do exactly -- Otherwise the object zon't move or drive in circles and the algorithm would not do exactly
-- what it is supposed to do, which is making groups drive around. -- what it is supposed to do, which is making groups drive around.
@ -1909,9 +1935,13 @@ do -- Patrol methods
local ToCoord = COORDINATE:NewFromVec2( { x = Waypoint.x, y = Waypoint.y } ) local ToCoord = COORDINATE:NewFromVec2( { x = Waypoint.x, y = Waypoint.y } )
-- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task -- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task
local Route = {} local Route = {}
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation ) if IsSub then
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation ) Route[#Route+1] = FromCoord:WaypointNaval( Speed, depth )
Route[#Route+1] = ToCoord:WaypointNaval( Speed, Waypoint.alt )
else
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation )
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation )
end
local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRouteRandom", Speed, Formation, ToWaypoint ) local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRouteRandom", Speed, Formation, ToWaypoint )
@ -1952,9 +1982,20 @@ do -- Patrol methods
self:F( { PatrolGroup = PatrolGroup:GetName() } ) self:F( { PatrolGroup = PatrolGroup:GetName() } )
if PatrolGroup:IsGround() or PatrolGroup:IsShip() then if PatrolGroup:IsGround() or PatrolGroup:IsShip() then
-- Calculate the new Route. -- Calculate the new Route.
local FromCoord = PatrolGroup:GetCoordinate() local FromCoord = PatrolGroup:GetCoordinate()
-- test for submarine
local depth = 0
local IsSub = false
if PatrolGroup:IsShip() then
local navalvec3 = FromCoord:GetVec3()
if navalvec3.y < 0 then
depth = navalvec3.y
IsSub = true
end
end
-- Select a random Zone and get the Coordinate of the new Zone. -- Select a random Zone and get the Coordinate of the new Zone.
local RandomZone = ZoneList[ math.random( 1, #ZoneList ) ] -- Core.Zone#ZONE local RandomZone = ZoneList[ math.random( 1, #ZoneList ) ] -- Core.Zone#ZONE
@ -1962,9 +2003,13 @@ do -- Patrol methods
-- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task -- Create a "ground route point", which is a "point" structure that can be given as a parameter to a Task
local Route = {} local Route = {}
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation ) if IsSub then
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation ) Route[#Route+1] = FromCoord:WaypointNaval( Speed, depth )
Route[#Route+1] = ToCoord:WaypointNaval( Speed, depth )
else
Route[#Route+1] = FromCoord:WaypointGround( Speed, Formation )
Route[#Route+1] = ToCoord:WaypointGround( Speed, Formation )
end
local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolZones", ZoneList, Speed, Formation, DelayMin, DelayMax ) local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolZones", ZoneList, Speed, Formation, DelayMin, DelayMax )
@ -1988,7 +2033,7 @@ function CONTROLLABLE:TaskRoute( Points )
id = 'Mission', id = 'Mission',
params = { params = {
airborne = self:IsAir(), airborne = self:IsAir(),
route = {points = Points}, route = {points = Points},
}, },
} }
@ -2914,9 +2959,9 @@ end
function CONTROLLABLE:OptionROE(ROEvalue) function CONTROLLABLE:OptionROE(ROEvalue)
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
if DCSControllable then if DCSControllable then
local Controller = self:_GetController() local Controller = self:_GetController()
if self:IsAir() then if self:IsAir() then
@ -3480,13 +3525,13 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionProhibitAfterburner(Prohibit) function CONTROLLABLE:OptionProhibitAfterburner(Prohibit)
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if Prohibit==nil then if Prohibit==nil then
Prohibit=true Prohibit=true
end end
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.id.PROHIBIT_AB, Prohibit) self:SetOption(AI.Option.Air.id.PROHIBIT_AB, Prohibit)
end end
return self return self
@ -3497,9 +3542,9 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_Never() function CONTROLLABLE:OptionECM_Never()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.id.ECM_USING, 0) self:SetOption(AI.Option.Air.id.ECM_USING, 0)
end end
return self return self
@ -3510,9 +3555,9 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_OnlyLockByRadar() function CONTROLLABLE:OptionECM_OnlyLockByRadar()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.id.ECM_USING, 1) self:SetOption(AI.Option.Air.id.ECM_USING, 1)
end end
return self return self
@ -3524,9 +3569,9 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_DetectedLockByRadar() function CONTROLLABLE:OptionECM_DetectedLockByRadar()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.id.ECM_USING, 2) self:SetOption(AI.Option.Air.id.ECM_USING, 2)
end end
return self return self
@ -3537,9 +3582,9 @@ end
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionECM_AlwaysOn() function CONTROLLABLE:OptionECM_AlwaysOn()
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.id.ECM_USING, 3) self:SetOption(AI.Option.Air.id.ECM_USING, 3)
end end
return self return self
@ -3681,22 +3726,22 @@ end
--- Sets Controllable Option for A2A attack range for AIR FIGHTER units. --- Sets Controllable Option for A2A attack range for AIR FIGHTER units.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param #number range Defines the range -- @param #number range Defines the range
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
-- @usage Range can be one of MAX_RANGE = 0, NEZ_RANGE = 1, HALF_WAY_RMAX_NEZ = 2, TARGET_THREAT_EST = 3, RANDOM_RANGE = 4. Defaults to 3. See: https://wiki.hoggitworld.com/view/DCS_option_missileAttack -- @usage Range can be one of MAX_RANGE = 0, NEZ_RANGE = 1, HALF_WAY_RMAX_NEZ = 2, TARGET_THREAT_EST = 3, RANDOM_RANGE = 4. Defaults to 3. See: https://wiki.hoggitworld.com/view/DCS_option_missileAttack
function CONTROLLABLE:OptionAAAttackRange(range) function CONTROLLABLE:OptionAAAttackRange(range)
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- defaults to 3 -- defaults to 3
local range = range or 3 local range = range or 3
if range < 0 or range > 4 then if range < 0 or range > 4 then
range = 3 range = 3
end end
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
if DCSControllable then if DCSControllable then
local Controller = self:_GetController() local Controller = self:_GetController()
if Controller then if Controller then
if self:IsAir() then if self:IsAir() then
self:SetOption(AI.Option.Air.val.MISSILE_ATTACK, range) self:SetOption(AI.Option.Air.val.MISSILE_ATTACK, range)
end end
end end
return self return self
@ -3709,7 +3754,7 @@ end
-- @param #number EngageRange Engage range limit in percent (a number between 0 and 100). Default 100. -- @param #number EngageRange Engage range limit in percent (a number between 0 and 100). Default 100.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionEngageRange(EngageRange) function CONTROLLABLE:OptionEngageRange(EngageRange)
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- Set default if not specified. -- Set default if not specified.
EngageRange=EngageRange or 100 EngageRange=EngageRange or 100
if EngageRange < 0 or EngageRange > 100 then if EngageRange < 0 or EngageRange > 100 then
@ -3718,9 +3763,9 @@ function CONTROLLABLE:OptionEngageRange(EngageRange)
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
if DCSControllable then if DCSControllable then
local Controller = self:_GetController() local Controller = self:_GetController()
if Controller then if Controller then
if self:IsGround() then if self:IsGround() then
self:SetOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION, EngageRange) self:SetOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION, EngageRange)
end end
end end
return self return self
@ -3736,9 +3781,9 @@ end
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false -- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut) function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut)
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
local _coord = self:GetCoordinate() local _coord = self:GetCoordinate()
local _radius = radius or 500 local _radius = radius or 500
local _speed = speed or 20 local _speed = speed or 20
local _tocoord = _coord:GetRandomCoordinateInRadius(_radius,100) local _tocoord = _coord:GetRandomCoordinateInRadius(_radius,100)
@ -3746,7 +3791,7 @@ function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortc
local _grptsk = {} local _grptsk = {}
local _candoroad = false local _candoroad = false
local _shortcut = shortcut or false local _shortcut = shortcut or false
-- create a DCS Task an push it on the group -- create a DCS Task an push it on the group
-- TaskGroundOnRoad(ToCoordinate,Speed,OffRoadFormation,Shortcut,FromCoordinate,WaypointFunction,WaypointFunctionArguments) -- TaskGroundOnRoad(ToCoordinate,Speed,OffRoadFormation,Shortcut,FromCoordinate,WaypointFunction,WaypointFunctionArguments)
if onroad then if onroad then
@ -3756,23 +3801,23 @@ function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortc
self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,"Off Road") self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,"Off Road")
end end
return self return self
end end
--- Defines how long a GROUND unit/group will move to avoid an ongoing attack. --- Defines how long a GROUND unit/group will move to avoid an ongoing attack.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @param #number Seconds Any positive number: AI will disperse, but only for the specified time before continuing their route. 0: AI will not disperse. -- @param #number Seconds Any positive number: AI will disperse, but only for the specified time before continuing their route. 0: AI will not disperse.
-- @return #CONTROLLABLE self -- @return #CONTROLLABLE self
function CONTROLLABLE:OptionDisperseOnAttack(Seconds) function CONTROLLABLE:OptionDisperseOnAttack(Seconds)
self:F2( { self.ControllableName } ) self:F2( { self.ControllableName } )
-- Set default if not specified. -- Set default if not specified.
local seconds = Seconds or 0 local seconds = Seconds or 0
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
if DCSControllable then if DCSControllable then
local Controller = self:_GetController() local Controller = self:_GetController()
if Controller then if Controller then
if self:IsGround() then if self:IsGround() then
self:SetOption(AI.Option.GROUND.id.DISPERSE_ON_ATTACK, seconds) self:SetOption(AI.Option.GROUND.id.DISPERSE_ON_ATTACK, seconds)
end end
end end
return self return self