PseudoATC v0.7.0

Pseudo ATC improvements.
Minor changes in RAT and Suppression.
This commit is contained in:
funkyfranky 2018-05-09 00:11:53 +02:00
parent 95d7b8250d
commit 191fcb25be
3 changed files with 320 additions and 139 deletions

View File

@ -7,7 +7,7 @@
-- --
-- The pseudo ATC enhances the standard DCS ATC functions. -- The pseudo ATC enhances the standard DCS ATC functions.
-- --
-- In particular, a menu entry "Pseudo ATC" is created in the special F10 menu. -- In particular, a menu entry "Pseudo ATC" is created in the "F10 Other..." radiomenu.
-- --
-- ## Features -- ## Features
-- --
@ -17,18 +17,17 @@
-- * Report absolute bearing and range to nearest airports. -- * Report absolute bearing and range to nearest airports.
-- * Report current altitude AGL of own aircraft. -- * Report current altitude AGL of own aircraft.
-- * Upon request, ATC reports altitude until touchdown. -- * Upon request, ATC reports altitude until touchdown.
-- * Pressure temperature, wind data and BR for mission waypoints. -- * Report weather (pressure temperature, wind) and BR at players mission waypoints.
-- * Works with static and dynamic weather. -- * Works with static and dynamic weather.
-- * All maps supported (Caucasus, NTTR, Normandy, and all future maps). -- * Player can select the unit system (metric or imperial) in which data is reported.
-- * Multiplayer ready (?) (I suppose yes, but I don't have a server to test or debug. Jumping from client to client works.) -- * All maps supported (Caucasus, NTTR, Normandy, Persion Gulf and all future maps).
--
-- Pressure units: hPa (european aircraft), mmHg (russian aircraft), inHg (american aircraft).
-- --
-- ==== -- ====
-- --
-- # Demo Missions -- # Demo Missions
-- --
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) -- ### [ALL Demo Missions of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
-- ### [ALL Demo Missions of the latest deveopment branch](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop)
-- --
-- ==== -- ====
-- --
@ -40,7 +39,7 @@
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)**
-- --
-- ### Contributions: **Sven van de Velde ([FlightControl](https://forums.eagle.ru/member.php?u=89536))** -- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)**
-- --
-- ==== -- ====
-- @module PseudoATC -- @module PseudoATC
@ -49,9 +48,10 @@
--- PSEUDOATC class --- PSEUDOATC class
-- @type PSEUDOATC -- @type PSEUDOATC
-- @field #string ClassName Name of the Class. -- @field #string ClassName Name of the Class.
-- @field #table player Table comprising each player info.
-- @field #boolean Debug If true, print debug info to dcs.log file. -- @field #boolean Debug If true, print debug info to dcs.log file.
-- @field #table player Table comprising the player info.
-- @field #number mdur Duration in seconds how low messages to the player are displayed. -- @field #number mdur Duration in seconds how low messages to the player are displayed.
-- @field #number mrefresh Interval in seconds after which the F10 menu is refreshed. E.g. by the closest airports.
-- @field #boolean eventsmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler. -- @field #boolean eventsmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@ -60,19 +60,19 @@
-- --
-- ## Scripting: -- ## Scripting:
-- --
-- Scripting is almost trivial. Just add the following line to your script: -- Scripting is almost trivial. Just add the following two lines to your script:
-- --
-- PSEUDOATC:Start() -- pseudoATC=PSEUDOATC:New()
-- pseudoATC:Start()
-- --
-- --
-- @field #PSEUDOATC -- @field #PSEUDOATC
PSEUDOATC={ PSEUDOATC={
ClassName = "PSEUDOATC", ClassName = "PSEUDOATC",
Debug=true,
player={}, player={},
maxairport=10, Debug=false,
mdur=30, mdur=30,
mrefresh=120, mrefresh=60,
eventsmoose=true, eventsmoose=true,
} }
@ -92,38 +92,93 @@ PSEUDOATC.unit={
PSEUDOATC.id="PseudoATC | " PSEUDOATC.id="PseudoATC | "
--- PSEUDOATC version. --- PSEUDOATC version.
-- @field #list -- @field #number version
PSEUDOATC.version={ PSEUDOATC.version="0.7.0"
version = "0.6.0",
print = true,
}
-----------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-- TODO: Add takeoff event.
-- TODO: Add user functions.
-----------------------------------------------------------------------------------------------------------------------------------------
--- PSEUDOATC contructor. Starts the PseudoATC. --- PSEUDOATC contructor. Starts the PseudoATC.
-- @param #PSEUDOATC self -- @param #PSEUDOATC self
-- @return #PSEUDOATC Returns a PSEUDOATC object. -- @return #PSEUDOATC Returns a PSEUDOATC object.
function PSEUDOATC:Start() function PSEUDOATC:New()
-- Inherit BASE. -- Inherit BASE.
local self=BASE:Inherit(self, BASE:New()) -- #PSEUDOATC local self=BASE:Inherit(self, BASE:New()) -- #PSEUDOATC
-- Debug info -- Debug info
self:E(PSEUDOATC.id..string.format("Creating PseudoATC object. PseudoATC version %s", PSEUDOATC.version.version)) self:E(PSEUDOATC.id..string.format("PseudoATC version %s", PSEUDOATC.version))
-- Return object.
return self
end
--- PSEUDOATC contructor. Starts the PseudoATC.
-- @param #PSEUDOATC self
-- @return #PSEUDOATC Returns a PSEUDOATC object.
function PSEUDOATC:Start()
self:F()
-- Debug info
self:E(PSEUDOATC.id.."Starting PseudoATC")
-- Handle events. -- Handle events.
if self.eventsmoose then if self.eventsmoose then
self:HandleEvent(EVENTS.Birth, self._OnBirth) self:T(PSEUDOATC.id.."Events are handled by MOOSE.")
self:HandleEvent(EVENTS.Birth, self._OnBirth)
self:HandleEvent(EVENTS.Land, self._PlayerLanded)
self:HandleEvent(EVENTS.Takeoff, self._PlayerTakeOff)
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._PlayerLeft) self:HandleEvent(EVENTS.PlayerLeaveUnit, self._PlayerLeft)
--self:HandleEvent(EVENTS.PilotDead, self._PlayerLeft) self:HandleEvent(EVENTS.Crash, self._PlayerLeft)
self:HandleEvent(EVENTS.Land, self._PlayerLanded) self:HandleEvent(EVENTS.Ejection, self._PlayerLeft)
--self:HandleEvent(EVENTS.Takeoff, self._PlayerTakeoff) --self:HandleEvent(EVENTS.PilotDead, self._PlayerLeft)
else else
self:T(PSEUDOATC.id.."Events are handled by DCS.")
-- Events are handled directly by DCS. -- Events are handled directly by DCS.
world.addEventHandler(self) world.addEventHandler(self)
end end
-- Return object. end
return self
-----------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
--- Debug mode on. Send messages to everone.
-- @param #PSEUDOATC self
function PSEUDOATC:DebugOn()
self.Debug=true
end
--- Debug mode off. This is the default setting.
-- @param #PSEUDOATC self
function PSEUDOATC:DebugOff()
self.Debug=false
end
--- Set message duration how long messages are displayed.
-- @param #PSEUDOATC self
-- @param #number duration Time in seconds. Default is 30 sec.
function PSEUDOATC:SetMessageDuration(duration)
self.mdur=duration or 30
end
--- Set time interval after which the F10 radio menu is refreshed.
-- @param #PSEUDOATC self
-- @param #number interval Interval in seconds. Default is every 60 sec.
function PSEUDOATC:SetMessageDuration(interval)
self.mrefresh=interval or 60
end
--- Enable/disable event handling by MOOSE or DCS.
-- @param #PSEUDOATC self
-- @param #boolean switch If true, events are handled by MOOSE (default). If fase, events are handled directly by DCS.
function PSEUDOATC:SetMessageDuration(switch)
self.eventsmoose=switch
end end
----------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------
@ -163,20 +218,23 @@ function PSEUDOATC:onEvent(Event)
end end
-- Event info. -- Event info.
if self.Debug then self:T3(PSEUDOATC.id..string.format("EVENT: Event in onEvent with ID = %s", tostring(Event.id)))
env.info(PSEUDOATC.id..string.format("EVENT: Event in onEvent with ID = %s", tostring(Event.id))) self:T3(PSEUDOATC.id..string.format("EVENT: Ini unit = %s" , tostring(EventData.IniUnitName)))
env.info(PSEUDOATC.id..string.format("EVENT: Ini unit = %s" , tostring(EventData.IniUnitName))) self:T3(PSEUDOATC.id..string.format("EVENT: Ini group = %s" , tostring(EventData.IniGroupName)))
env.info(PSEUDOATC.id..string.format("EVENT: Ini group = %s" , tostring(EventData.IniGroupName))) self:T3(PSEUDOATC.id..string.format("EVENT: Ini player = %s" , tostring(_playername)))
env.info(PSEUDOATC.id..string.format("EVENT: Ini player = %s" , tostring(_playername))) self:T3(PSEUDOATC.id..string.format("EVENT: Place = %s" , tostring(EventData.PlaceName)))
env.info(PSEUDOATC.id..string.format("EVENT: Place = %s" , tostring(EventData.PlaceName))) self:T3(PSEUDOATC.id..string.format("EVENT: SubPlace = %s" , tostring(EventData.SubPlaceName)))
env.info(PSEUDOATC.id..string.format("EVENT: SubPlace = %s" , tostring(EventData.SubPlaceName)))
end
-- Event birth. -- Event birth.
if Event.id == world.event.S_EVENT_BIRTH and _playername then if Event.id == world.event.S_EVENT_BIRTH and _playername then
self:_OnBirth(EventData) self:_OnBirth(EventData)
end end
-- Event takeoff.
if Event.id == world.event.S_EVENT_TAKEOFF and _playername then
self:_PlayerTakeOff(EventData)
end
-- Event land. -- Event land.
if Event.id == world.event.S_EVENT_LAND and _playername and EventData.Place then if Event.id == world.event.S_EVENT_LAND and _playername and EventData.Place then
self:_PlayerLanded(EventData) self:_PlayerLanded(EventData)
@ -187,6 +245,26 @@ function PSEUDOATC:onEvent(Event)
self:_PlayerLeft(EventData) self:_PlayerLeft(EventData)
end end
-- Event crash ==> player left unit
if Event.id == world.event.S_EVENT_CRASH and _playername then
self:_PlayerLeft(EventData)
end
-- Event eject ==> player left unit
if Event.id == world.event.S_EVENT_EJECTION and _playername then
self:_PlayerLeft(EventData)
end
-- Event pilot dead ==> player left unit
if Event.id == world.event.S_EVENT_PILOT_DEAD and _playername then
self:_PlayerLeft(EventData)
end
-- Event pilot dead ==> player left unit
if Event.id == world.event.S_EVENT_PILOT_DEAD and _playername then
self:_PlayerLeft(EventData)
end
end end
--- Function called my MOOSE event handler when a player enters a unit. --- Function called my MOOSE event handler when a player enters a unit.
@ -248,6 +326,28 @@ function PSEUDOATC:_PlayerLanded(EventData)
end end
end end
--- Function called by MOOSE/DCS event handler when a player took off.
-- @param #PSEUDOATC self
-- @param Core.Event#EVENTDATA EventData
function PSEUDOATC:_PlayerTakeOff(EventData)
self:F({EventData=EventData})
-- Get unit, player and place.
local _unitName=EventData.IniUnitName
local _unit,_playername=self:_GetPlayerUnitAndName(_unitName)
local _base=nil
local _baseName=nil
if EventData.place then
_base=EventData.place
_baseName=EventData.place:getName()
end
-- Call take-off function.
if _unit and _playername and _base then
self:PlayerTakeOff(_unit, _baseName)
end
end
----------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------
-- Event Functions -- Event Functions
@ -283,15 +383,15 @@ function PSEUDOATC:PlayerEntered(unit)
-- Create main F10 menu, i.e. "F10/Pseudo ATC" -- Create main F10 menu, i.e. "F10/Pseudo ATC"
self.player[GID].menu_main=missionCommands.addSubMenuForGroup(GID, "Pseudo ATC") self.player[GID].menu_main=missionCommands.addSubMenuForGroup(GID, "Pseudo ATC")
-- Create list of nearby airports. -- Create/update list of nearby airports.
self:LocalAirports(GID) self:LocalAirports(GID)
-- Create submenu My Positon. -- Create submenu of local airports.
self:MenuAircraft(GID)
-- Create submenu airports.
self:MenuAirports(GID) self:MenuAirports(GID)
-- Create submenu Waypoints.
self:MenuWaypoints(GID)
-- Start scheduler to refresh the F10 menues. -- Start scheduler to refresh the F10 menues.
self.player[GID].scheduler, self.player[GID].schedulerid=SCHEDULER:New(nil, self.MenuRefresh, {self, GID}, self.mrefresh, self.mrefresh) self.player[GID].scheduler, self.player[GID].schedulerid=SCHEDULER:New(nil, self.MenuRefresh, {self, GID}, self.mrefresh, self.mrefresh)
@ -319,7 +419,7 @@ function PSEUDOATC:PlayerLanded(unit, place)
MESSAGE:New(text, 30):ToAllIf(self.Debug) MESSAGE:New(text, 30):ToAllIf(self.Debug)
-- Stop altitude reporting timer if its activated. -- Stop altitude reporting timer if its activated.
self:AltidudeStopTimer(id) self:AltitudeTimerStop(id)
-- Welcome message. -- Welcome message.
if place then if place then
@ -329,11 +429,40 @@ function PSEUDOATC:PlayerLanded(unit, place)
end end
--- Function called when a player took off.
-- @param #PSEUDOATC self
-- @param Wrapper.Unit#UNIT unit Unit of player which has landed.
-- @param #string place Name of the place the player landed at.
function PSEUDOATC:PlayerTakeOff(unit, place)
self:F2({unit=unit, place=place})
-- Gather some information.
local group=unit:GetGroup()
local id=group:GetID()
local PlayerName=self.player[id].playername
local Callsign=self.player[id].callsign
local UnitName=self.player[id].unitname
local GroupName=self.player[id].groupname
local CallSign=self.player[id].callsign
-- Debug message.
local text=string.format("Player %s (%s) from group %s (ID %d) took off at %s", PlayerName, UnitName, GroupName, id, place)
self:T(PSEUDOATC.id..text)
MESSAGE:New(text, 30):ToAllIf(self.Debug)
-- Bye-Bye message.
if place then
local text=string.format("%s, %s, your are airborn. Have a save trip!", place, CallSign)
MESSAGE:New(text, self.mdur):ToGroup(group)
end
end
--- Function called when a player leaves a unit or dies. --- Function called when a player leaves a unit or dies.
-- @param #PSEUDOATC self -- @param #PSEUDOATC self
-- @param Wrapper.Unit#UNIT unit Player unit which was left. -- @param Wrapper.Unit#UNIT unit Player unit which was left.
function PSEUDOATC:PlayerLeft(unit) function PSEUDOATC:PlayerLeft(unit)
self:F2({unit=unit}) self:F({unit=unit})
-- Get id. -- Get id.
local group=unit:GetGroup() local group=unit:GetGroup()
@ -349,8 +478,13 @@ function PSEUDOATC:PlayerLeft(unit)
self.player[id].scheduler:Stop(self.player[id].schedulerid) self.player[id].scheduler:Stop(self.player[id].schedulerid)
end end
-- Stop scheduler for reporting alt if it runs.
self:AltitudeTimerStop(id)
-- Remove main menu. -- Remove main menu.
missionCommands.removeItem(self.player[id].menu_main) if self.player[id].menu_main then
missionCommands.removeItem(self.player[id].menu_main)
end
-- Remove player array. -- Remove player array.
self.player[id]=nil self.player[id]=nil
@ -376,11 +510,12 @@ function PSEUDOATC:MenuRefresh(id)
-- Create list of nearby airports. -- Create list of nearby airports.
self:LocalAirports(id) self:LocalAirports(id)
-- Create submenu My Positon. -- Create submenu Local Airports.
--self:MenuAircraft(id)
-- Create submenu airports.
self:MenuAirports(id) self:MenuAirports(id)
-- Create submenu Waypoints etc.
self:MenuWaypoints(id)
end end
@ -395,47 +530,49 @@ function PSEUDOATC:MenuClear(id)
self:T(PSEUDOATC.id..text) self:T(PSEUDOATC.id..text)
MESSAGE:New(text,30):ToAllIf(self.Debug) MESSAGE:New(text,30):ToAllIf(self.Debug)
-- Delete Airports menu.
if self.player[id].menu_airports then if self.player[id].menu_airports then
missionCommands.removeItemForGroup(id, self.player[id].menu_airports) missionCommands.removeItemForGroup(id, self.player[id].menu_airports)
--[[ self.player[id].menu_airports=nil
for name,item in pairs(self.player[id].menu_airports) do
-- Debug message.
self:E(PSEUDOATC.id..string.format("Deleting menu item %s for ID %d", name, id))
-- Remove menu item.
missionCommands.removeItemForGroup(id, self.player[id].menu_airports[name])
end
]]
else else
self:T2(PSEUDOATC.id.."No airports to clear menus.") self:T2(PSEUDOATC.id.."No airports to clear menus.")
end end
-- Remove -- Delete waypoints menu.
if self.player[id].menu_aircraft then if self.player[id].menu_waypoints then
missionCommands.removeItemForGroup(id, self.player[id].menu_aircraft.main) missionCommands.removeItemForGroup(id, self.player[id].menu_waypoints)
self.player[id].menu_waypoints=nil
end
-- Delete report alt until touchdown menu command.
if self.player[id].menu_reportalt then
missionCommands.removeItemForGroup(id, self.player[id].menu_reportalt)
self.player[id].menu_reportalt=nil
end
-- Delete request current alt menu command.
if self.player[id].menu_requesttalt then
missionCommands.removeItemForGroup(id, self.player[id].menu_requestalt)
self.player[id].menu_requestalt=nil
end end
self.player[id].menu_airports=nil
--self.player[id].menu_aircraft=nil
end end
--- Create "F10/Pseudo ATC" menu items "Airport Data". --- Create "F10/Pseudo ATC/Local Airports" menu item.
-- @param #PSEUDOATC self -- @param #PSEUDOATC self
-- @param #number id Group id of player unit for which menues are created. -- @param #number id Group id of player unit for which menues are created.
function PSEUDOATC:MenuAirports(id) function PSEUDOATC:MenuAirports(id)
self:F(id) self:F(id)
-- Table for menu entries. -- Table for menu entries.
self.player[id].menu_airports=missionCommands.addSubMenuForGroup(id, "Airports", self.player[id].menu_main) self.player[id].menu_airports=missionCommands.addSubMenuForGroup(id, "Local Airports", self.player[id].menu_main)
local i=0 local i=0
for _,airport in pairs(self.player[id].airports) do for _,airport in pairs(self.player[id].airports) do
i=i+1 i=i+1
if i>self.maxairport then if i > 10 then
break -- Max X<10 airports due to 10 menu items restriction. break -- Max 10 airports due to 10 menu items restriction.
end end
local name=airport.name local name=airport.name
@ -444,14 +581,9 @@ function PSEUDOATC:MenuAirports(id)
--F10menu_ATC_airports[ID][name] = missionCommands.addSubMenuForGroup(ID, name, F10menu_ATC) --F10menu_ATC_airports[ID][name] = missionCommands.addSubMenuForGroup(ID, name, F10menu_ATC)
local submenu=missionCommands.addSubMenuForGroup(id, name, self.player[id].menu_airports) local submenu=missionCommands.addSubMenuForGroup(id, name, self.player[id].menu_airports)
--self.player[id].menu_airports[name]=submenu
-- Create menu reporting commands -- Create menu reporting commands
missionCommands.addCommandForGroup(id, "Weather Report", submenu, self.ReportWeather, self, id, pos, name) missionCommands.addCommandForGroup(id, "Weather Report", submenu, self.ReportWeather, self, id, pos, name)
--missionCommands.addCommandForGroup(id, "Request QFE", submenu, self.ReportPressure, self, id, "QFE", pos, name)
--missionCommands.addCommandForGroup(id, "Request QNH", submenu, self.ReportPressure, self, id, "QNH", pos, name)
--missionCommands.addCommandForGroup(id, "Request Wind", submenu, self.ReportWind, self, id, pos, name)
--missionCommands.addCommandForGroup(id, "Request Temperature", submenu, self.ReportTemperature, self, id, pos, name)
missionCommands.addCommandForGroup(id, "Request BR", submenu, self.ReportBR, self, id, pos, name) missionCommands.addCommandForGroup(id, "Request BR", submenu, self.ReportBR, self, id, pos, name)
-- Debug message. -- Debug message.
@ -459,24 +591,19 @@ function PSEUDOATC:MenuAirports(id)
end end
end end
--- Create F10/Pseudo ATC menu item "My Plane". --- Create F10/Pseudo ATC/Waypoints menu items and misc items.
-- @param #PSEUDOATC self -- @param #PSEUDOATC self
-- @param #number id Group id of player unit for which menues are created. -- @param #number id Group id of player unit for which menues are created.
function PSEUDOATC:MenuAircraft(id) function PSEUDOATC:MenuWaypoints(id)
self:F(id) self:F(id)
-- Table for menu entries. -- Player unit and callsign.
--self.player[id].menu_aircraft={}
local unit=self.player[id].unit --Wrapper.Unit#UNIT local unit=self.player[id].unit --Wrapper.Unit#UNIT
local callsign=self.player[id].callsign local callsign=self.player[id].callsign
local name=string.format("My Aircraft (%s)", callsign) local name=string.format("My Aircraft (%s)", callsign)
-- Debug info. -- Debug info.
self:T(PSEUDOATC.id..string.format("Creating menu item %s for ID %d", name,id)) self:T(PSEUDOATC.id..string.format("Creating waypoint menu for %s (ID %d).", name, id))
-- F10/PseudoATC/My Aircraft (callsign)
--self.player[id].menu_aircraft.main = missionCommands.addSubMenuForGroup(id, name, self.player[id].menu_main)
if #self.player[id].waypoints>0 then if #self.player[id].waypoints>0 then
@ -485,6 +612,7 @@ function PSEUDOATC:MenuAircraft(id)
local j=0 local j=0
for i, wp in pairs(self.player[id].waypoints) do for i, wp in pairs(self.player[id].waypoints) do
-- Increase counter -- Increase counter
j=j+1 j=j+1
@ -501,23 +629,18 @@ function PSEUDOATC:MenuAircraft(id)
-- Menu commands for each waypoint "F10/PseudoATC/My Aircraft (callsign)/Waypoints/Waypoint X/<Commands>" -- Menu commands for each waypoint "F10/PseudoATC/My Aircraft (callsign)/Waypoints/Waypoint X/<Commands>"
missionCommands.addCommandForGroup(id, "Weather Report", submenu, self.ReportWeather, self, id, pos, name) missionCommands.addCommandForGroup(id, "Weather Report", submenu, self.ReportWeather, self, id, pos, name)
--missionCommands.addCommandForGroup(id, "Request QFE", submenu, self.ReportPressure, self, id, "QFE", pos, pname)
--missionCommands.addCommandForGroup(id, "Request QNH", submenu, self.ReportPressure, self, id, "QNH", pos, pname)
--missionCommands.addCommandForGroup(id, "Request Wind", submenu, self.ReportWind, self, id, pos, pname)
--missionCommands.addCommandForGroup(id, "Request Temperature", submenu, self.ReportTemperature, self, id, pos, pname)
missionCommands.addCommandForGroup(id, "Request BR", submenu, self.ReportBR, self, id, pos, name) missionCommands.addCommandForGroup(id, "Request BR", submenu, self.ReportBR, self, id, pos, name)
end end
end end
missionCommands.addCommandForGroup(id, "Request current altitude AGL", self.player[id].menu_main, self.ReportHeight, self, id) self.player[id].menu_reportalt = missionCommands.addCommandForGroup(id, "Report alt until touchdown", self.player[id].menu_main, self.AltidudeTimerToggle, self, id)
missionCommands.addCommandForGroup(id, "Report altitude until touchdown", self.player[id].menu_main, self.AltidudeStartTimer, self, id) self.player[id].menu_requestalt = missionCommands.addCommandForGroup(id, "Request altitude AGL", self.player[id].menu_main, self.ReportHeight, self, id)
missionCommands.addCommandForGroup(id, "Quit reporting altitude", self.player[id].menu_main, self.AltidudeStopTimer, self, id)
end end
----------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------
-- Reporting Functions -- Reporting Functions
--- Weather Report. Report pressure QFE/QNH, temperature, wind at certain location --- Weather Report. Report pressure QFE/QNH, temperature, wind at certain location.
-- @param #PSEUDOATC self -- @param #PSEUDOATC self
-- @param #number id Group id to which the report is delivered. -- @param #number id Group id to which the report is delivered.
-- @param Core.Point#COORDINATE position Coordinates at which the pressure is measured. -- @param Core.Point#COORDINATE position Coordinates at which the pressure is measured.
@ -675,7 +798,7 @@ function PSEUDOATC:ReportWind(id, position, location)
-- Formatted wind direction. -- Formatted wind direction.
local Ds = string.format('%03d°', Dir) local Ds = string.format('%03d°', Dir)
-- Settings. -- Player settings.
local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS
-- Velocity in player units. -- Velocity in player units.
@ -732,7 +855,7 @@ end
-- @param #number id Group id to the report is delivered. -- @param #number id Group id to the report is delivered.
-- @param #number dt (Optional) Duration the message is displayed. -- @param #number dt (Optional) Duration the message is displayed.
-- @param #boolean _clear (Optional) Clear previouse messages. -- @param #boolean _clear (Optional) Clear previouse messages.
-- @return #number Altuitude above ground. -- @return #number Altitude above ground.
function PSEUDOATC:ReportHeight(id, dt, _clear) function PSEUDOATC:ReportHeight(id, dt, _clear)
self:F({id=id, dt=dt}) self:F({id=id, dt=dt})
@ -743,43 +866,67 @@ function PSEUDOATC:ReportHeight(id, dt, _clear)
-- Return height [m] above ground level. -- Return height [m] above ground level.
local function get_AGL(p) local function get_AGL(p)
local vec2={x=p.x,y=p.z} local agl=0
local ground=land.getHeight(vec2) if p then
local agl=p.y-ground local vec2={x=p.x,y=p.z}
local ground=land.getHeight(vec2)
local agl=p.y-ground
end
return agl return agl
end end
-- Get height AGL. -- Get height AGL.
local unit=self.player[id].unit --Wrapper.Unit#UNIT local unit=self.player[id].unit --Wrapper.Unit#UNIT
local position=unit:GetCoordinate()
local height=get_AGL(position)
local callsign=unit:GetCallsign()
-- Settings. if unit and unit:IsAlive() then
local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS
local Hs=string.format("%d m", height) local position=unit:GetCoordinate()
if settings:IsMetric() then local height=get_AGL(position)
Hs=string.format("%d ft", height*PSEUDOATC.unit.meter2feet) local callsign=unit:GetCallsign()
-- Settings.
local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS
local Hs=string.format("%d m", height)
if settings:IsMetric() then
Hs=string.format("%d ft", height*PSEUDOATC.unit.meter2feet)
end
-- Message text.
local _text=string.format("%s: Your altitude is %s AGL.", callsign, Hs)
-- Send message to player group.
--MESSAGE:New(text, dt):ToGroup(self.player[id].group)
self:_DisplayMessageToGroup(self.player[id].unit,_text, dt,_clear)
-- Return height
return height
end end
-- Message text. return 0
local _text=string.format("%s: Your altitude is %s AGL.", callsign, Hs)
-- Send message to player group.
--MESSAGE:New(text, dt):ToGroup(self.player[id].group)
self:_DisplayMessageToGroup(self.player[id].unit,_text, dt,_clear)
-- Return height
return height
end end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Toggle report altitude reporting on/of.
-- @param #PSEUDOATC self.
-- @param #number id Group id of player unit.
function PSEUDOATC:AltidudeTimerToggle(id)
self:F(id)
if self.player[id].altimerid then
-- If the timer is on, we turn it off.
self:AltitudeTimerStop(id)
else
-- If the timer is off, we turn it on.
self:AltitudeTimeStart(id)
end
end
--- Start altitude reporting scheduler. --- Start altitude reporting scheduler.
-- @param #PSEUDOATC self. -- @param #PSEUDOATC self.
-- @param #number id Group id of player unit. -- @param #number id Group id of player unit.
function PSEUDOATC:AltidudeStartTimer(id) function PSEUDOATC:AltitudeTimeStart(id)
self:F(id) self:F(id)
-- Debug info. -- Debug info.
@ -787,13 +934,13 @@ function PSEUDOATC:AltidudeStartTimer(id)
-- Start timer. -- Start timer.
--self.player[id].altimer=timer.scheduleFunction(self.ReportAltTouchdown, self, id, Tnow+2) --self.player[id].altimer=timer.scheduleFunction(self.ReportAltTouchdown, self, id, Tnow+2)
self.player[id].altimer, self.player[id].altimerid=SCHEDULER:New(nil, self.ReportHeight, {self, id, 0.1, true}, 1, 5) self.player[id].altimer, self.player[id].altimerid=SCHEDULER:New(nil, self.ReportHeight, {self, id, 0.1, true}, 1, 3)
end end
--- Stop/destroy DCS scheduler function for reporting altitude. --- Stop/destroy DCS scheduler function for reporting altitude.
-- @param #PSEUDOATC self. -- @param #PSEUDOATC self.
-- @param #number id Group id of player unit. -- @param #number id Group id of player unit.
function PSEUDOATC:AltidudeStopTimer(id) function PSEUDOATC:AltitudeTimerStop(id)
-- Debug info. -- Debug info.
self:T(PSEUDOATC.id..string.format("Stopping altitude report timer for player ID %d.", id)) self:T(PSEUDOATC.id..string.format("Stopping altitude report timer for player ID %d.", id))
@ -863,13 +1010,23 @@ function PSEUDOATC:_GetPlayerUnitAndName(_unitName)
self:F(_unitName) self:F(_unitName)
if _unitName ~= nil then if _unitName ~= nil then
-- Get DCS unit from its name.
local DCSunit=Unit.getByName(_unitName) local DCSunit=Unit.getByName(_unitName)
local playername=DCSunit:getPlayerName() if DCSunit then
-- Get the player name to make sure a player entered.
if DCSunit and playername then local playername=DCSunit:getPlayerName()
local unit=UNIT:Find(DCSunit) local unit=UNIT:Find(DCSunit)
return unit, playername
-- Debug output.
self:T2({DCSunit=DCSunit, unit=unit, playername=playername})
if unit and playername then
-- Return MOOSE unit and player name
return unit, playername
end
end end
end end

