From 426dcff08569b20a2cf10aeb24df6652563f9572 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 3 Apr 2022 23:59:43 +0200 Subject: [PATCH] OPS FLIGHTGROUP - Improved homebase for spawned units - Enabled helo inAir check due to DCS bug that inAir returns true when spawned at airbase or farp SET_ZONE - Added DrawZone() function ARMYGROUP - Improved EngageTarget() function AUFTRAG - ARMORATTACK is not falling back to GROUNDATTACK --- Moose Development/Moose/Core/Set.lua | 25 +++++- Moose Development/Moose/Ops/AirWing.lua | 8 +- Moose Development/Moose/Ops/ArmyGroup.lua | 60 +++++-------- Moose Development/Moose/Ops/Auftrag.lua | 93 ++++++--------------- Moose Development/Moose/Ops/Chief.lua | 20 +++-- Moose Development/Moose/Ops/Cohort.lua | 2 +- Moose Development/Moose/Ops/FlightGroup.lua | 8 +- Moose Development/Moose/Ops/OpsGroup.lua | 88 +++++++++---------- Moose Development/Moose/Ops/Squadron.lua | 8 +- Moose Development/Moose/Ops/Target.lua | 2 +- Moose Development/Moose/Utilities/Utils.lua | 30 ++++++- 11 files changed, 174 insertions(+), 170 deletions(-) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index d89568336..b212789e3 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -5763,8 +5763,28 @@ do -- SET_ZONE return self end + --- Draw all zones in the set on the F10 map. + -- @param #SET_ZONE self + -- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All. + -- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red. + -- @param #number Alpha Transparency [0,1]. Default 1. + -- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. + -- @param #number FillAlpha Transparency [0,1]. Default 0.15. + -- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid. + -- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false. + -- @return #SET_ZONE self + function SET_ZONE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly) + + for _,_zone in pairs(self.Set) do + local zone=_zone --Core.Zone#ZONE + zone:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly) + end - --- + return self + end + + + --- Private function. -- @param #SET_ZONE self -- @param Core.Zone#ZONE_BASE MZone -- @return #SET_ZONE self @@ -5779,7 +5799,8 @@ do -- SET_ZONE if self.Filter.Prefixes then local MZonePrefix = false for ZonePrefixId, ZonePrefix in pairs( self.Filter.Prefixes ) do - self:T3( { "Prefix:", string.find( MZoneName, ZonePrefix, 1 ), ZonePrefix } ) + env.info(string.format("zone %s %s", MZoneName, ZonePrefix)) + self:I( { "Prefix:", string.find( MZoneName, ZonePrefix, 1 ), ZonePrefix } ) if string.find( MZoneName, ZonePrefix, 1 ) then MZonePrefix = true end diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index 546adbe25..cc7bc308f 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -40,7 +40,7 @@ -- -- @extends Ops.Legion#LEGION ---- Be surprised! +--- *I fly because it releases my mind from the tyranny of petty things* -- Antoine de Saint-Exupery -- -- === -- @@ -97,12 +97,6 @@ -- If the mission stop time is over (and the mission is not finished), it will be cancelled and removed from the queue. This applies also to mission that were not even -- started. -- --- # Command an Airwing --- --- An airwing can receive missions from a WINGCOMMANDER. See docs of that class for details. --- --- However, you are still free to add missions at anytime. --- -- -- @field #AIRWING AIRWING = { diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 819a7fae2..65b42d6e0 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -38,12 +38,10 @@ -- @field Core.Set#SET_ZONE retreatZones Set of retreat zones. -- @extends Ops.OpsGroup#OPSGROUP ---- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B Sledge +--- *Your soul may belong to Jesus, but your ass belongs to the marines* -- Eugene B Sledge -- -- === --- --- ![Banner Image](..\Presentations\OPS\ArmyGroup\_Main.png) --- +-- -- # The ARMYGROUP Concept -- -- This class enhances ground groups. @@ -60,6 +58,8 @@ ARMYGROUP = { -- @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 Speed Speed in knots. +-- @field #string Formation Formation used in the engagement. -- @field #number roe ROE backup. -- @field #number alarmstate Alarm state backup. @@ -281,11 +281,16 @@ function ARMYGROUP:New(group) --- Triggers the FSM event "EngageTarget". -- @function [parent=#ARMYGROUP] EngageTarget -- @param #ARMYGROUP self + -- @param Wrapper.Group#GROUP Group the group to be engaged. + -- @param #string Formation Formation used in the engagement. --- Triggers the FSM event "EngageTarget" after a delay. -- @function [parent=#ARMYGROUP] __EngageTarget -- @param #ARMYGROUP self -- @param #number delay Delay in seconds. + -- @param Wrapper.Group#GROUP Group the group to be engaged. + -- @param #string Formation Formation used in the engagement. + --- On after "EngageTarget" event. -- @function [parent=#ARMYGROUP] OnAfterEngageTarget @@ -293,6 +298,8 @@ function ARMYGROUP:New(group) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. + -- @param Wrapper.Group#GROUP Group the group to be engaged. + -- @param #string Formation Formation used in the engagement. --- Triggers the FSM event "Disengage". @@ -987,33 +994,6 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation) current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad) table.insert(waypoints, 2, current) - - -- Removing this for now as I don't see why it is necessary and it is very CPU intensive. - -- You only need the start and end waypoint on the road. Other waypoints on the road are not necessray. - --[[ - -- take direct line if on road is too long - local wptable,length,valid=self:GetCoordinate():GetPathOnRoad(wp.coordinate or wp.roadcoord,true,false,false,false) or {} - - local lenghtdirect = self:GetCoordinate():Get2DDistance(wp.coordinate) or 100000 - - if valid and length then - if length > lenghtdirect * 8 then - valid = false -- rather go directly - end - end - - local count = 2 - if valid then - for _,_coord in ipairs(wptable) do - local current = _coord:WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad) - table.insert(waypoints, count, current) - count=count+1 - end - else - current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad) - table.insert(waypoints, count, current) - end - ]] end -- Debug output. @@ -1392,7 +1372,9 @@ end -- @param #string Event Event. -- @param #string To To state. -- @param Wrapper.Group#GROUP Group the group to be engaged. -function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target) +-- @param #number Speed Speed in knots. +-- @param #string Formation Formation used in the engagement. Default `ENUMS.Formation.Vehicle.Vee`. +function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target, Speed, Formation) local dt=nil local allowed=true @@ -1430,7 +1412,9 @@ end -- @param #string Event Event. -- @param #string To To state. -- @param Wrapper.Group#GROUP Group the group to be engaged. -function ARMYGROUP:onafterEngageTarget(From, Event, To, Target) +-- @param #number Speed Attack speed in knots. +-- @param #string Formation Formation used in the engagement. Default `ENUMS.Formation.Vehicle.Vee`. +function ARMYGROUP:onafterEngageTarget(From, Event, To, Target, Speed, Formation) self:T(self.lid.."Engaging Target") -- Make sure this is a target. @@ -1458,11 +1442,13 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target) local uid=self:GetWaypointCurrent().uid -- Set formation. - --TODO: make this input. - local Formation=ENUMS.Formation.Vehicle.Vee + self.engage.Formation=Formation or ENUMS.Formation.Vehicle.Vee + + -- Set speed. + self.engage.Speed=Speed -- Add waypoint after current. - self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true) + self.engage.Waypoint=self:AddWaypoint(intercoord, self.engage.Speed, uid, self.engage.Formation, true) -- Set if we want to resume route after reaching the detour waypoint. self.engage.Waypoint.detour=1 @@ -1500,7 +1486,7 @@ function ARMYGROUP:_UpdateEngageTarget() local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9) -- Add waypoint after current. - self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true) + self.engage.Waypoint=self:AddWaypoint(intercoord, self.engage.Speed, uid, self.engage.Formation, true) -- Set if we want to resume route after reaching the detour waypoint. self.engage.Waypoint.detour=0 diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index f0965d826..2bdfc9720 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -279,13 +279,9 @@ -- -- An arty mission can be created with the @{#AUFTRAG.NewARTY}() function. -- --- ## ARMORATTACK +-- ## GROUNDATTACK -- --- A mission to send a tank group can be created with the @{#AUFTRAG.NewARMORATTACK}() function. --- --- # Options and Parameters --- --- TODO +-- A ground attack mission can be created with the @{#AUFTRAG.NewGROUNDATTACK}() function. -- -- # Assigning Missions -- @@ -1583,7 +1579,7 @@ end -- @param #AUFTRAG self -- @param Core.Set#SET_GROUP TransportGroupSet The set group(s) to be transported. -- @param Core.Point#COORDINATE DropoffCoordinate Coordinate where the helo will land drop off the the troops. --- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the fist transport group. +-- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the first transport group. -- @param #number PickupRadius Radius around the pickup coordinate in meters. Default 100 m. -- @return #AUFTRAG self function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate, PickupRadius) @@ -1740,7 +1736,7 @@ end -- @param Core.Zone#ZONE Zone The patrol zone. -- @param #number Speed Speed in knots. -- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL. --- @param #string Formation Formation used during patrol. +-- @param #string Formation Formation used by ground units during patrol. Default "Off Road". -- @return #AUFTRAG self function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation) @@ -1767,13 +1763,14 @@ function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation) mission.DCStask=mission:GetDCSMissionTask() - mission.DCStask.params.formation=Formation + mission.DCStask.params.formation=Formation or "Off Road" return mission end ---- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack. +--- **[OBSOLETE]** Create a ARMORATTACK mission. +-- ** Note that this is actually creating a GROUNDATTACK mission!** -- @param #AUFTRAG self -- @param Ops.Target#TARGET Target The target to attack. Can be a GROUP, UNIT or STATIC object. -- @param #number Speed Speed in knots. @@ -1781,23 +1778,10 @@ end -- @return #AUFTRAG self function AUFTRAG:NewARMORATTACK(Target, Speed, Formation) - local mission=AUFTRAG:New(AUFTRAG.Type.ARMORATTACK) - - mission:_TargetFromObject(Target) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.ARMORATTACK) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto - mission.optionFormation="On Road" - mission.optionAttackFormation=Formation or "Wedge" - - mission.missionFraction=1.0 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or 20 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() + local mission=AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation) + + -- Mission type. + mission.type=AUFTRAG.Type.ARMORATTACK return mission end @@ -1805,8 +1789,8 @@ end --- **[GROUND]** Create a GROUNDATTACK mission. Ground group(s) will go to a target object and attack. -- @param #AUFTRAG self -- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object. --- @param #number Speed Speed in knots. --- @param #string Formation The attack formation, e.g. "Wedge", "Vee" etc. +-- @param #number Speed Speed in knots. Default max. +-- @param #string Formation The attack formation, e.g. "Wedge", "Vee" etc. Default `ENUMS.Formation.Vehicle.Vee`. -- @return #AUFTRAG self function AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation) @@ -1816,18 +1800,20 @@ function AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation) mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.GROUNDATTACK) + -- Defaults. mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto + mission.optionAlarm=ENUMS.AlarmState.Auto mission.optionFormation="On Road" - mission.optionAttackFormation=Formation or "Wedge" - - mission.missionFraction=0.75 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or 20 + mission.missionFraction=0.70 + mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil mission.categories={AUFTRAG.Category.GROUND} mission.DCStask=mission:GetDCSMissionTask() - + + mission.DCStask.params.speed=Speed + mission.DCStask.params.formation=Formation or ENUMS.Formation.Vehicle.Vee + return mission end @@ -1836,10 +1822,11 @@ end -- @param Core.Set#SET_ZONE ZoneSet The recon zones. -- @param #number Speed Speed in knots. -- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL. --- @param #boolean Adinfinitum If true, the group will start over again after reaching the final zone. --- @param #boolean Randomly If true, the group will select a random zone. +-- @param #boolean Adinfinitum If `true`, the group will start over again after reaching the final zone. +-- @param #boolean Randomly If `true`, the group will select a random zone. +-- @param #string Formation Formation used during recon route. -- @return #AUFTRAG self -function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly) +function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly, Formation) local mission=AUFTRAG:New(AUFTRAG.Type.RECON) @@ -1860,12 +1847,7 @@ function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly) mission.DCStask=mission:GetDCSMissionTask() mission.DCStask.params.adinfinitum=Adinfinitum mission.DCStask.params.randomly=Randomly - - if Randomly then - local targets = mission.DCStask.params.target.targets -- Ops.Target#TARGET - local shuffled = UTILS.ShuffleTable(targets) - mission.DCStask.params.target.targets = shuffled - end + mission.DCStask.params.formation=Formation return mission end @@ -1978,7 +1960,6 @@ function AUFTRAG:NewARMOREDGUARD(Coordinate,Formation) mission.optionROE=ENUMS.ROE.OpenFire mission.optionAlarm=ENUMS.AlarmState.Auto mission.optionFormation=Formation or "On Road" - --mission.optionAttackFormation=Formation or "Wedge" mission.missionFraction=1.0 @@ -5118,28 +5099,6 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable) table.insert(DCStasks, DCStask) - elseif self.type==AUFTRAG.Type.ARMORATTACK then - - ------------------------- - -- ARMOR ATTACK Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.ARMORATTACK - - -- We create a "fake" DCS task and pass the parameters to the ARMYGROUP. - local param={} - param.zone=self:GetObjective() - param.tVec2=param.zone:GetVec2() - param.tzone=ZONE_RADIUS:New("ARMORATTACK-Zone-"..self.auftragsnummer,param.tVec2,1000) - param.action="Wedge" - param.speed=self.missionSpeed - - DCStask.params=param - - table.insert(DCStasks, DCStask) - elseif self.type==AUFTRAG.Type.GROUNDATTACK then --------------------------- diff --git a/Moose Development/Moose/Ops/Chief.lua b/Moose Development/Moose/Ops/Chief.lua index d9eea0efb..d261e3a30 100644 --- a/Moose Development/Moose/Ops/Chief.lua +++ b/Moose Development/Moose/Ops/Chief.lua @@ -2429,46 +2429,54 @@ function CHIEF:_GetMissionPerformanceFromTarget(Target) -- SEAD/DEAD table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.SEAD, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) elseif attribute==GROUP.Attribute.GROUND_EWR then -- EWR table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.SEAD, 100)) - --table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 90)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) elseif attribute==GROUP.Attribute.GROUND_AAA then -- AAA table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 40)) elseif attribute==GROUP.Attribute.GROUND_ARTILLERY then -- ARTY table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 75)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 70)) table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BOMBING, 70)) - table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARTY, 30)) - table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 75)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARTY, 30)) elseif attribute==GROUP.Attribute.GROUND_INFANTRY then -- Infantry - - table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 40)) elseif attribute==GROUP.Attribute.GROUND_TANK then -- Tanks - table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 75)) table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.CAS, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.ARMORATTACK, 40)) else table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.BAI, 100)) + table.insert(missionperf, self:_CreateMissionPerformance(AUFTRAG.Type.GROUNDATTACK, 50)) end diff --git a/Moose Development/Moose/Ops/Cohort.lua b/Moose Development/Moose/Ops/Cohort.lua index 2cdb30689..df1a3f284 100644 --- a/Moose Development/Moose/Ops/Cohort.lua +++ b/Moose Development/Moose/Ops/Cohort.lua @@ -45,7 +45,7 @@ -- @field #number cargobayLimit Cargo bay capacity in kg. -- @extends Core.Fsm#FSM ---- *It is unbelievable what a platoon of twelve aircraft did to tip the balance.* -- Adolf Galland +--- *It is unbelievable what a platoon of twelve aircraft did to tip the balance* -- Adolf Galland -- -- === -- diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index f8b69aea8..af59d7439 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -1201,7 +1201,7 @@ function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.SPAWNED) - if Element.unit:InAir(true) then + if Element.unit:InAir(not self.isHelo) then -- Setting check because of problems with helos dynamically spawned where inAir WRONGLY returned true if spawned at an airbase or farp! -- Trigger ElementAirborne event. Add a little delay because spawn is also delayed! self:__ElementAirborne(0.11, Element) else @@ -1531,6 +1531,12 @@ function FLIGHTGROUP:onafterParking(From, Event, To) -- Set current airbase. self.currbase=airbase + + -- Set homebase to current airbase if not defined yet. + -- This is necessary, e.g, when flights are spawned at an airbase because they do not have a takeoff waypoint. + if not self.homebase then + self.homebase=airbase + end -- Parking time stamp. self.Tparking=timer.getAbsTime() diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 4634143cc..edf9a8c85 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -3021,7 +3021,6 @@ function OPSGROUP:OnEventBirth(EventData) local group=EventData.IniGroup local unitname=EventData.IniUnitName - -- Set homebase if not already set. if self.isFlightgroup then @@ -3746,17 +3745,29 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) -- Target local target=Task.dcstask.params.target --Ops.Target#TARGET - self.lastindex=1 + + -- Init a table. + self.reconindecies={} + for i=1,#target.targets do + table.insert(self.reconindecies, i) + end + + local n=1 + if Task.dcstask.params.randomly then + n=UTILS.GetRandomTableElement(self.reconindecies) + else + table.remove(self.reconindecies, n) + end -- Target object and zone. - local object=target.targets[1] --Ops.Target#TARGET.Object + local object=target.targets[n] --Ops.Target#TARGET.Object local zone=object.Object --Core.Zone#ZONE -- Random coordinate in zone. local Coordinate=zone:GetRandomCoordinate() -- Speed and altitude. - local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise) + local Speed=Task.dcstask.params.speed and UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise) local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil --Coordinate:MarkToAll("Recon Waypoint Execute") @@ -3768,7 +3779,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) if self.isFlightgroup then wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude) elseif self.isArmygroup then - wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation) + wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Task.dcstask.params.formation) elseif self.isNavygroup then wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude) end @@ -3808,7 +3819,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) -- FLIGHTGROUP not implemented (intended!) for this AUFTRAG type. end - elseif Task.dcstask.id==AUFTRAG.SpecialTask.GROUNDATTACK then + elseif Task.dcstask.id==AUFTRAG.SpecialTask.GROUNDATTACK or Task.dcstask.id==AUFTRAG.SpecialTask.ARMORATTACK then --- -- Task "Ground Attack" Mission. @@ -3817,8 +3828,14 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) -- Engage target. local target=Task.dcstask.params.target --Ops.Target#TARGET + -- Set speed. Default max. + local speed=self.speedMax and UTILS.KmphToKnots(self.speedMax) or nil + if Task.dcstask.params.speed then + speed=Task.dcstask.params.speed + end + if target then - self:EngageTarget(target) + self:EngageTarget(target, speed, Task.dcstask.params.formation) end elseif Task.dcstask.id==AUFTRAG.SpecialTask.HOVER then @@ -3967,7 +3984,7 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task) done=true elseif Task.dcstask.id==AUFTRAG.SpecialTask.ONGUARD or Task.dcstask.id==AUFTRAG.SpecialTask.ARMOREDGUARD then done=true - elseif Task.dcstask.id==AUFTRAG.SpecialTask.GROUNDATTACK then + elseif Task.dcstask.id==AUFTRAG.SpecialTask.GROUNDATTACK or Task.dcstask.id==AUFTRAG.SpecialTask.ARMORATTACK then done=true elseif stopflag==1 or (not self:IsAlive()) or self:IsDead() or self:IsStopped() then -- Manual call TaskDone if setting flag to one was not successful. @@ -4744,20 +4761,6 @@ function OPSGROUP:RouteToMission(mission, delay) local zone=mission.engageTarget:GetObject() --Core.Zone#ZONE waypointcoord=zone:GetCoordinate() end - - local armorwaypointcoord = nil - if mission.type==AUFTRAG.Type.ARMORATTACK then - local target=mission.engageTarget:GetObject() -- Wrapper.Positionable#POSITIONABLE - --BASE:I({mission.DCStask}) - --BASE:I({mission.DCStask.params}) - --local zone = ZONE_RADIUS:New("AttackZone",target:GetVec2(),1000) - local zone = mission.DCStask.params.tzone -- Core.Zone#ZONE_RADIUS - -- final WP - waypointcoord=zone:GetRandomCoordinate(0, 100, surfacetypes) -- Core.Point#COORDINATE - -- Ingress - add formation to this one - armorwaypointcoord = zone:GetRandomCoordinate(1000, 500, surfacetypes) -- Core.Point#COORDINATE - self:__EngageTarget(2,target) - end -- Add enroute tasks. for _,task in pairs(mission.enrouteTasks) do @@ -4851,13 +4854,7 @@ function OPSGROUP:RouteToMission(mission, delay) if self:IsFlightgroup() then waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) elseif self:IsArmygroup() then - if mission.type==AUFTRAG.Type.ARMORATTACK then - waypoint=ARMYGROUP.AddWaypoint(self, armorwaypointcoord, SpeedToMission, uid, mission.optionFormation, false) - local attackformation = mission.optionAttackFormation or "Vee" - waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, nil, attackformation, false) - else - waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false) - end + waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false) elseif self:IsNavygroup() then waypoint=NAVYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.missionAltitude or self.altitudeCruise, false) end @@ -5107,7 +5104,6 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) -- Speed and altitude. local Speed=task.dcstask.params.speed and UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise) - -- local Speed=UTILS.KmphToKnots(speed or self.speedCruise) local Altitude=UTILS.MetersToFeet(task.dcstask.params.altitude or self.altitudeCruise) local currUID=self:GetWaypointCurrent().uid @@ -5130,11 +5126,24 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) -- TARGET. local target=task.dcstask.params.target --Ops.Target#TARGET - - local n=self.lastindex+1 - - if n<=#target.targets then - + + -- Init a table. + if self.adinfinitum and #self.reconindecies==0 then -- all targets done once + self.reconindecies={} + for i=1,#target.targets do + table.insert(self.reconindecies, i) + end + end + + if #self.reconindecies>0 then + + local n=1 + if task.dcstask.params.randomly then + n=UTILS.GetRandomTableElement(self.reconindecies) + else + table.remove(self.reconindecies, n) + end + -- Zone object. local object=target.targets[n] --Ops.Target#TARGET.Object local zone=object.Object --Core.Zone#ZONE @@ -5155,17 +5164,12 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) if self.isFlightgroup then wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude) elseif self.isArmygroup then - wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation) + wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, task.dcstask.params.formation) elseif self.isNavygroup then wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude) end wp.missionUID=mission and mission.auftragsnummer or nil - - -- Increase counter. - self.lastindex=self.lastindex+1 - if self.adinfinitum and n==#target.targets then -- all targets done once - self.lastindex = 1 - end + else -- Get waypoint index. diff --git a/Moose Development/Moose/Ops/Squadron.lua b/Moose Development/Moose/Ops/Squadron.lua index 22cd1f964..58e9a9257 100644 --- a/Moose Development/Moose/Ops/Squadron.lua +++ b/Moose Development/Moose/Ops/Squadron.lua @@ -48,15 +48,15 @@ -- @field #table parkingIDs Parking IDs for this squadron. -- @extends Ops.Cohort#COHORT ---- *It is unbelievable what a squadron of twelve aircraft did to tip the balance.* -- Adolf Galland +--- *It is unbelievable what a squadron of twelve aircraft did to tip the balance* -- Adolf Galland -- -- === -- --- ![Banner Image](..\Presentations\OPS\Squadron\_Main.png) --- -- # The SQUADRON Concept -- --- A SQUADRON is essential part of an AIRWING and consists of **one** type of aircraft. +-- A SQUADRON is essential part of an @{Ops.Airwing#AIRWING} and consists of **one** type of aircraft. +-- +-- -- -- -- diff --git a/Moose Development/Moose/Ops/Target.lua b/Moose Development/Moose/Ops/Target.lua index a71b5fed8..994ea64b2 100644 --- a/Moose Development/Moose/Ops/Target.lua +++ b/Moose Development/Moose/Ops/Target.lua @@ -1208,7 +1208,7 @@ function TARGET:GetCoordinate() end - self:E(self.lid..string.format("ERROR: Cannot get coordinate of target %s", self.name)) + self:E(self.lid..string.format("ERROR: Cannot get coordinate of target %s", tostring(self.name))) return nil end diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 12f8e7515..78ab74e58 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -1668,8 +1668,8 @@ function UTILS.GetOSTime() end --- Shuffle a table accoring to Fisher Yeates algorithm ---@param #table t Table to be shuffled ---@return #table +--@param #table t Table to be shuffled. +--@return #table Shuffled table. function UTILS.ShuffleTable(t) if t == nil or type(t) ~= "table" then BASE:I("Error in ShuffleTable: Missing or wrong type of Argument") @@ -1687,6 +1687,32 @@ function UTILS.ShuffleTable(t) return TempTable end +--- Get a random element of a table. +--@param #table t Table. +--@param #boolean replace If `true`, the drawn element is replaced, i.e. not deleted. +--@return #number Table element. +function UTILS.GetRandomTableElement(t, replace) + + if t == nil or type(t) ~= "table" then + BASE:I("Error in ShuffleTable: Missing or wrong type of Argument") + return + end + + math.random() + math.random() + math.random() + + local r=math.random(#t) + + local element=t[r] + + if not replace then + table.remove(t, r) + end + + return element +end + --- (Helicopter) Check if one loading door is open. --@param #string unit_name Unit name to be checked --@return #boolean Outcome - true if a (loading door) is open, false if not, nil if none exists.