mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
OPS
CHIEF: SetResponseOnTarget TRANSPORT: improved transfer of loaded cargo
This commit is contained in:
parent
bcb574e618
commit
469cc3d508
@ -92,7 +92,15 @@ function BRIGADE:New(WarehouseName, BrigadeName)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "ArmyOnMission", "*") -- An ARMYGROUP was send on a Mission (AUFTRAG).
|
||||
|
||||
@ -256,6 +256,17 @@ CHIEF.Strategy = {
|
||||
-- @field #string MissionType Mission Type.
|
||||
-- @field #number Performance Performance: a number between 0 and 100, where 100 is best performance.
|
||||
|
||||
--- Asset numbers for detected targets.
|
||||
-- @type CHIEF.AssetNumber
|
||||
-- @field #number nAssetMin Min number of assets.
|
||||
-- @field #number nAssetMax Max number of assets.
|
||||
-- @field #number threatlevel Threat level.
|
||||
-- @field #string targetCategory Target category.
|
||||
-- @field #string missionType Mission type.
|
||||
-- @field #number nUnits Number of enemy units.
|
||||
-- @field #string defcon Defense condition.
|
||||
-- @field #string strategy Strategy.
|
||||
|
||||
--- Strategic zone.
|
||||
-- @type CHIEF.StrategicZone
|
||||
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
|
||||
@ -773,6 +784,153 @@ function CHIEF:DeleteFromResource(Resource, MissionType)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set number of assets requested for detected targets.
|
||||
-- @param #CHIEF self
|
||||
-- @param #number NassetsMin Min number of assets. Should be at least 1. Default 1.
|
||||
-- @param #number NassetsMax Max number of assets. Default is same as `NassetsMin`.
|
||||
-- @param #number ThreatLevel Only apply this setting if the target threat level is greater or equal this number. Default 0.
|
||||
-- @param #string TargetCategory Only apply this setting if the target is of this category, e.g. `TARGET.Category.AIRCRAFT`.
|
||||
-- @param #string MissionType Only apply this setting for this mission type, e.g. `AUFTRAG.Type.INTERCEPT`.
|
||||
-- @param #string Nunits Only apply this setting if the number of enemy units is greater or equal this number.
|
||||
-- @param #string Defcon Only apply this setting if this defense condition is in place.
|
||||
-- @param #string Strategy Only apply this setting if this strategy is in currently. place.
|
||||
-- @return #CHIEF self
|
||||
function CHIEF:SetResponseOnTarget(NassetsMin, NassetsMax, ThreatLevel, TargetCategory, MissionType, Nunits, Defcon, Strategy)
|
||||
|
||||
local bla={} --#CHIEF.AssetNumber
|
||||
|
||||
bla.nAssetMin=NassetsMin or 1
|
||||
bla.nAssetMax=NassetsMax or bla.nAssetMin
|
||||
bla.threatlevel=ThreatLevel or 0
|
||||
bla.targetCategory=TargetCategory
|
||||
bla.missionType=MissionType
|
||||
bla.nUnits=Nunits or 1
|
||||
bla.defcon=Defcon
|
||||
bla.strategy=Strategy
|
||||
|
||||
self.assetNumbers=self.assetNumbers or {}
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.assetNumbers, bla)
|
||||
|
||||
end
|
||||
|
||||
--- Add mission type and number of required assets to resource.
|
||||
-- @param #CHIEF self
|
||||
-- @param Ops.Target#TARGET Target The target.
|
||||
-- @param #string MissionType Mission type.
|
||||
-- @return #number Number of min assets.
|
||||
-- @return #number Number of max assets.
|
||||
function CHIEF:_GetAssetsForTarget(Target, MissionType)
|
||||
|
||||
-- Threat level.
|
||||
local threatlevel=Target:GetThreatLevelMax()
|
||||
|
||||
-- Number of units.
|
||||
local nUnits=Target.N0
|
||||
|
||||
-- Target category.
|
||||
local targetcategory=Target:GetCategory()
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Getting number of assets for target with TL=%d, Category=%s, nUnits=%s, MissionType=%s", threatlevel, targetcategory, nUnits, tostring(MissionType)))
|
||||
|
||||
-- Candidates.
|
||||
local candidates={}
|
||||
|
||||
local threatlevelMatch=nil
|
||||
for _,_assetnumber in pairs(self.assetNumbers or {}) do
|
||||
local assetnumber=_assetnumber --#CHIEF.AssetNumber
|
||||
|
||||
if (threatlevelMatch==nil and threatlevel>=assetnumber.threatlevel) or (threatlevelMatch~=nil and threatlevelMatch==threatlevel) then
|
||||
|
||||
if threatlevelMatch==nil then
|
||||
threatlevelMatch=threatlevel
|
||||
end
|
||||
|
||||
-- Number of other parameters matching.
|
||||
local nMatch=0
|
||||
|
||||
-- Assume cand.
|
||||
local cand=true
|
||||
|
||||
if assetnumber.targetCategory~=nil then
|
||||
if assetnumber.targetCategory==targetcategory then
|
||||
nMatch=nMatch+1
|
||||
else
|
||||
cand=false
|
||||
end
|
||||
end
|
||||
|
||||
if MissionType and assetnumber.missionType~=nil then
|
||||
if assetnumber.missionType==MissionType then
|
||||
nMatch=nMatch+1
|
||||
else
|
||||
cand=false
|
||||
end
|
||||
end
|
||||
|
||||
if assetnumber.nUnits~=nil then
|
||||
if assetnumber.nUnits>=nUnits then
|
||||
nMatch=nMatch+1
|
||||
else
|
||||
cand=false
|
||||
end
|
||||
end
|
||||
|
||||
if assetnumber.defcon~=nil then
|
||||
if assetnumber.defcon==self.Defcon then
|
||||
nMatch=nMatch+1
|
||||
else
|
||||
cand=false
|
||||
end
|
||||
end
|
||||
|
||||
if assetnumber.strategy~=nil then
|
||||
if assetnumber.strategy==self.strategy then
|
||||
nMatch=nMatch+1
|
||||
else
|
||||
cand=false
|
||||
end
|
||||
end
|
||||
|
||||
-- Add to candidates.
|
||||
if cand then
|
||||
table.insert(candidates, {assetnumber=assetnumber, nMatch=nMatch})
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if #candidates>0 then
|
||||
|
||||
-- Return greater match.
|
||||
local function _sort(a,b)
|
||||
return a.nMatch>b.nMatch
|
||||
end
|
||||
|
||||
-- Sort table by matches.
|
||||
table.sort(candidates, _sort)
|
||||
|
||||
-- Pick the candidate with most matches.
|
||||
local candidate=candidates[1]
|
||||
|
||||
-- Asset number.
|
||||
local an=candidate.assetnumber --#CHIEF.AssetNumber
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Picking candidate with %d matches: NassetsMin=%d, NassetsMax=%d, ThreatLevel=%d, TargetCategory=%s, MissionType=%s, Defcon=%s, Strategy=%s",
|
||||
candidate.nMatch, an.nAssetMin, an.nAssetMax, an.threatlevel, tostring(an.targetCategory), tostring(an.missionType), tostring(an.defcon), tostring(an.strategy)))
|
||||
|
||||
-- Return number of assetes.
|
||||
return an.nAssetMin, an.nAssetMax
|
||||
else
|
||||
return 1, 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Get defence condition.
|
||||
-- @param #CHIEF self
|
||||
-- @param #string Current Defence condition. See @{#CHIEF.DEFCON}, e.g. `CHIEF.DEFCON.RED`.
|
||||
@ -2084,24 +2242,6 @@ function CHIEF:CheckTargetQueue()
|
||||
local Legions=nil
|
||||
|
||||
if #MissionPerformances>0 then
|
||||
|
||||
--TODO: Number of required assets. How many do we want? Should depend on:
|
||||
-- * number of enemy units
|
||||
-- * target threatlevel
|
||||
-- * how many assets are still in stock
|
||||
-- * is it inside of our border
|
||||
-- * add damping factor
|
||||
|
||||
local NassetsMin=1
|
||||
local NassetsMax=1
|
||||
|
||||
if threatlevel>=8 and target.N0 >=10 then
|
||||
NassetsMax=3
|
||||
elseif threatlevel>=5 then
|
||||
NassetsMax=2
|
||||
else
|
||||
NassetsMax=1
|
||||
end
|
||||
|
||||
for _,_mp in pairs(MissionPerformances) do
|
||||
local mp=_mp --#CHIEF.MissionPerformance
|
||||
@ -2112,6 +2252,9 @@ function CHIEF:CheckTargetQueue()
|
||||
--env.info(string.format("FF chief %s nolimit=%s", mp.MissionType, tostring(NoLimit)))
|
||||
|
||||
if notlimited then
|
||||
|
||||
-- Get min/max number of assets.
|
||||
local NassetsMin, NassetsMax=self:_GetAssetsForTarget(target, mp.MissionType)
|
||||
|
||||
-- Debug info.
|
||||
self:T2(self.lid..string.format("Recruiting assets for mission type %s [performance=%d] of target %s", mp.MissionType, mp.Performance, target:GetName()))
|
||||
|
||||
@ -1084,7 +1084,7 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
||||
table.insert(assets, asset)
|
||||
end
|
||||
|
||||
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.ALERT5) and AUFTRAG.CheckMissionCapability(MissionType, asset.payload.capabilities) then
|
||||
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.ALERT5) and AUFTRAG.CheckMissionCapability(MissionType, asset.payload.capabilities) and MissionType~=AUFTRAG.Type.ALERT5 then
|
||||
|
||||
-- Check if the payload of this asset is compatible with the mission.
|
||||
self:T(self.lid..string.format("Adding asset on ALERT 5 mission for %s mission", MissionType))
|
||||
|
||||
@ -108,6 +108,15 @@ function FLEET:New(WarehouseName, FleetName)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
|
||||
@ -4322,12 +4322,14 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
||||
if player and player.status~=OPSGROUP.ElementStatus.DEAD then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Updating MENU: State=%s, ATC=%s [%s]", self:GetState(),
|
||||
self.flightcontrol and self.flightcontrol.airbasename or "None", self.flightcontrol and self.flightcontrol:GetFlightStatus(self) or "Unknown")
|
||||
|
||||
-- Message to group.
|
||||
MESSAGE:New(text, 5):ToGroup(self.group)
|
||||
self:I(self.lid..text)
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Updating MENU: State=%s, ATC=%s [%s]", self:GetState(),
|
||||
self.flightcontrol and self.flightcontrol.airbasename or "None", self.flightcontrol and self.flightcontrol:GetFlightStatus(self) or "Unknown")
|
||||
|
||||
-- Message to group.
|
||||
MESSAGE:New(text, 5):ToGroup(self.group)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Get current position of player.
|
||||
local position=self:GetCoordinate(nil, player.name)
|
||||
|
||||
@ -1191,6 +1191,12 @@ function LEGION:onafterOpsOnMission(From, Event, To, OpsGroup, Mission)
|
||||
self:NavyOnMission(OpsGroup, Mission)
|
||||
end
|
||||
|
||||
-- Load group as cargo because it cannot swim! We pause the mission.
|
||||
if self:IsBrigade() and self:IsShip() then
|
||||
OpsGroup:PauseMission()
|
||||
self.warehouseOpsGroup:Load(OpsGroup, self.warehouseOpsElement)
|
||||
end
|
||||
|
||||
-- Trigger event for chief.
|
||||
if self.chief then
|
||||
self.chief:OpsOnMission(OpsGroup, Mission)
|
||||
@ -2689,15 +2695,15 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca
|
||||
|
||||
-- Set pickup zone to spawn zone or airbase if the legion has one that is operational.
|
||||
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=Transport:AddTransportZoneCombo(nil, pickupzone, Transport:GetDeployZone())
|
||||
tpz.PickupAirbase=legion:IsRunwayOperational() and legion.airbase or nil
|
||||
Transport:SetEmbarkZone(legion.spawnzone, tpz)
|
||||
|
||||
-- Set pickup airbase if the legion has an airbase. Could also be the ship itself.
|
||||
tpz.PickupAirbase=legion:IsRunwayOperational() and legion.airbase or nil
|
||||
|
||||
-- Set embark zone to spawn zone.
|
||||
Transport:SetEmbarkZone(legion.spawnzone, tpz)
|
||||
|
||||
-- Add cargo assets to transport.
|
||||
for _,_asset in pairs(CargoAssets) do
|
||||
|
||||
@ -462,7 +462,7 @@ OPSGROUP.CarrierStatus={
|
||||
-- @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 ASSIGNED Cargo is assigned to a carrier. (Not used!)
|
||||
-- @field #string BOARDING Cargo is boarding a carrier.
|
||||
-- @field #string LOADED Cargo is loaded into a carrier.
|
||||
OPSGROUP.CargoStatus={
|
||||
@ -5397,6 +5397,12 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
self:T(self.lid..string.format("Route To Mission: I am DEAD or STOPPED! Ooops..."))
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if this group is cargo.
|
||||
if self:IsCargo() then
|
||||
self:T(self.lid..string.format("Route To Mission: I am CARGO! You cannot route me..."))
|
||||
return
|
||||
end
|
||||
|
||||
-- OPSTRANSPORT: Just add the ops transport to the queue.
|
||||
if mission.type==AUFTRAG.Type.OPSTRANSPORT then
|
||||
@ -8661,12 +8667,12 @@ function OPSGROUP:onafterLoading(From, Event, To)
|
||||
-- Check if cargo is not already cargo.
|
||||
local isNotCargo=cargo.opsgroup:IsNotCargo(true)
|
||||
|
||||
-- Check if cargo is holding.
|
||||
local isHolding=cargo.opsgroup:IsHolding()
|
||||
-- Check if cargo is holding or loaded
|
||||
local isHolding=cargo.opsgroup:IsHolding() or cargo.opsgroup:IsLoaded()
|
||||
|
||||
-- Check if cargo is in embark/pickup zone.
|
||||
-- Added InUtero here, if embark zone is moving (ship) and cargo has been spawned late activated and its position is not updated. Not sure if that breaks something else!
|
||||
local inZone=cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) --or cargo.opsgroup:IsInUtero()
|
||||
local inZone=cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) or cargo.opsgroup:IsInUtero()
|
||||
|
||||
-- Check if cargo is currently on a mission.
|
||||
local isOnMission=cargo.opsgroup:IsOnMission()
|
||||
@ -8675,9 +8681,13 @@ function OPSGROUP:onafterLoading(From, Event, To)
|
||||
if isOnMission then
|
||||
local mission=cargo.opsgroup:GetMissionCurrent()
|
||||
if mission and mission.opstransport and mission.opstransport.uid==self.cargoTransport.uid then
|
||||
isOnMission=not cargo.opsgroup:IsHolding()
|
||||
isOnMission=not isHolding
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Loading: canCargo=%s, isCarrier=%s, isNotCargo=%s, isHolding=%s, isOnMission=%s",
|
||||
tostring(canCargo), tostring(isCarrier), tostring(isNotCargo), tostring(isHolding), tostring(isOnMission)))
|
||||
|
||||
-- TODO: Need a better :IsBusy() function or :IsReadyForMission() :IsReadyForBoarding() :IsReadyForTransport()
|
||||
if canCargo and inZone and isNotCargo and isHolding and (not (cargo.delivered or cargo.opsgroup:IsDead() or isCarrier or isOnMission)) then
|
||||
@ -8701,10 +8711,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
|
||||
local carrier=self:FindCarrierForCargo(cargo.opsgroup)
|
||||
|
||||
if carrier then
|
||||
|
||||
-- Set cargo status.
|
||||
cargo.opsgroup:_NewCargoStatus(OPSGROUP.CargoStatus.ASSIGNED)
|
||||
|
||||
|
||||
-- Order cargo group to board the carrier.
|
||||
cargo.opsgroup:Board(self, carrier)
|
||||
|
||||
@ -9312,7 +9319,10 @@ function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
|
||||
OpsGroupCargo:Returned()
|
||||
end
|
||||
|
||||
if self:_CountPausedMissions()>0 then
|
||||
-- Check if there is a paused mission.
|
||||
local paused=OpsGroupCargo:_CountPausedMissions()>0
|
||||
|
||||
if paused then
|
||||
OpsGroupCargo:UnpauseMission()
|
||||
end
|
||||
|
||||
@ -9586,9 +9596,6 @@ end
|
||||
-- @param #OPSGROUP.Element Carrier The OPSGROUP element
|
||||
function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
|
||||
|
||||
-- Set cargo status.
|
||||
self:_NewCargoStatus(OPSGROUP.CargoStatus.BOARDING)
|
||||
|
||||
-- Army or Navy group.
|
||||
local CarrierIsArmyOrNavy=CarrierGroup:IsArmygroup() or CarrierGroup:IsNavygroup()
|
||||
local CargoIsArmyOrNavy=self:IsArmygroup() or self:IsNavygroup()
|
||||
@ -9605,7 +9612,21 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
|
||||
board=false
|
||||
end
|
||||
|
||||
if board then
|
||||
if self:IsLoaded() then
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Group is loaded currently ==> Moving directly to new carrier - No Unload(), Disembart() events triggered!"))
|
||||
|
||||
-- Remove my carrier.
|
||||
self:_RemoveMyCarrier()
|
||||
|
||||
-- Trigger Load event.
|
||||
CarrierGroup:Load(self)
|
||||
|
||||
elseif board then
|
||||
|
||||
-- Set cargo status.
|
||||
self:_NewCargoStatus(OPSGROUP.CargoStatus.BOARDING)
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Boarding group=%s [%s], carrier=%s", CarrierGroup:GetName(), CarrierGroup:GetState(), tostring(Carrier.name)))
|
||||
|
||||
@ -2171,7 +2171,7 @@ function OPSTRANSPORT:_GetTransportZoneCombo(Carrier)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get an OPSGROUP from a given OPSGROUP or GROUP object. If the object is a GROUUP, an OPSGROUP is created automatically.
|
||||
--- Get an OPSGROUP from a given OPSGROUP or GROUP object. If the object is a GROUP, an OPSGROUP is created automatically.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Core.Base#BASE Object The object, which can be a GROUP or OPSGROUP.
|
||||
-- @return Ops.OpsGroup#OPSGROUP Ops Group.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user