- NAVYGROUP added engage target
- Barrage improvments
This commit is contained in:
Frank 2021-10-22 11:23:29 +02:00
parent ed6d5f727a
commit 6009432933
6 changed files with 272 additions and 35 deletions

View File

@ -1046,9 +1046,9 @@ function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
-- Fist, check if we want to rearm once out-of-ammo.
if self.rearmOnOutOfAmmo then
local truck=self:FindNearestAmmoSupply(30)
local truck, dist=self:FindNearestAmmoSupply(30)
if truck then
self:T(self.lid..string.format("Found Ammo Truck %s [%s]"))
self:T(self.lid..string.format("Found Ammo Truck %s [%s]", truck:GetName(), truck:GetTypeName()))
local Coordinate=truck:GetCoordinate()
self:Rearm(Coordinate, Formation)
return
@ -1159,6 +1159,10 @@ function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
if zone then
if self:IsInZone(zone) then
self:Returned()
else
-- Debug info.
self:I(self.lid..string.format("RTZ to Zone %s", zone:GetName()))
@ -1170,6 +1174,8 @@ function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
-- Set if we want to resume route after reaching the detour waypoint.
wp.detour=0
end
else
self:E(self.lid.."ERROR: No RTZ zone given!")
end
@ -1684,7 +1690,7 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
local unit=_unit --Wrapper.Unit#UNIT
-- Check coaliton and if unit can supply ammo.
if unit:GetCoalition()==myCoalition and unit:IsAmmoSupply() then
if unit:IsAlive() and unit:GetCoalition()==myCoalition and unit:IsAmmoSupply() and unit:GetVelocityKMH()<1 then
-- Distance.
local d=coord:Get2DDistance(unit:GetCoord())
@ -1693,6 +1699,8 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
if d<dmin then
dmin=d
truck=unit
-- Debug message.
self:T(self.lid..string.format("Ammo truck %s [%s] at dist=%d meters", unit:GetName(), unit:GetTypeName(), d))
end
end

View File

