- many fixes and improvements
This commit is contained in:
Frank 2021-07-29 13:43:29 +02:00
parent 615a220acb
commit d64de26ded
10 changed files with 288 additions and 202 deletions

View File

@ -4882,6 +4882,13 @@ function WAREHOUSE:onbeforeArrived(From, Event, To, group)
local asset=self:FindAssetInDB(group) local asset=self:FindAssetInDB(group)
if asset then if asset then
if asset.flightgroup and not asset.arrived then
--env.info("FF asset has a flightgroup. arrival will be handled there!")
asset.arrived=true
return false
end
if asset.arrived==true then if asset.arrived==true then
-- Asset already arrived (e.g. if multiple units trigger the event via landing). -- Asset already arrived (e.g. if multiple units trigger the event via landing).
return false return false
@ -4889,6 +4896,7 @@ function WAREHOUSE:onbeforeArrived(From, Event, To, group)
asset.arrived=true --ensure this is not called again from the same asset group. asset.arrived=true --ensure this is not called again from the same asset group.
return true return true
end end
end end
end end
@ -6042,7 +6050,7 @@ function WAREHOUSE:_RouteGround(group, request)
end end
for n,wp in ipairs(Waypoints) do for n,wp in ipairs(Waypoints) do
env.info(n) --env.info(n)
local tf=self:_SimpleTaskFunctionWP("warehouse:_PassingWaypoint",group, n, #Waypoints) local tf=self:_SimpleTaskFunctionWP("warehouse:_PassingWaypoint",group, n, #Waypoints)
group:SetTaskWaypoint(wp, tf) group:SetTaskWaypoint(wp, tf)
end end
@ -9046,11 +9054,11 @@ function WAREHOUSE:_GetFlightplan(asset, departure, destination)
-- Hot start. -- Hot start.
if asset.takeoffType and asset.takeoffType==COORDINATE.WaypointType.TakeOffParkingHot then if asset.takeoffType and asset.takeoffType==COORDINATE.WaypointType.TakeOffParkingHot then
env.info("FF hot") --env.info("FF hot")
_type=COORDINATE.WaypointType.TakeOffParkingHot _type=COORDINATE.WaypointType.TakeOffParkingHot
_action=COORDINATE.WaypointAction.FromParkingAreaHot _action=COORDINATE.WaypointAction.FromParkingAreaHot
else else
env.info("FF cold") --env.info("FF cold")
end end

View File

@ -612,9 +612,9 @@ function AIRWING:RemoveAssetFromSquadron(Asset)
end end
end end
--- Add mission to queue. --- Add a mission for the airwing. The airwing will pick the best available assets for the mission and lauch it when ready.
-- @param #AIRWING self -- @param #AIRWING self
-- @param Ops.Auftrag#AUFTRAG Mission for this group. -- @param Ops.Auftrag#AUFTRAG Mission Mission for this airwing.
-- @return #AIRWING self -- @return #AIRWING self
function AIRWING:AddMission(Mission) function AIRWING:AddMission(Mission)

View File

@ -6119,6 +6119,11 @@ function AIRBOSS:_ScanCarrierZone()
-- Get flight group if possible. -- Get flight group if possible.
local knownflight=self:_GetFlightFromGroupInQueue(group, self.flights) local knownflight=self:_GetFlightFromGroupInQueue(group, self.flights)
-- Unknown new AI flight. Create a new flight group.
if not knownflight and not self:_IsHuman(group) then
knownflight=self:_CreateFlightGroup(group)
end
-- Get aircraft type name. -- Get aircraft type name.
local actype=group:GetTypeName() local actype=group:GetTypeName()
@ -6175,10 +6180,7 @@ function AIRBOSS:_ScanCarrierZone()
else else
-- Unknown new AI flight. Create a new flight group.
if not self:_IsHuman(group) then
self:_CreateFlightGroup(group)
end
end end

View File

@ -538,6 +538,24 @@ end
function ARMYGROUP:onafterSpawned(From, Event, To) function ARMYGROUP:onafterSpawned(From, Event, To)
self:T(self.lid..string.format("Group spawned!")) self:T(self.lid..string.format("Group spawned!"))
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Army Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
self:I(self.lid..text)
end
-- Update position. -- Update position.
self:_UpdatePosition() self:_UpdatePosition()
@ -1180,24 +1198,6 @@ function ARMYGROUP:_InitGroup(Template)
-- Set type name. -- Set type name.
self.actype=units[1]:GetTypeName() self.actype=units[1]:GetTypeName()
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Army Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
self:I(self.lid..text)
end
-- Init done. -- Init done.
self.groupinitialized=true self.groupinitialized=true

View File

@ -7,7 +7,7 @@
-- * Set mission start/stop times -- * Set mission start/stop times
-- * Set mission priority and urgency (can cancel running missions) -- * Set mission priority and urgency (can cancel running missions)
-- * Specific mission options for ROE, ROT, formation, etc. -- * Specific mission options for ROE, ROT, formation, etc.
-- * Compatible with FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, WINGCOMMANDER and CHIEF classes -- * Compatible with OPS classes like FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, etc.
-- * FSM events when a mission is done, successful or failed -- * FSM events when a mission is done, successful or failed
-- --
-- === -- ===
@ -106,6 +106,7 @@
-- @field #number missionFraction Mission coordiante fraction. Default is 0.5. -- @field #number missionFraction Mission coordiante fraction. Default is 0.5.
-- @field #number missionRange Mission range in meters. Used in AIRWING class. -- @field #number missionRange Mission range in meters. Used in AIRWING class.
-- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate. -- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate.
-- @field Core.Point#COORDINATE missionEgressCoord Mission egress waypoint coordinate.
-- --
-- @field #table enrouteTasks Mission enroute tasks. -- @field #table enrouteTasks Mission enroute tasks.
-- --
@ -434,8 +435,9 @@ AUFTRAG.TargetType={
--- Group specific data. Each ops group subscribed to this mission has different data for this. --- Group specific data. Each ops group subscribed to this mission has different data for this.
-- @type AUFTRAG.GroupData -- @type AUFTRAG.GroupData
-- @field Ops.OpsGroup#OPSGROUP opsgroup The OPS group. -- @field Ops.OpsGroup#OPSGROUP opsgroup The OPS group.
-- @field Core.Point#COORDINATE waypointcoordinate Waypoint coordinate. -- @field Core.Point#COORDINATE waypointcoordinate Ingress waypoint coordinate.
-- @field #number waypointindex Waypoint index. -- @field #number waypointindex Waypoint index.
-- @field Core.Point#COORDINATE wpegresscoordinate Egress waypoint coordinate.
-- @field Ops.OpsGroup#OPSGROUP.Task waypointtask Waypoint task. -- @field Ops.OpsGroup#OPSGROUP.Task waypointtask Waypoint task.
-- @field #string status Group mission status. -- @field #string status Group mission status.
-- @field Ops.AirWing#AIRWING.SquadronAsset asset The squadron asset. -- @field Ops.AirWing#AIRWING.SquadronAsset asset The squadron asset.
@ -443,7 +445,7 @@ AUFTRAG.TargetType={
--- AUFTRAG class version. --- AUFTRAG class version.
-- @field #string version -- @field #string version
AUFTRAG.version="0.6.1" AUFTRAG.version="0.7.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -938,7 +940,7 @@ end
--- Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate. --- Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT or STATIC object. -- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC or TARGET object.
-- @param #number Altitude Engage altitude in feet. Default 2000 ft. -- @param #number Altitude Engage altitude in feet. Default 2000 ft.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:NewSTRIKE(Target, Altitude) function AUFTRAG:NewSTRIKE(Target, Altitude)
@ -966,7 +968,7 @@ end
--- Create a BOMBING mission. Flight will drop bombs a specified coordinate. --- Create a BOMBING mission. Flight will drop bombs a specified coordinate.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object. -- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object.
-- @param #number Altitude Engage altitude in feet. Default 25000 ft. -- @param #number Altitude Engage altitude in feet. Default 25000 ft.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:NewBOMBING(Target, Altitude) function AUFTRAG:NewBOMBING(Target, Altitude)
@ -1007,10 +1009,6 @@ function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude)
Airdrome=AIRBASE:FindByName(Airdrome) Airdrome=AIRBASE:FindByName(Airdrome)
end end
if Airdrome:IsInstanceOf("AIRBASE") then
end
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBRUNWAY) local mission=AUFTRAG:New(AUFTRAG.Type.BOMBRUNWAY)
mission:_TargetFromObject(Airdrome) mission:_TargetFromObject(Airdrome)
@ -1111,8 +1109,6 @@ function AUFTRAG:NewRESCUEHELO(Carrier)
local mission=AUFTRAG:New(AUFTRAG.Type.RESCUEHELO) local mission=AUFTRAG:New(AUFTRAG.Type.RESCUEHELO)
--mission.carrier=Carrier
mission:_TargetFromObject(Carrier) mission:_TargetFromObject(Carrier)
-- Mission options: -- Mission options:
@ -3138,12 +3134,45 @@ function AUFTRAG:GetMissionTypesText(MissionTypes)
return text return text
end end
--- Set the mission waypoint coordinate where the mission is executed. --- Set the mission waypoint coordinate where the mission is executed. Note that altitude is set via `:SetMissionAltitude`.
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @return Core.Point#COORDINATE Coordinate where the mission is executed. -- @param Core.Point#COORDINATE Coordinate Coordinate where the mission is executed.
-- @return #AUFTRAG self -- @return #AUFTRAG self
function AUFTRAG:SetMissionWaypointCoord(Coordinate) function AUFTRAG:SetMissionWaypointCoord(Coordinate)
-- Obviously a zone was passed. We get the coordinate.
if Coordinate:IsInstanceOf("ZONE_BASE") then
Coordinate=Coordinate:GetCoordinate()
end
self.missionWaypointCoord=Coordinate self.missionWaypointCoord=Coordinate
return self
end
--- Set the mission egress coordinate. This is the coordinate where the assigned group will go once the mission is finished.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Egrees coordinate.
-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate.
-- @return #AUFTRAG self
function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude)
-- Obviously a zone was passed. We get the coordinate.
if Coordinate:IsInstanceOf("ZONE_BASE") then
Coordinate=Coordinate:GetCoordinate()
end
self.missionEgressCoord=Coordinate
if Altitude then
self.missionEgressCoord.y=UTILS.FeetToMeters(Altitude)
end
end
--- Get the mission egress coordinate if this was defined.
-- @param #AUFTRAG self
-- @return Core.Point#COORDINATE Coordinate Coordinate or nil.
function AUFTRAG:GetMissionEgressCoord()
return self.missionEgressCoord
end end
--- Get coordinate of target. First unit/group of the set is used. --- Get coordinate of target. First unit/group of the set is used.

