- Added new AUFTRAG type  CASENHANCED
- Improved capturing of OPSZONES by CHIEF
This commit is contained in:
Frank 2022-03-05 14:43:34 +01:00
parent f3d0d55a2f
commit 3557706e3a
7 changed files with 364 additions and 175 deletions

View File

@ -5452,6 +5452,55 @@ function WAREHOUSE:onafterAssetDead(From, Event, To, asset, request)
local text=string.format("Asset %s from request id=%d is dead!", asset.templatename, request.uid) local text=string.format("Asset %s from request id=%d is dead!", asset.templatename, request.uid)
self:T(self.lid..text) self:T(self.lid..text)
self:_DebugMessage(text) self:_DebugMessage(text)
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
local groupname=asset.spawngroupname --self:_GetNameWithOut(group)
-- Dont trigger a Remove event for the group sets.
local NoTriggerEvent=true
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
---
-- Easy case: Group can simply be removed from the cargogroupset.
---
-- Remove dead group from cargo group set.
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
else
---
-- Complicated case: Dead unit could be:
-- 1.) A Cargo unit (e.g. waiting to be picked up).
-- 2.) A Transport unit which itself holds cargo groups.
---
-- Check if this a cargo or transport group.
local istransport=not asset.iscargo --self:_GroupIsTransport(group, request)
if istransport==true then
-- Whole carrier group is dead. Remove it from the carrier group set.
request.transportgroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
elseif istransport==false then
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
-- Remove dead group from cargo group set.
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
-- This as well?
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
else
--self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName()))
end
end
end end
@ -6556,7 +6605,8 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
end end
end end
--self:I(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s.", self.alias, tostring(EventData.IniUnitName))) -- Debug info.
self:T2(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s", self.alias, tostring(EventData.IniUnitName)))
-- Check if an asset unit was destroyed. -- Check if an asset unit was destroyed.
if EventData.IniGroup then if EventData.IniGroup then
@ -6571,7 +6621,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
if wid==self.uid then if wid==self.uid then
-- Debug message. -- Debug message.
self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s.", self.alias, EventData.IniUnitName)) self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s", self.alias, EventData.IniUnitName))
-- Loop over all pending requests and get the one belonging to this unit. -- Loop over all pending requests and get the one belonging to this unit.
for _,request in pairs(self.pending) do for _,request in pairs(self.pending) do
@ -6581,7 +6631,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
if request.uid==rid then if request.uid==rid then
-- Update cargo and transport group sets of this request. We need to know if this job is finished. -- Update cargo and transport group sets of this request. We need to know if this job is finished.
self:_UnitDead(EventData.IniUnit, request) self:_UnitDead(EventData.IniUnit, EventData.IniGroup, request)
end end
end end
@ -6594,38 +6644,51 @@ end
-- This is important in order to determine if a job is done and can be removed from the (pending) queue. -- This is important in order to determine if a job is done and can be removed from the (pending) queue.
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Unit#UNIT deadunit Unit that died. -- @param Wrapper.Unit#UNIT deadunit Unit that died.
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated. -- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
function WAREHOUSE:_UnitDead(deadunit, request) function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
--env.info("FF unit dead "..deadunit:GetName())
-- Find asset.
local asset=self:FindAssetInDB(deadgroup)
-- Find opsgroup.
local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
local groupdead=false
if opsgroup then
if opsgroup:IsDead() then
groupdead=true
end
else
-- Number of alive units in group.
local nalive=deadgroup:CountAliveUnits()
-- Whole group is dead?
if nalive>0 then
groupdead=false
else
groupdead=true
end
-- Flare unit.
if self.Debug then
deadunit:FlareRed()
end end
-- Group the dead unit belongs to.
local group=deadunit:GetGroup()
-- Number of alive units in group.
local nalive=group:CountAliveUnits()
-- Whole group is dead?
local groupdead=true
if nalive>0 then
groupdead=false
end
-- Here I need to get rid of the #CARGO at the end to obtain the original name again! -- Here I need to get rid of the #CARGO at the end to obtain the original name again!
local unitname=self:_GetNameWithOut(deadunit) local unitname=self:_GetNameWithOut(deadunit)
local groupname=self:_GetNameWithOut(group) local groupname=self:_GetNameWithOut(deadgroup)
-- Group is dead! -- Group is dead!
if groupdead then if groupdead then
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(group,request)))) -- Debug output.
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(deadgroup,request))))
if self.Debug then if self.Debug then
group:SmokeWhite() deadgroup:SmokeWhite()
end end
-- Trigger AssetDead event. -- Trigger AssetDead event.
local asset=self:FindAssetInDB(group)
self:AssetDead(asset, request) self:AssetDead(asset, request)
end end
@ -6633,19 +6696,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
-- Dont trigger a Remove event for the group sets. -- Dont trigger a Remove event for the group sets.
local NoTriggerEvent=true local NoTriggerEvent=true
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then if not request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
---
-- Easy case: Group can simply be removed from the cargogroupset.
---
-- Remove dead group from cargo group set.
if groupdead==true then
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
end
else
--- ---
-- Complicated case: Dead unit could be: -- Complicated case: Dead unit could be:
@ -6653,10 +6704,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
-- 2.) A Transport unit which itself holds cargo groups. -- 2.) A Transport unit which itself holds cargo groups.
--- ---
-- Check if this a cargo or transport group. if not asset.iscargo then
local istransport=self:_GroupIsTransport(group,request)
if istransport==true then
-- Get the carrier unit table holding the cargo groups inside this carrier. -- Get the carrier unit table holding the cargo groups inside this carrier.
local cargogroupnames=request.carriercargo[unitname] local cargogroupnames=request.carriercargo[unitname]
@ -6671,25 +6719,8 @@ function WAREHOUSE:_UnitDead(deadunit, request)
end end
-- Whole carrier group is dead. Remove it from the carrier group set.
if groupdead then
request.transportgroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
end
elseif istransport==false then
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
-- Remove dead group from cargo group set.
if groupdead==true then
request.cargogroupset:Remove(groupname, NoTriggerEvent)
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
-- This as well?
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
end
else else
self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName())) self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", deadgroup:GetName()))
end end
end end
@ -8056,57 +8087,12 @@ end
-- @return #number Request ID. -- @return #number Request ID.
function WAREHOUSE:_GetIDsFromGroup(group) function WAREHOUSE:_GetIDsFromGroup(group)
---@param #string text The text to analyse.
local function analyse(text)
-- Get rid of #0001 tail from spawn.
local unspawned=UTILS.Split(text, "#")[1]
-- Split keywords.
local keywords=UTILS.Split(unspawned, "_")
local _wid=nil -- warehouse UID
local _aid=nil -- asset UID
local _rid=nil -- request UID
-- Loop over keys.
for _,keys in pairs(keywords) do
local str=UTILS.Split(keys, "-")
local key=str[1]
local val=str[2]
if key:find("WID") then
_wid=tonumber(val)
elseif key:find("AID") then
_aid=tonumber(val)
elseif key:find("RID") then
_rid=tonumber(val)
end
end
return _wid,_aid,_rid
end
if group then if group then
-- Group name -- Group name
local name=group:GetName() local groupname=group:GetName()
-- Get asset id from group name. local wid, aid, rid=self:_GetIDsFromGroupName(groupname)
local wid,aid,rid=analyse(name)
-- Get Asset.
local asset=self:GetAssetByID(aid)
-- Get warehouse and request id from asset table.
if asset then
wid=asset.wid
rid=asset.rid
end
-- Debug info
self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid return wid,aid,rid
else else
@ -8115,14 +8101,13 @@ function WAREHOUSE:_GetIDsFromGroup(group)
end end
--- Get warehouse id, asset id and request id from group name (alias). --- Get warehouse id, asset id and request id from group name (alias).
-- @param #WAREHOUSE self -- @param #WAREHOUSE self
-- @param Wrapper.Group#GROUP group The group from which the info is gathered. -- @param #string groupname Name of the group from which the info is gathered.
-- @return #number Warehouse ID. -- @return #number Warehouse ID.
-- @return #number Asset ID. -- @return #number Asset ID.
-- @return #number Request ID. -- @return #number Request ID.
function WAREHOUSE:_GetIDsFromGroupOLD(group) function WAREHOUSE:_GetIDsFromGroupName(groupname)
---@param #string text The text to analyse. ---@param #string text The text to analyse.
local function analyse(text) local function analyse(text)
@ -8153,25 +8138,26 @@ function WAREHOUSE:_GetIDsFromGroupOLD(group)
return _wid,_aid,_rid return _wid,_aid,_rid
end end
if group then
-- Group name -- Get asset id from group name.
local name=group:GetName() local wid,aid,rid=analyse(groupname)
-- Get ids -- Get Asset.
local wid,aid,rid=analyse(name) local asset=self:GetAssetByID(aid)
-- Debug info -- Get warehouse and request id from asset table.
self:T3(self.lid..string.format("Group Name = %s", tostring(name))) if asset then
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid))) wid=asset.wid
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid))) rid=asset.rid
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid
else
self:E("WARNING: Group not found in GetIDsFromGroup() function!")
end end
-- Debug info
self:T3(self.lid..string.format("Group Name = %s", tostring(groupname)))
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
return wid,aid,rid
end end
--- Filter stock assets by descriptor and attribute. --- Filter stock assets by descriptor and attribute.

