**ZONE**
- Fixed incorrect fillcolor alpha.

**COORDINATE**
- Fixed incorrect fillcolor alpha.

**AUFTRAG**
- Fixed `CASENHANCED` order of arguments wrong in docs.

**FLEET**
- Improved docs.
- Added ``:SetPathfinding` function

**OPSGROUP**
- Fixed RECON mission behaviour if not random.
- Improved stuck check if engaging.

**LEGION**
- Added weapon type as parameter for selecting cohort assets.

**COHORT**
- Added `:GetMissionRange` function that accounts for long range weapons.
- Added counting of asset ammo.
This commit is contained in:
Frank 2022-04-13 22:39:48 +02:00
parent 4ba0a2dafb
commit 24f8116fce
15 changed files with 698 additions and 159 deletions

View File

@ -10,6 +10,8 @@
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Core.Astar
-- @image CORE_Astar.png
@ -36,12 +38,10 @@
-- @field #table CostArg Optional arguments passed to the cost function.
-- @extends Core.Base#BASE
--- **When nothing goes right... Go left!**
--- *When nothing goes right... Go left!*
--
-- ===
--
-- ![Banner Image](..\Presentations\Astar\ASTAR_Main.jpg)
--
-- # The ASTAR Concept
--
-- Pathfinding algorithm.

View File

@ -2164,14 +2164,21 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=self:GetVec3()
Radius=Radius or 1000
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.circleToAll(Coalition, MarkID, vec3, Radius, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@ -2196,13 +2203,19 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=Endpoint:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.rectToAll(Coalition, MarkID, self:GetVec3(), vec3, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@ -2226,17 +2239,23 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local point1=self:GetVec3()
local point2=Coord2:GetVec3()
local point3=Coord3:GetVec3()
local point4=Coord4:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
trigger.action.quadToAll(Coalition, MarkID, self:GetVec3(), point2, point3, point4, Color, FillColor, LineType, ReadOnly, Text or "")
trigger.action.quadToAll(Coalition, MarkID, point1, point2, point3, point4, Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID
end
@ -2320,11 +2339,15 @@ do -- COORDINATE
ReadOnly=false
end
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.3
FontSize=FontSize or 14
trigger.action.textToAll(Coalition, MarkID, self:GetVec3(), Color, FillColor, FontSize, ReadOnly, Text or "Hello World")
return MarkID
end
@ -2346,13 +2369,19 @@ do -- COORDINATE
if ReadOnly==nil then
ReadOnly=false
end
local vec3=Endpoint:GetVec3()
Coalition=Coalition or -1
Color=Color or {1,0,0}
Color[4]=Alpha or 1.0
LineType=LineType or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillColor[4]=FillAlpha or 0.15
--trigger.action.textToAll(Coalition, MarkID, self:GetVec3(), Color, FillColor, FontSize, ReadOnly, Text or "Hello World")
trigger.action.arrowToAll(Coalition, MarkID, vec3, self:GetVec3(), Color, FillColor, LineType, ReadOnly, Text or "")
return MarkID

View File

@ -622,7 +622,7 @@ function ZONE_RADIUS:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, Lin
Color=Color or self:GetColorRGB()
Alpha=Alpha or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillAlpha=FillAlpha or self:GetColorAlpha()
self.DrawID=coordinate:CircleToAll(Radius, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly)
@ -1862,7 +1862,8 @@ function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlph
Color=Color or self:GetColorRGB()
Alpha=Alpha or 1
FillColor=FillColor or Color
FillColor=FillColor or UTILS.DeepCopy(Color)
FillAlpha=FillAlpha or self:GetColorAlpha()

View File

@ -23,7 +23,6 @@
-- ### Author: **funkyfranky**
--
-- ==
--
-- @module Ops.ArmyGroup
-- @image OPS_ArmyGroup.png
@ -38,7 +37,7 @@
-- @field Core.Set#SET_ZONE retreatZones Set of retreat zones.
-- @extends Ops.OpsGroup#OPSGROUP
--- *Your soul may belong to Jesus, but your ass belongs to the marines* -- Eugene B Sledge
--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B Sledge
--
-- ===
--

View File

@ -165,7 +165,7 @@
--
-- @extends Core.Fsm#FSM
--- *A warrior's mission is to foster the success of others.* - Morihei Ueshiba
--- *A warrior's mission is to foster the success of others.* -- Morihei Ueshiba
--
-- ===
--
@ -436,8 +436,9 @@ AUFTRAG.Type={
--- Special task description.
-- @type AUFTRAG.SpecialTask
-- @field #string FORMATION AI formation task.
-- @field #string PATROLZONE Patrol zone task.
-- @field #string RECON Recon task
-- @field #string RECON Recon task.
-- @field #string AMMOSUPPLY Ammo Supply.
-- @field #string FUELSUPPLY Fuel Supply.
-- @field #string ALERT5 Alert 5 task.
@ -450,6 +451,7 @@ AUFTRAG.Type={
-- @field #string NOTHING Nothing.
-- @field #string RELOCATECOHORT Relocate cohort.
AUFTRAG.SpecialTask={
FORMATION="Formation",
PATROLZONE="PatrolZone",
RECON="ReconMission",
AMMOSUPPLY="Ammo Supply",
@ -584,7 +586,7 @@ AUFTRAG.Category={
--- AUFTRAG class version.
-- @field #string version
AUFTRAG.version="0.9.2"
AUFTRAG.version="0.9.3"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -937,7 +939,7 @@ function AUFTRAG:NewANTISHIP(Target, Altitude)
return mission
end
--- **[AIR/HELICOPTER]** Create an HOVER mission.
--- **[AIR ROTARY]** Create an HOVER mission.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to hover.
-- @param #number Altitude Hover altitude in feet AGL. Default is 50 feet above ground.
@ -968,7 +970,7 @@ function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
mission.optionROE=ENUMS.ROE.ReturnFire
mission.optionROT=ENUMS.ROT.PassiveDefense
mission.categories={AUFTRAG.Category.AIRCRAFT}
mission.categories={AUFTRAG.Category.HELICOPTER}
mission.DCStask=mission:GetDCSMissionTask()
@ -1257,8 +1259,8 @@ end
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
-- @param #number Speed Speed in knots.
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`.
-- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere.
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`.
-- @return #AUFTRAG self
function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZoneSet, TargetTypes)
@ -4857,6 +4859,24 @@ function AUFTRAG:GetMissionEgressCoord()
return self.missionEgressCoord
end
--- Get coordinate which was set as mission waypoint coordinate.
-- @param #AUFTRAG self
-- @return Core.Point#COORDINATE Coordinate where the mission is executed or `#nil`.
function AUFTRAG:_GetMissionWaypointCoordSet()
-- Check if a coord has been explicitly set.
if self.missionWaypointCoord then
local coord=self.missionWaypointCoord
if self.missionAltitude then
coord.y=self.missionAltitude
end
return coord
end
end
--- Get coordinate of target. First unit/group of the set is used.
-- @param #AUFTRAG self
-- @param Wrapper.Group#GROUP group Group.
@ -5102,7 +5122,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
local DCStask={}
DCStask.id="ReconMission"
DCStask.id=AUFTRAG.SpecialTask.RECON
-- We create a "fake" DCS task and pass the parameters to the OPSGROUP.
local param={}
@ -5202,7 +5222,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
local DCStask={}
DCStask.id="Formation"
DCStask.id=AUFTRAG.SpecialTask.FORMATION
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
@ -5222,9 +5242,30 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
-- ARTY Mission --
------------------
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, self:GetTargetVec2(), self.artyRadius, self.artyShots, self.engageWeaponType, self.artyAltitude)
if self.artyShots==1 or self.artyRadius<10 or true then
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, self:GetTargetVec2(), self.artyRadius, self.artyShots, self.engageWeaponType, self.artyAltitude)
table.insert(DCStasks, DCStask)
else
local Vec2=self:GetTargetVec2()
local zone=ZONE_RADIUS:New("temp", Vec2, self.artyRadius)
for i=1,self.artyShots do
local vec2=zone:GetRandomVec2()
table.insert(DCStasks, DCStask)
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, vec2, 0, 1, self.engageWeaponType, self.artyAltitude)
table.insert(DCStasks, DCStask)
end
end
--table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.BARRAGE then
@ -5258,7 +5299,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
local DCStask={}
DCStask.id="PatrolZone"
DCStask.id=AUFTRAG.SpecialTask.PATROLZONE
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
@ -5278,7 +5319,7 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
local DCStask={}
DCStask.id="PatrolZone"
DCStask.id=AUFTRAG.SpecialTask.PATROLZONE
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}