View File

@ -134,8 +134,8 @@ FLIGHTGROUP = {
fuelcritical = nil, fuelcritical = nil,
fuelcriticalthresh = nil, fuelcriticalthresh = nil,
fuelcriticalrtb = false, fuelcriticalrtb = false,
outofAAMrtb = true, outofAAMrtb = false,
outofAGMrtb = true, outofAGMrtb = false,
squadron = nil, squadron = nil,
flightcontrol = nil, flightcontrol = nil,
flaghold = nil, flaghold = nil,
@ -171,10 +171,6 @@ FLIGHTGROUP.Attribute = {
OTHER="Other", OTHER="Other",
} }
--- Flight group element.
-- @type FLIGHTGROUP.Element
-- @extends Ops.OpsGroup#OPSGROUP.Element
--- FLIGHTGROUP class version. --- FLIGHTGROUP class version.
-- @field #string version -- @field #string version
FLIGHTGROUP.version="0.7.0" FLIGHTGROUP.version="0.7.0"
@ -251,9 +247,9 @@ function FLIGHTGROUP:New(group)
self:AddTransition("*", "FuelLow", "*") -- Fuel state of group is low. Default ~25%. self:AddTransition("*", "FuelLow", "*") -- Fuel state of group is low. Default ~25%.
self:AddTransition("*", "FuelCritical", "*") -- Fuel state of group is critical. Default ~10%. self:AddTransition("*", "FuelCritical", "*") -- Fuel state of group is critical. Default ~10%.
self:AddTransition("*", "OutOfMissilesAA", "*") -- Group is out of A2A missiles. self:AddTransition("*", "OutOfMissilesAA", "*") -- Group is out of A2A (air) missiles.
self:AddTransition("*", "OutOfMissilesAG", "*") -- Group is out of A2G missiles. self:AddTransition("*", "OutOfMissilesAG", "*") -- Group is out of A2G (ground) missiles.
self:AddTransition("*", "OutOfMissilesAS", "*") -- Group is out of A2S(ship) missiles. Not implemented yet! self:AddTransition("*", "OutOfMissilesAS", "*") -- Group is out of A2S (ship) missiles.
self:AddTransition("Airborne", "EngageTarget", "Engaging") -- Engage targets. self:AddTransition("Airborne", "EngageTarget", "Engaging") -- Engage targets.
self:AddTransition("Engaging", "Disengage", "Airborne") -- Engagement over. self:AddTransition("Engaging", "Disengage", "Airborne") -- Engagement over.
@ -1036,6 +1032,9 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
self:FuelCritical() self:FuelCritical()
end end
-- This causes severe problems as OutOfMissiles is called over and over again leading to many RTB calls.
if false then
-- Out of AA Missiles? CAP, GCICAP, INTERCEPT -- Out of AA Missiles? CAP, GCICAP, INTERCEPT
local CurrIsCap = false local CurrIsCap = false
-- Out of AG Missiles? BAI, SEAD, CAS, STRIKE -- Out of AG Missiles? BAI, SEAD, CAS, STRIKE
@ -1058,6 +1057,8 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
self:OutOfMissilesAG() self:OutOfMissilesAG()
end end
end
end end
--- ---
@ -1596,6 +1597,34 @@ end
function FLIGHTGROUP:onafterSpawned(From, Event, To) function FLIGHTGROUP:onafterSpawned(From, Event, To)
self:T(self.lid..string.format("Flight spawned")) self:T(self.lid..string.format("Flight spawned"))
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Flight Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Range max = %.1f km\n", self.rangemax/1000)
text=text..string.format("Ceiling = %.1f feet\n", UTILS.MetersToFeet(self.ceiling))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Tanker type = %s\n", tostring(self.tankertype))
text=text..string.format("Refuel type = %s\n", tostring(self.refueltype))
text=text..string.format("AI = %s\n", tostring(self.isAI))
text=text..string.format("Helicopter = %s\n", tostring(self.group:IsHelicopter()))
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
text=text..string.format("Uncontrolled = %s\n", tostring(self:IsUncontrolled()))
text=text..string.format("Start Air = %s\n", tostring(self:IsTakeoffAir()))
text=text..string.format("Start Cold = %s\n", tostring(self:IsTakeoffCold()))
text=text..string.format("Start Hot = %s\n", tostring(self:IsTakeoffHot()))
text=text..string.format("Start Rwy = %s\n", tostring(self:IsTakeoffRunway()))
self:I(self.lid..text)
end
-- Update position. -- Update position.
self:_UpdatePosition() self:_UpdatePosition()
@ -1858,9 +1887,10 @@ function FLIGHTGROUP:onafterArrived(From, Event, To)
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.ARRIVED) self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.ARRIVED)
end end
-- Despawn in 5 min. -- Check what to do.
if self.airwing then if self.airwing then
-- Let airwing do its thing. -- Add the asset back to the airwing.
self.airwing:AddAsset(self.group, 1)
elseif self.isLandingAtAirbase then elseif self.isLandingAtAirbase then
local Template=UTILS.DeepCopy(self.template) --DCS#Template local Template=UTILS.DeepCopy(self.template) --DCS#Template
@ -1963,7 +1993,7 @@ function FLIGHTGROUP:onafterDead(From, Event, To)
else else
if self.airwing then if self.airwing then
-- Not all assets were destroyed (despawn) ==> Add asset back to airwing. -- Not all assets were destroyed (despawn) ==> Add asset back to airwing.
self.airwing:AddAsset(self.group, 1) --self.airwing:AddAsset(self.group, 1)
end end
end end
@ -2131,7 +2161,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAA(From, Event, To)
if self.outofAAMrtb then if self.outofAAMrtb then
-- Back to destination or home. -- Back to destination or home.
local airbase=self.destbase or self.homebase local airbase=self.destbase or self.homebase
self:__RTB(-5,airbase) self:__RTB(-5, airbase)
end end
end end
@ -2145,7 +2175,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAG(From, Event, To)
if self.outofAGMrtb then if self.outofAGMrtb then
-- Back to destination or home. -- Back to destination or home.
local airbase=self.destbase or self.homebase local airbase=self.destbase or self.homebase
self:__RTB(-5,airbase) self:__RTB(-5, airbase)
end end
end end
@ -2288,20 +2318,31 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
-- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases. -- Check that coaliton is okay. We allow same (blue=blue, red=red) or landing on neutral bases.
if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then if airbase and airbase:GetCoalition()~=self.group:GetCoalition() and airbase:GetCoalition()>0 then
self:E(self.lid..string.format("ERROR: Wrong airbase coalition %d in RTB() call! We allow only same as group %d or neutral airbases 0.", airbase:GetCoalition(), self.group:GetCoalition())) self:E(self.lid..string.format("ERROR: Wrong airbase coalition %d in RTB() call! We allow only same as group %d or neutral airbases 0", airbase:GetCoalition(), self.group:GetCoalition()))
allowed=false return false
end
if self.currbase and self.currbase:GetName()==airbase:GetName() then
self:E(self.lid.."WARNING: Currbase is already same as RTB airbase. RTB canceled!")
return false
end
-- Check if the group has landed at an airbase. If so, we lost control and RTBing is not possible (only after a respawn).
if self:IsLanded() then
self:E(self.lid.."WARNING: Flight has already landed. RTB canceled!")
return false
end end
if not self.group:IsAirborne(true) then if not self.group:IsAirborne(true) then
-- this should really not happen, either the AUFTRAG is cancelled before the group was airborne or it is stuck at the ground for some reason -- this should really not happen, either the AUFTRAG is cancelled before the group was airborne or it is stuck at the ground for some reason
self:I(self.lid..string.format("WARNING: Group is not AIRBORNE ==> RTB event is suspended for 20 sec.")) self:I(self.lid..string.format("WARNING: Group is not AIRBORNE ==> RTB event is suspended for 20 sec"))
allowed=false allowed=false
Tsuspend=-20 Tsuspend=-20
local groupspeed = self.group:GetVelocityMPS() local groupspeed = self.group:GetVelocityMPS()
if groupspeed<=1 and not self:IsParking() then if groupspeed<=1 and not self:IsParking() then
self.RTBRecallCount = self.RTBRecallCount+1 self.RTBRecallCount = self.RTBRecallCount+1
end end
if self.RTBRecallCount > 6 then if self.RTBRecallCount>6 then
self:I(self.lid..string.format("WARNING: Group is not moving and was called RTB %d times. Assuming a problem and despawning!", self.RTBRecallCount)) self:I(self.lid..string.format("WARNING: Group is not moving and was called RTB %d times. Assuming a problem and despawning!", self.RTBRecallCount))
self.RTBRecallCount=0 self.RTBRecallCount=0
self:Despawn(5) self:Despawn(5)
@ -3108,103 +3149,19 @@ function FLIGHTGROUP:_InitGroup(Template)
self.tankertype=select(2, unit:IsTanker()) self.tankertype=select(2, unit:IsTanker())
self.refueltype=select(2, unit:IsRefuelable()) self.refueltype=select(2, unit:IsRefuelable())
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Flight Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Range max = %.1f km\n", self.rangemax/1000)
text=text..string.format("Ceiling = %.1f feet\n", UTILS.MetersToFeet(self.ceiling))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Tanker type = %s\n", tostring(self.tankertype))
text=text..string.format("Refuel type = %s\n", tostring(self.refueltype))
text=text..string.format("AI = %s\n", tostring(self.isAI))
text=text..string.format("Helicopter = %s\n", tostring(self.group:IsHelicopter()))
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
text=text..string.format("Uncontrolled = %s\n", tostring(self:IsUncontrolled()))
text=text..string.format("Start Air = %s\n", tostring(self:IsTakeoffAir()))
text=text..string.format("Start Cold = %s\n", tostring(self:IsTakeoffCold()))
text=text..string.format("Start Hot = %s\n", tostring(self:IsTakeoffHot()))
text=text..string.format("Start Rwy = %s\n", tostring(self:IsTakeoffRunway()))
self:I(self.lid..text)
end
--env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE)) --env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE))
--env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE)) --env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE))
-- Init done. -- Init done.
self.groupinitialized=true self.groupinitialized=true
else
self:E(self.lid.."ERROR: no unit in _InigGroup!")
end end
return self return self
end end
--- Add an element to the flight group.
-- @param #FLIGHTGROUP self
-- @param #string unitname Name of unit.
-- @return Ops.OpsGroup#OPSGROUP.Element The element or nil.
function FLIGHTGROUP:AddElementByName(unitname)
local unit=UNIT:FindByName(unitname)
if unit then
local element={} --Ops.OpsGroup#OPSGROUP.Element
element.name=unitname
element.status=OPSGROUP.ElementStatus.INUTERO
element.unit=unit
element.group=unit:GetGroup()
-- TODO: this is wrong when grouping is used!
local unittemplate=element.unit:GetTemplate()
element.modex=unittemplate.onboard_num
element.skill=unittemplate.skill
element.payload=unittemplate.payload
element.pylons=unittemplate.payload and unittemplate.payload.pylons or nil --element.unit:GetTemplatePylons()
element.fuelmass0=unittemplate.payload and unittemplate.payload.fuel or 0 --element.unit:GetTemplatePayload().fuel
element.fuelmass=element.fuelmass0
element.fuelrel=element.unit:GetFuel()
element.category=element.unit:GetUnitCategory()
element.categoryname=element.unit:GetCategoryName()
element.callsign=element.unit:GetCallsign()
element.size=element.unit:GetObjectSize()
if element.skill=="Client" or element.skill=="Player" then
element.ai=false
element.client=CLIENT:FindByName(unitname)
else
element.ai=true
end
-- Debug text.
local text=string.format("Adding element %s: status=%s, skill=%s, modex=%s, fuelmass=%.1f (%d), category=%d, categoryname=%s, callsign=%s, ai=%s",
element.name, element.status, element.skill, element.modex, element.fuelmass, element.fuelrel*100, element.category, element.categoryname, element.callsign, tostring(element.ai))
self:T(self.lid..text)
-- Add element to table.
table.insert(self.elements, element)
if unit:IsAlive() then
self:ElementSpawned(element)
end
return element
end
return nil
end
--- Check if a unit is and element of the flightgroup. --- Check if a unit is and element of the flightgroup.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self

