mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
OPS
- Fixed oscillation between UpdateRoute and CheckGroupDone in FLIGHTGROUP - Improvements regarding capturing zones. - Reduced log output
This commit is contained in:
parent
be0558849c
commit
b48958995a
@ -1342,7 +1342,7 @@ function ZONE:New( ZoneName )
|
|||||||
|
|
||||||
-- Error!
|
-- Error!
|
||||||
if not Zone then
|
if not Zone then
|
||||||
error( "Zone " .. ZoneName .. " does not exist." )
|
env.error( "ERROR: Zone " .. ZoneName .. " does not exist!" )
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -812,6 +812,39 @@ function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation,
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "OutOfAmmo" event.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
||||||
|
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
||||||
|
|
||||||
|
-- Fist, check if we want to rearm once out-of-ammo.
|
||||||
|
if self.rearmOnOutOfAmmo then
|
||||||
|
local truck=self:FindNearestAmmoSupply(30)
|
||||||
|
if truck then
|
||||||
|
self:T(self.lid..string.format("Found Ammo Truck %s [%s]"))
|
||||||
|
local Coordinate=truck:GetCoordinate()
|
||||||
|
self:Rearm(Coordinate, Formation)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Second, check if we want to retreat once out of ammo.
|
||||||
|
if self.retreatOnOutOfAmmo then
|
||||||
|
self:Retreat()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Third, check if we want to RTZ once out of ammo.
|
||||||
|
if self.rtzOnOutOfAmmo then
|
||||||
|
self:RTZ()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- On before "Rearm" event.
|
--- On before "Rearm" event.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -1403,6 +1436,7 @@ end
|
|||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #number Radius Search radius in NM. Default 30 NM.
|
-- @param #number Radius Search radius in NM. Default 30 NM.
|
||||||
-- @return Wrapper.Group#GROUP Closest ammo supplying group or `nil` if no group is in the given radius.
|
-- @return Wrapper.Group#GROUP Closest ammo supplying group or `nil` if no group is in the given radius.
|
||||||
|
-- @return #number Distance to closest group in meters.
|
||||||
function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
||||||
|
|
||||||
-- Radius in meters.
|
-- Radius in meters.
|
||||||
@ -1410,6 +1444,9 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
|||||||
|
|
||||||
-- Current positon.
|
-- Current positon.
|
||||||
local coord=self:GetCoordinate()
|
local coord=self:GetCoordinate()
|
||||||
|
|
||||||
|
-- Get my coalition.
|
||||||
|
local myCoalition=self:GetCoalition()
|
||||||
|
|
||||||
-- Scanned units.
|
-- Scanned units.
|
||||||
local units=coord:ScanUnits(Radius)
|
local units=coord:ScanUnits(Radius)
|
||||||
@ -1421,10 +1458,10 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
|||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
-- Check coaliton and if unit can supply ammo.
|
-- Check coaliton and if unit can supply ammo.
|
||||||
if unit:GetCoalition()==self:GetCoalition() and unit:IsAmmoSupply() then
|
if unit:GetCoalition()==myCoalition and unit:IsAmmoSupply() then
|
||||||
|
|
||||||
-- Distance.
|
-- Distance.
|
||||||
local d=unit:GetCoordinate():Get2DDistance(coord)
|
local d=coord:Get2DDistance(unit:GetCoord())
|
||||||
|
|
||||||
-- Check if distance is smaller.
|
-- Check if distance is smaller.
|
||||||
if d<dmin then
|
if d<dmin then
|
||||||
@ -1436,10 +1473,10 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if truck then
|
if truck then
|
||||||
return truck:GetGroup()
|
return truck:GetGroup(), dmin
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -369,7 +369,7 @@ _AUFTRAGSNR=0
|
|||||||
-- @field #string AMMOSUPPLY Ammo supply.
|
-- @field #string AMMOSUPPLY Ammo supply.
|
||||||
-- @field #string FUELSUPPLY Fuel supply.
|
-- @field #string FUELSUPPLY Fuel supply.
|
||||||
-- @field #string ALERT5 Alert 5.
|
-- @field #string ALERT5 Alert 5.
|
||||||
-- @field #string ONWATCH On watch.
|
-- @field #string ONGUARD On guard.
|
||||||
AUFTRAG.Type={
|
AUFTRAG.Type={
|
||||||
ANTISHIP="Anti Ship",
|
ANTISHIP="Anti Ship",
|
||||||
AWACS="AWACS",
|
AWACS="AWACS",
|
||||||
@ -397,8 +397,8 @@ AUFTRAG.Type={
|
|||||||
OPSTRANSPORT="Ops Transport",
|
OPSTRANSPORT="Ops Transport",
|
||||||
AMMOSUPPLY="Ammo Supply",
|
AMMOSUPPLY="Ammo Supply",
|
||||||
FUELSUPPLY="Fuel Supply",
|
FUELSUPPLY="Fuel Supply",
|
||||||
ALERT5="Alert 5",
|
ALERT5="Alert5",
|
||||||
ONWATCH="On Watch",
|
ONGUARD="On Guard",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Mission status of an assigned group.
|
--- Mission status of an assigned group.
|
||||||
@ -408,14 +408,14 @@ AUFTRAG.Type={
|
|||||||
-- @field #string AMMOSUPPLY Ammo Supply.
|
-- @field #string AMMOSUPPLY Ammo Supply.
|
||||||
-- @field #string FUELSUPPLY Fuel Supply.
|
-- @field #string FUELSUPPLY Fuel Supply.
|
||||||
-- @field #string ALERT5 Alert 5 task.
|
-- @field #string ALERT5 Alert 5 task.
|
||||||
-- @field #string ONWATCH On Watch
|
-- @field #string ONGUARD On guard.
|
||||||
AUFTRAG.SpecialTask={
|
AUFTRAG.SpecialTask={
|
||||||
PATROLZONE="PatrolZone",
|
PATROLZONE="PatrolZone",
|
||||||
RECON="ReconMission",
|
RECON="ReconMission",
|
||||||
AMMOSUPPLY="Ammo Supply",
|
AMMOSUPPLY="Ammo Supply",
|
||||||
FUELSUPPLY="Fuel Supply",
|
FUELSUPPLY="Fuel Supply",
|
||||||
ALERT5="Alert 5",
|
ALERT5="Alert5",
|
||||||
ONWATCH="On Watch",
|
ONGUARD="On Guard",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Mission status.
|
--- Mission status.
|
||||||
@ -1692,6 +1692,7 @@ function AUFTRAG:NewALERT5(MissionType)
|
|||||||
local mission=AUFTRAG:New(AUFTRAG.Type.ALERT5)
|
local mission=AUFTRAG:New(AUFTRAG.Type.ALERT5)
|
||||||
|
|
||||||
mission.missionTask=self:GetMissionTaskforMissionType(MissionType)
|
mission.missionTask=self:GetMissionTaskforMissionType(MissionType)
|
||||||
|
|
||||||
mission.optionROE=ENUMS.ROE.WeaponHold
|
mission.optionROE=ENUMS.ROE.WeaponHold
|
||||||
mission.optionROT=ENUMS.ROT.NoReaction
|
mission.optionROT=ENUMS.ROT.NoReaction
|
||||||
|
|
||||||
@ -1706,6 +1707,28 @@ function AUFTRAG:NewALERT5(MissionType)
|
|||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[GROUND, NAVAL]** Create an ON GUARD mission.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate, were to be on guard.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:NewONGUARD(Coordinate)
|
||||||
|
|
||||||
|
local mission=AUFTRAG:New(AUFTRAG.Type.ONGUARD)
|
||||||
|
|
||||||
|
mission:_TargetFromObject(Coordinate)
|
||||||
|
|
||||||
|
mission.optionROE=ENUMS.ROE.OpenFire
|
||||||
|
mission.optionAlarm=ENUMS.AlarmState.Red
|
||||||
|
|
||||||
|
mission.missionFraction=1.0
|
||||||
|
|
||||||
|
mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL}
|
||||||
|
|
||||||
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Create a mission to attack a TARGET object.
|
--- Create a mission to attack a TARGET object.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
@ -2328,7 +2351,7 @@ function AUFTRAG:AssignSquadrons(Squadrons)
|
|||||||
|
|
||||||
for _,_squad in pairs(Squadrons) do
|
for _,_squad in pairs(Squadrons) do
|
||||||
local squadron=_squad --Ops.Squadron#SQUADRON
|
local squadron=_squad --Ops.Squadron#SQUADRON
|
||||||
self:I(self.lid..string.format("Assigning squadron %s", tostring(squadron.name)))
|
self:T(self.lid..string.format("Assigning squadron %s", tostring(squadron.name)))
|
||||||
self:AssignCohort(squadron)
|
self:AssignCohort(squadron)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3313,7 +3336,7 @@ end
|
|||||||
function AUFTRAG:AddLegion(Legion)
|
function AUFTRAG:AddLegion(Legion)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Adding legion %s", Legion.alias))
|
self:T(self.lid..string.format("Adding legion %s", Legion.alias))
|
||||||
|
|
||||||
-- Add legion to table.
|
-- Add legion to table.
|
||||||
table.insert(self.legions, Legion)
|
table.insert(self.legions, Legion)
|
||||||
@ -3332,7 +3355,7 @@ function AUFTRAG:RemoveLegion(Legion)
|
|||||||
local legion=self.legions[i] --Ops.Legion#LEGION
|
local legion=self.legions[i] --Ops.Legion#LEGION
|
||||||
if legion.alias==Legion.alias then
|
if legion.alias==Legion.alias then
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Removing legion %s", Legion.alias))
|
self:T(self.lid..string.format("Removing legion %s", Legion.alias))
|
||||||
table.remove(self.legions, i)
|
table.remove(self.legions, i)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -3353,7 +3376,7 @@ function AUFTRAG:SetLegionStatus(Legion, Status)
|
|||||||
local status=self:GetLegionStatus(Legion)
|
local status=self:GetLegionStatus(Legion)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Setting LEGION %s to status %s-->%s", Legion.alias, tostring(status), tostring(Status)))
|
self:T(self.lid..string.format("Setting LEGION %s to status %s-->%s", Legion.alias, tostring(status), tostring(Status)))
|
||||||
|
|
||||||
-- New status.
|
-- New status.
|
||||||
self.statusLegion[Legion.alias]=Status
|
self.statusLegion[Legion.alias]=Status
|
||||||
@ -4750,6 +4773,24 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
|||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.ONGUARD then
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- ON GUARD Mission --
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
local DCStask={}
|
||||||
|
|
||||||
|
DCStask.id=AUFTRAG.SpecialTask.ONGUARD
|
||||||
|
|
||||||
|
-- We create a "fake" DCS task and pass the parameters to the OPSGROUP.
|
||||||
|
local param={}
|
||||||
|
param.coordinate=self:GetObjective()
|
||||||
|
|
||||||
|
DCStask.params=param
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
-- @type BRIGADE
|
-- @type BRIGADE
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field #number verbose Verbosity of output.
|
-- @field #number verbose Verbosity of output.
|
||||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.RearmingZone`.
|
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
|
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
||||||
-- @extends Ops.Legion#LEGION
|
-- @extends Ops.Legion#LEGION
|
||||||
|
|
||||||
@ -33,16 +34,17 @@
|
|||||||
--
|
--
|
||||||
-- @field #BRIGADE
|
-- @field #BRIGADE
|
||||||
BRIGADE = {
|
BRIGADE = {
|
||||||
ClassName = "BRIGADE",
|
ClassName = "BRIGADE",
|
||||||
verbose = 0,
|
verbose = 0,
|
||||||
rearmingZones = {},
|
rearmingZones = {},
|
||||||
|
refuellingZones = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Rearming Zone.
|
--- Supply Zone.
|
||||||
-- @type BRIGADE.RearmingZone
|
-- @type BRIGADE.SupplyZone
|
||||||
-- @field Core.Zone#ZONE zone The zone.
|
-- @field Core.Zone#ZONE zone The zone.
|
||||||
-- @field #boolean occupied If `true`, a rearming truck is present in the zone.
|
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo.
|
-- @field #boolean markerOn If `true`, marker is on.
|
||||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||||
|
|
||||||
--- BRIGADE class version.
|
--- BRIGADE class version.
|
||||||
@ -225,13 +227,12 @@ end
|
|||||||
--- Add a rearming zone.
|
--- Add a rearming zone.
|
||||||
-- @param #BRIGADE self
|
-- @param #BRIGADE self
|
||||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
||||||
-- @return #BRIGADE.RearmingZone The rearming zone data.
|
-- @return #BRIGADE.SupplyZone The rearming zone data.
|
||||||
function BRIGADE:AddRearmingZone(RearmingZone)
|
function BRIGADE:AddRearmingZone(RearmingZone)
|
||||||
|
|
||||||
local rearmingzone={} --#BRIGADE.RearmingZone
|
local rearmingzone={} --#BRIGADE.SupplyZone
|
||||||
|
|
||||||
rearmingzone.zone=RearmingZone
|
rearmingzone.zone=RearmingZone
|
||||||
rearmingzone.occupied=false
|
|
||||||
rearmingzone.mission=nil
|
rearmingzone.mission=nil
|
||||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||||
|
|
||||||
@ -241,6 +242,24 @@ function BRIGADE:AddRearmingZone(RearmingZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Add a refuelling zone.
|
||||||
|
-- @param #BRIGADE self
|
||||||
|
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
||||||
|
-- @return #BRIGADE.SupplyZone The refuelling zone data.
|
||||||
|
function BRIGADE:AddRefuellingZone(RefuellingZone)
|
||||||
|
|
||||||
|
local supplyzone={} --#BRIGADE.SupplyZone
|
||||||
|
|
||||||
|
supplyzone.zone=RefuellingZone
|
||||||
|
supplyzone.mission=nil
|
||||||
|
supplyzone.marker=MARKER:New(supplyzone.zone:GetCoordinate(), "Refuelling Zone"):ToCoalition(self:GetCoalition())
|
||||||
|
|
||||||
|
table.insert(self.rearmingZones, supplyzone)
|
||||||
|
|
||||||
|
return supplyzone
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get platoon by name.
|
--- Get platoon by name.
|
||||||
-- @param #BRIGADE self
|
-- @param #BRIGADE self
|
||||||
-- @param #string PlatoonName Name of the platoon.
|
-- @param #string PlatoonName Name of the platoon.
|
||||||
@ -312,14 +331,28 @@ function BRIGADE:onafterStatus(From, Event, To)
|
|||||||
-- Rearming Zones ---
|
-- Rearming Zones ---
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||||
self:AddMission(rearmingzone.mission)
|
self:AddMission(rearmingzone.mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-----------------------
|
||||||
|
-- Refuelling Zones ---
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
-- Check refuelling zones.
|
||||||
|
for _,_supplyzone in pairs(self.refuellingZones) do
|
||||||
|
local supplyzone=_supplyzone --#BRIGADE.SupplyZone
|
||||||
|
-- Check if mission is nil or over.
|
||||||
|
if (not supplyzone.mission) or supplyzone.mission:IsOver() then
|
||||||
|
supplyzone.mission=AUFTRAG:NewFUELSUPPLY(supplyzone.zone)
|
||||||
|
self:AddMission(supplyzone.mission)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
-- Info ---
|
-- Info ---
|
||||||
@ -396,19 +429,28 @@ function BRIGADE:onafterStatus(From, Event, To)
|
|||||||
-------------------
|
-------------------
|
||||||
-- Rearming Info --
|
-- Rearming Info --
|
||||||
-------------------
|
-------------------
|
||||||
if self.verbose>=0 then
|
if self.verbose>=4 then
|
||||||
local text="Rearming Zones:"
|
local text="Rearming Zones:"
|
||||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
for i,_rearmingzone in pairs(self.rearmingZones) do
|
||||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||||
|
-- Info text.
|
||||||
local name=rearmingzone.zone:GetName()
|
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", rearmingzone.zone:GetName(), rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
||||||
|
|
||||||
-- Platoon text.
|
|
||||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", name, rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
|
||||||
|
|
||||||
end
|
end
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------
|
||||||
|
-- Refuelling Info --
|
||||||
|
-------------------
|
||||||
|
if self.verbose>=4 then
|
||||||
|
local text="Refuelling Zones:"
|
||||||
|
for i,_refuellingzone in pairs(self.refuellingZones) do
|
||||||
|
local refuellingzone=_refuellingzone --#BRIGADE.SupplyZone
|
||||||
|
-- Info text.
|
||||||
|
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", refuellingzone.zone:GetName(), refuellingzone.mission:GetState(), refuellingzone.mission:CountOpsGroups())
|
||||||
|
end
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -60,11 +60,13 @@ CHIEF.DEFCON = {
|
|||||||
|
|
||||||
--- Strategy.
|
--- Strategy.
|
||||||
-- @type CHIEF.Strategy
|
-- @type CHIEF.Strategy
|
||||||
|
-- @field #string PASSIVE No targets at all are engaged.
|
||||||
-- @field #string DEFENSIVE Only target in our own terretory are engaged.
|
-- @field #string DEFENSIVE Only target in our own terretory are engaged.
|
||||||
-- @field #string OFFENSIVE Targets in own terretory and yellow zones are engaged.
|
-- @field #string OFFENSIVE Targets in own terretory and yellow zones are engaged.
|
||||||
-- @field #string AGGRESSIVE Targets in own terretroy, yellow zones and engage zones are engaged.
|
-- @field #string AGGRESSIVE Targets in own terretory, conflict zones and attack zones are engaged.
|
||||||
-- @field #string TOTALWAR Anything is engaged anywhere.
|
-- @field #string TOTALWAR Anything is engaged anywhere.
|
||||||
CHIEF.Strategy = {
|
CHIEF.Strategy = {
|
||||||
|
PASSIVE="Passive",
|
||||||
DEFENSIVE="Defensive",
|
DEFENSIVE="Defensive",
|
||||||
OFFENSIVE="Offensive",
|
OFFENSIVE="Offensive",
|
||||||
AGGRESSIVE="Aggressive",
|
AGGRESSIVE="Aggressive",
|
||||||
@ -570,13 +572,25 @@ end
|
|||||||
--- Add a rearming zone.
|
--- Add a rearming zone.
|
||||||
-- @param #CHIEF self
|
-- @param #CHIEF self
|
||||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
||||||
-- @return Ops.Brigade#BRIGADE.RearmingZone The rearming zone data.
|
-- @return Ops.Brigade#BRIGADE.SupplyZone The rearming zone data.
|
||||||
function CHIEF:AddRearmingZone(RearmingZone)
|
function CHIEF:AddRearmingZone(RearmingZone)
|
||||||
|
|
||||||
-- Hand over to commander.
|
-- Hand over to commander.
|
||||||
local rearmingzone=self.commander:AddRearmingZone(RearmingZone)
|
local supplyzone=self.commander:AddRearmingZone(RearmingZone)
|
||||||
|
|
||||||
return rearmingzone
|
return supplyzone
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a refuelling zone.
|
||||||
|
-- @param #CHIEF self
|
||||||
|
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
||||||
|
-- @return Ops.Brigade#BRIGADE.SupplyZone The refuelling zone data.
|
||||||
|
function CHIEF:AddRefuellingZone(RefuellingZone)
|
||||||
|
|
||||||
|
-- Hand over to commander.
|
||||||
|
local supplyzone=self.commander:AddRefuellingZone(RefuellingZone)
|
||||||
|
|
||||||
|
return supplyzone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -840,7 +854,8 @@ function CHIEF:onafterStatus(From, Event, To)
|
|||||||
for i,_opszone in pairs(self.zonequeue) do
|
for i,_opszone in pairs(self.zonequeue) do
|
||||||
local opszone=_opszone --Ops.OpsZone#OPSZONE
|
local opszone=_opszone --Ops.OpsZone#OPSZONE
|
||||||
|
|
||||||
text=text..string.format("\n[%d] %s [%s]: owner=%d [%d]: Blue=%d, Red=%d, Neutral=%d", i, opszone.zone:GetName(), opszone:GetState(), opszone:GetOwner(), opszone:GetPreviousOwner(), opszone.Nblu, opszone.Nred, opszone.Nnut)
|
text=text..string.format("\n[%d] %s [%s]: owner=%d [%d] (prio=%d, importance=%s): Blue=%d, Red=%d, Neutral=%d", i,
|
||||||
|
opszone.zone:GetName(), opszone:GetState(), opszone:GetOwner(), opszone:GetPreviousOwner(), opszone.prio, tostring(opszone.importance), opszone.Nblu, opszone.Nred, opszone.Nnut)
|
||||||
|
|
||||||
end
|
end
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
@ -1059,14 +1074,22 @@ function CHIEF:CheckTargetQueue()
|
|||||||
local target=_target --Ops.Target#TARGET
|
local target=_target --Ops.Target#TARGET
|
||||||
|
|
||||||
-- Is this a threat?
|
-- Is this a threat?
|
||||||
local isThreat=target.threatlevel0>=self.threatLevelMin and target.threatlevel0<=self.threatLevelMax
|
local isThreat=target.threatlevel0>=self.threatLevelMin and target.threatlevel0<=self.threatLevelMax
|
||||||
|
|
||||||
-- Check that target is alive and not already a mission has been assigned.
|
-- Check that target is alive and not already a mission has been assigned.
|
||||||
if target:IsAlive() and (target.importance==nil or target.importance<=vip) and isThreat and not target.mission then
|
if target:IsAlive() and (target.importance==nil or target.importance<=vip) and isThreat and not target.mission then
|
||||||
|
|
||||||
-- Check if this target is "valid", i.e. fits with the current strategy.
|
-- Check if this target is "valid", i.e. fits with the current strategy.
|
||||||
local valid=false
|
local valid=false
|
||||||
if self.strategy==CHIEF.Strategy.DEFENSIVE then
|
if self.strategy==CHIEF.Strategy.PASSIVE then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- PASSIVE: No targets at all are attacked.
|
||||||
|
---
|
||||||
|
|
||||||
|
valid=false
|
||||||
|
|
||||||
|
elseif self.strategy==CHIEF.Strategy.DEFENSIVE then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- DEFENSIVE: Attack inside borders only.
|
-- DEFENSIVE: Attack inside borders only.
|
||||||
@ -1146,7 +1169,6 @@ function CHIEF:CheckTargetQueue()
|
|||||||
if mission then
|
if mission then
|
||||||
for _,_asset in pairs(assets) do
|
for _,_asset in pairs(assets) do
|
||||||
local asset=_asset
|
local asset=_asset
|
||||||
asset.isReserved=true
|
|
||||||
mission:AddAsset(asset)
|
mission:AddAsset(asset)
|
||||||
end
|
end
|
||||||
Legions=legions
|
Legions=legions
|
||||||
@ -1204,19 +1226,20 @@ function CHIEF:CheckOpsZoneQueue()
|
|||||||
|
|
||||||
-- Sort results table wrt ?.
|
-- Sort results table wrt ?.
|
||||||
local function _sort(a, b)
|
local function _sort(a, b)
|
||||||
local taskA=a --Ops.Target#TARGET
|
local taskA=a --Ops.OpsZone#OPSZONE
|
||||||
local taskB=b --Ops.Target#TARGET
|
local taskB=b --Ops.OpsZone#OPSZONE
|
||||||
return (taskA.prio<taskB.prio)
|
return (taskA.prio<taskB.prio)
|
||||||
end
|
end
|
||||||
--table.sort(self.zonequeue, _sort)
|
table.sort(self.zonequeue, _sort)
|
||||||
|
|
||||||
-- Get the lowest importance value (lower means more important).
|
-- Get the lowest importance value (lower means more important).
|
||||||
-- If a target with importance 1 exists, targets with importance 2 will not be assigned. Targets with no importance (nil) can still be selected.
|
-- If a zone with importance 1 exists that is not owned by us, zones with importance 2 will not be assigned. Zone with no importance (nil) can still be selected.
|
||||||
local vip=math.huge
|
local vip=math.huge
|
||||||
for _,_target in pairs(self.zonequeue) do
|
for _,_opszone in pairs(self.zonequeue) do
|
||||||
local target=_target --Ops.Target#TARGET
|
local opszone=_opszone --Ops.OpsZone#OPSZONE
|
||||||
if target.importance and target.importance<vip then
|
if opszone.importance and opszone.importance<vip and opszone:GetOwner()~=self.coalition then
|
||||||
vip=target.importance
|
-- Most important zone that is NOT owned by us.
|
||||||
|
vip=opszone.importance
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1226,15 +1249,43 @@ function CHIEF:CheckOpsZoneQueue()
|
|||||||
|
|
||||||
-- Current owner of the zone.
|
-- Current owner of the zone.
|
||||||
local ownercoalition=opszone:GetOwner()
|
local ownercoalition=opszone:GetOwner()
|
||||||
|
|
||||||
|
-- Check coalition and importance.
|
||||||
|
if ownercoalition~=self.coalition and (opszone.importance==nil or opszone.importance<=vip) then
|
||||||
|
|
||||||
local hasMission=opszone.missionPatrol and opszone.missionPatrol:IsNotOver() or false
|
-- Has a patrol mission?
|
||||||
|
local hasMissionPatrol=opszone.missionPatrol and opszone.missionPatrol:IsNotOver() or false
|
||||||
|
-- Has a CAS mission?
|
||||||
|
local hasMissionCAS=opszone.missionCAS and opszone.missionCAS:IsNotOver() or false
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Zone %s [%s] is owned by coalition %d", opszone.zone:GetName(), opszone:GetState(), ownercoalition))
|
||||||
|
|
||||||
if ownercoalition~=self.coalition and not hasMission then
|
if opszone:IsEmpty() then
|
||||||
|
|
||||||
env.info(string.format("Zone %s is owned by coalition %d", opszone.zone:GetName(), ownercoalition))
|
|
||||||
|
|
||||||
-- Recruit ground assets that
|
if not hasMissionPatrol then
|
||||||
local recruited=self:RecruitAssetsForZone(opszone, AUFTRAG.Type.PATROLZONE, 1, 3, {Group.Category.GROUND}, {GROUP.Attribute.GROUND_INFANTRY})
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Zone is empty ==> Recruit Patrol zone infantry assets"))
|
||||||
|
|
||||||
|
-- Recruit ground assets that
|
||||||
|
local recruited=self:RecruitAssetsForZone(opszone, AUFTRAG.Type.PATROLZONE, 1, 3, {Group.Category.GROUND}, {GROUP.Attribute.GROUND_INFANTRY})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if not hasMissionCAS then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid..string.format("Zone is NOT empty ==> recruit CAS assets"))
|
||||||
|
|
||||||
|
-- Recruite CAS assets.
|
||||||
|
local recruited=self:RecruitAssetsForZone(opszone, AUFTRAG.Type.CAS, 1, 3)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1568,45 +1619,78 @@ function CHIEF:RecruitAssetsForZone(OpsZone, MissionType, NassetsMin, NassetsMax
|
|||||||
|
|
||||||
-- Target position.
|
-- Target position.
|
||||||
local TargetVec2=OpsZone.zone:GetVec2()
|
local TargetVec2=OpsZone.zone:GetVec2()
|
||||||
|
|
||||||
-- Recruite infantry assets.
|
-- Recruite infantry assets.
|
||||||
local recruitedInf, assetsInf, legionsInf=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, nil, nil, nil, Categories, Attributes)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, nil, nil, nil, Categories, Attributes)
|
||||||
|
|
||||||
if recruitedInf then
|
if recruited then
|
||||||
|
|
||||||
env.info(string.format("Recruited %d assets from for PATROL mission", #assetsInf))
|
if MissionType==AUFTRAG.Type.PATROLZONE then
|
||||||
|
|
||||||
-- Recruit transport assets for infantry.
|
-- Debug messgage.
|
||||||
local recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assetsInf, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
|
self:T2(self.lid..string.format("Recruited %d assets from for PATROL mission", #assets))
|
||||||
|
|
||||||
|
local recruitedTrans=true
|
||||||
-- Create Patrol zone mission.
|
local transport=nil
|
||||||
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
|
if Attributes and Attributes[1]==GROUP.Attribute.GROUND_INFANTRY then
|
||||||
mission:SetEngageDetected()
|
|
||||||
|
-- Recruit transport assets for infantry.
|
||||||
-- Add assets to mission.
|
recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assets, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
|
||||||
for _,asset in pairs(assetsInf) do
|
|
||||||
mission:AddAsset(asset)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Attach OPS transport to mission.
|
|
||||||
mission.opstransport=transport
|
|
||||||
|
|
||||||
-- Assign mission to legions.
|
end
|
||||||
for _,_legion in pairs(legionsInf) do
|
|
||||||
local legion=_legion --Ops.Legion#LEGION
|
if recruitedTrans then
|
||||||
self.commander:MissionAssign(legion, mission)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Attach mission to ops zone.
|
|
||||||
-- TODO: Need a better way!
|
|
||||||
OpsZone.missionPatrol=mission
|
|
||||||
|
|
||||||
return true
|
-- Create Patrol zone mission.
|
||||||
else
|
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
|
||||||
LEGION.UnRecruitAssets(assetsInf)
|
mission:SetEngageDetected()
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
-- Add assets to mission.
|
||||||
|
for _,asset in pairs(assets) do
|
||||||
|
mission:AddAsset(asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attach OPS transport to mission.
|
||||||
|
mission.opstransport=transport
|
||||||
|
|
||||||
|
-- Assign mission to legions.
|
||||||
|
for _,_legion in pairs(legions) do
|
||||||
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
|
self.commander:MissionAssign(legion, mission)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attach mission to ops zone.
|
||||||
|
-- TODO: Need a better way!
|
||||||
|
OpsZone.missionPatrol=mission
|
||||||
|
|
||||||
|
else
|
||||||
|
LEGION.UnRecruitAssets(assets)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif MissionType==AUFTRAG.Type.CAS then
|
||||||
|
|
||||||
|
-- Create Patrol zone mission.
|
||||||
|
local mission=AUFTRAG:NewCAS(OpsZone.zone)
|
||||||
|
|
||||||
|
-- Add assets to mission.
|
||||||
|
for _,asset in pairs(assets) do
|
||||||
|
mission:AddAsset(asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Assign mission to legions.
|
||||||
|
for _,_legion in pairs(legions) do
|
||||||
|
local legion=_legion --Ops.Legion#LEGION
|
||||||
|
self.commander:MissionAssign(legion, mission)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Attach mission to ops zone.
|
||||||
|
-- TODO: Need a better way!
|
||||||
|
OpsZone.missionCAS=mission
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@ -906,8 +906,14 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--TODO: Check transport for combat readyness!
|
-- Check transport/cargo for combat readyness!
|
||||||
|
if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then
|
||||||
|
combatready=false
|
||||||
|
end
|
||||||
|
if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then
|
||||||
|
combatready=false
|
||||||
|
end
|
||||||
|
|
||||||
-- This asset is "combatready".
|
-- This asset is "combatready".
|
||||||
if combatready then
|
if combatready then
|
||||||
self:I(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
self:I(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||||
|
|||||||
@ -20,7 +20,8 @@
|
|||||||
-- @field #table legions Table of legions which are commanded.
|
-- @field #table legions Table of legions which are commanded.
|
||||||
-- @field #table missionqueue Mission queue.
|
-- @field #table missionqueue Mission queue.
|
||||||
-- @field #table transportqueue Transport queue.
|
-- @field #table transportqueue Transport queue.
|
||||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.RearmingZone`.
|
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
|
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||||
-- @field Ops.Chief#CHIEF chief Chief of staff.
|
-- @field Ops.Chief#CHIEF chief Chief of staff.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@ -35,12 +36,13 @@
|
|||||||
--
|
--
|
||||||
-- @field #COMMANDER
|
-- @field #COMMANDER
|
||||||
COMMANDER = {
|
COMMANDER = {
|
||||||
ClassName = "COMMANDER",
|
ClassName = "COMMANDER",
|
||||||
verbose = 0,
|
verbose = 0,
|
||||||
legions = {},
|
legions = {},
|
||||||
missionqueue = {},
|
missionqueue = {},
|
||||||
transportqueue = {},
|
transportqueue = {},
|
||||||
rearmingZones = {},
|
rearmingZones = {},
|
||||||
|
refuellingZones = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- COMMANDER class version.
|
--- COMMANDER class version.
|
||||||
@ -335,13 +337,12 @@ end
|
|||||||
--- Add a rearming zone.
|
--- Add a rearming zone.
|
||||||
-- @param #COMMANDER self
|
-- @param #COMMANDER self
|
||||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
||||||
-- @return Ops.Brigade#BRIGADE.RearmingZone The rearming zone data.
|
-- @return Ops.Brigade#BRIGADE.SupplyZone The rearming zone data.
|
||||||
function COMMANDER:AddRearmingZone(RearmingZone)
|
function COMMANDER:AddRearmingZone(RearmingZone)
|
||||||
|
|
||||||
local rearmingzone={} --Ops.Brigade#BRIGADE.RearmingZone
|
local rearmingzone={} --Ops.Brigade#BRIGADE.SupplyZone
|
||||||
|
|
||||||
rearmingzone.zone=RearmingZone
|
rearmingzone.zone=RearmingZone
|
||||||
rearmingzone.occupied=false
|
|
||||||
rearmingzone.mission=nil
|
rearmingzone.mission=nil
|
||||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||||
|
|
||||||
@ -350,6 +351,23 @@ function COMMANDER:AddRearmingZone(RearmingZone)
|
|||||||
return rearmingzone
|
return rearmingzone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add a refuelling zone.
|
||||||
|
-- @param #COMMANDER self
|
||||||
|
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
||||||
|
-- @return Ops.Brigade#BRIGADE.SupplyZone The refuelling zone data.
|
||||||
|
function COMMANDER:AddRefuellingZone(RefuellingZone)
|
||||||
|
|
||||||
|
local rearmingzone={} --Ops.Brigade#BRIGADE.SupplyZone
|
||||||
|
|
||||||
|
rearmingzone.zone=RefuellingZone
|
||||||
|
rearmingzone.mission=nil
|
||||||
|
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Refuelling Zone"):ToCoalition(self:GetCoalition())
|
||||||
|
|
||||||
|
table.insert(self.refuellingZones, rearmingzone)
|
||||||
|
|
||||||
|
return rearmingzone
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Start & Status
|
-- Start & Status
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -402,13 +420,23 @@ function COMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check rearming zones.
|
-- Check rearming zones.
|
||||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||||
-- Check if mission is nil or over.
|
-- Check if mission is nil or over.
|
||||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||||
self:AddMission(rearmingzone.mission)
|
self:AddMission(rearmingzone.mission)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check refuelling zones.
|
||||||
|
for _,_supplyzone in pairs(self.refuellingZones) do
|
||||||
|
local supplyzone=_supplyzone --#BRIGADE.SupplyZone
|
||||||
|
-- Check if mission is nil or over.
|
||||||
|
if (not supplyzone.mission) or supplyzone.mission:IsOver() then
|
||||||
|
supplyzone.mission=AUFTRAG:NewFUELSUPPLY(supplyzone.zone)
|
||||||
|
self:AddMission(supplyzone.mission)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- LEGIONS
|
-- LEGIONS
|
||||||
|
|||||||
@ -1140,7 +1140,7 @@ function FLIGHTGROUP:OnEventEngineShutdown(EventData)
|
|||||||
if element.unit and element.unit:IsAlive() then
|
if element.unit and element.unit:IsAlive() then
|
||||||
|
|
||||||
local airbase=self:GetClosestAirbase()
|
local airbase=self:GetClosestAirbase()
|
||||||
local parking=self:GetParkingSpot(element, 10, airbase)
|
local parking=self:GetParkingSpot(element, 100, airbase)
|
||||||
|
|
||||||
if airbase and parking then
|
if airbase and parking then
|
||||||
self:ElementArrived(element, airbase, parking)
|
self:ElementArrived(element, airbase, parking)
|
||||||
@ -1548,7 +1548,7 @@ end
|
|||||||
function FLIGHTGROUP:onafterParking(From, Event, To)
|
function FLIGHTGROUP:onafterParking(From, Event, To)
|
||||||
|
|
||||||
-- Get closest airbase
|
-- Get closest airbase
|
||||||
local airbase=self:GetClosestAirbase() --self.group:GetCoordinate():GetClosestAirbase()
|
local airbase=self:GetClosestAirbase()
|
||||||
local airbasename=airbase:GetName() or "unknown"
|
local airbasename=airbase:GetName() or "unknown"
|
||||||
|
|
||||||
-- Debug info
|
-- Debug info
|
||||||
@ -2006,7 +2006,7 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n, N)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Set current waypoint or we get problem that the _PassingWaypoint function is triggered too early, i.e. right now and not when passing the next WP.
|
-- Set current waypoint or we get problem that the _PassingWaypoint function is triggered too early, i.e. right now and not when passing the next WP.
|
||||||
local current=self.group:GetCoordinate():WaypointAir(COORDINATE.WaypointAltType.BARO, waypointType, waypointAction, speed, true, nil, {}, "Current")
|
local current=self:GetCoordinate():WaypointAir(COORDINATE.WaypointAltType.BARO, waypointType, waypointAction, speed, true, nil, {}, "Current")
|
||||||
table.insert(wp, current)
|
table.insert(wp, current)
|
||||||
|
|
||||||
-- Add remaining waypoints to route.
|
-- Add remaining waypoints to route.
|
||||||
@ -2087,14 +2087,14 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
|
|
||||||
if delay and delay>0 then
|
if delay and delay>0 then
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done in %.3f seconds...", fsmstate, delay))
|
self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done in %.3f seconds... (t=%.4f)", fsmstate, delay, timer.getTime()))
|
||||||
|
|
||||||
-- Delayed call.
|
-- Delayed call.
|
||||||
self:ScheduleOnce(delay, FLIGHTGROUP._CheckGroupDone, self)
|
self:ScheduleOnce(delay, FLIGHTGROUP._CheckGroupDone, self)
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done?", fsmstate))
|
self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done? (t=%.4f)", fsmstate, timer.getTime()))
|
||||||
|
|
||||||
-- First check if there is a paused mission that
|
-- First check if there is a paused mission that
|
||||||
if self.missionpaused then
|
if self.missionpaused then
|
||||||
@ -2134,7 +2134,9 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
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))
|
||||||
|
|
||||||
-- Final waypoint passed?
|
-- Final waypoint passed?
|
||||||
if self:HasPassedFinalWaypoint() then
|
-- Or next waypoint index is the first waypoint. Could be that the group was on a mission and the mission waypoints were deleted. then the final waypoint is FALSE but no real waypoint left.
|
||||||
|
-- Since we do not do ad infinitum, this leads to a rapid oscillation between UpdateRoute and CheckGroupDone!
|
||||||
|
if self:HasPassedFinalWaypoint() or self:GetWaypointIndexNext()==1 then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Final Waypoint PASSED
|
-- Final Waypoint PASSED
|
||||||
@ -2376,7 +2378,7 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand)
|
|||||||
local althold=self.isHelo and 1000+math.random(10)*100 or math.random(4,10)*1000
|
local althold=self.isHelo and 1000+math.random(10)*100 or math.random(4,10)*1000
|
||||||
|
|
||||||
-- Holding points.
|
-- Holding points.
|
||||||
local c0=self.group:GetCoordinate()
|
local c0=self:GetCoordinate()
|
||||||
local p0=airbase:GetZone():GetRandomCoordinate():SetAltitude(UTILS.FeetToMeters(althold))
|
local p0=airbase:GetZone():GetRandomCoordinate():SetAltitude(UTILS.FeetToMeters(althold))
|
||||||
local p1=nil
|
local p1=nil
|
||||||
local wpap=nil
|
local wpap=nil
|
||||||
@ -2527,7 +2529,7 @@ end
|
|||||||
function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
||||||
|
|
||||||
-- Group will orbit at its current position.
|
-- Group will orbit at its current position.
|
||||||
local Coord=self.group:GetCoordinate()
|
local Coord=self:GetCoordinate()
|
||||||
|
|
||||||
-- Set altitude: 1000 ft for helos and 10,000 ft for panes.
|
-- Set altitude: 1000 ft for helos and 10,000 ft for panes.
|
||||||
if Altitude then
|
if Altitude then
|
||||||
@ -2597,7 +2599,7 @@ function FLIGHTGROUP:onafterRefuel(From, Event, To, Coordinate)
|
|||||||
|
|
||||||
local Speed=self.speedCruise
|
local Speed=self.speedCruise
|
||||||
|
|
||||||
local coordinate=self.group:GetCoordinate()
|
local coordinate=self:GetCoordinate()
|
||||||
|
|
||||||
Coordinate=Coordinate or coordinate:Translate(UTILS.NMToMeters(5), self.group:GetHeading(), true)
|
Coordinate=Coordinate or coordinate:Translate(UTILS.NMToMeters(5), self.group:GetHeading(), true)
|
||||||
|
|
||||||
@ -3972,7 +3974,7 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
|||||||
self:I(self.lid.."FF updating menu NOW")
|
self:I(self.lid.."FF updating menu NOW")
|
||||||
|
|
||||||
-- Get current position of group.
|
-- Get current position of group.
|
||||||
local position=self.group:GetCoordinate()
|
local position=self:GetCoordinate()
|
||||||
|
|
||||||
-- Get all FLIGHTCONTROLS
|
-- Get all FLIGHTCONTROLS
|
||||||
local fc={}
|
local fc={}
|
||||||
|
|||||||
@ -841,6 +841,13 @@ function LEGION:onafterTransportCancel(From, Event, To, Transport)
|
|||||||
opsgroup:TransportCancel(Transport)
|
opsgroup:TransportCancel(Transport)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Delete awaited transport.
|
||||||
|
local cargos=Transport:GetCargoOpsGroups(false)
|
||||||
|
for _,_cargo in pairs(cargos) do
|
||||||
|
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
||||||
|
cargo:_DelMyLift(Transport)
|
||||||
|
end
|
||||||
|
|
||||||
-- Remove asset from mission.
|
-- Remove asset from mission.
|
||||||
Transport:DelAsset(asset)
|
Transport:DelAsset(asset)
|
||||||
|
|
||||||
@ -1068,7 +1075,7 @@ function LEGION:onafterAssetSpawned(From, Event, To, group, asset, request)
|
|||||||
if cohort then
|
if cohort then
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Cohort asset spawned %s", asset.spawngroupname))
|
self:T(self.lid..string.format("Cohort asset spawned %s", asset.spawngroupname))
|
||||||
|
|
||||||
-- Create a flight group.
|
-- Create a flight group.
|
||||||
local flightgroup=self:_CreateFlightGroup(asset)
|
local flightgroup=self:_CreateFlightGroup(asset)
|
||||||
@ -1150,7 +1157,7 @@ function LEGION:onafterAssetSpawned(From, Event, To, group, asset, request)
|
|||||||
-- Add group to the detection set of the CHIEF (INTEL).
|
-- Add group to the detection set of the CHIEF (INTEL).
|
||||||
local chief=self.chief or (self.commander and self.commander.chief or nil) --Ops.Chief#CHIEF
|
local chief=self.chief or (self.commander and self.commander.chief or nil) --Ops.Chief#CHIEF
|
||||||
if chief then
|
if chief then
|
||||||
self:I(self.lid..string.format("Adding group %s to agents of CHIEF", group:GetName()))
|
self:T(self.lid..string.format("Adding group %s to agents of CHIEF", group:GetName()))
|
||||||
chief.detectionset:AddGroup(asset.flightgroup.group)
|
chief.detectionset:AddGroup(asset.flightgroup.group)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1932,7 +1939,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
local RightAttribute=CheckAttribute(cohort)
|
local RightAttribute=CheckAttribute(cohort)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
cohort:I(cohort.lid..string.format("State=%s: Capable=%s, InRange=%s, Refuel=%s, CanCarry=%s, RightCategory=%s, RightAttribute=%s",
|
cohort:T(cohort.lid..string.format("State=%s: Capable=%s, InRange=%s, Refuel=%s, CanCarry=%s, RightCategory=%s, RightAttribute=%s",
|
||||||
cohort:GetState(), tostring(Capable), tostring(InRange), tostring(Refuel), tostring(CanCarry), tostring(RightCategory), tostring(RightAttribute)))
|
cohort:GetState(), tostring(Capable), tostring(InRange), tostring(Refuel), tostring(CanCarry), tostring(RightCategory), tostring(RightAttribute)))
|
||||||
|
|
||||||
-- Check OnDuty, capable, in range and refueling type (if TANKER).
|
-- Check OnDuty, capable, in range and refueling type (if TANKER).
|
||||||
|
|||||||
@ -69,6 +69,8 @@
|
|||||||
-- @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 #boolean rearmOnOutOfAmmo If `true`, group will go to rearm once it runs out of ammo.
|
||||||
|
--
|
||||||
-- @field Ops.Legion#LEGION legion Legion the group belongs to.
|
-- @field Ops.Legion#LEGION legion Legion the group belongs to.
|
||||||
-- @field Ops.Cohort#COHORT cohort Cohort the group belongs to.
|
-- @field Ops.Cohort#COHORT cohort Cohort the group belongs to.
|
||||||
--
|
--
|
||||||
@ -424,11 +426,13 @@ OPSGROUP.CarrierStatus={
|
|||||||
|
|
||||||
--- Cargo status.
|
--- Cargo status.
|
||||||
-- @type OPSGROUP.CargoStatus
|
-- @type OPSGROUP.CargoStatus
|
||||||
|
-- @field #string AWAITING Group is awaiting carrier.
|
||||||
-- @field #string NOTCARGO This group is no cargo yet.
|
-- @field #string NOTCARGO This group is no cargo yet.
|
||||||
-- @field #string ASSIGNED Cargo is assigned to a carrier.
|
-- @field #string ASSIGNED Cargo is assigned to a carrier.
|
||||||
-- @field #string BOARDING Cargo is boarding a carrier.
|
-- @field #string BOARDING Cargo is boarding a carrier.
|
||||||
-- @field #string LOADED Cargo is loaded into a carrier.
|
-- @field #string LOADED Cargo is loaded into a carrier.
|
||||||
OPSGROUP.CargoStatus={
|
OPSGROUP.CargoStatus={
|
||||||
|
AWAITING="Awaiting carrier",
|
||||||
NOTCARGO="not cargo",
|
NOTCARGO="not cargo",
|
||||||
ASSIGNED="assigned to carrier",
|
ASSIGNED="assigned to carrier",
|
||||||
BOARDING="boarding",
|
BOARDING="boarding",
|
||||||
@ -1170,6 +1174,14 @@ function OPSGROUP:SetEngageDetectedOff()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set that group is going to rearm once it runs out of ammo.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:SetRearmOnOutOfAmmo()
|
||||||
|
self.rearmOnOutOfAmmo=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if an element of the group has line of sight to a coordinate.
|
--- Check if an element of the group has line of sight to a coordinate.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param Core.Point#COORDINATE Coordinate The position to which we check the LoS.
|
-- @param Core.Point#COORDINATE Coordinate The position to which we check the LoS.
|
||||||
@ -2277,6 +2289,49 @@ function OPSGROUP:IsNotCargo(CheckTransport)
|
|||||||
return notcargo
|
return notcargo
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if awaiting a transport.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:_AddMyLift(Transport)
|
||||||
|
self.mylifts=self.mylifts or {}
|
||||||
|
self.mylifts[Transport.uid]=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove my lift.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport.
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:_DelMyLift(Transport)
|
||||||
|
if self.mylifts then
|
||||||
|
self.mylifts[Transport.uid]=nil
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if awaiting a transport lift.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Ops.OpsTransport#OPSTRANSPORT Transport (Optional) The transport.
|
||||||
|
-- @return #boolean If true, group is awaiting transport lift..
|
||||||
|
function OPSGROUP:IsAwaitingLift(Transport)
|
||||||
|
|
||||||
|
if self.mylifts then
|
||||||
|
|
||||||
|
for uid,iswaiting in pairs(self.mylifts) do
|
||||||
|
if Transport==nil or Transport.uid==uid then
|
||||||
|
if iswaiting==true then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
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.
|
||||||
@ -3589,10 +3644,20 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Task Alert 5 mission.
|
-- Task "Alert 5" mission.
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Just stay put on the airfield and wait until something happens.
|
-- Just stay put on the airfield and wait until something happens.
|
||||||
|
|
||||||
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ONGUARD then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Task "On Guard" Mission.
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Just stay put.
|
||||||
|
--TODO: Change ALARM STATE
|
||||||
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -3690,7 +3755,9 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
|
|||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.FUELSUPPLY then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.FUELSUPPLY then
|
||||||
done=true
|
done=true
|
||||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ALERT5 then
|
||||||
done=true
|
done=true
|
||||||
|
elseif Task.dcstask.id==AUFTRAG.SpecialTask.ONGUARD then
|
||||||
|
done=true
|
||||||
elseif stopflag==1 or (not self:IsAlive()) or self:IsDead() or self:IsStopped() then
|
elseif stopflag==1 or (not self:IsAlive()) or self:IsDead() or self:IsStopped() then
|
||||||
-- Manual call TaskDone if setting flag to one was not successful.
|
-- Manual call TaskDone if setting flag to one was not successful.
|
||||||
done=true
|
done=true
|
||||||
@ -4200,7 +4267,7 @@ function OPSGROUP:onafterMissionCancel(From, Event, To, Mission)
|
|||||||
---
|
---
|
||||||
|
|
||||||
-- Alert 5 missoins dont have a task set, which could be cancelled.
|
-- Alert 5 missoins dont have a task set, which could be cancelled.
|
||||||
if Mission.type==AUFTRAG.Type.ALERT5 then
|
if Mission.type==AUFTRAG.Type.ALERT5 or Mission.type==AUFTRAG.Type.ONGUARD then
|
||||||
self:MissionDone(Mission)
|
self:MissionDone(Mission)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -4440,6 +4507,10 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
|
|
||||||
elseif mission.type==AUFTRAG.Type.ARTY then
|
elseif mission.type==AUFTRAG.Type.ARTY then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- ARTY
|
||||||
|
---
|
||||||
|
|
||||||
-- Get weapon range.
|
-- Get weapon range.
|
||||||
local weapondata=self:GetWeaponData(mission.engageWeaponType)
|
local weapondata=self:GetWeaponData(mission.engageWeaponType)
|
||||||
|
|
||||||
@ -5990,7 +6061,7 @@ end
|
|||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function OPSGROUP:onafterOutOfAmmo(From, Event, To)
|
function OPSGROUP: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()))
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -7174,7 +7245,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
|
|||||||
|
|
||||||
-- New cargo status.
|
-- New cargo status.
|
||||||
CargoGroup:_NewCargoStatus(OPSGROUP.CargoStatus.LOADED)
|
CargoGroup:_NewCargoStatus(OPSGROUP.CargoStatus.LOADED)
|
||||||
|
|
||||||
-- Clear all waypoints.
|
-- Clear all waypoints.
|
||||||
CargoGroup:ClearWaypoints()
|
CargoGroup:ClearWaypoints()
|
||||||
|
|
||||||
@ -7191,6 +7262,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
|
|||||||
|
|
||||||
-- Trigger "Loaded" event for current cargo transport.
|
-- Trigger "Loaded" event for current cargo transport.
|
||||||
if self.cargoTransport then
|
if self.cargoTransport then
|
||||||
|
CargoGroup:_DelMyLift(self.cargoTransport)
|
||||||
self.cargoTransport:Loaded(CargoGroup, self, carrier)
|
self.cargoTransport:Loaded(CargoGroup, self, carrier)
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("WARNING: Loaded cargo but no current OPSTRANSPORT assignment!"))
|
self:T(self.lid..string.format("WARNING: Loaded cargo but no current OPSTRANSPORT assignment!"))
|
||||||
@ -7341,7 +7413,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- ARMYGROUP
|
-- ARMYGROUP
|
||||||
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid) ; waypoint.detour=1
|
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, ENUMS.Formation.Vehicle.OnRoad) ; waypoint.detour=1
|
||||||
|
|
||||||
-- Give cruise command.
|
-- Give cruise command.
|
||||||
self:Cruise()
|
self:Cruise()
|
||||||
@ -8444,7 +8516,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
|||||||
if self.outofMissilesAA and ammo.MissilesAA>0 then
|
if self.outofMissilesAA and ammo.MissilesAA>0 then
|
||||||
self.outofMissilesAA=false
|
self.outofMissilesAA=false
|
||||||
end
|
end
|
||||||
if ammo.MissilesAA and self.ammo.MissilesAA>0 and not self.outofMissilesAA then
|
if ammo.MissilesAA==0 and self.ammo.MissilesAA>0 and not self.outofMissilesAA then
|
||||||
self.outofMissilesAA=true
|
self.outofMissilesAA=true
|
||||||
self:OutOfMissilesAA()
|
self:OutOfMissilesAA()
|
||||||
end
|
end
|
||||||
@ -8453,7 +8525,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
|||||||
if self.outofMissilesAG and ammo.MissilesAG>0 then
|
if self.outofMissilesAG and ammo.MissilesAG>0 then
|
||||||
self.outofMissilesAG=false
|
self.outofMissilesAG=false
|
||||||
end
|
end
|
||||||
if ammo.MissilesAG and self.ammo.MissilesAG>0 and not self.outofMissilesAG then
|
if ammo.MissilesAG==0 and self.ammo.MissilesAG>0 and not self.outofMissilesAG then
|
||||||
self.outofMissilesAG=true
|
self.outofMissilesAG=true
|
||||||
self:OutOfMissilesAG()
|
self:OutOfMissilesAG()
|
||||||
end
|
end
|
||||||
@ -8462,7 +8534,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
|||||||
if self.outofMissilesAS and ammo.MissilesAS>0 then
|
if self.outofMissilesAS and ammo.MissilesAS>0 then
|
||||||
self.outofMissilesAS=false
|
self.outofMissilesAS=false
|
||||||
end
|
end
|
||||||
if ammo.MissilesAS and self.ammo.MissilesAS>0 and not self.outofMissilesAS then
|
if ammo.MissilesAS==0 and self.ammo.MissilesAS>0 and not self.outofMissilesAS then
|
||||||
self.outofMissilesAS=true
|
self.outofMissilesAS=true
|
||||||
self:OutOfMissilesAS()
|
self:OutOfMissilesAS()
|
||||||
end
|
end
|
||||||
|
|||||||
@ -485,6 +485,8 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo)
|
|||||||
table.insert(TransportZoneCombo.Cargos, cargo)
|
table.insert(TransportZoneCombo.Cargos, cargo)
|
||||||
TransportZoneCombo.Ncargo=TransportZoneCombo.Ncargo+1
|
TransportZoneCombo.Ncargo=TransportZoneCombo.Ncargo+1
|
||||||
|
|
||||||
|
cargo.opsgroup:_AddMyLift(self)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -1296,7 +1298,7 @@ end
|
|||||||
function OPSTRANSPORT:AddLegion(Legion)
|
function OPSTRANSPORT:AddLegion(Legion)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Adding legion %s", Legion.alias))
|
self:T(self.lid..string.format("Adding legion %s", Legion.alias))
|
||||||
|
|
||||||
-- Add legion to table.
|
-- Add legion to table.
|
||||||
table.insert(self.legions, Legion)
|
table.insert(self.legions, Legion)
|
||||||
@ -1315,7 +1317,7 @@ function OPSTRANSPORT:RemoveLegion(Legion)
|
|||||||
local legion=self.legions[i] --Ops.Legion#LEGION
|
local legion=self.legions[i] --Ops.Legion#LEGION
|
||||||
if legion.alias==Legion.alias then
|
if legion.alias==Legion.alias then
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Removing legion %s", Legion.alias))
|
self:T(self.lid..string.format("Removing legion %s", Legion.alias))
|
||||||
table.remove(self.legions, i)
|
table.remove(self.legions, i)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1409,7 +1411,7 @@ function OPSTRANSPORT:SetLegionStatus(Legion, Status)
|
|||||||
local status=self:GetLegionStatus(Legion)
|
local status=self:GetLegionStatus(Legion)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Setting LEGION %s to status %s-->%s", Legion.alias, tostring(status), tostring(Status)))
|
self:T(self.lid..string.format("Setting LEGION %s to status %s-->%s", Legion.alias, tostring(status), tostring(Status)))
|
||||||
|
|
||||||
-- New status.
|
-- New status.
|
||||||
self.statusLegion[Legion.alias]=Status
|
self.statusLegion[Legion.alias]=Status
|
||||||
@ -1681,7 +1683,7 @@ function OPSTRANSPORT:onafterCancel(From, Event, To)
|
|||||||
local Ngroups = #self.carriers
|
local Ngroups = #self.carriers
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("CANCELLING mission in status %s. Will wait for %d groups to report mission DONE before evaluation", self.status, Ngroups))
|
self:I(self.lid..string.format("CANCELLING transport in status %s. Will wait for %d carrier groups to report DONE before evaluation", self.status, Ngroups))
|
||||||
|
|
||||||
-- Time stamp.
|
-- Time stamp.
|
||||||
self.Tover=timer.getAbsTime()
|
self.Tover=timer.getAbsTime()
|
||||||
@ -1728,6 +1730,14 @@ function OPSTRANSPORT:onafterCancel(From, Event, To)
|
|||||||
carrier:TransportCancel(self)
|
carrier:TransportCancel(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Delete awaited transport.
|
||||||
|
local cargos=self:GetCargoOpsGroups(false)
|
||||||
|
for _,_cargo in pairs(cargos) do
|
||||||
|
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
||||||
|
cargo:_DelMyLift(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Special mission states.
|
-- Special mission states.
|
||||||
@ -1969,7 +1979,7 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
|
|||||||
local isInUtero=cargo:IsInUtero()
|
local isInUtero=cargo:IsInUtero()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(isInZone), tostring(isInUtero)))
|
self:T(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(isInZone), tostring(isInUtero)))
|
||||||
|
|
||||||
-- We look for groups that are not cargo, in the zone or in utero.
|
-- We look for groups that are not cargo, in the zone or in utero.
|
||||||
if isNotCargo and (isInZone or isInUtero) then
|
if isNotCargo and (isInZone or isInUtero) then
|
||||||
|
|||||||
@ -36,6 +36,8 @@
|
|||||||
-- @field #boolean neutralCanCapture Neutral units can capture. Default `false`.
|
-- @field #boolean neutralCanCapture Neutral units can capture. Default `false`.
|
||||||
-- @field #boolean drawZone If `true`, draw the zone on the F10 map.
|
-- @field #boolean drawZone If `true`, draw the zone on the F10 map.
|
||||||
-- @field #boolean markZone If `true`, mark the zone on the F10 map.
|
-- @field #boolean markZone If `true`, mark the zone on the F10 map.
|
||||||
|
-- @field #number prio Priority of the zone (for CHIEF queue).
|
||||||
|
-- @field #number importance Importance of the zone (for CHIEF queue).
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Be surprised!
|
--- Be surprised!
|
||||||
@ -90,15 +92,34 @@ function OPSZONE:New(Zone, CoalitionOwner)
|
|||||||
local self=BASE:Inherit(self, FSM:New()) -- #OPSZONE
|
local self=BASE:Inherit(self, FSM:New()) -- #OPSZONE
|
||||||
|
|
||||||
-- Check if zone name instead of ZONE object was passed.
|
-- Check if zone name instead of ZONE object was passed.
|
||||||
if type(Zone)=="string" then
|
if Zone then
|
||||||
Zone=ZONE:New(Zone)
|
if type(Zone)=="string" then
|
||||||
|
-- Convert string into a ZONE or ZONE_AIRBASE
|
||||||
|
local Name=Zone
|
||||||
|
Zone=ZONE:New(Name)
|
||||||
|
if not Zone then
|
||||||
|
local airbase=AIRBASE:FindByName(Name)
|
||||||
|
if airbase then
|
||||||
|
Zone=ZONE_AIRBASE:New(Name, 2000)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not Zone then
|
||||||
|
self:E(string.format("ERROR: No ZONE or ZONE_AIRBASE found for name: %s", Name))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E("ERROR: First parameter Zone is nil in OPSZONE:New(Zone) call!")
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Basic checks.
|
-- Basic checks.
|
||||||
if not Zone then
|
if Zone:IsInstanceOf("ZONE_AIRBASE") then
|
||||||
self:E("ERROR: OPSZONE not found!")
|
self.airbase=Zone._.ZoneAirbase
|
||||||
return nil
|
self.airbaseName=self.airbase:GetName()
|
||||||
elseif not Zone:IsInstanceOf("ZONE_RADIUS") then
|
elseif Zone:IsInstanceOf("ZONE_RADIUS") then
|
||||||
|
-- Nothing to do.
|
||||||
|
else
|
||||||
self:E("ERROR: OPSZONE must be a SPHERICAL zone due to DCS restrictions!")
|
self:E("ERROR: OPSZONE must be a SPHERICAL zone due to DCS restrictions!")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -115,10 +136,21 @@ function OPSZONE:New(Zone, CoalitionOwner)
|
|||||||
self.ownerCurrent=CoalitionOwner or coalition.side.NEUTRAL
|
self.ownerCurrent=CoalitionOwner or coalition.side.NEUTRAL
|
||||||
self.ownerPrevious=CoalitionOwner or coalition.side.NEUTRAL
|
self.ownerPrevious=CoalitionOwner or coalition.side.NEUTRAL
|
||||||
|
|
||||||
|
-- We take the airbase coalition.
|
||||||
|
if self.airbase then
|
||||||
|
self.ownerCurrent=self.airbase:GetCoalition()
|
||||||
|
self.ownerPrevious=self.airbase:GetCoalition()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set priority (default 50) and importance (default nil).
|
||||||
|
self:SetPriority()
|
||||||
|
self:SetImportance()
|
||||||
|
|
||||||
-- Set object categories.
|
-- Set object categories.
|
||||||
self:SetObjectCategories()
|
self:SetObjectCategories()
|
||||||
self:SetUnitCategories()
|
self:SetUnitCategories()
|
||||||
|
|
||||||
|
-- TODO: make input function
|
||||||
self.drawZone=true
|
self.drawZone=true
|
||||||
|
|
||||||
-- Status timer.
|
-- Status timer.
|
||||||
@ -138,8 +170,7 @@ function OPSZONE:New(Zone, CoalitionOwner)
|
|||||||
self:AddTransition("Empty", "Guarded", "Guarded") -- Owning coalition left the zone and returned.
|
self:AddTransition("Empty", "Guarded", "Guarded") -- Owning coalition left the zone and returned.
|
||||||
|
|
||||||
self:AddTransition("*", "Empty", "Empty") -- No red or blue units inside the zone.
|
self:AddTransition("*", "Empty", "Empty") -- No red or blue units inside the zone.
|
||||||
|
|
||||||
|
|
||||||
self:AddTransition("*", "Attacked", "Attacked") -- A guarded zone is under attack.
|
self:AddTransition("*", "Attacked", "Attacked") -- A guarded zone is under attack.
|
||||||
self:AddTransition("*", "Defeated", "Guarded") -- The owning coalition defeated an attack.
|
self:AddTransition("*", "Defeated", "Guarded") -- The owning coalition defeated an attack.
|
||||||
|
|
||||||
@ -318,6 +349,25 @@ function OPSZONE:SetNeutralCanCapture(CanCapture)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[CHIEF]** Set mission priority.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #number Prio Priority 1=high, 100=low. Default 50.
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:SetPriority(Prio)
|
||||||
|
self.prio=Prio or 50
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- **[CHIEF]** Set importance.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #number Importance Number 1-10. If missions with lower value are in the queue, these have to be finished first. Default is `nil`.
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:SetImportance(Importance)
|
||||||
|
self.importance=Importance
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get current owner of the zone.
|
--- Get current owner of the zone.
|
||||||
-- @param #OPSZONE self
|
-- @param #OPSZONE self
|
||||||
-- @return #number Owner coalition.
|
-- @return #number Owner coalition.
|
||||||
@ -426,21 +476,14 @@ function OPSZONE:onafterStart(From, Event, To)
|
|||||||
-- Reinit the timer.
|
-- Reinit the timer.
|
||||||
self.timerStatus=self.timerStatus or TIMER:New(OPSZONE.Status, self)
|
self.timerStatus=self.timerStatus or TIMER:New(OPSZONE.Status, self)
|
||||||
|
|
||||||
-- Perform initial scan.
|
|
||||||
self:Scan()
|
|
||||||
|
|
||||||
if self.Nblu==0 and self.Nred==0 then
|
|
||||||
elseif self.Nblu>0 and self.Nred>0 then
|
|
||||||
|
|
||||||
elseif self.Nblu>0 then
|
|
||||||
|
|
||||||
elseif self.Nred>0 then
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Status update.
|
-- Status update.
|
||||||
self.timerStatus:Start(1, 60)
|
self.timerStatus:Start(1, 60)
|
||||||
|
|
||||||
|
-- Handle base captured event.
|
||||||
|
if self.airbase then
|
||||||
|
self:HandleEvent(EVENTS.BaseCaptured)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stop OPSZONE FSM.
|
--- Stop OPSZONE FSM.
|
||||||
@ -456,6 +499,9 @@ function OPSZONE:onafterStop(From, Event, To)
|
|||||||
-- Reinit the timer.
|
-- Reinit the timer.
|
||||||
self.timerStatus:Stop()
|
self.timerStatus:Stop()
|
||||||
|
|
||||||
|
-- Unhandle events.
|
||||||
|
self:UnHandleEvent(EVENTS.BaseCaptured)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -481,6 +527,9 @@ function OPSZONE:Status()
|
|||||||
-- Scanning zone.
|
-- Scanning zone.
|
||||||
self:Scan()
|
self:Scan()
|
||||||
|
|
||||||
|
-- Evaluate the scan result.
|
||||||
|
self:EvaluateZone()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -782,10 +831,14 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nblu>0 then
|
if Nblu>0 then
|
||||||
-- Blue captured red zone.
|
-- Blue captured red zone.
|
||||||
self:Captured(coalition.side.BLUE)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.BLUE)
|
||||||
|
end
|
||||||
elseif Nnut>0 and self.neutralCanCapture then
|
elseif Nnut>0 and self.neutralCanCapture then
|
||||||
-- Neutral captured red zone.
|
-- Neutral captured red zone.
|
||||||
self:Captured(coalition.side.NEUTRAL)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.NEUTRAL)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Red zone is now empty (but will remain red).
|
-- Red zone is now empty (but will remain red).
|
||||||
if not self:IsEmpty() then
|
if not self:IsEmpty() then
|
||||||
@ -835,10 +888,14 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nred>0 then
|
if Nred>0 then
|
||||||
-- Red captured blue zone.
|
-- Red captured blue zone.
|
||||||
self:Captured(coalition.side.RED)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.RED)
|
||||||
|
end
|
||||||
elseif Nnut>0 and self.neutralCanCapture then
|
elseif Nnut>0 and self.neutralCanCapture then
|
||||||
-- Neutral captured blue zone.
|
-- Neutral captured blue zone.
|
||||||
self:Captured(coalition.side.NEUTRAL)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.NEUTRAL)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Blue zone is empty now.
|
-- Blue zone is empty now.
|
||||||
if not self:IsEmpty() then
|
if not self:IsEmpty() then
|
||||||
@ -896,10 +953,14 @@ function OPSZONE:EvaluateZone()
|
|||||||
self.isContested=true
|
self.isContested=true
|
||||||
elseif Nred>0 then
|
elseif Nred>0 then
|
||||||
-- Red captured neutral zone.
|
-- Red captured neutral zone.
|
||||||
self:Captured(coalition.side.RED)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.RED)
|
||||||
|
end
|
||||||
elseif Nblu>0 then
|
elseif Nblu>0 then
|
||||||
-- Blue captured neutral zone.
|
-- Blue captured neutral zone.
|
||||||
self:Captured(coalition.side.BLUE)
|
if not self.airbase then
|
||||||
|
self:Captured(coalition.side.BLUE)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Neutral zone is empty now.
|
-- Neutral zone is empty now.
|
||||||
if not self:IsEmpty() then
|
if not self:IsEmpty() then
|
||||||
@ -947,7 +1008,7 @@ function OPSZONE:OnEventHit(EventData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Monitor hit events.
|
--- Monitor base captured events.
|
||||||
-- @param #OPSZONE self
|
-- @param #OPSZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData The event data.
|
-- @param Core.Event#EVENTDATA EventData The event data.
|
||||||
function OPSZONE:OnEventBaseCaptured(EventData)
|
function OPSZONE:OnEventBaseCaptured(EventData)
|
||||||
@ -960,6 +1021,17 @@ function OPSZONE:OnEventBaseCaptured(EventData)
|
|||||||
-- Check that this airbase belongs or did belong to this warehouse.
|
-- Check that this airbase belongs or did belong to this warehouse.
|
||||||
if EventData.PlaceName==self.airbaseName then
|
if EventData.PlaceName==self.airbaseName then
|
||||||
|
|
||||||
|
-- New coalition of the airbase
|
||||||
|
local CoalitionNew=airbase:GetCoalition()
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("EVENT BASE CAPTURED: New coalition of airbase %s: %d [previous=%d]", self.airbaseName, CoalitionNew, self.ownerCurrent))
|
||||||
|
|
||||||
|
-- Check that coalition actually changed.
|
||||||
|
if CoalitionNew~=self.ownerCurrent then
|
||||||
|
self:Captured(CoalitionNew)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user