mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Stuff
This commit is contained in:
parent
eeffa31282
commit
801d00fa26
@ -82,6 +82,9 @@ __Moose.Include( 'Scripts/Moose/Ops/ArmyGroup.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Squadron.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Intelligence.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/ChiefOfStaff.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Army.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/Ops/Platoon.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||
|
||||
434
Moose Development/Moose/Ops/Army.lua
Normal file
434
Moose Development/Moose/Ops/Army.lua
Normal file
@ -0,0 +1,434 @@
|
||||
--- **Ops** - Army Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage platoons
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Ops.Army
|
||||
-- @image OPS_AirWing.png
|
||||
|
||||
|
||||
--- ARMY class.
|
||||
-- @type ARMY
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
-- @field #table menu Table of menu items.
|
||||
-- @field #table squadrons Table of squadrons.
|
||||
-- @field #table missionqueue Mission queue table.
|
||||
-- @field #table payloads Playloads for specific aircraft and mission types.
|
||||
-- @field #number payloadcounter Running index of payloads.
|
||||
-- @field Core.Set#SET_ZONE zonesetCAP Set of CAP zones.
|
||||
-- @field Core.Set#SET_ZONE zonesetTANKER Set of TANKER zones.
|
||||
-- @field Core.Set#SET_ZONE zonesetAWACS Set of AWACS zones.
|
||||
-- @field #number nflightsCAP Number of CAP flights constantly in the air.
|
||||
-- @field #number nflightsAWACS Number of AWACS flights constantly in the air.
|
||||
-- @field #number nflightsTANKERboom Number of TANKER flights with BOOM constantly in the air.
|
||||
-- @field #number nflightsTANKERprobe Number of TANKER flights with PROBE constantly in the air.
|
||||
-- @field #number nflightsRescueHelo Number of Rescue helo flights constantly in the air.
|
||||
-- @field #table pointsCAP Table of CAP points.
|
||||
-- @field #table pointsTANKER Table of Tanker points.
|
||||
-- @field #table pointsAWACS Table of AWACS points.
|
||||
-- @field Ops.WingCommander#WINGCOMMANDER wingcommander The wing commander responsible for this airwing.
|
||||
--
|
||||
-- @field Ops.RescueHelo#RESCUEHELO rescuehelo The rescue helo.
|
||||
-- @field Ops.RecoveryTanker#RECOVERYTANKER recoverytanker The recoverytanker.
|
||||
--
|
||||
-- @extends Functional.Warehouse#WAREHOUSE
|
||||
|
||||
--- Be surprised!
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The ARMY Concept
|
||||
--
|
||||
-- An ARMY consists of multiple SQUADRONS. These squadrons "live" in a WAREHOUSE, i.e. a physical structure that is connected to an airbase (airdrome, FRAP or ship).
|
||||
-- For an airwing to be operational, it needs airframes, weapons/fuel and an airbase.
|
||||
--
|
||||
-- # Create an Army
|
||||
--
|
||||
-- ## Constructing the Army
|
||||
--
|
||||
-- airwing=ARMY:New("Warehouse Batumi", "8th Fighter Wing")
|
||||
-- airwing:Start()
|
||||
--
|
||||
-- The first parameter specified the warehouse, i.e. the static building housing the airwing (or the name of the aircraft carrier). The second parameter is optional
|
||||
-- and sets an alias.
|
||||
--
|
||||
-- ## Adding Squadrons
|
||||
--
|
||||
-- At this point the airwing does not have any assets (aircraft). In order to add these, one needs to first define SQUADRONS.
|
||||
--
|
||||
-- VFA151=SQUADRON:New("F-14 Group", 8, "VFA-151 (Vigilantes)")
|
||||
-- VFA151:AddMissionCapability({AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT})
|
||||
--
|
||||
-- airwing:AddSquadron(VFA151)
|
||||
--
|
||||
-- This adds eight Tomcat groups beloning to VFA-151 to the airwing. This squadron has the ability to perform combat air patrols and intercepts.
|
||||
--
|
||||
-- ## Adding Payloads
|
||||
--
|
||||
-- Adding pure airframes is not enough. The aircraft also need weapons (and fuel) for certain missions. These must be given to the airwing from template groups
|
||||
-- defined in the Mission Editor.
|
||||
--
|
||||
-- -- F-14 payloads for CAP and INTERCEPT. Phoenix are first, sparrows are second choice.
|
||||
-- airwing:NewPayload(GROUP:FindByName("F-14 Payload AIM-54C"), 2, {AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.GCICAP}, 80)
|
||||
-- airwing:NewPayload(GROUP:FindByName("F-14 Payload AIM-7M"), 20, {AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.GCICAP})
|
||||
--
|
||||
-- This will add two AIM-54C and 20 AIM-7M payloads.
|
||||
--
|
||||
-- If the airwing gets an intercept or patrol mission assigned, it will first use the AIM-54s. Once these are consumed, the AIM-7s are attached to the aircraft.
|
||||
--
|
||||
-- When an airwing does not have a payload for a certain mission type, the mission cannot be carried out.
|
||||
--
|
||||
-- You can set the number of payloads to "unlimited" by setting its quantity to -1.
|
||||
--
|
||||
-- # Adding Missions
|
||||
--
|
||||
-- Various mission types can be added easily via the AUFTRAG class.
|
||||
--
|
||||
-- Once you created an AUFTRAG you can add it to the ARMY with the :AddMission(mission) function.
|
||||
--
|
||||
-- This mission will be put into the ARMY queue. Once the mission start time is reached and all resources (airframes and pylons) are available, the mission is started.
|
||||
-- If the mission stop time is over (and the mission is not finished), it will be cancelled and removed from the queue. This applies also to mission that were not even
|
||||
-- started.
|
||||
--
|
||||
-- # Command an Army
|
||||
--
|
||||
-- An airwing can receive missions from a WINGCOMMANDER. See docs of that class for details.
|
||||
--
|
||||
-- However, you are still free to add missions at anytime.
|
||||
--
|
||||
--
|
||||
-- @field #ARMY
|
||||
ARMY = {
|
||||
ClassName = "ARMY",
|
||||
verbose = 0,
|
||||
lid = nil,
|
||||
menu = nil,
|
||||
squadrons = {},
|
||||
missionqueue = {},
|
||||
payloads = {},
|
||||
payloadcounter = 0,
|
||||
pointsCAP = {},
|
||||
pointsTANKER = {},
|
||||
pointsAWACS = {},
|
||||
wingcommander = nil,
|
||||
}
|
||||
|
||||
--- Squadron asset.
|
||||
-- @type ARMY.SquadronAsset
|
||||
-- @field #ARMY.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
|
||||
|
||||
--- ARMY class version.
|
||||
-- @field #string version
|
||||
ARMY.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new ARMY class object.
|
||||
-- @param #ARMY self
|
||||
-- @param #string warehousename Name of the warehouse static or unit object representing the warehouse.
|
||||
-- @param #string airwingname Name of the air wing, e.g. "ARMY-8".
|
||||
-- @return #ARMY self
|
||||
function ARMY:New(warehousename, airwingname)
|
||||
|
||||
-- Inherit everything from WAREHOUSE class.
|
||||
local self=BASE:Inherit(self, WAREHOUSE:New(warehousename, airwingname)) -- #ARMY
|
||||
|
||||
-- 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("ARMY %s | ", self.alias)
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
|
||||
self:AddTransition("*", "MissionCancel", "*") -- Cancel mission.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the ARMY. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#ARMY] Start
|
||||
-- @param #ARMY self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the ARMY. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#ARMY] __Start
|
||||
-- @param #ARMY self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the ARMY and all its event handlers.
|
||||
-- @param #ARMY self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the ARMY and all its event handlers.
|
||||
-- @function [parent=#ARMY] __Stop
|
||||
-- @param #ARMY self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Start & Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start AIRWING FSM.
|
||||
-- @param #AIRWING self
|
||||
function AIRWING:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting AIRWING v%s", AIRWING.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #AIRWING self
|
||||
function AIRWING:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
|
||||
-- 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, Payloads=%d (%d), Squads=%d, Assets=%s", fsmstate, Nmissions, Npayloads, #self.payloads, #self.squadrons, 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="Squadrons:"
|
||||
for i,_squadron in pairs(self.squadrons) 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:CountAssetsInStock(), #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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Stuff
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check if mission is not over and ready to cancel.
|
||||
-- @param #AIRWING self
|
||||
function AIRWING:_CheckMissions()
|
||||
|
||||
-- Loop over missions in queue.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
if mission:IsNotOver() and mission:IsReadyToCancel() then
|
||||
mission:Cancel()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
--- Get next mission.
|
||||
-- @param #AIRWING self
|
||||
-- @return Ops.Auftrag#AUFTRAG Next mission or *nil*.
|
||||
function AIRWING:_GetNextMission()
|
||||
|
||||
-- Number of missions.
|
||||
local Nmissions=#self.missionqueue
|
||||
|
||||
-- Treat special cases.
|
||||
if Nmissions==0 then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Sort results table wrt prio and start time.
|
||||
local function _sort(a, b)
|
||||
local taskA=a --Ops.Auftrag#AUFTRAG
|
||||
local taskB=b --Ops.Auftrag#AUFTRAG
|
||||
return (taskA.prio<taskB.prio) or (taskA.prio==taskB.prio and taskA.Tstart<taskB.Tstart)
|
||||
end
|
||||
table.sort(self.missionqueue, _sort)
|
||||
|
||||
-- Look for first mission that is SCHEDULED.
|
||||
local vip=math.huge
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
if mission.importance and mission.importance<vip then
|
||||
vip=mission.importance
|
||||
end
|
||||
end
|
||||
|
||||
-- Current time.
|
||||
local time=timer.getAbsTime()
|
||||
|
||||
-- Look for first task that is not accomplished.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
-- Firstly, check if mission is due?
|
||||
if mission:IsQueued() and mission:IsReadyToGo() and (mission.importance==nil or mission.importance<=vip) then
|
||||
|
||||
-- Check if airwing can do the mission and gather required assets.
|
||||
local can, assets=self:CanMission(mission)
|
||||
|
||||
-- Check that mission is still scheduled, time has passed and enough assets are available.
|
||||
if can then
|
||||
|
||||
-- Optimize the asset selection. Most useful assets will come first. We do not include the payload as some assets have and some might not.
|
||||
self:_OptimizeAssetSelection(assets, mission, false)
|
||||
|
||||
-- Assign assets to mission.
|
||||
local remove={}
|
||||
local gotpayload={}
|
||||
for i=1,#assets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
|
||||
-- Get payload for the asset.
|
||||
if not asset.payload then
|
||||
local payload=self:FetchPayloadFromStock(asset.unittype, mission.type, mission.payloads)
|
||||
if payload then
|
||||
asset.payload=payload
|
||||
table.insert(gotpayload, asset.uid)
|
||||
else
|
||||
table.insert(remove, asset.uid)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:T(self.lid..string.format("Provided %d assets with payloads. Could not get payload for %d assets", #gotpayload, #remove))
|
||||
|
||||
-- Now remove assets for which we don't have a payload.
|
||||
for i=#assets,1,-1 do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
for _,uid in pairs(remove) do
|
||||
if uid==asset.uid then
|
||||
table.remove(assets, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Another check.
|
||||
if #assets<mission.nassets then
|
||||
self:E(self.lid..string.format("ERROR: Not enough payloads for mission assets! Can only do %d/%d", #assets, mission.nassets))
|
||||
end
|
||||
|
||||
-- Optimize the asset selection. Now we include the payload performance as this could change the result.
|
||||
self:_OptimizeAssetSelection(assets, mission, true)
|
||||
|
||||
-- Check that mission.assets table is clean.
|
||||
if mission.assets and #mission.assets>0 then
|
||||
self:E(self.lid..string.format("ERROR: mission %s of type %s has already assets attached!", mission.name, mission.type))
|
||||
end
|
||||
mission.assets={}
|
||||
|
||||
-- Assign assets to mission.
|
||||
for i=1,mission.nassets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
|
||||
-- Should not happen as we just checked!
|
||||
if not asset.payload then
|
||||
self:E(self.lid.."ERROR: No payload for asset! This should not happen!")
|
||||
end
|
||||
|
||||
-- Add asset to mission.
|
||||
mission:AddAsset(asset)
|
||||
end
|
||||
|
||||
-- Now return the remaining payloads.
|
||||
for i=mission.nassets+1,#assets do
|
||||
local asset=assets[i] --#AIRWING.SquadronAsset
|
||||
for _,uid in pairs(gotpayload) do
|
||||
if uid==asset.uid then
|
||||
self:ReturnPayloadFromAsset(asset)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
end -- mission due?
|
||||
end -- mission loop
|
||||
|
||||
return nil
|
||||
end
|
||||
0
Moose Development/Moose/Ops/Platoon.lua
Normal file
0
Moose Development/Moose/Ops/Platoon.lua
Normal file
Loading…
x
Reference in New Issue
Block a user