View File

@ -384,6 +384,7 @@ _AUFTRAGSNR=0
-- @field #string ARMOREDGUARD On guard - with armored groups. -- @field #string ARMOREDGUARD On guard - with armored groups.
-- @field #string BARRAGE Barrage. -- @field #string BARRAGE Barrage.
-- @field #string ARMORATTACK Armor attack. -- @field #string ARMORATTACK Armor attack.
-- @field #string CASENHANCED Enhanced CAS.
AUFTRAG.Type={ AUFTRAG.Type={
ANTISHIP="Anti Ship", ANTISHIP="Anti Ship",
AWACS="AWACS", AWACS="AWACS",
@ -416,6 +417,7 @@ AUFTRAG.Type={
ARMOREDGUARD="Armored Guard", ARMOREDGUARD="Armored Guard",
BARRAGE="Barrage", BARRAGE="Barrage",
ARMORATTACK="Armor Attack", ARMORATTACK="Armor Attack",
CASENHANCED="CAS Enhanced",
} }
--- Mission status of an assigned group. --- Mission status of an assigned group.
@ -558,7 +560,7 @@ AUFTRAG.Category={
--- AUFTRAG class version. --- AUFTRAG class version.
-- @field #string version -- @field #string version
AUFTRAG.version="0.8.2" AUFTRAG.version="0.8.3"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -1187,6 +1189,45 @@ function AUFTRAG:NewCAS(ZoneCAS, Altitude, Speed, Coordinate, Heading, Leg, Targ
return mission return mission
end end
--- **[AIR]** Create a CASENHANCED mission. Group(s) will go to the zone and patrol it randomly.
-- @param #AUFTRAG self
-- @param Core.Zone#ZONE CasZone The CAS zone.
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
-- @param #number Speed Speed in knots.
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`.
-- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere.
-- @return #AUFTRAG self
function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZoneSet, TargetTypes)
local mission=AUFTRAG:New(AUFTRAG.Type.CASENHANCED)
-- Ensure we got a ZONE and not just the zone name.
if type(CasZone)=="string" then
CasZone=ZONE:New(CasZone)
end
mission:_TargetFromObject(CasZone)
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CASENHANCED)
mission:SetEngageDetected(RangeMax, TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"}, CasZone, NoEngageZoneSet)
mission.optionROE=ENUMS.ROE.OpenFire
mission.optionROT=ENUMS.ROT.EvadeFire
mission.missionFraction=1.0
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil
mission.categories={AUFTRAG.Category.AIRCRAFT}
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- **[AIR]** Create a FACA mission. --- **[AIR]** Create a FACA mission.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object. -- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object.
@ -1678,6 +1719,7 @@ function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
return mission return mission
end end
--- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack. --- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object. -- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object.
@ -4943,6 +4985,26 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
table.insert(DCStasks, DCStask) table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.CASENHANCED then
-------------------------
-- CAS ENHANCED Mission --
-------------------------
local DCStask={}
DCStask.id="PatrolZone"
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
local param={}
param.zone=self:GetObjective()
param.altitude=self.missionAltitude
param.speed=self.missionSpeed
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.ARMORATTACK then elseif self.type==AUFTRAG.Type.ARMORATTACK then
------------------------- -------------------------
@ -5131,6 +5193,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType)
mtask=ENUMS.MissionTask.CAS mtask=ENUMS.MissionTask.CAS
elseif MissionType==AUFTRAG.Type.PATROLZONE then elseif MissionType==AUFTRAG.Type.PATROLZONE then
mtask=ENUMS.MissionTask.CAS mtask=ENUMS.MissionTask.CAS
elseif MissionType==AUFTRAG.Type.CASENHANCED then
mtask=ENUMS.MissionTask.CAS
elseif MissionType==AUFTRAG.Type.ESCORT then elseif MissionType==AUFTRAG.Type.ESCORT then
mtask=ENUMS.MissionTask.ESCORT mtask=ENUMS.MissionTask.ESCORT
elseif MissionType==AUFTRAG.Type.FACA then elseif MissionType==AUFTRAG.Type.FACA then

View File

@ -103,7 +103,7 @@
-- --
-- Strategically important zones, which should be captured can be added via the @{#CHIEF.AddStrategicZone}() function. -- Strategically important zones, which should be captured can be added via the @{#CHIEF.AddStrategicZone}() function.
-- --
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS mission is lauchned. -- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS and an ARTY mission are lauchned, provided assets are available.
-- --
-- Once the zone is cleaned of enemy forces, ground (infantry) troops are send there. These require a transportation via helicopters. -- Once the zone is cleaned of enemy forces, ground (infantry) troops are send there. These require a transportation via helicopters.
-- So in order to deploy our own troops, infantry assets with `AUFTRAG.Type.ONGUARD` and helicopters with `AUFTRAG.Type.OPSTRANSPORT` need to be available. -- So in order to deploy our own troops, infantry assets with `AUFTRAG.Type.ONGUARD` and helicopters with `AUFTRAG.Type.OPSTRANSPORT` need to be available.
@ -1731,7 +1731,7 @@ function CHIEF:CheckOpsZoneQueue()
-- Has a patrol mission? -- Has a patrol mission?
local hasMissionPatrol=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ONGUARD) or stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARMOREDGUARD) local hasMissionPatrol=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ONGUARD) or stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARMOREDGUARD)
-- Has a CAS mission? -- Has a CAS mission?
local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS) local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
-- Has a ARTY mission? -- Has a ARTY mission?
local hasMissionARTY=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY) local hasMissionARTY=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
@ -1775,12 +1775,13 @@ function CHIEF:CheckOpsZoneQueue()
-- Recruite CAS assets. -- Recruite CAS assets.
local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CAS, 1, 1) local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CASENHANCED, 1, 1)
-- Debug message. -- Debug message.
self:T(self.lid..string.format("Zone is NOT empty ==> Recruit CAS assets=%s", tostring(recruited))) self:T(self.lid..string.format("Zone is NOT empty ==> Recruit CAS assets=%s", tostring(recruited)))
end end
if not hasMissionARTY then if not hasMissionARTY then
-- Debug message. -- Debug message.
@ -1811,7 +1812,7 @@ function CHIEF:CheckOpsZoneQueue()
local hasMissionPATROL=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.PATROLZONE) local hasMissionPATROL=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.PATROLZONE)
-- Has a CAS mission? -- Has a CAS mission?
local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS) local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
local hasMissionARTY, ARTYMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY) local hasMissionARTY, ARTYMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
if ownercoalition==self.coalition and stratzone.opszone:IsEmpty() and hasMissionCAS then if ownercoalition==self.coalition and stratzone.opszone:IsEmpty() and hasMissionCAS then
@ -2260,12 +2261,48 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM
-- Attach mission to ops zone. -- Attach mission to ops zone.
StratZone.opszone:_AddMission(self.coalition, MissionType, mission) StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
-- Set ops zone to transport.
transport.opszone=StratZone.opszone
transport.chief=self
transport.commander=self.commander
return true return true
else else
LEGION.UnRecruitAssets(assets) LEGION.UnRecruitAssets(assets)
return false return false
end end
elseif MissionType==AUFTRAG.Type.CASENHANCED then
-- Create Patrol zone mission.
local caszone = StratZone.opszone.zone
local coord = caszone:GetCoordinate()
local height = UTILS.MetersToFeet(coord:GetLandHeight())+2500
local Speed = 200
if assets[1] then
if assets[1].speedmax then
Speed = UTILS.KmphToKnots(assets[1].speedmax * 0.7) or 200
end
end
--local mission=AUFTRAG:NewCAS(caszone,height,Speed,coord,math.random(0,359),Leg)
local mission=AUFTRAG:NewCASENHANCED(caszone, height, Speed)
-- Add assets to mission.
for _,asset in pairs(assets) do
mission:AddAsset(asset)
end
-- Assign mission to legions.
self:MissionAssign(mission, legions)
-- Attach mission to ops zone.
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
return true
elseif MissionType==AUFTRAG.Type.CAS then elseif MissionType==AUFTRAG.Type.CAS then
-- Create Patrol zone mission. -- Create Patrol zone mission.

View File

@ -919,36 +919,38 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
-- ARMY/NAVYGROUP combat ready? -- ARMY/NAVYGROUP combat ready?
--- ---
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
--self:I("Attribute is: "..asset.attribute)
if flightgroup:IsArmygroup() then
-- check for fighting assets
if asset.attribute == WAREHOUSE.Attribute.GROUND_ARTILLERY or
asset.attribute == WAREHOUSE.Attribute.GROUND_TANK or
asset.attribute == WAREHOUSE.Attribute.GROUND_INFANTRY or
asset.attribute == WAREHOUSE.Attribute.GROUND_AAA or
asset.attribute == WAREHOUSE.Attribute.GROUND_SAM
then
combatready=true
end
else
combatready=false
end
-- Not ready when rearming, retreating or returning!
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
combatready=false combatready=false
end end
end end
-- Check transport/cargo for combat readyness! -- Not ready when currently acting as ops transport carrier.
if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then
combatready=false combatready=false
end end
-- Not ready when currently acting as ops transport cargo.
if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then
combatready=false combatready=false
end end
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
--self:I("Attribute is: "..asset.attribute)
if flightgroup:IsArmygroup() then
-- check for fighting assets
if asset.attribute == WAREHOUSE.Attribute.GROUND_ARTILLERY or
asset.attribute == WAREHOUSE.Attribute.GROUND_TANK or
asset.attribute == WAREHOUSE.Attribute.GROUND_INFANTRY or
asset.attribute == WAREHOUSE.Attribute.GROUND_AAA or
asset.attribute == WAREHOUSE.Attribute.GROUND_SAM
then
combatready=true
end
else
combatready=false
end
-- This asset is "combatready". -- This asset is "combatready".
if combatready then if combatready then
self:T(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY") self:T(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")

View File

@ -82,6 +82,10 @@ function LEGION:New(WarehouseName, LegionName)
-- TODO: What? -- TODO: What?
self:SetMarker(false) self:SetMarker(false)
-- Dead and crash events are handled via opsgroups.
self:UnHandleEvent(EVENTS.Crash)
self:UnHandleEvent(EVENTS.Dead)
-- Add FSM transitions. -- Add FSM transitions.
-- From State --> Event --> To State -- From State --> Event --> To State
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse. self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
@ -882,7 +886,18 @@ function LEGION:onafterTransportCancel(From, Event, To, Transport)
local cargos=Transport:GetCargoOpsGroups(false) local cargos=Transport:GetCargoOpsGroups(false)
for _,_cargo in pairs(cargos) do for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP local cargo=_cargo --Ops.OpsGroup#OPSGROUP
-- Remover my lift.
cargo:_DelMyLift(Transport) cargo:_DelMyLift(Transport)
-- Legion of cargo group
local legion=cargo.legion
-- Add asset back to legion.
if legion then
legion:T(self.lid..string.format("Adding cargo group %s back to legion", cargo:GetName()))
legion:__AddAsset(0.1, cargo.group, 1)
end
end end
-- Remove asset from mission. -- Remove asset from mission.
@ -993,7 +1008,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
-- Debug text. -- Debug text.
local text=string.format("New asset %s with assignment %s and request assignment %s", asset.spawngroupname, tostring(asset.assignment), tostring(assignment)) local text=string.format("New asset %s with assignment %s and request assignment %s", asset.spawngroupname, tostring(asset.assignment), tostring(assignment))
self:T3(self.lid..text) self:T(self.lid..text)
-- Get cohort. -- Get cohort.
local cohort=self:_GetCohort(asset.assignment) local cohort=self:_GetCohort(asset.assignment)
@ -1061,6 +1076,8 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
-- Asset is returned to the COHORT -- Asset is returned to the COHORT
--- ---
self:T(self.lid..string.format("Asset returned to legion ==> calling LegionAssetReturned event"))
-- Trigger event. -- Trigger event.
self:LegionAssetReturned(cohort, asset) self:LegionAssetReturned(cohort, asset)
@ -1078,7 +1095,7 @@ end
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned. -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset) function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
-- Debug message. -- Debug message.
self:T(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment))) self:I(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
-- Stop flightgroup. -- Stop flightgroup.
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
@ -2397,11 +2414,33 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
score=score-distance score=score-distance
-- Intercepts need to be carried out quickly. We prefer spawned assets. -- Intercepts need to be carried out quickly. We prefer spawned assets.
--if MissionType==AUFTRAG.Type.INTERCEPT then if asset.spawned and asset.flightgroup and asset.flightgroup:IsAlive() then
if asset.spawned then
score=score+25 local currmission=asset.flightgroup:GetMissionCurrent()
if currmission then
if currmission.type==AUFTRAG.Type.ALERT5 and currmission.alert5MissionType==MissionType then
-- Prefer assets that are on ALERT5 for this mission type.
score=score+25
elseif currmission==AUFTRAG.Type.GCICAP and MissionType==AUFTRAG.Type.INTERCEPT then
-- Prefer assets that are on GCICAP to perform INTERCEPTS
score=score+25
end
end end
--end
if MissionType==AUFTRAG.Type.OPSTRANSPORT or MissionType==AUFTRAG.Type.AMMOSUPPLY or MissionType==AUFTRAG.Type.AWACS or MissionType==AUFTRAG.Type.FUELSUPPLY or MissionType==AUFTRAG.Type.TANKER then
-- TODO: need to check for missions that do not require ammo like transport, recon, awacs, tanker etc.
-- We better take a fresh asset. Sometimes spawned assets to something else, which is difficult to check.
score=score-10
else
-- Combat mission.
if asset.flightgroup:IsOutOfAmmo() then
-- Assets that are out of ammo are not considered.
score=score-1000
end
end
end
-- TRANSPORT specific. -- TRANSPORT specific.
if MissionType==AUFTRAG.Type.OPSTRANSPORT then if MissionType==AUFTRAG.Type.OPSTRANSPORT then

View File

@ -3673,7 +3673,6 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- BARRAGE is special! -- BARRAGE is special!
if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
env.info("FF Barrage")
local vec2=self:GetVec2() local vec2=self:GetVec2()
local param=Task.dcstask.params local param=Task.dcstask.params
local heading=param.heading or math.random(1, 360) local heading=param.heading or math.random(1, 360)
@ -4230,7 +4229,7 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
-- IMMOBILE Group -- IMMOBILE Group
--- ---
env.info("FF Immobile GROUP") --env.info("FF Immobile GROUP")
-- Add waypoint task. UpdateRoute is called inside. -- Add waypoint task. UpdateRoute is called inside.
local Clock=Mission.Tpush and UTILS.SecondsToClock(Mission.Tpush) or 5 local Clock=Mission.Tpush and UTILS.SecondsToClock(Mission.Tpush) or 5
@ -5768,6 +5767,32 @@ function OPSGROUP:onafterElementInUtero(From, Event, To, Element)
end end
--- On after "ElementDamaged" event.
-- @param #OPSGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #OPSGROUP.Element Element The flight group element.
function OPSGROUP:onafterElementDamaged(From, Event, To, Element)
self:T(self.lid..string.format("Element damaged %s", Element.name))
if Element and Element.status~=OPSGROUP.ElementStatus.DEAD then
local lifepoints=Element.DCSunit:getLife()
local lifepoint0=Element.DCSunit:getLife0()
self:T(self.lid..string.format("Element life %s: %.2f/%.2f", Element.name, lifepoints, lifepoint0))
if lifepoints<=1.0 then
self:T(self.lid..string.format("Element %s life %.2f <= 1.0 ==> Destroyed!", Element.name, lifepoints))
self:ElementDestroyed(Element)
end
end
end
--- On after "ElementDestroyed" event. --- On after "ElementDestroyed" event.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #string From From state. -- @param #string From From state.
@ -5802,11 +5827,19 @@ end
function OPSGROUP:onafterElementDead(From, Event, To, Element) function OPSGROUP:onafterElementDead(From, Event, To, Element)
-- Debug info. -- Debug info.
self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime())) self:I(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
-- Set element status. -- Set element status.
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD) self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
if self.legion then
if not self:IsInUtero() then
local asset=self.legion:GetAssetByName(self.groupname)
local request=self.legion:GetRequestByID(asset.rid)
self.legion:_UnitDead(Element.unit, self.group, request)
end
end
-- Check if element was lasing and if so, switch to another unit alive to lase. -- Check if element was lasing and if so, switch to another unit alive to lase.
if self.spot.On and self.spot.element.name==Element.name then if self.spot.On and self.spot.element.name==Element.name then
@ -6140,12 +6173,18 @@ function OPSGROUP:onafterDead(From, Event, To)
-- All elements were destroyed ==> Asset group is gone. -- All elements were destroyed ==> Asset group is gone.
self.cohort:DelGroup(self.groupname) self.cohort:DelGroup(self.groupname)
end end
if self.legion then
--self.legion:Get
--self.legion:AssetDead()
end
else else
-- Not all assets were destroyed (despawn) ==> Add asset back to legion? -- Not all assets were destroyed (despawn) ==> Add asset back to legion?
end end
-- Stop in a sec. -- Stop in 5 sec to give possible respawn attempts a chance.
--self:__Stop(-5) if self.legion then
self:__Stop(-5)
end
end end
--- On before "Stop" event. --- On before "Stop" event.
@ -6188,6 +6227,11 @@ function OPSGROUP:onafterStop(From, Event, To)
self.currbase=nil self.currbase=nil
end end
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
self:MissionCancel(mission)
end
-- Stop check timers. -- Stop check timers.
self.timerCheckZone:Stop() self.timerCheckZone:Stop()
self.timerQueueUpdate:Stop() self.timerQueueUpdate:Stop()

View File

@ -57,6 +57,8 @@
-- @field #table statusLegion Transport status of all assigned LEGIONs. -- @field #table statusLegion Transport status of all assigned LEGIONs.
-- @field #string statusCommander Staus of the COMMANDER. -- @field #string statusCommander Staus of the COMMANDER.
-- @field Ops.Commander#COMMANDER commander Commander of the transport. -- @field Ops.Commander#COMMANDER commander Commander of the transport.
-- @field Ops.Chief#CHIEF chief Chief of the transport.
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed. -- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
-- --
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@ -1305,7 +1307,7 @@ function OPSTRANSPORT:GetNcarrier()
return self.Ncarrier return self.Ncarrier
end end
--- Add asset to transport. --- Add carrier asset to transport.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added. -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. -- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
@ -1323,7 +1325,7 @@ function OPSTRANSPORT:AddAsset(Asset, TransportZoneCombo)
return self return self
end end
--- Delete asset from mission. --- Delete carrier asset from transport.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed. -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed.
-- @return #OPSTRANSPORT self -- @return #OPSTRANSPORT self
@ -1736,12 +1738,12 @@ function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup)
-- Increase dead counter. -- Increase dead counter.
self.NcarrierDead=self.NcarrierDead+1 self.NcarrierDead=self.NcarrierDead+1
-- Remove group from carrier list/table.
self:_DelCarrier(OpsGroup)
if #self.carriers==0 then if #self.carriers==0 then
self:DeadCarrierAll() self:DeadCarrierAll()
end end
-- Remove group from carrier list/table.
self:_DelCarrier(OpsGroup)
end end
--- On after "DeadCarrierAll" event. --- On after "DeadCarrierAll" event.
@ -1750,15 +1752,30 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To) function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To)
self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead! Setting stage to PLANNED if not all cargo was delivered.")) self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead!"))
-- Check if cargo was delivered. if self.opszone then
self:_CheckDelivered()
self:I(self.lid..string.format("Cancelling transport on CHIEF level"))
self.chief:TransportCancel(self)
--for _,_legion in pairs(self.legions) do
-- local legion=_legion --Ops.Legion#LEGION
-- legion:TransportCancel(self)
--end
else
-- Check if cargo was delivered.
self:_CheckDelivered()
-- Set state back to PLANNED if not delivered.
if not self:IsDelivered() then
self:Planned()
end
-- Set state back to PLANNED if not delivered.
if not self:IsDelivered() then
self:Planned()
end end
end end
--- On after "Cancel" event. --- On after "Cancel" event.