View File

@ -118,7 +118,7 @@
--
-- ## Adding Fleets
--
-- Fleets are not implemented yet.
-- Fleets can be added via the @{#CHIEF.AddFleet}() function.
--
--
-- # Strategic (Capture) Zones
@ -866,12 +866,24 @@ end
-- @return #CHIEF self
function CHIEF:AddBrigade(Brigade)
-- Add brigade to the commander
-- Add brigade to the commander.
self:AddLegion(Brigade)
return self
end
--- Add a FLEET to the chief's commander.
-- @param #CHIEF self
-- @param Ops.Fleet#FLEET Fleet The fleet to add.
-- @return #CHIEF self
function CHIEF:AddFleet(Fleet)
-- Add fleet to the commander.
self:AddLegion(Fleet)
return self
end
--- Add a LEGION to the chief's commander.
-- @param #CHIEF self
-- @param Ops.Legion#LEGION Legion The legion to add.
@ -2373,7 +2385,7 @@ end
--- Get mission performance for a given TARGET.
-- @param #CHIEF self
-- @param Ops.Target#TARGET Target
-- @param Ops.Target#TARGET Target The target.
-- @return #table Mission performances of type `#CHIEF.MissionPerformance`.
function CHIEF:_GetMissionPerformanceFromTarget(Target)

View File

@ -47,7 +47,7 @@
-- @field #number cargobayLimit Cargo bay capacity in kg.
-- @extends Core.Fsm#FSM
--- *It is unbelievable what a platoon of twelve aircraft did to tip the balance* -- Adolf Galland
--- *I came, I saw, I conquered.* -- Julius Caesar
--
-- ===
--
@ -89,7 +89,7 @@ COHORT.version="0.3.0"
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Create FLOTILLA class.
-- DONE: Create FLOTILLA class.
-- DONE: Added check for properties.
-- DONE: Make general so that PLATOON and SQUADRON can inherit this class.
@ -613,6 +613,49 @@ function COHORT:ReturnTacan(channel)
self.tacanChannel[channel]=true
end
--- Add a weapon range for ARTY missions (@{Ops.Auftrag#AUFTRAG}).
-- @param #COHORT self
-- @param #number RangeMin Minimum range in nautical miles. Default 0 NM.
-- @param #number RangeMax Maximum range in nautical miles. Default 10 NM.
-- @param #number BitType Bit mask of weapon type for which the given min/max ranges apply. Default is `ENUMS.WeaponFlag.Auto`, i.e. for all weapon types.
-- @return #COHORT self
function COHORT:AddWeaponRange(RangeMin, RangeMax, BitType)
RangeMin=UTILS.NMToMeters(RangeMin or 0)
RangeMax=UTILS.NMToMeters(RangeMax or 10)
local weapon={} --Ops.OpsGroup#OPSGROUP.WeaponData
weapon.BitType=BitType or ENUMS.WeaponFlag.Auto
weapon.RangeMax=RangeMax
weapon.RangeMin=RangeMin
self.weaponData=self.weaponData or {}
self.weaponData[tostring(weapon.BitType)]=weapon
-- Debug info.
self:T(self.lid..string.format("Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax))
if self.verbose>=2 then
local text="Weapon data:"
for _,_weapondata in pairs(self.weaponData) do
local weapondata=_weapondata
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax)
end
self:I(self.lid..text)
end
return self
end
--- Get weapon range for given bit type.
-- @param #COHORT self
-- @param #number BitType Bit mask of weapon type.
-- @return Ops.OpsGroup#OPSGROUP.WeaponData Weapon data.
function COHORT:GetWeaponData(BitType)
return self.weaponData[tostring(BitType)]
end
--- Check if cohort is "OnDuty".
-- @param #COHORT self
-- @return #boolean If true, cohort is in state "OnDuty".
@ -1048,6 +1091,42 @@ function COHORT:GetRepairTime(Asset)
end
--- Get max mission range. We add the largest weapon range, e.g. for arty or naval if weapon data is available.
-- @param #COHORT self
-- @param #table WeaponTypes (Optional) Weapon bit type(s) to add to the total range. Default is the max weapon type available.
-- @return #number Range in meters.
function COHORT:GetMissionRange(WeaponTypes)
if WeaponTypes and type(WeaponTypes)~="table" then
WeaponTypes={WeaponTypes}
end
local function checkWeaponType(Weapon)
local weapon=Weapon --Ops.OpsGroup#OPSGROUP.WeaponData
if WeaponTypes and #WeaponTypes>0 then
for _,weapontype in pairs(WeaponTypes) do
if weapontype==weapon.BitType then
return true
end
end
return false
end
return true
end
-- Get max weapon range.
local WeaponRange=0
for _,_weapon in pairs(self.weaponData or {}) do
local weapon=_weapon --Ops.OpsGroup#OPSGROUP.WeaponData
if weapon.RangeMax>WeaponRange and checkWeaponType(weapon) then
WeaponRange=weapon.RangeMax
end
end
return self.engageRange+WeaponRange
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.
@ -1088,6 +1167,237 @@ function COHORT:CheckAttribute(Attributes)
return false
end
--- Check ammo.
-- @param #COHORT self
-- @return Ops.OpsGroup#OPSGROUP.Ammo Ammo.
function COHORT:_CheckAmmo()
-- Get units of group.
local units=self.templategroup:GetUnits()
-- Init counter.
local nammo=0
local nguns=0
local nshells=0
local nrockets=0
local nmissiles=0
local nmissilesAA=0
local nmissilesAG=0
local nmissilesAS=0
local nmissilesSA=0
local nmissilesBM=0
local nmissilesCR=0
local ntorps=0
local nbombs=0
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
-- Output.
local text=string.format("Unit %s:\n", unit:GetName())
-- Get ammo table.
local ammotable=unit:GetAmmo()
if ammotable then
-- Debug info.
self:T3(ammotable)
-- Loop over all weapons.
for w=1,#ammotable do
-- Weapon table.
local weapon=ammotable[w]
-- Descriptors.
local Desc=weapon["desc"]
-- Warhead.
local Warhead=Desc["warhead"]
-- Number of current weapon.
local Nammo=weapon["count"]
-- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3, torpedo=4
local Category=Desc["category"]
-- Get missile category: Weapon.MissileCategory AAM=1, SAM=2, BM=3, ANTI_SHIP=4, CRUISE=5, OTHER=6
local MissileCategory = (Category==Weapon.Category.MISSILE) and Desc.missileCategory or nil
-- Type name of current weapon.
local TypeName=Desc["typeName"]
-- WeaponName
local weaponString = UTILS.Split(TypeName,"%.")
local WeaponName = weaponString[#weaponString]
-- Range in meters. Seems only to exist for missiles (not shells).
local Rmin=Desc["rangeMin"] or 0
local Rmax=Desc["rangeMaxAltMin"] or 0
-- Caliber in mm.
local Caliber=Warhead and Warhead["caliber"] or 0
-- We are specifically looking for shells or rockets here.
if Category==Weapon.Category.SHELL then
---
-- SHELL
---
-- Add up all shells.
if Caliber<70 then
nguns=nguns+Nammo
else
nshells=nshells+Nammo
end
-- Debug info.
text=text..string.format("- %d shells [%s]: caliber=%d mm, range=%d - %d meters\n", Nammo, WeaponName, Caliber, Rmin, Rmax)
elseif Category==Weapon.Category.ROCKET then
---
-- ROCKET
---
-- Add up all rockets.
nrockets=nrockets+Nammo
-- Debug info.
text=text..string.format("- %d rockets [%s]: caliber=%d mm, range=%d - %d meters\n", Nammo, WeaponName, Caliber, Rmin, Rmax)
elseif Category==Weapon.Category.BOMB then
---
-- BOMB
---
-- Add up all rockets.
nbombs=nbombs+Nammo
-- Debug info.
text=text..string.format("- %d bombs [%s]: caliber=%d mm, range=%d - %d meters\n", Nammo, WeaponName, Caliber, Rmin, Rmax)
elseif Category==Weapon.Category.MISSILE then
---
-- MISSILE
---
-- Add up all cruise missiles (category 5)
if MissileCategory==Weapon.MissileCategory.AAM then
nmissiles=nmissiles+Nammo
nmissilesAA=nmissilesAA+Nammo
-- Auto add range for AA missles. Useless here as this is not an aircraft.
if Rmax>0 then
self:AddWeaponRange(UTILS.MetersToNM(Rmin), UTILS.MetersToNM(Rmax), ENUMS.WeaponFlag.AnyAA)
end
elseif MissileCategory==Weapon.MissileCategory.SAM then
nmissiles=nmissiles+Nammo
nmissilesSA=nmissilesSA+Nammo
-- Dont think there is a bit type for SAM.
if Rmax>0 then
--self:AddWeaponRange(Rmin, Rmax, ENUMS.WeaponFlag.AnyASM)
end
elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then
nmissiles=nmissiles+Nammo
nmissilesAS=nmissilesAS+Nammo
-- Auto add weapon range for anti-ship missile.
if Rmax>0 then
self:AddWeaponRange(UTILS.MetersToNM(Rmin), UTILS.MetersToNM(Rmax), ENUMS.WeaponFlag.AntiShipMissile)
end
elseif MissileCategory==Weapon.MissileCategory.BM then
nmissiles=nmissiles+Nammo
nmissilesBM=nmissilesBM+Nammo
-- Don't think there is a good bit type for ballistic missiles.
if Rmax>0 then
--self:AddWeaponRange(Rmin, Rmax, ENUMS.WeaponFlag.AnyASM)
end
elseif MissileCategory==Weapon.MissileCategory.CRUISE then
nmissiles=nmissiles+Nammo
nmissilesCR=nmissilesCR+Nammo
-- Auto add weapon range for cruise missile.
if Rmax>0 then
self:AddWeaponRange(UTILS.MetersToNM(Rmin), UTILS.MetersToNM(Rmax), ENUMS.WeaponFlag.CruiseMissile)
end
elseif MissileCategory==Weapon.MissileCategory.OTHER then
nmissiles=nmissiles+Nammo
nmissilesAG=nmissilesAG+Nammo
end
-- Debug info.
text=text..string.format("- %d %s missiles [%s]: caliber=%d mm, range=%d - %d meters\n", Nammo, self:_MissileCategoryName(MissileCategory), WeaponName, Caliber, Rmin, Rmax)
elseif Category==Weapon.Category.TORPEDO then
-- Add up all rockets.
ntorps=ntorps+Nammo
-- Debug info.
text=text..string.format("- %d torpedos [%s]: caliber=%d mm, range=%d - %d meters\n", Nammo, WeaponName, Caliber, Rmin, Rmax)
else
-- Debug info.
text=text..string.format("- %d unknown ammo of type %s (category=%d, missile category=%s)\n", Nammo, TypeName, Category, tostring(MissileCategory))
end
end
end
-- Debug text and send message.
if self.verbose>=5 then
self:I(self.lid..text)
else
self:T2(self.lid..text)
end
end
-- Total amount of ammunition.
nammo=nguns+nshells+nrockets+nmissiles+nbombs+ntorps
local ammo={} --Ops.OpsGroup#OPSGROUP.Ammo
ammo.Total=nammo
ammo.Guns=nguns
ammo.Shells=nshells
ammo.Rockets=nrockets
ammo.Bombs=nbombs
ammo.Torpedos=ntorps
ammo.Missiles=nmissiles
ammo.MissilesAA=nmissilesAA
ammo.MissilesAG=nmissilesAG
ammo.MissilesAS=nmissilesAS
ammo.MissilesCR=nmissilesCR
ammo.MissilesBM=nmissilesBM
ammo.MissilesSA=nmissilesSA
return ammo
end
--- Returns a name of a missile category.
-- @param #COHORT self
-- @param #number categorynumber Number of missile category from weapon missile category enumerator. See https://wiki.hoggitworld.com/view/DCS_Class_Weapon
-- @return #string Missile category name.
function COHORT:_MissileCategoryName(categorynumber)
local cat="unknown"
if categorynumber==Weapon.MissileCategory.AAM then
cat="air-to-air"
elseif categorynumber==Weapon.MissileCategory.SAM then
cat="surface-to-air"
elseif categorynumber==Weapon.MissileCategory.BM then
cat="ballistic"
elseif categorynumber==Weapon.MissileCategory.ANTI_SHIP then
cat="anti-ship"
elseif categorynumber==Weapon.MissileCategory.CRUISE then
cat="cruise"
elseif categorynumber==Weapon.MissileCategory.OTHER then
cat="other"
end
return cat
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -8,6 +8,8 @@
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Ops.Commander
-- @image OPS_Commander.png
@ -32,7 +34,7 @@
-- @field #table limitMission Table of limits for mission types.
-- @extends Core.Fsm#FSM
--- *He who has never leared to obey cannot be a good commander* -- Aristotle
--- *He who has never leared to obey cannot be a good commander.* -- Aristotle
--
-- ===
--

View File

@ -25,23 +25,44 @@
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
-- @field #boolean pathfinding Set pathfinding on for all spawned navy groups.
-- @extends Ops.Legion#LEGION
--- *I am not afraid of an Army of lions lead by a sheep; I am afraid of sheep lead by a lion* -- Alexander the Great
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The FLEET Concept
--
-- A FLEET consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
--
-- # Basic Setup
--
-- A new `FLEET` object can be created with the @{#FLEET.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
--
-- myFleet=FLEET:New("myWarehouseName", "1st Fleet")
-- myFleet:SetPortZone(ZonePort1stFleet)
-- myFleet:Start()
--
-- A fleet needs a *port zone*, which is set via the @{#FLEET.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
--
-- Finally, the fleet needs to be started using the @{#FLEET.Start}() function. If the fleet is not started, it will not process any requests.
--
-- ## Adding Flotillas
--
-- Flotillas can be added via the @{#FLEET.AddFlotilla}(`Flotilla`) function. See @{Ops.Flotilla#FLOTILLA} for how to create a flotilla.
--
-- myFleet:AddFlotilla(FlotillaTiconderoga)
-- myFleet:AddFlotilla(FlotillaPerry)
--
--
--
-- @field #FLEET
FLEET = {
ClassName = "FLEET",
verbose = 0,
rearmingZones = {},
refuellingZones = {},
verbose = 0,
pathfinding = false,
}
--- Supply Zone.
@ -59,7 +80,7 @@ FLEET.version="0.0.1"
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: .
-- TODO: Add routes?
-- DONE: Add weapon range.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -199,6 +220,15 @@ function FLEET:AddAssetToFlotilla(Flotilla, Nassets)
return self
end
--- Set pathfinding for all spawned naval groups.
-- @param #FLEET self
-- @param #boolean Switch If `true`, pathfinding is used.
-- @return #FLEET self
function FLEET:SetPathfinding(Switch)
self.pathfinding=Switch
return self
end
--- Define a set of retreat zones.
-- @param #FLEET self
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.

View File

@ -22,13 +22,13 @@
-- @field Ops.OpsGroup#OPSGROUP.WeaponData weaponData Weapon data table with key=BitType.
-- @extends Ops.Cohort#COHORT
--- *Some cool cohort quote* -- Known Author
--- *No captain can do very wrong if he places his ship alongside that of an enemy.* -- Horation Nelson
--
-- ===
--
-- # The FLOTILLA Concept
--
-- A FLOTILLA is essential part of a FLEET.
-- A FLOTILLA is an essential part of a FLEET.
--
--
--
@ -64,6 +64,7 @@ function FLOTILLA:New(TemplateGroupName, Ngroups, FlotillaName)
-- Inherit everything from COHORT class.
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, FlotillaName)) -- #FLOTILLA
self.ammo=self:_CheckAmmo()
return self
end
@ -90,41 +91,6 @@ function FLOTILLA:GetFleet()
return self.legion
end
--- Add a weapon range for ARTY auftrag.
-- @param #FLOTILLA self
-- @param #number RangeMin Minimum range in nautical miles. Default 0 NM.
-- @param #number RangeMax Maximum range in nautical miles. Default 10 NM.
-- @param #number BitType Bit mask of weapon type for which the given min/max ranges apply. Default is `ENUMS.WeaponFlag.Auto`, i.e. for all weapon types.
-- @return #FLOTILLA self
function FLOTILLA:AddWeaponRange(RangeMin, RangeMax, BitType)
RangeMin=UTILS.NMToMeters(RangeMin or 0)
RangeMax=UTILS.NMToMeters(RangeMax or 10)
local weapon={} --Ops.OpsGroup#OPSGROUP.WeaponData
weapon.BitType=BitType or ENUMS.WeaponFlag.Auto
weapon.RangeMax=RangeMax
weapon.RangeMin=RangeMin
self.weaponData=self.weaponData or {}
self.weaponData[tostring(weapon.BitType)]=weapon
-- Debug info.
self:T(self.lid..string.format("Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax))
if self.verbose>=2 then
local text="Weapon data:"
for _,_weapondata in pairs(self.weaponData) do
local weapondata=_weapondata
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax)
end
self:I(self.lid..text)
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -157,7 +123,6 @@ function FLOTILLA:onafterStatus(From, Event, To)
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
@ -168,8 +133,8 @@ function FLOTILLA:onafterStatus(From, Event, To)
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)
local text=string.format("%s [Type=%s, Call=%s, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
fsmstate, self.aircrafttype, callsign, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
self:T(self.lid..text)
-- Weapon data info.
@ -196,7 +161,7 @@ end
-- Misc Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Misc functions.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@
-- @field Ops.Chief#CHIEF chief Chief of this legion.
-- @extends Functional.Warehouse#WAREHOUSE
--- *Per aspera ad astra*
--- *Per aspera ad astra.*
--
-- ===
--
@ -47,13 +47,13 @@ LEGION = {
--- LEGION class version.
-- @field #string version
LEGION.version="0.3.0"
LEGION.version="0.3.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Create FLEED class.
-- DONE: Create FLEED class.
-- DONE: Relocate cohorts.
-- DONE: Aircraft will not start hot on Alert5.
-- DONE: OPS transport.
@ -1135,7 +1135,8 @@ function LEGION:onafterOpsOnMission(From, Event, To, OpsGroup, Mission)
-- Trigger event for Brigades.
self:ArmyOnMission(OpsGroup, Mission)
else
--TODO: Flotilla
-- Trigger event for Fleets.
self:NavyOnMission(OpsGroup, Mission)
end
-- Trigger event for chief.
@ -1363,6 +1364,11 @@ function LEGION:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Assignment.
local assignment=request.assignment
-- Set pathfinding for naval groups.
if self:IsFleet() then
flightgroup:SetPathfinding(self.pathfinding)
end
if string.find(assignment, "Mission-") then
---
@ -2029,7 +2035,8 @@ function LEGION:RecruitAssetsForMission(Mission)
end
-- Recuit assets.
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem)
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads,
Mission.engageRange, Mission.refuelSystem, nil, nil, nil, nil, nil, {Mission.engageWeaponType})
return recruited, assets, legions
end
@ -2142,10 +2149,11 @@ end
-- @param #table Categories Group categories.
-- @param #table Attributes Group attributes. See `GROUP.Attribute.`
-- @param #table Properties DCS attributes.
-- @param #table WeaponTypes Bit of weapon types.
-- @return #boolean If `true` enough assets could be recruited.
-- @return #table Recruited assets. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
-- @return #table Legions of recruited assets.
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, TotalWeight, Categories, Attributes, Properties)
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, TotalWeight, Categories, Attributes, Properties, WeaponTypes)
-- The recruited assets.
local Assets={}
@ -2202,8 +2210,23 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
end
end
--BASE:I({Attributes=Attributes})
--BASE:I({Properties=Properties})
--- Function to check weapon type.
local function CheckWeapon(_cohort)
local cohort=_cohort --Ops.Cohort#COHORT
if WeaponTypes and #WeaponTypes>0 then
for _,WeaponType in pairs(WeaponTypes) do
for _,_weaponData in pairs(cohort.weaponData or {}) do
local weaponData=_weaponData --Ops.OpsGroup#OPSGROUP.WeaponData
if weaponData.BitType==WeaponType then
return true
end
end
end
return false
else
return true
end
end
-- Loops over cohorts.
for _,_cohort in pairs(Cohorts) do
@ -2213,7 +2236,8 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
local TargetDistance=TargetVec2 and UTILS.VecDist2D(TargetVec2, cohort.legion:GetVec2()) or 0
-- Is in range?
local InRange=(RangeMax and math.max(RangeMax, cohort.engageRange) or cohort.engageRange) >= TargetDistance
local Rmax=cohort:GetMissionRange(WeaponTypes)
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
-- Has the requested refuelsystem?
local Refuel=RefuelSystem~=nil and (RefuelSystem==cohort.tankerSystem) or true
@ -2245,12 +2269,15 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
-- Right property (DCS attribute).
local RightProperty=CheckProperty(cohort)
-- Right weapon type.
local RightWeapon=CheckWeapon(cohort)
-- Debug info.
cohort:T2(cohort.lid..string.format("State=%s: Capable=%s, InRange=%s, Refuel=%s, CanCarry=%s, RightCategory=%s, RightAttribute=%s, RightProperty=%s",
cohort:GetState(), tostring(Capable), tostring(InRange), tostring(Refuel), tostring(CanCarry), tostring(RightCategory), tostring(RightAttribute), tostring(RightProperty)))
cohort:T2(cohort.lid..string.format("State=%s: Capable=%s, InRange=%s, Refuel=%s, CanCarry=%s, Category=%s, Attribute=%s, Property=%s, Weapon=%s",
cohort:GetState(), tostring(Capable), tostring(InRange), tostring(Refuel), tostring(CanCarry), tostring(RightCategory), tostring(RightAttribute), tostring(RightProperty), tostring(RightWeapon)))
-- Check OnDuty, capable, in range and refueling type (if TANKER).
if cohort:IsOnDuty() and Capable and InRange and Refuel and CanCarry and RightCategory and RightAttribute and RightProperty then
if cohort:IsOnDuty() and Capable and InRange and Refuel and CanCarry and RightCategory and RightAttribute and RightProperty and RightWeapon then
-- Recruit assets from cohort.
local assets, npayloads=cohort:RecruitAssets(MissionTypeRecruit, 999)

View File

@ -1496,16 +1496,56 @@ function NAVYGROUP:onafterDisengage(From, Event, To)
-- Restore previous ROE and alarm state.
self:SwitchROE(self.engage.roe)
self:SwitchAlarmstate(self.engage.alarmstate)
-- Get current task
local task=self:GetTaskCurrent()
-- Get if current task is ground attack.
if task and task.dcstask.id==AUFTRAG.SpecialTask.GROUNDATTACK then
self:T(self.lid.."Disengage with current task GROUNDATTACK ==> Task Done!")
self:TaskDone(task)
end
-- Remove current waypoint
if self.engage.Waypoint then
self:RemoveWaypointByID(self.engage.Waypoint.uid)
self:RemoveWaypointByID(self.engage.Waypoint.uid)
end
-- Check group is done
self:_CheckGroupDone(1)
end
--- On after "OutOfAmmo" event.
-- @param #NAVYGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function NAVYGROUP:onafterOutOfAmmo(From, Event, To)
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
-- Check if we want to retreat once out of ammo.
if self.retreatOnOutOfAmmo then
self:__Retreat(-1)
return
end
-- Third, check if we want to RTZ once out of ammo.
if self.rtzOnOutOfAmmo then
self:__RTZ(-1)
end
-- Get current task.
local task=self:GetTaskCurrent()
if task then
if task.dcstask.id=="FireAtPoint" or task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
self:T(self.lid..string.format("Cancelling current %s task because out of ammo!", task.dcstask.id))
self:TaskCancel(task)
end
end
end
--- On after "RTZ" event.
-- @param #NAVYGROUP self
-- @param #string From From state.
@ -1722,18 +1762,12 @@ function NAVYGROUP:_CheckFreePath(DistanceMax, dx)
offsetY=5.01
end
-- Current coordinate.
--local coordinate=self:GetCoordinate():SetAltitude(offsetY, true)
local vec3=self:GetVec3()
vec3.y=offsetY
-- Current heading.
local heading=self:GetHeading()
-- Check from 500 meters in front.
--coordinate=coordinate:Translate(500, heading, true)
local function LoS(dist)
local checkvec3=UTILS.VecTranslate(vec3, dist, heading)
local los=land.isVisible(vec3, checkvec3)
@ -1780,8 +1814,9 @@ function NAVYGROUP:_CheckFreePath(DistanceMax, dx)
return 0
end
local _check=check()
return check()
return _check
end
--- Check if group is turning.

View File

@ -136,7 +136,7 @@
--
-- @extends Core.Fsm#FSM
--- *A small group of determined and like-minded people can change the course of history* -- Mahatma Gandhi
--- *A small group of determined and like-minded people can change the course of history.* -- Mahatma Gandhi
--
-- ===
--
@ -3671,7 +3671,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Get mission of this task (if any).
local Mission=self:GetMissionByTaskID(self.taskcurrent)
if Task.dcstask.id=="Formation" then
if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
-- Set of group(s) to follow Mother.
local followSet=SET_GROUP:New():AddGroup(self.group)
@ -3681,7 +3681,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
local followUnit=UNIT:FindByName(param.unitname)
-- Define AI Formation object.
Task.formation=AI_FORMATION:New(followUnit, followSet, "Formation", "Follow X at given parameters.")
Task.formation=AI_FORMATION:New(followUnit, followSet, AUFTRAG.SpecialTask.FORMATION, "Follow X at given parameters.")
-- Formation parameters.
Task.formation:FormationCenterWing(-param.offsetX, 50, math.abs(param.altitude), 50, param.offsetZ, 50)
@ -3695,7 +3695,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Start formation FSM.
Task.formation:Start()
elseif Task.dcstask.id=="PatrolZone" then
elseif Task.dcstask.id==AUFTRAG.SpecialTask.PATROLZONE then
---
-- Task patrol zone.
@ -3735,7 +3735,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Set mission UID.
wp.missionUID=Mission and Mission.auftragsnummer or nil
elseif Task.dcstask.id=="ReconMission" then
elseif Task.dcstask.id==AUFTRAG.SpecialTask.RECON then
---
-- Task recon.
@ -3999,12 +3999,12 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
Task.stopflag:Set(1)
local done=false
if Task.dcstask.id=="Formation" then
if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
Task.formation:Stop()
done=true
elseif Task.dcstask.id=="PatrolZone" then
elseif Task.dcstask.id==AUFTRAG.SpecialTask.PATROLZONE then
done=true
elseif Task.dcstask.id=="ReconMission" then
elseif Task.dcstask.id==AUFTRAG.SpecialTask.RECON then
done=true
elseif Task.dcstask.id==AUFTRAG.SpecialTask.AMMOSUPPLY then
done=true
@ -4885,19 +4885,23 @@ function OPSGROUP:RouteToMission(mission, delay)
-- ARTY
---
-- Coord
local coord=waypointcoord
-- Get weapon range.
local weapondata=self:GetWeaponData(mission.engageWeaponType)
local coordInRange=nil --Core.Point#COORDINATE
if weapondata then
-- Get target coordinate.
local targetcoord=mission:GetTargetCoordinate()
-- Heading to target.
local heading=self:GetCoordinate():HeadingTo(targetcoord)
local heading=coord:HeadingTo(targetcoord)
-- Distance to target.
local dist=self:GetCoordinate():Get2DDistance(targetcoord)
local dist=coord:Get2DDistance(targetcoord)
-- Check if we are within range.
if dist>weapondata.RangeMax then
@ -4905,7 +4909,7 @@ function OPSGROUP:RouteToMission(mission, delay)
local d=(dist-weapondata.RangeMax)*1.1
-- New waypoint coord.
waypointcoord=self:GetCoordinate():Translate(d, heading)
coordInRange=coord:Translate(d, heading)
-- Debug info.
self:T(self.lid..string.format("Out of max range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(mission.engageWeaponType)))
@ -4914,7 +4918,7 @@ function OPSGROUP:RouteToMission(mission, delay)
local d=(dist-weapondata.RangeMin)*1.1
-- New waypoint coord.
waypointcoord=self:GetCoordinate():Translate(d, heading)
coordInRange=coord:Translate(d, heading)
-- Debug info.
self:T(self.lid..string.format("Out of min range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(mission.engageWeaponType)))
@ -4923,8 +4927,28 @@ function OPSGROUP:RouteToMission(mission, delay)
else
self:T(self.lid..string.format("No weapon data for weapon type %s", tostring(mission.engageWeaponType)))
end
end
if coordInRange then
-- Add waypoint at
local waypoint=nil --#OPSGROUP.Waypoint
if self:IsFlightgroup() then
waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
elseif self:IsArmygroup() then
waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false)
elseif self:IsNavygroup() then
waypoint=NAVYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
end
waypoint.missionUID=mission.auftragsnummer
-- Set waypoint coord to be the one in range. Take care of proper waypoint uid.
waypointcoord=coordInRange
uid=waypoint.uid
end
end
-- Add waypoint.
local waypoint=nil --#OPSGROUP.Waypoint
if self:IsFlightgroup() then
@ -5155,7 +5179,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
mission=self:GetMissionByTaskID(task.id)
end
if task and task.dcstask.id=="PatrolZone" then
if task and task.dcstask.id==AUFTRAG.SpecialTask.PATROLZONE then
---
-- SPECIAL TASK: Patrol Zone
@ -5194,7 +5218,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
end
wp.missionUID=mission and mission.auftragsnummer or nil
elseif task and task.dcstask.id=="ReconMission" then
elseif task and task.dcstask.id==AUFTRAG.SpecialTask.RECON then
---
-- SPECIAL TASK: Recon Mission
@ -5216,8 +5240,9 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
local n=1
if task.dcstask.params.randomly then
n=UTILS.GetRandomTableElement(self.reconindecies)
else
table.remove(self.reconindecies, n)
else
n=self.reconindecies[1]
table.remove(self.reconindecies, 1)
end
-- Zone object.
@ -9160,8 +9185,10 @@ function OPSGROUP:_CheckStuck()
-- Debug warning.
self:T(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
-- Give cruise command again.
if self:IsReturning() then
-- Check what is happening.
if self:IsEngaging() then
self:__Disengage(1)
elseif self:IsReturning() then
self:__RTZ(1)
else
self:__Cruise(1)
@ -9173,7 +9200,6 @@ function OPSGROUP:_CheckStuck()
self:T(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
--TODO: Stuck event!
-- Look for a current mission and cancel it as we do not seem to be able to perform it.
local mission=self:GetMissionCurrent()
if mission then
@ -11396,6 +11422,8 @@ function OPSGROUP:GetAmmoUnit(unit, display)
if display==nil then
display=false
end
unit=unit or self.group:GetUnit(1)
-- Init counter.
local nammo=0
@ -11420,12 +11448,18 @@ function OPSGROUP:GetAmmoUnit(unit, display)
if ammotable then
local weapons=#ammotable
--self:I(ammotable)
-- Loop over all weapons.
for w=1,weapons do
-- Number of current weapon.
local Nammo=ammotable[w]["count"]
-- Range in meters. Seems only to exist for missiles (not shells).
local rmin=ammotable[w]["desc"]["rangeMin"] or 0
local rmax=ammotable[w]["desc"]["rangeMaxAltMin"] or 0
-- Type name of current weapon.
local Tammo=ammotable[w]["desc"]["typeName"]
@ -11449,7 +11483,7 @@ function OPSGROUP:GetAmmoUnit(unit, display)
nshells=nshells+Nammo
-- Debug info.
text=text..string.format("- %d shells of type %s\n", Nammo, _weaponName)
text=text..string.format("- %d shells of type %s, range=%d - %d meters\n", Nammo, _weaponName, rmin, rmax)
elseif Category==Weapon.Category.ROCKET then
@ -11457,7 +11491,7 @@ function OPSGROUP:GetAmmoUnit(unit, display)
nrockets=nrockets+Nammo
-- Debug info.
text=text..string.format("- %d rockets of type %s\n", Nammo, _weaponName)
text=text..string.format("- %d rockets of type %s, \n", Nammo, _weaponName, rmin, rmax)
elseif Category==Weapon.Category.BOMB then
@ -11491,7 +11525,7 @@ function OPSGROUP:GetAmmoUnit(unit, display)
end
-- Debug info.
text=text..string.format("- %d %s missiles of type %s\n", Nammo, self:_MissileCategoryName(MissileCategory), _weaponName)
text=text..string.format("- %d %s missiles of type %s, range=%d - %d meters\n", Nammo, self:_MissileCategoryName(MissileCategory), _weaponName, rmin, rmax)
elseif Category==Weapon.Category.TORPEDO then

View File

@ -63,6 +63,8 @@ function PLATOON:New(TemplateGroupName, Ngroups, PlatoonName)
-- Inherit everything from COHORT class.
local self=BASE:Inherit(self, COHORT:New(TemplateGroupName, Ngroups, PlatoonName)) -- #PLATOON
-- Get ammo.
self.ammo=self:_CheckAmmo()
return self
end
@ -88,42 +90,6 @@ end
function PLATOON:GetBrigade()
return self.legion
end
--- Add a weapon range for ARTY auftrag.
-- @param #PLATOON self
-- @param #number RangeMin Minimum range in nautical miles. Default 0 NM.
-- @param #number RangeMax Maximum range in nautical miles. Default 10 NM.
-- @param #number BitType Bit mask of weapon type for which the given min/max ranges apply. Default is `ENUMS.WeaponFlag.Auto`, i.e. for all weapon types.
-- @return #PLATOON self
function PLATOON:AddWeaponRange(RangeMin, RangeMax, BitType)
RangeMin=UTILS.NMToMeters(RangeMin or 0)
RangeMax=UTILS.NMToMeters(RangeMax or 10)
local weapon={} --Ops.OpsGroup#OPSGROUP.WeaponData
weapon.BitType=BitType or ENUMS.WeaponFlag.Auto
weapon.RangeMax=RangeMax
weapon.RangeMin=RangeMin
self.weaponData=self.weaponData or {}
self.weaponData[tostring(weapon.BitType)]=weapon
-- Debug info.
self:T(self.lid..string.format("Adding weapon data: Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapon.BitType), weapon.RangeMin, weapon.RangeMax))
if self.verbose>=2 then
local text="Weapon data:"
for _,_weapondata in pairs(self.weaponData) do
local weapondata=_weapondata
text=text..string.format("\n- Bit=%s, Rmin=%d m, Rmax=%d m", tostring(weapondata.BitType), weapondata.RangeMin, weapondata.RangeMax)
end
self:I(self.lid..text)
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Start & Status
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -156,7 +122,6 @@ function PLATOON:onafterStatus(From, Event, To)
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
@ -167,8 +132,8 @@ function PLATOON:onafterStatus(From, Event, To)
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)
local text=string.format("%s [Type=%s, Call=%s, Skill=%s]: Assets Total=%d, Stock=%d, Mission=%d [Active=%d, Queue=%d]",
fsmstate, self.aircrafttype, callsign, skill, NassetsTot, NassetsInS, NassetsQP, NassetsP, NassetsQ)
self:T(self.lid..text)
-- Weapon data info.

View File

@ -126,6 +126,8 @@ ENUMS.WeaponFlag={
AnyMissile = 268402688, -- AnyASM + AnyAAM
--- Guns
Cannons = 805306368, -- GUN_POD + BuiltInCannon
--- Torpedo
Torpedo = 4294967296,
---
-- Even More Genral
Auto = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
@ -136,6 +138,93 @@ ENUMS.WeaponFlag={
AnyGuided = 268402702, -- Any Guided Weapon
}
--- Weapon types by category. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on hoggit wiki.
-- @type ENUMS.WeaponType
-- @field #table Bomb Bombs.
-- @field #table Rocket Rocket.
-- @field #table Gun Guns.
-- @field #table Missile Missiles.
-- @field #table AAM Air-to-Air missiles.
-- @field #table Torpedo Torpedos.
-- @field #table Any Combinations.
ENUMS.WeaponType={}
ENUMS.WeaponType.Bomb={
-- Bombs
LGB = 2,
TvGB = 4,
SNSGB = 8,
HEBomb = 16,
Penetrator = 32,
NapalmBomb = 64,
FAEBomb = 128,
ClusterBomb = 256,
Dispencer = 512,
CandleBomb = 1024,
ParachuteBomb = 2147483648,
-- Combinations
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
}
ENUMS.WeaponType.Rocket={
-- Rockets
LightRocket = 2048,
MarkerRocket = 4096,
CandleRocket = 8192,
HeavyRocket = 16384,
-- Combinations
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
}
ENUMS.WeaponType.Gun={
-- Guns
GunPod = 268435456,
BuiltInCannon = 536870912,
-- Combinations
Cannons = 805306368, -- GUN_POD + BuiltInCannon
}
ENUMS.WeaponType.Missile={
-- Missiles
AntiRadarMissile = 32768,
AntiShipMissile = 65536,
AntiTankMissile = 131072,
FireAndForgetASM = 262144,
LaserASM = 524288,
TeleASM = 1048576,
CruiseMissile = 2097152,
AntiRadarMissile2 = 1073741824,
-- Combinations
GuidedASM = 1572864, -- (LaserASM + TeleASM)
TacticalASM = 1835008, -- (GuidedASM + FireAndForgetASM)
AnyASM = 4161536, -- (AntiRadarMissile + AntiShipMissile + AntiTankMissile + FireAndForgetASM + GuidedASM + CruiseMissile)
AnyASM2 = 1077903360, -- 4161536+1073741824,
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
AnyMissile = 268402688, -- AnyASM + AnyAAM
}
ENUMS.WeaponType.AAM={
-- Air-To-Air Missiles
SRAM = 4194304,
MRAAM = 8388608,
LRAAM = 16777216,
IR_AAM = 33554432,
SAR_AAM = 67108864,
AR_AAM = 134217728,
-- Combinations
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
}
ENUMS.WeaponType.Torpedo={
-- Torpedo
Torpedo = 4294967296,
}
ENUMS.WeaponType.Any={
-- General combinations
Weapon = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
AG = 2956984318, -- Any Air-To-Ground Weapon
AA = 264241152, -- Any Air-To-Air Weapon
Unguided = 2952822768, -- Any Unguided Weapon
Guided = 268402702, -- Any Guided Weapon
}
--- Mission tasks.
-- @type ENUMS.MissionTask
-- @field #string NOTHING No special task. Group can perform the minimal tasks: Orbit, Refuelling, Follow and Aerobatics.