This commit is contained in:
Frank
2020-04-09 01:30:32 +02:00
parent a0ecf58c7f
commit f554642505
4 changed files with 155 additions and 32 deletions
+31 -11
View File
@@ -48,6 +48,7 @@
AIRWING = {
ClassName = "AIRWING",
Debug = false,
verbose = 0,
lid = nil,
menu = nil,
squadrons = {},
@@ -100,17 +101,17 @@ AIRWING.version="0.1.5"
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- DONE: Add squadrons to warehouse.
-- TODO: Spawn in air or hot.
-- TODO: Make special request to transfer squadrons to anther airwing (or warehouse).
-- TODO: Border zone or even multiple zones.
-- TODO: Check that airbase has enough parking spots if a request is BIG. Alternatively, split requests.
-- DONE: Add squadrons to warehouse.
-- DONE: Build mission queue.
-- DONE: Find way to start missions.
-- DONE: Check if missions are done/cancelled.
-- DONE: Payloads as resources.
-- TODO: Spawn in air or hot.
-- DONE: Define CAP zones.
-- DONE: Define TANKER zones for refuelling.
-- TODO: Border zone or even multiple zones.
-- TODO: Check that airbase has enough parking spots if a request is BIG. Alternatively, split requests.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@@ -263,8 +264,8 @@ function AIRWING:NewPayload(Unit, MissionTypes, Npayloads, Unlimited, Priority)
table.insert(self.payloads, payload)
-- Info
self:I(self.lid..string.format("Adding new payload from unit %s for aircraft type %s: N=%d (unlimited=%s), missions:", payload.unitname, payload.aircrafttype, payload.navail, tostring(payload.unlimited)))
self:I({MissionTypes=payload.missiontypes})
self:I(self.lid..string.format("Adding new payload from unit %s for aircraft type %s: N=%d (unlimited=%s), prio=%d, missions: %s",
payload.unitname, payload.aircrafttype, payload.navail, tostring(payload.unlimited), payload.priority, table.concat(payload.missiontypes, ", ")))
return payload
end
@@ -280,15 +281,28 @@ end
-- @return #AIRWING.Payload Payload table or *nil*.
function AIRWING:FetchPayloadFromStock(UnitType, MissionType)
--- Sort payload wrt the following criteria:
-- 1) Highest prio (lower value) is the main selection criterion.
-- 2) If payloads have the same prio, unlimited payloads are preferred over limited ones.
-- 3) If payloads have the same prio _and_ are limited, the abundant one is preferred.
local function sortpayloads(a,b)
local pA=a --#AIRWING.Payload
local pB=b --#AIRWING.Payload
return pA.priority<pB.priority
end
return (pA.priority<pB.priority) or (pA.priority==pB.priority and pA.unlimited==true) or (pA.priority==pB.priority and pA.unlimited==true and pB.unlimited==true and pA.navail>pB.navail)
end
table.sort(self.payloads, sortpayloads)
--[[
env.info("FF sorted payloads for mission type X and aircraft type=Y:")
for _,_payload in ipairs(self.payloads) do
local payload=_payload --#AIRWING.Payload
if payload.aircrafttype==UnitType and self:CheckMissionType(MissionType, payload.missiontypes) then
self:I(string.format("FF %s payload for %s: avail=%d prio=%d", MissionType, payload.aircrafttype, payload.navail, payload.priority))
end
end
]]
for _,_payload in pairs(self.payloads) do
for _,_payload in ipairs(self.payloads) do
local payload=_payload --#AIRWING.Payload
@@ -300,6 +314,8 @@ function AIRWING:FetchPayloadFromStock(UnitType, MissionType)
payload.navail=payload.navail-1
end
--self:I(string.format("FETCHING %s payload for %s: avail=%d prio=%d", MissionType, payload.aircrafttype, payload.navail, payload.priority))
-- Return a copy of the table.
return payload
end
@@ -618,8 +634,12 @@ function AIRWING:onafterStatus(From, Event, To)
for i,_squadron in pairs(self.squadrons) do
local squadron=_squadron --Ops.Squadron#SQUADRON
local callsign=squadron.callsignName and squadron.callsignName or "N/A"
local modex=squadron.modex and squadron.modex or "N/A"
local skill=squadron.skill and tostring(squadron.skill) or "N/A"
-- Squadron text
text=text..string.format("\n* %s %s", squadron.name, squadron:GetState())
text=text..string.format("\n* %s %s: Callsign=%s, Modex=%d, Skill=%s", squadron.name, squadron:GetState(), callsign, modex, skill)
-- Loop over all assets.
for j,_asset in pairs(squadron.assets) do
+88 -13
View File
@@ -159,6 +159,8 @@ AUFTRAG = {
missionFraction = 0.5,
enrouteTasks = {},
markerID = nil,
startconditions = {},
stopconditions = {},
}
--- Global mission counter.
@@ -182,6 +184,8 @@ _AUFTRAGSNR=0
-- @field #string ORBIT Orbit mission.
-- @field #string PATROL Similar to CAP but no auto engage targets.
-- @field #string RECON Recon mission.
-- @field #string RECOVERYTANKER Recovery tanker mission.
-- @field #string RESCUEHELO Rescue helo.
-- @field #string SEAD Suppression/destruction of enemy air defences.
-- @field #string STRIKE Strike mission.
-- @field #string TANKER Tanker mission.
@@ -202,6 +206,8 @@ AUFTRAG.Type={
ORBIT="Orbit",
PATROL="Patrol",
RECON="Recon",
RECOVERYTANKER="Recovery Tanker",
RESCUEHELO="Rescue Helo",
SEAD="SEAD",
STRIKE="Strike",
TANKER="Tanker",
@@ -272,6 +278,7 @@ AUFTRAG.TargetType={
-- @field Wrapper.Positionable#POSITIONABLE Target Target Object.
-- @field #string Type Target type: "Group", "Unit", "Static", "Coordinate", "Airbase.
-- @field #number Ninital Number of initial targets.
-- @field #number Lifepoints Total life points.
--- Mission success.
-- @type AUFTRAG.Success
@@ -297,6 +304,9 @@ AUFTRAG.version="0.0.9"
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add mission start conditions.
-- TODO: Add recovery tanker mission for boat ops.
-- TODO: Add rescue helo mission for boat ops.
-- TODO: Mission success options damaged, destroyed.
-- DONE: Mission ROE and ROT.
-- TODO: Mission frequency, formation, etc.
@@ -313,7 +323,7 @@ AUFTRAG.version="0.0.9"
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new AUFTRAG object.
--- Create a new generic AUFTRAG object.
-- @param #AUFTRAG self
-- @param #string Type Mission type.
-- @return #AUFTRAG self
@@ -342,12 +352,9 @@ function AUFTRAG:New(Type)
self:SetPriority()
self:SetTime()
self.engageAsGroup=true
self.missionRepeated=0
self.missionRepeatMax=0
self.nassets=1
self.dTevaluate=0
-- FMS start state is PLANNED.
@@ -365,7 +372,8 @@ function AUFTRAG:New(Type)
self:AddTransition(AUFTRAG.Status.STARTED, "Executing", AUFTRAG.Status.EXECUTING) -- First asset is executing the mission.
self:AddTransition("*", "Done", AUFTRAG.Status.DONE) -- All assets have reported that mission is done.
self:AddTransition("*", "Cancel", "*") --AUFTRAG.Status.CANCELLED) -- Command to cancel the mission.
self:AddTransition("*", "Cancel", "*") -- Command to cancel the mission.
self:AddTransition("*", "Success", AUFTRAG.Status.SUCCESS)
self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED)
@@ -377,13 +385,9 @@ function AUFTRAG:New(Type)
self:AddTransition("*", "FlightDead", "*")
self:AddTransition("*", "AssetDead", "*")
--[[
self:HandleEvent(EVENTS.PilotDead, self._UnitDead)
self:HandleEvent(EVENTS.Ejection, self._UnitDead)
self:HandleEvent(EVENTS.Crash, self._UnitDead)
]]
-- Init status update.
self:__Status(-1)
return self
@@ -393,6 +397,27 @@ end
-- Create Missions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a RESCUE HELO mission.
-- @param #AUFTRAG self
-- @param Wrapper.UnitUNIT Carrier The carrier unit.
-- @return #AUFTRAG self
function AUFTRAG:NewRESCUEHELO(Carrier)
local mission=AUFTRAG:New(AUFTRAG.Type.RESCUEHELO)
mission.engageTarget=mission:_TargetFromObject(Target)
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
mission.missionTask=ENUMS.MissionTask.NOTHING
mission.missionFraction=0.4
mission.optionROE=ENUMS.ROE.OpenFire
mission.optionROT=ENUMS.ROT.EvadeFire
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- Create an ANTI-SHIP mission.
-- @param #AUFTRAG self
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be passed as a @{Wrapper.Group#GROUP} or @{Wrapper.Unit#UNIT} object.
@@ -729,7 +754,7 @@ end
--- Create a BOMBING mission. Flight will drop bombs a specified coordinate.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE TargetCoordinate Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object.
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object.
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
-- @return #AUFTRAG self
function AUFTRAG:NewBOMBING(Target, Altitude)
@@ -1903,6 +1928,56 @@ function AUFTRAG:CountMissionTargets()
return N
end
--- Get target life points.
-- @param #AUFTRAG self
-- @return #number Number of alive target units.
function AUFTRAG:GetTargetLife()
local N=0
if self.engageTarget then
if self.engageTarget.Type==AUFTRAG.TargetType.GROUP then
local target=self.engageTarget.Target --Wrapper.Group#GROUP
local units=target:GetUnits()
for _,_unit in pairs(units or {}) do
local unit=_unit --Wrapper.Unit#UNIT
-- We check that unit is "alive".
if unit and unit:IsAlive() then
N=N+unit:GetLife()
end
end
elseif self.engageTarget.Type==AUFTRAG.TargetType.UNIT then
local target=self.engageTarget.Target --Wrapper.Unit#UNIT
if target and target:IsAlive() then
N=N+target:GetLife()
end
elseif self.engageTarget.Type==AUFTRAG.TargetType.STATIC then
local target=self.engageTarget.Target --Wrapper.Static#STATIC
if target and target:IsAlive() then
N=N+1 --target:GetLife()
end
elseif self.engageTarget.Type==AUFTRAG.TargetType.AIRBASE then
-- TODO: any (good) way to tell whether an airbase was "destroyed" or at least damaged? Is :GetLive() working?
end
end
return N
end
--- Count alive flight groups assigned for this mission.
-- @param #AUFTRAG self
-- @return #number Number of alive flight groups.
@@ -2251,7 +2326,7 @@ function AUFTRAG:GetDCSMissionTask()
-- Count mission targets.
self.Ntargets=self:CountMissionTargets()
self:I({Ntargets=self.Ntargets, missiontask=DCStasks})
self:T({Ntargets=self.Ntargets, missiontask=DCStasks})
-- Return the task.
if #DCStasks==1 then
+24 -6
View File
@@ -372,6 +372,7 @@ FLIGHTGROUP.version="0.3.8"
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Use new UnitLost event instead of crash/dead.
-- TODO: Options EPLRS, Afterburner restrict etc.
-- TODO: Add TACAN beacon.
-- TODO: Damage?
@@ -2872,13 +2873,30 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
wp[#wp+1]=c0:WaypointAir(nil, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, UTILS.KnotsToKmph(SpeedTo), true , nil, {}, "Current Pos")
wp[#wp+1]=p0:WaypointAir(nil, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, UTILS.KnotsToKmph(SpeedTo), true , nil, {TaskArrived, TaskHold, TaskKlar}, "Holding Point")
-- Approach point: 10 NN in direction of runway.
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
wp[#wp+1]=papp:WaypointAirTurningPoint(nil, UTILS.KnotsToKmph(SpeedLand), {}, "Final Approach")
-- Approach point: 10 NN in direction of runway.
if airbase:GetAirbaseCategory()==Airbase.Category.AIRDROME then
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
---
-- Airdrome
---
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
wp[#wp+1]=papp:WaypointAirTurningPoint(nil, UTILS.KnotsToKmph(SpeedLand), {}, "Final Approach")
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
elseif airbase:GetAirbaseCategory()==Airbase.Category.SHIP then
---
-- Ship
---
local pland=airbase:GetCoordinate()
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
end
-- Respawn?
if fc or world.event.S_EVENT_KILL then
+12 -2
View File
@@ -192,7 +192,16 @@ end
-- User functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set livery.
--- Set livery painted on all squadron 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:
--
-- * `DCS World OpenBeta\CoreMods\aircraft\<Aircraft Type>\<Livery Name>`
-- * `DCS World OpenBeta\Bazar\Liveries\<Aircraft Type>\<Livery Name>`
--
-- Or personal liveries you have installed somewhere in your saved games folder.
--
-- @param #SQUADRON self
-- @param #string LiveryName Name of the livery.
-- @return #SQUADRON self
@@ -201,9 +210,10 @@ function SQUADRON:SetLivery(LiveryName)
return self
end
--- Set skill.
--- Set skill level of all squadron team members.
-- @param #SQUADRON self
-- @param #string Skill Skill of all flights.
-- @usage mysquadron:SetSkill(AI.Skill.EXCELLENT)
-- @return #SQUADRON self
function SQUADRON:SetSkill(Skill)
self.skill=Skill