View File

@ -648,7 +648,7 @@ end
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param #NAVYGROUP.Element Element The group element. -- @param Ops.OpsGroup#OPSGROUP.Element Element The group element.
function NAVYGROUP:onafterElementSpawned(From, Event, To, Element) function NAVYGROUP:onafterElementSpawned(From, Event, To, Element)
self:T(self.lid..string.format("Element spawned %s", Element.name)) self:T(self.lid..string.format("Element spawned %s", Element.name))
@ -665,6 +665,24 @@ end
function NAVYGROUP:onafterSpawned(From, Event, To) function NAVYGROUP:onafterSpawned(From, Event, To)
self:T(self.lid..string.format("Group spawned!")) self:T(self.lid..string.format("Group spawned!"))
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d/T=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles, self.ammo.Torpedos)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
self:I(self.lid..text)
end
-- Update position. -- Update position.
self:_UpdatePosition() self:_UpdatePosition()
@ -1200,24 +1218,6 @@ function NAVYGROUP:_InitGroup(Template)
-- Set type name. -- Set type name.
self.actype=units[1]:GetTypeName() self.actype=units[1]:GetTypeName()
-- Debug info.
if self.verbose>=1 then
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
text=text..string.format("Unit type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Weight = %.1f kg\n", self:GetWeightTotal())
text=text..string.format("Cargo bay = %.1f kg\n", self:GetFreeCargobay())
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d/T=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles, self.ammo.Torpedos)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
self:I(self.lid..text)
end
-- Init done. -- Init done.
self.groupinitialized=true self.groupinitialized=true

