mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
OPS
This commit is contained in:
parent
259b201e65
commit
1e6899c40b
@ -1187,11 +1187,6 @@ function ARMYGROUP:_InitGroup(Template)
|
||||
|
||||
-- Get template of group.
|
||||
local template=Template or self:_GetTemplate()
|
||||
|
||||
-- Define category.
|
||||
self.isAircraft=false
|
||||
self.isNaval=false
|
||||
self.isGround=true
|
||||
|
||||
-- Ground are always AI.
|
||||
self.isAI=true
|
||||
@ -1243,21 +1238,8 @@ function ARMYGROUP:_InitGroup(Template)
|
||||
self:_AddElementByName(unit:GetName())
|
||||
end
|
||||
|
||||
-- Get first unit. This is used to extract other parameters.
|
||||
local unit=units[1] --Wrapper.Unit#UNIT
|
||||
|
||||
if unit then
|
||||
|
||||
-- Get Descriptors.
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
-- Set type name.
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
end
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
-- @type BRIGADE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field Ops.General#GENERAL general The genral responsible for this brigade.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- Be surprised!
|
||||
@ -31,8 +30,7 @@
|
||||
-- @field #BRIGADE
|
||||
BRIGADE = {
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 3,
|
||||
genral = nil,
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
|
||||
@ -44,7 +42,7 @@ BRIGADE.version="0.0.1"
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
-- TODO: Add weapon range.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@ -89,13 +87,13 @@ function BRIGADE:AddPlatoon(Platoon)
|
||||
-- Add platoon to brigade.
|
||||
table.insert(self.cohorts, Platoon)
|
||||
|
||||
-- Add assets to squadron.
|
||||
-- Add assets to platoon.
|
||||
self:AddAssetToPlatoon(Platoon, Platoon.Ngroups)
|
||||
|
||||
-- Set airwing to squadron.
|
||||
-- Set brigade of platoon.
|
||||
Platoon:SetBrigade(self)
|
||||
|
||||
-- Start squadron.
|
||||
-- Start platoon.
|
||||
if Platoon:IsStopped() then
|
||||
Platoon:Start()
|
||||
end
|
||||
@ -114,7 +112,7 @@ function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
||||
|
||||
if Platoon then
|
||||
|
||||
-- Get the template group of the squadron.
|
||||
-- Get the template group of the platoon.
|
||||
local Group=GROUP:FindByName(Platoon.templatename)
|
||||
|
||||
if Group then
|
||||
@ -131,7 +129,7 @@ function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Squadron does not exit!")
|
||||
self:E(self.lid.."ERROR: Platoon does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
@ -148,20 +146,20 @@ end
|
||||
|
||||
--- Get platoon of an asset.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
-- @return Ops.Platoon#PLATOON The platoon object.
|
||||
function BRIGADE:GetPlatoonOfAsset(Asset)
|
||||
local platoon=self:GetPlatoon(Asset.squadname)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Remove asset from squadron.
|
||||
--- Remove asset from platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #BRIGADE.SquadronAsset Asset The squad asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
function BRIGADE:RemoveAssetFromPlatoon(Asset)
|
||||
local squad=self:GetPlatoonOfAsset(Asset)
|
||||
if squad then
|
||||
squad:DelAsset(Asset)
|
||||
local platoon=self:GetPlatoonOfAsset(Asset)
|
||||
if platoon then
|
||||
platoon:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
@ -188,9 +186,8 @@ function BRIGADE:onafterStatus(From, Event, To)
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
env.info("FF Brigade status "..fsmstate)
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
@ -198,13 +195,14 @@ function BRIGADE:onafterStatus(From, Event, To)
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Assets tot
|
||||
-- Asset count.
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
local assets=string.format("%d (OnMission: Total=%d, Active=%d, Queued=%d)", self:CountAssets(), Npq, Np, Nq)
|
||||
-- Asset string.
|
||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
||||
|
||||
-- Output.
|
||||
local text=string.format("%s: Missions=%d, Squads=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
local text=string.format("%s: Missions=%d, Platoons=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
@ -226,19 +224,19 @@ function BRIGADE:onafterStatus(From, Event, To)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Squadron Info --
|
||||
-- Platoon Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Platoons:"
|
||||
for i,_squadron in pairs(self.cohorts) do
|
||||
local squadron=_squadron --Ops.Squadron#SQUADRON
|
||||
for i,_platoon in pairs(self.cohorts) do
|
||||
local platoon=_platoon --Ops.Platoon#PLATOON
|
||||
|
||||
local callsign=squadron.callsignName and UTILS.GetCallsignName(squadron.callsignName) or "N/A"
|
||||
local modex=squadron.modex and squadron.modex or -1
|
||||
local skill=squadron.skill and tostring(squadron.skill) or "N/A"
|
||||
local callsign=platoon.callsignName and UTILS.GetCallsignName(platoon.callsignName) or "N/A"
|
||||
local modex=platoon.modex and platoon.modex or -1
|
||||
local skill=platoon.skill and tostring(platoon.skill) or "N/A"
|
||||
|
||||
-- Squadron text
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", squadron.name, squadron:GetState(), squadron.aircrafttype, squadron:CountAssets(true), #squadron.assets, callsign, modex, skill)
|
||||
-- Platoon text.
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", platoon.name, platoon:GetState(), platoon.aircrafttype, platoon:CountAssets(true), #platoon.assets, callsign, modex, skill)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
@ -783,109 +783,115 @@ end
|
||||
function COHORT:RecruitAssets(Mission, Npayloads)
|
||||
|
||||
-- Number of payloads available.
|
||||
Npayloads=Npayloads or self.legion:CountPayloadsInStock(Mission.type, self.aircrafttype, Mission.payloads)
|
||||
Npayloads=Npayloads or self.legion:CountPayloadsInStock(Mission.type, self.aircrafttype, Mission.payloads)
|
||||
|
||||
-- Recruited assets.
|
||||
local assets={}
|
||||
|
||||
-- Loop over assets.
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- First check that asset is not requested. This could happen if multiple requests are processed simultaniously.
|
||||
if not asset.requested then
|
||||
|
||||
-- Check if asset is currently on a mission (STARTED or QUEUED).
|
||||
if self.legion:IsAssetOnMission(asset) then
|
||||
|
||||
---
|
||||
-- Asset is already on a mission.
|
||||
---
|
||||
|
||||
-- Check if this asset is currently on a GCICAP mission (STARTED or EXECUTING).
|
||||
if self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
|
||||
-- Check if the payload of this asset is compatible with the mission.
|
||||
-- Note: we do not check the payload as an asset that is on a GCICAP mission should be able to do an INTERCEPT as well!
|
||||
self:I(self.lid.."Adding asset on GCICAP mission for an INTERCEPT mission")
|
||||
table.insert(assets, asset)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Asset as NO current mission
|
||||
---
|
||||
|
||||
if asset.spawned then
|
||||
|
||||
---
|
||||
-- Asset is already SPAWNED (could be uncontrolled on the airfield or inbound after another mission)
|
||||
---
|
||||
|
||||
local flightgroup=asset.flightgroup
|
||||
|
||||
-- Firstly, check if it has the right payload.
|
||||
if self:CheckMissionCapability(Mission.type, asset.payload.capabilities) and flightgroup and flightgroup:IsAlive() then
|
||||
|
||||
-- Assume we are ready and check if any condition tells us we are not.
|
||||
local combatready=true
|
||||
-- Check if asset is currently on a mission (STARTED or QUEUED).
|
||||
if self.legion:IsAssetOnMission(asset) then
|
||||
|
||||
if Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
combatready=flightgroup:CanAirToAir()
|
||||
else
|
||||
local excludeguns=Mission.type==AUFTRAG.Type.BOMBING or Mission.type==AUFTRAG.Type.BOMBRUNWAY or Mission.type==AUFTRAG.Type.BOMBCARPET or Mission.type==AUFTRAG.Type.SEAD or Mission.type==AUFTRAG.Type.ANTISHIP
|
||||
combatready=flightgroup:CanAirToGround(excludeguns)
|
||||
end
|
||||
---
|
||||
-- Asset is already on a mission.
|
||||
---
|
||||
|
||||
-- Check if this asset is currently on a GCICAP mission (STARTED or EXECUTING).
|
||||
if self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
|
||||
-- Check if the payload of this asset is compatible with the mission.
|
||||
-- Note: we do not check the payload as an asset that is on a GCICAP mission should be able to do an INTERCEPT as well!
|
||||
self:I(self.lid.."Adding asset on GCICAP mission for an INTERCEPT mission")
|
||||
table.insert(assets, asset)
|
||||
|
||||
-- No more attacks if fuel is already low. Safety first!
|
||||
if flightgroup:IsFuelLow() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- Check if in a state where we really do not want to fight any more.
|
||||
if flightgroup:IsFlightgroup() then
|
||||
if flightgroup:IsHolding() or flightgroup:IsLanding() or flightgroup:IsLanded() or flightgroup:IsArrived() then
|
||||
combatready=false
|
||||
end
|
||||
else
|
||||
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
|
||||
combatready=false
|
||||
end
|
||||
end
|
||||
-- Applies to all opsgroups.
|
||||
if flightgroup:IsDead() or flightgroup:IsStopped() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
|
||||
--TODO: Check transport for combat readyness!
|
||||
end
|
||||
|
||||
-- This asset is "combatready".
|
||||
if combatready then
|
||||
self:I(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||
table.insert(assets, asset)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Asset is still in STOCK
|
||||
---
|
||||
|
||||
-- Check that asset is not already requested for another mission.
|
||||
if Npayloads>0 and self:IsRepaired(asset) and (not asset.requested) then
|
||||
|
||||
-- Add this asset to the selection.
|
||||
table.insert(assets, asset)
|
||||
|
||||
-- Reduce number of payloads so we only return the number of assets that could do the job.
|
||||
Npayloads=Npayloads-1
|
||||
|
||||
end
|
||||
-- Asset as NO current mission
|
||||
---
|
||||
|
||||
if asset.spawned then
|
||||
|
||||
end
|
||||
end
|
||||
---
|
||||
-- Asset is already SPAWNED (could be uncontrolled on the airfield or inbound after another mission)
|
||||
---
|
||||
|
||||
local flightgroup=asset.flightgroup
|
||||
|
||||
-- Firstly, check if it has the right payload.
|
||||
if self:CheckMissionCapability(Mission.type, asset.payload.capabilities) and flightgroup and flightgroup:IsAlive() then
|
||||
|
||||
-- Assume we are ready and check if any condition tells us we are not.
|
||||
local combatready=true
|
||||
|
||||
if Mission.type==AUFTRAG.Type.INTERCEPT then
|
||||
combatready=flightgroup:CanAirToAir()
|
||||
else
|
||||
local excludeguns=Mission.type==AUFTRAG.Type.BOMBING or Mission.type==AUFTRAG.Type.BOMBRUNWAY or Mission.type==AUFTRAG.Type.BOMBCARPET or Mission.type==AUFTRAG.Type.SEAD or Mission.type==AUFTRAG.Type.ANTISHIP
|
||||
combatready=flightgroup:CanAirToGround(excludeguns)
|
||||
end
|
||||
|
||||
-- No more attacks if fuel is already low. Safety first!
|
||||
if flightgroup:IsFuelLow() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- Check if in a state where we really do not want to fight any more.
|
||||
if flightgroup:IsFlightgroup() then
|
||||
if flightgroup:IsHolding() or flightgroup:IsLanding() or flightgroup:IsLanded() or flightgroup:IsArrived() then
|
||||
combatready=false
|
||||
end
|
||||
else
|
||||
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
|
||||
combatready=false
|
||||
end
|
||||
end
|
||||
-- Applies to all opsgroups.
|
||||
if flightgroup:IsDead() or flightgroup:IsStopped() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
|
||||
--TODO: Check transport for combat readyness!
|
||||
|
||||
-- This asset is "combatready".
|
||||
if combatready then
|
||||
self:I(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||
table.insert(assets, asset)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- Asset is still in STOCK
|
||||
---
|
||||
|
||||
-- Check that we have payloads and asset is repaired.
|
||||
if Npayloads>0 and self:IsRepaired(asset) then
|
||||
|
||||
-- Add this asset to the selection.
|
||||
table.insert(assets, asset)
|
||||
|
||||
-- Reduce number of payloads so we only return the number of assets that could do the job.
|
||||
Npayloads=Npayloads-1
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end -- not requested check
|
||||
end -- loop over assets
|
||||
|
||||
return assets
|
||||
|
||||
@ -2612,7 +2612,11 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
||||
local Coord=self.group:GetCoordinate()
|
||||
|
||||
-- Set altitude: 1000 ft for helos and 10,000 ft for panes.
|
||||
Altitude=Altitude or (self.isHelo and 1000 or 10000)
|
||||
if Altitude then
|
||||
Altitude=UTILS.FeetToMeters(Altitude)
|
||||
else
|
||||
Altitude=self.altitudeCruise
|
||||
end
|
||||
|
||||
-- Set speed.
|
||||
Speed=Speed or (self.isHelo and 20 or 250)
|
||||
@ -2624,7 +2628,7 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
||||
--TODO: set ROE passive. introduce roe event/state/variable.
|
||||
|
||||
-- Orbit until flaghold=1 (true) but max 5 min if no FC is giving the landing clearance.
|
||||
local TaskOrbit = self.group:TaskOrbit(Coord, UTILS.FeetToMeters(Altitude), UTILS.KnotsToMps(Speed))
|
||||
local TaskOrbit = self.group:TaskOrbit(Coord, Altitude, UTILS.KnotsToMps(Speed))
|
||||
local TaskStop = self.group:TaskCondition(nil, nil, nil, nil, Duration)
|
||||
local TaskCntr = self.group:TaskControlled(TaskOrbit, TaskStop)
|
||||
local TaskOver = self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self)
|
||||
@ -3022,7 +3026,7 @@ function FLIGHTGROUP._FinishedWaiting(group, flightgroup)
|
||||
flightgroup.Twaiting=nil
|
||||
flightgroup.dTwait=nil
|
||||
|
||||
-- Trigger Holding event.
|
||||
-- Check group done.
|
||||
flightgroup:_CheckGroupDone(0.1)
|
||||
end
|
||||
|
||||
@ -3048,11 +3052,6 @@ function FLIGHTGROUP:_InitGroup(Template)
|
||||
-- Get template of group.
|
||||
local template=Template or self:_GetTemplate()
|
||||
|
||||
-- Define category.
|
||||
self.isAircraft=true
|
||||
self.isNaval=false
|
||||
self.isGround=false
|
||||
|
||||
-- Helo group.
|
||||
self.isHelo=group:IsHelicopter()
|
||||
|
||||
@ -3130,32 +3129,9 @@ function FLIGHTGROUP:_InitGroup(Template)
|
||||
self:_AddElementByName(unit:GetName())
|
||||
end
|
||||
|
||||
-- Get first unit. This is used to extract other parameters.
|
||||
local unit=units[1] --Wrapper.Unit#UNIT
|
||||
|
||||
if unit then
|
||||
|
||||
self.rangemax=unit:GetRange()
|
||||
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
self.ceiling=self.descriptors.Hmax
|
||||
|
||||
self.tankertype=select(2, unit:IsTanker())
|
||||
self.refueltype=select(2, unit:IsRefuelable())
|
||||
|
||||
--env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE))
|
||||
--env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE))
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: no unit in _InigGroup!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@ -1164,25 +1164,54 @@ end
|
||||
function LEGION:_CreateFlightGroup(asset)
|
||||
|
||||
-- Create flightgroup.
|
||||
local flightgroup=nil --Ops.OpsGroup#OPSGROUP
|
||||
local opsgroup=nil --Ops.OpsGroup#OPSGROUP
|
||||
|
||||
if self:IsAirwing() then
|
||||
flightgroup=FLIGHTGROUP:New(asset.spawngroupname)
|
||||
|
||||
---
|
||||
-- FLIGHTGROUP
|
||||
---
|
||||
|
||||
opsgroup=FLIGHTGROUP:New(asset.spawngroupname)
|
||||
|
||||
|
||||
elseif self:IsBrigade() then
|
||||
flightgroup=ARMYGROUP:New(asset.spawngroupname)
|
||||
|
||||
---
|
||||
-- ARMYGROUP
|
||||
---
|
||||
|
||||
opsgroup=ARMYGROUP:New(asset.spawngroupname)
|
||||
|
||||
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: not airwing or brigade!")
|
||||
end
|
||||
|
||||
-- Set legion.
|
||||
flightgroup:_SetLegion(self)
|
||||
opsgroup:_SetLegion(self)
|
||||
|
||||
-- Set cohort.
|
||||
flightgroup.cohort=self:_GetCohortOfAsset(asset)
|
||||
opsgroup.cohort=self:_GetCohortOfAsset(asset)
|
||||
|
||||
-- Set home base.
|
||||
flightgroup.homebase=self.airbase
|
||||
opsgroup.homebase=self.airbase
|
||||
|
||||
|
||||
return flightgroup
|
||||
-- Set weapon data.
|
||||
if opsgroup.cohort.weaponData then
|
||||
local text="Weapon data for group:"
|
||||
opsgroup.weaponData=opsgroup.weaponData or {}
|
||||
for bittype,_weapondata in pairs(opsgroup.cohort.weaponData) do
|
||||
local weapondata=_weapondata --Ops.OpsGroup#OPSGROUP.WeaponData
|
||||
opsgroup.weaponData[bittype]=UTILS.DeepCopy(weapondata) -- Careful with the units.
|
||||
text=text..string.format("\n- Bit=%s: Rmin=%.1f km, Rmax=%.1f km", bittype, weapondata.RangeMin/1000, weapondata.RangeMax/1000)
|
||||
end
|
||||
self:T3(self.lid..text)
|
||||
end
|
||||
|
||||
return opsgroup
|
||||
end
|
||||
|
||||
|
||||
|
||||
@ -1142,11 +1142,6 @@ function NAVYGROUP:_InitGroup(Template)
|
||||
-- Get template of group.
|
||||
local template=Template or self:_GetTemplate()
|
||||
|
||||
-- Define category.
|
||||
self.isAircraft=false
|
||||
self.isNaval=true
|
||||
self.isGround=false
|
||||
|
||||
--TODO: Submarine check
|
||||
--self.isSubmarine=self.group:IsSubmarine()
|
||||
|
||||
@ -1202,21 +1197,8 @@ function NAVYGROUP:_InitGroup(Template)
|
||||
self:_AddElementByName(unit:GetName())
|
||||
end
|
||||
|
||||
-- Get first unit. This is used to extract other parameters.
|
||||
local unit=units[1] --Wrapper.Unit#UNIT
|
||||
|
||||
if unit then
|
||||
|
||||
-- Get Descriptors.
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
-- Set type name.
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
end
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -20,18 +20,16 @@
|
||||
-- @field Wrapper.Group#GROUP group Group object.
|
||||
-- @field DCS#Controller controller The DCS controller of the group.
|
||||
-- @field DCS#Template template Template table of the group.
|
||||
-- @field #table elements Table of elements, i.e. units of the group.
|
||||
-- @field #boolean isLateActivated Is the group late activated.
|
||||
-- @field #boolean isUncontrolled Is the group uncontrolled.
|
||||
-- @field #boolean isFlightgroup Is a FLIGHTGROUP.
|
||||
-- @field #boolean isArmygroup Is an ARMYGROUP.
|
||||
-- @field #boolean isNavygroup Is a NAVYGROUP.
|
||||
-- @field #boolean isHelo If true, the is a helicopter group.
|
||||
-- @field #boolean isVTOL If true, the is capable of Vertical TakeOff and Landing (VTOL).
|
||||
-- @field #table elements Table of elements, i.e. units of the group.
|
||||
-- @field #boolean isHelo If true, this is a helicopter group.
|
||||
-- @field #boolean isVTOL If true, this is capable of Vertical TakeOff and Landing (VTOL).
|
||||
-- @field #boolean isSubmarine If true, this is a submarine group.
|
||||
-- @field #boolean isAI If true, group is purely AI.
|
||||
-- @field #boolean isAircraft If true, group is airplane or helicopter.
|
||||
-- @field #boolean isNaval If true, group is ships or submarine.
|
||||
-- @field #boolean isGround If true, group is some ground unit.
|
||||
-- @field #boolean isDestroyed If true, the whole group was destroyed.
|
||||
-- @field #boolean isDead If true, the whole group is dead.
|
||||
-- @field #table waypoints Table of waypoints.
|
||||
@ -504,6 +502,7 @@ function OPSGROUP:New(group)
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("OPSGROUP %s | ", tostring(self.groupname))
|
||||
|
||||
-- Check if group exists.
|
||||
if self.group then
|
||||
if not self:IsExist() then
|
||||
self:E(self.lid.."ERROR: GROUP does not exist! Returning nil")
|
||||
@ -517,6 +516,34 @@ function OPSGROUP:New(group)
|
||||
-- Set DCS group and controller.
|
||||
self.dcsgroup=self:GetDCSGroup()
|
||||
self.controller=self.dcsgroup:getController()
|
||||
|
||||
local units=self.group:GetUnits()
|
||||
if units then
|
||||
local masterunit=units[1] --Wrapper.Unit#UNIT
|
||||
|
||||
-- Get Descriptors.
|
||||
self.descriptors=masterunit:GetDesc()
|
||||
|
||||
-- Set type name.
|
||||
self.actype=masterunit:GetTypeName()
|
||||
|
||||
if self:IsFlightgroup() then
|
||||
|
||||
self.rangemax=masterunit:GetRange()
|
||||
|
||||
self.descriptors=masterunit:GetDesc()
|
||||
|
||||
self.ceiling=self.descriptors.Hmax
|
||||
|
||||
self.tankertype=select(2, masterunit:IsTanker())
|
||||
self.refueltype=select(2, masterunit:IsRefuelable())
|
||||
|
||||
--env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE))
|
||||
--env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Init set of detected units.
|
||||
self.detectedunits=SET_UNIT:New()
|
||||
@ -876,7 +903,7 @@ function OPSGROUP:AddWeaponRange(RangeMin, RangeMax, BitType)
|
||||
weapon.RangeMin=RangeMin
|
||||
|
||||
self.weaponData=self.weaponData or {}
|
||||
self.weaponData[weapon.BitType]=weapon
|
||||
self.weaponData[tostring(weapon.BitType)]=weapon
|
||||
|
||||
return self
|
||||
end
|
||||
@ -887,12 +914,12 @@ end
|
||||
-- @return #OPSGROUP.WeaponData Weapon range data.
|
||||
function OPSGROUP:GetWeaponData(BitType)
|
||||
|
||||
BitType=BitType or ENUMS.WeaponFlag.Auto
|
||||
BitType=tostring(BitType or ENUMS.WeaponFlag.Auto)
|
||||
|
||||
if self.weaponData[BitType] then
|
||||
return self.weaponData[BitType]
|
||||
else
|
||||
return self.weaponData[ENUMS.WeaponFlag.Auto]
|
||||
return self.weaponData[tostring(ENUMS.WeaponFlag.Auto)]
|
||||
end
|
||||
|
||||
end
|
||||
@ -3937,7 +3964,7 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
end
|
||||
|
||||
elseif mission.type==AUFTRAG.Type.ARTY then
|
||||
|
||||
|
||||
-- Get weapon range.
|
||||
local weapondata=self:GetWeaponData(mission.engageWeaponType)
|
||||
|
||||
@ -3959,8 +3986,9 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
|
||||
-- New waypoint coord.
|
||||
waypointcoord=self:GetCoordinate():Translate(d, heading)
|
||||
|
||||
self:T(self.lid..string.format("Out of max range = %.1f km for weapon %d", weapondata.RangeMax/1000, mission.engageWeaponType))
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Out of max range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(mission.engageWeaponType)))
|
||||
elseif dist<weapondata.RangeMin then
|
||||
|
||||
local d=(dist-weapondata.RangeMin)*1.1
|
||||
@ -3968,15 +3996,18 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
-- New waypoint coord.
|
||||
waypointcoord=self:GetCoordinate():Translate(d, heading)
|
||||
|
||||
self:T(self.lid..string.format("Out of min range = %.1f km for weapon %d", weapondata.RangeMax/1000, mission.engageWeaponType))
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Out of min range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(mission.engageWeaponType)))
|
||||
end
|
||||
|
||||
else
|
||||
self:T(self.lid..string.format("No weapon data for weapon type %s", tostring(mission.engageWeaponType)))
|
||||
end
|
||||
end
|
||||
|
||||
-- Formation.
|
||||
local formation=nil
|
||||
if self.isGround and mission.optionFormation then
|
||||
if self.isArmygroup and mission.optionFormation then
|
||||
formation=mission.optionFormation
|
||||
end
|
||||
|
||||
@ -4526,7 +4557,7 @@ function OPSGROUP:onbeforeLaserOn(From, Event, To, Target)
|
||||
|
||||
-- Height offset. No offset for aircraft. We take the height for ground or naval.
|
||||
local offsetY=0
|
||||
if self.isGround or self.isNaval then
|
||||
if self.isFlightgroup or self.isNavygroup then
|
||||
offsetY=element.height
|
||||
end
|
||||
|
||||
@ -6288,7 +6319,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
|
||||
end
|
||||
|
||||
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
|
||||
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, 200, false) ; waypoint.detour=1
|
||||
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, self.altitudeCruise, false) ; waypoint.detour=1
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Carrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone")
|
||||
@ -6660,7 +6691,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
|
||||
---
|
||||
|
||||
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
|
||||
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, 200, false) ; waypoint.detour=1
|
||||
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, self.altitudeCruise, false) ; waypoint.detour=1
|
||||
|
||||
-- Cancel landedAt task. This should trigger Cruise once airborne.
|
||||
if self:IsFlightgroup() and self:IsLandedAt() then
|
||||
@ -7870,14 +7901,20 @@ function OPSGROUP:Route(waypoints, delay)
|
||||
|
||||
if self:IsAlive() then
|
||||
|
||||
-- Clear all DCS tasks.
|
||||
-- Clear all DCS tasks. NOTE: This can make DCS crash!
|
||||
--self:ClearTasks()
|
||||
|
||||
-- Route (Mission) task.
|
||||
local TaskRoute=self.group:TaskRoute(waypoints)
|
||||
-- DCS mission task.
|
||||
local DCSTask = {
|
||||
id = 'Mission',
|
||||
params = {
|
||||
airborne = self:IsFlightgroup(),
|
||||
route={points=waypoints},
|
||||
},
|
||||
}
|
||||
|
||||
-- Set mission task.
|
||||
self:SetTask(TaskRoute)
|
||||
self:SetTask(DCSTask)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group is not alive! Cannot route group.")
|
||||
@ -7965,7 +8002,7 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid)
|
||||
opsgroup:T(opsgroup.lid..string.format("Next waypoint UID=%d index=%d", wpnext.uid, opsgroup:GetWaypointIndex(wpnext.uid)))
|
||||
|
||||
-- Set formation.
|
||||
if opsgroup.isGround then
|
||||
if opsgroup.isArmygroup then
|
||||
opsgroup.formation=wpnext.action
|
||||
end
|
||||
|
||||
@ -8733,7 +8770,7 @@ function OPSGROUP:SwitchFormation(Formation)
|
||||
|
||||
self.group:SetOption(AI.Option.Air.id.FORMATION, Formation)
|
||||
|
||||
elseif self.isGround then
|
||||
elseif self.isArmygroup then
|
||||
|
||||
-- Polymorphic and overwritten in ARMYGROUP.
|
||||
|
||||
@ -9684,6 +9721,38 @@ function OPSGROUP:_IsElement(unitname)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Count elements of the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #table States (Optional) Only count elements in specific states. Can also be a single state passed as #string.
|
||||
-- @return #number Number of elements.
|
||||
function OPSGROUP:CountElements(States)
|
||||
|
||||
if States then
|
||||
if type(States)=="string" then
|
||||
States={States}
|
||||
end
|
||||
else
|
||||
States=OPSGROUP.ElementStatus
|
||||
end
|
||||
|
||||
local IncludeDeads=true
|
||||
|
||||
local N=0
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --#OPSGROUP.Element
|
||||
if element and (IncludeDeads or element.status~=OPSGROUP.ElementStatus.DEAD) then
|
||||
for _,state in pairs(States) do
|
||||
if element.status==state then
|
||||
N=N+1
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Add a unit/element to the OPS group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string unitname Name of unit.
|
||||
|
||||
@ -46,7 +46,7 @@ PLATOON.version="0.0.1"
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
-- TODO: Add weapon data.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@ -60,7 +60,7 @@ PLATOON.version="0.0.1"
|
||||
-- @return #PLATOON self
|
||||
function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
-- Inherit everything from COHORT class.
|
||||
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, PlatoonName)) -- #PLATOON
|
||||
|
||||
|
||||
@ -107,7 +107,17 @@ function PLATOON:AddWeaponRange(RangeMin, RangeMax, BitType)
|
||||
weapon.RangeMin=RangeMin
|
||||
|
||||
self.weaponData=self.weaponData or {}
|
||||
self.weaponData[weapon.BitType]=weapon
|
||||
self.weaponData[tostring(weapon.BitType)]=weapon
|
||||
|
||||
-- Debug info.
|
||||
env.info(string.format("FF Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax))
|
||||
|
||||
local text="Weapon data:"
|
||||
for _,_weapondata in pairs(self.weaponData) do
|
||||
local weapondata=_weapondata
|
||||
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
|
||||
return self
|
||||
end
|
||||
@ -150,8 +160,8 @@ function PLATOON:onafterStatus(From, Event, To)
|
||||
local NassetsTot=#self.assets
|
||||
local NassetsInS=self:CountAssets(true)
|
||||
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||
if self.brigade then
|
||||
NassetsQP, NassetsP, NassetsQ=self.brigade:CountAssetsOnMission(nil, self)
|
||||
if self.legion then
|
||||
NassetsQP, NassetsP, NassetsQ=self.legion:CountAssetsOnMission(nil, self)
|
||||
end
|
||||
|
||||
-- Short info.
|
||||
@ -159,6 +169,16 @@ function PLATOON:onafterStatus(From, Event, To)
|
||||
fsmstate, self.aircrafttype, callsign, modex, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Weapon data info.
|
||||
if self.weaponData then
|
||||
local text="Weapon Data:"
|
||||
for bit,_weapondata in pairs(self.weaponData) do
|
||||
local weapondata=_weapondata --Ops.OpsGroup#OPSGROUP.WeaponData
|
||||
text=text..string.format("\n- Bit=%s: Rmin=%.1f km, Rmax=%.1f km", bit, weapondata.RangeMin/1000, weapondata.RangeMax/1000)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Check if group has detected any units.
|
||||
self:_CheckAssetStatus()
|
||||
|
||||
|
||||
@ -2022,22 +2022,20 @@ do -- Patrol methods
|
||||
end
|
||||
|
||||
|
||||
--- Return a Misson task to follow a given route defined by Points.
|
||||
--- Return a "Misson" task to follow a given route defined by Points.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #table Points A table of route points.
|
||||
-- @return DCS#Task
|
||||
-- @return DCS#Task DCS mission task. Has entries `.id="Mission"`, `params`, were params has entries `airborne` and `route`, which is a table of `points`.
|
||||
function CONTROLLABLE:TaskRoute( Points )
|
||||
self:F2( Points )
|
||||
|
||||
local DCSTask = {
|
||||
id = 'Mission',
|
||||
params = {
|
||||
airborne = self:IsAir(),
|
||||
airborne = self:IsAir(), -- This is important to make aircraft land without respawning them (which was a long standing DCS issue).
|
||||
route = {points = Points},
|
||||
},
|
||||
}
|
||||
|
||||
self:T3( { DCSTask } )
|
||||
|
||||
return DCSTask
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user