View File

@ -1280,7 +1280,7 @@ end
--- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediatly. --- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediatly.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, check is performed. If false, this check is omitted. -- @param #boolean switch If true, check is performed. If false, this check is omitted.
function RAT:CheckOnRunway(switch) function RAT:CheckOnRunway(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then
@ -1291,7 +1291,7 @@ end
--- Check if aircraft have accidentally been spawned on top of each other. If yes, they will be removed immediately. --- Check if aircraft have accidentally been spawned on top of each other. If yes, they will be removed immediately.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, check is performed. If false, this check is omitted. -- @param #boolean switch If true, check is performed. If false, this check is omitted.
function RAT:CheckOnTop(switch) function RAT:CheckOnTop(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then
@ -1302,7 +1302,7 @@ end
--- Put parking spot coordinates in a data base for future use of aircraft. --- Put parking spot coordinates in a data base for future use of aircraft.
-- @param #RAT self -- @param #RAT self
-- @param #booblen switch If true, parking spots are memorized. This is also the default setting. -- @param #boolean switch If true, parking spots are memorized. This is also the default setting.
function RAT:ParkingSpotDB(switch) function RAT:ParkingSpotDB(switch)
self:F2(switch) self:F2(switch)
if switch==nil then if switch==nil then

View File

@ -28,7 +28,7 @@
-- --
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)**
-- --
-- ### Contributions: **Sven van de Velde ([FlightControl](https://forums.eagle.ru/member.php?u=89536))** -- ### Contributions: **[FlightControl](https://forums.eagle.ru/member.php?u=89536)**
-- --
-- ==== -- ====
-- @module Suppression -- @module Suppression
@ -45,7 +45,7 @@
-- @field #string Type Type of the group. -- @field #string Type Type of the group.
-- @field #number SpeedMax Maximum speed of group in km/h. -- @field #number SpeedMax Maximum speed of group in km/h.
-- @field #boolean IsInfantry True if group has attribute Infantry. -- @field #boolean IsInfantry True if group has attribute Infantry.
-- @field Core.Controllable#CONTROLLABLE Controllable Controllable of the FSM. Must be a ground group. -- @field Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the FSM. Must be a ground group.
-- @field #number Tsuppress_ave Average time in seconds a group gets suppressed. Actual value is sampled randomly from a Gaussian distribution. -- @field #number Tsuppress_ave Average time in seconds a group gets suppressed. Actual value is sampled randomly from a Gaussian distribution.
-- @field #number Tsuppress_min Minimum time in seconds the group gets suppressed. -- @field #number Tsuppress_min Minimum time in seconds the group gets suppressed.
-- @field #number Tsuppress_max Maximum time in seconds the group gets suppressed. -- @field #number Tsuppress_max Maximum time in seconds the group gets suppressed.
@ -283,11 +283,16 @@ SUPPRESSION.MenuF10=nil
-- @field #string id -- @field #string id
SUPPRESSION.id="SFX | " SUPPRESSION.id="SFX | "
--- PSEUDOATC version.
-- @field #number version
SUPPRESSION.version="0.7.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--TODO: Figure out who was shooting and move away from him. --TODO list
--TODO: Move behind a scenery building if there is one nearby. --DONE: Figure out who was shooting and move away from him.
--TODO: Retreat to a given zone or point. --DONE: Move behind a scenery building if there is one nearby.
--DONE: Retreat to a given zone or point.
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -304,7 +309,7 @@ function SUPPRESSION:New(group)
-- Check that group is present. -- Check that group is present.
if group then if group then
self:T(SUPPRESSION.id.."Suppressive fire for group "..group:GetName()) self:T(SUPPRESSION.id..string.format("SUPPRESSION version %s. Activating suppressive fire for group %s", SUPPRESSION.version, group:GetName()))
else else
self:E(SUPPRESSION.id.."Suppressive fire: Requested group does not exist! (Has to be a MOOSE group.)") self:E(SUPPRESSION.id.."Suppressive fire: Requested group does not exist! (Has to be a MOOSE group.)")
return nil return nil
@ -312,7 +317,7 @@ function SUPPRESSION:New(group)
-- Check that we actually have a GROUND group. -- Check that we actually have a GROUND group.
if group:IsGround()==false then if group:IsGround()==false then
self:E(SUPPRESSION.id.."SUPPRESSION fire group "..group:GetName().." has to be a GROUND group!") self:E(SUPPRESSION.id..string.format("SUPPRESSION fire group %s has to be a GROUND group!", group:GetName()))
return nil return nil
end end
@ -326,7 +331,6 @@ function SUPPRESSION:New(group)
-- Get max speed the group can do and convert to km/h. -- Get max speed the group can do and convert to km/h.
self.SpeedMax=self.DCSdesc.speedMaxOffRoad*3.6 self.SpeedMax=self.DCSdesc.speedMaxOffRoad*3.6
--self.SpeedMaxOffRoad=DCSdesc.speedMaxOffRoad
-- Set speed to maximum. -- Set speed to maximum.
self.Speed=self.SpeedMax self.Speed=self.SpeedMax
@ -503,6 +507,7 @@ end
-- @param #number Tmin (Optional) Minimum time [seconds] a group will be suppressed. Default is 5 seconds. -- @param #number Tmin (Optional) Minimum time [seconds] a group will be suppressed. Default is 5 seconds.
-- @param #number Tmax (Optional) Maximum time a group will be suppressed. Default is 25 seconds. -- @param #number Tmax (Optional) Maximum time a group will be suppressed. Default is 25 seconds.
function SUPPRESSION:SetSuppressionTime(Tave, Tmin, Tmax) function SUPPRESSION:SetSuppressionTime(Tave, Tmin, Tmax)
self:F({Tave=Tave, Tmin=Tmin, Tmax=Tmax})
-- Minimum suppression time is input or default but at least 1 second. -- Minimum suppression time is input or default but at least 1 second.
self.Tsuppress_min=Tmin or self.Tsuppress_min self.Tsuppress_min=Tmin or self.Tsuppress_min
@ -526,24 +531,28 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param Core.Zone#ZONE zone MOOSE zone object. -- @param Core.Zone#ZONE zone MOOSE zone object.
function SUPPRESSION:SetRetreatZone(zone) function SUPPRESSION:SetRetreatZone(zone)
self:F({zone=zone})
self.RetreatZone=zone self.RetreatZone=zone
end end
--- Turn Debug mode on. Enables messages and more output to DCS log file. --- Turn Debug mode on. Enables messages and more output to DCS log file.
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
function SUPPRESSION:DebugOn() function SUPPRESSION:DebugOn()
self:F()
self.Debug=true self.Debug=true
end end
--- Flare units when they are hit, die or recover from suppression. --- Flare units when they are hit, die or recover from suppression.
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
function SUPPRESSION:FlareOn() function SUPPRESSION:FlareOn()
self:F()
self.flare=true self.flare=true
end end
--- Smoke positions where units fall back to, hide or retreat. --- Smoke positions where units fall back to, hide or retreat.
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
function SUPPRESSION:SmokeOn() function SUPPRESSION:SmokeOn()
self:F()
self.smoke=true self.smoke=true
end end
@ -551,6 +560,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #string formation Formation of the group. Default "Vee". -- @param #string formation Formation of the group. Default "Vee".
function SUPPRESSION:SetFormation(formation) function SUPPRESSION:SetFormation(formation)
self:F(formation)
self.Formation=formation or "Vee" self.Formation=formation or "Vee"
end end
@ -558,6 +568,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number speed Speed in km/h of group. Default max speed the group can do. -- @param #number speed Speed in km/h of group. Default max speed the group can do.
function SUPPRESSION:SetSpeed(speed) function SUPPRESSION:SetSpeed(speed)
self:F(speed)
self.Speed=speed or self.SpeedMax self.Speed=speed or self.SpeedMax
self.Speed=math.min(self.Speed, self.SpeedMax) self.Speed=math.min(self.Speed, self.SpeedMax)
end end
@ -566,6 +577,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #boolean switch Enable=true or disable=false fall back of group. -- @param #boolean switch Enable=true or disable=false fall back of group.
function SUPPRESSION:Fallback(switch) function SUPPRESSION:Fallback(switch)
self:F(switch)
if switch==nil then if switch==nil then
switch=true switch=true
end end
@ -576,6 +588,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number distance Distance in meters. -- @param #number distance Distance in meters.
function SUPPRESSION:SetFallbackDistance(distance) function SUPPRESSION:SetFallbackDistance(distance)
self:F(distance)
self.FallbackDist=distance self.FallbackDist=distance
end end
@ -583,6 +596,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number time Time in seconds. -- @param #number time Time in seconds.
function SUPPRESSION:SetFallbackWait(time) function SUPPRESSION:SetFallbackWait(time)
self:F(time)
self.FallbackWait=time self.FallbackWait=time
end end
@ -590,6 +604,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #boolean switch Enable=true or disable=false fall back of group. -- @param #boolean switch Enable=true or disable=false fall back of group.
function SUPPRESSION:Takecover(switch) function SUPPRESSION:Takecover(switch)
self:F(switch)
if switch==nil then if switch==nil then
switch=true switch=true
end end
@ -600,6 +615,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number time Time in seconds. -- @param #number time Time in seconds.
function SUPPRESSION:SetTakecoverWait(time) function SUPPRESSION:SetTakecoverWait(time)
self:F(time)
self.TakecoverWait=time self.TakecoverWait=time
end end
@ -607,6 +623,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number range Search range in meters. -- @param #number range Search range in meters.
function SUPPRESSION:SetTakecoverRange(range) function SUPPRESSION:SetTakecoverRange(range)
self:F(range)
self.TakecoverRange=range self.TakecoverRange=range
end end
@ -621,6 +638,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number probability Probability in percent. -- @param #number probability Probability in percent.
function SUPPRESSION:SetMinimumFleeProbability(probability) function SUPPRESSION:SetMinimumFleeProbability(probability)
self:F(probability)
self.PminFlee=probability or 10 self.PminFlee=probability or 10
end end
@ -628,6 +646,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number probability Probability in percent. -- @param #number probability Probability in percent.
function SUPPRESSION:SetMaximumFleeProbability(probability) function SUPPRESSION:SetMaximumFleeProbability(probability)
self:F(probability)
self.PmaxFlee=probability or 90 self.PmaxFlee=probability or 90
end end
@ -637,6 +656,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number damage Damage in percent. If group gets damaged above this value, the group will retreat. Default 50 %. -- @param #number damage Damage in percent. If group gets damaged above this value, the group will retreat. Default 50 %.
function SUPPRESSION:SetRetreatDamage(damage) function SUPPRESSION:SetRetreatDamage(damage)
self:F(damage)
self.RetreatDamage=damage or 50 self.RetreatDamage=damage or 50
end end
@ -644,6 +664,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #number time Time in seconds. Default 7200 seconds = 2 hours. -- @param #number time Time in seconds. Default 7200 seconds = 2 hours.
function SUPPRESSION:SetRetreatWait(time) function SUPPRESSION:SetRetreatWait(time)
self:F(time)
self.RetreatWait=time or 7200 self.RetreatWait=time or 7200
end end
@ -651,6 +672,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #string alarmstate Alarm state. Possible "Auto", "Green", "Red". Default is "Auto". -- @param #string alarmstate Alarm state. Possible "Auto", "Green", "Red". Default is "Auto".
function SUPPRESSION:SetDefaultAlarmState(alarmstate) function SUPPRESSION:SetDefaultAlarmState(alarmstate)
self:F(alarmstate)
if alarmstate:lower()=="auto" then if alarmstate:lower()=="auto" then
self.DefaultAlarmState=SUPPRESSION.AlarmState.Auto self.DefaultAlarmState=SUPPRESSION.AlarmState.Auto
elseif alarmstate:lower()=="green" then elseif alarmstate:lower()=="green" then
@ -666,6 +688,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #string roe ROE after suppression. Possible "Free", "Hold" or "Return". Default "Free". -- @param #string roe ROE after suppression. Possible "Free", "Hold" or "Return". Default "Free".
function SUPPRESSION:SetDefaultROE(roe) function SUPPRESSION:SetDefaultROE(roe)
self:F(roe)
if roe:lower()=="free" then if roe:lower()=="free" then
self.DefaultROE=SUPPRESSION.ROE.Free self.DefaultROE=SUPPRESSION.ROE.Free
elseif roe:lower()=="hold" then elseif roe:lower()=="hold" then
@ -681,6 +704,7 @@ end
-- @param #SUPPRESSION self -- @param #SUPPRESSION self
-- @param #boolean switch Enable=true or disable=false menu group. Default is true. -- @param #boolean switch Enable=true or disable=false menu group. Default is true.
function SUPPRESSION:MenuOn(switch) function SUPPRESSION:MenuOn(switch)
self:F(switch)
if switch==nil then if switch==nil then
switch=true switch=true
end end
@ -1298,7 +1322,7 @@ function SUPPRESSION:onEvent(Event)
self:_OnEventHit(EventData) self:_OnEventHit(EventData)
end end
-- Event HIT -- Event DEAD
if Event.id == world.event.S_EVENT_DEAD then if Event.id == world.event.S_EVENT_DEAD then
self:_OnEventDead(EventData) self:_OnEventDead(EventData)
end end
@ -1441,12 +1465,12 @@ end
--- Make group run/drive to a certain point. We put in several intermediate waypoints because sometimes the group stops before it arrived at the desired point. --- Make group run/drive to a certain point. We put in several intermediate waypoints because sometimes the group stops before it arrived at the desired point.
--@param #SUPPRESSION self --@param #SUPPRESSION self
--@param Core.Point#COORDINATE fin Coordinate where we want to go. --@param Core.Point#COORDINATE fin Coordinate where we want to go.
--@param #number speed Speed of group. Default is 999. --@param #number speed Speed of group. Default is 20.
--@param #string formation Formation of group. Default is "Vee". --@param #string formation Formation of group. Default is "Vee".
--@param #number wait Time the group will wait/hold at final waypoint. Default is 30 seconds. --@param #number wait Time the group will wait/hold at final waypoint. Default is 30 seconds.
function SUPPRESSION:_Run(fin, speed, formation, wait) function SUPPRESSION:_Run(fin, speed, formation, wait)
speed=speed or 999 speed=speed or 20
formation=formation or "Vee" formation=formation or "Vee"
wait=wait or 30 wait=wait or 30