diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 4c27e75ee..30bb2f75e 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -134,17 +134,234 @@ function ARMYGROUP:New(group) ------------------------ --- Pseudo Functions --- ------------------------ - - --- Triggers the FSM event "Stop". Stops the ARMYGROUP and all its event handlers. + --- Triggers the FSM event "Cruise". + -- @function [parent=#ARMYGROUP] Cruise -- @param #ARMYGROUP self + -- @param #number Speed Speed in knots until next waypoint is reached. + -- @param #number Formation Formation. - --- Triggers the FSM event "Stop" after a delay. Stops the ARMYGROUP and all its event handlers. - -- @function [parent=#ARMYGROUP] __Stop + --- Triggers the FSM event "Cruise" after a delay. + -- @function [parent=#ARMYGROUP] __Cruise -- @param #ARMYGROUP self -- @param #number delay Delay in seconds. - - -- TODO: Add pseudo functions. + -- @param #number Speed Speed in knots until next waypoint is reached. + -- @param #number Formation Formation. + --- On after "Cruise" event. + -- @function [parent=#ARMYGROUP] OnAfterCruise + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + -- @param #number Speed Speed in knots until next waypoint is reached. + -- @param #number Formation Formation. + + + --- Triggers the FSM event "FullStop". + -- @function [parent=#ARMYGROUP] FullStop + -- @param #ARMYGROUP self + + --- Triggers the FSM event "FullStop" after a delay. + -- @function [parent=#ARMYGROUP] __FullStop + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "FullStop" event. + -- @function [parent=#ARMYGROUP] OnAfterFullStop + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "RTZ". + -- @function [parent=#ARMYGROUP] RTZ + -- @param #ARMYGROUP self + + --- Triggers the FSM event "RTZ" after a delay. + -- @function [parent=#ARMYGROUP] __RTZ + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "RTZ" event. + -- @function [parent=#ARMYGROUP] OnAfterRTZ + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Returned". + -- @function [parent=#ARMYGROUP] Returned + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Returned" after a delay. + -- @function [parent=#ARMYGROUP] __Returned + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Returned" event. + -- @function [parent=#ARMYGROUP] OnAfterReturned + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Detour". + -- @function [parent=#ARMYGROUP] Detour + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Detour" after a delay. + -- @function [parent=#ARMYGROUP] __Detour + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Detour" event. + -- @function [parent=#ARMYGROUP] OnAfterDetour + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "DetourReached". + -- @function [parent=#ARMYGROUP] DetourReached + -- @param #ARMYGROUP self + + --- Triggers the FSM event "DetourReached" after a delay. + -- @function [parent=#ARMYGROUP] __DetourReached + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "DetourReached" event. + -- @function [parent=#ARMYGROUP] OnAfterDetourReached + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Retreat". + -- @function [parent=#ARMYGROUP] Retreat + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Retreat" after a delay. + -- @function [parent=#ARMYGROUP] __Retreat + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Retreat" event. + -- @function [parent=#ARMYGROUP] OnAfterRetreat + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Retreated". + -- @function [parent=#ARMYGROUP] Retreated + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Retreated" after a delay. + -- @function [parent=#ARMYGROUP] __Retreated + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Retreated" event. + -- @function [parent=#ARMYGROUP] OnAfterRetreated + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "EngageTarget". + -- @function [parent=#ARMYGROUP] EngageTarget + -- @param #ARMYGROUP self + + --- Triggers the FSM event "EngageTarget" after a delay. + -- @function [parent=#ARMYGROUP] __EngageTarget + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "EngageTarget" event. + -- @function [parent=#ARMYGROUP] OnAfterEngageTarget + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Disengage". + -- @function [parent=#ARMYGROUP] Disengage + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Disengage" after a delay. + -- @function [parent=#ARMYGROUP] __Disengage + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Disengage" event. + -- @function [parent=#ARMYGROUP] OnAfterDisengage + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Rearm". + -- @function [parent=#ARMYGROUP] Rearm + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Rearm" after a delay. + -- @function [parent=#ARMYGROUP] __Rearm + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Rearm" event. + -- @function [parent=#ARMYGROUP] OnAfterRearm + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Rearming". + -- @function [parent=#ARMYGROUP] Rearming + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Rearming" after a delay. + -- @function [parent=#ARMYGROUP] __Rearming + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Rearming" event. + -- @function [parent=#ARMYGROUP] OnAfterRearming + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Triggers the FSM event "Rearmed". + -- @function [parent=#ARMYGROUP] Rearmed + -- @param #ARMYGROUP self + + --- Triggers the FSM event "Rearmed" after a delay. + -- @function [parent=#ARMYGROUP] __Rearmed + -- @param #ARMYGROUP self + -- @param #number delay Delay in seconds. + + --- On after "Rearmed" event. + -- @function [parent=#ARMYGROUP] OnAfterRearmed + -- @param #ARMYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + -- TODO: Add pseudo functions. -- Init waypoints. self:_InitWaypoints() @@ -598,8 +815,10 @@ function ARMYGROUP:onafterSpawned(From, Event, To) -- Update route. if #self.waypoints>1 then + self:T(self.lid.."Got waypoints on spawn ==> Cruise in -0.1 sec!") self:__Cruise(-0.1, nil, self.option.Formation) else + self:T(self.lid.."No waypoints on spawn ==> Full Stop!") self:FullStop() end @@ -629,6 +848,8 @@ function ARMYGROUP:onbeforeUpdateRoute(From, Event, To, n, N, Speed, Formation) elseif self:IsStopped() then self:E(self.lid.."Update route denied. Group is STOPPED!") return false + elseif self:IsHolding() then + self:E(self.lid.."Update route denied. Group is holding position! Use Cruise()") end return true end @@ -724,10 +945,10 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation) -- Debug output. - if false then + if self.verbose>=5 then for i,_wp in pairs(waypoints) do local wp=_wp - local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or 0, wp.type, wp.speed, wp.alt, wp.action) + local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or -1, wp.type, wp.speed, wp.alt, wp.action) self:T(text) end end @@ -1376,7 +1597,8 @@ function ARMYGROUP:_InitGroup(Template) -- Add elemets. for _,unit in pairs(units) do - self:_AddElementByName(unit:GetName()) + local unitname=unit:GetName() + self:_AddElementByName(unitname) end diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index eb91f0b7a..10b1b7e2c 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -2255,11 +2255,11 @@ end --- Attach OPS transport to the mission. Mission assets will be transported before the mission is started at the OPSGROUP level. -- @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 #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`. +-- @param Core.Zone#ZONE DisembarkZone Zone where assets are disembarked to. -- @return #AUFTRAG self -function AUFTRAG:SetRequiredTransport(DeployZone, DisembarkZone, NcarriersMin, NcarriersMax) +function AUFTRAG:SetRequiredTransport(DeployZone, NcarriersMin, NcarriersMax, DisembarkZone) -- OPS transport from pickup to deploy zone. self.transportDeployZone=DeployZone diff --git a/Moose Development/Moose/Ops/Chief.lua b/Moose Development/Moose/Ops/Chief.lua index 20c82e8ad..1c723f44c 100644 --- a/Moose Development/Moose/Ops/Chief.lua +++ b/Moose Development/Moose/Ops/Chief.lua @@ -235,15 +235,15 @@ function CHIEF:New(Coalition, AgentSet, Alias) --- Triggers the FSM event "MissionAssign". -- @function [parent=#CHIEF] MissionAssign -- @param #CHIEF self - -- @param Ops.Legion#LEGION Legion The legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The Legion(s) to which the mission is assigned. --- Triggers the FSM event "MissionAssign" after a delay. -- @function [parent=#CHIEF] __MissionAssign -- @param #CHIEF self -- @param #number delay Delay in seconds. - -- @param Ops.Legion#LEGION Legion The legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The Legion(s) to which the mission is assigned. --- On after "MissionAssign" event. -- @function [parent=#CHIEF] OnAfterMissionAssign @@ -251,9 +251,8 @@ function CHIEF:New(Coalition, AgentSet, Alias) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. - -- @param Ops.Legion#LEGION Legion The legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. - + -- @param #table Legions The Legion(s) to which the mission is assigned. --- Triggers the FSM event "MissionCancel". -- @function [parent=#CHIEF] MissionCancel @@ -1183,15 +1182,15 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param Ops.Legion#LEGION Legion The legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. -function CHIEF:onafterMissionAssign(From, Event, To, Legion, Mission) + -- @param #table Legions The Legion(s) to which the mission is assigned. +function CHIEF:onafterMissionAssign(From, Event, To, Mission, Legions) if self.commander then self:I(self.lid..string.format("Assigning mission %s (%s) to COMMANDER", Mission.name, Mission.type)) Mission.chief=self Mission.statusChief=AUFTRAG.Status.QUEUED - self.commander:MissionAssign(Legion, Mission) + self.commander:MissionAssign(Mission, Legions) else self:E(self.lid..string.format("Mission cannot be assigned as no COMMANDER is defined!")) end @@ -1523,11 +1522,9 @@ function CHIEF:CheckTargetQueue() -- Mission parameters. mission.prio=target.prio mission.importance=target.importance - - -- Assign mission to legions. - for _,Legion in pairs(Legions) do - self:MissionAssign(Legion, mission) - end + + -- Assign mission to legions. + self:MissionAssign(mission, Legions) -- Only ONE target is assigned per check. return @@ -2054,10 +2051,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM mission.opstransport=transport -- Assign mission to legions. - for _,_legion in pairs(legions) do - local legion=_legion --Ops.Legion#LEGION - self:MissionAssign(legion, mission) - end + self:MissionAssign(mission, legions) -- Attach mission to ops zone. -- TODO: Need a better way! @@ -2078,10 +2072,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM end -- Assign mission to legions. - for _,_legion in pairs(legions) do - local legion=_legion --Ops.Legion#LEGION - self:MissionAssign(legion, mission) - end + self:MissionAssign(mission, legions) -- Attach mission to ops zone. -- TODO: Need a better way! diff --git a/Moose Development/Moose/Ops/Commander.lua b/Moose Development/Moose/Ops/Commander.lua index d3834fda3..1bae4aecf 100644 --- a/Moose Development/Moose/Ops/Commander.lua +++ b/Moose Development/Moose/Ops/Commander.lua @@ -1,4 +1,4 @@ ---- **Ops** - Commander of Airwings, Brigades and Flotillas. +--- **Ops** - Commander of Airwings, Brigades and Fleets. -- -- **Main Features:** -- @@ -36,8 +36,81 @@ -- -- # The COMMANDER Concept -- --- A commander is the head of legions. He/she will find the best LEGIONs to perform an assigned AUFTRAG (mission). +-- A commander is the head of legions. He/she will find the best LEGIONs to perform an assigned AUFTRAG (mission) or OPSTRANSPORT. +-- A legion can be an AIRWING, BRIGADE or FLEET. -- +-- # Constructor +-- +-- A new CHIEF object is created with the @{#CHIEF.New}(*Coalition, Alias*) function, where the parameter *Coalition* is the coalition side. +-- It can be `coalition.side.RED`, `coalition.side.BLUE` or `coalition.side.NEUTRAL`. This parameter is mandatory. +-- The second parameter *Alias* is optional and can be used to give the COMMANDER a "name", which is used for output in the dcs.log file. +-- +-- local myCommander=COMANDER:New(coalition.side.BLUE, "General Patton") +-- +-- # Adding Legions +-- +-- Legions, i.e. AIRWINGS, BRIGADES and FLEETS can be added via the @{#COMMANDER.AddLegion}(*Legion*) command: +-- +-- myCommander:AddLegion(myLegion) +-- +-- ## Adding Airwings +-- +-- It is also possible to use @{#COMMANDER.AddAirwing}(*myAirwing*) function. This does the same as the `AddLegion` function but might be a bit more intuitive. +-- +-- ## Adding Brigades +-- +-- It is also possible to use @{#COMMANDER.AddBrigade}(*myBrigade*) function. This does the same as the `AddLegion` function but might be a bit more intuitive. +-- +-- ## Adding Fleets +-- +-- It is also possible to use @{#COMMANDER.AddFleet}(*myFleet*) function. This does the same as the `AddLegion` function but might be a bit more intuitive. +-- +-- # Adding Missions +-- +-- Mission can be added via the @{#COMMANDER.AddMission}(*myMission*) function. +-- +-- # Adding OPS Transports +-- +-- Transportation assignments can be added via the @{#COMMANDER.AddOpsTransport}(*myTransport*) function. +-- +-- # Adding CAP Zones +-- +-- A CAP zone can be added via the @{#COMMANDER.AddCapZone}() function. +-- +-- # Adding Rearming Zones +-- +-- A rearming zone can be added via the @{#COMMANDER.AddRearmingZone}() function. +-- +-- # Adding Refuelling Zones +-- +-- A refuelling zone can be added via the @{#COMMANDER.AddRefuellingZone}() function. +-- +-- +-- # FSM Events +-- +-- The COMMANDER will +-- +-- # OPSGROUP on Mission +-- +-- Whenever an OPSGROUP (FLIGHTGROUP, ARMYGROUP or NAVYGROUP) is send on a mission, the `OnAfterOpsOnMission()` event is triggered. +-- Mission designers can hook into the event with the @{#COMMANDER.OnAfterOpsOnMission}() function +-- +-- function myCommander:OnAfterOpsOnMission(From, Event, To, OpsGroup, Mission) +-- -- Your code +-- end +-- +-- # Canceling a Mission +-- +-- A mission can be cancelled with the @{#COMMMANDER.MissionCancel}() function +-- +-- myCommander:MissionCancel(myMission) +-- +-- or +-- myCommander:__MissionCancel(5*60, myMission) +-- +-- The last commander cancels the mission after 5 minutes (300 seconds). +-- +-- The cancel command will be forwarded to all assigned legions and OPS groups, which will abort their mission or remove it from their queue. -- -- @field #COMMANDER COMMANDER = { @@ -62,8 +135,8 @@ COMMANDER.version="0.1.0" -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO: Add CAP zones. --- TODO: Add tanker zones. +-- DONE: Add CAP zones. +-- DONE: Add tanker zones. -- DONE: Improve legion selection. Mostly done! -- DONE: Find solution for missions, which require a transport. This is not as easy as it sounds since the selected mission assets restrict the possible transport assets. -- DONE: Add ops transports. @@ -83,11 +156,28 @@ function COMMANDER:New(Coalition, Alias) -- Inherit everything from INTEL class. local self=BASE:Inherit(self, FSM:New()) --#COMMANDER + + if Coalition==nil then + env.error("ERROR: Coalition parameter is nil in COMMANDER:New() call!") + return nil + end -- Set coaliton. self.coalition=Coalition + -- Alias name. - self.alias=Alias or string.format("John Doe") + self.alias=Alias + + -- Choose a name for red or blue. + if self.alias==nil then + if Coalition==coalition.side.BLUE then + self.alias="George S. Patton" + elseif Coalition==coalition.side.RED then + self.alias="Georgy Zhukov" + elseif Coalition==coalition.side.NEUTRAL then + self.alias="Mahatma Gandhi" + end + end -- Log ID. self.lid=string.format("COMMANDER %s [%s] | ", self.alias, UTILS.GetCoalitionName(self.coalition)) @@ -145,15 +235,15 @@ function COMMANDER:New(Coalition, Alias) --- Triggers the FSM event "MissionAssign". Mission is added to a LEGION mission queue and already requested. Needs assets to be added to the mission! -- @function [parent=#COMMANDER] MissionAssign -- @param #COMMANDER self - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The Legion(s) to which the mission is assigned. --- Triggers the FSM event "MissionAssign" after a delay. Mission is added to a LEGION mission queue and already requested. Needs assets to be added to the mission! -- @function [parent=#COMMANDER] __MissionAssign -- @param #COMMANDER self -- @param #number delay Delay in seconds. - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The Legion(s) to which the mission is assigned. --- On after "MissionAssign" event. -- @function [parent=#COMMANDER] OnAfterMissionAssign @@ -161,8 +251,8 @@ function COMMANDER:New(Coalition, Alias) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The Legion(s) to which the mission is assigned. --- Triggers the FSM event "MissionCancel". @@ -188,15 +278,15 @@ function COMMANDER:New(Coalition, Alias) --- Triggers the FSM event "TransportAssign". -- @function [parent=#COMMANDER] TransportAssign -- @param #COMMANDER self - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- Triggers the FSM event "TransportAssign" after a delay. -- @function [parent=#COMMANDER] __TransportAssign -- @param #COMMANDER self -- @param #number delay Delay in seconds. - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- On after "TransportAssign" event. -- @function [parent=#COMMANDER] OnAfterTransportAssign @@ -204,8 +294,8 @@ function COMMANDER:New(Coalition, Alias) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. - -- @param Ops.Legion#LEGION Legion The Legion. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- Triggers the FSM event "TransportCancel". @@ -377,7 +467,7 @@ function COMMANDER:RemoveTransport(Transport) local transport=_transport --Ops.OpsTransport#OPSTRANSPORT if transport.uid==Transport.uid then - self:I(self.lid..string.format("Removing mission %s (%s) status=%s from queue", transport.uid, transport:GetState())) + self:I(self.lid..string.format("Removing transport UID=%d status=%s from queue", transport.uid, transport:GetState())) transport.commander=nil table.remove(self.transportqueue, i) break @@ -444,7 +534,7 @@ function COMMANDER:AddCapZone(Zone, Altitude, Speed, Heading, Leg) table.insert(self.capZones, patrolzone) - return awacszone + return patrolzone end --- Add an AWACS zone. @@ -496,7 +586,7 @@ function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSyst table.insert(self.tankerZones, tankerzone) - return awacszone + return tankerzone end --- Check if this mission is already in the queue. @@ -762,24 +852,29 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param Ops.Legion#LEGION Legion The LEGION. -- @param Ops.Auftrag#AUFTRAG Mission The mission. -function COMMANDER:onafterMissionAssign(From, Event, To, Legion, Mission) - - -- Debug info. - self:I(self.lid..string.format("Assigning mission %s (%s) to legion %s", Mission.name, Mission.type, Legion.alias)) +-- @param #table Legions The Legion(s) to which the mission is assigned. +function COMMANDER:onafterMissionAssign(From, Event, To, Mission, Legions) -- Add mission to queue. self:AddMission(Mission) -- Set mission commander status to QUEUED as it is now queued at a legion. Mission.statusCommander=AUFTRAG.Status.QUEUED - - -- Add mission to legion. - Legion:AddMission(Mission) - - -- Directly request the mission as the assets have already been selected. - Legion:MissionRequest(Mission) + + for _,_Legion in pairs(Legions) do + local Legion=_Legion --Ops.Legion#LEGION + + -- Debug info. + self:I(self.lid..string.format("Assigning mission \"%s\" [%s] to legion \"%s\"", Mission.name, Mission.type, Legion.alias)) + + -- Add mission to legion. + Legion:AddMission(Mission) + + -- Directly request the mission as the assets have already been selected. + Legion:MissionRequest(Mission) + + end end @@ -792,7 +887,7 @@ end function COMMANDER:onafterMissionCancel(From, Event, To, Mission) -- Debug info. - self:I(self.lid..string.format("Cancelling mission %s (%s) in status %s", Mission.name, Mission.type, Mission.status)) + self:I(self.lid..string.format("Cancelling mission \"%s\" [%s] in status %s", Mission.name, Mission.type, Mission.status)) -- Set commander status. Mission.statusCommander=AUFTRAG.Status.CANCELLED @@ -825,21 +920,26 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param Ops.Legion#LEGION Legion The LEGION. --- @param Ops.OpsTransport#OPSTRANSPORT -function COMMANDER:onafterTransportAssign(From, Event, To, Legion, Transport) - - -- Debug info. - self:I(self.lid..string.format("Assigning transport %d to legion %s", Transport.uid, Legion.alias)) +-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. +function COMMANDER:onafterTransportAssign(From, Event, To, Transport, Legions) -- Set mission commander status to QUEUED as it is now queued at a legion. Transport.statusCommander=OPSTRANSPORT.Status.QUEUED - -- Add mission to legion. - Legion:AddOpsTransport(Transport) + for _,_Legion in pairs(Legions) do + local Legion=_Legion --Ops.Legion#LEGION + + -- Debug info. + self:I(self.lid..string.format("Assigning transport UID=%d to legion \"%s\"", Transport.uid, Legion.alias)) - -- Directly request the mission as the assets have already been selected. - Legion:TransportRequest(Transport) + -- Add mission to legion. + Legion:AddOpsTransport(Transport) + + -- Directly request the mission as the assets have already been selected. + Legion:TransportRequest(Transport) + + end end @@ -889,7 +989,7 @@ end -- @param Ops.Auftrag#AUFTRAG Mission The requested mission. function COMMANDER:onafterOpsOnMission(From, Event, To, OpsGroup, Mission) -- Debug info. - self:T2(self.lid..string.format("Group %s on %s mission %s", OpsGroup:GetName(), Mission:GetType(), Mission:GetName())) + self:T2(self.lid..string.format("Group \"%s\" on mission \"%s\" [%s]", OpsGroup:GetName(), Mission:GetName(), Mission:GetType())) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -981,17 +1081,8 @@ function COMMANDER:CheckMissionQueue() -- 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 - - -- Debug message. - self:I(self.lid..string.format("Assigning mission %s [%s] to legion %s", mission:GetName(), mission:GetType(), legion.alias)) - - -- Add mission to legion. - self:MissionAssign(legion, mission) - - end + -- Add mission to legion. + self:MissionAssign(mission, legions) else -- Recruited assets but no requested escort available. Unrecruit assets! @@ -1188,16 +1279,7 @@ function COMMANDER:CheckTransportQueue() 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 + self:TransportAssign(transport, legions) -- Only ONE transport is assigned. return diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua index 372aad628..97c8e8a2f 100644 --- a/Moose Development/Moose/Ops/Legion.lua +++ b/Moose Development/Moose/Ops/Legion.lua @@ -125,15 +125,15 @@ function LEGION:New(WarehouseName, LegionName) --- Triggers the FSM event "MissionAssign". -- @function [parent=#LEGION] MissionAssign -- @param #LEGION self - -- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The legion(s) from which the mission assets are requested. --- Triggers the FSM event "MissionAssign" after a delay. -- @function [parent=#LEGION] __MissionAssign -- @param #LEGION self -- @param #number delay Delay in seconds. - -- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The legion(s) from which the mission assets are requested. --- On after "MissionAssign" event. -- @function [parent=#LEGION] OnAfterMissionAssign @@ -141,8 +141,8 @@ function LEGION:New(WarehouseName, LegionName) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. - -- @param Ops.Legion#LEGION Legion The legion from which the mission assets are requested. -- @param Ops.Auftrag#AUFTRAG Mission The mission. + -- @param #table Legions The legion(s) from which the mission assets are requested. --- Triggers the FSM event "MissionRequest". @@ -183,15 +183,15 @@ function LEGION:New(WarehouseName, LegionName) --- Triggers the FSM event "TransportAssign". -- @function [parent=#LEGION] TransportAssign -- @param #LEGION self - -- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- Triggers the FSM event "TransportAssign" after a delay. -- @function [parent=#LEGION] __TransportAssign -- @param #LEGION self -- @param #number delay Delay in seconds. - -- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- On after "TransportAssign" event. -- @function [parent=#LEGION] OnAfterTransportAssign @@ -199,8 +199,8 @@ function LEGION:New(WarehouseName, LegionName) -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. - -- @param Ops.Legion#LEGION Legion The legion from which the transport assets are requested. -- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. + -- @param #table Legions The legion(s) to which this transport is assigned. --- Triggers the FSM event "TransportRequest". @@ -617,18 +617,23 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param Ops.Legion#LEGION Legion The LEGION. -- @param Ops.Auftrag#AUFTRAG Mission The mission. -function LEGION:onafterMissionAssign(From, Event, To, Legion, Mission) +-- @param #table Legions The LEGIONs. +function LEGION:onafterMissionAssign(From, Event, To, Mission, Legions) + + for _,_Legion in pairs(Legions) do + local Legion=_Legion --Ops.Legion#LEGION - -- Debug info. - self:I(self.lid..string.format("Assigning mission %s (%s) to legion %s", Mission.name, Mission.type, Legion.alias)) - - -- Add mission to legion. - Legion:AddMission(Mission) - - -- Directly request the mission as the assets have already been selected. - Legion:MissionRequest(Mission) + -- Debug info. + self:I(self.lid..string.format("Assigning mission %s (%s) to legion %s", Mission.name, Mission.type, Legion.alias)) + + -- Add mission to legion. + Legion:AddMission(Mission) + + -- Directly request the mission as the assets have already been selected. + Legion:MissionRequest(Mission) + + end end @@ -749,18 +754,23 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param Ops.Legion#LEGION Legion The LEGION. --- @param Ops.OpsTransport#OPSTRANSPORT The transport. -function LEGION:onafterTransportAssign(From, Event, To, Legion, Transport) +-- @param Ops.OpsTransport#OPSTRANSPORT Transport The transport. +-- @param #table Legions The legion(s) to which the transport is assigned. +function LEGION:onafterTransportAssign(From, Event, To, Transport, Legions) - -- Debug info. - self:I(self.lid..string.format("Assigning transport %d to legion %s", Transport.uid, Legion.alias)) + for _,_Legion in pairs(Legions) do + local Legion=_Legion --Ops.Legion#LEGION + + -- Debug info. + self:I(self.lid..string.format("Assigning transport %d to legion %s", Transport.uid, Legion.alias)) + + -- Add mission to legion. + Legion:AddOpsTransport(Transport) - -- Add mission to legion. - Legion:AddOpsTransport(Transport) - - -- Directly request the mission as the assets have already been selected. - Legion:TransportRequest(Transport) + -- Directly request the mission as the assets have already been selected. + Legion:TransportRequest(Transport) + + end end @@ -2148,7 +2158,7 @@ function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax) end -- Assign mission to legion. - self:MissionAssign(legion, escort) + self:MissionAssign(escort, {legion}) end end @@ -2240,7 +2250,7 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca end -- Debug info. - env.info(string.format("FF Transport available with %d carrier assets", #CarrierAssets)) + self:T(self.lid..string.format("Transport available with %d carrier assets", #CarrierAssets)) -- Add cargo assets to transport. for _,_legion in pairs(CargoLegions) do @@ -2272,10 +2282,7 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca end -- Assign TRANSPORT to legions. This also sends the request for the assets. - for _,_legion in pairs(CarrierLegions) do - local legion=_legion --Ops.Legion#LEGION - self:TransportAssign(legion, Transport) - end + self:TransportAssign(Transport, CarrierLegions) -- Got transport. return true, Transport @@ -2393,15 +2400,15 @@ function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, Include table.sort(assets, optimize) -- Remove distance parameter. - --[[ - local text=string.format("Optimized %d assets for %s mission/transport (payload=%s):", #assets, MissionType, tostring(IncludePayload)) - for i,Asset in pairs(assets) do - local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem - text=text..string.format("\n%s %s: score=%d", asset.squadname, asset.spawngroupname, asset.score) - asset.score=nil + if LEGION.verbose>0 then + local text=string.format("Optimized %d assets for %s mission/transport (payload=%s):", #assets, MissionType, tostring(IncludePayload)) + for i,Asset in pairs(assets) do + local asset=Asset --Functional.Warehouse#WAREHOUSE.Assetitem + text=text..string.format("\n%s %s: score=%d", asset.squadname, asset.spawngroupname, asset.score) + asset.score=nil + end + env.info(text) end - env.info(text) - ]] end diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index 4b7d1139a..77adc930b 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -159,13 +159,38 @@ function NAVYGROUP:New(group) self:AddTransition("*", "CollisionWarning", "*") -- Collision warning. self:AddTransition("*", "ClearAhead", "*") -- Clear ahead. - self:AddTransition("*", "Dive", "*") -- Command a submarine to dive. - self:AddTransition("Diving", "Surface", "*") -- Command a submarine to go to the surface. + self:AddTransition("Cruising", "Dive", "Cruising") -- Command a submarine to dive. + self:AddTransition("Cruising", "Surface", "Cruising") -- Command a submarine to go to the surface. ------------------------ --- Pseudo Functions --- ------------------------ + --- Triggers the FSM event "Cruise". + -- @function [parent=#NAVYGROUP] Cruise + -- @param #NAVYGROUP self + -- @param #number Speed Speed in knots until next waypoint is reached. + + --- Triggers the FSM event "Cruise" after a delay. + -- @function [parent=#NAVYGROUP] __Cruise + -- @param #NAVYGROUP self + -- @param #number delay Delay in seconds. + -- @param #number Speed Speed in knots until next waypoint is reached. + + --- On after "Cruise" event. + -- @function [parent=#NAVYGROUP] OnAfterCruise + -- @param #NAVYGROUP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + -- @param #number Speed Speed in knots until next waypoint is reached. + + + + + + + --- Triggers the FSM event "TurnIntoWind". -- @function [parent=#NAVYGROUP] TurnIntoWind -- @param #NAVYGROUP self @@ -240,7 +265,6 @@ function NAVYGROUP:New(group) -- @param #NAVYGROUP.IntoWind IntoWindData Data table. - --- Triggers the FSM event "TurningStarted". -- @function [parent=#NAVYGROUP] TurningStarted -- @param #NAVYGROUP self diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 284c4d3bd..14f09e47e 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -2899,6 +2899,9 @@ function OPSGROUP:OnEventBirth(EventData) local element=self:GetElementByName(unitname) if element and element.status~=OPSGROUP.ElementStatus.SPAWNED then + + -- Debug info. + self:T(self.lid..string.format("EVENT: Element %s born ==> spawned", unitname)) -- Set element to spawned state. self:ElementSpawned(element) @@ -6113,7 +6116,6 @@ function OPSGROUP:_CheckCargoTransport() local Time=timer.getAbsTime() -- Cargo bay debug info. - -- Check cargo bay and declare cargo groups dead. if self.verbose>=1 then local text="" for _,_element in pairs(self.elements) do @@ -8046,10 +8048,15 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) -- Debug info. self:T(self.lid..string.format("Board with direct load to carrier %s", CarrierGroup:GetName())) - local mycarriergroup=self:_GetMyCarrierGroup() + -- Get current carrier group. + local mycarriergroup=self:_GetMyCarrierGroup() + if mycarriergroup then + self:T(self.lid..string.format("Current carrier group %s", mycarriergroup:GetName())) + end -- Unload cargo first. - if mycarriergroup then + if mycarriergroup and mycarriergroup:GetName()~=CarrierGroup:GetName() and self:IsLoaded() then + -- TODO: Unload triggers other stuff like Disembarked. This can be a problem! mycarriergroup:Unload(self) end @@ -8880,8 +8887,8 @@ function OPSGROUP:Route(waypoints, delay) airborne = self:IsFlightgroup(), route={points=waypoints}, }, - } - + } + -- Set mission task. self:SetTask(DCSTask) @@ -10813,11 +10820,20 @@ function OPSGROUP:_AddElementByName(unitname) --local unittemplate=_DATABASE:GetUnitTemplateFromUnitName(unitname) -- Element table. - local element={} --#OPSGROUP.Element + local element=self:GetElementByName(unitname) + + -- Add element to table. + if element then + -- We already know this element. + else + -- Add a new element. + element={} + element.status=OPSGROUP.ElementStatus.INUTERO + table.insert(self.elements, element) + end -- Name and status. element.name=unitname - element.status=OPSGROUP.ElementStatus.INUTERO -- Unit and group. element.unit=unit @@ -10904,11 +10920,6 @@ function OPSGROUP:_AddElementByName(unitname) element.size, element.length, element.height, element.width, element.weight, element.weightMaxTotal, element.weightCargo, element.weightMaxCargo) self:T(self.lid..text) - -- Add element to table. - if not self:_IsElement(unitname) then - table.insert(self.elements, element) - end - -- Trigger spawned event if alive. if unit:IsAlive() and element.status~=OPSGROUP.ElementStatus.SPAWNED then -- This needs to be slightly delayed (or moved elsewhere) or the first element will always trigger the group spawned event as it is not known that more elements are in the group. diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index e860d50a5..ec7f9ac44 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -38,8 +38,8 @@ -- @field #number duration Duration (`Tstop-Tstart`) of the transport in seconds. -- @field #table conditionStart Start conditions. -- --- @field #table cargos Cargos. Each element is a @{Ops.OpsGroup#OPSGROUP.CargoGroup}. -- @field #table carriers Carriers assigned for this transport. +-- @field #table carrierTransportStatus Status of each carrier. -- -- @field #table tzCombos Table of transport zone combos. Each element of the table is of type `#OPSTRANSPORT.TransportZoneCombo`. -- @field #number tzcCounter Running number of added transport zone combos. @@ -117,7 +117,6 @@ OPSTRANSPORT = { ClassName = "OPSTRANSPORT", verbose = 0, - cargos = {}, carriers = {}, carrierTransportStatus = {}, tzCombos = {}, @@ -152,7 +151,7 @@ OPSTRANSPORT.Status={ FAILED="failed", } ---- Pickup and deploy set. +--- Transport zone combination. -- @type OPSTRANSPORT.TransportZoneCombo -- @field #number uid Unique ID of the TZ combo. -- @field #number Ncarriers Number of carrier groups using this transport zone. @@ -233,7 +232,6 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) self:SetRequiredCarriers() -- Init arrays and counters. - self.cargos={} self.carriers={} self.Ncargo=0 self.Ncarrier=0 @@ -256,7 +254,7 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) self:AddTransition(OPSTRANSPORT.Status.SCHEDULED, "Executing", OPSTRANSPORT.Status.EXECUTING) -- Cargo is being transported. self:AddTransition("*", "Delivered", OPSTRANSPORT.Status.DELIVERED) -- Cargo was delivered. - self:AddTransition("*", "Status", "*") + self:AddTransition("*", "StatusUpdate", "*") self:AddTransition("*", "Stop", "*") self:AddTransition("*", "Cancel", OPSTRANSPORT.Status.CANCELLED) -- Command to cancel the transport. @@ -272,12 +270,12 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) --- Pseudo Functions --- ------------------------ - --- Triggers the FSM event "Status". - -- @function [parent=#OPSTRANSPORT] Status + --- Triggers the FSM event "StatusUpdate". + -- @function [parent=#OPSTRANSPORT] StatusUpdate -- @param #OPSTRANSPORT self --- Triggers the FSM event "Status" after a delay. - -- @function [parent=#OPSTRANSPORT] __Status + -- @function [parent=#OPSTRANSPORT] __StatusUpdate -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. @@ -291,6 +289,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Planned" event. + -- @function [parent=#OPSTRANSPORT] OnAfterPlanned + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Queued". -- @function [parent=#OPSTRANSPORT] Queued @@ -301,6 +306,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Queued" event. + -- @function [parent=#OPSTRANSPORT] OnAfterQueued + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Requested". -- @function [parent=#OPSTRANSPORT] Requested @@ -311,6 +323,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Requested" event. + -- @function [parent=#OPSTRANSPORT] OnAfterRequested + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Scheduled". -- @function [parent=#OPSTRANSPORT] Scheduled @@ -321,6 +340,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Scheduled" event. + -- @function [parent=#OPSTRANSPORT] OnAfterScheduled + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Executing". -- @function [parent=#OPSTRANSPORT] Executing @@ -331,6 +357,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Executing" event. + -- @function [parent=#OPSTRANSPORT] OnAfterExecuting + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Delivered". -- @function [parent=#OPSTRANSPORT] Delivered @@ -341,6 +374,13 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) -- @param #OPSTRANSPORT self -- @param #number delay Delay in seconds. + --- On after "Delivered" event. + -- @function [parent=#OPSTRANSPORT] OnAfterDelivered + -- @param #OPSTRANSPORT self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + --- Triggers the FSM event "Cancel". -- @function [parent=#OPSTRANSPORT] Cancel @@ -414,7 +454,7 @@ function OPSTRANSPORT:New(CargoGroups, PickupZone, DeployZone) --TODO: Psydofunctions -- Call status update. - self:__Status(-1) + self:__StatusUpdate(-1) return self end @@ -481,7 +521,7 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo) if cargo then -- Add to main table. - table.insert(self.cargos, cargo) + --table.insert(self.cargos, cargo) self.Ncargo=self.Ncargo+1 -- Add to TZC table. @@ -514,7 +554,7 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo) Weight=Weight+weight text=text..string.format("\n- %s [%s] weight=%.1f kg", cargo.opsgroup:GetName(), cargo.opsgroup:GetState(), weight) end - text=text..string.format("\nTOTAL: Ncargo=%d, Weight=%.1f kg", #self.cargos, Weight) + text=text..string.format("\nTOTAL: Ncargo=%d, Weight=%.1f kg", self.Ncargo, Weight) self:I(self.lid..text) end @@ -927,13 +967,8 @@ function OPSTRANSPORT:_DelCarrier(CarrierGroup) self:T(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) table.remove(self.carriers, i) end - end - - if #self.carriers==0 then - -- TODO: This call can be WRONG! - self:DeadCarrierAll() end - + end return self @@ -1557,12 +1592,12 @@ end -- Status Update ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- On after "Status" event. +--- On after "StatusUpdate" event. -- @param #OPSTRANSPORT self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -function OPSTRANSPORT:onafterStatus(From, Event, To) +function OPSTRANSPORT:onafterStatusUpdate(From, Event, To) -- Current FSM state. local fsmstate=self:GetState() @@ -1577,7 +1612,9 @@ function OPSTRANSPORT:onafterStatus(From, Event, To) for i,_tz in pairs(self.tzCombos) do local tz=_tz --#OPSTRANSPORT.TransportZoneCombo - text=text..string.format("\n[%d] %s --> %s", i, tz.PickupZone and tz.PickupZone:GetName() or "Unknown", tz.DeployZone and tz.DeployZone and tz.DeployZone:GetName() or "Unknown", tz.Ncarriers) + local pickupzone=tz.PickupZone and tz.PickupZone:GetName() or "Unknown" + local deployzone=tz.DeployZone and tz.DeployZone:GetName() or "Unknown" + text=text..string.format("\n[%d] %s --> %s: Ncarriers=%d, Ncargo=%d (%d)", i, pickupzone, deployzone, tz.Ncarriers, #tz.Cargos, tz.Ncargo) end end @@ -1613,7 +1650,7 @@ function OPSTRANSPORT:onafterStatus(From, Event, To) -- Update status again. if not self:IsDelivered() then - self:__Status(-30) + self:__StatusUpdate(-30) end end @@ -1671,9 +1708,9 @@ end function OPSTRANSPORT:onafterDelivered(From, Event, To) self:T(self.lid..string.format("New status: %s-->%s", From, To)) - -- Inform all assigned carriers that cargo was delivered. They can have this in the queue or are currently processing this transport. - for _,_carrier in pairs(self.carriers) do - local carrier=_carrier --Ops.OpsGroup#OPSGROUP + -- Inform all assigned carriers that cargo was delivered. They can have this in the queue or are currently processing this transport. + for i=#self.carriers, 1, -1 do + local carrier=self.carriers[i] --Ops.OpsGroup#OPSGROUP if self:GetCarrierTransportStatus(carrier)~=OPSTRANSPORT.Status.DELIVERED then carrier:Delivered(self) end @@ -1712,8 +1749,15 @@ end -- @param Ops.OpsGroup#OPSGROUP OpsGroup Carrier OPSGROUP that is dead. function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup) self:I(self.lid..string.format("Carrier OPSGROUP %s dead!", OpsGroup:GetName())) - -- Remove group from carrier list/table. - self.NdeadCarrier=self.NdeadCarrier+1 + + -- Increase dead counter. + self.NcarrierDead=self.NcarrierDead+1 + + if #self.carriers==0 then + self:DeadCarrierAll() + end + + -- Remove group from carrier list/table. self:_DelCarrier(OpsGroup) end @@ -1724,7 +1768,11 @@ end -- @param #string To To state. 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.")) + + -- Check if cargo was delivered. self:_CheckDelivered() + + -- Set state back to PLANNED if not delivered. if not self:IsDelivered() then self:Planned() end @@ -2064,9 +2112,16 @@ function OPSTRANSPORT:_GetTransportZoneCombo(Carrier) -- Get carrier position. local vec2=Carrier:GetVec2() + + --- Penalty function. + local function penalty(candidate) + local p=candidate.ncarriers*10-candidate.ncargo+candidate.distance/10 + return p + end + + -- TZC candidates. + local candidates={} - local pickup=nil --#OPSTRANSPORT.TransportZoneCombo - local distmin=nil for i,_transportzone in pairs(self.tzCombos) do local tz=_transportzone --#OPSTRANSPORT.TransportZoneCombo @@ -2078,31 +2133,58 @@ function OPSTRANSPORT:_GetTransportZoneCombo(Carrier) -- Count undelivered cargos in embark(!) zone that fit into the carrier. local ncargo=self:_CountCargosInZone(tz.EmbarkZone, false, Carrier, tz) - --env.info(string.format("FF GetPickupZone i=%d, ncargo=%d", i, ncargo)) - -- At least one group in the zone. if ncargo>=1 then -- Distance to the carrier in meters. local dist=tz.PickupZone:Get2DDistance(vec2) - - if distmin==nil or dist0 then + + -- Minimize penalty. + local function optTZC(candA, candB) + return candA.penalty=3 then + local text="TZC optimized" + for i,candidate in pairs(candidates) do + text=text..string.format("\n[%d] TPZ=%d, Ncarriers=%d, Ncargo=%d, Distance=%.1f km, PENALTY=%d", i, candidate.tzc.uid, candidate.ncarriers, candidate.ncargo, candidate.distance, candidate.penalty) + end + self:I(self.lid..text) + end + + -- Return best candidate. + return candidates[1].tzc else + -- No candidates. self:T(self.lid..string.format("Could NOT find a pickup zone (with cargo) for carrier group %s", Carrier:GetName())) - end + end - return pickup + return nil end --- Get an OPSGROUP from a given OPSGROUP or GROUP object. If the object is a GROUUP, an OPSGROUP is created automatically.