mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
OPS
- Added Cohort and Legion classes - Added Platoon and Brigade classes
This commit is contained in:
parent
629c5e7739
commit
86bb256bf1
@ -1623,6 +1623,10 @@ WAREHOUSE = {
|
||||
-- @field #number rid The request ID of this asset.
|
||||
-- @field #boolean arrived If true, asset arrived at its destination.
|
||||
-- @field #number damage Damage of asset group in percent.
|
||||
-- @field Ops.AirWing#AIRWING.Payload payload The payload of the asset.
|
||||
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup object.
|
||||
-- @field #string squadname Name of the squadron this asset belongs to.
|
||||
-- @field #number Treturned Time stamp when asset returned to the airwing.
|
||||
|
||||
--- Item of the warehouse queue table.
|
||||
-- @type WAREHOUSE.Queueitem
|
||||
@ -1842,8 +1846,8 @@ WAREHOUSE.version="1.0.2"
|
||||
|
||||
--- The WAREHOUSE constructor. Creates a new WAREHOUSE object from a static object. Parameters like the coalition and country are taken from the static object structure.
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param Wrapper.Static#STATIC warehouse The physical structure representing the warehouse.
|
||||
-- @param #string alias (Optional) Alias of the warehouse, i.e. the name it will be called when sending messages etc. Default is the name of the static
|
||||
-- @param Wrapper.Static#STATIC warehouse The physical structure representing the warehouse. Can also be a @{Wrapper.Unit#UNIT}.
|
||||
-- @param #string alias (Optional) Alias of the warehouse, i.e. the name it will be called when sending messages etc. Default is the name of the static/unit representing the warehouse.
|
||||
-- @return #WAREHOUSE self
|
||||
function WAREHOUSE:New(warehouse, alias)
|
||||
|
||||
|
||||
@ -81,8 +81,12 @@ __Moose.Include( 'Scripts/Moose/Ops/OpsGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/FlightGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/NavyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ArmyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Cohort.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Platoon.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Legion.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Brigade.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Intelligence.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/WingCommander.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ChiefOfStaff.lua' )
|
||||
|
||||
@ -125,10 +125,6 @@ AIRWING = {
|
||||
|
||||
--- Squadron asset.
|
||||
-- @type AIRWING.SquadronAsset
|
||||
-- @field #AIRWING.Payload payload The payload of the asset.
|
||||
-- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup object.
|
||||
-- @field #string squadname Name of the squadron this asset belongs to.
|
||||
-- @field #number Treturned Time stamp when asset returned to the airwing.
|
||||
-- @extends Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
--- Payload data.
|
||||
@ -251,7 +247,7 @@ function AIRWING:New(warehousename, airwingname)
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.Squadron#SQUADRON Squadron The asset squadron.
|
||||
-- @param #AIRWING.SquadronAsset Asset The asset that returned.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||
|
||||
return self
|
||||
end
|
||||
@ -513,7 +509,7 @@ end
|
||||
|
||||
--- Return payload from asset back to stock.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset asset The squadron asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The squadron asset.
|
||||
function AIRWING:ReturnPayloadFromAsset(asset)
|
||||
|
||||
local payload=asset.payload
|
||||
@ -596,7 +592,7 @@ end
|
||||
|
||||
--- Get squadron of an asset.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset Asset The squadron asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The squadron asset.
|
||||
-- @return Ops.Squadron#SQUADRON The squadron object.
|
||||
function AIRWING:GetSquadronOfAsset(Asset)
|
||||
return self:GetSquadron(Asset.squadname)
|
||||
@ -604,7 +600,7 @@ end
|
||||
|
||||
--- Remove asset from squadron.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset Asset The squad asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The squad asset.
|
||||
function AIRWING:RemoveAssetFromSquadron(Asset)
|
||||
local squad=self:GetSquadronOfAsset(Asset)
|
||||
if squad then
|
||||
@ -908,7 +904,7 @@ function AIRWING:onafterStatus(From, Event, To)
|
||||
local skill=squadron.skill and tostring(squadron.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:CountAssetsInStock(), #squadron.assets, callsign, modex, skill)
|
||||
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)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
@ -1105,7 +1101,7 @@ end
|
||||
--- Check how many AWACS missions are assigned and add number of missing missions.
|
||||
-- @param #AIRWING self
|
||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup.
|
||||
-- @return #AIRWING.SquadronAsset The tanker asset.
|
||||
-- @return Functional.Warehouse#WAREHOUSE.Assetitem The tanker asset.
|
||||
function AIRWING:GetTankerForFlight(flightgroup)
|
||||
|
||||
local tankers=self:GetAssetsOnMission(AUFTRAG.Type.TANKER)
|
||||
@ -1114,7 +1110,7 @@ function AIRWING:GetTankerForFlight(flightgroup)
|
||||
|
||||
local tankeropt={}
|
||||
for _,_tanker in pairs(tankers) do
|
||||
local tanker=_tanker --#AIRWING.SquadronAsset
|
||||
local tanker=_tanker --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Check that donor and acceptor use the same refuelling system.
|
||||
if flightgroup.refueltype and flightgroup.refueltype==tanker.flightgroup.tankertype then
|
||||
@ -1214,7 +1210,7 @@ function AIRWING:_GetNextMission()
|
||||
local remove={}
|
||||
local gotpayload={}
|
||||
for i=1,#assets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
local asset=assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Get payload for the asset.
|
||||
if not asset.payload then
|
||||
@ -1231,7 +1227,7 @@ function AIRWING:_GetNextMission()
|
||||
|
||||
-- Now remove assets for which we don't have a payload.
|
||||
for i=#assets,1,-1 do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
local asset=assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
for _,uid in pairs(remove) do
|
||||
if uid==asset.uid then
|
||||
table.remove(assets, i)
|
||||
@ -1255,7 +1251,7 @@ function AIRWING:_GetNextMission()
|
||||
|
||||
-- Assign assets to mission.
|
||||
for i=1,mission.nassets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
local asset=assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Should not happen as we just checked!
|
||||
if not asset.payload then
|
||||
@ -1268,7 +1264,7 @@ function AIRWING:_GetNextMission()
|
||||
|
||||
-- Now return the remaining payloads.
|
||||
for i=mission.nassets+1,#assets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
local asset=assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
for _,uid in pairs(gotpayload) do
|
||||
if uid==asset.uid then
|
||||
self:ReturnPayloadFromAsset(asset)
|
||||
@ -1288,7 +1284,7 @@ end
|
||||
|
||||
--- Calculate the mission score of an asset.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset asset Asset
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset Asset
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission Mission for which the best assets are desired.
|
||||
-- @param #boolean includePayload If true, include the payload in the calulation if the asset has one attached.
|
||||
-- @return #number Mission score.
|
||||
@ -1351,7 +1347,7 @@ function AIRWING:_OptimizeAssetSelection(assets, Mission, includePayload)
|
||||
local distmin=math.huge
|
||||
local distmax=0
|
||||
for _,_asset in pairs(assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if asset.spawned then
|
||||
local group=GROUP:FindByName(asset.spawngroupname)
|
||||
@ -1373,15 +1369,15 @@ function AIRWING:_OptimizeAssetSelection(assets, Mission, includePayload)
|
||||
|
||||
-- Calculate the mission score of all assets.
|
||||
for _,_asset in pairs(assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
--self:I(string.format("FF asset %s has payload %s", asset.spawngroupname, asset.payload and "yes" or "no!"))
|
||||
asset.score=self:CalculateAssetMissionScore(asset, Mission, includePayload)
|
||||
end
|
||||
|
||||
--- Sort assets wrt to their mission score. Higher is better.
|
||||
local function optimize(a, b)
|
||||
local assetA=a --#AIRWING.SquadronAsset
|
||||
local assetB=b --#AIRWING.SquadronAsset
|
||||
local assetA=a --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
local assetB=b --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Higher score wins. If equal score ==> closer wins.
|
||||
-- TODO: Need to include the distance in a smarter way!
|
||||
@ -1392,7 +1388,7 @@ function AIRWING:_OptimizeAssetSelection(assets, Mission, includePayload)
|
||||
-- Remove distance parameter.
|
||||
local text=string.format("Optimized assets for %s mission (payload=%s):", Mission.type, tostring(includePayload))
|
||||
for i,Asset in pairs(assets) do
|
||||
local asset=Asset --#AIRWING.SquadronAsset
|
||||
local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
text=text..string.format("\n%s %s: score=%d, distance=%.1f km", asset.squadname, asset.spawngroupname, asset.score, asset.dist/1000)
|
||||
asset.dist=nil
|
||||
asset.score=nil
|
||||
@ -1425,7 +1421,7 @@ function AIRWING:onafterMissionRequest(From, Event, To, Mission)
|
||||
local Assetlist={}
|
||||
|
||||
for _,_asset in pairs(Mission.assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if asset.spawned then
|
||||
|
||||
@ -1452,7 +1448,7 @@ function AIRWING:onafterMissionRequest(From, Event, To, Mission)
|
||||
|
||||
--local text=string.format("Requesting assets for mission %s:", Mission.name)
|
||||
for i,_asset in pairs(Assetlist) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Set asset to requested! Important so that new requests do not use this asset!
|
||||
asset.requested=true
|
||||
@ -1493,7 +1489,7 @@ function AIRWING:onafterMissionCancel(From, Event, To, Mission)
|
||||
else
|
||||
|
||||
for _,_asset in pairs(Mission.assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
local flightgroup=asset.flightgroup
|
||||
|
||||
@ -1519,7 +1515,7 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AIRWING.SquadronAsset asset The asset that has just been added.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset that has just been added.
|
||||
-- @param #string assignment The (optional) assignment for the asset.
|
||||
function AIRWING:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
|
||||
@ -1604,7 +1600,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.Squadron#SQUADRON Squadron The asset squadron.
|
||||
-- @param #AIRWING.SquadronAsset Asset The asset that returned.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||
function AIRWING:onafterSquadAssetReturned(From, Event, To, Squadron, Asset)
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Asset %s from squadron %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Squadron.name, tostring(Asset.assignment)))
|
||||
@ -1634,7 +1630,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Group#GROUP group The group spawned.
|
||||
-- @param #AIRWING.SquadronAsset asset The asset that was spawned.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset that was spawned.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Pendingitem request The request of the dead asset.
|
||||
function AIRWING:onafterAssetSpawned(From, Event, To, group, asset, request)
|
||||
|
||||
@ -1731,7 +1727,7 @@ end
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AIRWING.SquadronAsset asset The asset that is dead.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset that is dead.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Pendingitem request The request of the dead asset.
|
||||
function AIRWING:onafterAssetDead(From, Event, To, asset, request)
|
||||
|
||||
@ -1793,7 +1789,7 @@ function AIRWING:onafterRequest(From, Event, To, Request)
|
||||
if Mission and assets then
|
||||
|
||||
for _,_asset in pairs(assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
-- This would be the place to modify the asset table before the asset is spawned.
|
||||
end
|
||||
|
||||
@ -1820,7 +1816,7 @@ function AIRWING:onafterSelfRequest(From, Event, To, groupset, request)
|
||||
local mission=self:GetMissionByID(request.assignment)
|
||||
|
||||
for _,_asset in pairs(request.assets) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
end
|
||||
|
||||
for _,_group in pairs(groupset:GetSet()) do
|
||||
@ -1835,7 +1831,7 @@ end
|
||||
|
||||
--- Create a new flight group after an asset was spawned.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset asset The asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset.
|
||||
-- @return Ops.FlightGroup#FLIGHTGROUP The created flightgroup object.
|
||||
function AIRWING:_CreateFlightGroup(asset)
|
||||
|
||||
@ -1857,7 +1853,7 @@ end
|
||||
|
||||
--- Check if an asset is currently on a mission (STARTED or EXECUTING).
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset asset The asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset.
|
||||
-- @param #table MissionTypes Types on mission to be checked. Default all.
|
||||
-- @return #boolean If true, asset has at least one mission of that type in the queue.
|
||||
function AIRWING:IsAssetOnMission(asset, MissionTypes)
|
||||
@ -1900,7 +1896,7 @@ function AIRWING:IsAssetOnMission(asset, MissionTypes)
|
||||
|
||||
if mission:IsNotOver() then
|
||||
for _,_asset in pairs(mission.assets) do
|
||||
local sqasset=_asset --#AIRWING.SquadronAsset
|
||||
local sqasset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if sqasset.uid==asset.uid then
|
||||
return true
|
||||
@ -1917,7 +1913,7 @@ end
|
||||
|
||||
--- Get the current mission of the asset.
|
||||
-- @param #AIRWING self
|
||||
-- @param #AIRWING.SquadronAsset asset The asset.
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset.
|
||||
-- @return Ops.Auftrag#AUFTRAG Current mission or *nil*.
|
||||
function AIRWING:GetAssetCurrentMission(asset)
|
||||
|
||||
@ -2026,33 +2022,19 @@ function AIRWING:CountMissionsInQueue(MissionTypes)
|
||||
return N
|
||||
end
|
||||
|
||||
--- Count total number of assets. This is the sum of all squadron assets.
|
||||
-- @param #AIRWING self
|
||||
-- @return #number Amount of asset groups.
|
||||
function AIRWING:CountAssets()
|
||||
|
||||
local N=0
|
||||
|
||||
for _,_squad in pairs(self.squadrons) do
|
||||
local squad=_squad --Ops.Squadron#SQUADRON
|
||||
N=N+#squad.assets
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
|
||||
--- Count total number of assets that are in the warehouse stock (not spawned).
|
||||
-- @param #AIRWING self
|
||||
-- @param #boolean InStock If true, only assets that are in the warehouse stock/inventory are counted.
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Amount of asset groups in stock.
|
||||
function AIRWING:CountAssetsInStock(MissionTypes)
|
||||
function AIRWING:CountAssets(InStock, MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
|
||||
for _,_squad in pairs(self.squadrons) do
|
||||
local squad=_squad --Ops.Squadron#SQUADRON
|
||||
N=N+squad:CountAssetsInStock(MissionTypes)
|
||||
N=N+squad:CountAssets(InStock, MissionTypes, Attributes)
|
||||
end
|
||||
|
||||
return N
|
||||
@ -2077,7 +2059,7 @@ function AIRWING:CountAssetsOnMission(MissionTypes, Squadron)
|
||||
if self:CheckMissionType(mission.type, MissionTypes or AUFTRAG.Type) then
|
||||
|
||||
for _,_asset in pairs(mission.assets or {}) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if Squadron==nil or Squadron.name==asset.squadname then
|
||||
|
||||
@ -2115,7 +2097,7 @@ function AIRWING:GetAssetsOnMission(MissionTypes)
|
||||
if self:CheckMissionType(mission.type, MissionTypes) then
|
||||
|
||||
for _,_asset in pairs(mission.assets or {}) do
|
||||
local asset=_asset --#AIRWING.SquadronAsset
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
table.insert(assets, asset)
|
||||
|
||||
|
||||
@ -1224,8 +1224,10 @@ 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.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude)
|
||||
function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.RECON)
|
||||
|
||||
@ -1240,6 +1242,8 @@ function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude)
|
||||
mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or UTILS.FeetToMeters(2000)
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
mission.DCStask.params.adinfitum=Adinfinitum
|
||||
mission.DCStask.params.randomly=Randomly
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
273
Moose Development/Moose/Ops/Brigade.lua
Normal file
273
Moose Development/Moose/Ops/Brigade.lua
Normal file
@ -0,0 +1,273 @@
|
||||
--- **Ops** - Brigade Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage platoons
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- @module Ops.Brigade
|
||||
-- @image OPS_Brigade.png
|
||||
|
||||
|
||||
--- BRIGADE class.
|
||||
-- @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!
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The BRIGADE Concept
|
||||
--
|
||||
-- An BRIGADE consists of multiple PLATOONS. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
--
|
||||
-- @field #BRIGADE
|
||||
BRIGADE = {
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 3,
|
||||
genral = nil,
|
||||
}
|
||||
|
||||
|
||||
--- BRIGADE class version.
|
||||
-- @field #string version
|
||||
BRIGADE.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new BRIGADE class object.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
||||
-- @param #string BrigadeName Name of the brigade.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:New(WarehouseName, BrigadeName)
|
||||
|
||||
-- Inherit everything from LEGION class.
|
||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, BrigadeName)) -- #BRIGADE
|
||||
|
||||
-- Nil check.
|
||||
if not self then
|
||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("BRIGADE %s | ", self.alias)
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "PlatoonOnMission", "*") -- Add a (mission) request to the warehouse.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a platoon to the brigade.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddPlatoon(Platoon)
|
||||
|
||||
-- Add squadron to airwing.
|
||||
table.insert(self.cohorts, Platoon)
|
||||
|
||||
-- Add assets to squadron.
|
||||
self:AddAssetToPlatoon(Platoon, Platoon.Ngroups)
|
||||
|
||||
-- Set airwing to squadron.
|
||||
Platoon:SetBrigade(self)
|
||||
|
||||
-- Start squadron.
|
||||
if Platoon:IsStopped() then
|
||||
Platoon:Start()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Add asset group(s) to platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @param #number Nassets Number of asset groups to add.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
||||
|
||||
if Platoon then
|
||||
|
||||
-- Get the template group of the squadron.
|
||||
local Group=GROUP:FindByName(Platoon.templatename)
|
||||
|
||||
if Group then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to platoon %s", Group:GetName(), Platoon.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Platoon.skill, Platoon.livery, Platoon.name)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group does not exist!")
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Squadron does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get platoon by name.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string PlatoonName Name of the platoon.
|
||||
-- @return Ops.Platoon#PLATOON The Platoon object.
|
||||
function BRIGADE:GetPlatoon(PlatoonName)
|
||||
|
||||
local platoon=self:_GetCohort(PlatoonName)
|
||||
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Get platoon of an asset.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
-- @return Ops.Platoon#PLATOON The platoon object.
|
||||
function BRIGADE:GetSquadronOfAsset(Asset)
|
||||
local platoon=self:GetPlatoon(Asset.squadname)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Remove asset from squadron.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #BRIGADE.SquadronAsset Asset The squad asset.
|
||||
function BRIGADE:RemoveAssetFromSquadron(Asset)
|
||||
local squad=self:GetSquadronOfAsset(Asset)
|
||||
if squad then
|
||||
squad:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start BRIGADE FSM.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self, BRIGADE).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting BRIGADE v%s", BRIGADE.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
env.info("FF Brigade status "..fsmstate)
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Assets tot
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
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)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Mission Info --
|
||||
------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.nassets)
|
||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
||||
|
||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Squadron Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Platoons:"
|
||||
for i,_squadron in pairs(self.cohorts) do
|
||||
local squadron=_squadron --Ops.Squadron#SQUADRON
|
||||
|
||||
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"
|
||||
|
||||
-- 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)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
--------------
|
||||
-- Mission ---
|
||||
--------------
|
||||
|
||||
-- Check if any missions should be cancelled.
|
||||
self:_CheckMissions()
|
||||
|
||||
-- Get next mission.
|
||||
local mission=self:_GetNextMission()
|
||||
|
||||
-- Request mission execution.
|
||||
if mission then
|
||||
self:MissionRequest(mission)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -66,6 +66,19 @@ CHIEF.DEFCON = {
|
||||
RED="Red",
|
||||
}
|
||||
|
||||
--- Strategy.
|
||||
-- @type CHIEF.Strategy
|
||||
-- @field #string DEFENSIVE Only target in our own terretory are engaged.
|
||||
-- @field #string OFFENSIVE Targets in own terretory and yellow zones are engaged.
|
||||
-- @field #string AGGRESSIVE Targets in own terretroy, yellow zones and engage zones are engaged.
|
||||
-- @field #string TOTALWAR Anything is engaged anywhere.
|
||||
CHIEF.Strategy = {
|
||||
DEFENSIVE="Defensive",
|
||||
OFFENSIVE="Offensive",
|
||||
AGGRESSIVE="Aggressive",
|
||||
TOTALWAR="Total War"
|
||||
}
|
||||
|
||||
--- CHIEF class version.
|
||||
-- @field #string version
|
||||
CHIEF.version="0.0.1"
|
||||
@ -74,6 +87,10 @@ CHIEF.version="0.0.1"
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Get list of own assets and capabilities.
|
||||
-- TODO: Get list/overview of enemy assets etc.
|
||||
-- TODO: Put all contacts into target list. Then make missions from them.
|
||||
-- TODO: Set of interesting zones.
|
||||
-- TODO: Define A2A and A2G parameters.
|
||||
-- DONE: Add/remove spawned flightgroups to detection set.
|
||||
-- DONE: Borderzones.
|
||||
@ -113,6 +130,8 @@ function CHIEF:New(AgentSet, Coalition)
|
||||
|
||||
self:AddTransition("*", "Defcon", "*") -- Change defence condition.
|
||||
|
||||
self:AddTransition("*", "Stategy", "*") -- Change strategy condition.
|
||||
|
||||
self:AddTransition("*", "DeclareWar", "*") -- Declare War.
|
||||
|
||||
------------------------
|
||||
@ -393,6 +412,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
||||
|
||||
if contact.mission and contact.mission:IsNotOver() then
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Lost contact to target %s! %s mission %s will be cancelled.", contact.groupname, contact.mission.type:upper(), contact.mission.name)
|
||||
MESSAGE:New(text, 120, "CHIEF"):ToAll()
|
||||
self:I(self.lid..text)
|
||||
@ -473,16 +493,48 @@ function CHIEF:onafterStatus(From, Event, To)
|
||||
-- Check mission queue and assign one PLANNED mission.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
local text=string.format("Defcon=%s Missions=%d, Contacts: Total=%d Yellow=%d Red=%d", self.Defcon, #self.missionqueue, #self.Contacts, Nyellow, Nred)
|
||||
---
|
||||
-- Mission Queue
|
||||
---
|
||||
|
||||
local Nassets=self.wingcommander:CountAssets()
|
||||
|
||||
local text=string.format("Defcon=%s Assets=%d, Missions=%d, Contacts: Total=%d Yellow=%d Red=%d", self.Defcon, Nassets, #self.missionqueue, #self.Contacts, Nyellow, Nred)
|
||||
self:I(self.lid..text)
|
||||
|
||||
---
|
||||
-- Assets
|
||||
---
|
||||
|
||||
local text="Assets:"
|
||||
for _,missiontype in pairs(AUFTRAG.Type) do
|
||||
local N=self.wingcommander:CountAssets(nil, missiontype)
|
||||
if N>0 then
|
||||
text=text..string.format("\n- %s %d", missiontype, N)
|
||||
end
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
local text="Assets:"
|
||||
for _,attribute in pairs(WAREHOUSE.Attribute) do
|
||||
local N=self.wingcommander:CountAssets(nil, nil, attribute)
|
||||
if N>0 or self.verbose>=10 then
|
||||
text=text..string.format("\n- %s %d", attribute, N)
|
||||
end
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
|
||||
---
|
||||
-- Target Queue
|
||||
---
|
||||
|
||||
for _,_target in pairs(self.targetqueue) do
|
||||
if #self.targetqueue>0 then
|
||||
local text="Targets:"
|
||||
for i,_target in pairs(self.targetqueue) do
|
||||
local target=_target --Ops.Target#TARGET
|
||||
|
||||
text=text..string.format("\n[%d] %s: Category=%s, alive=%s [%.1f/%.1f]", i, target:GetName(), target.category, tostring(target:IsAlive()), target:GetLife(), target:GetLife0())
|
||||
|
||||
|
||||
if target:IsAlive() then
|
||||
|
||||
if self:CheckTargetInZones(target, self.borderzoneset) then
|
||||
@ -492,6 +544,8 @@ function CHIEF:onafterStatus(From, Event, To)
|
||||
end
|
||||
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
---
|
||||
-- Contacts
|
||||
|
||||
992
Moose Development/Moose/Ops/Cohort.lua
Normal file
992
Moose Development/Moose/Ops/Cohort.lua
Normal file
@ -0,0 +1,992 @@
|
||||
--- **Ops** - Cohort encompassed all characteristics of SQUADRONs, PLATOONs and FLOTILLAs.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all platoon members.
|
||||
-- * Define modex and callsigns.
|
||||
-- * Define mission types, this platoon can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause platoon operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Cohort
|
||||
-- @image OPS_Cohort.png
|
||||
|
||||
|
||||
--- COHORT class.
|
||||
-- @type COHORT
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #string name Name of the platoon.
|
||||
-- @field #string templatename Name of the template group.
|
||||
-- @field #string aircrafttype Type of the airframe the platoon is using.
|
||||
-- @field Wrapper.Group#GROUP templategroup Template group.
|
||||
-- @field #table assets Cohort assets.
|
||||
-- @field #table missiontypes Capabilities (mission types and performances) of the platoon.
|
||||
-- @field #number maintenancetime Time in seconds needed for maintenance of a returned flight.
|
||||
-- @field #number repairtime Time in seconds for each
|
||||
-- @field #string livery Livery of the platoon.
|
||||
-- @field #number skill Skill of platoon members.
|
||||
-- @field Ops.Legion#LEGION legion The LEGION object the cohort belongs to.
|
||||
-- @field #number Ngroups Number of asset flight groups this platoon has.
|
||||
-- @field #number engageRange Mission range in meters.
|
||||
-- @field #string attribute Generalized attribute of the platoon template group.
|
||||
-- @field #table tacanChannel List of TACAN channels available to the platoon.
|
||||
-- @field #number radioFreq Radio frequency in MHz the cohort uses.
|
||||
-- @field #number radioModu Radio modulation the cohort uses.
|
||||
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *It is unbelievable what a platoon of twelve aircraft did to tip the balance.* -- Adolf Galland
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The COHORT Concept
|
||||
--
|
||||
-- A COHORT is essential part of an BRIGADE and consists of **one** type of aircraft.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #COHORT
|
||||
COHORT = {
|
||||
ClassName = "COHORT",
|
||||
verbose = 0,
|
||||
lid = nil,
|
||||
name = nil,
|
||||
templatename = nil,
|
||||
assets = {},
|
||||
missiontypes = {},
|
||||
repairtime = 0,
|
||||
maintenancetime= 0,
|
||||
livery = nil,
|
||||
skill = nil,
|
||||
legion = nil,
|
||||
Ngroups = nil,
|
||||
engageRange = nil,
|
||||
tacanChannel = {},
|
||||
}
|
||||
|
||||
--- COHORT class version.
|
||||
-- @field #string version
|
||||
COHORT.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
-- TODO: Make general so that PLATOON and SQUADRON can inherit this class.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new COHORT object and start the FSM.
|
||||
-- @param #COHORT self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this platoon. Default 3.
|
||||
-- @param #string CohortName Name of the platoon, e.g. "VFA-37".
|
||||
-- @return #COHORT self
|
||||
function COHORT:New(TemplateGroupName, Ngroups, CohortName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #COHORT
|
||||
|
||||
-- Name of the template group.
|
||||
self.templatename=TemplateGroupName
|
||||
|
||||
-- Cohort name.
|
||||
self.name=tostring(CohortName or TemplateGroupName)
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("COHORT %s | ", self.name)
|
||||
|
||||
-- Template group.
|
||||
self.templategroup=GROUP:FindByName(self.templatename)
|
||||
|
||||
-- Check if template group exists.
|
||||
if not self.templategroup then
|
||||
self:E(self.lid..string.format("ERROR: Template group %s does not exist!", tostring(self.templatename)))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Defaults.
|
||||
self.Ngroups=Ngroups or 3
|
||||
self:SetMissionRange()
|
||||
self:SetSkill(AI.Skill.GOOD)
|
||||
|
||||
-- Everyone can ORBIT.
|
||||
--self:AddMissionCapability(AUFTRAG.Type.ORBIT)
|
||||
|
||||
-- Generalized attribute.
|
||||
self.attribute=self.templategroup:GetAttribute()
|
||||
|
||||
-- Aircraft type.
|
||||
self.aircrafttype=self.templategroup:GetTypeName()
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "OnDuty") -- Start FSM.
|
||||
self:AddTransition("*", "Status", "*") -- Status update.
|
||||
|
||||
self:AddTransition("OnDuty", "Pause", "Paused") -- Pause platoon.
|
||||
self:AddTransition("Paused", "Unpause", "OnDuty") -- Unpause platoon.
|
||||
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop platoon.
|
||||
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the COHORT. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#COHORT] Start
|
||||
-- @param #COHORT self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the COHORT. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#COHORT] __Start
|
||||
-- @param #COHORT self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the COHORT and all its event handlers.
|
||||
-- @param #COHORT self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the COHORT and all its event handlers.
|
||||
-- @function [parent=#COHORT] __Stop
|
||||
-- @param #COHORT self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Status".
|
||||
-- @function [parent=#COHORT] Status
|
||||
-- @param #COHORT self
|
||||
|
||||
--- Triggers the FSM event "Status" after a delay.
|
||||
-- @function [parent=#COHORT] __Status
|
||||
-- @param #COHORT self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set livery painted on all platoon aircraft.
|
||||
-- Note that the livery name in general is different from the name shown in the mission editor.
|
||||
--
|
||||
-- Valid names are the names of the **livery directories**. Check out the folder in your DCS installation for:
|
||||
--
|
||||
-- * Full modules: `DCS World OpenBeta\CoreMods\aircraft\<Aircraft Type>\Liveries\<Aircraft Type>\<Livery Name>`
|
||||
-- * AI units: `DCS World OpenBeta\Bazar\Liveries\<Aircraft Type>\<Livery Name>`
|
||||
--
|
||||
-- The folder name `<Livery Name>` is the string you want.
|
||||
--
|
||||
-- Or personal liveries you have installed somewhere in your saved games folder.
|
||||
--
|
||||
-- @param #COHORT self
|
||||
-- @param #string LiveryName Name of the livery.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetLivery(LiveryName)
|
||||
self.livery=LiveryName
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set skill level of all platoon team members.
|
||||
-- @param #COHORT self
|
||||
-- @param #string Skill Skill of all flights.
|
||||
-- @usage myplatoon:SetSkill(AI.Skill.EXCELLENT)
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetSkill(Skill)
|
||||
self.skill=Skill
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set verbosity level.
|
||||
-- @param #COHORT self
|
||||
-- @param #number VerbosityLevel Level of output (higher=more). Default 0.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetVerbosity(VerbosityLevel)
|
||||
self.verbose=VerbosityLevel or 0
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set turnover and repair time. If an asset returns from a mission, it will need some time until the asset is available for further missions.
|
||||
-- @param #COHORT self
|
||||
-- @param #number MaintenanceTime Time in minutes it takes until a flight is combat ready again. Default is 0 min.
|
||||
-- @param #number RepairTime Time in minutes it takes to repair a flight for each life point taken. Default is 0 min.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetTurnoverTime(MaintenanceTime, RepairTime)
|
||||
self.maintenancetime=MaintenanceTime and MaintenanceTime*60 or 0
|
||||
self.repairtime=RepairTime and RepairTime*60 or 0
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set radio frequency and modulation the cohort uses.
|
||||
-- @param #COHORT self
|
||||
-- @param #number Frequency Radio frequency in MHz. Default 251 MHz.
|
||||
-- @param #number Modulation Radio modulation. Default 0=AM.
|
||||
-- @usage myplatoon:SetSkill(AI.Skill.EXCELLENT)
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetRadio(Frequency, Modulation)
|
||||
self.radioFreq=Frequency or 251
|
||||
self.radioModu=Modulation or radio.modulation.AM
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set number of units in groups.
|
||||
-- @param #COHORT self
|
||||
-- @param #number nunits Number of units. Must be >=1 and <=4. Default 2.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetGrouping(nunits)
|
||||
self.ngrouping=nunits or 2
|
||||
if self.ngrouping<1 then self.ngrouping=1 end
|
||||
if self.ngrouping>4 then self.ngrouping=4 end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set mission types this platoon is able to perform.
|
||||
-- @param #COHORT self
|
||||
-- @param #table MissionTypes Table of mission types. Can also be passed as a #string if only one type.
|
||||
-- @param #number Performance Performance describing how good this mission can be performed. Higher is better. Default 50. Max 100.
|
||||
-- @return #COHORT self
|
||||
function COHORT:AddMissionCapability(MissionTypes, Performance)
|
||||
|
||||
-- Ensure Missiontypes is a table.
|
||||
if MissionTypes and type(MissionTypes)~="table" then
|
||||
MissionTypes={MissionTypes}
|
||||
end
|
||||
|
||||
-- Set table.
|
||||
self.missiontypes=self.missiontypes or {}
|
||||
|
||||
for _,missiontype in pairs(MissionTypes) do
|
||||
|
||||
-- Check not to add the same twice.
|
||||
if self:CheckMissionCapability(missiontype, self.missiontypes) then
|
||||
self:E(self.lid.."WARNING: Mission capability already present! No need to add it twice.")
|
||||
-- TODO: update performance.
|
||||
else
|
||||
|
||||
local capability={} --Ops.Auftrag#AUFTRAG.Capability
|
||||
capability.MissionType=missiontype
|
||||
capability.Performance=Performance or 50
|
||||
table.insert(self.missiontypes, capability)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Debug info.
|
||||
self:T2(self.missiontypes)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get mission types this platoon is able to perform.
|
||||
-- @param #COHORT self
|
||||
-- @return #table Table of mission types. Could be empty {}.
|
||||
function COHORT:GetMissionTypes()
|
||||
|
||||
local missiontypes={}
|
||||
|
||||
for _,Capability in pairs(self.missiontypes) do
|
||||
local capability=Capability --Ops.Auftrag#AUFTRAG.Capability
|
||||
table.insert(missiontypes, capability.MissionType)
|
||||
end
|
||||
|
||||
return missiontypes
|
||||
end
|
||||
|
||||
--- Get mission capabilities of this platoon.
|
||||
-- @param #COHORT self
|
||||
-- @return #table Table of mission capabilities.
|
||||
function COHORT:GetMissionCapabilities()
|
||||
return self.missiontypes
|
||||
end
|
||||
|
||||
--- Get mission performance for a given type of misson.
|
||||
-- @param #COHORT self
|
||||
-- @param #string MissionType Type of mission.
|
||||
-- @return #number Performance or -1.
|
||||
function COHORT:GetMissionPeformance(MissionType)
|
||||
|
||||
for _,Capability in pairs(self.missiontypes) do
|
||||
local capability=Capability --Ops.Auftrag#AUFTRAG.Capability
|
||||
if capability.MissionType==MissionType then
|
||||
return capability.Performance
|
||||
end
|
||||
end
|
||||
|
||||
return -1
|
||||
end
|
||||
|
||||
--- Set max mission range. Only missions in a circle of this radius around the platoon airbase are executed.
|
||||
-- @param #COHORT self
|
||||
-- @param #number Range Range in NM. Default 100 NM.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetMissionRange(Range)
|
||||
self.engageRange=UTILS.NMToMeters(Range or 100)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set call sign.
|
||||
-- @param #COHORT self
|
||||
-- @param #number Callsign Callsign from CALLSIGN.Aircraft, e.g. "Chevy" for CALLSIGN.Aircraft.CHEVY.
|
||||
-- @param #number Index Callsign index, Chevy-**1**.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetCallsign(Callsign, Index)
|
||||
self.callsignName=Callsign
|
||||
self.callsignIndex=Index
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set modex.
|
||||
-- @param #COHORT self
|
||||
-- @param #number Modex A number like 100.
|
||||
-- @param #string Prefix A prefix string, which is put before the `Modex` number.
|
||||
-- @param #string Suffix A suffix string, which is put after the `Modex` number.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetModex(Modex, Prefix, Suffix)
|
||||
self.modex=Modex
|
||||
self.modexPrefix=Prefix
|
||||
self.modexSuffix=Suffix
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set Legion.
|
||||
-- @param #COHORT self
|
||||
-- @param Ops.Legion#LEGION Legion The Legion.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetLegion(Legion)
|
||||
self.legion=Legion
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add asset to cohort.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The warehouse asset.
|
||||
-- @return #COHORT self
|
||||
function COHORT:AddAsset(Asset)
|
||||
self:T(self.lid..string.format("Adding asset %s of type %s", Asset.spawngroupname, Asset.unittype))
|
||||
Asset.squadname=self.name
|
||||
table.insert(self.assets, Asset)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove asset from chort.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
||||
-- @return #COHORT self
|
||||
function COHORT:DelAsset(Asset)
|
||||
for i,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
if Asset.uid==asset.uid then
|
||||
self:T2(self.lid..string.format("Removing asset %s", asset.spawngroupname))
|
||||
table.remove(self.assets, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove asset group from cohort.
|
||||
-- @param #COHORT self
|
||||
-- @param #string GroupName Name of the asset group.
|
||||
-- @return #COHORT self
|
||||
function COHORT:DelGroup(GroupName)
|
||||
for i,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
if GroupName==asset.spawngroupname then
|
||||
self:T2(self.lid..string.format("Removing asset %s", asset.spawngroupname))
|
||||
table.remove(self.assets, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get name of the platoon
|
||||
-- @param #COHORT self
|
||||
-- @return #string Name of the platoon.
|
||||
function COHORT:GetName()
|
||||
return self.name
|
||||
end
|
||||
|
||||
--- Get radio frequency and modulation.
|
||||
-- @param #COHORT self
|
||||
-- @return #number Radio frequency in MHz.
|
||||
-- @return #number Radio Modulation (0=AM, 1=FM).
|
||||
function COHORT:GetRadio()
|
||||
return self.radioFreq, self.radioModu
|
||||
end
|
||||
|
||||
--- Create a callsign for the asset.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The warehouse asset.
|
||||
-- @return #COHORT self
|
||||
function COHORT:GetCallsign(Asset)
|
||||
|
||||
if self.callsignName then
|
||||
|
||||
Asset.callsign={}
|
||||
|
||||
for i=1,Asset.nunits do
|
||||
|
||||
local callsign={}
|
||||
|
||||
callsign[1]=self.callsignName
|
||||
callsign[2]=math.floor(self.callsigncounter / 10)
|
||||
callsign[3]=self.callsigncounter % 10
|
||||
if callsign[3]==0 then
|
||||
callsign[3]=1
|
||||
self.callsigncounter=self.callsigncounter+2
|
||||
else
|
||||
self.callsigncounter=self.callsigncounter+1
|
||||
end
|
||||
|
||||
Asset.callsign[i]=callsign
|
||||
|
||||
self:T3({callsign=callsign})
|
||||
|
||||
--TODO: there is also a table entry .name, which is a string.
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Create a modex for the asset.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The warehouse asset.
|
||||
-- @return #COHORT self
|
||||
function COHORT:GetModex(Asset)
|
||||
|
||||
if self.modex then
|
||||
|
||||
Asset.modex={}
|
||||
|
||||
for i=1,Asset.nunits do
|
||||
|
||||
Asset.modex[i]=string.format("%03d", self.modex+self.modexcounter)
|
||||
|
||||
self.modexcounter=self.modexcounter+1
|
||||
|
||||
self:T3({modex=Asset.modex[i]})
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Add TACAN channels to the platoon. Note that channels can only range from 1 to 126.
|
||||
-- @param #COHORT self
|
||||
-- @param #number ChannelMin Channel.
|
||||
-- @param #number ChannelMax Channel.
|
||||
-- @return #COHORT self
|
||||
-- @usage mysquad:AddTacanChannel(64,69) -- adds channels 64, 65, 66, 67, 68, 69
|
||||
function COHORT:AddTacanChannel(ChannelMin, ChannelMax)
|
||||
|
||||
ChannelMax=ChannelMax or ChannelMin
|
||||
|
||||
if ChannelMin>126 then
|
||||
self:E(self.lid.."ERROR: TACAN Channel must be <= 126! Will not add to available channels")
|
||||
return self
|
||||
end
|
||||
if ChannelMax>126 then
|
||||
self:E(self.lid.."WARNING: TACAN Channel must be <= 126! Adjusting ChannelMax to 126")
|
||||
ChannelMax=126
|
||||
end
|
||||
|
||||
for i=ChannelMin,ChannelMax do
|
||||
self.tacanChannel[i]=true
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get an unused TACAN channel.
|
||||
-- @param #COHORT self
|
||||
-- @return #number TACAN channel or *nil* if no channel is free.
|
||||
function COHORT:FetchTacan()
|
||||
|
||||
-- Get the smallest free channel if there is one.
|
||||
local freechannel=nil
|
||||
for channel,free in pairs(self.tacanChannel) do
|
||||
if free then
|
||||
if freechannel==nil or channel<freechannel then
|
||||
freechannel=channel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if freechannel then
|
||||
self:T(self.lid..string.format("Checking out Tacan channel %d", freechannel))
|
||||
self.tacanChannel[freechannel]=false
|
||||
end
|
||||
|
||||
return freechannel
|
||||
end
|
||||
|
||||
--- "Return" a used TACAN channel.
|
||||
-- @param #COHORT self
|
||||
-- @param #number channel The channel that is available again.
|
||||
function COHORT:ReturnTacan(channel)
|
||||
self:T(self.lid..string.format("Returning Tacan channel %d", channel))
|
||||
self.tacanChannel[channel]=true
|
||||
end
|
||||
|
||||
--- Check if platoon is "OnDuty".
|
||||
-- @param #COHORT self
|
||||
-- @return #boolean If true, squdron is in state "OnDuty".
|
||||
function COHORT:IsOnDuty()
|
||||
return self:Is("OnDuty")
|
||||
end
|
||||
|
||||
--- Check if platoon is "Stopped".
|
||||
-- @param #COHORT self
|
||||
-- @return #boolean If true, squdron is in state "Stopped".
|
||||
function COHORT:IsStopped()
|
||||
return self:Is("Stopped")
|
||||
end
|
||||
|
||||
--- Check if platoon is "Paused".
|
||||
-- @param #COHORT self
|
||||
-- @return #boolean If true, squdron is in state "Paused".
|
||||
function COHORT:IsPaused()
|
||||
return self:Is("Paused")
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #COHORT self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function COHORT:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting COHORT %s", self.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
|
||||
--- Check asset status.
|
||||
-- @param #COHORT self
|
||||
function COHORT:_CheckAssetStatus()
|
||||
|
||||
if self.verbose>=2 and #self.assets>0 then
|
||||
|
||||
local text=""
|
||||
for j,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
-- Text.
|
||||
text=text..string.format("\n[%d] %s (%s*%d): ", j, asset.spawngroupname, asset.unittype, asset.nunits)
|
||||
|
||||
if asset.spawned then
|
||||
|
||||
---
|
||||
-- Spawned
|
||||
---
|
||||
|
||||
-- Mission info.
|
||||
local mission=self.legion and self.legion:GetAssetCurrentMission(asset) or false
|
||||
if mission then
|
||||
local distance=asset.flightgroup and UTILS.MetersToNM(mission:GetTargetDistance(asset.flightgroup.group:GetCoordinate())) or 0
|
||||
text=text..string.format("Mission %s - %s: Status=%s, Dist=%.1f NM", mission.name, mission.type, mission.status, distance)
|
||||
else
|
||||
text=text.."Mission None"
|
||||
end
|
||||
|
||||
-- Flight status.
|
||||
text=text..", Flight: "
|
||||
if asset.flightgroup and asset.flightgroup:IsAlive() then
|
||||
local status=asset.flightgroup:GetState()
|
||||
local fuelmin=asset.flightgroup:GetFuelMin()
|
||||
local fuellow=asset.flightgroup:IsFuelLow()
|
||||
local fuelcri=asset.flightgroup:IsFuelCritical()
|
||||
|
||||
text=text..string.format("%s Fuel=%d", status, fuelmin)
|
||||
if fuelcri then
|
||||
text=text.." (Critical!)"
|
||||
elseif fuellow then
|
||||
text=text.." (Low)"
|
||||
end
|
||||
|
||||
local lifept, lifept0=asset.flightgroup:GetLifePoints()
|
||||
text=text..string.format(", Life=%d/%d", lifept, lifept0)
|
||||
|
||||
local ammo=asset.flightgroup:GetAmmoTot()
|
||||
text=text..string.format(", Ammo=%d [G=%d, R=%d, B=%d, M=%d]", ammo.Total,ammo.Guns, ammo.Rockets, ammo.Bombs, ammo.Missiles)
|
||||
else
|
||||
text=text.."N/A"
|
||||
end
|
||||
|
||||
-- Payload info.
|
||||
local payload=asset.payload and table.concat(self.legion:GetPayloadMissionTypes(asset.payload), ", ") or "None"
|
||||
text=text..", Payload={"..payload.."}"
|
||||
|
||||
else
|
||||
|
||||
---
|
||||
-- In Stock
|
||||
---
|
||||
|
||||
text=text..string.format("In Stock")
|
||||
|
||||
if self:IsRepaired(asset) then
|
||||
text=text..", Combat Ready"
|
||||
else
|
||||
|
||||
text=text..string.format(", Repaired in %d sec", self:GetRepairTime(asset))
|
||||
|
||||
if asset.damage then
|
||||
text=text..string.format(" (Damage=%.1f)", asset.damage)
|
||||
end
|
||||
end
|
||||
|
||||
if asset.Treturned then
|
||||
local T=timer.getAbsTime()-asset.Treturned
|
||||
text=text..string.format(", Returned for %d sec", T)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "Stop" event.
|
||||
-- @param #COHORT self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function COHORT:onafterStop(From, Event, To)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid.."STOPPING Cohort and removing all assets!")
|
||||
|
||||
-- Remove all assets.
|
||||
for i=#self.assets,1,-1 do
|
||||
local asset=self.assets[i]
|
||||
self:DelAsset(asset)
|
||||
end
|
||||
|
||||
-- Clear call scheduler.
|
||||
self.CallScheduler:Clear()
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check if there is a platoon that can execute a given mission.
|
||||
-- We check the mission type, the refuelling system, engagement range
|
||||
-- @param #COHORT self
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
-- @return #boolean If true, Cohort can do that type of mission.
|
||||
function COHORT:CanMission(Mission)
|
||||
|
||||
local cando=true
|
||||
|
||||
-- On duty?=
|
||||
if not self:IsOnDuty() then
|
||||
self:T(self.lid..string.format("Cohort in not OnDuty but in state %s. Cannot do mission %s with target %s", self:GetState(), Mission.name, Mission:GetTargetName()))
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check mission type. WARNING: This assumes that all assets of the squad can do the same mission types!
|
||||
if not self:CheckMissionType(Mission.type, self:GetMissionTypes()) then
|
||||
self:T(self.lid..string.format("INFO: Squad cannot do mission type %s (%s, %s)", Mission.type, Mission.name, Mission:GetTargetName()))
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check that tanker mission has the correct refuelling system.
|
||||
if Mission.type==AUFTRAG.Type.TANKER then
|
||||
|
||||
if Mission.refuelSystem and Mission.refuelSystem==self.tankerSystem then
|
||||
-- Correct refueling system.
|
||||
else
|
||||
self:T(self.lid..string.format("INFO: Wrong refueling system requested=%s != %s=available", tostring(Mission.refuelSystem), tostring(self.tankerSystem)))
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Distance to target.
|
||||
local TargetDistance=Mission:GetTargetDistance(self.legion:GetCoordinate())
|
||||
|
||||
-- Max engage range.
|
||||
local engagerange=Mission.engageRange and math.max(self.engageRange, Mission.engageRange) or self.engageRange
|
||||
|
||||
-- Set range is valid. Mission engage distance can overrule the squad engage range.
|
||||
if TargetDistance>engagerange then
|
||||
self:I(self.lid..string.format("INFO: Squad is not in range. Target dist=%d > %d NM max mission Range", UTILS.MetersToNM(TargetDistance), UTILS.MetersToNM(engagerange)))
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- Count assets in legion warehouse stock.
|
||||
-- @param #COHORT self
|
||||
-- @param #boolean InStock If true, only assets that are in the warehouse stock/inventory are counted.
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Number of assets.
|
||||
function COHORT:CountAssets(InStock, MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
if MissionTypes==nil or self:CheckMissionCapability(MissionTypes, self.missiontypes) then
|
||||
if Attributes==nil or self:CheckAttribute(Attributes) then
|
||||
if asset.spawned then
|
||||
if not InStock then
|
||||
N=N+1 --Spawned but we also count the spawned ones.
|
||||
end
|
||||
else
|
||||
N=N+1 --This is in stock.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
--- Get assets for a mission.
|
||||
-- @param #COHORT self
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
-- @param #number Nplayloads Number of payloads available.
|
||||
-- @return #table Assets that can do the required mission.
|
||||
function COHORT:RecruitAssets(Mission, Npayloads)
|
||||
|
||||
-- Number of payloads available.
|
||||
Npayloads=Npayloads or self.legion:CountPayloadsInStock(Mission.type, self.aircrafttype, Mission.payloads)
|
||||
|
||||
local assets={}
|
||||
|
||||
-- Loop over assets.
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
|
||||
-- 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
|
||||
|
||||
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:IsHolding() or flightgroup:IsLanding() or flightgroup:IsLanded() or flightgroup:IsArrived() or flightgroup:IsDead() or flightgroup:IsStopped() then
|
||||
combatready=false
|
||||
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
|
||||
|
||||
end
|
||||
end
|
||||
end -- loop over assets
|
||||
|
||||
return assets
|
||||
end
|
||||
|
||||
|
||||
--- Get the time an asset needs to be repaired.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
||||
-- @return #number Time in seconds until asset is repaired.
|
||||
function COHORT:GetRepairTime(Asset)
|
||||
|
||||
if Asset.Treturned then
|
||||
|
||||
local t=self.maintenancetime
|
||||
t=t+Asset.damage*self.repairtime
|
||||
|
||||
-- Seconds after returned.
|
||||
local dt=timer.getAbsTime()-Asset.Treturned
|
||||
|
||||
local T=t-dt
|
||||
|
||||
return T
|
||||
else
|
||||
return 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Checks if a mission type is contained in a table of possible types.
|
||||
-- @param #COHORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
||||
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||
function COHORT:IsRepaired(Asset)
|
||||
|
||||
if Asset.Treturned then
|
||||
local Tnow=timer.getAbsTime()
|
||||
local Trepaired=Asset.Treturned+self.maintenancetime
|
||||
if Tnow>=Trepaired then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
else
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Checks if a mission type is contained in a table of possible types.
|
||||
-- @param #COHORT self
|
||||
-- @param #string MissionType The requested mission type.
|
||||
-- @param #table PossibleTypes A table with possible mission types.
|
||||
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||
function COHORT:CheckMissionType(MissionType, PossibleTypes)
|
||||
|
||||
if type(PossibleTypes)=="string" then
|
||||
PossibleTypes={PossibleTypes}
|
||||
end
|
||||
|
||||
for _,canmission in pairs(PossibleTypes) do
|
||||
if canmission==MissionType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if a mission type is contained in a list of possible capabilities.
|
||||
-- @param #COHORT self
|
||||
-- @param #table MissionTypes The requested mission type. Can also be passed as a single mission type `#string`.
|
||||
-- @param #table Capabilities A table with possible capabilities.
|
||||
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||
function COHORT:CheckMissionCapability(MissionTypes, Capabilities)
|
||||
|
||||
if type(MissionTypes)~="table" then
|
||||
MissionTypes={MissionTypes}
|
||||
end
|
||||
|
||||
for _,cap in pairs(Capabilities) do
|
||||
local capability=cap --Ops.Auftrag#AUFTRAG.Capability
|
||||
for _,MissionType in pairs(MissionTypes) do
|
||||
if capability.MissionType==MissionType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if the platoon attribute matches the given attribute(s).
|
||||
-- @param #COHORT self
|
||||
-- @param #table Attributes The requested attributes. See `WAREHOUSE.Attribute` enum. Can also be passed as a single attribute `#string`.
|
||||
-- @return #boolean If true, the squad has the requested attribute.
|
||||
function COHORT:CheckAttribute(Attributes)
|
||||
|
||||
if type(Attributes)~="table" then
|
||||
Attributes={Attributes}
|
||||
end
|
||||
|
||||
for _,attribute in pairs(Attributes) do
|
||||
if attribute==self.attribute then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -346,6 +346,13 @@ function FLIGHTGROUP:SetAirwing(airwing)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get airwing the flight group belongs to.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return Ops.AirWing#AIRWING The AIRWING object.
|
||||
function FLIGHTGROUP:GetAirWing()
|
||||
return self.airwing
|
||||
end
|
||||
|
||||
--- Set if aircraft is VTOL capable. Unfortunately, there is no DCS way to determine this via scripting.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #FLIGHTGROUP self
|
||||
@ -354,13 +361,6 @@ function FLIGHTGROUP:SetVTOL()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get airwing the flight group belongs to.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return Ops.AirWing#AIRWING The AIRWING object.
|
||||
function FLIGHTGROUP:GetAirWing()
|
||||
return self.airwing
|
||||
end
|
||||
|
||||
--- Set the FLIGHTCONTROL controlling this flight group.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
|
||||
|
||||
1439
Moose Development/Moose/Ops/Legion.lua
Normal file
1439
Moose Development/Moose/Ops/Legion.lua
Normal file
File diff suppressed because it is too large
Load Diff
@ -701,6 +701,15 @@ function OPSGROUP:SetVerbosity(VerbosityLevel)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set legion this ops group belongs to.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param Ops.Legion#LEGION Legion The Legion.
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:_SetLegion(Legion)
|
||||
self.legion=Legion
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set default cruise speed.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number Speed Speed in knots.
|
||||
|
||||
155
Moose Development/Moose/Ops/Platoon.lua
Normal file
155
Moose Development/Moose/Ops/Platoon.lua
Normal file
@ -0,0 +1,155 @@
|
||||
--- **Ops** - Brigade Platoon.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Set parameters like livery, skill valid for all platoon members.
|
||||
-- * Define modex and callsigns.
|
||||
-- * Define mission types, this platoon can perform (see Ops.Auftrag#AUFTRAG).
|
||||
-- * Pause/unpause platoon operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Platoon
|
||||
-- @image OPS_Platoon.png
|
||||
|
||||
|
||||
--- PLATOON class.
|
||||
-- @type PLATOON
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity level.
|
||||
-- @extends Ops.Cohort#COHORT
|
||||
|
||||
--- *Some cool cohort quote* -- Known Author
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The PLATOON Concept
|
||||
--
|
||||
-- A PLATOON is essential part of an BRIGADE.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #PLATOON
|
||||
PLATOON = {
|
||||
ClassName = "PLATOON",
|
||||
verbose = 0,
|
||||
}
|
||||
|
||||
--- PLATOON class version.
|
||||
-- @field #string version
|
||||
PLATOON.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new PLATOON object and start the FSM.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string TemplateGroupName Name of the template group.
|
||||
-- @param #number Ngroups Number of asset groups of this platoon. Default 3.
|
||||
-- @param #string PlatoonName Name of the platoon, e.g. "VFA-37".
|
||||
-- @return #PLATOON self
|
||||
function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, PlatoonName)) -- #PLATOON
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Platoon specific user functions.
|
||||
|
||||
--- Set brigade of this platoon.
|
||||
-- @param #PLATOON self
|
||||
-- @param Ops.Brigade#BRIGADE Brigade The brigade.
|
||||
-- @return #PLATOON self
|
||||
function PLATOON:SetBrigade(Brigade)
|
||||
self.legion=Brigade
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get brigade of this platoon.
|
||||
-- @param #PLATOON self
|
||||
-- @return Ops.Brigade#BRIGADE The brigade.
|
||||
function PLATOON:GetBrigade()
|
||||
return self.legion
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function PLATOON:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting PLATOON %s", self.name)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Start the status monitoring.
|
||||
self:__Status(-1)
|
||||
end
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #PLATOON self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function PLATOON:onafterStatus(From, Event, To)
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
local callsign=self.callsignName and UTILS.GetCallsignName(self.callsignName) or "N/A"
|
||||
local modex=self.modex and self.modex or -1
|
||||
local skill=self.skill and tostring(self.skill) or "N/A"
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("%s [Type=%s, Call=%s, Modex=%d, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
|
||||
fsmstate, self.aircrafttype, callsign, modex, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Check if group has detected any units.
|
||||
self:_CheckAssetStatus()
|
||||
|
||||
end
|
||||
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-60)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Misc Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Misc functions.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -704,7 +704,7 @@ function SQUADRON:onafterStatus(From, Event, To)
|
||||
local skill=self.skill and tostring(self.skill) or "N/A"
|
||||
|
||||
local NassetsTot=#self.assets
|
||||
local NassetsInS=self:CountAssetsInStock()
|
||||
local NassetsInS=self:CountAssets(true)
|
||||
local NassetsQP=0 ; local NassetsP=0 ; local NassetsQ=0
|
||||
if self.airwing then
|
||||
NassetsQP, NassetsP, NassetsQ=self.airwing:CountAssetsOnMission(nil, self)
|
||||
@ -888,18 +888,25 @@ end
|
||||
|
||||
--- Count assets in airwing (warehous) stock.
|
||||
-- @param #SQUADRON self
|
||||
-- @param #boolean InStock If true, only assets that are in the warehouse stock/inventory are counted.
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @return #number Assets not spawned.
|
||||
function SQUADRON:CountAssetsInStock(MissionTypes)
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Number of assets.
|
||||
function SQUADRON:CountAssets(InStock, MissionTypes, Attributes)
|
||||
|
||||
local N=0
|
||||
for _,_asset in pairs(self.assets) do
|
||||
local asset=_asset --Ops.AirWing#AIRWING.SquadronAsset
|
||||
if asset.spawned then
|
||||
|
||||
else
|
||||
if MissionTypes==nil or self:CheckMissionCapability(MissionTypes, self.missiontypes) then
|
||||
N=N+1
|
||||
if Attributes==nil or self:CheckAttribute(Attributes) then
|
||||
if asset.spawned then
|
||||
if not InStock then
|
||||
N=N+1 --Spawned but we also count the spawned ones.
|
||||
end
|
||||
else
|
||||
N=N+1 --This is in stock.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1099,6 +1106,26 @@ function SQUADRON:CheckMissionCapability(MissionTypes, Capabilities)
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if the squadron attribute matches the given attribute(s).
|
||||
-- @param #SQUADRON self
|
||||
-- @param #table Attributes The requested attributes. See `WAREHOUSE.Attribute` enum. Can also be passed as a single attribute `#string`.
|
||||
-- @return #boolean If true, the squad has the requested attribute.
|
||||
function SQUADRON:CheckAttribute(Attributes)
|
||||
|
||||
if type(Attributes)~="table" then
|
||||
Attributes={Attributes}
|
||||
end
|
||||
|
||||
for _,attribute in pairs(Attributes) do
|
||||
if attribute==self.attribute then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -223,10 +223,10 @@ function WINGCOMMANDER:onafterStatus(From, Event, To)
|
||||
for _,_airwing in pairs(self.airwings) do
|
||||
local airwing=_airwing --Ops.AirWing#AIRWING
|
||||
local Nassets=airwing:CountAssets()
|
||||
local Nastock=airwing:CountAssetsInStock()
|
||||
local Nastock=airwing:CountAssets(true)
|
||||
text=text..string.format("\n* %s [%s]: Assets=%s stock=%s", airwing.alias, airwing:GetState(), Nassets, Nastock)
|
||||
for _,aname in pairs(AUFTRAG.Type) do
|
||||
local na=airwing:CountAssetsInStock({aname})
|
||||
local na=airwing:CountAssets(true, {aname})
|
||||
local np=airwing:CountPayloadsInStock({aname})
|
||||
local nm=airwing:CountAssetsOnMission({aname})
|
||||
if na>0 or np>0 then
|
||||
@ -405,6 +405,22 @@ function WINGCOMMANDER:GetAirwingForMission(Mission)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Check mission queue and assign ONE planned mission.
|
||||
-- @param #WINGCOMMANDER self
|
||||
-- @param #boolean InStock If true, only assets that are in the warehouse stock/inventory are counted.
|
||||
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||
-- @return #number Amount of asset groups in stock.
|
||||
function WINGCOMMANDER:CountAssets(InStock, MissionTypes, Attributes)
|
||||
local N=0
|
||||
for _,_airwing in pairs(self.airwings) do
|
||||
local airwing=_airwing --Ops.AirWing#AIRWING
|
||||
N=N+airwing:CountAssets(InStock, MissionTypes, Attributes)
|
||||
end
|
||||
|
||||
return N
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Loading…
x
Reference in New Issue
Block a user