mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cc3d73c04 | ||
|
|
e541e39403 | ||
|
|
c7ea45e5fd | ||
|
|
20f28b3d2c | ||
|
|
f3f63ab8aa | ||
|
|
e91090cfff | ||
|
|
1a7fb3c13e | ||
|
|
59857ed79d | ||
|
|
4797665939 | ||
|
|
b89749036d | ||
|
|
c6268488de | ||
|
|
de04369703 | ||
|
|
05b6f19a87 | ||
|
|
2753df8216 |
@@ -47,19 +47,21 @@ function AI_CARGO:New( Carrier, CargoSet )
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
-- Board
|
||||
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||
self:AddTransition( "*", "Load", "*" )
|
||||
self:AddTransition( "*", "Reload", "*" )
|
||||
self:AddTransition( "*", "Board", "*" )
|
||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||
|
||||
self:AddTransition( "*", "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Loaded", "Board", "Loaded" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Boarding" )
|
||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
||||
-- Unload
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
self:AddTransition( "*", "Unload", "*" )
|
||||
self:AddTransition( "*", "Unboard", "*" )
|
||||
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnBeforePickup
|
||||
@@ -393,7 +395,7 @@ end
|
||||
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
||||
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
||||
|
||||
if Carrier and Carrier:IsAlive() and From == "Boarding" then
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
||||
@@ -509,7 +511,7 @@ end
|
||||
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend )
|
||||
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } )
|
||||
|
||||
if Carrier and Carrier:IsAlive() and From == "Unboarding" then
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend )
|
||||
return
|
||||
@@ -580,4 +582,3 @@ function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -98,7 +98,8 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
self:AddTransition( "*", "Guard", "Unloaded" )
|
||||
self:AddTransition( "*", "Home", "*" )
|
||||
self:AddTransition( "*", "Reload", "Boarding" )
|
||||
|
||||
self:AddTransition( "*", "Deployed", "*" )
|
||||
self:AddTransition( "*", "PickedUp", "*" )
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
|
||||
self:SetCombatRadius( CombatRadius )
|
||||
|
||||
@@ -64,21 +64,25 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
-- Boarding
|
||||
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||
self:AddTransition( "*", "Landed", "*" )
|
||||
self:AddTransition( "*", "Load", "*" )
|
||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Unboarding", "Pickup", "Unloaded" )
|
||||
self:AddTransition( "Unloaded", "Unboard", "Unloaded" )
|
||||
self:AddTransition( "Unloaded", "Unloaded", "Unloaded" )
|
||||
self:AddTransition( "*", "PickedUp", "*" )
|
||||
self:AddTransition( "*", "Landed", "*" )
|
||||
self:AddTransition( "*", "Queue", "*" )
|
||||
self:AddTransition( "*", "Orbit" , "*" )
|
||||
-- Unboarding
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
self:AddTransition( "*", "Queue", "*" )
|
||||
self:AddTransition( "*", "Orbit" , "*" )
|
||||
self:AddTransition( "*", "Destroyed", "*" )
|
||||
self:AddTransition( "*", "Unload", "*" )
|
||||
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||
|
||||
-- RTB
|
||||
self:AddTransition( "*", "Home" , "*" )
|
||||
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
@@ -207,6 +211,9 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
|
||||
self:SetCarrier( Helicopter )
|
||||
|
||||
self.landingspeed = 15 -- kph
|
||||
self.landingheight = 5.5 -- meter
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -255,6 +262,25 @@ function AI_CARGO_HELICOPTER:SetCarrier( Helicopter )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set landingspeed and -height for helicopter landings. Adjust after tracing if your helis get stuck after landing.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param #number speed Landing speed in kph(!), e.g. 15
|
||||
-- @param #number height Landing height in meters(!), e.g. 5.5
|
||||
-- @return #AI_CARGO_HELICOPTER self
|
||||
-- @usage If your choppers get stuck, add tracing to your script to determine if they hit the right parameters like so:
|
||||
--
|
||||
-- BASE:TraceOn()
|
||||
-- BASE:TraceClass("AI_CARGO_HELICOPTER")
|
||||
--
|
||||
-- Watch the DCS.log for entries stating `Helicopter:<name>, Height = Helicopter:<number>, Velocity = Helicopter:<number>`
|
||||
-- Adjust if necessary.
|
||||
function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
||||
local _speed = speed or 15
|
||||
local _height = height or 5.5
|
||||
self.landingheight = _height
|
||||
self.landingspeed = _speed
|
||||
return self
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
@@ -271,13 +297,13 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
-- 1 - When the helo lands normally on the ground.
|
||||
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
||||
-- For point 2, this is an issue, the infantry may not unload in this case!
|
||||
-- So we check if the helo is on the ground, and velocity< 5.
|
||||
-- So we check if the helo is on the ground, and velocity< 15.
|
||||
-- Only then the infantry can unload (and load too, for consistency)!
|
||||
|
||||
self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
||||
self:T( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
||||
|
||||
if self.RoutePickup == true then
|
||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
||||
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||
--self:Load( Helicopter:GetPointVec2() )
|
||||
self:Load( self.PickupZone )
|
||||
self.RoutePickup = false
|
||||
@@ -285,7 +311,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
end
|
||||
|
||||
if self.RouteDeploy == true then
|
||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
||||
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||
self:Unload( self.DeployZone )
|
||||
self.RouteDeploy = false
|
||||
end
|
||||
|
||||
@@ -1707,8 +1707,8 @@ end
|
||||
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||
-- @param #FOX self
|
||||
-- @param DCS#Weapon weapon The weapon.
|
||||
-- @return #number Notching heading right, i.e. missile heading +90<EFBFBD>
|
||||
-- @return #number Notching heading left, i.e. missile heading -90<EFBFBD>.
|
||||
-- @return #number Notching heading right, i.e. missile heading +90°.
|
||||
-- @return #number Notching heading left, i.e. missile heading -90°.
|
||||
function FOX:_GetNotchingHeadings(weapon)
|
||||
|
||||
if weapon then
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range <EFBFBD>
|
||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range °
|
||||
-- * Provide alerts when a missile would have killed your aircraft.
|
||||
-- * Provide alerts when the missile self destructs.
|
||||
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
||||
|
||||
@@ -5371,7 +5371,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
||||
|
||||
if spawnonground then
|
||||
|
||||
-- Sh<EFBFBD>ps and FARPS seem to have a build in queue.
|
||||
-- Sh°ps and FARPS seem to have a build in queue.
|
||||
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
||||
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
||||
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions: Example missions will be added later.
|
||||
-- ## Missions:
|
||||
--
|
||||
-- * [MAR - On the Range - MOOSE - SC](https://www.digitalcombatsimulator.com/en/files/3317765/) by shagrat
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -2558,7 +2560,7 @@ function RANGE:_DisplayBombTargets(_unitname)
|
||||
-- Get elevation
|
||||
local elevation=coord:GetLandHeight()
|
||||
local eltxt=string.format("%d m", elevation)
|
||||
if _settings:IsImperial() then
|
||||
if not _settings:IsMetric() then
|
||||
elevation=UTILS.MetersToFeet(elevation)
|
||||
eltxt=string.format("%d ft", elevation)
|
||||
end
|
||||
|
||||
@@ -92,7 +92,7 @@ function SEAD:New( SEADGroupPrefixes )
|
||||
end
|
||||
|
||||
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
||||
self:I("*** SEAD - Started Version 0.2.8")
|
||||
self:I("*** SEAD - Started Version 0.2.9")
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -102,7 +102,7 @@ end
|
||||
-- @return #SEAD self
|
||||
function SEAD:UpdateSet( SEADGroupPrefixes )
|
||||
|
||||
self:F( SEADGroupPrefixes )
|
||||
self:T( SEADGroupPrefixes )
|
||||
|
||||
if type( SEADGroupPrefixes ) == 'table' then
|
||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||
@@ -120,7 +120,7 @@ end
|
||||
-- @param #number range Set the engagement range in percent, e.g. 50
|
||||
-- @return self
|
||||
function SEAD:SetEngagementRange(range)
|
||||
self:F( { range } )
|
||||
self:T( { range } )
|
||||
range = range or 75
|
||||
if range < 0 or range > 100 then
|
||||
range = 75
|
||||
@@ -135,7 +135,7 @@ end
|
||||
-- @param #string WeaponName
|
||||
-- @return #boolean Returns true for a match
|
||||
function SEAD:_CheckHarms(WeaponName)
|
||||
self:F( { WeaponName } )
|
||||
self:T( { WeaponName } )
|
||||
local hit = false
|
||||
for _,_name in pairs (SEAD.Harms) do
|
||||
if string.find(WeaponName,_name,1) then hit = true end
|
||||
@@ -166,7 +166,7 @@ function SEAD:HandleEventShot( EventData )
|
||||
local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object
|
||||
if _targetUnit and _targetUnit:IsAlive() then
|
||||
local _targetMimgroup = _targetUnit:GetGroup()
|
||||
local _targetMimgroupName = _targetMimgroup:GetName() -- group name
|
||||
_targetMimgroupName = _targetMimgroup:GetName() -- group name
|
||||
--local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill
|
||||
self:T( self.SEADGroupPrefixes )
|
||||
self:T( _targetMimgroupName )
|
||||
@@ -174,6 +174,7 @@ function SEAD:HandleEventShot( EventData )
|
||||
-- see if we are shot at
|
||||
local SEADGroupFound = false
|
||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
||||
self:T( SEADGroupPrefix )
|
||||
if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then
|
||||
SEADGroupFound = true
|
||||
self:T( '*** SEAD - Group Found' )
|
||||
|
||||
@@ -725,7 +725,7 @@
|
||||
--
|
||||
-- The same holds true after the recovery window closes. The carrier will head back to the place where he left its assigned route and resume the path to the next waypoint defined in the mission editor.
|
||||
--
|
||||
-- Note that the carrier will only head into the wind, if the wind direction is different by more than 5° from the current heading of the carrier (the angled runway, if any, fis taken into account here).
|
||||
-- Note that the carrier will only head into the wind, if the wind direction is different by more than 5° from the current heading of the carrier (the angled runway, if any, fis taken into account here).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -864,10 +864,10 @@
|
||||
--
|
||||
-- The graph displays the lineup error (LUE) as a function of the distance to the carrier.
|
||||
--
|
||||
-- The pilot approaches the carrier from the port side, LUE>0°, at a distance of ~1 NM.
|
||||
-- At the beginning of the groove (X), he significantly overshoots to the starboard side (LUE<5°).
|
||||
-- The pilot approaches the carrier from the port side, LUE>0°, at a distance of ~1 NM.
|
||||
-- At the beginning of the groove (X), he significantly overshoots to the starboard side (LUE<5°).
|
||||
-- In the middle (IM), he performs good corrections and smoothly reduces the lineup error.
|
||||
-- Finally, at a distance of ~0.3 NM (IC) he has corrected his lineup with the runway to a reasonable level, |LUE|<0.5°.
|
||||
-- Finally, at a distance of ~0.3 NM (IC) he has corrected his lineup with the runway to a reasonable level, |LUE|<0.5°.
|
||||
--
|
||||
-- ## Glideslope Error
|
||||
--
|
||||
@@ -876,7 +876,7 @@
|
||||
-- The graph displays the glideslope error (GSE) as a function of the distance to the carrier.
|
||||
--
|
||||
-- In this case the pilot already enters the groove (X) below the optimal glideslope. He is not able to correct his height in the IM part and
|
||||
-- stays significantly too low. In close, he performs a harsh correction to gain altitude and ends up even slightly too high (GSE>0.5°).
|
||||
-- stays significantly too low. In close, he performs a harsh correction to gain altitude and ends up even slightly too high (GSE>0.5°).
|
||||
-- At his point further corrections are necessary.
|
||||
--
|
||||
-- ## Angle of Attack
|
||||
@@ -2438,7 +2438,7 @@ end
|
||||
-- @param #number duration Default duration of the recovery in minutes. Default 30 min.
|
||||
-- @param #number windondeck Default wind on deck in knots. Default 25 knots.
|
||||
-- @param #boolean uturn U-turn after recovery window closes on=true or off=false/nil. Default off.
|
||||
-- @param #number offset Relative Marshal radial in degrees for Case II/III recoveries. Default 30°.
|
||||
-- @param #number offset Relative Marshal radial in degrees for Case II/III recoveries. Default 30°.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetMenuRecovery(duration, windondeck, uturn, offset)
|
||||
|
||||
@@ -3878,7 +3878,7 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
-- Check if time is less than 5 minutes.
|
||||
if nextwindow.WIND and nextwindow.START-time<self.dTturn and not self.turnintowind then
|
||||
|
||||
-- Check that wind is blowing from a direction > 5° different from the current heading.
|
||||
-- Check that wind is blowing from a direction > 5° different from the current heading.
|
||||
local hdg=self:GetHeading()
|
||||
local wind=self:GetHeadingIntoWind()
|
||||
local delta=self:_GetDeltaHeading(hdg, wind)
|
||||
@@ -3896,7 +3896,7 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
end
|
||||
|
||||
--Debug info
|
||||
self:T(self.lid..string.format("Heading=%03d°, Wind=%03d° %.1f kts, Delta=%03d° ==> U-turn=%s", hdg, wind,UTILS.MpsToKnots(vwind), delta, tostring(uturn)))
|
||||
self:T(self.lid..string.format("Heading=%03d°, Wind=%03d° %.1f kts, Delta=%03d° ==> U-turn=%s", hdg, wind,UTILS.MpsToKnots(vwind), delta, tostring(uturn)))
|
||||
|
||||
-- Time into the wind 1 day or if longer recovery time + the 5 min early.
|
||||
local t=math.max(nextwindow.STOP-nextwindow.START+self.dTturn, 60*60*24)
|
||||
@@ -6933,7 +6933,7 @@ function AIRBOSS:_AddMarshalGroup(flight, stack)
|
||||
-- For case 1 we want the BRC but above routine return FB.
|
||||
radial=self:GetBRC()
|
||||
end
|
||||
local text=string.format("Select TACAN %03d°, channel %d%s (%s)", radial, self.TACANchannel,self.TACANmode, self.TACANmorse)
|
||||
local text=string.format("Select TACAN %03d°, channel %d%s (%s)", radial, self.TACANchannel,self.TACANmode, self.TACANmorse)
|
||||
self:MessageToPlayer(flight, text, nil, "")
|
||||
end
|
||||
|
||||
@@ -9346,7 +9346,7 @@ function AIRBOSS:_Initial(playerData)
|
||||
-- Hook down for students.
|
||||
if playerData.difficulty==AIRBOSS.Difficulty.EASY and playerData.actype~=AIRBOSS.AircraftCarrier.AV8B then
|
||||
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then
|
||||
hint=hint.." - Hook down, SAS on, Wing Sweep 68°!"
|
||||
hint=hint.." - Hook down, SAS on, Wing Sweep 68°!"
|
||||
else
|
||||
hint=hint.." - Hook down!"
|
||||
end
|
||||
@@ -11331,15 +11331,15 @@ function AIRBOSS:_AttitudeMonitor(playerData)
|
||||
|
||||
-- Output
|
||||
local text=string.format("Pattern step: %s", step)
|
||||
text=text..string.format("\nAoA=%.1f° = %.1f Units | |V|=%.1f knots", aoa, self:_AoADeg2Units(playerData, aoa), UTILS.MpsToKnots(vabs))
|
||||
text=text..string.format("\nAoA=%.1f° = %.1f Units | |V|=%.1f knots", aoa, self:_AoADeg2Units(playerData, aoa), UTILS.MpsToKnots(vabs))
|
||||
if self.Debug then
|
||||
-- Velocity vector.
|
||||
text=text..string.format("\nVx=%.1f Vy=%.1f Vz=%.1f m/s", velo.x, velo.y, velo.z)
|
||||
--Wind vector.
|
||||
text=text..string.format("\nWind Vx=%.1f Vy=%.1f Vz=%.1f m/s", wind.x, wind.y, wind.z)
|
||||
end
|
||||
text=text..string.format("\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw)
|
||||
text=text..string.format("\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y*196.85)
|
||||
text=text..string.format("\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw)
|
||||
text=text..string.format("\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y*196.85)
|
||||
local dist=self:_GetOptLandingCoordinate():Get3DDistance(playerData.unit)
|
||||
-- Get player velocity in km/h.
|
||||
local vplayer=playerData.unit:GetVelocityKMH()
|
||||
@@ -11360,14 +11360,14 @@ function AIRBOSS:_AttitudeMonitor(playerData)
|
||||
playerData.step==AIRBOSS.PatternStep.GROOVE_IW then
|
||||
local lue=self:_Lineup(playerData.unit, true)
|
||||
local gle=self:_Glideslope(playerData.unit)
|
||||
text=text..string.format("\nGamma=%.1f° | Rho=%.1f°", relhead, phi)
|
||||
text=text..string.format("\nLineUp=%.2f° | GlideSlope=%.2f° | AoA=%.1f Units", lue, gle, self:_AoADeg2Units(playerData, aoa))
|
||||
text=text..string.format("\nGamma=%.1f° | Rho=%.1f°", relhead, phi)
|
||||
text=text..string.format("\nLineUp=%.2f° | GlideSlope=%.2f° | AoA=%.1f Units", lue, gle, self:_AoADeg2Units(playerData, aoa))
|
||||
local grade, points, analysis=self:_LSOgrade(playerData)
|
||||
text=text..string.format("\nTgroove=%.1f sec", self:_GetTimeInGroove(playerData))
|
||||
text=text..string.format("\nGrade: %s %.1f PT - %s", grade, points, analysis)
|
||||
else
|
||||
text=text..string.format("\nR=%.2f NM | X=%d Z=%d m", UTILS.MetersToNM(rho), dx, dz)
|
||||
text=text..string.format("\nGamma=%.1f° | Rho=%.1f°", relhead, phi)
|
||||
text=text..string.format("\nGamma=%.1f° | Rho=%.1f°", relhead, phi)
|
||||
end
|
||||
|
||||
MESSAGE:New(text, 1, nil , true):ToClient(playerData.client)
|
||||
@@ -12695,7 +12695,7 @@ function AIRBOSS:_PlayerHint(playerData, delay, soundoff)
|
||||
if self.holdingoffset<0 then
|
||||
turn="left"
|
||||
end
|
||||
hint=hint..string.format("\nTurn %s and select TACAN %03d°.", turn, radial)
|
||||
hint=hint..string.format("\nTurn %s and select TACAN %03d°.", turn, radial)
|
||||
end
|
||||
|
||||
end
|
||||
@@ -12704,7 +12704,7 @@ function AIRBOSS:_PlayerHint(playerData, delay, soundoff)
|
||||
if playerData.step==AIRBOSS.PatternStep.DIRTYUP then
|
||||
if playerData.difficulty==AIRBOSS.Difficulty.EASY then
|
||||
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||
hint=hint.."\nFAF! Checks completed. Nozzles 50°."
|
||||
hint=hint.."\nFAF! Checks completed. Nozzles 50°."
|
||||
else
|
||||
--TODO: Tomcat?
|
||||
hint=hint.."\nDirty up! Hook, gear and flaps down."
|
||||
@@ -12773,14 +12773,14 @@ function AIRBOSS:_StepHint(playerData, step)
|
||||
-- Late break.
|
||||
if step==AIRBOSS.PatternStep.LATEBREAK then
|
||||
if playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then
|
||||
hint=hint.."\nWing Sweep 20°, Gear DOWN < 280 KIAS."
|
||||
hint=hint.."\nWing Sweep 20°, Gear DOWN < 280 KIAS."
|
||||
end
|
||||
end
|
||||
|
||||
-- Abeam.
|
||||
if step==AIRBOSS.PatternStep.ABEAM then
|
||||
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||
hint=hint.."\nNozzles 50°-60°. Antiskid OFF. Lights OFF."
|
||||
hint=hint.."\nNozzles 50°-60°. Antiskid OFF. Lights OFF."
|
||||
elseif playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then
|
||||
hint=hint.."\nSlats/Flaps EXTENDED < 225 KIAS. DLC SELECTED. Auto Throttle IF DESIRED."
|
||||
else
|
||||
@@ -13215,7 +13215,7 @@ function AIRBOSS:_Debrief(playerData)
|
||||
end
|
||||
|
||||
-- Re-enter message.
|
||||
local text=string.format("fly heading %03d° for %d NM to re-enter the pattern.", heading, UTILS.MetersToNM(distance))
|
||||
local text=string.format("fly heading %03d° for %d NM to re-enter the pattern.", heading, UTILS.MetersToNM(distance))
|
||||
self:MessageToPlayer(playerData, text, "LSO", nil, nil, false, 5)
|
||||
|
||||
else
|
||||
@@ -13411,9 +13411,9 @@ function AIRBOSS:_CheckCollisionCoord(coordto, coordfrom)
|
||||
|
||||
local text=""
|
||||
if clear then
|
||||
text=string.format("Path into direction %03d° is clear for the next %.1f NM.", direction, UTILS.MetersToNM(d))
|
||||
text=string.format("Path into direction %03d° is clear for the next %.1f NM.", direction, UTILS.MetersToNM(d))
|
||||
else
|
||||
text=string.format("Detected obstacle at distance %.1f NM into direction %03d°.", UTILS.MetersToNM(d), direction)
|
||||
text=string.format("Detected obstacle at distance %.1f NM into direction %03d°.", UTILS.MetersToNM(d), direction)
|
||||
end
|
||||
self:T2(self.lid..text)
|
||||
|
||||
@@ -13473,7 +13473,7 @@ function AIRBOSS:_Pathfinder()
|
||||
local collision=self:_CheckFreePathToNextWP(fromcoord)
|
||||
|
||||
-- Debug info.
|
||||
self:T2(self.lid..string.format("Pathfinder d=%.1f m, direction=%03d°, collision=%s", distance, direction, tostring(collision)))
|
||||
self:T2(self.lid..string.format("Pathfinder d=%.1f m, direction=%03d°, collision=%s", distance, direction, tostring(collision)))
|
||||
|
||||
-- If path is clear, we start a little detour.
|
||||
if not collision then
|
||||
@@ -13907,7 +13907,7 @@ function AIRBOSS:_CheckPatternUpdate()
|
||||
-- Update if carrier moves by more than 2.5 NM.
|
||||
local Dupdate=UTILS.NMToMeters(2.5)
|
||||
|
||||
-- Update if carrier turned by more than 5°.
|
||||
-- Update if carrier turned by more than 5°.
|
||||
local Hupdate=5
|
||||
|
||||
-----------------------
|
||||
@@ -13941,7 +13941,7 @@ function AIRBOSS:_CheckPatternUpdate()
|
||||
-- Check if orientation changed.
|
||||
local Hchange=false
|
||||
if math.abs(deltaHeading)>=Hupdate then
|
||||
self:T(self.lid..string.format("Carrier heading changed by %d°.", deltaHeading))
|
||||
self:T(self.lid..string.format("Carrier heading changed by %d°.", deltaHeading))
|
||||
Hchange=true
|
||||
end
|
||||
|
||||
@@ -15642,7 +15642,7 @@ end
|
||||
function AIRBOSS:_MarshalCallNewFinalBearing(FB)
|
||||
|
||||
-- Subtitle.
|
||||
local text=string.format("new final bearing %03d°.", FB)
|
||||
local text=string.format("new final bearing %03d°.", FB)
|
||||
|
||||
-- Debug message.
|
||||
self:I(self.lid..text)
|
||||
@@ -15665,7 +15665,7 @@ end
|
||||
function AIRBOSS:_MarshalCallCarrierTurnTo(hdg)
|
||||
|
||||
-- Subtitle.
|
||||
local text=string.format("carrier is now starting turn to heading %03d°.", hdg)
|
||||
local text=string.format("carrier is now starting turn to heading %03d°.", hdg)
|
||||
|
||||
-- Debug message.
|
||||
self:I(self.lid..text)
|
||||
@@ -15718,11 +15718,11 @@ function AIRBOSS:_MarshalCallRecoveryStart(case)
|
||||
-- Debug output.
|
||||
local text=string.format("Starting aircraft recovery Case %d ops.", case)
|
||||
if case==1 then
|
||||
text=text..string.format(" BRC %03d°.", self:GetBRC())
|
||||
text=text..string.format(" BRC %03d°.", self:GetBRC())
|
||||
elseif case==2 then
|
||||
text=text..string.format(" Marshal radial %03d°. BRC %03d°.", radial, self:GetBRC())
|
||||
text=text..string.format(" Marshal radial %03d°. BRC %03d°.", radial, self:GetBRC())
|
||||
elseif case==3 then
|
||||
text=text..string.format(" Marshal radial %03d°. Final heading %03d°.", radial, self:GetFinalBearing(false))
|
||||
text=text..string.format(" Marshal radial %03d°. Final heading %03d°.", radial, self:GetFinalBearing(false))
|
||||
end
|
||||
self:T(self.lid..text)
|
||||
|
||||
@@ -15767,7 +15767,7 @@ function AIRBOSS:_MarshalCallArrived(modex, case, brc, altitude, charlie, qfe)
|
||||
local CT=UTILS.Split(clock[1], ":")
|
||||
|
||||
-- Subtitle text.
|
||||
local text=string.format("Case %d, expected BRC %03d°, hold at angels %d. Expected Charlie Time %s. Altimeter %.2f. Report see me.", case, brc, angels, charlie, qfe)
|
||||
local text=string.format("Case %d, expected BRC %03d°, hold at angels %d. Expected Charlie Time %s. Altimeter %.2f. Report see me.", case, brc, angels, charlie, qfe)
|
||||
|
||||
-- Debug message.
|
||||
self:I(self.lid..text)
|
||||
@@ -15944,11 +15944,11 @@ function AIRBOSS:_AddF10Commands(_unitName)
|
||||
missionCommands.addCommandForGroup(gid, "60 min", _menusetrtime, self._SkipperRecoveryTime, self, _unitName, 60)
|
||||
missionCommands.addCommandForGroup(gid, "90 min", _menusetrtime, self._SkipperRecoveryTime, self, _unitName, 90)
|
||||
local _menusetrtime=missionCommands.addSubMenuForGroup(gid, "Set Marshal Radial", _skipperPath)
|
||||
missionCommands.addCommandForGroup(gid, "+30°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 30)
|
||||
missionCommands.addCommandForGroup(gid, "+15°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 15)
|
||||
missionCommands.addCommandForGroup(gid, "0°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 0)
|
||||
missionCommands.addCommandForGroup(gid, "-15°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, -15)
|
||||
missionCommands.addCommandForGroup(gid, "-30°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, -30)
|
||||
missionCommands.addCommandForGroup(gid, "+30°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 30)
|
||||
missionCommands.addCommandForGroup(gid, "+15°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 15)
|
||||
missionCommands.addCommandForGroup(gid, "0°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, 0)
|
||||
missionCommands.addCommandForGroup(gid, "-15°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, -15)
|
||||
missionCommands.addCommandForGroup(gid, "-30°", _menusetrtime, self._SkipperRecoveryOffset, self, _unitName, -30)
|
||||
missionCommands.addCommandForGroup(gid, "U-turn On/Off", _skipperPath, self._SkipperRecoveryUturn, self, _unitName)
|
||||
missionCommands.addCommandForGroup(gid, "Start CASE I", _skipperPath, self._SkipperStartRecovery, self, _unitName, 1)
|
||||
missionCommands.addCommandForGroup(gid, "Start CASE II", _skipperPath, self._SkipperStartRecovery, self, _unitName, 2)
|
||||
@@ -16005,7 +16005,7 @@ function AIRBOSS:_SkipperStartRecovery(_unitName, case)
|
||||
-- Inform player.
|
||||
local text=string.format("affirm, Case %d recovery will start in 5 min for %d min. Wind on deck %d knots. U-turn=%s.", case, self.skipperTime, self.skipperSpeed, tostring(self.skipperUturn))
|
||||
if case>1 then
|
||||
text=text..string.format(" Marshal radial %d°.", self.skipperOffset)
|
||||
text=text..string.format(" Marshal radial %d°.", self.skipperOffset)
|
||||
end
|
||||
if self:IsRecovering() then
|
||||
text="negative, carrier is already recovering."
|
||||
@@ -16071,7 +16071,7 @@ function AIRBOSS:_SkipperRecoveryOffset(_unitName, offset)
|
||||
if playerData then
|
||||
|
||||
-- Inform player.
|
||||
local text=string.format("roger, relative CASE II/III Marshal radial set to %d°.", offset)
|
||||
local text=string.format("roger, relative CASE II/III Marshal radial set to %d°.", offset)
|
||||
self:MessageToPlayer(playerData, text, "AIRBOSS")
|
||||
|
||||
self.skipperOffset=offset
|
||||
@@ -16534,7 +16534,7 @@ function AIRBOSS:_RequestCommence(_unitName)
|
||||
-- For case 1 we want the BRC but above routine return FB.
|
||||
radial=self:GetBRC()
|
||||
end
|
||||
text=text..string.format("\nSelect TACAN %03d°, Channel %d%s (%s).\n", radial, self.TACANchannel,self.TACANmode, self.TACANmorse)
|
||||
text=text..string.format("\nSelect TACAN %03d°, Channel %d%s (%s).\n", radial, self.TACANchannel,self.TACANmode, self.TACANmorse)
|
||||
end
|
||||
|
||||
-- TODO: Inform section members.
|
||||
@@ -17146,7 +17146,7 @@ function AIRBOSS:_DisplayCarrierInfo(_unitname)
|
||||
-- Only include current and future recovery windows.
|
||||
if Tabs<recovery.STOP then
|
||||
-- Output text.
|
||||
recoverytext=recoverytext..string.format("\n* %s - %s: Case %d (%d°)", UTILS.SecondsToClock(recovery.START), UTILS.SecondsToClock(recovery.STOP), recovery.CASE, recovery.OFFSET)
|
||||
recoverytext=recoverytext..string.format("\n* %s - %s: Case %d (%d°)", UTILS.SecondsToClock(recovery.START), UTILS.SecondsToClock(recovery.STOP), recovery.CASE, recovery.OFFSET)
|
||||
if recovery.WIND then
|
||||
recoverytext=recoverytext..string.format(" @ %.1f kts wind", recovery.SPEED)
|
||||
end
|
||||
@@ -17187,9 +17187,9 @@ function AIRBOSS:_DisplayCarrierInfo(_unitname)
|
||||
text=text..string.format("Case %d recovery ops\n", self.case)
|
||||
else
|
||||
local radial=self:GetRadial(self.case, true, true, false)
|
||||
text=text..string.format("Case %d recovery ops\nMarshal radial %03d°\n", self.case, radial)
|
||||
text=text..string.format("Case %d recovery ops\nMarshal radial %03d°\n", self.case, radial)
|
||||
end
|
||||
text=text..string.format("BRC %03d° - FB %03d°\n", self:GetBRC(), self:GetFinalBearing(true))
|
||||
text=text..string.format("BRC %03d° - FB %03d°\n", self:GetBRC(), self:GetFinalBearing(true))
|
||||
text=text..string.format("Speed %.1f kts - Wind on deck %.1f kts\n", carrierspeed, wind)
|
||||
text=text..string.format("Tower frequency %.3f MHz\n", self.TowerFreq)
|
||||
text=text..string.format("Marshal radio %.3f MHz\n", self.MarshalFreq)
|
||||
@@ -17250,10 +17250,10 @@ function AIRBOSS:_DisplayCarrierWeather(_unitname)
|
||||
local WodPA=UTILS.MpsToKnots(WodPA)
|
||||
local WodPP=UTILS.MpsToKnots(WodPP)
|
||||
|
||||
local WD=string.format('%03d°', Wd)
|
||||
local Ts=string.format("%d°C",T)
|
||||
local WD=string.format('%03d°', Wd)
|
||||
local Ts=string.format("%d°C",T)
|
||||
|
||||
local tT=string.format("%d°C",T)
|
||||
local tT=string.format("%d°C",T)
|
||||
local tW=string.format("%.1f knots", UTILS.MpsToKnots(Ws))
|
||||
local tP=string.format("%.2f inHg", UTILS.hPa2inHg(P))
|
||||
|
||||
@@ -17504,7 +17504,7 @@ function AIRBOSS:_DisplayPlayerStatus(_unitName)
|
||||
if playerData.step==AIRBOSS.PatternStep.HOLDING and playerData.case>1 then
|
||||
-- Get inverse magnetic radial potential offset.
|
||||
local radial=self:GetRadial(playerData.case, true, true, true)
|
||||
stacktext=stacktext..string.format("Select TACAN %03d°, %d DME\n", radial, angels+15)
|
||||
stacktext=stacktext..string.format("Select TACAN %03d°, %d DME\n", radial, angels+15)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17545,7 +17545,7 @@ function AIRBOSS:_DisplayPlayerStatus(_unitName)
|
||||
local brc=self:GetBRC()
|
||||
|
||||
-- Help player to find its way to the initial zone.
|
||||
text=text..string.format("\nTo Initial: Fly heading %03d° for %.1f NM and turn to BRC %03d°", flyhdg, flydist, brc)
|
||||
text=text..string.format("\nTo Initial: Fly heading %03d° for %.1f NM and turn to BRC %03d°", flyhdg, flydist, brc)
|
||||
|
||||
elseif playerData.step==AIRBOSS.PatternStep.PLATFORM then
|
||||
|
||||
@@ -17560,7 +17560,7 @@ function AIRBOSS:_DisplayPlayerStatus(_unitName)
|
||||
local hdg=self:GetRadial(playerData.case, true, true, true)
|
||||
|
||||
-- Help player to find its way to the initial zone.
|
||||
text=text..string.format("\nTo Platform: Fly heading %03d° for %.1f NM and turn to %03d°", flyhdg, flydist, hdg)
|
||||
text=text..string.format("\nTo Platform: Fly heading %03d° for %.1f NM and turn to %03d°", flyhdg, flydist, hdg)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
--- **Ops** -- Combat Search and Rescue.
|
||||
--
|
||||
-- ===
|
||||
@@ -23,7 +22,7 @@
|
||||
-- @module Ops.CSAR
|
||||
-- @image OPS_CSAR.jpg
|
||||
|
||||
-- Date: July 2021
|
||||
-- Date: Aug 2021
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||
@@ -70,6 +69,7 @@
|
||||
--
|
||||
-- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms.
|
||||
-- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only!
|
||||
-- self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
|
||||
-- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near.
|
||||
-- self.autosmokedistance = 1000 -- distance for autosmoke
|
||||
-- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates.
|
||||
@@ -95,6 +95,8 @@
|
||||
-- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
||||
-- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
||||
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
|
||||
-- -- (added 0.1.9)
|
||||
-- self.suppressmessages = false -- switch off all messaging if you want to do your own
|
||||
--
|
||||
-- ## 2.1 Experimental Features
|
||||
--
|
||||
@@ -214,26 +216,6 @@ CSAR = {
|
||||
-- @field Wrapper.Group#GROUP group Spawned group object.
|
||||
-- @field #number timestamp Timestamp for approach process
|
||||
-- @field #boolean alive Group is alive or dead/rescued
|
||||
--
|
||||
--- Updated and sorted list of known NDB beacons (in kHz!) from the available maps.
|
||||
|
||||
--[[ Moved to Utils
|
||||
-- @field #CSAR.SkipFrequencies
|
||||
CSAR.SkipFrequencies = {
|
||||
214,274,291.5,295,297.5,
|
||||
300.5,304,307,309.5,311,312,312.5,316,
|
||||
320,324,328,329,330,336,337,
|
||||
342,343,348,351,352,353,358,
|
||||
363,365,368,372.5,374,
|
||||
380,381,384,389,395,396,
|
||||
414,420,430,432,435,440,450,455,462,470,485,
|
||||
507,515,520,525,528,540,550,560,570,577,580,602,625,641,662,670,680,682,690,
|
||||
705,720,722,730,735,740,745,750,770,795,
|
||||
822,830,862,866,
|
||||
905,907,920,935,942,950,995,
|
||||
1000,1025,1030,1050,1065,1116,1175,1182,1210
|
||||
}
|
||||
--]]
|
||||
|
||||
--- All slot / Limit settings
|
||||
-- @type CSAR.AircraftType
|
||||
@@ -251,7 +233,7 @@ CSAR.AircraftType["Mi-24V"] = 8
|
||||
|
||||
--- CSAR class version.
|
||||
-- @field #string version
|
||||
CSAR.version="0.1.8r3"
|
||||
CSAR.version="0.1.10r3"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -361,6 +343,7 @@ function CSAR:New(Coalition, Template, Alias)
|
||||
self.loadtimemax = 135 -- seconds
|
||||
self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK!
|
||||
self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase
|
||||
self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
|
||||
self.max_units = 6 --max number of pilots that can be carried
|
||||
self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below
|
||||
self.csarPrefix = { "helicargo", "MEDEVAC"} -- prefixes used for useprefix=true - DON\'T use # in names!
|
||||
@@ -378,6 +361,7 @@ function CSAR:New(Coalition, Template, Alias)
|
||||
self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
||||
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
||||
self.pilotmustopendoors = false -- switch to true to enable check on open doors
|
||||
self.suppressmessages = false
|
||||
|
||||
-- WARNING - here\'ll be dragons
|
||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||
@@ -642,7 +626,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
||||
local _typeName = _typeName or "Pilot"
|
||||
|
||||
if not noMessage then
|
||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, 10)
|
||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
|
||||
end
|
||||
|
||||
if _freq then
|
||||
@@ -806,8 +790,7 @@ function CSAR:_EventHandler(EventData)
|
||||
if self:_DoubleEjection(_unitname) then
|
||||
return
|
||||
end
|
||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!", self.coalition, 10)
|
||||
--local m = MESSAGE:New("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!",10,"Info"):ToCoalition(self.coalition)
|
||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!", self.coalition, self.messageTime)
|
||||
else
|
||||
self:T(self.lid .. " Pilot has not taken off, ignore")
|
||||
end
|
||||
@@ -894,11 +877,14 @@ function CSAR:_EventHandler(EventData)
|
||||
end
|
||||
|
||||
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
|
||||
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true)
|
||||
--[[
|
||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_event.IniUnitName) then
|
||||
self:_DisplayMessageToSAR(_unit, "Open the door to let me out!", self.messageTime, true)
|
||||
else
|
||||
self:_RescuePilots(_unit)
|
||||
end
|
||||
--]]
|
||||
else
|
||||
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
|
||||
end
|
||||
@@ -1112,7 +1098,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam
|
||||
player = grouptable.player,
|
||||
}
|
||||
|
||||
_woundedGroup:Destroy()
|
||||
_woundedGroup:Destroy(false)
|
||||
self:_RemoveNameFromDownedPilots(_woundedGroupName,true)
|
||||
|
||||
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true)
|
||||
@@ -1143,6 +1129,8 @@ end
|
||||
-- @return #boolean outcome The outcome.
|
||||
function CSAR:_IsLoadingDoorOpen( unit_name )
|
||||
self:T(self.lid .. " _IsLoadingDoorOpen")
|
||||
|
||||
--[[
|
||||
local ret_val = false
|
||||
local unit = Unit.getByName(unit_name)
|
||||
if unit ~= nil then
|
||||
@@ -1174,8 +1162,9 @@ function CSAR:_IsLoadingDoorOpen( unit_name )
|
||||
return ret_val
|
||||
|
||||
end -- nil
|
||||
--]]
|
||||
return UTILS.IsLoadingDoorOpen(unit_name)
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--- (Internal) Function to check if heli is close to group.
|
||||
@@ -1314,7 +1303,8 @@ end
|
||||
-- @param #CSAR self
|
||||
-- @param #string heliname Heli name
|
||||
-- @param #string groupname Group name
|
||||
function CSAR:_ScheduledSARFlight(heliname,groupname)
|
||||
-- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP
|
||||
function CSAR:_ScheduledSARFlight(heliname,groupname, isairport)
|
||||
self:T(self.lid .. " _ScheduledSARFlight")
|
||||
self:T({heliname,groupname})
|
||||
local _heliUnit = self:_GetSARHeli(heliname)
|
||||
@@ -1337,8 +1327,8 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
|
||||
return
|
||||
end
|
||||
|
||||
if _dist < 200 and _heliUnit:InAir() == false then
|
||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(heliname) then
|
||||
if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then
|
||||
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then
|
||||
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true)
|
||||
else
|
||||
self:_RescuePilots(_heliUnit)
|
||||
@@ -1347,7 +1337,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
|
||||
end
|
||||
|
||||
--queue up
|
||||
self:__Returning(-5,heliname,_woundedGroupName)
|
||||
self:__Returning(-5,heliname,_woundedGroupName, isairport)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1403,7 +1393,9 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak)
|
||||
local group = _unit:GetGroup()
|
||||
local _clear = _clear or nil
|
||||
local _time = _time or self.messageTime
|
||||
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
|
||||
if not self.suppressmessages then
|
||||
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
|
||||
end
|
||||
-- integrate SRS
|
||||
if _speak and self.useSRS then
|
||||
local srstext = SOUNDTEXT:New(_text)
|
||||
@@ -1501,10 +1493,17 @@ function CSAR:_GetClosestDownedPilot(_heli)
|
||||
local _shortestDistance = -1
|
||||
local _distance = 0
|
||||
local _closestGroupInfo = nil
|
||||
local _heliCoord = _heli:GetCoordinate()
|
||||
local _heliCoord = _heli:GetCoordinate() or _heli:GetCoordinate()
|
||||
|
||||
if _heliCoord == nil then
|
||||
self:E("****Error obtaining coordinate!")
|
||||
return nil
|
||||
end
|
||||
|
||||
local DownedPilotsTable = self.downedPilots
|
||||
for _, _groupInfo in pairs(DownedPilotsTable) do
|
||||
|
||||
for _, _groupInfo in UTILS.spairs(DownedPilotsTable) do
|
||||
--for _, _groupInfo in pairs(DownedPilotsTable) do
|
||||
local _woundedName = _groupInfo.name
|
||||
local _tempWounded = _groupInfo.group
|
||||
|
||||
@@ -1570,12 +1569,11 @@ end
|
||||
-- @param #number _messagetime How long to show.
|
||||
function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
|
||||
self:T(self.lid .. " _DisplayToAllSAR")
|
||||
local messagetime = _messagetime or self.messageTime
|
||||
for _, _unitName in pairs(self.csarUnits) do
|
||||
local _unit = self:_GetSARHeli(_unitName)
|
||||
if _unit then
|
||||
if not _messagetime then
|
||||
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
|
||||
end
|
||||
if _unit and not self.suppressmessages then
|
||||
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
|
||||
end
|
||||
end
|
||||
return self
|
||||
@@ -1747,9 +1745,21 @@ end
|
||||
function CSAR:_GetDistance(_point1, _point2)
|
||||
self:T(self.lid .. " _GetDistance")
|
||||
if _point1 and _point2 then
|
||||
local distance = _point1:DistanceFromPointVec2(_point2)
|
||||
return distance
|
||||
local distance1 = _point1:Get2DDistance(_point2)
|
||||
local distance2 = _point1:DistanceFromPointVec2(_point2)
|
||||
self:I({dist1=distance1, dist2=distance2})
|
||||
if distance1 and type(distance1) == "number" then
|
||||
return distance1
|
||||
elseif distance2 and type(distance2) == "number" then
|
||||
return distance2
|
||||
else
|
||||
self:E("*****Cannot calculate distance!")
|
||||
self:E({_point1,_point2})
|
||||
return -1
|
||||
end
|
||||
else
|
||||
self:E("******Cannot calculate distance!")
|
||||
self:E({_point1,_point2})
|
||||
return -1
|
||||
end
|
||||
end
|
||||
@@ -1915,19 +1925,19 @@ end
|
||||
-- @param #CSAR self
|
||||
function CSAR:_CheckDownedPilotTable()
|
||||
local pilots = self.downedPilots
|
||||
for _,_entry in pairs (pilots) do
|
||||
self:T("Checking for " .. _entry.name)
|
||||
self:T({entry=_entry})
|
||||
local group = _entry.group
|
||||
if not group:IsAlive() then
|
||||
self:T("Group is dead")
|
||||
if _entry.alive == true then
|
||||
self:T("Switching .alive to false")
|
||||
local npilots = {}
|
||||
|
||||
for _ind,_entry in pairs(pilots) do
|
||||
local _group = _entry.group
|
||||
if _group:IsAlive() then
|
||||
npilots[_ind] = _entry
|
||||
else
|
||||
if _entry.alive then
|
||||
self:__KIA(1,_entry.desc)
|
||||
self:_RemoveNameFromDownedPilots(_entry.name,true)
|
||||
end
|
||||
end
|
||||
end
|
||||
self.downedPilots = npilots
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2047,9 +2057,10 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #string Heliname Name of the helicopter group.
|
||||
-- @param #string Woundedgroupname Name of the downed pilot\'s group.
|
||||
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname)
|
||||
-- @param #boolean IsAirport True if heli has landed on an AFB (from event land).
|
||||
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname, IsAirPort)
|
||||
self:T({From, Event, To, Heliname, Woundedgroupname})
|
||||
self:_ScheduledSARFlight(Heliname,Woundedgroupname)
|
||||
self:_ScheduledSARFlight(Heliname,Woundedgroupname, IsAirPort)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
-- @module Ops.CTLD
|
||||
-- @image OPS_CTLD.jpg
|
||||
|
||||
-- Date: July 2021
|
||||
-- Date: Aug 2021
|
||||
|
||||
do
|
||||
------------------------------------------------------
|
||||
@@ -264,7 +264,7 @@ do
|
||||
-- Add zones for loading troops and crates and dropping, building crates
|
||||
--
|
||||
-- -- Add a zone of type LOAD to our setup. Players can load troops and crates.
|
||||
-- -- "Loadzone" is the name of the zone from the ME. Players can load, if they are inside of the zone.
|
||||
-- -- "Loadzone" is the name of the zone from the ME. Players can load, if they are inside the zone.
|
||||
-- -- Smoke and Flare color for this zone is blue, it is active (can be used) and has a radio beacon.
|
||||
-- my_ctld:AddCTLDZone("Loadzone",CTLD.CargoZoneType.LOAD,SMOKECOLOR.Blue,true,true)
|
||||
--
|
||||
@@ -279,6 +279,13 @@ do
|
||||
--
|
||||
-- my_ctld:AddCTLDZone("Movezone2",CTLD.CargoZoneType.MOVE,SMOKECOLOR.White,true,true)
|
||||
--
|
||||
-- -- Add a zone of type SHIP to our setup. Players can load troops and crates from this ship
|
||||
-- -- "Tarawa" is the unitname (callsign) of the ship from the ME. Players can load, if they are inside the zone.
|
||||
-- -- The ship is 240 meters long and 20 meters wide.
|
||||
-- -- Note that smoke, flares, beacons don't work for this type of loadzone (yet). Also, you need to adjust
|
||||
-- -- the max hover height to deck height plus 5 meters or so for loading to work.
|
||||
-- -- When the ship is moving, forcing hoverload might not be a good idea.
|
||||
-- my_ctld:AddCTLDZone("Tarawa",CTLD.CargoZoneType.SHIP,SMOKECOLOR.Blue,true,true,240,20)
|
||||
--
|
||||
-- ## 2. Options
|
||||
--
|
||||
@@ -511,11 +518,13 @@ CTLD = {
|
||||
-- @field #string name Name of Zone.
|
||||
-- @field #string color Smoke color for zone, e.g. SMOKECOLOR.Red.
|
||||
-- @field #boolean active Active or not.
|
||||
-- @field #string type Type of zone, i.e. load,drop,move
|
||||
-- @field #string type Type of zone, i.e. load,drop,move,ship
|
||||
-- @field #boolean hasbeacon Create and run radio beacons if active.
|
||||
-- @field #table fmbeacon Beacon info as #CTLD.ZoneBeacon
|
||||
-- @field #table uhfbeacon Beacon info as #CTLD.ZoneBeacon
|
||||
-- @field #table vhfbeacon Beacon info as #CTLD.ZoneBeacon
|
||||
-- @field #number shiplength For ships - length of ship
|
||||
-- @field #number shipwidth For ships - width of ship
|
||||
|
||||
--- Zone Type Info.
|
||||
-- @type CTLD.CargoZoneType
|
||||
@@ -523,6 +532,7 @@ CTLD.CargoZoneType = {
|
||||
LOAD = "load",
|
||||
DROP = "drop",
|
||||
MOVE = "move",
|
||||
SHIP = "ship",
|
||||
}
|
||||
|
||||
--- Buildable table info.
|
||||
@@ -557,7 +567,7 @@ CTLD.UnitTypes = {
|
||||
|
||||
--- CTLD class version.
|
||||
-- @field #string version
|
||||
CTLD.version="0.1.4r3"
|
||||
CTLD.version="0.1.5a1"
|
||||
|
||||
--- Instantiate a new CTLD.
|
||||
-- @param #CTLD self
|
||||
@@ -643,6 +653,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
self.pickupZones = {}
|
||||
self.dropOffZones = {}
|
||||
self.wpZones = {}
|
||||
self.shipZones = {}
|
||||
|
||||
-- Cargo
|
||||
self.Cargo_Crates = {}
|
||||
@@ -659,6 +670,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
|
||||
-- setup
|
||||
self.CrateDistance = 30 -- list/load crates in this radius
|
||||
self.ExtractFactor = 3.33 -- factor for troops extraction, i.e. CrateDistance * Extractfactor
|
||||
self.prefixes = Prefixes or {"Cargoheli"}
|
||||
--self.I({prefixes = self.prefixes})
|
||||
self.useprefix = true
|
||||
@@ -927,6 +939,9 @@ function CTLD:_LoadTroops(Group, Unit, Cargotype)
|
||||
local hoverload = self:CanHoverLoad(Unit)
|
||||
-- check if we are in LOAD zone
|
||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||
if not inzone then
|
||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||
end
|
||||
if not inzone then
|
||||
self:_SendMessage("You are not close enough to a logistics zone!", 10, false, Group)
|
||||
if not self.debug then return self end
|
||||
@@ -1117,7 +1132,9 @@ end
|
||||
end
|
||||
end
|
||||
|
||||
if nearestGroup == nil or nearestDistance > self.CrateDistance then
|
||||
local extractdistance = self.CrateDistance * self.ExtractFactor
|
||||
|
||||
if nearestGroup == nil or nearestDistance > extractdistance then
|
||||
self:_SendMessage("No units close enough to extract!", 10, false, Group)
|
||||
return self
|
||||
end
|
||||
@@ -1165,7 +1182,7 @@ end
|
||||
|
||||
-- clean up:
|
||||
table.remove(self.DroppedTroops, nearestGroupIndex)
|
||||
nearestGroup:Destroy()
|
||||
nearestGroup:Destroy(false)
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -1183,8 +1200,13 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
|
||||
-- check if we are in LOAD zone
|
||||
local inzone = false
|
||||
local drop = drop or false
|
||||
local ship = nil
|
||||
local width = 20
|
||||
if not drop then
|
||||
inzone = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||
if not inzone then
|
||||
inzone, ship, zone, distance, width = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||
end
|
||||
else
|
||||
if self.dropcratesanywhere then -- #1570
|
||||
inzone = true
|
||||
@@ -1230,7 +1252,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
|
||||
for i=1,50 do
|
||||
math.random(90,270)
|
||||
end
|
||||
local rheading = math.floor(math.random(90,270) * heading + 1 / 360)
|
||||
local rheading = math.floor(((math.random(90,270) * heading) + 1) / 360)
|
||||
if not IsHerc then
|
||||
rheading = rheading + 180 -- mirror for Helis
|
||||
end
|
||||
@@ -1238,10 +1260,25 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
|
||||
local cratecoord = position:Translate(cratedistance,rheading)
|
||||
local cratevec2 = cratecoord:GetVec2()
|
||||
self.CrateCounter = self.CrateCounter + 1
|
||||
if type(ship) == "string" then
|
||||
self:T("Spawning on ship "..ship)
|
||||
local Ship = UNIT:FindByName(ship)
|
||||
local shipcoord = Ship:GetCoordinate()
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local dist = shipcoord:Get2DDistance(unitcoord)
|
||||
dist = dist - (20 + math.random(1,10))
|
||||
local width = width / 2
|
||||
local Offy = math.random(-width,width)
|
||||
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType("container_cargo","Cargos",country.id.GERMANY)
|
||||
--:InitCoordinate(cratecoord)
|
||||
:InitLinkToUnit(Ship,dist,Offy,0)
|
||||
:Spawn(270,cratealias)
|
||||
else
|
||||
self.Spawned_Crates[self.CrateCounter] = SPAWNSTATIC:NewFromType("container_cargo","Cargos",country.id.GERMANY)
|
||||
:InitCoordinate(cratecoord)
|
||||
--:InitLinkToUnit(Unit,OffsetX,OffsetY,OffsetAngle)
|
||||
:Spawn(270,cratealias)
|
||||
|
||||
end
|
||||
local templ = cargotype:GetTemplates()
|
||||
local sorte = cargotype:GetType()
|
||||
self.CargoCounter = self.CargoCounter +1
|
||||
@@ -1390,8 +1427,13 @@ function CTLD:_LoadCratesNearby(Group, Unit)
|
||||
-- get nearby crates
|
||||
local finddist = self.CrateDistance or 30
|
||||
local nearcrates,number = self:_FindCratesNearby(Group,Unit,finddist) -- #table
|
||||
if number == 0 or numberonboard == cratelimit then
|
||||
self:_SendMessage("Sorry no loadable crates nearby or fully loaded!", 10, false, Group)
|
||||
if number == 0 and self.hoverautoloading then
|
||||
return -- exit
|
||||
elseif number == 0 then
|
||||
self:_SendMessage("Sorry no loadable crates nearby!", 10, false, Group)
|
||||
return -- exit
|
||||
elseif numberonboard == cratelimit then
|
||||
self:_SendMessage("Sorry no fully loaded!", 10, false, Group)
|
||||
return -- exit
|
||||
else
|
||||
-- go through crates and load
|
||||
@@ -1415,14 +1457,14 @@ function CTLD:_LoadCratesNearby(Group, Unit)
|
||||
table.insert(loaded.Cargo, crate)
|
||||
table.insert(crateidsloaded,crate:GetID())
|
||||
-- destroy crate
|
||||
crate:GetPositionable():Destroy()
|
||||
crate:GetPositionable():Destroy(false)
|
||||
crate.Positionable = nil
|
||||
self:_SendMessage(string.format("Crate ID %d for %s loaded!",crate:GetID(),crate:GetName()), 10, false, Group)
|
||||
self:_UpdateUnitCargoMass(Unit)
|
||||
self:__CratesPickedUp(1, Group, Unit, crate)
|
||||
end
|
||||
end
|
||||
self.Loaded_Cargo[unitname] = loaded
|
||||
self:_UpdateUnitCargoMass(Unit)
|
||||
-- clean up real world crates
|
||||
local existingcrates = self.Spawned_Cargo -- #table
|
||||
local newexcrates = {}
|
||||
@@ -1474,9 +1516,10 @@ function CTLD:_UpdateUnitCargoMass(Unit)
|
||||
self:T(self.lid .. " _UpdateUnitCargoMass")
|
||||
local calculatedMass = self:_GetUnitCargoMass(Unit)
|
||||
Unit:SetUnitInternalCargo(calculatedMass)
|
||||
local report = REPORT:New("Loadmaster report")
|
||||
report:Add("Carrying " .. calculatedMass .. "Kg")
|
||||
self:_SendMessage(report:Text(),10,false,Unit:GetGroup())
|
||||
--local report = REPORT:New("Loadmaster report")
|
||||
--report:Add("Carrying " .. calculatedMass .. "Kg")
|
||||
--self:_SendMessage(report:Text(),10,false,Unit:GetGroup())
|
||||
return self
|
||||
end
|
||||
|
||||
--- (Internal) Function to list loaded cargo.
|
||||
@@ -1557,6 +1600,9 @@ function CTLD:_UnloadTroops(Group, Unit)
|
||||
-- check if we are in LOAD zone
|
||||
local droppingatbase = false
|
||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||
if not inzone then
|
||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||
end
|
||||
if inzone then
|
||||
droppingatbase = true
|
||||
end
|
||||
@@ -1893,17 +1939,16 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
|
||||
end
|
||||
for _,_template in pairs(temptable) do
|
||||
self.TroopCounter = self.TroopCounter + 1
|
||||
if canmove then
|
||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(true,20,2)
|
||||
:InitDelayOff()
|
||||
:SpawnFromVec2(randomcoord)
|
||||
if canmove then
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
:InitRandomizeUnits(true,20,2)
|
||||
:InitDelayOff()
|
||||
:SpawnFromVec2(randomcoord)
|
||||
else -- don't random position of e.g. SAM units build as FOB
|
||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||
--:InitRandomizeUnits(true,20,2)
|
||||
:InitDelayOff()
|
||||
:SpawnFromVec2(randomcoord)
|
||||
:InitDelayOff()
|
||||
:SpawnFromVec2(randomcoord)
|
||||
end
|
||||
if self.movetroopstowpzone and canmove then
|
||||
self:_MoveGroupToZone(self.DroppedTroops[self.TroopCounter])
|
||||
@@ -1967,7 +2012,7 @@ function CTLD:_CleanUpCrates(Crates,Build,Number)
|
||||
if name == nametype then -- matching crate type
|
||||
table.insert(destIDs,thisID)
|
||||
found = found + 1
|
||||
nowcrate:GetPositionable():Destroy()
|
||||
nowcrate:GetPositionable():Destroy(false)
|
||||
nowcrate.Positionable = nil
|
||||
end
|
||||
if found == numberdest then break end -- got enough
|
||||
@@ -2133,6 +2178,8 @@ function CTLD:AddZone(Zone)
|
||||
table.insert(self.pickupZones,zone)
|
||||
elseif zone.type == CTLD.CargoZoneType.DROP then
|
||||
table.insert(self.dropOffZones,zone)
|
||||
elseif zone.type == CTLD.CargoZoneType.SHIP then
|
||||
table.insert(self.shipZones,zone)
|
||||
else
|
||||
table.insert(self.wpZones,zone)
|
||||
end
|
||||
@@ -2158,6 +2205,8 @@ function CTLD:ActivateZone(Name,ZoneType,NewState)
|
||||
table = self.pickupZones
|
||||
elseif ZoneType == CTLD.CargoZoneType.DROP then
|
||||
table = self.dropOffZones
|
||||
elseif ZoneType == CTLD.CargoZoneType.SHIP then
|
||||
table = self.shipZones
|
||||
else
|
||||
table = self.wpZones
|
||||
end
|
||||
@@ -2255,8 +2304,10 @@ end
|
||||
-- @param #number Color Smoke/Flare color e.g. #SMOKECOLOR.Red
|
||||
-- @param #string Active Is this zone currently active?
|
||||
-- @param #string HasBeacon Does this zone have a beacon if it is active?
|
||||
-- @param #number Shiplength Length of Ship for shipzones
|
||||
-- @param #number Shipwidth Width of Ship for shipzones
|
||||
-- @return #CTLD self
|
||||
function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon)
|
||||
function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon, Shiplength, Shipwidth)
|
||||
self:T(self.lid .. " AddCTLDZone")
|
||||
|
||||
local ctldzone = {} -- #CTLD.CargoZone
|
||||
@@ -2276,6 +2327,11 @@ function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon)
|
||||
ctldzone.vhfbeacon = nil
|
||||
end
|
||||
|
||||
if Type == CTLD.CargoZoneType.SHIP then
|
||||
ctldzone.shiplength = Shiplength or 100
|
||||
ctldzone.shipwidth = Shipwidth or 10
|
||||
end
|
||||
|
||||
self:AddZone(ctldzone)
|
||||
return self
|
||||
end
|
||||
@@ -2367,10 +2423,12 @@ end
|
||||
-- @param #CTLD.CargoZoneType Zonetype Zonetype
|
||||
-- @return #boolean Outcome Is in zone or not
|
||||
-- @return #string name Closest zone name
|
||||
-- @return #string zone Closest Core.Zone#ZONE object
|
||||
-- @return Core.Zone#ZONE zone Closest Core.Zone#ZONE object
|
||||
-- @return #number distance Distance to closest zone
|
||||
-- @return #number width Radius of zone or width of ship
|
||||
function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
self:T(self.lid .. " IsUnitInZone")
|
||||
self:T(Zonetype)
|
||||
local unitname = Unit:GetName()
|
||||
local zonetable = {}
|
||||
local outcome = false
|
||||
@@ -2378,6 +2436,8 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
zonetable = self.pickupZones -- #table
|
||||
elseif Zonetype == CTLD.CargoZoneType.DROP then
|
||||
zonetable = self.dropOffZones -- #table
|
||||
elseif Zonetype == CTLD.CargoZoneType.SHIP then
|
||||
zonetable = self.shipZones -- #table
|
||||
else
|
||||
zonetable = self.wpZones -- #table
|
||||
end
|
||||
@@ -2386,16 +2446,29 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
local colorret = nil
|
||||
local maxdist = 1000000 -- 100km
|
||||
local zoneret = nil
|
||||
local zonewret = nil
|
||||
local zonenameret = nil
|
||||
for _,_cargozone in pairs(zonetable) do
|
||||
local czone = _cargozone -- #CTLD.CargoZone
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
local zonename = czone.name
|
||||
local zone = ZONE:FindByName(zonename)
|
||||
zonecoord = zone:GetCoordinate()
|
||||
local active = czone.active
|
||||
local color = czone.color
|
||||
local zoneradius = zone:GetRadius()
|
||||
local zone = nil
|
||||
local zoneradius = 100
|
||||
local zonewidth = 20
|
||||
if Zonetype == CTLD.CargoZoneType.SHIP then
|
||||
self:T("Checking Type Ship: "..zonename)
|
||||
zone = UNIT:FindByName(zonename)
|
||||
zonecoord = zone:GetCoordinate()
|
||||
zoneradius = czone.shiplength
|
||||
zonewidth = czone.shipwidth
|
||||
else
|
||||
zone = ZONE:FindByName(zonename)
|
||||
zonecoord = zone:GetCoordinate()
|
||||
zoneradius = zone:GetRadius()
|
||||
zonewidth = zoneradius
|
||||
end
|
||||
local distance = self:_GetDistance(zonecoord,unitcoord)
|
||||
if distance <= zoneradius and active then
|
||||
outcome = true
|
||||
@@ -2404,10 +2477,15 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
||||
maxdist = distance
|
||||
zoneret = zone
|
||||
zonenameret = zonename
|
||||
zonewret = zonewidth
|
||||
colorret = color
|
||||
end
|
||||
end
|
||||
return outcome, zonenameret, zoneret, maxdist
|
||||
if Zonetype == CTLD.CargoZoneType.SHIP then
|
||||
return outcome, zonenameret, zoneret, maxdist, zonewret
|
||||
else
|
||||
return outcome, zonenameret, zoneret, maxdist
|
||||
end
|
||||
end
|
||||
|
||||
--- User function - Start smoke in a zone close to the Unit.
|
||||
@@ -2590,6 +2668,9 @@ end
|
||||
self:T(self.lid .. " CanHoverLoad")
|
||||
if self:IsHercules(Unit) then return false end
|
||||
local outcome = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) and self:IsCorrectHover(Unit)
|
||||
if not outcome then
|
||||
outcome = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP) --and self:IsCorrectHover(Unit)
|
||||
end
|
||||
return outcome
|
||||
end
|
||||
|
||||
@@ -2651,7 +2732,7 @@ end
|
||||
if self.hoverautoloading then
|
||||
for _,_pilot in pairs (self.CtldUnits) do
|
||||
local Unit = UNIT:FindByName(_pilot)
|
||||
self:AutoHoverLoad(Unit)
|
||||
if self:CanHoverLoad(Unit) then self:AutoHoverLoad(Unit) end
|
||||
end
|
||||
end
|
||||
return self
|
||||
@@ -2683,7 +2764,7 @@ end
|
||||
-- @return #CTLD self
|
||||
function CTLD:onafterStart(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
self:I(self.lid .. "Started.")
|
||||
self:I(self.lid .. "Started ("..self.version..")")
|
||||
if self.useprefix or self.enableHercules then
|
||||
local prefix = self.prefixes
|
||||
if self.enableHercules then
|
||||
|
||||
@@ -162,33 +162,32 @@ RADIOSPEECH.Vocabulary.RU = {
|
||||
["8000"] = { "8000", 0.92 },
|
||||
["9000"] = { "9000", 0.87 },
|
||||
|
||||
["Ñ<EFBFBD>тепени"] = { "degrees", 0.5 },
|
||||
["километров"] = { "kilometers", 0.65 },
|
||||
["градусы"] = { "degrees", 0.5 },
|
||||
["километры"] = { "kilometers", 0.65 },
|
||||
["km"] = { "kilometers", 0.65 },
|
||||
["миль"] = { "miles", 0.45 },
|
||||
["мили"] = { "miles", 0.45 },
|
||||
["mi"] = { "miles", 0.45 },
|
||||
["метры"] = { "meters", 0.41 },
|
||||
["метров"] = { "meters", 0.41 },
|
||||
["m"] = { "meters", 0.41 },
|
||||
["ноги"] = { "feet", 0.37 },
|
||||
["ноги"] = { "feet", 0.37 },
|
||||
|
||||
["br"] = { "br", 1.1 },
|
||||
["bra"] = { "bra", 0.3 },
|
||||
|
||||
["возвращение на базу"] = { "returning_to_base", 1.40 },
|
||||
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
||||
["перехват боги"] = { "intercepting_bogeys", 1.22 },
|
||||
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
||||
["привлечение болотных птиц"] = { "engaging_bogeys", 1.68 },
|
||||
["колёса вверх..."] = { "wheels_up", 0.92 },
|
||||
["посадка на базу"] = { "landing at base", 1.04 },
|
||||
["патрулирование"] = { "patrolling", 0.96 },
|
||||
|
||||
["возвращаÑ<EFBFBD>Ñ<EFBFBD>ÑŒ на базу"] = { "returning_to_base", 1.40 },
|
||||
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
||||
["перехват Ñ<>амолетов"] = { "intercepting_bogeys", 1.22 },
|
||||
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
||||
["захватывающие Ñ<>амолеты"] = { "engaging_bogeys", 1.68 },
|
||||
["колеÑ<EFBFBD>а вверх"] = { "wheels_up", 0.92 },
|
||||
["поÑ<EFBFBD>адка на базу"] = { "landing at base", 1.04 },
|
||||
["патрулирующий"] = { "patrolling", 0.96 },
|
||||
|
||||
["за"] = { "for", 0.27 },
|
||||
["и"] = { "and", 0.17 },
|
||||
["в"] = { "at", 0.19 },
|
||||
["dot"] = { "dot", 0.51 },
|
||||
["defender"] = { "defender", 0.45 },
|
||||
["для"] = { "for", 0.27 },
|
||||
["и"] = { "and", 0.17 },
|
||||
["на сайте"] = { "at", 0.19 },
|
||||
["точка"] = { "dot", 0.51 },
|
||||
["защитник"] = { "defender", 0.45 },
|
||||
}
|
||||
|
||||
--- Create a new RADIOSPEECH object for a given radio frequency/modulation.
|
||||
|
||||
@@ -491,7 +491,7 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
|
||||
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
||||
end
|
||||
|
||||
-- 024<EFBFBD> 23' 12"N or 024<EFBFBD> 23' 12.03"N
|
||||
-- 024° 23' 12"N or 024° 23' 12.03"N
|
||||
return string.format('%03d°', latDeg)..string.format('%02d', latMin)..'\''..string.format(secFrmtStr, latSec)..'"'..latHemi..' '
|
||||
.. string.format('%03d°', lonDeg)..string.format('%02d', lonMin)..'\''..string.format(secFrmtStr, lonSec)..'"'..lonHemi
|
||||
|
||||
@@ -1510,7 +1510,7 @@ end
|
||||
--@return #table
|
||||
function UTILS.ShuffleTable(t)
|
||||
if t == nil or type(t) ~= "table" then
|
||||
BASE:I("Error in ShuffleTable: Missing or wrong tyåe of Argument")
|
||||
BASE:I("Error in ShuffleTable: Missing or wrong type of Argument")
|
||||
return
|
||||
end
|
||||
math.random()
|
||||
@@ -1535,8 +1535,8 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
||||
if unit ~= nil then
|
||||
local type_name = unit:getTypeName()
|
||||
|
||||
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
||||
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
||||
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
||||
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
||||
ret_val = true
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user