From 801d00fa26abfb28e2a21d9f69a96cd5ac08789b Mon Sep 17 00:00:00 2001 From: Frank Date: Mon, 30 Nov 2020 11:38:36 +0100 Subject: [PATCH] Stuff --- Moose Development/Moose/Modules.lua | 3 + Moose Development/Moose/Ops/Army.lua | 434 ++++++++++++++++++++++++ Moose Development/Moose/Ops/Platoon.lua | 0 3 files changed, 437 insertions(+) create mode 100644 Moose Development/Moose/Ops/Army.lua create mode 100644 Moose Development/Moose/Ops/Platoon.lua diff --git a/Moose Development/Moose/Modules.lua b/Moose Development/Moose/Modules.lua index 8e1cd2860..2474442f4 100644 --- a/Moose Development/Moose/Modules.lua +++ b/Moose Development/Moose/Modules.lua @@ -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' ) diff --git a/Moose Development/Moose/Ops/Army.lua b/Moose Development/Moose/Ops/Army.lua new file mode 100644 index 000000000..884a6ed22 --- /dev/null +++ b/Moose Development/Moose/Ops/Army.lua @@ -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! +-- +-- === +-- +-- ![Banner Image](..\Presentations\OPS\AirWing\_Main.png) +-- +-- # 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.prio0 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 \ No newline at end of file diff --git a/Moose Development/Moose/Ops/Platoon.lua b/Moose Development/Moose/Ops/Platoon.lua new file mode 100644 index 000000000..e69de29bb