@ -47,8 +47,9 @@
-- @field #number Tstop Mission stop time in abs. seconds.
-- @field #number duration Mission duration in seconds.
-- @field #number durationExe Mission execution time in seconds.
-- @field #number Texecuting Mission time stamp (abs) when it started to execute. Is #nil on start.
-- @field #number Texecuting Time stamp (abs) when mission is executing. Is `#nil` on start.
-- @field #number Tpush Mission push/execute time in abs. seconds.
-- @field #number Tstarted Time stamp (abs) when mission is started.
-- @field Wrapper.Marker#MARKER marker F10 map marker.
-- @field #boolean markerOn If true, display marker on F10 map with the AUFTRAG status.
-- @field #number markerCoaliton Coalition to which the marker is dispayed.
@ -103,6 +104,8 @@
-- @field #number artyRadius Radius in meters.
-- @field #number artyShots Number of shots fired.
-- @field #number artyAltitude Altitude in meters. Can be used for a Barrage.
-- @field #number artyHeading Heading in degrees (for Barrage).
-- @field #number artyDistance Distance in meters (for barrage).
--
-- @field #string alert5MissionType Alert 5 mission type. This is the mission type, the alerted assets will be able to carry out.
--
@ -373,6 +376,7 @@ _AUFTRAGSNR=0
-- @field #string FUELSUPPLY Fuel supply.
-- @field #string ALERT5 Alert 5.
-- @field #string ONGUARD On guard.
-- @field #string BARRAGE Barrage.
AUFTRAG.Type={
ANTISHIP="Anti Ship",
AWACS="AWACS",
@ -402,6 +406,7 @@ AUFTRAG.Type={
FUELSUPPLY="Fuel Supply",
ALERT5="Alert5",
ONGUARD="On Guard",
BARRAGE="Barrage",
}
--- Mission status of an assigned group.
@ -412,6 +417,7 @@ AUFTRAG.Type={
-- @field #string FUELSUPPLY Fuel Supply.
-- @field #string ALERT5 Alert 5 task.
-- @field #string ONGUARD On guard.
-- @field #string BARRAGE Barrage.
AUFTRAG.SpecialTask={
PATROLZONE="PatrolZone",
RECON="ReconMission",
@ -419,6 +425,7 @@ AUFTRAG.SpecialTask={
FUELSUPPLY="Fuel Supply",
ALERT5="Alert5",
ONGUARD="On Guard",
BARRAGE="Barrage",
}
--- Mission status.
@ -1572,7 +1579,45 @@ function AUFTRAG:NewARTY(Target, Nshots, Radius, Altitude)
-- Evaluate after 8 min.
mission.dTevaluate=8*60
mission.categories={AUFTRAG.Category.GROUND}
mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL}
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- **[GROUND, NAVAL]** Create an BARRAGE mission. Assigned groups will move to a random coordinate within a given zone and start firing into the air.
-- @param #AUFTRAG self
-- @param Core.Zone#ZONE Zone The zone where the unit will go.
-- @param #number Radius Radius of the shells in meters. Default 100 meters.
-- @param #number Altitude Altitude in meters. Default 500 m.
-- @param #number Heading Heading in degrees. Default random heading [0, 360).
-- @param #number Distance Distance in meters. Default 500 m.
-- @param #number Nshots Number of shots to be fired. Default is until ammo is empty (`#nil`).
-- @return #AUFTRAG self
function AUFTRAG:NewBARRAGE(Zone, Radius, Altitude, Heading, Distance, Nshots)
local mission=AUFTRAG:New(AUFTRAG.Type.BARRAGE)
mission:_TargetFromObject(Zone)
mission.artyShots=Nshots
mission.artyRadius=Radius or 100
mission.artyAltitude=Altitude
mission.artyHeading=Heading
mission.artyDistance=Distance
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
mission.optionROE=ENUMS.ROE.OpenFire -- Ground/naval need open fire!
mission.optionAlarm=0
mission.missionFraction=0.0
-- Evaluate after instantly.
mission.dTevaluate=10
mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL}
mission.DCStask=mission:GetDCSMissionTask()
@ -4728,6 +4773,30 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.BARRAGE then
---------------------
-- BARRAGE Mission --
---------------------
local DCStask={}
DCStask.id=AUFTRAG.SpecialTask.BARRAGE
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
param.zone=self:GetObjective()
param.altitude=self.artyAltitude
param.radius=self.artyRadius
param.heading=self.artyHeading
param.distance=self.artyDistance
param.shots=self.artyShots
param.weaponTypoe=self.engageWeaponType
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.PATROLZONE then
-------------------------

View File

@ -3137,7 +3137,7 @@ function FLIGHTGROUP:FindNearestTanker(Radius)
local istanker, refuelsystem=unit:IsTanker()
if istanker and self.refueltype==refuelsystem and unit:GetCoalition()==self:GetCoalition() then
if istanker and self.refueltype==refuelsystem and unit:IsAlive() and unit:GetCoalition()==self:GetCoalition() then
-- Distance.
local d=unit:GetCoordinate():Get2DDistance(coord)

View File

@ -43,6 +43,7 @@
-- @field #boolean pathfindingOn If true, enable pathfining.
-- @field #number pathCorridor Path corrdidor width in meters.
-- @field #boolean ispathfinding If true, group is currently path finding.
-- @field #NAVYGROUP.Target engage Engage target.
-- @extends Ops.OpsGroup#OPSGROUP
--- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson
@ -61,6 +62,7 @@ NAVYGROUP = {
intowindcounter = 0,
Qintowind = {},
pathCorridor = 400,
engage = {},
}
--- Turn into wind parameters.
@ -77,6 +79,13 @@ NAVYGROUP = {
-- @field #boolean Open Currently active.
-- @field #boolean Over This turn is over.
--- Engage Target.
-- @type NAVYGROUP.Target
-- @field Ops.Target#TARGET Target The target.
-- @field Core.Point#COORDINATE Coordinate Last known coordinate of the target.
-- @field Ops.OpsGroup#OPSGROUP.Waypoint Waypoint the waypoint created to go to the target.
-- @field #number roe ROE backup.
-- @field #number alarmstate Alarm state backup.
--- NavyGroup version.
-- @field #string version
@ -160,7 +169,9 @@ function NAVYGROUP:New(group)
self:AddTransition("*", "ClearAhead", "*") -- Clear ahead.
self:AddTransition("Cruising", "Dive", "Cruising") -- Command a submarine to dive.
self:AddTransition("Engaging", "Dive", "Engaging") -- Command a submarine to dive.
self:AddTransition("Cruising", "Surface", "Cruising") -- Command a submarine to go to the surface.
self:AddTransition("Engaging", "Surface", "Engaging") -- Command a submarine to go to the surface.
------------------------
--- Pseudo Functions ---
@ -745,8 +756,8 @@ function NAVYGROUP:Status(From, Event, To)
local intowind=self:IsSteamingIntoWind() and UTILS.SecondsToClock(self.intowind.Tstop-timer.getAbsTime(), true) or "N/A"
local turning=tostring(self:IsTurning())
local alt=self.position.y
local speed=UTILS.MpsToKnots(self.velocity)
local alt=self.position and self.position.y or 0
local speed=UTILS.MpsToKnots(self.velocity or 0)
local speedExpected=UTILS.MpsToKnots(self:GetExpectedSpeed())
-- Waypoint stuff.
@ -765,7 +776,7 @@ function NAVYGROUP:Status(From, Event, To)
-- Info text.
local text=string.format("%s [ROE=%d,AS=%d, T/M=%d/%d]: Wp=%d[%d]-->%d[%d] /%d [%s] Dist=%.1f NM ETA=%s - Speed=%.1f (%.1f) kts, Depth=%.1f m, Hdg=%03d, Turn=%s Collision=%d IntoWind=%s",
fsmstate, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, wpN, wpF, wpDist, wpETA, speed, speedExpected, alt, self.heading, turning, freepath, intowind)
fsmstate, roe, als, nTaskTot, nMissions, wpidxCurr, wpuidCurr, wpidxNext, wpuidNext, wpN, wpF, wpDist, wpETA, speed, speedExpected, alt, self.heading or 0, turning, freepath, intowind)
self:I(self.lid..text)
end
@ -809,6 +820,21 @@ function NAVYGROUP:Status(From, Event, To)
end
---
-- Engage Detected Targets
---
if self:IsCruising() and self.detectionOn and self.engagedetectedOn then
local targetgroup, targetdist=self:_GetDetectedTarget()
-- If we found a group, we engage it.
if targetgroup then
self:I(self.lid..string.format("Engaging target group %s at distance %d meters", targetgroup:GetName(), targetdist))
self:EngageTarget(targetgroup)
end
end
---
-- Cargo
---
@ -974,6 +1000,8 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Depth)
-- Waypoint.
local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
--env.info(string.format("FF i=%d UID=%d n=%d, N=%d", i, wp.uid, n, N))
-- Speed.
if Speed then
-- Take speed specified.
@ -1013,8 +1041,16 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Depth)
if self:IsEngaging() or not self.passedfinalwp then
--[[
env.info("FF:")
for i=2,#waypoints do
local wp=waypoints[i] --Ops.OpsGroup#OPSGROUP.Waypoint
self:I(self.lid..string.format("[%d] UID=%d", i-1, wp.uid))
end
]]
-- Debug info.
self:T(self.lid..string.format("Updateing route: WP %d-->%d (%d/%d), Speed=%.1f knots, Depth=%d m", self.currentwp, n, #waypoints, #self.waypoints, UTILS.MpsToKnots(self.speedWp), self.altWp))
self:I(self.lid..string.format("Updateing route: WP %d-->%d (%d/%d), Speed=%.1f knots, Depth=%d m", self.currentwp, n, #waypoints, #self.waypoints, UTILS.MpsToKnots(self.speedWp), self.altWp))
-- Route group to all defined waypoints remaining.
self:Route(waypoints)
@ -1311,6 +1347,114 @@ function NAVYGROUP:onafterCollisionWarning(From, Event, To, Distance)
self.collisionwarning=true
end
--- On after "EngageTarget" event.
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param Wrapper.Group#GROUP Group the group to be engaged.
function NAVYGROUP:onafterEngageTarget(From, Event, To, Target)
self:T(self.lid.."Engaging Target")
if Target:IsInstanceOf("TARGET") then
self.engage.Target=Target
else
self.engage.Target=TARGET:New(Target)
end
-- Target coordinate.
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
-- Backup ROE and alarm state.
self.engage.roe=self:GetROE()
self.engage.alarmstate=self:GetAlarmstate()
-- Switch ROE and alarm state.
self:SwitchAlarmstate(ENUMS.AlarmState.Auto)
self:SwitchROE(ENUMS.ROE.OpenFire)
-- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
-- Add waypoint after current.
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
-- Set if we want to resume route after reaching the detour waypoint.
self.engage.Waypoint.detour=1
end
--- Update engage target.
-- @param #NAVYGROUP self
function NAVYGROUP:_UpdateEngageTarget()
if self.engage.Target and self.engage.Target:IsAlive() then
-- Get current position vector.
local vec3=self.engage.Target:GetVec3()
-- Distance to last known position of target.
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
-- Check if target moved more than 100 meters.
if dist>100 then
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
-- Update new position.
self.engage.Coordinate:UpdateFromVec3(vec3)
-- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
-- Remove current waypoint
self:RemoveWaypointByID(self.engage.Waypoint.uid)
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
-- Add waypoint after current.
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
-- Set if we want to resume route after reaching the detour waypoint.
self.engage.Waypoint.detour=0
end
else
-- Target not alive any more == Disengage.
self:Disengage()
end
end
--- On after "Disengage" event.
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function NAVYGROUP:onafterDisengage(From, Event, To)
self:T(self.lid.."Disengage Target")
-- Restore previous ROE and alarm state.
self:SwitchROE(self.engage.roe)
self:SwitchAlarmstate(self.engage.alarmstate)
-- Remove current waypoint
if self.engage.Waypoint then
self:RemoveWaypointByID(self.engage.Waypoint.uid)
end
-- Check group is done
self:_CheckGroupDone(1)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Routing

View File

@ -3663,20 +3663,34 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Just stay put.
--TODO: Change ALARM STATE
else
-- If task is scheduled (not waypoint) set task.
if Task.type==OPSGROUP.TaskType.SCHEDULED or Task.ismission then
local DCSTask=nil --UTILS.DeepCopy(Task.dcstask)
-- BARRAGE is special!
if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
--env.info("FF Barrage")
local vec2=self:GetVec2()
local param=Task.dcstask.params
local heading=param.heading or math.random(1, 360)
local distance=param.distance or 100
local tvec2=UTILS.Vec2Translate(vec2, distance, heading)
DCSTask=CONTROLLABLE.TaskFireAtPoint(nil, tvec2, param.radius, param.shots, param.weaponType, param.altitude)
else
DCSTask=Task.dcstask
end
local DCStasks={}
if Task.dcstask.id=='ComboTask' then
if DCSTask.id=='ComboTask' then
-- Loop over all combo tasks.
for TaskID, Task in ipairs(Task.dcstask.params.tasks) do
for TaskID, Task in ipairs(DCSTask.params.tasks) do
table.insert(DCStasks, Task)
end
else
table.insert(DCStasks, Task.dcstask)
table.insert(DCStasks, DCSTask)
end
-- Combo task.
@ -3853,7 +3867,7 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task)
if self.currentmission and self.currentmission==Mission.auftragsnummer then
self.currentmission=nil
end
env.info("Remove mission waypoints")
self:T(self.lid.."Remove mission waypoints")
self:_RemoveMissionWaypoints(Mission, false)
end
@ -4474,7 +4488,7 @@ function OPSGROUP:RouteToMission(mission, delay)
end
-- Get ingress waypoint.
if mission.type==AUFTRAG.Type.PATROLZONE then
if mission.type==AUFTRAG.Type.PATROLZONE or mission.type==AUFTRAG.Type.BARRAGE then
local zone=mission.engageTarget:GetObject() --Core.Zone#ZONE
waypointcoord=zone:GetRandomCoordinate(nil , nil, surfacetypes)
else
@ -5042,6 +5056,8 @@ end
-- @param #number Speed (Optional) Speed to waypoint in knots.
function OPSGROUP:onafterGotoWaypoint(From, Event, To, UID, Speed)
--env.info("FF goto waypoint uid="..tostring(UID))
local n=self:GetWaypointIndex(UID)
if n then
@ -5050,10 +5066,10 @@ function OPSGROUP:onafterGotoWaypoint(From, Event, To, UID, Speed)
Speed=Speed or self:GetSpeedToWaypoint(n)
-- Debug message
self:T(self.lid..string.format("Goto Waypoint UID=%d index=%d from %d at speed %.1f knots", UID, n, self.currentwp, Speed))
self:I(self.lid..string.format("Goto Waypoint UID=%d index=%d from %d at speed %.1f knots", UID, n, self.currentwp, Speed))
-- Update the route.
self:__UpdateRoute(-0.01, n, nil, Speed)
self:__UpdateRoute(0.1, n, nil, Speed)
end
@ -8388,7 +8404,7 @@ end
function OPSGROUP:_CheckStuck()
-- Cases we are not stuck.
if self:IsHolding() or self:Is("Rearming") or self:IsWaiting() then
if self:IsHolding() or self:Is("Rearming") or self:IsWaiting() or self:HasPassedFinalWaypoint() then
return
end
@ -9764,7 +9780,7 @@ function OPSGROUP:SwitchRadio(Frequency, Modulation)
Modulation=Modulation or self.radioDefault.Modu
if self:IsFlightgroup() and not self.radio.On then
env.info("FF radio OFF")
--env.info("FF radio OFF")
self.group:SetOption(AI.Option.Air.id.SILENCE, false)
end

View File

@ -1460,7 +1460,7 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType, Alti
DCSTask.params.weaponType=WeaponType
end
--self:I(DCSTask)
--BASE:I(DCSTask)
return DCSTask
end