mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
OPS
** ARMYGROUP** - Added suppression option **COMMANDER** - Added function to add targets with defined resources **OPSGROUP** - Added option to pause multiple missions **INTEL** - Fixed bug in cluster calc **LEGION** - Added function to get alive opsgroups **TARGET** * Added start condition
This commit is contained in:
parent
d3d815f26a
commit
ae54cd8fde
@ -1543,6 +1543,33 @@ function DATABASE:FindOpsGroup(groupname)
|
|||||||
return self.FLIGHTGROUPS[groupname]
|
return self.FLIGHTGROUPS[groupname]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Find an OPSGROUP (FLIGHTGROUP, ARMYGROUP, NAVYGROUP) in the data base for a given unit.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string unitname Unit name. Can also be passed as UNIT object.
|
||||||
|
-- @return Ops.OpsGroup#OPSGROUP OPS group object.
|
||||||
|
function DATABASE:FindOpsGroupFromUnit(unitname)
|
||||||
|
|
||||||
|
local unit=nil --Wrapper.Unit#UNIT
|
||||||
|
local groupname
|
||||||
|
|
||||||
|
-- Get group and group name.
|
||||||
|
if type(unitname)=="string" then
|
||||||
|
unit=UNIT:FindByName(unitname)
|
||||||
|
else
|
||||||
|
unit=unitname
|
||||||
|
end
|
||||||
|
|
||||||
|
if unit then
|
||||||
|
groupname=unit:GetGroup():GetName()
|
||||||
|
end
|
||||||
|
|
||||||
|
if groupname then
|
||||||
|
return self.FLIGHTGROUPS[groupname]
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Add a flight control to the data base.
|
--- Add a flight control to the data base.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol
|
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol
|
||||||
|
|||||||
@ -6395,6 +6395,14 @@ do -- SET_OPSGROUP
|
|||||||
self:Added(ObjectName, object)
|
self:Added(ObjectName, object)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using the Object Name as the index.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Ops.OpsGroup#OPSGROUP Object Ops group
|
||||||
|
-- @return Core.Base#BASE The added BASE Object.
|
||||||
|
function SET_OPSGROUP:AddObject(Object)
|
||||||
|
self:Add(Object.groupname, Object)
|
||||||
|
end
|
||||||
|
|
||||||
--- Add a GROUP or OPSGROUP object to the set.
|
--- Add a GROUP or OPSGROUP object to the set.
|
||||||
-- **NOTE** that an OPSGROUP is automatically created from the GROUP if it does not exist already.
|
-- **NOTE** that an OPSGROUP is automatically created from the GROUP if it does not exist already.
|
||||||
-- @param Core.Set#SET_OPSGROUP self
|
-- @param Core.Set#SET_OPSGROUP self
|
||||||
|
|||||||
@ -349,6 +349,7 @@
|
|||||||
-- * @{#WAREHOUSE.Attribute.GROUND_APC} Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
-- * @{#WAREHOUSE.Attribute.GROUND_APC} Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
||||||
-- * @{#WAREHOUSE.Attribute.GROUND_TRUCK} Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
-- * @{#WAREHOUSE.Attribute.GROUND_TRUCK} Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
||||||
-- * @{#WAREHOUSE.Attribute.GROUND_INFANTRY} Ground infantry assets.
|
-- * @{#WAREHOUSE.Attribute.GROUND_INFANTRY} Ground infantry assets.
|
||||||
|
-- * @{#WAREHOUSE.Attribute.GROUND_IFV} Ground infantry fighting vehicle.
|
||||||
-- * @{#WAREHOUSE.Attribute.GROUND_ARTILLERY} Artillery assets.
|
-- * @{#WAREHOUSE.Attribute.GROUND_ARTILLERY} Artillery assets.
|
||||||
-- * @{#WAREHOUSE.Attribute.GROUND_TANK} Tanks (modern or old).
|
-- * @{#WAREHOUSE.Attribute.GROUND_TANK} Tanks (modern or old).
|
||||||
-- * @{#WAREHOUSE.Attribute.GROUND_TRAIN} Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
-- * @{#WAREHOUSE.Attribute.GROUND_TRAIN} Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
||||||
@ -1704,6 +1705,7 @@ WAREHOUSE.Descriptor = {
|
|||||||
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
||||||
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
||||||
-- @field #string GROUND_INFANTRY Ground infantry assets.
|
-- @field #string GROUND_INFANTRY Ground infantry assets.
|
||||||
|
-- @field #string GROUND_IFV Ground infantry fighting vehicle.
|
||||||
-- @field #string GROUND_ARTILLERY Artillery assets.
|
-- @field #string GROUND_ARTILLERY Artillery assets.
|
||||||
-- @field #string GROUND_TANK Tanks (modern or old).
|
-- @field #string GROUND_TANK Tanks (modern or old).
|
||||||
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
||||||
@ -1730,6 +1732,7 @@ WAREHOUSE.Attribute = {
|
|||||||
GROUND_APC="Ground_APC",
|
GROUND_APC="Ground_APC",
|
||||||
GROUND_TRUCK="Ground_Truck",
|
GROUND_TRUCK="Ground_Truck",
|
||||||
GROUND_INFANTRY="Ground_Infantry",
|
GROUND_INFANTRY="Ground_Infantry",
|
||||||
|
GROUND_IFV="Ground_IFV",
|
||||||
GROUND_ARTILLERY="Ground_Artillery",
|
GROUND_ARTILLERY="Ground_Artillery",
|
||||||
GROUND_TANK="Ground_Tank",
|
GROUND_TANK="Ground_Tank",
|
||||||
GROUND_TRAIN="Ground_Train",
|
GROUND_TRAIN="Ground_Train",
|
||||||
@ -8352,9 +8355,10 @@ function WAREHOUSE:_GetAttribute(group)
|
|||||||
--- Ground ---
|
--- Ground ---
|
||||||
--------------
|
--------------
|
||||||
-- Ground
|
-- Ground
|
||||||
local apc=group:HasAttribute("Infantry carriers")
|
local apc=group:HasAttribute("APC") --("Infantry carriers")
|
||||||
local truck=group:HasAttribute("Trucks") and group:GetCategory()==Group.Category.GROUND
|
local truck=group:HasAttribute("Trucks") and group:GetCategory()==Group.Category.GROUND
|
||||||
local infantry=group:HasAttribute("Infantry")
|
local infantry=group:HasAttribute("Infantry")
|
||||||
|
local ifv=group:HasAttribute("IFV")
|
||||||
local artillery=group:HasAttribute("Artillery")
|
local artillery=group:HasAttribute("Artillery")
|
||||||
local tank=group:HasAttribute("Old Tanks") or group:HasAttribute("Modern Tanks")
|
local tank=group:HasAttribute("Old Tanks") or group:HasAttribute("Modern Tanks")
|
||||||
local aaa=group:HasAttribute("AAA")
|
local aaa=group:HasAttribute("AAA")
|
||||||
@ -8391,6 +8395,8 @@ function WAREHOUSE:_GetAttribute(group)
|
|||||||
attribute=WAREHOUSE.Attribute.AIR_UAV
|
attribute=WAREHOUSE.Attribute.AIR_UAV
|
||||||
elseif apc then
|
elseif apc then
|
||||||
attribute=WAREHOUSE.Attribute.GROUND_APC
|
attribute=WAREHOUSE.Attribute.GROUND_APC
|
||||||
|
elseif ifv then
|
||||||
|
attribute=WAREHOUSE.Attribute.GROUND_IFV
|
||||||
elseif infantry then
|
elseif infantry then
|
||||||
attribute=WAREHOUSE.Attribute.GROUND_INFANTRY
|
attribute=WAREHOUSE.Attribute.GROUND_INFANTRY
|
||||||
elseif artillery then
|
elseif artillery then
|
||||||
|
|||||||
@ -34,6 +34,11 @@
|
|||||||
-- @field #boolean isMobile If true, group is mobile.
|
-- @field #boolean isMobile If true, group is mobile.
|
||||||
-- @field #ARMYGROUP.Target engage Engage target.
|
-- @field #ARMYGROUP.Target engage Engage target.
|
||||||
-- @field Core.Set#SET_ZONE retreatZones Set of retreat zones.
|
-- @field Core.Set#SET_ZONE retreatZones Set of retreat zones.
|
||||||
|
-- @field #boolean suppressOn Bla
|
||||||
|
-- @field #boolean isSuppressed Bla
|
||||||
|
-- @field #number TsuppressMin Bla
|
||||||
|
-- @field #number TsuppressMax Bla
|
||||||
|
-- @field #number TsuppressAve Bla
|
||||||
-- @extends Ops.OpsGroup#OPSGROUP
|
-- @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
|
||||||
@ -122,6 +127,9 @@ function ARMYGROUP:New(group)
|
|||||||
self:AddTransition("*", "Retreat", "Retreating") -- Order a retreat.
|
self:AddTransition("*", "Retreat", "Retreating") -- Order a retreat.
|
||||||
self:AddTransition("Retreating", "Retreated", "Retreated") -- Group retreated.
|
self:AddTransition("Retreating", "Retreated", "Retreated") -- Group retreated.
|
||||||
|
|
||||||
|
self:AddTransition("*", "Suppressed", "*") -- Group is suppressed
|
||||||
|
self:AddTransition("*", "Unsuppressed", "*") -- Group is unsuppressed.
|
||||||
|
|
||||||
self:AddTransition("Cruising", "EngageTarget", "Engaging") -- Engage a target from Cruising state
|
self:AddTransition("Cruising", "EngageTarget", "Engaging") -- Engage a target from Cruising state
|
||||||
self:AddTransition("Holding", "EngageTarget", "Engaging") -- Engage a target from Holding state
|
self:AddTransition("Holding", "EngageTarget", "Engaging") -- Engage a target from Holding state
|
||||||
self:AddTransition("OnDetour", "EngageTarget", "Engaging") -- Engage a target from OnDetour state
|
self:AddTransition("OnDetour", "EngageTarget", "Engaging") -- Engage a target from OnDetour state
|
||||||
@ -280,6 +288,7 @@ function ARMYGROUP:New(group)
|
|||||||
-- @function [parent=#ARMYGROUP] EngageTarget
|
-- @function [parent=#ARMYGROUP] EngageTarget
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
||||||
|
-- @param #number Speed Speed in knots.
|
||||||
-- @param #string Formation Formation used in the engagement.
|
-- @param #string Formation Formation used in the engagement.
|
||||||
|
|
||||||
--- Triggers the FSM event "EngageTarget" after a delay.
|
--- Triggers the FSM event "EngageTarget" after a delay.
|
||||||
@ -287,6 +296,7 @@ function ARMYGROUP:New(group)
|
|||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
||||||
|
-- @param #number Speed Speed in knots.
|
||||||
-- @param #string Formation Formation used in the engagement.
|
-- @param #string Formation Formation used in the engagement.
|
||||||
|
|
||||||
|
|
||||||
@ -297,6 +307,7 @@ function ARMYGROUP:New(group)
|
|||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
||||||
|
-- @param #number Speed Speed in knots.
|
||||||
-- @param #string Formation Formation used in the engagement.
|
-- @param #string Formation Formation used in the engagement.
|
||||||
|
|
||||||
|
|
||||||
@ -386,7 +397,7 @@ function ARMYGROUP:New(group)
|
|||||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||||
--self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
||||||
|
|
||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
self.timerStatus=TIMER:New(self.Status, self):Start(1, 30)
|
self.timerStatus=TIMER:New(self.Status, self):Start(1, 30)
|
||||||
@ -572,6 +583,47 @@ function ARMYGROUP:AddRetreatZone(RetreatZone)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set suppression on. average, minimum and maximum time a unit is suppressed each time it gets hit.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #number Tave Average time [seconds] a group will be suppressed. Default is 15 seconds.
|
||||||
|
-- @param #number Tmin (Optional) Minimum time [seconds] a group will be suppressed. Default is 5 seconds.
|
||||||
|
-- @param #number Tmax (Optional) Maximum time a group will be suppressed. Default is 25 seconds.
|
||||||
|
-- @return #ARMYGROUP self
|
||||||
|
function ARMYGROUP:SetSuppressionOn(Tave, Tmin, Tmax)
|
||||||
|
|
||||||
|
-- Activate suppression.
|
||||||
|
self.suppressionOn=true
|
||||||
|
|
||||||
|
-- Minimum suppression time is input or default 5 sec (but at least 1 second).
|
||||||
|
self.TsuppressMin=Tmin or 1
|
||||||
|
self.TsuppressMin=math.max(self.TsuppressMin, 1)
|
||||||
|
|
||||||
|
-- Maximum suppression time is input or default but at least Tmin.
|
||||||
|
self.TsuppressMax=Tmax or 15
|
||||||
|
self.TsuppressMax=math.max(self.TsuppressMax, self.TsuppressMin)
|
||||||
|
|
||||||
|
-- Expected suppression time is input or default but at leat Tmin and at most Tmax.
|
||||||
|
self.TsuppressAve=Tave or 10
|
||||||
|
self.TsuppressAve=math.max(self.TsuppressMin)
|
||||||
|
self.TsuppressAve=math.min(self.TsuppressMax)
|
||||||
|
|
||||||
|
-- Debug Info
|
||||||
|
self:T(self.lid..string.format("Set ave suppression time to %d seconds.", self.TsuppressAve))
|
||||||
|
self:T(self.lid..string.format("Set min suppression time to %d seconds.", self.TsuppressMin))
|
||||||
|
self:T(self.lid..string.format("Set max suppression time to %d seconds.", self.TsuppressMax))
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set suppression off.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @return #ARMYGROUP self
|
||||||
|
function ARMYGROUP:SetSuppressionOff()
|
||||||
|
-- Activate suppression.
|
||||||
|
self.suppressionOn=false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if the group is currently holding its positon.
|
--- Check if the group is currently holding its positon.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @return #boolean If true, group was ordered to hold.
|
-- @return #boolean If true, group was ordered to hold.
|
||||||
@ -654,10 +706,14 @@ function ARMYGROUP:Status()
|
|||||||
if timer.getAbsTime()>self.Twaiting+self.dTwait then
|
if timer.getAbsTime()>self.Twaiting+self.dTwait then
|
||||||
self.Twaiting=nil
|
self.Twaiting=nil
|
||||||
self.dTwait=nil
|
self.dTwait=nil
|
||||||
|
if self:_CountPausedMissions()>0 then
|
||||||
|
self:UnpauseMission()
|
||||||
|
else
|
||||||
self:Cruise()
|
self:Cruise()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
-- Check damage of elements and group.
|
-- Check damage of elements and group.
|
||||||
@ -799,22 +855,6 @@ end
|
|||||||
-- DCS Events ==> See OPSGROUP
|
-- DCS Events ==> See OPSGROUP
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Event function handling when a unit is hit.
|
|
||||||
-- @param #ARMYGROUP self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
|
||||||
function ARMYGROUP:OnEventHit(EventData)
|
|
||||||
|
|
||||||
-- Check that this is the right group.
|
|
||||||
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
|
||||||
local unit=EventData.IniUnit
|
|
||||||
local group=EventData.IniGroup
|
|
||||||
local unitname=EventData.IniUnitName
|
|
||||||
|
|
||||||
-- TODO: suppression
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- FSM Events
|
-- FSM Events
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -1126,7 +1166,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
|||||||
self.speedWp=wp.speed
|
self.speedWp=wp.speed
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
if self.verbose>=10 or true then
|
if self.verbose>=10 then
|
||||||
for i,_wp in pairs(waypoints) do
|
for i,_wp in pairs(waypoints) do
|
||||||
local wp=_wp --Ops.OpsGroup#OPSGROUP.Waypoint
|
local wp=_wp --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||||
|
|
||||||
@ -1228,6 +1268,16 @@ end
|
|||||||
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
||||||
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
-- Fist, check if we want to rearm once out-of-ammo.
|
-- Fist, check if we want to rearm once out-of-ammo.
|
||||||
--TODO: IsMobile() check
|
--TODO: IsMobile() check
|
||||||
if self.rearmOnOutOfAmmo then
|
if self.rearmOnOutOfAmmo then
|
||||||
@ -1251,16 +1301,6 @@ function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
|||||||
self:__RTZ(-1)
|
self:__RTZ(-1)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1292,6 +1332,15 @@ function ARMYGROUP:onbeforeRearm(From, Event, To, Coordinate, Formation)
|
|||||||
allowed=false
|
allowed=false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check if coordinate is provided.
|
||||||
|
if allowed and not Coordinate then
|
||||||
|
local truck=self:FindNearestAmmoSupply()
|
||||||
|
if truck and truck:IsAlive() then
|
||||||
|
self:__Rearm(-0.1, truck:GetCoordinate(), Formation)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-- Try again...
|
-- Try again...
|
||||||
if dt then
|
if dt then
|
||||||
self:T(self.lid..string.format("Trying Rearm again in %.2f sec", dt))
|
self:T(self.lid..string.format("Trying Rearm again in %.2f sec", dt))
|
||||||
@ -1589,7 +1638,7 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target, Speed, Formation
|
|||||||
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
|
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
|
||||||
|
|
||||||
-- Get a coordinate close to the target.
|
-- Get a coordinate close to the target.
|
||||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.95)
|
||||||
|
|
||||||
-- Backup ROE and alarm state.
|
-- Backup ROE and alarm state.
|
||||||
self.engage.roe=self:GetROE()
|
self.engage.roe=self:GetROE()
|
||||||
@ -1752,6 +1801,21 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed, Formation)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "Hit" event.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Wrapper.Unit#UNIT Enemy Unit that hit the element or `nil`.
|
||||||
|
function ARMYGROUP:onafterHit(From, Event, To, Enemy)
|
||||||
|
self:T(self.lid..string.format("ArmyGroup hit by %s", Enemy and Enemy:GetName() or "unknown"))
|
||||||
|
|
||||||
|
if self.suppressionOn then
|
||||||
|
env.info(self.lid.."FF suppress")
|
||||||
|
self:_Suppress()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Routing
|
-- Routing
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -1996,6 +2060,100 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Suppress fire of the group by setting its ROE to weapon hold.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
function ARMYGROUP:_Suppress()
|
||||||
|
|
||||||
|
-- Current time.
|
||||||
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
|
-- Current ROE
|
||||||
|
local currROE=self:GetROE()
|
||||||
|
|
||||||
|
|
||||||
|
-- Get randomized time the unit is suppressed.
|
||||||
|
local sigma=(self.TsuppressMax-self.TsuppressMin)/4
|
||||||
|
|
||||||
|
-- Gaussian distribution.
|
||||||
|
local Tsuppress=UTILS.RandomGaussian(self.TsuppressAve,sigma,self.TsuppressMin, self.TsuppressMax)
|
||||||
|
|
||||||
|
-- Time at which the suppression is over.
|
||||||
|
local renew=true
|
||||||
|
if not self.TsuppressionOver then
|
||||||
|
|
||||||
|
-- Group is not suppressed currently.
|
||||||
|
self.TsuppressionOver=Tnow+Tsuppress
|
||||||
|
|
||||||
|
-- Group will hold their weapons.
|
||||||
|
self:SwitchROE(ENUMS.ROE.WeaponHold)
|
||||||
|
|
||||||
|
-- Backup ROE.
|
||||||
|
self.suppressionROE=currROE
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Check if suppression is longer than current time.
|
||||||
|
if Tsuppress+Tnow > self.TsuppressionOver then
|
||||||
|
self.TsuppressionOver=Tnow+Tsuppress
|
||||||
|
else
|
||||||
|
renew=false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Recovery event will be called in Tsuppress seconds.
|
||||||
|
if renew then
|
||||||
|
self:__Unsuppressed(self.TsuppressionOver-Tnow)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Suppressed for %d sec", Tsuppress))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Before "Recovered" event. Check if suppression time is over.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @return #boolean
|
||||||
|
function ARMYGROUP:onbeforeUnsuppressed(From, Event, To)
|
||||||
|
|
||||||
|
-- Current time.
|
||||||
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
|
-- Debug info
|
||||||
|
self:T(self.lid..string.format("onbeforeRecovered: Time now: %d - Time over: %d", Tnow, self.TsuppressionOver))
|
||||||
|
|
||||||
|
-- Recovery is only possible if enough time since the last hit has passed.
|
||||||
|
if Tnow >= self.TsuppressionOver then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- After "Recovered" event. Group has recovered and its ROE is set back to the "normal" unsuppressed state. Optionally the group is flared green.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function ARMYGROUP:onafterUnsuppressed(From, Event, To)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
local text=string.format("Group %s has recovered!", self:GetName())
|
||||||
|
MESSAGE:New(text, 10):ToAll()
|
||||||
|
self:T(self.lid..text)
|
||||||
|
|
||||||
|
-- Set ROE back to default.
|
||||||
|
self:SwitchROE(self.suppressionROE)
|
||||||
|
|
||||||
|
-- Flare unit green.
|
||||||
|
if true then
|
||||||
|
self.group:FlareGreen()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -2529,6 +2529,21 @@ function AUFTRAG:GetRequiredAssets(Legion)
|
|||||||
return Nmin, Nmax
|
return Nmin, Nmax
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[LEGION, COMMANDER, CHIEF]** Set that only alive (spawned) assets are considered.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param #boolean Switch If true or nil, only active assets. If false
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:SetAssetsStayAlive(Switch)
|
||||||
|
|
||||||
|
if Switch==nil then
|
||||||
|
Switch=true
|
||||||
|
end
|
||||||
|
|
||||||
|
self.assetStayAlive=Switch
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- **[LEGION, COMMANDER, CHIEF]** Define how many assets are required that escort the mission assets.
|
--- **[LEGION, COMMANDER, CHIEF]** Define how many assets are required that escort the mission assets.
|
||||||
-- Only used if the mission is handled by a **LEGION** (AIRWING, BRIGADE, FLEET) or higher level.
|
-- Only used if the mission is handled by a **LEGION** (AIRWING, BRIGADE, FLEET) or higher level.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
|
|||||||
@ -955,6 +955,7 @@ end
|
|||||||
function CHIEF:AddTarget(Target)
|
function CHIEF:AddTarget(Target)
|
||||||
|
|
||||||
if not self:IsTarget(Target) then
|
if not self:IsTarget(Target) then
|
||||||
|
Target.chief=self
|
||||||
table.insert(self.targetqueue, Target)
|
table.insert(self.targetqueue, Target)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1536,7 +1537,7 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
for _,_target in pairs(self.targetqueue) do
|
for _,_target in pairs(self.targetqueue) do
|
||||||
local target=_target --Ops.Target#TARGET
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
if target and target:IsAlive() and target.mission and target.mission:IsNotOver() then
|
if target and target:IsAlive() and target.chief and target.mission and target.mission:IsNotOver() then
|
||||||
|
|
||||||
local inborder=self:CheckTargetInZones(target, self.borderzoneset)
|
local inborder=self:CheckTargetInZones(target, self.borderzoneset)
|
||||||
|
|
||||||
|
|||||||
@ -987,6 +987,31 @@ function COHORT:CountAssets(InStock, MissionTypes, Attributes)
|
|||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get OPSGROUPs.
|
||||||
|
-- @param #COHORT self
|
||||||
|
-- @param #table MissionTypes (Optional) Count only assest that can perform certain mission type(s). Default is all types.
|
||||||
|
-- @param #table Attributes (Optional) Count only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||||
|
-- @return Core.Set#SET_OPSGROUPS Ops groups set.
|
||||||
|
function COHORT:GetOpsGroups(MissionTypes, Attributes)
|
||||||
|
|
||||||
|
local set=SET_OPSGROUP:New()
|
||||||
|
|
||||||
|
for _,_asset in pairs(self.assets) do
|
||||||
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
|
if MissionTypes==nil or AUFTRAG.CheckMissionCapability(MissionTypes, self.missiontypes) then
|
||||||
|
if Attributes==nil or self:CheckAttribute(Attributes) then
|
||||||
|
if asset.flightgroup and asset.flightgroup:IsAlive() then
|
||||||
|
--set:AddObject(asset.flightgroup)
|
||||||
|
set:AddGroup(asset.flightgroup)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return set
|
||||||
|
end
|
||||||
|
|
||||||
--- Get assets for a mission.
|
--- Get assets for a mission.
|
||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @param #string MissionType Mission type.
|
-- @param #string MissionType Mission type.
|
||||||
@ -1034,7 +1059,7 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
|||||||
|
|
||||||
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.NOTHING) then
|
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.NOTHING) then
|
||||||
|
|
||||||
-- Relocation: Take all assets. Mission will be cancelled.
|
-- Assets on mission NOTHING are considered.
|
||||||
table.insert(assets, asset)
|
table.insert(assets, asset)
|
||||||
|
|
||||||
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and MissionType==AUFTRAG.Type.INTERCEPT then
|
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||||
|
|||||||
@ -837,7 +837,7 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Status.
|
-- Status.
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
local text=string.format("Status %s: Legions=%d, Missions=%d, Transports", fsmstate, #self.legions, #self.missionqueue, #self.transportqueue)
|
local text=string.format("Status %s: Legions=%d, Missions=%d, Targets=%d, Transports=%d", fsmstate, #self.legions, #self.missionqueue, #self.targetqueue, #self.transportqueue)
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1032,6 +1032,21 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
-- TARGETS
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Target queue.
|
||||||
|
if self.verbose>=2 and #self.targetqueue>0 then
|
||||||
|
local text="Target queue:"
|
||||||
|
for i,_target in pairs(self.targetqueue) do
|
||||||
|
local target=_target --Ops.Target#TARGET
|
||||||
|
text=text..string.format("\n[%d] %s: status=%s, life=%d", i, target:GetName(), target:GetState(), target:GetLife())
|
||||||
|
end
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- TRANSPORTS
|
-- TRANSPORTS
|
||||||
---
|
---
|
||||||
@ -1214,6 +1229,20 @@ function COMMANDER:CheckTargetQueue()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Remove done targets.
|
||||||
|
for i=#self.targetqueue,1,-1 do
|
||||||
|
local target=self.targetqueue[i] --Ops.Target#TARGET
|
||||||
|
if (not target:IsAlive()) or target:EvalConditionsAny(target.conditionStop) then
|
||||||
|
for _,_resource in pairs(target.resources) do
|
||||||
|
local resource=_resource --Ops.Target#TARGET.Resource
|
||||||
|
if resource.mission and resource.mission:IsNotOver() then
|
||||||
|
self:MissionCancel(resource.mission)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.remove(self.targetqueue, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if total number of missions is reached.
|
-- Check if total number of missions is reached.
|
||||||
local NoLimit=self:_CheckMissionLimit("Total")
|
local NoLimit=self:_CheckMissionLimit("Total")
|
||||||
if NoLimit==false then
|
if NoLimit==false then
|
||||||
@ -1248,6 +1277,9 @@ function COMMANDER:CheckTargetQueue()
|
|||||||
-- Is this target important enough.
|
-- Is this target important enough.
|
||||||
local isImportant=(target.importance==nil or target.importance<=vip)
|
local isImportant=(target.importance==nil or target.importance<=vip)
|
||||||
|
|
||||||
|
-- Check ALL start conditions are true.
|
||||||
|
local isReadyStart=target:EvalConditionsAll(target.conditionStart)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Target %s: Alive=%s, Threat=%s, Important=%s", target:GetName(), tostring(isAlive), tostring(isThreat), tostring(isImportant))
|
local text=string.format("Target %s: Alive=%s, Threat=%s, Important=%s", target:GetName(), tostring(isAlive), tostring(isThreat), tostring(isImportant))
|
||||||
self:T2(self.lid..text)
|
self:T2(self.lid..text)
|
||||||
@ -1270,10 +1302,13 @@ function COMMANDER:CheckTargetQueue()
|
|||||||
local mission=AUFTRAG:NewFromTarget(target, missionType)
|
local mission=AUFTRAG:NewFromTarget(target, missionType)
|
||||||
|
|
||||||
if mission then
|
if mission then
|
||||||
|
|
||||||
|
-- Set mission parameters.
|
||||||
mission:SetRequiredAssets(resource.Nmin, resource.Nmax)
|
mission:SetRequiredAssets(resource.Nmin, resource.Nmax)
|
||||||
mission:SetRequiredAttribute(resource.Attributes)
|
mission:SetRequiredAttribute(resource.Attributes)
|
||||||
mission:SetRequiredProperty(resource.Properties)
|
mission:SetRequiredProperty(resource.Properties)
|
||||||
|
|
||||||
|
-- Set resource mission.
|
||||||
resource.mission=mission
|
resource.mission=mission
|
||||||
|
|
||||||
-- Add mission to queue.
|
-- Add mission to queue.
|
||||||
|
|||||||
@ -2232,9 +2232,22 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- First check if there is a paused mission.
|
-- Number of tasks remaining.
|
||||||
if self.missionpaused then
|
local nTasks=self:CountRemainingTasks()
|
||||||
self:T(self.lid..string.format("Found paused mission %s [%s]. Unpausing mission...", self.missionpaused.name, self.missionpaused.type))
|
|
||||||
|
-- Number of mission remaining.
|
||||||
|
local nMissions=self:CountRemainingMissison()
|
||||||
|
|
||||||
|
-- Number of cargo transports remaining.
|
||||||
|
local nTransports=self:CountRemainingTransports()
|
||||||
|
|
||||||
|
-- Number of paused missions.
|
||||||
|
local nPaused=self:_CountPausedMissions()
|
||||||
|
|
||||||
|
-- First check if there is a paused mission and that all remaining missions are paused. If there are other missions in the queue, we will run those.
|
||||||
|
if nPaused>0 and nPaused==nMissions then
|
||||||
|
local missionpaused=self:_GetPausedMission()
|
||||||
|
self:T(self.lid..string.format("Found paused mission %s [%s]. Unpausing mission...", missionpaused.name, missionpaused.type))
|
||||||
self:UnpauseMission()
|
self:UnpauseMission()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -2251,15 +2264,6 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Number of tasks remaining.
|
|
||||||
local nTasks=self:CountRemainingTasks()
|
|
||||||
|
|
||||||
-- Number of mission remaining.
|
|
||||||
local nMissions=self:CountRemainingMissison()
|
|
||||||
|
|
||||||
-- Number of cargo transports remaining.
|
|
||||||
local nTransports=self:CountRemainingTransports()
|
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Remaining (final=%s): missions=%d, tasks=%d, transports=%d", tostring(self.passedfinalwp), nMissions, nTasks, nTransports))
|
self:T(self.lid..string.format("Remaining (final=%s): missions=%d, tasks=%d, transports=%d", tostring(self.passedfinalwp), nMissions, nTasks, nTransports))
|
||||||
|
|
||||||
|
|||||||
@ -1454,6 +1454,9 @@ function INTEL:PaintPicture()
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Paint Picture: contact %s has no closest cluster ==> Create new cluster", contact.groupname))
|
||||||
|
|
||||||
-- Create a brand new cluster.
|
-- Create a brand new cluster.
|
||||||
local newcluster=self:_CreateClusterFromContact(contact)
|
local newcluster=self:_CreateClusterFromContact(contact)
|
||||||
|
|
||||||
@ -1817,13 +1820,13 @@ function INTEL:IsContactConnectedToCluster(contact, cluster)
|
|||||||
--local dist=Contact.position:Get2DDistance(contact.position)
|
--local dist=Contact.position:Get2DDistance(contact.position)
|
||||||
local dist=Contact.position:DistanceFromPointVec2(contact.position)
|
local dist=Contact.position:DistanceFromPointVec2(contact.position)
|
||||||
|
|
||||||
-- AIR - check for spatial proximity
|
-- AIR - check for spatial proximity (corrected because airprox was always false for ctype~=INTEL.Ctype.AIRCRAFT)
|
||||||
local airprox = false
|
local airprox = true
|
||||||
if contact.ctype == INTEL.Ctype.AIRCRAFT then
|
if contact.ctype == INTEL.Ctype.AIRCRAFT then
|
||||||
self:T(string.format("Cluster Alt=%d | Contact Alt=%d",cluster.altitude,contact.altitude))
|
self:T(string.format("Cluster Alt=%d | Contact Alt=%d",cluster.altitude,contact.altitude))
|
||||||
local adist = math.abs(cluster.altitude - contact.altitude)
|
local adist = math.abs(cluster.altitude - contact.altitude)
|
||||||
if adist < UTILS.FeetToMeters(10000) then -- limit to 10kft
|
if adist > UTILS.FeetToMeters(10000) then -- limit to 10kft
|
||||||
airprox = true
|
airprox = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1903,16 +1906,16 @@ function INTEL:_GetClosestClusterOfContact(Contact)
|
|||||||
|
|
||||||
local dist=self:_GetDistContactToCluster(Contact, cluster)
|
local dist=self:_GetDistContactToCluster(Contact, cluster)
|
||||||
|
|
||||||
-- AIR - check for spatial proximity
|
-- AIR - check for spatial proximity (ff: Changed because airprox was always false for ctype~=AIRCRAFT!)
|
||||||
local airprox = false
|
local airprox=true
|
||||||
if Contact.ctype == INTEL.Ctype.AIRCRAFT then
|
if Contact.ctype == INTEL.Ctype.AIRCRAFT then
|
||||||
if not cluster.altitude then
|
if not cluster.altitude then
|
||||||
cluster.altitude = self:GetClusterAltitude(cluster,true)
|
cluster.altitude = self:GetClusterAltitude(cluster,true)
|
||||||
end
|
end
|
||||||
local adist = math.abs(cluster.altitude - Contact.altitude)
|
local adist = math.abs(cluster.altitude - Contact.altitude)
|
||||||
self:T(string.format("Cluster Alt=%d | Contact Alt=%d",cluster.altitude,Contact.altitude))
|
self:T(string.format("Cluster Alt=%d | Contact Alt=%d",cluster.altitude,Contact.altitude))
|
||||||
if adist < UTILS.FeetToMeters(10000) then
|
if adist > UTILS.FeetToMeters(10000) then
|
||||||
airprox = true
|
airprox = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1858,6 +1858,24 @@ function LEGION:CountAssets(InStock, MissionTypes, Attributes)
|
|||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get OPSGROUPs that are spawned and alive.
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @param #table MissionTypes (Optional) Get only assest that can perform certain mission type(s). Default is all types.
|
||||||
|
-- @param #table Attributes (Optional) Get only assest that have a certain attribute(s), e.g. `WAREHOUSE.Attribute.AIR_BOMBER`.
|
||||||
|
-- @return Core.Set#SET_OPSGROUP The set of OPSGROUPs. Can be empty if no groups are spawned or alive!
|
||||||
|
function LEGION:GetOpsGroups(MissionTypes, Attributes)
|
||||||
|
|
||||||
|
local setLegion=SET_OPSGROUP:New()
|
||||||
|
|
||||||
|
for _,_cohort in pairs(self.cohorts) do
|
||||||
|
local cohort=_cohort --Ops.Cohort#COHORT
|
||||||
|
local setcohort=cohort:GetOpsGroups(MissionTypes, Attributes)
|
||||||
|
setLegion:AddSet(setcohort)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setLegion
|
||||||
|
end
|
||||||
|
|
||||||
--- Count total number of assets in LEGION warehouse stock that also have a payload.
|
--- Count total number of assets in LEGION warehouse stock that also have a payload.
|
||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
-- @param #boolean Payloads (Optional) Specifc payloads to consider. Default all.
|
-- @param #boolean Payloads (Optional) Specifc payloads to consider. Default all.
|
||||||
|
|||||||
@ -780,10 +780,14 @@ function NAVYGROUP:Status(From, Event, To)
|
|||||||
if timer.getAbsTime()>self.Twaiting+self.dTwait then
|
if timer.getAbsTime()>self.Twaiting+self.dTwait then
|
||||||
self.Twaiting=nil
|
self.Twaiting=nil
|
||||||
self.dTwait=nil
|
self.dTwait=nil
|
||||||
|
if self:_CountPausedMissions()>0 then
|
||||||
|
self:UnpauseMission()
|
||||||
|
else
|
||||||
self:Cruise()
|
self:Cruise()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
-- Check damage of elements and group.
|
-- Check damage of elements and group.
|
||||||
|
|||||||
@ -68,9 +68,10 @@
|
|||||||
-- @field Core.Timer#TIMER timerQueueUpdate Timer for queue updates.
|
-- @field Core.Timer#TIMER timerQueueUpdate Timer for queue updates.
|
||||||
-- @field #boolean groupinitialized If true, group parameters were initialized.
|
-- @field #boolean groupinitialized If true, group parameters were initialized.
|
||||||
-- @field #boolean detectionOn If true, detected units of the group are analyzed.
|
-- @field #boolean detectionOn If true, detected units of the group are analyzed.
|
||||||
-- @field Ops.Auftrag#AUFTRAG missionpaused Paused mission.
|
-- @field #table pausedmissions Paused missions.
|
||||||
-- @field #number Ndestroyed Number of destroyed units.
|
-- @field #number Ndestroyed Number of destroyed units.
|
||||||
-- @field #number Nkills Number kills of this groups.
|
-- @field #number Nkills Number kills of this groups.
|
||||||
|
-- @field #number Nhit Number of hits taken.
|
||||||
--
|
--
|
||||||
-- @field #boolean rearmOnOutOfAmmo If `true`, group will go to rearm once it runs out of ammo.
|
-- @field #boolean rearmOnOutOfAmmo If `true`, group will go to rearm once it runs out of ammo.
|
||||||
--
|
--
|
||||||
@ -185,6 +186,7 @@ OPSGROUP = {
|
|||||||
callsign = {},
|
callsign = {},
|
||||||
Ndestroyed = 0,
|
Ndestroyed = 0,
|
||||||
Nkills = 0,
|
Nkills = 0,
|
||||||
|
Nhit = 0,
|
||||||
weaponData = {},
|
weaponData = {},
|
||||||
cargoqueue = {},
|
cargoqueue = {},
|
||||||
cargoBay = {},
|
cargoBay = {},
|
||||||
@ -192,6 +194,7 @@ OPSGROUP = {
|
|||||||
carrierLoader = {},
|
carrierLoader = {},
|
||||||
carrierUnloader = {},
|
carrierUnloader = {},
|
||||||
useMEtasks = false,
|
useMEtasks = false,
|
||||||
|
pausedmissions = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -206,6 +209,7 @@ OPSGROUP = {
|
|||||||
-- @field #boolean ai If true, element is AI.
|
-- @field #boolean ai If true, element is AI.
|
||||||
-- @field #string skill Skill level.
|
-- @field #string skill Skill level.
|
||||||
-- @field #string playerName Name of player if this is a client.
|
-- @field #string playerName Name of player if this is a client.
|
||||||
|
-- @field #number Nhit Number of times the element was hit.
|
||||||
--
|
--
|
||||||
-- @field Core.Zone#ZONE_POLYGON_BASE zoneBoundingbox Bounding box zone of the element unit.
|
-- @field Core.Zone#ZONE_POLYGON_BASE zoneBoundingbox Bounding box zone of the element unit.
|
||||||
-- @field Core.Zone#ZONE_POLYGON_BASE zoneLoad Loading zone.
|
-- @field Core.Zone#ZONE_POLYGON_BASE zoneLoad Loading zone.
|
||||||
@ -646,8 +650,9 @@ function OPSGROUP:New(group)
|
|||||||
self:AddTransition("*", "InUtero", "InUtero") -- Deactivated group goes back to mummy.
|
self:AddTransition("*", "InUtero", "InUtero") -- Deactivated group goes back to mummy.
|
||||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
|
|
||||||
self:AddTransition("*", "Destroyed", "*") -- The whole group is dead.
|
self:AddTransition("*", "Hit", "*") -- Someone in the group was hit.
|
||||||
self:AddTransition("*", "Damaged", "*") -- Someone in the group took damage.
|
self:AddTransition("*", "Damaged", "*") -- Someone in the group took damage.
|
||||||
|
self:AddTransition("*", "Destroyed", "*") -- The whole group is dead.
|
||||||
|
|
||||||
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group.
|
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group.
|
||||||
|
|
||||||
@ -706,6 +711,7 @@ function OPSGROUP:New(group)
|
|||||||
self:AddTransition("*", "ElementDestroyed", "*") -- An element was destroyed.
|
self:AddTransition("*", "ElementDestroyed", "*") -- An element was destroyed.
|
||||||
self:AddTransition("*", "ElementDead", "*") -- An element is dead.
|
self:AddTransition("*", "ElementDead", "*") -- An element is dead.
|
||||||
self:AddTransition("*", "ElementDamaged", "*") -- An element was damaged.
|
self:AddTransition("*", "ElementDamaged", "*") -- An element was damaged.
|
||||||
|
self:AddTransition("*", "ElementHit", "*") -- An element was hit.
|
||||||
|
|
||||||
self:AddTransition("*", "Board", "*") -- Group is ordered to board the carrier.
|
self:AddTransition("*", "Board", "*") -- Group is ordered to board the carrier.
|
||||||
self:AddTransition("*", "Embarked", "*") -- Group was loaded into a cargo carrier.
|
self:AddTransition("*", "Embarked", "*") -- Group was loaded into a cargo carrier.
|
||||||
@ -1176,6 +1182,105 @@ function OPSGROUP:IsTargetDetected(TargetObject)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if a given coordinate is in weapon range.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Core.Point#COORDINATE TargetCoord Coordinate of the target.
|
||||||
|
-- @param #number WeaponBitType Weapon type.
|
||||||
|
-- @param Core.Point#COORDINATE RefCoord Reference coordinate.
|
||||||
|
-- @return #boolean If `true`, coordinate is in range.
|
||||||
|
function OPSGROUP:InWeaponRange(TargetCoord, WeaponBitType, RefCoord)
|
||||||
|
|
||||||
|
RefCoord=RefCoord or self:GetCoordinate()
|
||||||
|
|
||||||
|
local dist=TargetCoord:Get2DDistance(RefCoord)
|
||||||
|
|
||||||
|
if WeaponBitType then
|
||||||
|
|
||||||
|
local weapondata=self:GetWeaponData(WeaponBitType)
|
||||||
|
|
||||||
|
if weapondata then
|
||||||
|
|
||||||
|
if dist>=weapondata.RangeMin and dist<=weapondata.RangeMax then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
for _,_weapondata in pairs(self.weaponData or {}) do
|
||||||
|
local weapondata=_weapondata --#OPSGROUP.WeaponData
|
||||||
|
|
||||||
|
if dist>=weapondata.RangeMin and dist<=weapondata.RangeMax then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a coordinate, which is in weapon range.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Core.Point#COORDINATE TargetCoord Coordinate of the target.
|
||||||
|
-- @param #number WeaponBitType Weapon type.
|
||||||
|
-- @param Core.Point#COORDINATE RefCoord Reference coordinate.
|
||||||
|
-- @return Core.Point#COORDINATE Coordinate in weapon range
|
||||||
|
function OPSGROUP:GetCoordinateInRange(TargetCoord, WeaponBitType, RefCoord)
|
||||||
|
|
||||||
|
local coordInRange=nil --Core.Point#COORDINATE
|
||||||
|
|
||||||
|
RefCoord=RefCoord or self:GetCoordinate()
|
||||||
|
|
||||||
|
-- Get weapon range.
|
||||||
|
local weapondata=self:GetWeaponData(WeaponBitType)
|
||||||
|
|
||||||
|
if weapondata then
|
||||||
|
|
||||||
|
-- Heading to target.
|
||||||
|
local heading=RefCoord:HeadingTo(TargetCoord)
|
||||||
|
|
||||||
|
-- Distance to target.
|
||||||
|
local dist=RefCoord:Get2DDistance(TargetCoord)
|
||||||
|
|
||||||
|
-- Check if we are within range.
|
||||||
|
if dist>weapondata.RangeMax then
|
||||||
|
|
||||||
|
local d=(dist-weapondata.RangeMax)*1.05
|
||||||
|
|
||||||
|
-- New waypoint coord.
|
||||||
|
coordInRange=RefCoord:Translate(d, heading)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Out of max range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(WeaponBitType)))
|
||||||
|
elseif dist<weapondata.RangeMin then
|
||||||
|
|
||||||
|
local d=(dist-weapondata.RangeMin)*1.05
|
||||||
|
|
||||||
|
-- New waypoint coord.
|
||||||
|
coordInRange=RefCoord:Translate(d, heading)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Out of min range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(WeaponBitType)))
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Already in range for weapon %s", tostring(WeaponBitType)))
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
self:T(self.lid..string.format("No weapon data for weapon type %s", tostring(WeaponBitType)))
|
||||||
|
end
|
||||||
|
|
||||||
|
return coordInRange
|
||||||
|
end
|
||||||
|
|
||||||
--- Set LASER parameters.
|
--- Set LASER parameters.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #number Code Laser code. Default 1688.
|
-- @param #number Code Laser code. Default 1688.
|
||||||
@ -2623,6 +2728,61 @@ function OPSGROUP:IsAwaitingLift(Transport)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get paused mission.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @return Ops.Auftrag#AUFTRAG Paused mission or nil.
|
||||||
|
function OPSGROUP:_GetPausedMission()
|
||||||
|
|
||||||
|
if self.pausedmissions and #self.pausedmissions>0 then
|
||||||
|
for _,mid in pairs(self.pausedmissions) do
|
||||||
|
if mid then
|
||||||
|
local mission=self:GetMissionByID(mid)
|
||||||
|
if mission and mission:IsNotOver() then
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Count paused mission.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @return #number Number of paused missions.
|
||||||
|
function OPSGROUP:_CountPausedMissions()
|
||||||
|
local N=0
|
||||||
|
if self.pausedmissions and #self.pausedmissions>0 then
|
||||||
|
for _,mid in pairs(self.pausedmissions) do
|
||||||
|
local mission=self:GetMissionByID(mid)
|
||||||
|
if mission and mission:IsNotOver() then
|
||||||
|
N=N+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return N
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove paused mission from the table.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #number AuftragsNummer Mission ID of the paused mission to remove.
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:_RemovePausedMission(AuftragsNummer)
|
||||||
|
|
||||||
|
if self.pausedmissions and #self.pausedmissions>0 then
|
||||||
|
for i=#self.pausedmissions,1,-1 do
|
||||||
|
local mid=self.pausedmissions[i]
|
||||||
|
if mid==AuftragsNummer then
|
||||||
|
table.remove(self.pausedmissions, i)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if the group is currently boarding a carrier.
|
--- Check if the group is currently boarding a carrier.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string CarrierGroupName (Optional) Additionally check if group is boarding this particular carrier group.
|
-- @param #string CarrierGroupName (Optional) Additionally check if group is boarding this particular carrier group.
|
||||||
@ -3213,7 +3373,36 @@ function OPSGROUP:OnEventBirth(EventData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Event function handling the crash of a unit.
|
--- Event function handling the hit of a unit.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function OPSGROUP:OnEventHit(EventData)
|
||||||
|
|
||||||
|
-- Check that this is the right group. Here the hit group is stored as target.
|
||||||
|
if EventData and EventData.TgtGroup and EventData.TgtUnit and EventData.TgtGroupName and EventData.TgtGroupName==self.groupname then
|
||||||
|
self:T2(self.lid..string.format("EVENT: Unit %s hit!", EventData.TgtUnitName))
|
||||||
|
|
||||||
|
local unit=EventData.TgtUnit
|
||||||
|
local group=EventData.TgtGroup
|
||||||
|
local unitname=EventData.TgtUnitName
|
||||||
|
|
||||||
|
-- Get element.
|
||||||
|
local element=self:GetElementByName(unitname)
|
||||||
|
|
||||||
|
-- Increase group hit counter.
|
||||||
|
self.Nhit=self.Nhit or 0
|
||||||
|
self.Nhit=self.Nhit + 1
|
||||||
|
|
||||||
|
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
|
-- Trigger Element Hit Event.
|
||||||
|
self:ElementHit(element, EventData.IniUnit)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event function handling the dead of a unit.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
function OPSGROUP:OnEventDead(EventData)
|
function OPSGROUP:OnEventDead(EventData)
|
||||||
@ -4491,8 +4680,10 @@ function OPSGROUP:RemoveMission(Mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Take care of a paused mission.
|
-- Take care of a paused mission.
|
||||||
if self.missionpaused and self.missionpaused.auftragsnummer==Mission.auftragsnummer then
|
for j,mid in pairs(self.pausedmissions) do
|
||||||
self.missionpaused=nil
|
if Mission.auftragsnummer==mid then
|
||||||
|
table.remove(self.pausedmission, j)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove mission from queue.
|
-- Remove mission from queue.
|
||||||
@ -4865,7 +5056,7 @@ function OPSGROUP:onafterPauseMission(From, Event, To)
|
|||||||
self:_RemoveMissionWaypoints(Mission)
|
self:_RemoveMissionWaypoints(Mission)
|
||||||
|
|
||||||
-- Set mission to pause so we can unpause it later.
|
-- Set mission to pause so we can unpause it later.
|
||||||
self.missionpaused=Mission
|
table.insert(self.pausedmissions, 1, Mission.auftragsnummer)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -4878,18 +5069,27 @@ end
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function OPSGROUP:onafterUnpauseMission(From, Event, To)
|
function OPSGROUP:onafterUnpauseMission(From, Event, To)
|
||||||
|
|
||||||
-- Debug info.
|
-- Get paused mission.
|
||||||
self:T(self.lid..string.format("Unpausing mission"))
|
local mission=self:_GetPausedMission()
|
||||||
|
|
||||||
if self.missionpaused then
|
|
||||||
|
|
||||||
local mission=self:GetMissionByID(self.missionpaused.auftragsnummer)
|
|
||||||
|
|
||||||
if mission then
|
if mission then
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Unpausing mission %s [%s]", mission:GetName(), mission:GetType()))
|
||||||
|
|
||||||
|
-- Start mission.
|
||||||
self:MissionStart(mission)
|
self:MissionStart(mission)
|
||||||
|
|
||||||
|
-- Remove mission from
|
||||||
|
for i,mid in pairs(self.pausedmissions) do
|
||||||
|
--self:T(self.lid..string.format("Checking paused mission", mid))
|
||||||
|
if mid==mission.auftragsnummer then
|
||||||
|
self:T(self.lid..string.format("Removing paused mission id=%d", mid))
|
||||||
|
table.remove(self.pausedmissions, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.missionpaused=nil
|
|
||||||
else
|
else
|
||||||
self:T(self.lid.."ERROR: No mission to unpause!")
|
self:T(self.lid.."ERROR: No mission to unpause!")
|
||||||
end
|
end
|
||||||
@ -4911,14 +5111,15 @@ function OPSGROUP:onafterMissionCancel(From, Event, To, Mission)
|
|||||||
-- Current Mission
|
-- Current Mission
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Alert 5 missoins dont have a task set, which could be cancelled.
|
-- Some missions dont have a task set, which could be cancelled.
|
||||||
if Mission.type==AUFTRAG.Type.ALERT5 or
|
if Mission.type==AUFTRAG.Type.ALERT5 or
|
||||||
Mission.type==AUFTRAG.Type.ONGUARD or
|
Mission.type==AUFTRAG.Type.ONGUARD or
|
||||||
Mission.type==AUFTRAG.Type.ARMOREDGUARD or
|
Mission.type==AUFTRAG.Type.ARMOREDGUARD or
|
||||||
Mission.type==AUFTRAG.Type.NOTHING or
|
--Mission.type==AUFTRAG.Type.NOTHING or
|
||||||
Mission.type==AUFTRAG.Type.AIRDEFENSE or
|
Mission.type==AUFTRAG.Type.AIRDEFENSE or
|
||||||
Mission.type==AUFTRAG.Type.EWR then
|
Mission.type==AUFTRAG.Type.EWR then
|
||||||
|
|
||||||
|
-- Trigger mission don task.
|
||||||
self:MissionDone(Mission)
|
self:MissionDone(Mission)
|
||||||
|
|
||||||
return
|
return
|
||||||
@ -5144,10 +5345,6 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.speedMax<=3.6 or mission.teleport then
|
|
||||||
--self:ClearWaypoints()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ID of current waypoint.
|
-- ID of current waypoint.
|
||||||
local uid=self:GetWaypointCurrentUID()
|
local uid=self:GetWaypointCurrentUID()
|
||||||
|
|
||||||
@ -5157,8 +5354,6 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- Current coordinate of the group.
|
-- Current coordinate of the group.
|
||||||
local currentcoord=self:GetCoordinate()
|
local currentcoord=self:GetCoordinate()
|
||||||
|
|
||||||
currentcoord:MarkToAll(mission:GetName(),ReadOnly,Text)
|
|
||||||
|
|
||||||
-- Road connection.
|
-- Road connection.
|
||||||
local roadcoord=currentcoord:GetClosestPointToRoad()
|
local roadcoord=currentcoord:GetClosestPointToRoad()
|
||||||
|
|
||||||
@ -5181,12 +5376,9 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
surfacetypes={land.SurfaceType.WATER, land.SurfaceType.SHALLOW_WATER}
|
surfacetypes={land.SurfaceType.WATER, land.SurfaceType.SHALLOW_WATER}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Get ingress waypoint.
|
-- Get ingress waypoint.
|
||||||
if mission.opstransport and not mission.opstransport:IsCargoDelivered(self.groupname) then
|
if mission.opstransport and not mission.opstransport:IsCargoDelivered(self.groupname) then
|
||||||
|
|
||||||
--env.info(self.lid.."FF mission waypoint in embark zone")
|
|
||||||
|
|
||||||
-- Get transport zone combo.
|
-- Get transport zone combo.
|
||||||
local tzc=mission.opstransport:GetTZCofCargo(self.groupname)
|
local tzc=mission.opstransport:GetTZCofCargo(self.groupname)
|
||||||
|
|
||||||
@ -5200,7 +5392,6 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
else
|
else
|
||||||
-- Get a random coordinate inside the pickup zone.
|
-- Get a random coordinate inside the pickup zone.
|
||||||
waypointcoord=pickupzone:GetRandomCoordinate()
|
waypointcoord=pickupzone:GetRandomCoordinate()
|
||||||
--waypointcoord:MarkToAll(self.lid.." embark here")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif mission.type==AUFTRAG.Type.PATROLZONE or
|
elseif mission.type==AUFTRAG.Type.PATROLZONE or
|
||||||
@ -5219,7 +5410,6 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- Random coordinate.
|
-- Random coordinate.
|
||||||
waypointcoord=targetzone:GetRandomCoordinate(nil , nil, surfacetypes)
|
waypointcoord=targetzone:GetRandomCoordinate(nil , nil, surfacetypes)
|
||||||
|
|
||||||
waypointcoord:MarkToAll(mission:GetName(),ReadOnly,Text)
|
|
||||||
elseif mission.type==AUFTRAG.Type.ONGUARD or mission.type==AUFTRAG.Type.ARMOREDGUARD then
|
elseif mission.type==AUFTRAG.Type.ONGUARD or mission.type==AUFTRAG.Type.ARMOREDGUARD then
|
||||||
---
|
---
|
||||||
-- Guard
|
-- Guard
|
||||||
@ -5338,48 +5528,22 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- ARTY
|
-- ARTY
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Coord
|
-- Target 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()
|
local targetcoord=mission:GetTargetCoordinate()
|
||||||
|
|
||||||
-- Heading to target.
|
|
||||||
local heading=coord:HeadingTo(targetcoord)
|
|
||||||
|
|
||||||
-- Distance to target.
|
-- In range already?
|
||||||
local dist=coord:Get2DDistance(targetcoord)
|
local inRange=self:InWeaponRange(targetcoord, mission.engageWeaponType)
|
||||||
|
|
||||||
-- Check if we are within range.
|
if inRange then
|
||||||
if dist>weapondata.RangeMax then
|
|
||||||
|
|
||||||
local d=(dist-weapondata.RangeMax)*1.1
|
env.info("FF in range!")
|
||||||
|
|
||||||
-- New waypoint coord.
|
waypointcoord=self:GetCoordinate(true)
|
||||||
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)))
|
|
||||||
elseif dist<weapondata.RangeMin then
|
|
||||||
|
|
||||||
local d=(dist-weapondata.RangeMin)*1.1
|
|
||||||
|
|
||||||
-- New waypoint coord.
|
|
||||||
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)))
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("No weapon data for weapon type %s", tostring(mission.engageWeaponType)))
|
|
||||||
end
|
local coordInRange=self:GetCoordinateInRange(targetcoord, mission.engageWeaponType, waypointcoord)
|
||||||
|
|
||||||
if coordInRange then
|
if coordInRange then
|
||||||
|
|
||||||
@ -5402,6 +5566,8 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Add mission execution (ingress) waypoint.
|
-- Add mission execution (ingress) waypoint.
|
||||||
local waypoint=nil --#OPSGROUP.Waypoint
|
local waypoint=nil --#OPSGROUP.Waypoint
|
||||||
@ -5568,6 +5734,7 @@ function OPSGROUP:_QueueUpdate()
|
|||||||
|
|
||||||
-- Current mission but new mission is urgent with higher prio.
|
-- Current mission but new mission is urgent with higher prio.
|
||||||
if mission.urgent and mission.prio<currentmission.prio then
|
if mission.urgent and mission.prio<currentmission.prio then
|
||||||
|
self:T(self.lid.."FF got urgent mission with higher prio!")
|
||||||
self:MissionCancel(currentmission)
|
self:MissionCancel(currentmission)
|
||||||
self:__MissionStart(1, mission)
|
self:__MissionStart(1, mission)
|
||||||
end
|
end
|
||||||
@ -5617,9 +5784,17 @@ end
|
|||||||
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
|
-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever).
|
||||||
function OPSGROUP:onbeforeWait(From, Event, To, Duration)
|
function OPSGROUP:onbeforeWait(From, Event, To, Duration)
|
||||||
|
|
||||||
|
env.info("FF before wait")
|
||||||
|
|
||||||
local allowed=true
|
local allowed=true
|
||||||
local Tsuspend=nil
|
local Tsuspend=nil
|
||||||
|
|
||||||
|
local mission=self:GetMissionCurrent()
|
||||||
|
if mission then
|
||||||
|
self:PauseMission()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- Check for a current task.
|
-- Check for a current task.
|
||||||
if self.taskcurrent>0 then
|
if self.taskcurrent>0 then
|
||||||
self:T(self.lid..string.format("WARNING: Got current task ==> WAIT event is suspended for 30 sec!"))
|
self:T(self.lid..string.format("WARNING: Got current task ==> WAIT event is suspended for 30 sec!"))
|
||||||
@ -6652,6 +6827,37 @@ function OPSGROUP:onafterElementDamaged(From, Event, To, Element)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "ElementHit" event.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #OPSGROUP.Element Element The flight group element.
|
||||||
|
-- @param Wrapper.Unit#UNIT Enemy Unit that hit the element or `nil`.
|
||||||
|
function OPSGROUP:onafterElementHit(From, Event, To, Element, Enemy)
|
||||||
|
|
||||||
|
-- Increase element hit counter.
|
||||||
|
Element.Nhit=Element.Nhit+1
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Element hit %s by %s [n=%d, N=%d]", Element.name, Enemy and Enemy:GetName() or "unknown", Element.Nhit, self.Nhit))
|
||||||
|
|
||||||
|
-- Group was hit.
|
||||||
|
self:__Hit(-3, Enemy)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Hit" event.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Wrapper.Unit#UNIT Enemy Unit that hit the element or `nil`.
|
||||||
|
function OPSGROUP:onafterHit(From, Event, To, Enemy)
|
||||||
|
self:T(self.lid..string.format("Group hit by %s", Enemy and Enemy:GetName() or "unknown"))
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- On after "ElementDestroyed" event.
|
--- On after "ElementDestroyed" event.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -6818,9 +7024,9 @@ function OPSGROUP:Teleport(Coordinate, Delay, NoPauseMission)
|
|||||||
if self:IsFlightgroup() then
|
if self:IsFlightgroup() then
|
||||||
Template.route.points[1]=Coordinate:WaypointAir("BARO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, 300, true, nil, nil, "Spawnpoint")
|
Template.route.points[1]=Coordinate:WaypointAir("BARO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, 300, true, nil, nil, "Spawnpoint")
|
||||||
elseif self:IsArmygroup() then
|
elseif self:IsArmygroup() then
|
||||||
Template.route.points[1]=Coordinate:WaypointGround()
|
Template.route.points[1]=Coordinate:WaypointGround(0)
|
||||||
elseif self:IsNavygroup() then
|
elseif self:IsNavygroup() then
|
||||||
Template.route.points[1]=Coordinate:WaypointNaval()
|
Template.route.points[1]=Coordinate:WaypointNaval(0)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Template units.
|
-- Template units.
|
||||||
@ -6892,6 +7098,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
|
|
||||||
-- Number of destroyed units.
|
-- Number of destroyed units.
|
||||||
self.Ndestroyed=0
|
self.Ndestroyed=0
|
||||||
|
self.Nhit=0
|
||||||
|
|
||||||
-- Check if group is currently alive.
|
-- Check if group is currently alive.
|
||||||
if self:IsAlive() then
|
if self:IsAlive() then
|
||||||
@ -7192,6 +7399,8 @@ function OPSGROUP:onafterStop(From, Event, To)
|
|||||||
self:UnHandleEvent(EVENTS.Ejection)
|
self:UnHandleEvent(EVENTS.Ejection)
|
||||||
self:UnHandleEvent(EVENTS.Crash)
|
self:UnHandleEvent(EVENTS.Crash)
|
||||||
self.currbase=nil
|
self.currbase=nil
|
||||||
|
elseif self.isArmygroup then
|
||||||
|
self:UnHandleEvent(EVENTS.Hit)
|
||||||
end
|
end
|
||||||
|
|
||||||
for _,_mission in pairs(self.missionqueue) do
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
@ -9038,7 +9247,7 @@ function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
|
|||||||
OpsGroupCargo:Returned()
|
OpsGroupCargo:Returned()
|
||||||
end
|
end
|
||||||
|
|
||||||
if OpsGroupCargo.missionpaused then
|
if self:_CountPausedMissions()>0 then
|
||||||
OpsGroupCargo:UnpauseMission()
|
OpsGroupCargo:UnpauseMission()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -9618,9 +9827,13 @@ function OPSGROUP:_CheckGroupDone(delay)
|
|||||||
-- Number of cargo transports remaining.
|
-- Number of cargo transports remaining.
|
||||||
local nTransports=self:CountRemainingTransports()
|
local nTransports=self:CountRemainingTransports()
|
||||||
|
|
||||||
-- First check if there is a paused mission that
|
-- Number of paused missions.
|
||||||
if self.missionpaused and nMissions==1 then
|
local nPaused=self:_CountPausedMissions()
|
||||||
self:T(self.lid..string.format("Found paused mission %s [%s]. Unpausing mission...", self.missionpaused.name, self.missionpaused.type))
|
|
||||||
|
-- First check if there is a paused mission and that all remaining missions are paused. If there are other missions in the queue, we will run those.
|
||||||
|
if nPaused>0 and nPaused==nMissions then
|
||||||
|
local missionpaused=self:_GetPausedMission()
|
||||||
|
self:T(self.lid..string.format("Found paused mission %s [%s]. Unpausing mission...", missionpaused.name, missionpaused.type))
|
||||||
self:UnpauseMission()
|
self:UnpauseMission()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -12414,6 +12627,7 @@ function OPSGROUP:_AddElementByName(unitname)
|
|||||||
element.uid=element.DCSunit:getID()
|
element.uid=element.DCSunit:getID()
|
||||||
--element.group=unit:GetGroup()
|
--element.group=unit:GetGroup()
|
||||||
element.controller=element.DCSunit:getController()
|
element.controller=element.DCSunit:getController()
|
||||||
|
element.Nhit=0
|
||||||
element.opsgroup=self
|
element.opsgroup=self
|
||||||
|
|
||||||
-- Skill etc.
|
-- Skill etc.
|
||||||
@ -12431,7 +12645,7 @@ function OPSGROUP:_AddElementByName(unitname)
|
|||||||
element.categoryname=unit:GetCategoryName()
|
element.categoryname=unit:GetCategoryName()
|
||||||
element.typename=unit:GetTypeName()
|
element.typename=unit:GetTypeName()
|
||||||
|
|
||||||
|
-- Describtors.
|
||||||
--self:I({desc=element.descriptors})
|
--self:I({desc=element.descriptors})
|
||||||
|
|
||||||
-- Ammo.
|
-- Ammo.
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
-- @field Ops.Intelligence#INTEL.Contact contact Contact attached to this target.
|
-- @field Ops.Intelligence#INTEL.Contact contact Contact attached to this target.
|
||||||
-- @field #boolean isDestroyed If true, target objects were destroyed.
|
-- @field #boolean isDestroyed If true, target objects were destroyed.
|
||||||
-- @field #table resources Resource list.
|
-- @field #table resources Resource list.
|
||||||
|
-- @field #table conditionStart Start condition functions.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- **It is far more important to be able to hit the target than it is to haggle over who makes a weapon or who pulls a trigger** -- Dwight D Eisenhower
|
--- **It is far more important to be able to hit the target than it is to haggle over who makes a weapon or who pulls a trigger** -- Dwight D Eisenhower
|
||||||
@ -65,7 +66,8 @@ TARGET = {
|
|||||||
Ndead = 0,
|
Ndead = 0,
|
||||||
elements = {},
|
elements = {},
|
||||||
casualties = {},
|
casualties = {},
|
||||||
threatlevel0 = 0
|
threatlevel0 = 0,
|
||||||
|
conditionStart = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -318,6 +320,95 @@ function TARGET:SetImportance(Importance)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add start condition.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #function ConditionFunction Function that needs to be true before the mission can be started. Must return a #boolean.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #TARGET self
|
||||||
|
function TARGET:AddConditionStart(ConditionFunction, ...)
|
||||||
|
|
||||||
|
local condition={} --Ops.Auftrag#AUFTRAG.Condition
|
||||||
|
|
||||||
|
condition.func=ConditionFunction
|
||||||
|
condition.arg={}
|
||||||
|
if arg then
|
||||||
|
condition.arg=arg
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self.conditionStart, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add stop condition.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #function ConditionFunction Function that needs to be true before the mission can be started. Must return a #boolean.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #TARGET self
|
||||||
|
function TARGET:AddConditionStop(ConditionFunction, ...)
|
||||||
|
|
||||||
|
local condition={} --Ops.Auftrag#AUFTRAG.Condition
|
||||||
|
|
||||||
|
condition.func=ConditionFunction
|
||||||
|
condition.arg={}
|
||||||
|
if arg then
|
||||||
|
condition.arg=arg
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(self.conditionStop, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if all given condition are true.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #table Conditions Table of conditions.
|
||||||
|
-- @return #boolean If true, all conditions were true. Returns false if at least one condition returned false.
|
||||||
|
function TARGET:EvalConditionsAll(Conditions)
|
||||||
|
|
||||||
|
-- Any stop condition must be true.
|
||||||
|
for _,_condition in pairs(Conditions or {}) do
|
||||||
|
local condition=_condition --Ops.Auftrag#AUFTRAG.Condition
|
||||||
|
|
||||||
|
-- Call function.
|
||||||
|
local istrue=condition.func(unpack(condition.arg))
|
||||||
|
|
||||||
|
-- Any false will return false.
|
||||||
|
if not istrue then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- All conditions were true.
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if any of the given conditions is true.
|
||||||
|
-- @param #TARGET self
|
||||||
|
-- @param #table Conditions Table of conditions.
|
||||||
|
-- @return #boolean If true, at least one condition is true.
|
||||||
|
function TARGET:EvalConditionsAny(Conditions)
|
||||||
|
|
||||||
|
-- Any stop condition must be true.
|
||||||
|
for _,_condition in pairs(Conditions or {}) do
|
||||||
|
local condition=_condition --Ops.Auftrag#AUFTRAG.Condition
|
||||||
|
|
||||||
|
-- Call function.
|
||||||
|
local istrue=condition.func(unpack(condition.arg))
|
||||||
|
|
||||||
|
-- Any true will return true.
|
||||||
|
if istrue then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- No condition was true.
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--- Add mission type and number of required assets to resource.
|
--- Add mission type and number of required assets to resource.
|
||||||
-- @param #TARGET self
|
-- @param #TARGET self
|
||||||
-- @param #string MissionType Mission Type.
|
-- @param #string MissionType Mission Type.
|
||||||
|
|||||||
@ -187,6 +187,7 @@ GROUPTEMPLATE.Takeoff = {
|
|||||||
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
||||||
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
||||||
-- @field #string GROUND_INFANTRY Ground infantry assets.
|
-- @field #string GROUND_INFANTRY Ground infantry assets.
|
||||||
|
-- @field #string GROUND_IFV Ground Infantry Fighting Vehicle.
|
||||||
-- @field #string GROUND_ARTILLERY Artillery assets.
|
-- @field #string GROUND_ARTILLERY Artillery assets.
|
||||||
-- @field #string GROUND_TANK Tanks (modern or old).
|
-- @field #string GROUND_TANK Tanks (modern or old).
|
||||||
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
||||||
@ -213,6 +214,7 @@ GROUP.Attribute = {
|
|||||||
GROUND_APC="Ground_APC",
|
GROUND_APC="Ground_APC",
|
||||||
GROUND_TRUCK="Ground_Truck",
|
GROUND_TRUCK="Ground_Truck",
|
||||||
GROUND_INFANTRY="Ground_Infantry",
|
GROUND_INFANTRY="Ground_Infantry",
|
||||||
|
GROUND_IFV="Ground_IFV",
|
||||||
GROUND_ARTILLERY="Ground_Artillery",
|
GROUND_ARTILLERY="Ground_Artillery",
|
||||||
GROUND_TANK="Ground_Tank",
|
GROUND_TANK="Ground_Tank",
|
||||||
GROUND_TRAIN="Ground_Train",
|
GROUND_TRAIN="Ground_Train",
|
||||||
@ -2378,13 +2380,14 @@ function GROUP:GetAttribute()
|
|||||||
--- Ground ---
|
--- Ground ---
|
||||||
--------------
|
--------------
|
||||||
-- Ground
|
-- Ground
|
||||||
local apc=self:HasAttribute("Infantry carriers")
|
local apc=self:HasAttribute("APC")
|
||||||
local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND
|
local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND
|
||||||
local infantry=self:HasAttribute("Infantry")
|
local infantry=self:HasAttribute("Infantry")
|
||||||
local artillery=self:HasAttribute("Artillery")
|
local artillery=self:HasAttribute("Artillery")
|
||||||
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
|
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
|
||||||
local aaa=self:HasAttribute("AAA")
|
local aaa=self:HasAttribute("AAA")
|
||||||
local ewr=self:HasAttribute("EWR")
|
local ewr=self:HasAttribute("EWR")
|
||||||
|
local ifv=self:HasAttribute("IFV")
|
||||||
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
|
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
|
||||||
-- Train
|
-- Train
|
||||||
local train=self:GetCategory()==Group.Category.TRAIN
|
local train=self:GetCategory()==Group.Category.TRAIN
|
||||||
@ -2432,6 +2435,8 @@ function GROUP:GetAttribute()
|
|||||||
attribute=GROUP.Attribute.GROUND_APC
|
attribute=GROUP.Attribute.GROUND_APC
|
||||||
elseif infantry then
|
elseif infantry then
|
||||||
attribute=GROUP.Attribute.GROUND_INFANTRY
|
attribute=GROUP.Attribute.GROUND_INFANTRY
|
||||||
|
elseif ifv then
|
||||||
|
attribute=GROUP.Attribute.GROUND_IFV
|
||||||
elseif truck then
|
elseif truck then
|
||||||
attribute=GROUP.Attribute.GROUND_TRUCK
|
attribute=GROUP.Attribute.GROUND_TRUCK
|
||||||
elseif train then
|
elseif train then
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user