View File

@ -620,6 +620,7 @@ function OPSGROUP:New(group)
self:AddTransition("*", "Unloading", "*") -- Carrier is unloading the cargo. self:AddTransition("*", "Unloading", "*") -- Carrier is unloading the cargo.
self:AddTransition("*", "Unload", "*") -- Carrier unload a cargo group. self:AddTransition("*", "Unload", "*") -- Carrier unload a cargo group.
self:AddTransition("*", "Unloaded", "*") -- Carrier unloaded all its current cargo. self:AddTransition("*", "Unloaded", "*") -- Carrier unloaded all its current cargo.
self:AddTransition("*", "UnloadingDone", "*") -- Carrier is unloading the cargo.
self:AddTransition("*", "Delivered", "*") -- Carrier delivered ALL cargo of the transport assignment. self:AddTransition("*", "Delivered", "*") -- Carrier delivered ALL cargo of the transport assignment.
------------------------ ------------------------
@ -1883,13 +1884,33 @@ end
--- Check if the group is **not** cargo. --- Check if the group is **not** cargo.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #boolean CheckTransport If true or nil, also check if cargo is associated with a transport assignment. If not, we consider it not cargo. -- @param #boolean CheckTransport If `true` or `nil`, also check if cargo is associated with a transport assignment. If not, we consider it not cargo.
-- @return #boolean If true, group is *not* cargo. -- @return #boolean If true, group is *not* cargo.
function OPSGROUP:IsNotCargo(CheckTransport) function OPSGROUP:IsNotCargo(CheckTransport)
local notcargo=self.cargoStatus==OPSGROUP.CargoStatus.NOTCARGO local notcargo=self.cargoStatus==OPSGROUP.CargoStatus.NOTCARGO
if self.cargoTransportUID==nil then
--notcargo=true if notcargo then
-- Not cargo.
return true
else
-- Is cargo (e.g. loaded or boarding)
if CheckTransport then
-- Check if transport UID was set.
if self.cargoTransportUID==nil then
return true
else
-- Some transport UID was assigned.
return false
end
else
-- Is cargo.
return false
end
end end
return notcargo return notcargo
end end
@ -2398,8 +2419,12 @@ function OPSGROUP:OnEventBirth(EventData)
-- Get element. -- Get element.
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
-- Set element to spawned state. if element then
self:ElementSpawned(element)
-- Set element to spawned state.
self:ElementSpawned(element)
end
end end
@ -2412,7 +2437,7 @@ function OPSGROUP:OnEventDead(EventData)
-- Check that this is the right group. -- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
self:T(self.lid..string.format("EVENT: Unit %s dead!", EventData.IniUnitName)) self:T2(self.lid..string.format("EVENT: Unit %s dead!", EventData.IniUnitName))
local unit=EventData.IniUnit local unit=EventData.IniUnit
local group=EventData.IniGroup local group=EventData.IniGroup
@ -2421,7 +2446,7 @@ function OPSGROUP:OnEventDead(EventData)
-- Get element. -- Get element.
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
if element then if element and element.status~=OPSGROUP.ElementStatus.DEAD then
self:T(self.lid..string.format("EVENT: Element %s dead ==> destroyed", element.name)) self:T(self.lid..string.format("EVENT: Element %s dead ==> destroyed", element.name))
self:ElementDestroyed(element) self:ElementDestroyed(element)
end end
@ -2437,6 +2462,8 @@ function OPSGROUP:OnEventRemoveUnit(EventData)
-- Check that this is the right group. -- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
self:T2(self.lid..string.format("EVENT: Unit %s removed!", EventData.IniUnitName))
local unit=EventData.IniUnit local unit=EventData.IniUnit
local group=EventData.IniGroup local group=EventData.IniGroup
local unitname=EventData.IniUnitName local unitname=EventData.IniUnitName
@ -2444,7 +2471,7 @@ function OPSGROUP:OnEventRemoveUnit(EventData)
-- Get element. -- Get element.
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
if element then if element and element.status~=OPSGROUP.ElementStatus.DEAD then
self:T(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name)) self:T(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name))
self:ElementDead(element) self:ElementDead(element)
end end
@ -3053,7 +3080,12 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone}) local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
-- Set task for group. -- Set task for group.
self:SetTask(TaskFinal) -- NOTE: I am pushing the task instead of setting it as it seems to keep the mission task alive.
-- There were issues that flights did not proceed to a later waypoint because the task did not finish until the fired missiles
-- impacted (took rather long). Then the flight flew to the nearest airbase and one lost completely the control over the group.
self:PushTask(TaskFinal)
--self:SetTask(TaskFinal)
elseif Task.type==OPSGROUP.TaskType.WAYPOINT then elseif Task.type==OPSGROUP.TaskType.WAYPOINT then
-- Waypoint tasks are executed elsewhere! -- Waypoint tasks are executed elsewhere!
@ -3781,6 +3813,8 @@ function OPSGROUP:RouteToMission(mission, delay)
formation=mission.optionFormation formation=mission.optionFormation
end end
--waypointcoord:MarkToAll(string.format("Mission %s alt=%d m", mission:GetName(), waypointcoord.y))
-- Add waypoint. -- Add waypoint.
local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, formation, false) local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, formation, false)
@ -3794,6 +3828,11 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Set waypoint index. -- Set waypoint index.
mission:SetGroupWaypointIndex(self, waypoint.uid) mission:SetGroupWaypointIndex(self, waypoint.uid)
local egress=mission:GetMissionEgressCoord()
if egress then
local waypoint=self:AddWaypoint(egress, SpeedToMission, nil, formation, false)
end
--- ---
-- Mission Specific Settings -- Mission Specific Settings
--- ---
@ -4038,6 +4077,7 @@ function OPSGROUP:_SetWaypointTasks(Waypoint)
-- Check if there is mission task -- Check if there is mission task
if missiontask then if missiontask then
self:T(self.lid.."Executing mission task")
self:TaskExecute(missiontask) self:TaskExecute(missiontask)
return 1 return 1
end end
@ -5218,8 +5258,8 @@ function OPSGROUP:_CheckCargoTransport()
-- Unloading finished ==> pickup next batch or call it a day. -- Unloading finished ==> pickup next batch or call it a day.
if delivered then if delivered then
self:T(self.lid.."Unloading finished ==> Unloaded") self:T(self.lid.."Unloading finished ==> UnloadingDone")
self:Unloaded() self:UnloadingDone()
else else
self:Unloading() self:Unloading()
end end
@ -5954,7 +5994,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone. -- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
Coordinate:SetAltitude(200) Coordinate:SetAltitude(200)
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=true local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1
else else
self:E(self.lid.."ERROR: Carrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone") self:E(self.lid.."ERROR: Carrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone")
@ -5982,7 +6022,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
end end
-- NAVYGROUP -- NAVYGROUP
local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=true local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1
-- Give cruise command. -- Give cruise command.
self:__Cruise(-2) self:__Cruise(-2)
@ -6010,7 +6050,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
end end
-- ARMYGROUP -- ARMYGROUP
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=true local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1
self:__Cruise(-2) self:__Cruise(-2)
@ -6045,7 +6085,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
-- Check that group is NOT cargo and NOT acting as carrier already -- Check that group is NOT cargo and NOT acting as carrier already
-- TODO: Need a better :IsBusy() function or :IsReadyForMission() :IsReadyForBoarding() :IsReadyForTransport() -- TODO: Need a better :IsBusy() function or :IsReadyForMission() :IsReadyForBoarding() :IsReadyForTransport()
if cargo.opsgroup:IsNotCargo() and not (cargo.opsgroup:IsPickingup() or cargo.opsgroup:IsLoading() or cargo.opsgroup:IsTransporting() or cargo.opsgroup:IsUnloading()) then if cargo.opsgroup:IsNotCargo(true) and not (cargo.opsgroup:IsPickingup() or cargo.opsgroup:IsLoading() or cargo.opsgroup:IsTransporting() or cargo.opsgroup:IsUnloading()) then
-- Check if cargo is in embark/pickup zone. -- Check if cargo is in embark/pickup zone.
local inzone=self.cargoTransport.embarkzone:IsCoordinateInZone(cargo.opsgroup:GetCoordinate()) local inzone=self.cargoTransport.embarkzone:IsCoordinateInZone(cargo.opsgroup:GetCoordinate())
@ -6333,7 +6373,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone. -- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
Coordinate:SetAltitude(200) Coordinate:SetAltitude(200)
local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=true local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1
else else
self:E(self.lid.."ERROR: Carrier aircraft cannot land in Deploy zone! Specify a ZONE_AIRBASE as deploy zone") self:E(self.lid.."ERROR: Carrier aircraft cannot land in Deploy zone! Specify a ZONE_AIRBASE as deploy zone")
@ -6356,7 +6396,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
end end
-- ARMYGROUP -- ARMYGROUP
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid) ; waypoint.detour=true local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid) ; waypoint.detour=1
-- Give cruise command. -- Give cruise command.
self:Cruise() self:Cruise()
@ -6379,7 +6419,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
end end
-- NAVYGROUP -- NAVYGROUP
local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=true local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1
-- Give cruise command. -- Give cruise command.
self:Cruise() self:Cruise()
@ -6613,6 +6653,9 @@ function OPSGROUP:onafterUnload(From, Event, To, OpsGroup, Coordinate, Activated
-- Trigger "Disembarked" event. -- Trigger "Disembarked" event.
OpsGroup:Disembarked(OpsGroup:_GetMyCarrierGroup(), OpsGroup:_GetMyCarrierElement()) OpsGroup:Disembarked(OpsGroup:_GetMyCarrierGroup(), OpsGroup:_GetMyCarrierElement())
-- Trigger "Unloaded" event.
self:Unloaded(OpsGroup)
-- Remove my carrier. -- Remove my carrier.
OpsGroup:_RemoveMyCarrier() OpsGroup:_RemoveMyCarrier()
@ -6623,10 +6666,21 @@ end
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function OPSGROUP:onafterUnloaded(From, Event, To) -- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier.
function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
self:I(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName()))
end
--- On after "UnloadingDone" event.
-- @param #OPSGROUP self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
function OPSGROUP:onafterUnloadingDone(From, Event, To)
-- Debug info -- Debug info
self:T(self.lid.."Cargo unloaded..") self:T(self.lid.."Cargo unloading done..")
-- Cancel landedAt task. -- Cancel landedAt task.
if self:IsFlightgroup() and self:IsLandedAt() then if self:IsFlightgroup() and self:IsLandedAt() then
@ -6777,10 +6831,10 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
self:ClearWaypoints(self.currentwp+1) self:ClearWaypoints(self.currentwp+1)
if self.isArmygroup then if self.isArmygroup then
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=0 local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1
self:Cruise() self:Cruise()
else else
local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=0 local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1
self:Cruise() self:Cruise()
end end
@ -7216,7 +7270,7 @@ function OPSGROUP:_CheckAmmoStatus()
-- Guns. -- Guns.
if self.outofGuns and ammo.Guns>0 then if self.outofGuns and ammo.Guns>0 then
self.outoffGuns=false self.outofGuns=false
end end
if ammo.Guns==0 and self.ammo.Guns>0 and not self.outofGuns then if ammo.Guns==0 and self.ammo.Guns>0 and not self.outofGuns then
self.outofGuns=true self.outofGuns=true
@ -7225,7 +7279,7 @@ function OPSGROUP:_CheckAmmoStatus()
-- Rockets. -- Rockets.
if self.outofRockets and ammo.Rockets>0 then if self.outofRockets and ammo.Rockets>0 then
self.outoffRockets=false self.outofRockets=false
end end
if ammo.Rockets==0 and self.ammo.Rockets>0 and not self.outofRockets then if ammo.Rockets==0 and self.ammo.Rockets>0 and not self.outofRockets then
self.outofRockets=true self.outofRockets=true
@ -7234,22 +7288,50 @@ function OPSGROUP:_CheckAmmoStatus()
-- Bombs. -- Bombs.
if self.outofBombs and ammo.Bombs>0 then if self.outofBombs and ammo.Bombs>0 then
self.outoffBombs=false self.outofBombs=false
end end
if ammo.Bombs==0 and self.ammo.Bombs>0 and not self.outofBombs then if ammo.Bombs==0 and self.ammo.Bombs>0 and not self.outofBombs then
self.outofBombs=true self.outofBombs=true
self:OutOfBombs() self:OutOfBombs()
end end
-- Missiles. -- Missiles (All).
if self.outofMissiles and ammo.Missiles>0 then if self.outofMissiles and ammo.Missiles>0 then
self.outoffMissiles=false self.outofMissiles=false
end end
if ammo.Missiles==0 and self.ammo.Missiles>0 and not self.outofMissiles then if ammo.Missiles==0 and self.ammo.Missiles>0 and not self.outofMissiles then
self.outofMissiles=true self.outofMissiles=true
self:OutOfMissiles() self:OutOfMissiles()
end end
-- Missiles AA.
if self.outofMissilesAA and ammo.MissilesAA>0 then
self.outofMissilesAA=false
end
if ammo.MissilesAA and self.ammo.MissilesAA>0 and not self.outofMissilesAA then
self.outofMissilesAA=true
self:OutOfMissilesAA()
end
-- Missiles AG.
if self.outofMissilesAG and ammo.MissilesAG>0 then
self.outofMissilesAG=false
end
if ammo.MissilesAG and self.ammo.MissilesAG>0 and not self.outofMissilesAG then
self.outofMissilesAG=true
self:OutOfMissilesAG()
end
-- Missiles AS.
if self.outofMissilesAS and ammo.MissilesAS>0 then
self.outofMissilesAS=false
end
if ammo.MissilesAS and self.ammo.MissilesAS>0 and not self.outofMissilesAS then
self.outofMissilesAS=true
self:OutOfMissilesAS()
end
-- Check if group is engaging. -- Check if group is engaging.
if self:IsEngaging() and ammo.Total==0 then if self:IsEngaging() and ammo.Total==0 then
self:Disengage() self:Disengage()
@ -7725,7 +7807,7 @@ function OPSGROUP._TaskDone(group, opsgroup, task)
-- Debug message. -- Debug message.
local text=string.format("_TaskDone %s", task.description) local text=string.format("_TaskDone %s", task.description)
opsgroup:T3(opsgroup.lid..text) opsgroup:T(opsgroup.lid..text)
-- Set current task to nil so that the next in line can be executed. -- Set current task to nil so that the next in line can be executed.
if opsgroup then if opsgroup then
@ -9352,7 +9434,8 @@ function OPSGROUP:_AddElementByName(unitname)
-- Trigger spawned event if alive. -- Trigger spawned event if alive.
if unit:IsAlive() then if unit:IsAlive() then
self:ElementSpawned(element) -- 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.
self:__ElementSpawned(0.05, element)
end end
return element return element

