From d7dae1366db20bbbed4528138f77df4f7387726f Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 22 Sep 2021 19:27:33 +0200 Subject: [PATCH] OPS - Improved OPSTRANSPORT for LEGION assets. --- .../Moose/Functional/Warehouse.lua | 4 +- Moose Development/Moose/Ops/Auftrag.lua | 41 +-- Moose Development/Moose/Ops/Brigade.lua | 3 + Moose Development/Moose/Ops/Chief.lua | 261 ++++++++++++++++-- Moose Development/Moose/Ops/Cohort.lua | 4 + Moose Development/Moose/Ops/Commander.lua | 211 ++++++++++---- Moose Development/Moose/Ops/FlightGroup.lua | 5 +- Moose Development/Moose/Ops/Legion.lua | 60 +++- Moose Development/Moose/Ops/OpsGroup.lua | 29 +- Moose Development/Moose/Ops/OpsTransport.lua | 31 ++- Moose Development/Moose/Ops/OpsZone.lua | 140 ++++++++-- 11 files changed, 631 insertions(+), 158 deletions(-) diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index e67257aa5..77378e7fb 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -1867,6 +1867,7 @@ function WAREHOUSE:New(warehouse, alias) else self.isunit=true if warehouse:IsShip() then + env.info("FF warehouse is ship!") self.isShip=true end end @@ -1925,7 +1926,6 @@ function WAREHOUSE:New(warehouse, alias) self:SetMarker(true) self:SetReportOff() self:SetRunwayRepairtime() - --self:SetVerbosityLevel(0) -- Add warehouse to database. _WAREHOUSEDB.Warehouses[self.uid]=self @@ -5829,7 +5829,7 @@ function WAREHOUSE:_SpawnAssetGroundNaval(alias, asset, request, spawnzone, late -- Late activation. template.lateActivation=lateactivated - env.info("FF lateActivation="..tostring(template.lateActivation)) + --env.info("FF lateActivation="..tostring(template.lateActivation)) template.route.points[1].x = coord.x template.route.points[1].y = coord.z diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index e5e7182b7..853b0e9a2 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -1968,9 +1968,10 @@ end -- @param #AUFTRAG self -- @param Core.Zone#ZONE DeployZone Zone where assets are deployed. -- @param Core.Zone#ZONE DisembarkZone Zone where assets are disembarked to. --- @param Core.Set#SET_OPSGROUP Carriers Set of carriers. Can also be a single group. Can also be added via the AddTransportCarriers functions. +-- @param #number NcarriersMin Number of carriers *at least* required. Default 1. +-- @param #number NcarriersMax Number of carriers *at most* used for transportation. Default is same as `NcarriersMin`. -- @return #AUFTRAG self -function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, Carriers) +function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax) -- OPS transport from pickup to deploy zone. self.opstransport=OPSTRANSPORT:New(nil, nil, DeployZone) @@ -1978,8 +1979,20 @@ function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, Carriers) if DisembarkZone then self.opstransport:SetDisembarkZone(DisembarkZone) end - - if Carriers then + + -- Set required carriers. + self:SetRequiredCarriers(NcarriersMin, NcarriersMax) + + return self +end + +--- Add carriers for a transport of mission assets. +-- @param #AUFTRAG self +-- @param Core.Set#SET_OPSGROUP Carriers Set of carriers. Can also be a single group. +-- @return #AUFTRAG self +function AUFTRAG:AddTransportCarriers(Carriers) + + if self.opstransport then if Carriers:IsInstanceOf("SET_OPSGROUP") then for _,_carrier in pairs(Carriers.Set) do @@ -1992,12 +2005,7 @@ function AUFTRAG:SetTransportForAssets(DeployZone, DisembarkZone, Carriers) end end - - -- Set min/max number of carriers to be assigned. - self.opstransport.nCarriersMin=self.nCarriersMin - self.opstransport.nCarriersMax=self.nCarriersMax - - return self + end --- Set number of required carrier groups if an OPSTRANSPORT assignment is required. @@ -2347,9 +2355,11 @@ function AUFTRAG:AddOpsGroup(OpsGroup) if self.opstransport then for _,_tzc in pairs(self.opstransport.tzCombos) do local tzc=_tzc --Ops.OpsTransport#OPSTRANSPORT.TransportZoneCombo - if tzc.uid~=self.opstransport.tzcDefault.uid then + + if tzc.assetsCargo and tzc.assetsCargo[OpsGroup:GetName()] then self.opstransport:AddCargoGroups(OpsGroup, tzc) end + end end @@ -2544,15 +2554,6 @@ function AUFTRAG:IsReadyToGo() return false end - -- Ops transport at - if self.opstransport then - if #self.legions>0 then - end - if self.opstransport:IsPlanned() or self.opstransport:IsQueued() or self.opstransport:IsRequested() then - --return false - end - end - -- All start conditions true? local startme=self:EvalConditionsAll(self.conditionStart) diff --git a/Moose Development/Moose/Ops/Brigade.lua b/Moose Development/Moose/Ops/Brigade.lua index be89ff9eb..5210a85c2 100644 --- a/Moose Development/Moose/Ops/Brigade.lua +++ b/Moose Development/Moose/Ops/Brigade.lua @@ -52,6 +52,9 @@ BRIGADE.version="0.1.0" -- ToDo list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO: Spawn when hosting warehouse is a ship or oil rig or gas platform. +-- TODO: Rearming zones. +-- TODO: Retreat zones. -- DONE: Add weapon range. ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Ops/Chief.lua b/Moose Development/Moose/Ops/Chief.lua index d1019de85..82ed4cdac 100644 --- a/Moose Development/Moose/Ops/Chief.lua +++ b/Moose Development/Moose/Ops/Chief.lua @@ -509,6 +509,23 @@ function CHIEF:AddStrateticZone(Zone) return self end +--- Add strategically important zone. +-- @param #CHIEF self +-- @param Ops.OpsZone#OPSZONE OpsZone OPS zone object. +-- @return #CHIEF self +function CHIEF:AddOpsZone(OpsZone) + + -- Start ops zone. + if OpsZone:IsStopped() then + OpsZone:Start() + end + + -- Add to table. + table.insert(self.zonequeue, OpsZone) + + return self +end + --- Set border zone set. -- @param #CHIEF self @@ -663,27 +680,7 @@ function CHIEF:onafterStatus(From, Event, To) self:AddTarget(Target) end - - --[[ - local redalert=true - if self.borderzoneset:Count()>0 then - redalert=inred - end - - if redalert and threat and not contact.target then - - -- Create a new TARGET of the contact group. - local Target=TARGET:New(contact.group) - - -- Set to contact. - contact.target=Target - - -- Add target to queue. - self:AddTarget(Target) - - end - ]] - + end --- @@ -706,6 +703,13 @@ function CHIEF:onafterStatus(From, Event, To) -- Check target queue and assign missions to new targets. self:CheckTargetQueue() + --- + -- Check Strategic Zone Queue + --- + + -- Check target queue and assign missions to new targets. + self:CheckOpsZoneQueue() + --- -- Info General --- @@ -771,7 +775,24 @@ function CHIEF:onafterStatus(From, Event, To) text=text..string.format("\n[%d] %s (%s): status=%s, target=%s", i, mission.name, mission.type, mission.status, target) end self:I(self.lid..text) - end + end + + --- + -- Info Strategic Zones + --- + + -- Loop over targets. + if self.verbose>=4 and #self.zonequeue>0 then + local text="Zone queue:" + 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) + + end + self:I(self.lid..text) + end + --- -- Info Assets @@ -1111,6 +1132,63 @@ function CHIEF:CheckTargetQueue() end +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Strategic Zone Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + + +--- Check strategic zone queue. +-- @param #CHIEF self +function CHIEF:CheckOpsZoneQueue() + + -- Number of zones. + local Nzones=#self.zonequeue + + -- Treat special cases. + if Nzones==0 then + return nil + end + + -- Sort results table wrt ?. + local function _sort(a, b) + local taskA=a --Ops.Target#TARGET + local taskB=b --Ops.Target#TARGET + return (taskA.prioweightGroup then + weightGroup=weight + end + end + + env.info(string.format("FF mission requires transport for cargo weight %d", weightGroup)) + + -- Recruit transport assets. + local TransportAvail, assetsTrans, legionsTrans=self:RecruitAssetsForTransport(mission.opstransport, weightGroup) + + if TransportAvail then + + env.info(string.format("FF Transport available with %d carrier assets", #assetsTrans)) + + -- Add cargo assets to transport. + for _,_legion in pairs(legions) do + local legion=_legion --Ops.Legion#LEGION + + local pickupzone=legion.spawnzone + if legion.airbase and legion:IsRunwayOperational() then + pickupzone=ZONE_AIRBASE:New(legion.airbasename, 4000) + end + + -- Add TZC from legion spawn zone to deploy zone. + local tpz=mission.opstransport:AddTransportZoneCombo(pickupzone, mission.opstransport:GetDeployZone()) + mission.opstransport:SetEmbarkZone(legion.spawnzone, tpz) + + -- Add cargo assets to transport. + for _,_asset in pairs(assets) do + local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem + if asset.legion.alias==legion.alias then + mission.opstransport:AddAssetCargo(asset, tpz) + end + end + end + + -- Add carrier assets. + for _,_asset in pairs(assetsTrans) do + local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem + mission.opstransport:AddAsset(asset) + end + + + -- Assign TRANSPORT to legions. This also sends the request for the assets. + for _,_legion in pairs(legionsTrans) do + local legion=_legion --Ops.Legion#LEGION + self:TransportAssign(legion, mission.opstransport) + end + + else + -- Uncrecruit transport assets. + LEGION.UnRecruitAssets(assetsTrans) + end + + end + + end + + -- Escort and transport must be available (or not required). + if EscortAvail and TransportAvail then + -- Assign mission to legion(s). for _,_legion in pairs(legions) do local legion=_legion --Ops.Legion#LEGION @@ -741,11 +820,14 @@ end -- @return #table Legions that have recruited assets. function COMMANDER:RecruitAssetsForMission(Mission) + -- Debug info. + env.info(string.format("FF recruiting assets for mission %s [%s]", Mission:GetName(), Mission:GetType())) + -- Cohorts. local Cohorts=Mission.squadrons if not Cohorts then Cohorts={} - for _,_legion in pairs(Mission.mylegions or self.legions) do + for _,_legion in pairs(Mission.specialLegions or self.legions) do local legion=_legion --Ops.Legion#LEGION -- Loops over cohorts. for _,_cohort in pairs(legion.cohorts) do @@ -781,7 +863,7 @@ function COMMANDER:RecruitAssetsForEscort(Mission, Assets) local Cohorts=Mission.squadrons if not Cohorts then Cohorts={} - for _,_legion in pairs(Mission.mylegions or self.legions) do + for _,_legion in pairs(Mission.specialLegions or self.legions) do local legion=_legion --Ops.Legion#LEGION -- Loops over cohorts. for _,_cohort in pairs(legion.cohorts) do @@ -917,33 +999,56 @@ function COMMANDER:CheckTransportQueue() -- 1. Select best assets from legions -- 2. Assign mission to legions that have the best assets. --- - - -- Recruite assets from legions. - local recruited, assets, legions=self:RecruitAssetsForTransport(transport) - - if recruited then - - -- Add asset to transport. - for _,_asset in pairs(assets) do - local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem - asset.isReserved=true - transport:AddAsset(asset) - end - -- Assign transport to legion(s). - for _,_legion in pairs(legions) do - local legion=_legion --Ops.Legion#LEGION - - -- Debug message. - self:I(self.lid..string.format("Assigning transport UID=%d to legion %s", transport.uid, legion.alias)) + -- Get all undelivered cargo ops groups. + local cargoOpsGroups=transport:GetCargoOpsGroups(false) - -- Add mission to legion. - self:TransportAssign(legion, transport) - - end + -- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit! + local weightGroup=0 + + -- Calculate the max weight so we know which cohorts can provide carriers. + if #cargoOpsGroups>0 then + for _,_opsgroup in pairs(cargoOpsGroups) do + local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP + local weight=opsgroup:GetWeightTotal() + if weight>weightGroup then + weightGroup=weight + end + end + end + + if weightGroup>0 then - -- Only ONE transport is assigned. - return + -- Recruite assets from legions. + local recruited, assets, legions=self:RecruitAssetsForTransport(transport, weightGroup) + + if recruited then + + -- Add asset to transport. + for _,_asset in pairs(assets) do + local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem + transport:AddAsset(asset) + end + + -- Assign transport to legion(s). + for _,_legion in pairs(legions) do + local legion=_legion --Ops.Legion#LEGION + + -- Debug message. + self:I(self.lid..string.format("Assigning transport UID=%d to legion %s", transport.uid, legion.alias)) + + -- Add mission to legion. + self:TransportAssign(legion, transport) + + end + + -- Only ONE transport is assigned. + return + else + -- Not recruited. + LEGION.UnRecruitAssets(assets) + end + end else @@ -964,37 +1069,29 @@ end -- @return #boolean If `true`, enough assets could be recruited. -- @return #table Recruited assets. -- @return #table Legions that have recruited assets. -function COMMANDER:RecruitAssetsForTransport(Transport) - - -- Get all undelivered cargo ops groups. - local cargoOpsGroups=Transport:GetCargoOpsGroups(false) +function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight) - local weightGroup=0 - - -- At least one group should be spawned. - if #cargoOpsGroups>0 then - - -- Calculate the max weight so we know which cohorts can provide carriers. - for _,_opsgroup in pairs(cargoOpsGroups) do - local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP - local weight=opsgroup:GetWeightTotal() - if weight>weightGroup then - weightGroup=weight - end - end - else + if weightGroup==0 then -- No cargo groups! - return false + return false, {}, {} end -- Cohorts. local Cohorts={} for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - -- Loops over cohorts. - for _,_cohort in pairs(legion.cohorts) do - local cohort=_cohort --Ops.Cohort#COHORT - table.insert(Cohorts, cohort) + local legion=_legion --Ops.Legion#LEGION + + -- Check that runway is operational. + local Runway=legion:IsAirwing() and legion:IsRunwayOperational() or true + + if legion:IsRunning() and Runway then + + -- Loops over cohorts. + for _,_cohort in pairs(legion.cohorts) do + local cohort=_cohort --Ops.Cohort#COHORT + table.insert(Cohorts, cohort) + end + end end @@ -1006,7 +1103,7 @@ function COMMANDER:RecruitAssetsForTransport(Transport) local NreqMin,NreqMax=Transport:GetRequiredCarriers() -- Recruit assets and legions. - local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, weightGroup) + local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, CargoWeight) return recruited, assets, legions end diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 02ce12453..f9dc40ba8 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -1864,10 +1864,11 @@ function FLIGHTGROUP:onafterArrived(From, Event, To) self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.ARRIVED) end - local airwing=self:GetAirWing() + --TODO: Check that current base is airwing base. + local airwing=self:GetAirWing() --airwing:GetAirbaseName()==self.currbase:GetName() -- Check what to do. - if airwing then + if airwing and not (self:IsPickingup() or self:IsTransporting()) then -- Debug info. self:T(self.lid..string.format("Airwing asset group %s arrived ==> Adding asset back to stock of airwing %s", self.groupname, airwing.alias)) diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua index f42d19909..c9be9aa88 100644 --- a/Moose Development/Moose/Ops/Legion.lua +++ b/Moose Development/Moose/Ops/Legion.lua @@ -275,7 +275,7 @@ function LEGION:AddMission(Mission) end -- Add ops transport to transport Legions. - if Mission.opstransport then + if Mission.opstransport and false then local PickupZone=self.spawnzone local DeployZone=Mission.opstransport.tzcDefault.DeployZone @@ -622,7 +622,7 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) -- Cancel the current ALERT 5 mission. if currM and currM.type==AUFTRAG.Type.ALERT5 then - asset.flightgroup:MissionCancel(currM) + asset.flightgroup:MissionCancel(currM) end @@ -673,8 +673,8 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) if request then if self.isShip then - self:T(self.lid.."FF request late activated") - request.lateActivation=true + --self:T(self.lid.."FF request late activated") + --request.lateActivation=true end end @@ -1793,7 +1793,7 @@ end -- Recruiting and Optimization Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- Recruit assets from Cohorts for the given parameters. +--- Recruit assets from Cohorts for the given parameters. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else. -- @param #table Cohorts Cohorts included. -- @param #string MissionTypeRecruit Mission type for recruiting the cohort assets. -- @param #string MissionTypeOpt Mission type for which the assets are optimized. Default is the same as `MissionTypeRecruit`. @@ -1804,10 +1804,12 @@ end -- @param #number RangeMax Max range in meters. -- @param #number RefuelSystem Refuelsystem. -- @param #number CargoWeight Cargo weight for recruiting transport carriers. +-- @param #table Categories Group categories. +-- @param #table Attributes Group attributes. See `GROUP.Attribute.` -- @return #boolean If `true` enough assets could be recruited. --- @return #table Recruited assets. +-- @return #table Recruited assets. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else. -- @return #table Legions of recruited assets. -function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight) +function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, Categories, Attributes) -- The recruited assets. local Assets={} @@ -1815,10 +1817,39 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, -- Legions of recruited assets. local Legions={} + -- Set MissionTypeOpt to Recruit if nil. if MissionTypeOpt==nil then MissionTypeOpt=MissionTypeRecruit end + --- Function to check category. + local function CheckCategory(_cohort) + local cohort=_cohort --Ops.Cohort#COHORT + if Categories and #Categories>0 then + for _,category in pairs(Categories) do + if category==cohort.category then + return true + end + end + else + return true + end + end + + --- Function to check attribute. + local function CheckAttribute(_cohort) + local cohort=_cohort --Ops.Cohort#COHORT + if Attributes and #Attributes>0 then + for _,attribute in pairs(Attributes) do + if attribute==cohort.attribute then + return true + end + end + else + return true + end + end + -- Loops over cohorts. for _,_cohort in pairs(Cohorts) do local cohort=_cohort --Ops.Cohort#COHORT @@ -1838,9 +1869,19 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, -- Can carry the cargo? local CanCarry=CargoWeight and cohort.cargobayLimit>=CargoWeight or true - -- Check OnDuty, capable, in range and refueling type (if TANKER). - if cohort:IsOnDuty() and Capable and InRange and Refuel and CanCarry then + -- Right category. + local RightCategory=CheckCategory(cohort) + -- Right attribute. + 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:GetState(), tostring(Capable), tostring(InRange), tostring(Refuel), tostring(CanCarry), tostring(RightCategory), tostring(RightAttribute))) + + -- Check OnDuty, capable, in range and refueling type (if TANKER). + if cohort:IsOnDuty() and Capable and InRange and Refuel and CanCarry and RightCategory and RightAttribute then + -- Recruit assets from cohort. local assets, npayloads=cohort:RecruitAssets(MissionTypeRecruit, 999) @@ -1893,6 +1934,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, -- Add assets to mission. for i=1,Nassets do local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem + asset.isReserved=true Legions[asset.legion.alias]=asset.legion end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index e5845c8cc..7c8f64225 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -3801,20 +3801,7 @@ function OPSGROUP:_GetNextMission() -- Look for first mission that is SCHEDULED. for _,_mission in pairs(self.missionqueue) do local mission=_mission --Ops.Auftrag#AUFTRAG - - -- Local transport. - local transport=true - if mission.opstransport then - local cargos=mission.opstransport:GetCargoOpsGroups(false) or {} - for _,_opsgroup in pairs(cargos) do - local opscargo=_opsgroup --Ops.OpsGroup#OPSGROUP - if opscargo.groupname==self.groupname then - transport=false - break - end - end - end - + -- TODO: One could think of opsgroup specific start conditions. A legion also checks if "ready" but it can be other criteria for the group to actually start the mission. -- Good example is the above transport. The legion should start the mission but the group should only start after the transport is finished. @@ -3826,12 +3813,24 @@ function OPSGROUP:_GetNextMission() isEscort=false end end + + -- Local transport. + local isTransport=true + if mission.opstransport then + local cargos=mission.opstransport:GetCargoOpsGroups(false) or {} + for _,_opsgroup in pairs(cargos) do + local opscargo=_opsgroup --Ops.OpsGroup#OPSGROUP + if opscargo.groupname==self.groupname then + isTransport=false + break + end + end + end -- Conditons to start. local isScheduled=mission:GetGroupStatus(self)==AUFTRAG.GroupStatus.SCHEDULED local isReadyToGo=(mission:IsReadyToGo() or self.legion) local isImportant=(mission.importance==nil or mission.importance<=vip) - local isTransport=transport -- Check necessary conditions. if isScheduled and isReadyToGo and isImportant and isTransport and isEscort then diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index 195debb81..8d5ece50d 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -168,6 +168,7 @@ OPSTRANSPORT.Status={ -- @field #table DisembarkCarriers Carriers where the cargo is directly disembarked to. -- @field #boolean disembarkActivation If true, troops are spawned in late activated state when disembarked from carrier. -- @field #boolean disembarkInUtero If true, troops are disembarked "in utero". +-- @field #boolean assets Cargo assets. --- Path used for pickup or transport. -- @type OPSTRANSPORT.Path @@ -1225,14 +1226,16 @@ end --- Add asset to transport. -- @param #OPSTRANSPORT self -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added. +-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. -- @return #OPSTRANSPORT self -function OPSTRANSPORT:AddAsset(Asset) +function OPSTRANSPORT:AddAsset(Asset, TransportZoneCombo) -- Debug info - self:T(self.lid..string.format("Adding asset \"%s\" to transport", tostring(Asset.spawngroupname))) + self:T(self.lid..string.format("Adding asset carrier \"%s\" to transport", tostring(Asset.spawngroupname))) -- Add asset to table. - self.assets=self.assets or {} + self.assets=self.assets or {} + table.insert(self.assets, Asset) return self @@ -1258,6 +1261,28 @@ function OPSTRANSPORT:DelAsset(Asset) return self end +--- Add cargo asset. +-- @param #OPSTRANSPORT self +-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added. +-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. +-- @return #OPSTRANSPORT self +function OPSTRANSPORT:AddAssetCargo(Asset, TransportZoneCombo) + + -- Debug info + self:T(self.lid..string.format("Adding asset cargo \"%s\" to transport and TZC=%s", tostring(Asset.spawngroupname), TransportZoneCombo and TransportZoneCombo.uid or "N/A")) + + -- Add asset to table. + self.assetsCargo=self.assetsCargo or {} + + table.insert(self.assetsCargo, Asset) + + TransportZoneCombo.assetsCargo=TransportZoneCombo.assetsCargo or {} + + TransportZoneCombo.assetsCargo[Asset.spawngroupname]=Asset + + return self +end + --- Add LEGION to the transport. -- @param #OPSTRANSPORT self -- @param Ops.Legion#LEGION Legion The legion. diff --git a/Moose Development/Moose/Ops/OpsZone.lua b/Moose Development/Moose/Ops/OpsZone.lua index 1127954f8..140f9a688 100644 --- a/Moose Development/Moose/Ops/OpsZone.lua +++ b/Moose Development/Moose/Ops/OpsZone.lua @@ -2,7 +2,8 @@ -- -- **Main Features:** -- --- * Monitor if zone is captured. +-- * Monitor if a zone is captured. +-- * Monitor if an airbase is captured. -- -- === -- @@ -17,6 +18,8 @@ -- @field #string ClassName Name of the class. -- @field #number verbose Verbosity of output. -- @field Core.Zone#ZONE zone The zone. +-- @field Wrapper.Airbase#AIRBASE airbase The airbase that is monitored. +-- @field #string airbaseName Name of the airbase that is monitored. -- @field #string zoneName Name of the zone. -- @field #number zoneRadius Radius of the zone in meters. -- @field #number ownerCurrent Coalition of the current owner of the zone. @@ -30,7 +33,7 @@ -- @field #number Tattacked Abs. mission time stamp when an attack was started. -- @field #number dTCapture Time interval in seconds until a zone is captured. -- @field #boolean neutralCanCapture Neutral units can capture. Default `false`. --- @field #drawZone If `true`, draw the zone on the F10 map. +-- @field #boolean drawZone If `true`, draw the zone on the F10 map. -- @extends Core.Fsm#FSM --- Be surprised! @@ -63,6 +66,7 @@ OPSZONE.version="0.1.0" -- ToDo list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO: Capture airbases. -- TODO: Pause/unpause evaluations. -- TODO: Capture time, i.e. time how long a single coalition has to be inside the zone to capture it. -- TODO: Can neutrals capture? No, since they are _neutral_! @@ -113,17 +117,19 @@ function OPSZONE:New(Zone, CoalitionOwner) self:SetObjectCategories() self:SetUnitCategories() + self.drawZone=true + -- Status timer. self.timerStatus=TIMER:New(OPSZONE.Status, self) -- FMS start state is EMPTY. - self:SetStartState("Empty") + self:SetStartState("Stopped") -- Add FSM transitions. -- From State --> Event --> To State - self:AddTransition("*", "Start", "*") -- Start FSM. - self:AddTransition("*", "Stop", "*") -- Stop FSM. + self:AddTransition("Stopped", "Start", "Empty") -- Start FSM. + self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:AddTransition("*", "Captured", "Guarded") -- Zone was captured. self:AddTransition("*", "Empty", "Empty") -- No red or blue units inside the zone. @@ -372,9 +378,16 @@ function OPSZONE:IsContested() return self.isContested end +--- Check if FMS is stopped. +-- @param #OPSZONE self +-- @return #boolean If `true`, FSM is stopped +function OPSZONE:IsStopped() + local is=self:is("Stopped") + return is +end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Start/Stop and Status Functions +-- Start/Stop Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Start OPSZONE FSM. @@ -395,6 +408,25 @@ function OPSZONE:onafterStart(From, Event, To) end +--- Stop OPSZONE FSM. +-- @param #OPSZONE self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function OPSZONE:onafterStop(From, Event, To) + + -- Info. + self:I(self.lid..string.format("Stopping OPSZONE")) + + -- Reinit the timer. + self.timerStatus:Stop() + +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Status Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + --- Update status. -- @param #OPSZONE self function OPSZONE:Status() @@ -434,7 +466,7 @@ function OPSZONE:onafterCaptured(From, Event, To, NewOwnerCoalition) -- Set owners. self.ownerPrevious=self.ownerCurrent self.ownerCurrent=NewOwnerCoalition - + end --- On after "Empty" event. @@ -445,7 +477,7 @@ end function OPSZONE:onafterEmpty(From, Event, To) -- Debug info. - self:T(self.lid..string.format("Zone is empty now")) + self:T(self.lid..string.format("Zone is empty EVENT")) end @@ -462,19 +494,6 @@ function OPSZONE:onafterAttacked(From, Event, To, AttackerCoalition) end - ---- On after "Empty" event. --- @param #OPSZONE self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function OPSZONE:onafterEmpty(From, Event, To) - - -- Debug info. - self:T(self.lid..string.format("Zone is empty now")) - -end - --- On after "Defeated" event. -- @param #OPSZONE self -- @param #string From From state. @@ -504,6 +523,14 @@ function OPSZONE:onenterGuarded(From, Event, To) -- Not attacked any more. self.Tattacked=nil + if self.drawZone then + self.zone:UndrawZone() + + local color=self:_GetZoneColor() + + self.zone:DrawZone(nil, color, 1.0, color, 0.7) + end + end --- On enter "Guarded" state. @@ -519,6 +546,34 @@ function OPSZONE:onenterAttacked(From, Event, To) -- Time stamp when the attack started. self.Tattacked=timer.getAbsTime() + if self.drawZone then + self.zone:UndrawZone() + + local color={1,1,1} + + self.zone:DrawZone(nil, color, 1.0, color, 0.9) + end + +end + +--- On enter "Empty" event. +-- @param #OPSZONE self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function OPSZONE:onenterEmpty(From, Event, To) + + -- Debug info. + self:T(self.lid..string.format("Zone is empty now")) + + if self.drawZone then + self.zone:UndrawZone() + + local color=self:_GetZoneColor() + + self.zone:DrawZone(nil, color, 1.0, color, 0.2) + end + end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -837,6 +892,49 @@ function OPSZONE:OnEventHit(EventData) end +--- Monitor hit events. +-- @param #OPSZONE self +-- @param Core.Event#EVENTDATA EventData The event data. +function OPSZONE:OnEventBaseCaptured(EventData) + + if EventData and EventData.Place and self.airbase and self.airbaseName then + + -- Place is the airbase that was captured. + local airbase=EventData.Place --Wrapper.Airbase#AIRBASE + + -- Check that this airbase belongs or did belong to this warehouse. + if EventData.PlaceName==self.airbaseName then + + end + + end + +end + +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Misc Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Get RGB color of zone depending on current owner. +-- @param #OPSZONE self +-- @return #table RGB color. +function OPSZONE:_GetZoneColor() + + local color={0,0,0} + + if self.ownerCurrent==coalition.side.NEUTRAL then + color={0, 1, 0} + elseif self.ownerCurrent==coalition.side.BLUE then + color={1, 0, 0} + elseif self.ownerCurrent==coalition.side.RED then + color={0, 0, 1} + else + + end + + return color +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------