From 268eb1d60dbcbc891d8b4e0b68099b1db53cadce Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 11 Jul 2021 18:15:25 +0200 Subject: [PATCH] OPS --- Moose Development/Moose/Core/Database.lua | 6 +- Moose Development/Moose/Core/Point.lua | 6 +- Moose Development/Moose/Core/Set.lua | 2 +- Moose Development/Moose/Ops/Airboss.lua | 2 +- Moose Development/Moose/Ops/ArmyGroup.lua | 15 +- Moose Development/Moose/Ops/FlightGroup.lua | 210 +++++++++++++++---- Moose Development/Moose/Ops/NavyGroup.lua | 9 +- Moose Development/Moose/Ops/OpsGroup.lua | 188 ++++++++++------- Moose Development/Moose/Ops/OpsTransport.lua | 77 +++++-- 9 files changed, 358 insertions(+), 157 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 6b19d7ae3..df836f7dd 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1478,7 +1478,7 @@ end -- @param #DATABASE self -- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group added to the DB. function DATABASE:AddOpsGroup(opsgroup) - env.info("Adding OPSGROUP "..tostring(opsgroup.groupname)) + --env.info("Adding OPSGROUP "..tostring(opsgroup.groupname)) self.FLIGHTGROUPS[opsgroup.groupname]=opsgroup end @@ -1494,7 +1494,7 @@ function DATABASE:GetOpsGroup(groupname) groupname=groupname:GetName() end - env.info("Getting OPSGROUP "..tostring(groupname)) + --env.info("Getting OPSGROUP "..tostring(groupname)) return self.FLIGHTGROUPS[groupname] end @@ -1510,7 +1510,7 @@ function DATABASE:FindOpsGroup(groupname) groupname=groupname:GetName() end - env.info("Getting OPSGROUP "..tostring(groupname)) + --env.info("Getting OPSGROUP "..tostring(groupname)) return self.FLIGHTGROUPS[groupname] end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index b78ade334..1c28e0730 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -647,7 +647,8 @@ do -- COORDINATE local y=X*math.sin(phi)+Y*math.cos(phi) -- Coordinate assignment looks bit strange but is correct. - return COORDINATE:NewFromVec3({x=y, y=self.y, z=x}) + local coord=COORDINATE:NewFromVec3({x=y, y=self.y, z=x}) + return coord end --- Return a random Vec2 within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE. @@ -690,7 +691,8 @@ do -- COORDINATE function COORDINATE:GetRandomCoordinateInRadius( OuterRadius, InnerRadius ) self:F2( { OuterRadius, InnerRadius } ) - return COORDINATE:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) ) + local coord=COORDINATE:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) ) + return coord end diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 7dfdfca49..c978d8f85 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -6112,7 +6112,7 @@ do -- SET_OPSGROUP -- @param Core.Base#BASE Object The object itself. -- @return Core.Base#BASE The added BASE Object. function SET_OPSGROUP:Add(ObjectName, Object) - self:I( { ObjectName = ObjectName, Object = Object } ) + self:T( { ObjectName = ObjectName, Object = Object } ) -- Ensure that the existing element is removed from the Set before a new one is inserted to the Set if self.Set[ObjectName] then diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 71a6087fe..3133cd715 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -6134,7 +6134,7 @@ function AIRBOSS:_ScanCarrierZone() local flight=_DATABASE:GetOpsGroup(groupname) if flight and flight:IsInbound() and flight.destbase:GetName()==self.carrier:GetName() then - if flight.ishelo then + if flight.isHelo then else putintomarshal=true end diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index f2953ede0..d8b506e64 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -38,7 +38,7 @@ -- @field Core.Set#SET_ZONE retreatZones Set of retreat zones. -- @extends Ops.OpsGroup#OPSGROUP ---- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B. Sledge +--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B Sledge -- -- === -- @@ -55,17 +55,6 @@ ARMYGROUP = { engage = {}, } ---- Army group element. --- @type ARMYGROUP.Element --- @field #string name Name of the element, i.e. the unit. --- @field Wrapper.Unit#UNIT unit The UNIT object. --- @field #string status The element status. --- @field #string typename Type name. --- @field #number length Length of element in meters. --- @field #number width Width of element in meters. --- @field #number height Height of element in meters. --- @extends Ops.OpsGroup#OPSGROUP.Element - --- Target -- @type ARMYGROUP.Target -- @field Ops.Target#TARGET Target The target. @@ -73,7 +62,7 @@ ARMYGROUP = { --- Army Group version. -- @field #string version -ARMYGROUP.version="0.4.0" +ARMYGROUP.version="0.7.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 205141623..fa3aec358 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -173,17 +173,11 @@ FLIGHTGROUP.Attribute = { --- Flight group element. -- @type FLIGHTGROUP.Element --- @field #string modex Tail number. --- @field Wrapper.Client#CLIENT client The client if element is occupied by a human player. --- @field #table pylons Table of pylons. --- @field #number fuelmass Mass of fuel in kg. --- @field #string callsign Call sign, e.g. "Uzi 1-1". --- @field Wrapper.Airbase#AIRBASE.ParkingSpot parking The parking spot table the element is parking on. -- @extends Ops.OpsGroup#OPSGROUP.Element --- FLIGHTGROUP class version. -- @field #string version -FLIGHTGROUP.version="0.6.1" +FLIGHTGROUP.version="0.7.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -278,6 +272,7 @@ function FLIGHTGROUP:New(group) self:AddTransition("*", "Taxiing", "Taxiing") -- The whole flight group is taxiing. self:AddTransition("*", "Takeoff", "Airborne") -- The whole flight group is airborne. self:AddTransition("*", "Airborne", "Airborne") -- The whole flight group is airborne. + self:AddTransition("*", "Cruise", "Cruising") -- The whole flight group is cruising. self:AddTransition("*", "Landing", "Landing") -- The whole flight group is landing. self:AddTransition("*", "Landed", "Landed") -- The whole flight group has landed. self:AddTransition("*", "Arrived", "Arrived") -- The whole flight group has arrived. @@ -600,11 +595,18 @@ function FLIGHTGROUP:IsTaxiing() return self:Is("Taxiing") end ---- Check if flight is airborne. +--- Check if flight is airborne or cruising. -- @param #FLIGHTGROUP self -- @return #boolean If true, flight is airborne. function FLIGHTGROUP:IsAirborne() - return self:Is("Airborne") + return self:Is("Airborne") or self:Is("Cruising") +end + +--- Check if flight is airborne or cruising. +-- @param #FLIGHTGROUP self +-- @return #boolean If true, flight is airborne. +function FLIGHTGROUP:IsCruising() + return self:Is("Cruising") end --- Check if flight is waiting after passing final waypoint. @@ -732,7 +734,7 @@ function FLIGHTGROUP:StartUncontrolled(delay) self:Activate() _delay=1 end - self:I(self.lid.."Starting uncontrolled group") + self:T(self.lid.."Starting uncontrolled group") self.group:StartUncontrolled(_delay) self.isUncontrolled=false else @@ -804,7 +806,7 @@ function FLIGHTGROUP:onbeforeStatus(From, Event, To) -- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase. for i,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element -- Check that element is not already dead or not yet alive. if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then @@ -881,7 +883,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To) -- Check if flight began to taxi (if it was parking). if self:IsParking() then for _,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element if element.parking then -- Get distance to assigned parking spot. @@ -927,7 +929,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To) if self.verbose>=2 then local text="Elements:" for i,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element local name=element.name local status=element.status @@ -974,7 +976,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To) local TmaxFuel=math.huge for _,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element -- Get relative fuel of element. local fuel=element.unit:GetFuel() or 0 @@ -1019,7 +1021,8 @@ function FLIGHTGROUP:onafterStatus(From, Event, To) local fuelmin=self:GetFuelMin() - self:I(self.lid..string.format("Fuel state=%d", fuelmin)) + -- Debug info. + self:T2(self.lid..string.format("Fuel state=%d", fuelmin)) if fuelmin>=self.fuellowthresh then self.fuellow=false @@ -1365,8 +1368,10 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element) + + -- Debug info. self:T(self.lid..string.format("Element spawned %s", Element.name)) -- Set element status. @@ -1391,6 +1396,7 @@ function FLIGHTGROUP:onafterElementSpawned(From, Event, To, Element) self:__ElementParking(0.11, Element) end end + end --- On after "ElementParking" event. @@ -1398,9 +1404,11 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. -- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot. function FLIGHTGROUP:onafterElementParking(From, Event, To, Element, Spot) + + -- Debug info. self:T(self.lid..string.format("Element parking %s at spot %s", Element.name, Element.parking and tostring(Element.parking.TerminalID) or "N/A")) -- Set element status. @@ -1417,6 +1425,7 @@ function FLIGHTGROUP:onafterElementParking(From, Event, To, Element, Spot) elseif self:IsTakeoffRunway() then self:__ElementEngineOn(0.5, Element) end + end --- On after "ElementEngineOn" event. @@ -1424,7 +1433,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementEngineOn(From, Event, To, Element) -- Debug info. @@ -1432,6 +1441,7 @@ function FLIGHTGROUP:onafterElementEngineOn(From, Event, To, Element) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.ENGINEON) + end --- On after "ElementTaxiing" event. @@ -1439,7 +1449,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementTaxiing(From, Event, To, Element) -- Get terminal ID. @@ -1453,6 +1463,7 @@ function FLIGHTGROUP:onafterElementTaxiing(From, Event, To, Element) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.TAXIING) + end --- On after "ElementTakeoff" event. @@ -1460,7 +1471,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. -- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil. function FLIGHTGROUP:onafterElementTakeoff(From, Event, To, Element, airbase) self:T(self.lid..string.format("Element takeoff %s at %s airbase.", Element.name, airbase and airbase:GetName() or "unknown")) @@ -1475,6 +1486,7 @@ function FLIGHTGROUP:onafterElementTakeoff(From, Event, To, Element, airbase) -- Trigger element airborne event. self:__ElementAirborne(0.1, Element) + end --- On after "ElementAirborne" event. @@ -1482,12 +1494,15 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementAirborne(From, Event, To, Element) + + -- Debug info. self:T2(self.lid..string.format("Element airborne %s", Element.name)) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.AIRBORNE) + end --- On after "ElementLanded" event. @@ -1495,9 +1510,11 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. -- @param Wrapper.Airbase#AIRBASE airbase The airbase if applicable or nil. function FLIGHTGROUP:onafterElementLanded(From, Event, To, Element, airbase) + + -- Debug info. self:T2(self.lid..string.format("Element landed %s at %s airbase", Element.name, airbase and airbase:GetName() or "unknown")) if self.despawnAfterLanding then @@ -1523,6 +1540,7 @@ function FLIGHTGROUP:onafterElementLanded(From, Event, To, Element, airbase) end end + end --- On after "ElementArrived" event. @@ -1530,7 +1548,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. -- @param Wrapper.Airbase#AIRBASE airbase The airbase, where the element arrived. -- @param Wrapper.Airbase#AIRBASE.ParkingSpot Parking The Parking spot the element has. function FLIGHTGROUP:onafterElementArrived(From, Event, To, Element, airbase, Parking) @@ -1548,7 +1566,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementDestroyed(From, Event, To, Element) -- Call OPSGROUP function. @@ -1561,7 +1579,7 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #FLIGHTGROUP.Element Element The flight group element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The flight group element. function FLIGHTGROUP:onafterElementDead(From, Event, To, Element) -- Call OPSGROUP function. @@ -1577,7 +1595,7 @@ function FLIGHTGROUP:onafterElementDead(From, Event, To, Element) end ---- On after "Spawned" event. Sets the template, initializes the waypoints. +--- On after "Spawned" event. -- @param #FLIGHTGROUP self -- @param #string From From state. -- @param #string Event Event. @@ -1701,6 +1719,7 @@ function FLIGHTGROUP:onafterTaxiing(From, Event, To) else -- Human flights go to TAXI OUT queue. They will go to the ready for takeoff queue when they request it. self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAXIOUT) + -- Update menu. self:_UpdateMenu() end @@ -1736,8 +1755,30 @@ function FLIGHTGROUP:onafterAirborne(From, Event, To) -- No current airbase any more. self.currbase=nil + + -- Cruising. + self:__Cruise(-0.05) + +end + +--- On after "Cruising" event. +-- @param #FLIGHTGROUP self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function FLIGHTGROUP:onafterCruise(From, Event, To) + self:T(self.lid..string.format("Flight cruising")) + + -- Not waiting anymore. + self.Twaiting=nil + self.dTwait=nil if self.isAI then + + --- + -- AI + --- + if self:IsTransporting() then if self.cargoTransport and self.cargoTransport.deployzone and self.cargoTransport.deployzone:IsInstanceOf("ZONE_AIRBASE") then local airbase=self.cargoTransport.deployzone:GetAirbase() @@ -1749,11 +1790,19 @@ function FLIGHTGROUP:onafterAirborne(From, Event, To) self:LandAtAirbase(airbase) end else - self:_CheckGroupDone() + self:_CheckGroupDone(nil, 120) end + else + + --- + -- CLIENT + --- + self:_UpdateMenu() + end + end --- On after "Landing" event. @@ -1944,7 +1993,7 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n) local allowed=true local trepeat=nil - if self:IsAlive() then -- and (self:IsAirborne() or self:IsWaiting() or self:IsInbound() or self:IsHolding()) then + if self:IsAlive() then -- Alive & Airborne ==> Update route possible. self:T3(self.lid.."Update route possible. Group is ALIVE") elseif self:IsDead() then @@ -2117,7 +2166,8 @@ end -- -- @param #FLIGHTGROUP self -- @param #number delay Delay in seconds. -function FLIGHTGROUP:_CheckGroupDone(delay) +-- @param #number waittime Time to wait if group is done. +function FLIGHTGROUP:_CheckGroupDone(delay, waittime) if self:IsAlive() and self.isAI then @@ -2127,7 +2177,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay) else -- Debug info. - self:T(self.lid.."Check group done?") + self:T(self.lid.."Check FLIGHTGROUP done?") -- First check if there is a paused mission that if self.missionpaused then @@ -2146,6 +2196,12 @@ function FLIGHTGROUP:_CheckGroupDone(delay) self:T(self.lid.."Landing at airbase! Group NOT done...") return end + + -- Group is waiting. + if self.Twaiting then + self:T(self.lid.."Waiting! Group NOT done...") + return + end -- Number of tasks remaining. local nTasks=self:CountRemainingTasks() @@ -2161,6 +2217,10 @@ function FLIGHTGROUP:_CheckGroupDone(delay) -- Final waypoint passed? if self.passedfinalwp then + + --- + -- Final Waypoint PASSED + --- -- Got current mission or task? if self.currentmission==nil and self.taskcurrent==0 and self.cargoTransport==nil then @@ -2172,13 +2232,16 @@ function FLIGHTGROUP:_CheckGroupDone(delay) local destzone=self.destzone or self.homezone -- Send flight to destination. - if destbase then + if waittime then + self:T(self.lid..string.format("Passed Final WP and No current and/or future missions/tasks/transports. Waittime given ==> Waiting for %d sec!", waittime)) + self:Wait(waittime) + elseif destbase then self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTB!") --self:RTB(destbase) self:__RTB(-0.1, destbase) elseif destzone then self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTZ!") - self:__RTZ(-3, destzone) + self:__RTZ(-0.1, destzone) else self:T(self.lid.."Passed Final WP and NO Tasks/Missions left. No DestBase or DestZone ==> Wait!") self:__Wait(-1) @@ -2192,8 +2255,17 @@ function FLIGHTGROUP:_CheckGroupDone(delay) self:T(self.lid..string.format("Passed Final WP but still have current Task (#%s) or Mission (#%s) left to do", tostring(self.taskcurrent), tostring(self.currentmission))) end else + + --- + -- Final Waypoint NOT PASSED + --- + + -- Debug info. self:T(self.lid..string.format("Flight (status=%s) did NOT pass the final waypoint yet ==> update route", self:GetState())) + + -- Update route. self:__UpdateRoute(-1) + end end @@ -2251,22 +2323,27 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold) local Ntot,Nsched, Nwp=self:CountRemainingTasks() if self.taskcurrent>0 then - self:I(self.lid..string.format("WARNING: Got current task ==> RTB event is suspended for 10 sec.")) + self:I(self.lid..string.format("WARNING: Got current task ==> RTB event is suspended for 10 sec")) Tsuspend=-10 allowed=false end if Nsched>0 then - self:I(self.lid..string.format("WARNING: Still got %d SCHEDULED tasks in the queue ==> RTB event is suspended for 10 sec.", Nsched)) + self:I(self.lid..string.format("WARNING: Still got %d SCHEDULED tasks in the queue ==> RTB event is suspended for 10 sec", Nsched)) Tsuspend=-10 allowed=false end if Nwp>0 then - self:I(self.lid..string.format("WARNING: Still got %d WAYPOINT tasks in the queue ==> RTB event is suspended for 10 sec.", Nwp)) + self:I(self.lid..string.format("WARNING: Still got %d WAYPOINT tasks in the queue ==> RTB event is suspended for 10 sec", Nwp)) Tsuspend=-10 allowed=false end + + if self.Twaiting and self.dTwait then + self:I(self.lid..string.format("WARNING: Group is Waiting for a specific duration ==> RTB event is canceled", Nwp)) + allowed=false + end end @@ -2342,6 +2419,9 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand) -- Set current airbase. self.currbase=airbase + + -- Passed final waypoint! + self.passedfinalwp=true -- Defaults: SpeedTo=SpeedTo or UTILS.KmphToKnots(self.speedCruise) @@ -2500,10 +2580,11 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. +-- @param #number Duration Duration how long the group will be waiting in seconds. Default `nil` (=forever). -- @param Core.Point#COORDINATE Coord Coordinate where to orbit. Default current position. -- @param #number Altitude Altitude in feet. Default 10000 ft. -- @param #number Speed Speed in knots. Default 250 kts. -function FLIGHTGROUP:onafterWait(From, Event, To, Coord, Altitude, Speed) +function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Coord, Altitude, Speed) Coord=Coord or self.group:GetCoordinate() Altitude=Altitude or (self.isHelo and 1000 or 10000) @@ -2517,9 +2598,34 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Coord, Altitude, Speed) -- Orbit task. local TaskOrbit=self.group:TaskOrbit(Coord, UTILS.FeetToMeters(Altitude), UTILS.KnotsToMps(Speed)) + + -- Orbit task. + local TaskFunction=self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self) + local DCSTasks=self.group:TaskCombo({TaskOrbit, TaskFunction}) + + -- Orbit until flaghold=1 (true) but max 5 min if no FC is giving the landing clearance. + local TaskOrbit = self.group:TaskOrbit(Coord, UTILS.FeetToMeters(Altitude), UTILS.KnotsToMps(Speed)) + local TaskStop = self.group:TaskCondition(nil, nil, nil, nil, Duration) + local TaskCntr = self.group:TaskControlled(TaskOrbit, TaskStop) + local TaskOver = self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self) + + local DCSTasks + if Duration then + DCSTasks=self.group:TaskCombo({TaskCntr, TaskOver}) + else + DCSTasks=self.group:TaskCombo({TaskOrbit, TaskOver}) + end + + -- Set task. - self:SetTask(TaskOrbit) + self:SetTask(DCSTasks) + + -- Set time stamp. + self.Twaiting=timer.getAbsTime() + + -- Max waiting + self.dTwait=Duration end @@ -2885,6 +2991,20 @@ function FLIGHTGROUP._FinishedRefuelling(group, flightgroup) flightgroup:__Refueled(-1) end +--- Function called when flight finished waiting. +-- @param Wrapper.Group#GROUP group Group object. +-- @param #FLIGHTGROUP flightgroup Flight group object. +function FLIGHTGROUP._FinishedWaiting(group, flightgroup) + flightgroup:T(flightgroup.lid..string.format("Group finished waiting")) + + -- Not waiting any more. + flightgroup.Twaiting=nil + flightgroup.dTwait=nil + + -- Trigger Holding event. + flightgroup:_CheckGroupDone(1) +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Misc functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -3034,14 +3154,14 @@ end --- Add an element to the flight group. -- @param #FLIGHTGROUP self -- @param #string unitname Name of unit. --- @return #FLIGHTGROUP.Element The element or nil. +-- @return Ops.OpsGroup#OPSGROUP.Element The element or nil. function FLIGHTGROUP:AddElementByName(unitname) local unit=UNIT:FindByName(unitname) if unit then - local element={} --#FLIGHTGROUP.Element + local element={} --Ops.OpsGroup#OPSGROUP.Element element.name=unitname element.status=OPSGROUP.ElementStatus.INUTERO @@ -3384,7 +3504,7 @@ function FLIGHTGROUP:InitWaypoints() end -- Debug info. - self:I(self.lid..string.format("Initializing %d waypoints. Homebase %s ==> %s Destination", #self.waypoints, self.homebase and self.homebase:GetName() or "unknown", self.destbase and self.destbase:GetName() or "uknown")) + self:T(self.lid..string.format("Initializing %d waypoints. Homebase %s ==> %s Destination", #self.waypoints, self.homebase and self.homebase:GetName() or "unknown", self.destbase and self.destbase:GetName() or "uknown")) -- Update route. if #self.waypoints>0 then @@ -3501,7 +3621,7 @@ end function FLIGHTGROUP:_IsElement(unitname) for _,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element if element.name==unitname then return true @@ -3516,7 +3636,7 @@ end --- Set parking spot of element. -- @param #FLIGHTGROUP self --- @param #FLIGHTGROUP.Element Element The element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The element. -- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot. function FLIGHTGROUP:_SetElementParkingAt(Element, Spot) @@ -3540,7 +3660,7 @@ end --- Set parking spot of element to free -- @param #FLIGHTGROUP self --- @param #FLIGHTGROUP.Element Element The element. +-- @param Ops.OpsGroup#OPSGROUP.Element Element The element. function FLIGHTGROUP:_SetElementParkingFree(Element) if Element.parking then @@ -3650,7 +3770,7 @@ end --- Returns the parking spot of the element. -- @param #FLIGHTGROUP self --- @param #FLIGHTGROUP.Element element Element of the flight group. +-- @param Ops.OpsGroup#OPSGROUP.Element element Element of the flight group. -- @param #number maxdist Distance threshold in meters. Default 5 m. -- @param Wrapper.Airbase#AIRBASE airbase (Optional) The airbase to check for parking. Default is closest airbase to the element. -- @return Wrapper.Airbase#AIRBASE.ParkingSpot Parking spot or nil if no spot is within distance threshold. @@ -3825,7 +3945,7 @@ function FLIGHTGROUP:GetParking(airbase) -- Loop over all units - each one needs a spot. for i,_element in pairs(self.elements) do - local element=_element --#FLIGHTGROUP.Element + local element=_element --Ops.OpsGroup#OPSGROUP.Element -- Loop over all parking spots. local gotit=false diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index 0310292ac..9ce1b4210 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -65,12 +65,7 @@ NAVYGROUP = { pathCorridor = 400, } ---- Navy group element. --- @type NAVYGROUP.Element --- @field #string name Name of the element, i.e. the unit. --- @field #string typename Type name. - ---- Navy group element. +--- Turn into wind parameters. -- @type NAVYGROUP.IntoWind -- @field #number Tstart Time to start. -- @field #number Tstop Time to stop. @@ -87,7 +82,7 @@ NAVYGROUP = { --- NavyGroup version. -- @field #string version -NAVYGROUP.version="0.5.0" +NAVYGROUP.version="0.7.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 901bdebc0..9ed08f08a 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -117,7 +117,6 @@ -- @field #string cargoStatus Cargo status of this group acting as cargo. -- @field #number cargoTransportUID Unique ID of the transport assignment this cargo group is associated with. -- @field #string carrierStatus Carrier status of this group acting as cargo carrier. --- @field #number cargocounter Running number of cargo UIDs. -- @field #OPSGROUP.CarrierLoader carrierLoader Carrier loader parameters. -- @field #OPSGROUP.CarrierLoader carrierUnloader Carrier unloader parameters. -- @@ -134,7 +133,7 @@ -- -- # The OPSGROUP Concept -- --- The OPSGROUP class contains common functions used by other classes such as FLIGHGROUP, NAVYGROUP and ARMYGROUP. +-- The OPSGROUP class contains common functions used by other classes such as FLIGHTGROUP, NAVYGROUP and ARMYGROUP. -- Those classes inherit everything of this class and extend it with features specific to their unit category. -- -- This class is **NOT** meant to be used by the end user itself. @@ -180,7 +179,6 @@ OPSGROUP = { weaponData = {}, cargoqueue = {}, cargoBay = {}, - cargocounter = 1, mycarrier = {}, carrierLoader = {}, carrierUnloader = {}, @@ -225,6 +223,14 @@ OPSGROUP = { -- @field #number weightCargo Current cargo weight in kg. -- @field #number weight Current weight including cargo in kg. -- @field #table cargoBay Cargo bay. +-- +-- @field #string modex Tail number. +-- @field Wrapper.Client#CLIENT client The client if element is occupied by a human player. +-- @field #table pylons Table of pylons. +-- @field #number fuelmass Mass of fuel in kg. +-- @field #string callsign Call sign, e.g. "Uzi 1-1". +-- @field Wrapper.Airbase#AIRBASE.ParkingSpot parking The parking spot table the element is parking on. + --- Status of group element. -- @type OPSGROUP.ElementStatus @@ -446,7 +452,7 @@ OPSGROUP.CargoStatus={ --- OpsGroup version. -- @field #string version -OPSGROUP.version="0.7.3" +OPSGROUP.version="0.7.5" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -511,13 +517,13 @@ function OPSGROUP:New(group) self.spot.timer=TIMER:New(self._UpdateLaser, self) self.spot.Coordinate=COORDINATE:New(0, 0, 0) self:SetLaser(1688, true, false, 0.5) + + -- Cargo. self.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO self.carrierStatus=OPSGROUP.CarrierStatus.NOTCARRIER - self.cargocounter=1 self:SetCarrierLoaderAllAspect() self:SetCarrierUnloaderAllAspect() - -- Init task counter. self.taskcurrent=0 self.taskcounter=0 @@ -1513,6 +1519,7 @@ function OPSGROUP:RadioTransmission(Text, Delay) self.msrs:SetFrequencies(freq) self.msrs:SetModulations(modu) + -- Debug info. self:I(self.lid..string.format("Radio transmission on %.3f MHz %s: %s", freq, UTILS.GetModulationName(modu), Text)) self.msrs:PlayText(Text) @@ -2365,7 +2372,7 @@ function OPSGROUP:OnEventBirth(EventData) self.destbase=self.homebase end - self:I(self.lid..string.format("EVENT: Element %s born at airbase %s ==> spawned", unitname, self.currbase and self.currbase:GetName() or "unknown")) + self:T(self.lid..string.format("EVENT: Element %s born at airbase %s ==> spawned", unitname, self.currbase and self.currbase:GetName() or "unknown")) else self:T3(self.lid..string.format("EVENT: Element %s born ==> spawned", unitname)) end @@ -4572,7 +4579,9 @@ end -- @param #string To To state. -- @param #OPSGROUP.Element Element The flight group element. function OPSGROUP:onafterElementDead(From, Event, To, Element) - self:I(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime())) + + -- Debug info. + self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime())) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD) @@ -4615,7 +4624,7 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element) -- Clear cargo bay of element. --for _,_cargo in pairs(Element.cargoBay) do for i=#Element.cargoBay,1,-1 do - local cargo=Element.cargoBay[i] --#OPSGROUP.MyCargo --_cargo --#OPSGROUP.MyCargo + local cargo=Element.cargoBay[i] --#OPSGROUP.MyCargo -- Remove from cargo bay. self:_DelCargobay(cargo.group) @@ -4628,7 +4637,7 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element) if cargo.reserved then -- This group was not loaded yet ==> Not cargo any more. - cargo.group.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO + cargo.group:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) else @@ -4798,6 +4807,8 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterDead(From, Event, To) + + -- Debug info. self:I(self.lid..string.format("Group dead at t=%.3f", timer.getTime())) -- Is dead now. @@ -4897,7 +4908,7 @@ function OPSGROUP:onafterStop(From, Event, To) _DATABASE.FLIGHTGROUPS[self.groupname]=nil -- Debug output. - self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from database") + self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from _DATABASE") end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -4983,7 +4994,7 @@ function OPSGROUP:_CheckCargoTransport() if self:IsNotCarrier() then -- Debug info. - self:I(self.lid.."Not carrier ==> pickup") + self:T(self.lid.."Not carrier ==> pickup") -- Initiate the cargo transport process. self:__Pickup(-1) @@ -5000,7 +5011,7 @@ function OPSGROUP:_CheckCargoTransport() self.Tloading=self.Tloading or Time -- Debug info. - self:I(self.lid.."Loading...") + self:T(self.lid.."Loading...") local boarding=false local gotcargo=false @@ -5018,15 +5029,10 @@ function OPSGROUP:_CheckCargoTransport() end end - - -- Debug. - --self:I(self.lid.."gotcargo="..tostring(gotcargo)) - --self:I(self.lid.."boarding="..tostring(boarding)) - --self:I(self.lid.."required="..tostring(self.cargoTransport:_CheckRequiredCargos())) -- Boarding finished ==> Transport cargo. if gotcargo and self.cargoTransport:_CheckRequiredCargos() and not boarding then - self:I(self.lid.."Boarding finished ==> Loaded") + self:T(self.lid.."Boarding finished ==> Loaded") self:Loaded() else -- No cargo and no one is boarding ==> check again if we can make anyone board. @@ -5046,7 +5052,7 @@ function OPSGROUP:_CheckCargoTransport() elseif self:IsUnloading() then -- Debug info. - self:I(self.lid.."Unloading ==> Checking if all cargo was delivered") + self:T(self.lid.."Unloading ==> Checking if all cargo was delivered") local delivered=true for _,_cargo in pairs(self.cargoTransport.cargos) do @@ -5064,7 +5070,7 @@ function OPSGROUP:_CheckCargoTransport() -- Unloading finished ==> pickup next batch or call it a day. if delivered then - self:I(self.lid.."Unloading finished ==> Unloaded") + self:T(self.lid.."Unloading finished ==> Unloaded") self:Unloaded() else self:Unloading() @@ -5468,6 +5474,23 @@ function OPSGROUP:GetWeightCargoMax(UnitName) return weight end +--- Get OPSGROUPs in the cargo bay. +-- @param #OPSGROUP self +-- @return #table Cargo OPSGROUPs. +function OPSGROUP:GetCargoOpsGroups() + + local opsgroups={} + for _,_element in pairs(self.elements) do + local element=_element --#OPSGROUP.Element + for _,_cargo in pairs(element.cargoBay) do + local cargo=_cargo --#OPSGROUP.MyCargo + table.insert(opsgroups, cargo.group) + end + end + + return opsgroups +end + --- Add weight to the internal cargo of an element of the group. -- @param #OPSGROUP self -- @param #string UnitName Name of the unit. Default is of the whole group. @@ -5635,11 +5658,9 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterPickup(From, Event, To) - -- Debug info. - self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.PICKUP)) -- Set carrier status. - self.carrierStatus=OPSGROUP.CarrierStatus.PICKUP + self:_NewCarrierStatus(OPSGROUP.CarrierStatus.PICKUP) -- Pickup zone. local Zone=self.cargoTransport.pickupzone @@ -5790,11 +5811,9 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterLoading(From, Event, To) - -- Debug info. - self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.LOADING)) -- Set carrier status. - self.carrierStatus=OPSGROUP.CarrierStatus.LOADING + self:_NewCarrierStatus(OPSGROUP.CarrierStatus.LOADING) -- Loading time stamp. self.Tloading=timer.getAbsTime() @@ -5824,7 +5843,7 @@ function OPSGROUP:onafterLoading(From, Event, To) if carrier then -- Set cargo status. - cargo.opsgroup.cargoStatus=OPSGROUP.CargoStatus.ASSIGNED + cargo.opsgroup:_NewCargoStatus(OPSGROUP.CargoStatus.ASSIGNED) -- Order cargo group to board the carrier. cargo.opsgroup:Board(self, carrier) @@ -5860,6 +5879,36 @@ function OPSGROUP:ClearWaypoints() self.waypoints={} end +--- Set (new) cargo status. +-- @param #OPSGROUP self +-- @param #string Status New status. +function OPSGROUP:_NewCargoStatus(Status) + + -- Debug info. + if self.verbose>=2 then + self:I(self.lid..string.format("New cargo status: %s --> %s", tostring(self.cargoStatus), tostring(Status))) + end + + -- Set cargo status. + self.cargoStatus=Status + +end + +--- Set (new) carrier status. +-- @param #OPSGROUP self +-- @param #string Status New status. +function OPSGROUP:_NewCarrierStatus(Status) + + -- Debug info. + if self.verbose>=2 then + self:I(self.lid..string.format("New carrier status: %s --> %s", tostring(self.carrierStatus), tostring(Status))) + end + + -- Set cargo status. + self.carrierStatus=Status + +end + --- Transfer cargo from to another carrier. -- @param #OPSGROUP self -- @param #OPSGROUP CargoGroup The cargo group to be transferred. @@ -5886,7 +5935,7 @@ end function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) -- Debug info. - self:I(self.lid..string.format("Loading group %s", tostring(CargoGroup.groupname))) + self:T(self.lid..string.format("Loading group %s", tostring(CargoGroup.groupname))) -- Carrier element. local carrier=Carrier or CargoGroup:_GetMyCarrierElement() --#OPSGROUP.Element @@ -5902,12 +5951,9 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) --- -- Embark Cargo --- - - -- Debug info. - CargoGroup:I(CargoGroup.lid..string.format("New cargo status: %s --> %s", CargoGroup.cargoStatus, OPSGROUP.CargoStatus.LOADED)) - - -- Set cargo status. - CargoGroup.cargoStatus=OPSGROUP.CargoStatus.LOADED + + -- New cargo status. + CargoGroup:_NewCargoStatus(OPSGROUP.CargoStatus.LOADED) -- Clear all waypoints. CargoGroup:ClearWaypoints() @@ -5927,7 +5973,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) if self.cargoTransport then self.cargoTransport:Loaded(CargoGroup, self, carrier) else - self:E(self.lid..string.format("WARNING: Loaded cargo but no current OPSTRANSPORT assignment!")) + self:T(self.lid..string.format("WARNING: Loaded cargo but no current OPSTRANSPORT assignment!")) end else @@ -5981,11 +6027,8 @@ end -- @param #string To To state. function OPSGROUP:onafterTransport(From, Event, To) - -- Debug info. - self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.TRANSPORTING)) - -- Set carrier status. - self.carrierStatus=OPSGROUP.CarrierStatus.TRANSPORTING + self:_NewCarrierStatus(OPSGROUP.CarrierStatus.TRANSPORTING) --TODO: This is all very similar to the onafterPickup() function. Could make it general. @@ -6131,11 +6174,9 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterUnloading(From, Event, To) - -- Debug info. - self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.UNLOADING)) -- Set carrier status to UNLOADING. - self.carrierStatus=OPSGROUP.CarrierStatus.UNLOADING + self:_NewCarrierStatus(OPSGROUP.CarrierStatus.UNLOADING) -- Deploy zone. local zone=self.cargoTransport.disembarkzone or self.cargoTransport.deployzone --Core.Zone#ZONE @@ -6270,12 +6311,9 @@ end -- @param #boolean Activated If `true`, group is active. If `false`, group is spawned in late activated state. -- @param #number Heading (Optional) Heading of group in degrees. Default is random heading for each unit. function OPSGROUP:onafterUnload(From, Event, To, OpsGroup, Coordinate, Activated, Heading) - - -- Debug info. - OpsGroup:I(OpsGroup.lid..string.format("New cargo status: %s --> %s", OpsGroup.cargoStatus, OPSGROUP.CargoStatus.NOTCARGO)) - - -- Set cargo status. - OpsGroup.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO + + -- New cargo status. + OpsGroup:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) --TODO: Unload flightgroup. Find parking spot etc. @@ -6362,8 +6400,9 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterUnloaded(From, Event, To) + -- Debug info - self:I(self.lid.."Cargo unloaded..") + self:T(self.lid.."Cargo unloaded..") -- Cancel landedAt task. if self:IsFlightgroup() and self:IsLandedAt() then @@ -6400,9 +6439,9 @@ function OPSGROUP:onafterDelivered(From, Event, To, CargoTransport) -- Check if this was the current transport. if self.cargoTransport and self.cargoTransport.uid==CargoTransport.uid then - - -- Debug info. - self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.NOTCARRIER)) + + -- This is not a carrier anymore. + self:_NewCarrierStatus(OPSGROUP.CarrierStatus.NOTCARRIER) -- Checks if self:IsPickingup() then @@ -6419,9 +6458,6 @@ function OPSGROUP:onafterDelivered(From, Event, To, CargoTransport) -- Nothing to do? end - -- This is not a carrier anymore. - self.carrierStatus=OPSGROUP.CarrierStatus.NOTCARRIER - -- Startup uncontrolled aircraft to allow it to go back. if self:IsFlightgroup() then if self:IsUncontrolled() then @@ -6436,7 +6472,7 @@ function OPSGROUP:onafterDelivered(From, Event, To, CargoTransport) end -- Check group done. - self:I(self.lid.."All cargo delivered ==> check group done") + self:T(self.lid.."All cargo delivered ==> check group done") self:_CheckGroupDone(0.2) -- No current transport any more. @@ -6467,11 +6503,11 @@ function OPSGROUP:onbeforeBoard(From, Event, To, CarrierGroup, Carrier) return false elseif CarrierGroup:IsDead() then self:I(self.lid.."Carrier Group DEAD ==> Deny Board transition!") - self.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO + self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) return false elseif Carrier.status==OPSGROUP.ElementStatus.DEAD then self:I(self.lid.."Carrier Element DEAD ==> Deny Board transition!") - self.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO + self:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO) return false end @@ -6486,11 +6522,9 @@ end -- @param #OPSGROUP CarrierGroup The carrier group. -- @param #OPSGROUP.Element Carrier The OPSGROUP element function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) - -- Debug info. - self:I(self.lid..string.format("New cargo status: %s --> %s", self.cargoStatus, OPSGROUP.CargoStatus.BOARDING)) -- Set cargo status. - self.cargoStatus=OPSGROUP.CargoStatus.BOARDING + self:_NewCargoStatus(OPSGROUP.CargoStatus.BOARDING) -- Army or Navy group. local CarrierIsArmyOrNavy=CarrierGroup:IsArmygroup() or CarrierGroup:IsNavygroup() @@ -6510,7 +6544,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) if board then -- Debug info. - self:I(self.lid..string.format("Boarding group=%s [%s], carrier=%s", CarrierGroup:GetName(), CarrierGroup:GetState(), Carrier.name)) + self:T(self.lid..string.format("Boarding group=%s [%s], carrier=%s", CarrierGroup:GetName(), CarrierGroup:GetState(), Carrier.name)) -- TODO: Implement embarkzone. local Coordinate=Carrier.unit:GetCoordinate() @@ -6536,7 +6570,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) --- -- Debug info. - self:I(self.lid..string.format("Board with direct load to carrier %s", CarrierGroup:GetName())) + self:T(self.lid..string.format("Board with direct load to carrier %s", CarrierGroup:GetName())) local mycarriergroup=self:_GetMyCarrierGroup() @@ -6733,6 +6767,9 @@ function OPSGROUP:_CheckGroupDone(delay) self:ScheduleOnce(delay, self._CheckGroupDone, self) else + -- Debug info. + self:T(self.lid.."Check OPSGROUP done?") + -- Group is engaging something. if self:IsEngaging() then self:UpdateRoute() @@ -7523,7 +7560,8 @@ function OPSGROUP:SwitchROT(rot) self.group:OptionROT(self.option.ROT) - self:I(self.lid..string.format("Setting current ROT=%d (0=NoReaction, 1=Passive, 2=Evade, 3=ByPass, 4=AllowAbort)", self.option.ROT)) + -- Debug info. + self:T(self.lid..string.format("Setting current ROT=%d (0=NoReaction, 1=Passive, 2=Evade, 3=ByPass, 4=AllowAbort)", self.option.ROT)) end @@ -8326,7 +8364,7 @@ function OPSGROUP:_UpdateStatus(element, newstatus, airbase) --- if self:_AllSimilarStatus(newstatus) then - self:__Spawned(-0.5) + self:Spawned() end elseif newstatus==OPSGROUP.ElementStatus.PARKING then @@ -8335,7 +8373,7 @@ function OPSGROUP:_UpdateStatus(element, newstatus, airbase) --- if self:_AllSimilarStatus(newstatus) then - self:__Parking(-0.5) + self:Parking() end elseif newstatus==OPSGROUP.ElementStatus.ENGINEON then @@ -8351,7 +8389,7 @@ function OPSGROUP:_UpdateStatus(element, newstatus, airbase) --- if self:_AllSimilarStatus(newstatus) then - self:__Taxiing(-0.5) + self:Taxiing() end elseif newstatus==OPSGROUP.ElementStatus.TAKEOFF then @@ -8361,7 +8399,7 @@ function OPSGROUP:_UpdateStatus(element, newstatus, airbase) if self:_AllSimilarStatus(newstatus) then -- Trigger takeoff event. Also triggers airborne event. - self:__Takeoff(-0.5, airbase) + self:Takeoff(airbase) end elseif newstatus==OPSGROUP.ElementStatus.AIRBORNE then @@ -8370,7 +8408,7 @@ function OPSGROUP:_UpdateStatus(element, newstatus, airbase) --- if self:_AllSimilarStatus(newstatus) then - self:__Airborne(-0.1) + self:Airborne() end elseif newstatus==OPSGROUP.ElementStatus.LANDED then @@ -8463,13 +8501,19 @@ function OPSGROUP:GetElementZoneBoundingBox(UnitName) -- Create a new zone if necessary. element.zoneBoundingbox=element.zoneBoundingbox or ZONE_POLYGON_BASE:New(element.name.." Zone Bounding Box", {}) + -- Length in meters. local l=element.length + -- Width in meters. local w=element.width + -- Orientation vector. local X=self:GetOrientationX(element.name) + + -- Heading in degrees. local heading=math.deg(math.atan2(X.z, X.x)) - env.info(string.format("FF l=%d w=%d h=%d", l, w, heading)) + -- Debug info. + self:T(self.lid..string.format("Element %s bouding box: l=%d w=%d heading=%d", element.name, l, w, heading)) -- Set of edges facing "North" at the origin of the map. local b={} @@ -8559,7 +8603,7 @@ function OPSGROUP:_GetElementZoneLoader(Element, Zone, Loader) -- Heading in deg. local heading=math.deg(math.atan2(X.z, X.x)) - env.info(string.format("FF l=%d w=%d h=%d", l, w, heading)) + --env.info(string.format("FF l=%d w=%d h=%d", l, w, heading)) -- Bounding box at the origin of the map facing "North". local b={} diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index 0ef309150..bea743fe7 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -69,6 +69,44 @@ -- * Cargo groups are **not** split and distributed into different carrier *units*. That means that the whole cargo group **must fit** into one of the carrier units. -- * Cargo groups must be inside the pickup zones to be considered for loading. Groups not inside the pickup zone will not get the command to board. -- +-- # Constructor +-- +-- A new cargo transport assignment is created with the @{#OPSTRANSPORT.New}() function +-- +-- local opstransport=OPSTRANSPORT:New(Cargo, PickupZone, DeployZone) +-- +-- Here `Cargo` is an object of the troops to be transported. This can be a GROUP, OPSGROUP, SET_GROUP or SET_OPSGROUP object. +-- +-- `PickupZone` is the zone where the troops are picked up by the transport carriers. **Note** that troops *must* be inside this zone to be considered for loading! +-- +-- `DeployZone` is the zone where the troops are transported to. +-- +-- ## Assign to Carrier(s) +-- +-- A transport can be assigned to one or multiple carrier OPSGROUPS with this @{Ops.OpsGroup#OPSGROUP.AddOpsTransport}() function +-- +-- myopsgroup:AddOpsTransport(opstransport) +-- +-- There is no restriction to the type of the carrier. It can be a ground group (e.g. an APC), a helicopter, an airplane or even a ship. +-- +-- You can also mix carrier types. For instance, you can assign the same transport to APCs and helicopters. Or to helicopters and airplanes. +-- +-- # Examples +-- +-- A carrier group is assigned to transport infantry troops from zone "Zone Kobuleti X" to zone "Zone Alpha". +-- +-- -- Carrier group. +-- local carrier=ARMYGROUP:New("TPz Fuchs Group") +-- +-- -- Set of groups to transport. +-- local infantryset=SET_GROUP:New():FilterPrefixes("Infantry Platoon Alpha"):FilterOnce() +-- +-- -- Cargo transport assignment. +-- local opstransport=OPSTRANSPORT:New(infantryset, ZONE:New("Zone Kobuleti X"), ZONE:New("Zone Alpha")) +-- +-- -- Assign transport to carrier. +-- carrier:AddOpsTransport(opstransport) +-- -- -- @field #OPSTRANSPORT OPSTRANSPORT = { @@ -112,7 +150,7 @@ _OPSTRANSPORTID=0 --- Army Group version. -- @field #string version -OPSTRANSPORT.version="0.0.8" +OPSTRANSPORT.version="0.1.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -227,7 +265,7 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet) end -- Debug info. - if self.verbose>=0 then + if self.verbose>=1 then local text=string.format("Added cargo groups:") local Weight=0 for _,_cargo in pairs(self.cargos) do @@ -432,20 +470,29 @@ end --- Get (all) cargo @{Ops.OpsGroup#OPSGROUP}s. Optionally, only delivered or undelivered groups can be returned. -- @param #OPSTRANSPORT self -- @param #boolean Delivered If `true`, only delivered groups are returned. If `false` only undelivered groups are returned. If `nil`, all groups are returned. --- @return #table Ops groups. +-- @return #table Cargo Ops groups. function OPSTRANSPORT:GetCargoOpsGroups(Delivered) local opsgroups={} for _,_cargo in pairs(self.cargos) do local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup if Delivered==nil or cargo.delivered==Delivered then - table.insert(opsgroups, cargo.opsgroup) + if cargo.opsgroup and not (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then + table.insert(opsgroups, cargo.opsgroup) + end end end return opsgroups end +--- Get carrier @{Ops.OpsGroup#OPSGROUP}s. +-- @param #OPSTRANSPORT self +-- @return #table Carrier Ops groups. +function OPSTRANSPORT:GetCarrierOpsGroups() + return self.carriers +end + --- Set transport start and stop time. -- @param #OPSTRANSPORT self @@ -579,11 +626,13 @@ function OPSTRANSPORT:_GetPathTransport() local coordinates={} - for _,coord in ipairs(path.coords) do + for _,_coord in ipairs(path.coords) do + local coord=_coord --Core.Point#COORDINATE + + -- Get random coordinate. + local c=coord:GetRandomCoordinateInRadius(path.radius) - -- TODO: Add randomization. - - table.insert(coordinates, coord) + table.insert(coordinates, c) end return coordinates @@ -642,11 +691,13 @@ function OPSTRANSPORT:_GetPathPickup() local coordinates={} - for _,coord in ipairs(path.coords) do + for _,_coord in ipairs(path.coords) do + local coord=_coord --Core.Point#COORDINATE + + -- Get random coordinate. + local c=coord:GetRandomCoordinateInRadius(path.radius) - -- TODO: Add randomization. - - table.insert(coordinates, coord) + table.insert(coordinates, c) end return coordinates @@ -753,7 +804,7 @@ function OPSTRANSPORT:IsReadyToGo() -- Nope, not yet. if not startme then text=text..("No way, at least one start condition is not true!") - self:I(text) + self:T(text) return false end