View File

@ -849,8 +849,8 @@ function OPSTRANSPORT:onafterStatus(From, Event, To)
local carrier=cargo.opsgroup:_GetMyCarrierElement() local carrier=cargo.opsgroup:_GetMyCarrierElement()
local name=carrier and carrier.name or "none" local name=carrier and carrier.name or "none"
local cstate=carrier and carrier.status or "N/A" local cstate=carrier and carrier.status or "N/A"
text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s", text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s [UID=%s]",
cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered)) cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered), tostring(cargo.opsgroup.cargoTransportUID))
end end
text=text..string.format("\nCarriers:") text=text..string.format("\nCarriers:")

View File

@ -608,15 +608,22 @@ end
-- @return #number TACAN channel or *nil* if no channel is free. -- @return #number TACAN channel or *nil* if no channel is free.
function SQUADRON:FetchTacan() function SQUADRON:FetchTacan()
-- Get the smallest free channel if there is one.
local freechannel=nil
for channel,free in pairs(self.tacanChannel) do for channel,free in pairs(self.tacanChannel) do
if free then if free then
self:T(self.lid..string.format("Checking out Tacan channel %d", channel)) if freechannel==nil or channel<freechannel then
self.tacanChannel[channel]=false freechannel=channel
return channel end
end end
end end
return nil if freechannel then
self:T(self.lid..string.format("Checking out Tacan channel %d", freechannel))
self.tacanChannel[freechannel]=false
end
return freechannel
end end
--- "Return" a used TACAN channel. --- "Return" a used TACAN channel.