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!
|
||||
if not Zone then
|
||||
error( "Zone " .. ZoneName .. " does not exist." )
|
||||
env.error( "ERROR: Zone " .. ZoneName .. " does not exist!" )
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@ -812,6 +812,39 @@ function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation,
|
||||
|
||||
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.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -1403,6 +1436,7 @@ end
|
||||
-- @param #ARMYGROUP self
|
||||
-- @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 #number Distance to closest group in meters.
|
||||
function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
||||
|
||||
-- Radius in meters.
|
||||
@ -1410,6 +1444,9 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
||||
|
||||
-- Current positon.
|
||||
local coord=self:GetCoordinate()
|
||||
|
||||
-- Get my coalition.
|
||||
local myCoalition=self:GetCoalition()
|
||||
|
||||
-- Scanned units.
|
||||
local units=coord:ScanUnits(Radius)
|
||||
@ -1421,10 +1458,10 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- 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.
|
||||
local d=unit:GetCoordinate():Get2DDistance(coord)
|
||||
local d=coord:Get2DDistance(unit:GetCoord())
|
||||
|
||||
-- Check if distance is smaller.
|
||||
if d<dmin then
|
||||
@ -1436,10 +1473,10 @@ function ARMYGROUP:FindNearestAmmoSupply(Radius)
|
||||
end
|
||||
|
||||
if truck then
|
||||
return truck:GetGroup()
|
||||
return truck:GetGroup(), dmin
|
||||
end
|
||||
|
||||
return nil
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -369,7 +369,7 @@ _AUFTRAGSNR=0
|
||||
-- @field #string AMMOSUPPLY Ammo supply.
|
||||
-- @field #string FUELSUPPLY Fuel supply.
|
||||
-- @field #string ALERT5 Alert 5.
|
||||
-- @field #string ONWATCH On watch.
|
||||
-- @field #string ONGUARD On guard.
|
||||
AUFTRAG.Type={
|
||||
ANTISHIP="Anti Ship",
|
||||
AWACS="AWACS",
|
||||
@ -397,8 +397,8 @@ AUFTRAG.Type={
|
||||
OPSTRANSPORT="Ops Transport",
|
||||
AMMOSUPPLY="Ammo Supply",
|
||||
FUELSUPPLY="Fuel Supply",
|
||||
ALERT5="Alert 5",
|
||||
ONWATCH="On Watch",
|
||||
ALERT5="Alert5",
|
||||
ONGUARD="On Guard",
|
||||
}
|
||||
|
||||
--- Mission status of an assigned group.
|
||||
@ -408,14 +408,14 @@ AUFTRAG.Type={
|
||||
-- @field #string AMMOSUPPLY Ammo Supply.
|
||||
-- @field #string FUELSUPPLY Fuel Supply.
|
||||
-- @field #string ALERT5 Alert 5 task.
|
||||
-- @field #string ONWATCH On Watch
|
||||
-- @field #string ONGUARD On guard.
|
||||
AUFTRAG.SpecialTask={
|
||||
PATROLZONE="PatrolZone",
|
||||
RECON="ReconMission",
|
||||
AMMOSUPPLY="Ammo Supply",
|
||||
FUELSUPPLY="Fuel Supply",
|
||||
ALERT5="Alert 5",
|
||||
ONWATCH="On Watch",
|
||||
ALERT5="Alert5",
|
||||
ONGUARD="On Guard",
|
||||
}
|
||||
|
||||
--- Mission status.
|
||||
@ -1692,6 +1692,7 @@ function AUFTRAG:NewALERT5(MissionType)
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.ALERT5)
|
||||
|
||||
mission.missionTask=self:GetMissionTaskforMissionType(MissionType)
|
||||
|
||||
mission.optionROE=ENUMS.ROE.WeaponHold
|
||||
mission.optionROT=ENUMS.ROT.NoReaction
|
||||
|
||||
@ -1706,6 +1707,28 @@ function AUFTRAG:NewALERT5(MissionType)
|
||||
return mission
|
||||
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.
|
||||
-- @param #AUFTRAG self
|
||||
@ -2328,7 +2351,7 @@ function AUFTRAG:AssignSquadrons(Squadrons)
|
||||
|
||||
for _,_squad in pairs(Squadrons) do
|
||||
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)
|
||||
end
|
||||
|
||||
@ -3313,7 +3336,7 @@ end
|
||||
function AUFTRAG:AddLegion(Legion)
|
||||
|
||||
-- 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.
|
||||
table.insert(self.legions, Legion)
|
||||
@ -3332,7 +3355,7 @@ function AUFTRAG:RemoveLegion(Legion)
|
||||
local legion=self.legions[i] --Ops.Legion#LEGION
|
||||
if legion.alias==Legion.alias then
|
||||
-- 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)
|
||||
return self
|
||||
end
|
||||
@ -3353,7 +3376,7 @@ function AUFTRAG:SetLegionStatus(Legion, Status)
|
||||
local status=self:GetLegionStatus(Legion)
|
||||
|
||||
-- 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.
|
||||
self.statusLegion[Legion.alias]=Status
|
||||
@ -4750,6 +4773,24 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
||||
DCStask.params=param
|
||||
|
||||
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
|
||||
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
||||
|
||||
@ -18,7 +18,8 @@
|
||||
-- @type BRIGADE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @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.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
@ -33,16 +34,17 @@
|
||||
--
|
||||
-- @field #BRIGADE
|
||||
BRIGADE = {
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 0,
|
||||
rearmingZones = {},
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 0,
|
||||
rearmingZones = {},
|
||||
refuellingZones = {},
|
||||
}
|
||||
|
||||
--- Rearming Zone.
|
||||
-- @type BRIGADE.RearmingZone
|
||||
--- Supply Zone.
|
||||
-- @type BRIGADE.SupplyZone
|
||||
-- @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.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||
-- @field #boolean markerOn If `true`, marker is on.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
|
||||
--- BRIGADE class version.
|
||||
@ -225,13 +227,12 @@ end
|
||||
--- Add a rearming zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @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)
|
||||
|
||||
local rearmingzone={} --#BRIGADE.RearmingZone
|
||||
local rearmingzone={} --#BRIGADE.SupplyZone
|
||||
|
||||
rearmingzone.zone=RearmingZone
|
||||
rearmingzone.occupied=false
|
||||
rearmingzone.mission=nil
|
||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
@ -241,6 +242,24 @@ function BRIGADE:AddRearmingZone(RearmingZone)
|
||||
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.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string PlatoonName Name of the platoon.
|
||||
@ -312,14 +331,28 @@ function BRIGADE:onafterStatus(From, Event, To)
|
||||
-- Rearming Zones ---
|
||||
---------------------
|
||||
|
||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||
self:AddMission(rearmingzone.mission)
|
||||
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 ---
|
||||
@ -396,19 +429,28 @@ function BRIGADE:onafterStatus(From, Event, To)
|
||||
-------------------
|
||||
-- Rearming Info --
|
||||
-------------------
|
||||
if self.verbose>=0 then
|
||||
if self.verbose>=4 then
|
||||
local text="Rearming Zones:"
|
||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
||||
|
||||
local name=rearmingzone.zone:GetName()
|
||||
|
||||
-- Platoon text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", name, rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
||||
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", rearmingzone.zone:GetName(), rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
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
|
||||
|
||||
|
||||
@ -60,11 +60,13 @@ CHIEF.DEFCON = {
|
||||
|
||||
--- 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 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.
|
||||
CHIEF.Strategy = {
|
||||
PASSIVE="Passive",
|
||||
DEFENSIVE="Defensive",
|
||||
OFFENSIVE="Offensive",
|
||||
AGGRESSIVE="Aggressive",
|
||||
@ -570,13 +572,25 @@ end
|
||||
--- Add a rearming zone.
|
||||
-- @param #CHIEF self
|
||||
-- @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)
|
||||
|
||||
-- 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
|
||||
|
||||
|
||||
@ -840,7 +854,8 @@ function CHIEF:onafterStatus(From, Event, To)
|
||||
for i,_opszone in pairs(self.zonequeue) do
|
||||
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
|
||||
self:I(self.lid..text)
|
||||
@ -1059,14 +1074,22 @@ function CHIEF:CheckTargetQueue()
|
||||
local target=_target --Ops.Target#TARGET
|
||||
|
||||
-- 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.
|
||||
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.
|
||||
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.
|
||||
@ -1146,7 +1169,6 @@ function CHIEF:CheckTargetQueue()
|
||||
if mission then
|
||||
for _,_asset in pairs(assets) do
|
||||
local asset=_asset
|
||||
asset.isReserved=true
|
||||
mission:AddAsset(asset)
|
||||
end
|
||||
Legions=legions
|
||||
@ -1204,19 +1226,20 @@ function CHIEF:CheckOpsZoneQueue()
|
||||
|
||||
-- Sort results table wrt ?.
|
||||
local function _sort(a, b)
|
||||
local taskA=a --Ops.Target#TARGET
|
||||
local taskB=b --Ops.Target#TARGET
|
||||
local taskA=a --Ops.OpsZone#OPSZONE
|
||||
local taskB=b --Ops.OpsZone#OPSZONE
|
||||
return (taskA.prio<taskB.prio)
|
||||
end
|
||||
--table.sort(self.zonequeue, _sort)
|
||||
table.sort(self.zonequeue, _sort)
|
||||
|
||||
-- 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
|
||||
for _,_target in pairs(self.zonequeue) do
|
||||
local target=_target --Ops.Target#TARGET
|
||||
if target.importance and target.importance<vip then
|
||||
vip=target.importance
|
||||
for _,_opszone in pairs(self.zonequeue) do
|
||||
local opszone=_opszone --Ops.OpsZone#OPSZONE
|
||||
if opszone.importance and opszone.importance<vip and opszone:GetOwner()~=self.coalition then
|
||||
-- Most important zone that is NOT owned by us.
|
||||
vip=opszone.importance
|
||||
end
|
||||
end
|
||||
|
||||
@ -1226,15 +1249,43 @@ function CHIEF:CheckOpsZoneQueue()
|
||||
|
||||
-- Current owner of the zone.
|
||||
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
|
||||
|
||||
env.info(string.format("Zone %s is owned by coalition %d", opszone.zone:GetName(), ownercoalition))
|
||||
if opszone:IsEmpty() then
|
||||
|
||||
-- Recruit ground assets that
|
||||
local recruited=self:RecruitAssetsForZone(opszone, AUFTRAG.Type.PATROLZONE, 1, 3, {Group.Category.GROUND}, {GROUP.Attribute.GROUND_INFANTRY})
|
||||
if not hasMissionPatrol then
|
||||
|
||||
-- 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
|
||||
|
||||
@ -1568,45 +1619,78 @@ function CHIEF:RecruitAssetsForZone(OpsZone, MissionType, NassetsMin, NassetsMax
|
||||
|
||||
-- Target position.
|
||||
local TargetVec2=OpsZone.zone:GetVec2()
|
||||
|
||||
|
||||
-- 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))
|
||||
|
||||
-- Recruit transport assets for infantry.
|
||||
local recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assetsInf, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
|
||||
|
||||
|
||||
-- Create Patrol zone mission.
|
||||
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
|
||||
mission:SetEngageDetected()
|
||||
|
||||
-- Add assets to mission.
|
||||
for _,asset in pairs(assetsInf) do
|
||||
mission:AddAsset(asset)
|
||||
end
|
||||
|
||||
-- Attach OPS transport to mission.
|
||||
mission.opstransport=transport
|
||||
if MissionType==AUFTRAG.Type.PATROLZONE then
|
||||
|
||||
-- Debug messgage.
|
||||
self:T2(self.lid..string.format("Recruited %d assets from for PATROL mission", #assets))
|
||||
|
||||
local recruitedTrans=true
|
||||
local transport=nil
|
||||
if Attributes and Attributes[1]==GROUP.Attribute.GROUND_INFANTRY then
|
||||
|
||||
-- Recruit transport assets for infantry.
|
||||
recruitedTrans, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, assets, 1, 1, OpsZone.zone, nil, {Group.Category.HELICOPTER, Group.Category.GROUND})
|
||||
|
||||
-- Assign mission to legions.
|
||||
for _,_legion in pairs(legionsInf) 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
|
||||
end
|
||||
|
||||
if recruitedTrans then
|
||||
|
||||
return true
|
||||
else
|
||||
LEGION.UnRecruitAssets(assetsInf)
|
||||
return false
|
||||
end
|
||||
-- Create Patrol zone mission.
|
||||
local mission=AUFTRAG:NewPATROLZONE(OpsZone.zone)
|
||||
mission:SetEngageDetected()
|
||||
|
||||
|
||||
-- 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
|
||||
end
|
||||
|
||||
@ -906,8 +906,14 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
||||
|
||||
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".
|
||||
if combatready then
|
||||
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 missionqueue Mission 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.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
@ -35,12 +36,13 @@
|
||||
--
|
||||
-- @field #COMMANDER
|
||||
COMMANDER = {
|
||||
ClassName = "COMMANDER",
|
||||
verbose = 0,
|
||||
legions = {},
|
||||
missionqueue = {},
|
||||
transportqueue = {},
|
||||
rearmingZones = {},
|
||||
ClassName = "COMMANDER",
|
||||
verbose = 0,
|
||||
legions = {},
|
||||
missionqueue = {},
|
||||
transportqueue = {},
|
||||
rearmingZones = {},
|
||||
refuellingZones = {},
|
||||
}
|
||||
|
||||
--- COMMANDER class version.
|
||||
@ -335,13 +337,12 @@ end
|
||||
--- Add a rearming zone.
|
||||
-- @param #COMMANDER self
|
||||
-- @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)
|
||||
|
||||
local rearmingzone={} --Ops.Brigade#BRIGADE.RearmingZone
|
||||
local rearmingzone={} --Ops.Brigade#BRIGADE.SupplyZone
|
||||
|
||||
rearmingzone.zone=RearmingZone
|
||||
rearmingzone.occupied=false
|
||||
rearmingzone.mission=nil
|
||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
@ -350,6 +351,23 @@ function COMMANDER:AddRearmingZone(RearmingZone)
|
||||
return rearmingzone
|
||||
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
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -402,13 +420,23 @@ function COMMANDER:onafterStatus(From, Event, To)
|
||||
|
||||
-- Check rearming zones.
|
||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.RearmingZone
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
-- Check if mission is nil or over.
|
||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||
self:AddMission(rearmingzone.mission)
|
||||
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
|
||||
|
||||
@ -1140,7 +1140,7 @@ function FLIGHTGROUP:OnEventEngineShutdown(EventData)
|
||||
if element.unit and element.unit:IsAlive() then
|
||||
|
||||
local airbase=self:GetClosestAirbase()
|
||||
local parking=self:GetParkingSpot(element, 10, airbase)
|
||||
local parking=self:GetParkingSpot(element, 100, airbase)
|
||||
|
||||
if airbase and parking then
|
||||
self:ElementArrived(element, airbase, parking)
|
||||
@ -1548,7 +1548,7 @@ end
|
||||
function FLIGHTGROUP:onafterParking(From, Event, To)
|
||||
|
||||
-- Get closest airbase
|
||||
local airbase=self:GetClosestAirbase() --self.group:GetCoordinate():GetClosestAirbase()
|
||||
local airbase=self:GetClosestAirbase()
|
||||
local airbasename=airbase:GetName() or "unknown"
|
||||
|
||||
-- Debug info
|
||||
@ -2006,7 +2006,7 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n, N)
|
||||
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.
|
||||
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)
|
||||
|
||||
-- Add remaining waypoints to route.
|
||||
@ -2087,14 +2087,14 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
||||
|
||||
if delay and delay>0 then
|
||||
-- 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.
|
||||
self:ScheduleOnce(delay, FLIGHTGROUP._CheckGroupDone, self)
|
||||
else
|
||||
|
||||
-- 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
|
||||
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))
|
||||
|
||||
-- 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
|
||||
@ -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
|
||||
|
||||
-- Holding points.
|
||||
local c0=self.group:GetCoordinate()
|
||||
local c0=self:GetCoordinate()
|
||||
local p0=airbase:GetZone():GetRandomCoordinate():SetAltitude(UTILS.FeetToMeters(althold))
|
||||
local p1=nil
|
||||
local wpap=nil
|
||||
@ -2527,7 +2529,7 @@ end
|
||||
function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
||||
|
||||
-- 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.
|
||||
if Altitude then
|
||||
@ -2597,7 +2599,7 @@ function FLIGHTGROUP:onafterRefuel(From, Event, To, Coordinate)
|
||||
|
||||
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)
|
||||
|
||||
@ -3972,7 +3974,7 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
||||
self:I(self.lid.."FF updating menu NOW")
|
||||
|
||||
-- Get current position of group.
|
||||
local position=self.group:GetCoordinate()
|
||||
local position=self:GetCoordinate()
|
||||
|
||||
-- Get all FLIGHTCONTROLS
|
||||
local fc={}
|
||||
|
||||
@ -841,6 +841,13 @@ function LEGION:onafterTransportCancel(From, Event, To, Transport)
|
||||
opsgroup:TransportCancel(Transport)
|
||||
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.
|
||||
Transport:DelAsset(asset)
|
||||
|
||||
@ -1068,7 +1075,7 @@ function LEGION:onafterAssetSpawned(From, Event, To, group, asset, request)
|
||||
if cohort then
|
||||
|
||||
-- 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.
|
||||
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).
|
||||
local chief=self.chief or (self.commander and self.commander.chief or nil) --Ops.Chief#CHIEF
|
||||
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)
|
||||
end
|
||||
|
||||
@ -1932,7 +1939,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
||||
local RightAttribute=CheckAttribute(cohort)
|
||||
|
||||
-- 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)))
|
||||
|
||||
-- Check OnDuty, capable, in range and refueling type (if TANKER).
|
||||
|
||||
@ -69,6 +69,8 @@
|
||||
-- @field #number Ndestroyed Number of destroyed units.
|
||||
-- @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.Cohort#COHORT cohort Cohort the group belongs to.
|
||||
--
|
||||
@ -424,11 +426,13 @@ OPSGROUP.CarrierStatus={
|
||||
|
||||
--- Cargo status.
|
||||
-- @type OPSGROUP.CargoStatus
|
||||
-- @field #string AWAITING Group is awaiting carrier.
|
||||
-- @field #string NOTCARGO This group is no cargo yet.
|
||||
-- @field #string ASSIGNED Cargo is assigned to a carrier.
|
||||
-- @field #string BOARDING Cargo is boarding a carrier.
|
||||
-- @field #string LOADED Cargo is loaded into a carrier.
|
||||
OPSGROUP.CargoStatus={
|
||||
AWAITING="Awaiting carrier",
|
||||
NOTCARGO="not cargo",
|
||||
ASSIGNED="assigned to carrier",
|
||||
BOARDING="boarding",
|
||||
@ -1170,6 +1174,14 @@ function OPSGROUP:SetEngageDetectedOff()
|
||||
return self
|
||||
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.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param Core.Point#COORDINATE Coordinate The position to which we check the LoS.
|
||||
@ -2277,6 +2289,49 @@ function OPSGROUP:IsNotCargo(CheckTransport)
|
||||
return notcargo
|
||||
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.
|
||||
-- @param #OPSGROUP self
|
||||
-- @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
|
||||
|
||||
---
|
||||
-- Task Alert 5 mission.
|
||||
-- Task "Alert 5" mission.
|
||||
---
|
||||
|
||||
-- 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
|
||||
|
||||
@ -3690,7 +3755,9 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
|
||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.FUELSUPPLY then
|
||||
done=true
|
||||
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
|
||||
-- Manual call TaskDone if setting flag to one was not successful.
|
||||
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.
|
||||
if Mission.type==AUFTRAG.Type.ALERT5 then
|
||||
if Mission.type==AUFTRAG.Type.ALERT5 or Mission.type==AUFTRAG.Type.ONGUARD then
|
||||
self:MissionDone(Mission)
|
||||
return
|
||||
end
|
||||
@ -4440,6 +4507,10 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
|
||||
elseif mission.type==AUFTRAG.Type.ARTY then
|
||||
|
||||
---
|
||||
-- ARTY
|
||||
---
|
||||
|
||||
-- Get weapon range.
|
||||
local weapondata=self:GetWeaponData(mission.engageWeaponType)
|
||||
|
||||
@ -5990,7 +6061,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -7174,7 +7245,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
|
||||
|
||||
-- New cargo status.
|
||||
CargoGroup:_NewCargoStatus(OPSGROUP.CargoStatus.LOADED)
|
||||
|
||||
|
||||
-- Clear all waypoints.
|
||||
CargoGroup:ClearWaypoints()
|
||||
|
||||
@ -7191,6 +7262,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
|
||||
|
||||
-- Trigger "Loaded" event for current cargo transport.
|
||||
if self.cargoTransport then
|
||||
CargoGroup:_DelMyLift(self.cargoTransport)
|
||||
self.cargoTransport:Loaded(CargoGroup, self, carrier)
|
||||
else
|
||||
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
|
||||
|
||||
-- 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.
|
||||
self:Cruise()
|
||||
@ -8444,7 +8516,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
||||
if self.outofMissilesAA and ammo.MissilesAA>0 then
|
||||
self.outofMissilesAA=false
|
||||
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()
|
||||
end
|
||||
@ -8453,7 +8525,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
||||
if self.outofMissilesAG and ammo.MissilesAG>0 then
|
||||
self.outofMissilesAG=false
|
||||
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()
|
||||
end
|
||||
@ -8462,7 +8534,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
||||
if self.outofMissilesAS and ammo.MissilesAS>0 then
|
||||
self.outofMissilesAS=false
|
||||
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()
|
||||
end
|
||||
|
||||
@ -485,6 +485,8 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo)
|
||||
table.insert(TransportZoneCombo.Cargos, cargo)
|
||||
TransportZoneCombo.Ncargo=TransportZoneCombo.Ncargo+1
|
||||
|
||||
cargo.opsgroup:_AddMyLift(self)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
@ -1296,7 +1298,7 @@ end
|
||||
function OPSTRANSPORT:AddLegion(Legion)
|
||||
|
||||
-- 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.
|
||||
table.insert(self.legions, Legion)
|
||||
@ -1315,7 +1317,7 @@ function OPSTRANSPORT:RemoveLegion(Legion)
|
||||
local legion=self.legions[i] --Ops.Legion#LEGION
|
||||
if legion.alias==Legion.alias then
|
||||
-- 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)
|
||||
return self
|
||||
end
|
||||
@ -1409,7 +1411,7 @@ function OPSTRANSPORT:SetLegionStatus(Legion, Status)
|
||||
local status=self:GetLegionStatus(Legion)
|
||||
|
||||
-- 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.
|
||||
self.statusLegion[Legion.alias]=Status
|
||||
@ -1681,7 +1683,7 @@ function OPSTRANSPORT:onafterCancel(From, Event, To)
|
||||
local Ngroups = #self.carriers
|
||||
|
||||
-- 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.
|
||||
self.Tover=timer.getAbsTime()
|
||||
@ -1728,6 +1730,14 @@ function OPSTRANSPORT:onafterCancel(From, Event, To)
|
||||
carrier:TransportCancel(self)
|
||||
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
|
||||
|
||||
-- Special mission states.
|
||||
@ -1969,7 +1979,7 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
|
||||
local isInUtero=cargo:IsInUtero()
|
||||
|
||||
-- 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.
|
||||
if isNotCargo and (isInZone or isInUtero) then
|
||||
|
||||
@ -36,6 +36,8 @@
|
||||
-- @field #boolean neutralCanCapture Neutral units can capture. Default `false`.
|
||||
-- @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 #number prio Priority of the zone (for CHIEF queue).
|
||||
-- @field #number importance Importance of the zone (for CHIEF queue).
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Be surprised!
|
||||
@ -90,15 +92,34 @@ function OPSZONE:New(Zone, CoalitionOwner)
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #OPSZONE
|
||||
|
||||
-- Check if zone name instead of ZONE object was passed.
|
||||
if type(Zone)=="string" then
|
||||
Zone=ZONE:New(Zone)
|
||||
if Zone then
|
||||
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
|
||||
|
||||
-- Basic checks.
|
||||
if not Zone then
|
||||
self:E("ERROR: OPSZONE not found!")
|
||||
return nil
|
||||
elseif not Zone:IsInstanceOf("ZONE_RADIUS") then
|
||||
if Zone:IsInstanceOf("ZONE_AIRBASE") then
|
||||
self.airbase=Zone._.ZoneAirbase
|
||||
self.airbaseName=self.airbase:GetName()
|
||||
elseif Zone:IsInstanceOf("ZONE_RADIUS") then
|
||||
-- Nothing to do.
|
||||
else
|
||||
self:E("ERROR: OPSZONE must be a SPHERICAL zone due to DCS restrictions!")
|
||||
return nil
|
||||
end
|
||||
@ -115,10 +136,21 @@ function OPSZONE:New(Zone, CoalitionOwner)
|
||||
self.ownerCurrent=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.
|
||||
self:SetObjectCategories()
|
||||
self:SetUnitCategories()
|
||||
|
||||
-- TODO: make input function
|
||||
self.drawZone=true
|
||||
|
||||
-- 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", "Empty") -- No red or blue units inside the zone.
|
||||
|
||||
|
||||
|
||||
self:AddTransition("*", "Attacked", "Attacked") -- A guarded zone is under attack.
|
||||
self:AddTransition("*", "Defeated", "Guarded") -- The owning coalition defeated an attack.
|
||||
|
||||
@ -318,6 +349,25 @@ function OPSZONE:SetNeutralCanCapture(CanCapture)
|
||||
return self
|
||||
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.
|
||||
-- @param #OPSZONE self
|
||||
-- @return #number Owner coalition.
|
||||
@ -426,21 +476,14 @@ function OPSZONE:onafterStart(From, Event, To)
|
||||
-- Reinit the timer.
|
||||
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.
|
||||
self.timerStatus:Start(1, 60)
|
||||
|
||||
-- Handle base captured event.
|
||||
if self.airbase then
|
||||
self:HandleEvent(EVENTS.BaseCaptured)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Stop OPSZONE FSM.
|
||||
@ -456,6 +499,9 @@ function OPSZONE:onafterStop(From, Event, To)
|
||||
-- Reinit the timer.
|
||||
self.timerStatus:Stop()
|
||||
|
||||
-- Unhandle events.
|
||||
self:UnHandleEvent(EVENTS.BaseCaptured)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -481,6 +527,9 @@ function OPSZONE:Status()
|
||||
-- Scanning zone.
|
||||
self:Scan()
|
||||
|
||||
-- Evaluate the scan result.
|
||||
self:EvaluateZone()
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -782,10 +831,14 @@ function OPSZONE:EvaluateZone()
|
||||
|
||||
if Nblu>0 then
|
||||
-- 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
|
||||
-- Neutral captured red zone.
|
||||
self:Captured(coalition.side.NEUTRAL)
|
||||
if not self.airbase then
|
||||
self:Captured(coalition.side.NEUTRAL)
|
||||
end
|
||||
else
|
||||
-- Red zone is now empty (but will remain red).
|
||||
if not self:IsEmpty() then
|
||||
@ -835,10 +888,14 @@ function OPSZONE:EvaluateZone()
|
||||
|
||||
if Nred>0 then
|
||||
-- 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
|
||||
-- Neutral captured blue zone.
|
||||
self:Captured(coalition.side.NEUTRAL)
|
||||
if not self.airbase then
|
||||
self:Captured(coalition.side.NEUTRAL)
|
||||
end
|
||||
else
|
||||
-- Blue zone is empty now.
|
||||
if not self:IsEmpty() then
|
||||
@ -896,10 +953,14 @@ function OPSZONE:EvaluateZone()
|
||||
self.isContested=true
|
||||
elseif Nred>0 then
|
||||
-- Red captured neutral zone.
|
||||
self:Captured(coalition.side.RED)
|
||||
if not self.airbase then
|
||||
self:Captured(coalition.side.RED)
|
||||
end
|
||||
elseif Nblu>0 then
|
||||
-- Blue captured neutral zone.
|
||||
self:Captured(coalition.side.BLUE)
|
||||
if not self.airbase then
|
||||
self:Captured(coalition.side.BLUE)
|
||||
end
|
||||
else
|
||||
-- Neutral zone is empty now.
|
||||
if not self:IsEmpty() then
|
||||
@ -947,7 +1008,7 @@ function OPSZONE:OnEventHit(EventData)
|
||||
|
||||
end
|
||||
|
||||
--- Monitor hit events.
|
||||
--- Monitor base captured events.
|
||||
-- @param #OPSZONE self
|
||||
-- @param Core.Event#EVENTDATA EventData The event data.
|
||||
function OPSZONE:OnEventBaseCaptured(EventData)
|
||||
@ -960,6 +1021,17 @@ function OPSZONE:OnEventBaseCaptured(EventData)
|
||||
-- Check that this airbase belongs or did belong to this warehouse.
|
||||
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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user