Merge remote-tracking branch 'origin/develop' into develop

This commit is contained in:
Ben Birch 2021-08-22 12:54:25 +10:00
commit a68eeae9bd
14 changed files with 278 additions and 152 deletions

View File

@ -3477,7 +3477,7 @@ do -- AI_A2A_DISPATCHER
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " wheels up.", DefenderGroup )
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " колеÑ<EFBFBD>а вверх.", DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " колёса вверх.", DefenderGroup )
end
--Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit
Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
@ -3498,7 +3498,7 @@ do -- AI_A2A_DISPATCHER
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", intercepting bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", перехват Ñ<>амолеÑов в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", перехватывая боги в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
elseif Squadron.Language == "DE" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", Eindringlinge abfangen bei" .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
end
@ -3520,7 +3520,7 @@ do -- AI_A2A_DISPATCHER
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", engaging bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", захватывающие Ñ<>амолеÑÑ Ð² " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", задействуя боги в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
end
end
self:GetParent( Fsm ).onafterEngage( self, DefenderGroup, From, Event, To, AttackSetUnit )
@ -3538,7 +3538,7 @@ do -- AI_A2A_DISPATCHER
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", возвращаÑ<EFBFBD>Ñ<EFBFBD>ÑŒ на базу.", DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", возвращение на базу.", DefenderGroup )
end
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
@ -3569,7 +3569,7 @@ do -- AI_A2A_DISPATCHER
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " landing at base.", DefenderGroup )
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", захватывающие Ñ<>амолеÑÑ Ð² поÑ<C2BE>адка на базу.", DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", посадка на базу.", DefenderGroup )
end
if Action and Action == "Destroy" then

View File

@ -47,19 +47,21 @@ function AI_CARGO:New( Carrier, CargoSet )
self:SetStartState( "Unloaded" )
self:AddTransition( "Unloaded", "Pickup", "*" )
-- Board
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
self:AddTransition( "*", "Load", "*" )
self:AddTransition( "*", "Reload", "*" )
self:AddTransition( "*", "Board", "*" )
self:AddTransition( "*", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
-- Unload
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "*", "Unload", "*" )
self:AddTransition( "*", "Unboard", "*" )
self:AddTransition( "*", "Unloaded", "Unloaded" )
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
self:AddTransition( "*", "Load", "Boarding" )
self:AddTransition( "Boarding", "Board", "Boarding" )
self:AddTransition( "Loaded", "Board", "Loaded" )
self:AddTransition( "Boarding", "Loaded", "Boarding" )
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
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

View File

@ -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 )

View File

@ -174,8 +174,8 @@ function AI_CARGO_DISPATCHER_HELICOPTER:New( HelicopterSet, CargoSet, PickupZone
self:SetPickupSpeed( 350, 150 )
self:SetDeploySpeed( 350, 150 )
self:SetPickupRadius( 0, 0 )
self:SetDeployRadius( 0, 0 )
self:SetPickupRadius( 40, 12 )
self:SetDeployRadius( 40, 12 )
self:SetPickupHeight( 500, 200 )
self:SetDeployHeight( 500, 200 )
@ -186,6 +186,9 @@ end
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, CargoSet )
return AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
local dispatcher = AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
dispatcher:SetLandingSpeedAndHeight(27, 6)
return dispatcher
end

View File

@ -64,20 +64,24 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
self:SetStartState( "Unloaded" )
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", "*" )
-- Boarding
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
self:AddTransition( "*", "Landed", "*" )
self:AddTransition( "*", "Load", "*" )
self:AddTransition( "*", "Loaded", "Loaded" )
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
-- Unboarding
self:AddTransition( "Loaded", "Deploy", "*" )
self:AddTransition( "*", "Queue", "*" )
self:AddTransition( "*", "Orbit" , "*" )
self:AddTransition( "*", "Home" , "*" )
self:AddTransition( "*", "Destroyed", "*" )
self:AddTransition( "*", "Unload", "*" )
self:AddTransition( "*", "Unloaded", "Unloaded" )
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
-- RTB
self:AddTransition( "*", "Home" , "*" )
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
@ -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

View File

@ -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

View File

@ -59,7 +59,7 @@
-- @extends Core.Base#BASE
--- *The worst thing that can happen to a good cause is, not to be skillfully attacked, but to be ineptly defended.* - Frédéric Bastiat
--- *The worst thing that can happen to a good cause is, not to be skillfully attacked, but to be ineptly defended.* - Frédéric Bastiat
--
-- Simple Class for a more intelligent Air Defense System
--

View File

@ -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 <20>
-- * 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.

View File

@ -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.
-- Ships 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()))

View File

@ -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' )

View File

@ -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,12 +343,13 @@ 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!
self.template = Template or "generic" -- template for downed pilot
self.mashprefix = {"MASH"} -- prefixes used to find MASHes
self.mash = SET_GROUP:New():FilterCoalitions(self.coalition):FilterPrefixes(self.mashprefix):FilterOnce() -- currently only GROUP objects, maybe support STATICs also?
self.autosmoke = false -- automatically smoke location when heli is near
self.autosmokedistance = 2000 -- distance for autosmoke
-- added 0.1.4
@ -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
@ -934,7 +920,7 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
end
-- trigger FSM event
self:__PilotDown(2,_downedGroup, _freqk, _leadername, _coordinatesText)
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText)
return self
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
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,14 +1569,13 @@ 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
if _unit and not self.suppressmessages then
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
end
end
end
return self
end
@ -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
@ -1907,6 +1917,7 @@ function CSAR:onafterStart(From, Event, To)
else
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
end
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
self:__Status(-10)
return self
end
@ -1915,19 +1926,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 +2058,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

View File

@ -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,7 +1457,7 @@ 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:__CratesPickedUp(1, Group, Unit, crate)
@ -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
@ -1966,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
@ -2132,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
@ -2157,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
@ -2254,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
@ -2275,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
@ -2366,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
@ -2377,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
@ -2385,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
@ -2403,10 +2477,15 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
maxdist = distance
zoneret = zone
zonenameret = zonename
zonewret = zonewidth
colorret = color
end
end
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.
@ -2589,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
@ -2650,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
@ -2682,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

View File

@ -162,33 +162,33 @@ 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 },
["возвращаÑ<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 },
["возвращение на базу"] = { "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 },
["за"] = { "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.

View File

@ -507,7 +507,7 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
end
-- 024<EFBFBD> 23' 12"N or 024<32> 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
@ -923,7 +923,7 @@ function UTILS.RandomGaussian(x0, sigma, xmin, xmax, imax)
local x1=math.random()
local x2=math.random()
-- Transform to Gaussian exp(-(x-x0)²/(2*sigma²).
-- Transform to Gaussian exp(-(x-x0)°/(2*sigma°).
r = math.sqrt(-2*sigma*sigma * math.log(x1)) * math.cos(2*math.pi * x2) + x0
i=i+1
@ -1553,7 +1553,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()
@ -1578,7 +1578,7 @@ 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
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