From f9d7eea72115cf27cfa82109a9d1ce3e4105206e Mon Sep 17 00:00:00 2001 From: funkyfranky Date: Wed, 9 May 2018 23:56:55 +0200 Subject: [PATCH] ARTY, PseudoATC, RANGE, RAT, SUPPRESSION ARTY v0.9.0: Added anti-ship missiles. Various fixes. PSEUDOATC v0.9.0: Added docu. Cleaned up code. Bug fixes. RANGE v1.1.1: Changed menu. RAT v2.2.2: Changed default setting to menu = off. Added user function to enable/disable menus. SUPPRESSION v0.9.0: Improvements. --- .../Moose/Functional/Artillery.lua | 98 +++-- .../Moose/Functional/PseudoATC.lua | 355 ++++++++---------- Moose Development/Moose/Functional/RAT.lua | 30 +- Moose Development/Moose/Functional/Range.lua | 5 +- .../Moose/Functional/Suppression.lua | 19 +- 5 files changed, 250 insertions(+), 257 deletions(-) diff --git a/Moose Development/Moose/Functional/Artillery.lua b/Moose Development/Moose/Functional/Artillery.lua index 973b6ccbf..418bb359a 100644 --- a/Moose Development/Moose/Functional/Artillery.lua +++ b/Moose Development/Moose/Functional/Artillery.lua @@ -23,19 +23,19 @@ -- -- # Demo Missions -- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS) -- -- ==== -- -- # YouTube Channel -- --- ### [MOOSE YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) +-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) -- -- === -- -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- --- ### Contributions: **[FlightControl](https://forums.eagle.ru/member.php?u=89536)** +-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- -- ==== -- @module Arty @@ -311,10 +311,10 @@ -- normandy=ARTY:New(GROUP:FindByName("Normandy")) -- -- -- Add target: prio=50, radius=300 m, number of missiles=20, number of engagements=1, start time=08:05 hours, only use cruise missiles for this attack. --- normandy:AssignTargetCoord(GROUP:FindByName("Red Targets 1"), 20, 300, 50, 1, "08:01:00", ARTY.WeaponType.CruiseMissile) +-- normandy:AssignTargetCoord(GROUP:FindByName("Red Targets 1"):GetCoordinate(), 20, 300, 50, 1, "08:01:00", ARTY.WeaponType.CruiseMissile) -- -- -- Add target: prio=50, radius=300 m, number of shells=100, number of engagements=1, start time=08:15 hours, only use cannons during this attack. --- normandy:AssignTargetCoord(GROUP:FindByName("Red Targets 1"), 50, 300, 100, 1, "08:15:00", ARTY.WeaponType.Cannon) +-- normandy:AssignTargetCoord(GROUP:FindByName("Red Targets 1"):GetCoordinate(), 50, 300, 100, 1, "08:15:00", ARTY.WeaponType.Cannon) -- -- -- Define shells that are counted to check whether the ship is out of ammo. -- -- Note that this is necessary because the Normandy has a lot of other shell type weapons which cannot be used to engage ground targets in an artillery style manner. @@ -356,9 +356,12 @@ ARTY={ RearmingArtyOnRoad=false, InitialCoord=nil, report=true, - ammoshells={"weapons.shells"}, - ammorockets={"weapons.nurs"}, - ammomissiles={"weapons.missiles"}, + --ammoshells={"weapons.shells"}, + ammoshells={}, + --ammorockets={"weapons.nurs"}, + ammorockets={}, + --ammomissiles={"weapons.missiles"}, + ammomissiles={}, Nshots=0, minrange=500, maxrange=1000000, @@ -373,6 +376,7 @@ ARTY.WeaponType={ UnguidedAny=805339120, GuidedMissile=268402688, CruiseMissile=2097152, + AntiShipMissile=65536, } --- Some ID to identify who we are in output of the DCS.log file. @@ -381,7 +385,7 @@ ARTY.id="ARTY | " --- Arty script version. -- @field #number version -ARTY.version="0.8.9" +ARTY.version="0.9.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -485,7 +489,6 @@ function ARTY:New(group) -- Red branch. self:AddTransition({"CombatReady", "OutOfAmmo"}, "Rearm", "Rearming") - self:AddTransition("Rearming", "Move", "Rearming") self:AddTransition("Rearming", "Rearmed", "Rearmed") -- Green branch. @@ -503,7 +506,8 @@ function ARTY:New(group) -- Unknown transitons. To be checked if adding these causes problems. self:AddTransition("Rearming", "Arrived", "Rearming") - + self:AddTransition("Rearming", "Move", "Rearming") + return self end @@ -968,15 +972,16 @@ function ARTY:_OnEventShot(EventData) elseif self.currentTarget.weapontype==ARTY.WeaponType.UnguidedAny and _nshells+_nrockets==0 then - self:T(ARTY.id.."Unguided weapon requested but shells and rockets empty.") + self:T(ARTY.id.."Unguided weapon requested but shells AND rockets empty.") self:CeaseFire(self.currentTarget) return - elseif (self.currentTarget.weapontype==ARTY.WeaponType.CruiseMissile or self.currentTarget.weapontype==ARTY.WeaponType.CruiseMissile) and _nmissiles==0 then + elseif (self.currentTarget.weapontype==ARTY.WeaponType.GuidedMissile or self.currentTarget.weapontype==ARTY.WeaponType.CruiseMissile or self.currentTarget.weapontype==ARTY.WeaponType.AntiShipMissile) and _nmissiles==0 then - self:T(ARTY.id.."Guided or Cruise missiles requested but all missiles empty.") + self:T(ARTY.id.."Guided, anti-ship or cruise missiles requested but all missiles empty.") self:CeaseFire(self.currentTarget) return + end -- Check if number of shots reached max. @@ -1214,11 +1219,14 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target) _type="shells or rockets" elseif self.WeaponType==ARTY.WeaponType.GuidedMissile then nfire=Nmissiles - _type="missiles" + _type="guided missiles" elseif self.WeaponType==ARTY.WeaponType.CruiseMissile then nfire=Nmissiles _type="cruise missiles" - end + elseif self.WeaponType==ARTY.WeaponType.AntiShipMissile then + nfire=Nmissiles + _type="anti-ship missiles" + end -- Adjust if less than requested ammo is left. local _n=math.min(target.nshells, nfire) @@ -1877,6 +1885,11 @@ function ARTY:GetAmmo(display) self:T2(ARTY.id..string.format("Number of weapons %d.", weapons)) self:T2({ammotable=ammotable}) + self:T(ARTY.id.."Ammotable:") + for id,bla in pairs(ammotable) do + self:T({id=id, ammo=bla}) + end + -- Loop over all weapons. for w=1,weapons do @@ -1886,28 +1899,55 @@ function ARTY:GetAmmo(display) -- Typename of current weapon local Tammo=ammotable[w]["desc"]["typeName"] + -- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3 + local Category=ammotable[w].desc.category + + local MissileCategory=nil + if Category==Weapon.Category.MISSILE then + MissileCategory=ammotable[w].desc.missileCategory + end + -- Check for correct shell type. local _gotshell=false - for _,_type in pairs(self.ammoshells) do - if string.match(Tammo, _type) then + if #self.ammoshells>0 then + -- User explicitly specified the valid type(s) of shells. + for _,_type in pairs(self.ammoshells) do + if string.match(Tammo, _type) then + _gotshell=true + end + end + else + if Category==Weapon.Category.SHELL then _gotshell=true end end -- Check for correct rocket type. local _gotrocket=false - for _,_type in pairs(self.ammorockets) do - if string.match(Tammo, _type) then - _gotrocket=true + if #self.ammorockets>0 then + for _,_type in pairs(self.ammorockets) do + if string.match(Tammo, _type) then + _gotrocket=true + end end + else + if Category==Weapon.Category.ROCKET then + _gotrocket=true + end end -- Check for correct missile type. local _gotmissile=false - for _,_type in pairs(self.ammomissiles) do - if string.match(Tammo,_type) then - _gotmissile=true + if #self.ammomissiles>0 then + for _,_type in pairs(self.ammomissiles) do + if string.match(Tammo,_type) then + _gotmissile=true + end end + else + if Category==Weapon.Category.ROCKET then + _gotmissile=true + end end -- We are specifically looking for shells or rockets here. @@ -1917,7 +1957,7 @@ function ARTY:GetAmmo(display) nshells=nshells+Nammo -- Debug info. - text=text..string.format("- %d shells of type %s\n", Nammo, Tammo) + text=text..string.format("- %d shells of type %s (category=%d mc=%s)\n", Nammo, Tammo, Category, tostring(MissileCategory)) elseif _gotrocket then @@ -1925,7 +1965,7 @@ function ARTY:GetAmmo(display) nrockets=nrockets+Nammo -- Debug info. - text=text..string.format("- %d rockets of type %s\n", Nammo, Tammo) + text=text..string.format("- %d rockets of type %s (category=%d mc=%s)\n", Nammo, Tammo, Category, tostring(MissileCategory)) elseif _gotmissile then @@ -1933,12 +1973,12 @@ function ARTY:GetAmmo(display) nmissiles=nmissiles+Nammo -- Debug info. - text=text..string.format("- %d missiles of type %s\n", name, Nammo, Tammo) + text=text..string.format("- %d missiles of type %s (category=%d mc=%s)\n", Nammo, Tammo, Category, tostring(MissileCategory)) else -- Debug info. - text=text..string.format("- %d unknown ammo of type %s\n", Nammo, Tammo) + text=text..string.format("- %d unknown ammo of type %s (category=%d mc=%s)\n", Nammo, Tammo, Category, tostring(MissileCategory)) end @@ -1946,7 +1986,7 @@ function ARTY:GetAmmo(display) end -- Debug text and send message. - self:T2(ARTY.id..text) + self:T(ARTY.id..text) MESSAGE:New(text, 10):ToAllIf(display) end diff --git a/Moose Development/Moose/Functional/PseudoATC.lua b/Moose Development/Moose/Functional/PseudoATC.lua index 10b28166e..9726f1666 100644 --- a/Moose Development/Moose/Functional/PseudoATC.lua +++ b/Moose Development/Moose/Functional/PseudoATC.lua @@ -1,5 +1,5 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- **Functional** - Pseudo ATC. +--- **Functional** - (R2.4) Rudimentary ATC. -- -- ![Banner Image](..\Presentations\PSEUDOATC\PSEUDOATC_Main.jpg) -- @@ -11,35 +11,31 @@ -- -- ## Features -- --- * Report QFE or QNH pressures at nearby airbases. --- * Report wind direction and strength at airbases. --- * Report temperature at airbases. --- * Report absolute bearing and range to nearest airports. +-- * Weather report at nearby airbases and mission waypoints. +-- * Report absolute bearing and range to nearest airports and mission waypoints. -- * Report current altitude AGL of own aircraft. -- * Upon request, ATC reports altitude until touchdown. --- * Report weather (pressure temperature, wind) and BR at players mission waypoints. -- * Works with static and dynamic weather. --- * Player can select the unit system (metric or imperial) in which data is reported. --- * All maps supported (Caucasus, NTTR, Normandy, Persion Gulf and all future maps). +-- * Player can select the unit system (metric or imperial) in which information is reported. +-- * All maps supported (Caucasus, NTTR, Normandy, Persian Gulf and all future maps). -- -- ==== -- -- # Demo Missions -- --- ### [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) +-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS) -- -- ==== -- -- # YouTube Channel -- --- ### [MOOSE YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) +-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) -- -- === -- -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- --- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)** +-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- -- ==== -- @module PseudoATC @@ -51,14 +47,37 @@ -- @field #table player Table comprising each player info. -- @field #boolean Debug If true, print debug info to dcs.log file. -- @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 #number mrefresh Interval in seconds after which the F10 menu is refreshed. E.g. by the closest airports. Default is 120 sec. +-- @field #number talt Interval in seconds between reporting altitude until touchdown. Default 3 sec. +-- @field #boolean chatty Display some messages on events like take-off and touchdown. -- @field #boolean eventsmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler. -- @extends Core.Base#BASE ---# PSEUDOATC class, extends @{Base#BASE} -- The PSEUDOATC class adds some rudimentary ATC functionality via the radio menu. -- --- ## Scripting: +-- Local weather reports can be requested for nearby airports and player's mission waypoints. +-- The weather report includes +-- +-- * QFE and QNH pressures, +-- * Temperature, +-- * Wind direction and strength. +-- +-- The list of airports is updated every 60 seconds. This interval can be adjusted by the function @{#PSEUDOATC.SetMenuRefresh}(*interval*). +-- +-- Likewise, absolute bearing and range to the close by airports and mission waypoints can be requested. +-- +-- The player can switch the unit system in which all information is displayed during the mission with the MOOSE settings radio menu. +-- The unit system can be set to either imperial or metric. Altitudes are reported in feet or meter, distances in kilometers or nautical miles, +-- temperatures in degrees Fahrenheit or Celsius and QFE/QNH pressues in inHg or mmHg. +-- Note that the pressures are also reported in hPa independent of the unit system setting. +-- +-- In bad weather conditions, the ATC can "talk you down", i.e. will continuously report your altitude on the final approach. +-- Default reporting time interval is 3 seconds. This can be adjusted via the @{#PSEUDOATC.SetReportAltInterval}(*interval*) function. +-- The reporting stops automatically when the player lands or can be stopped manually by clicking on the radio menu item again. +-- So the radio menu item acts as a toggle to switch the reporting on and off. +-- +-- ## Scripting -- -- Scripting is almost trivial. Just add the following two lines to your script: -- @@ -72,38 +91,31 @@ PSEUDOATC={ player={}, Debug=false, mdur=30, - mrefresh=60, + mrefresh=120, + talt=3, + chatty=true, eventsmoose=true, } ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- PSEUDOATC unit conversions. --- @list unit -PSEUDOATC.unit={ - hPa2inHg=0.0295299830714, - hPa2mmHg=0.7500615613030, - meter2feet=3.28084, - km2nm=0.539957, -} - --- Some ID to identify who we are in output of the DCS.log file. -- @field #string id PSEUDOATC.id="PseudoATC | " --- PSEUDOATC version. -- @field #number version -PSEUDOATC.version="0.7.0" +PSEUDOATC.version="0.9.0" ----------------------------------------------------------------------------------------------------------------------------------------- -- TODO list --- TODO: Add takeoff event. --- TODO: Add user functions. +-- DONE: Add takeoff event. +-- DONE: Add user functions. ----------------------------------------------------------------------------------------------------------------------------------------- ---- PSEUDOATC contructor. Starts the PseudoATC. +--- PSEUDOATC contructor. -- @param #PSEUDOATC self -- @return #PSEUDOATC Returns a PSEUDOATC object. function PSEUDOATC:New() @@ -118,9 +130,8 @@ function PSEUDOATC:New() return self end ---- PSEUDOATC contructor. Starts the PseudoATC. +--- Starts the PseudoATC event handlers. -- @param #PSEUDOATC self --- @return #PSEUDOATC Returns a PSEUDOATC object. function PSEUDOATC:Start() self:F() @@ -160,7 +171,19 @@ function PSEUDOATC:DebugOff() self.Debug=false end ---- Set message duration how long messages are displayed. +--- Chatty mode on. Display some messages on take-off and touchdown. +-- @param #PSEUDOATC self +function PSEUDOATC:ChattyOn() + self.chatty=true +end + +--- Chatty mode off. Don't display some messages on take-off and touchdown. +-- @param #PSEUDOATC self +function PSEUDOATC:ChattyOff() + self.chatty=false +end + +--- Set duration how long messages are displayed. -- @param #PSEUDOATC self -- @param #number duration Time in seconds. Default is 30 sec. function PSEUDOATC:SetMessageDuration(duration) @@ -169,18 +192,25 @@ 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 +-- @param #number interval Interval in seconds. Default is every 120 sec. +function PSEUDOATC:SetMenuRefresh(interval) + self.mrefresh=interval or 120 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) +-- @param #boolean switch If true, events are handled by MOOSE (default). If false, events are handled directly by DCS. +function PSEUDOATC:SetEventsMoose(switch) self.eventsmoose=switch end +--- Set time interval for reporting altitude until touchdown. +-- @param #PSEUDOATC self +-- @param #number interval Interval in seconds. Default is every 3 sec. +function PSEUDOATC:SetReportAltInterval(interval) + self.talt=interval or 3 +end + ----------------------------------------------------------------------------------------------------------------------------------------- -- Event Handling @@ -231,7 +261,7 @@ function PSEUDOATC:onEvent(Event) end -- Event takeoff. - if Event.id == world.event.S_EVENT_TAKEOFF and _playername then + if Event.id == world.event.S_EVENT_TAKEOFF and _playername and EventData.Place then self:_PlayerTakeOff(EventData) end @@ -259,12 +289,7 @@ function PSEUDOATC:onEvent(Event) 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 --- Function called my MOOSE event handler when a player enters a unit. @@ -376,7 +401,7 @@ function PSEUDOATC:PlayerEntered(unit) self.player[GID].waypoints=group:GetTaskRoute() -- Info message. - local text=string.format("Player %s entered unit %s of group %s. ID = %d", PlayerName, UnitName, GroupName, GID) + local text=string.format("Player %s entered unit %s of group %s (id=%d).", PlayerName, UnitName, GroupName, GID) self:T(PSEUDOATC.id..text) MESSAGE:New(text, 30):ToAllIf(self.Debug) @@ -414,7 +439,7 @@ function PSEUDOATC:PlayerLanded(unit, place) local CallSign=self.player[id].callsign -- Debug message. - local text=string.format("Player %s (%s) from group %s (ID %d) landed at %s", PlayerName, UnitName, GroupName, id, place) + local text=string.format("Player %s in unit %s of group %s (id=%d) landed at %s.", PlayerName, UnitName, GroupName, id, place) self:T(PSEUDOATC.id..text) MESSAGE:New(text, 30):ToAllIf(self.Debug) @@ -422,7 +447,7 @@ function PSEUDOATC:PlayerLanded(unit, place) self:AltitudeTimerStop(id) -- Welcome message. - if place then + if place and self.chatty then local text=string.format("Touchdown! Welcome to %s. Have a nice day!", place) MESSAGE:New(text, self.mdur):ToGroup(group) end @@ -446,13 +471,13 @@ function PSEUDOATC:PlayerTakeOff(unit, place) 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) + local text=string.format("Player %s in unit %s of 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) + if place and self.chatty then + local text=string.format("%s, %s, you are airborn. Have a save trip!", place, CallSign) MESSAGE:New(text, self.mdur):ToGroup(group) end @@ -468,26 +493,30 @@ function PSEUDOATC:PlayerLeft(unit) local group=unit:GetGroup() local id=group:GetID() - -- Debug message. - local text=string.format("Player %s (%s) callsign %s of group %s just left.", self.player[id].playername, self.player[id].unitname, self.player[id].callsign, self.player[id].groupname) - self:T(PSEUDOATC.id..text) - MESSAGE:New(text, 30):ToAllIf(self.Debug) + if self.player[id] then - -- Stop scheduler for menu updates - if self.player[id].schedulerid then - self.player[id].scheduler:Stop(self.player[id].schedulerid) + -- Debug message. + local text=string.format("Player %s (callsign %s) of group %s just left unit %s.", self.player[id].playername, self.player[id].callsign, self.player[id].groupname, self.player[id].unitname) + self:T(PSEUDOATC.id..text) + MESSAGE:New(text, 30):ToAllIf(self.Debug) + + -- Stop scheduler for menu updates + if self.player[id].schedulerid then + self.player[id].scheduler:Stop(self.player[id].schedulerid) + end + + -- Stop scheduler for reporting alt if it runs. + self:AltitudeTimerStop(id) + + -- Remove main menu. + if self.player[id].menu_main then + missionCommands.removeItem(self.player[id].menu_main) + end + + -- Remove player array. + self.player[id]=nil + end - - -- Stop scheduler for reporting alt if it runs. - self:AltitudeTimerStop(id) - - -- Remove main menu. - if self.player[id].menu_main then - missionCommands.removeItem(self.player[id].menu_main) - end - - -- Remove player array. - self.player[id]=nil end ----------------------------------------------------------------------------------------------------------------------------------------- @@ -551,14 +580,14 @@ function PSEUDOATC:MenuClear(id) end -- Delete request current alt menu command. - if self.player[id].menu_requesttalt then + if self.player[id].menu_requestalt then missionCommands.removeItemForGroup(id, self.player[id].menu_requestalt) self.player[id].menu_requestalt=nil end end ---- Create "F10/Pseudo ATC/Local Airports" menu item. +--- Create "F10/Pseudo ATC/Local Airports/Airport Name/" menu items each containing weather report and BR request. -- @param #PSEUDOATC self -- @param #number id Group id of player unit for which menues are created. function PSEUDOATC:MenuAirports(id) @@ -591,7 +620,7 @@ function PSEUDOATC:MenuAirports(id) end end ---- Create F10/Pseudo ATC/Waypoints menu items and misc items. +--- Create "F10/Pseudo ATC/Waypoints/ menu items. -- @param #PSEUDOATC self -- @param #number id Group id of player unit for which menues are created. function PSEUDOATC:MenuWaypoints(id) @@ -600,10 +629,9 @@ function PSEUDOATC:MenuWaypoints(id) -- Player unit and callsign. local unit=self.player[id].unit --Wrapper.Unit#UNIT local callsign=self.player[id].callsign - local name=string.format("My Aircraft (%s)", callsign) -- Debug info. - self:T(PSEUDOATC.id..string.format("Creating waypoint menu for %s (ID %d).", name, id)) + self:T(PSEUDOATC.id..string.format("Creating waypoint menu for %s (ID %d).", callsign, id)) if #self.player[id].waypoints>0 then @@ -633,8 +661,8 @@ function PSEUDOATC:MenuWaypoints(id) end end - self.player[id].menu_reportalt = missionCommands.addCommandForGroup(id, "Report alt until touchdown", self.player[id].menu_main, self.AltidudeTimerToggle, self, id) - self.player[id].menu_requestalt = missionCommands.addCommandForGroup(id, "Request altitude AGL", self.player[id].menu_main, self.ReportHeight, self, id) + self.player[id].menu_reportalt = missionCommands.addCommandForGroup(id, "Talk me down", self.player[id].menu_main, self.AltidudeTimerToggle, self, id) + self.player[id].menu_requestalt = missionCommands.addCommandForGroup(id, "Request altitude", self.player[id].menu_main, self.ReportHeight, self, id) end ----------------------------------------------------------------------------------------------------------------------------------------- @@ -657,28 +685,27 @@ function PSEUDOATC:ReportWeather(id, position, location) local Pqnh=position:GetPressure(0) -- Get pressure at sea level. local Pqfe=position:GetPressure() -- Get pressure at (land) height of position. + -- Pressure conversion + local hPa2inHg=0.0295299830714 + local hPa2mmHg=0.7500615613030 + -- Unit conversion. - local _Pqnh=string.format("%.2f inHg", Pqnh * PSEUDOATC.unit.hPa2inHg) - local _Pqfe=string.format("%.2f inHg", Pqfe * PSEUDOATC.unit.hPa2inHg) + local _Pqnh=string.format("%.2f inHg", Pqnh * hPa2inHg) + local _Pqfe=string.format("%.2f inHg", Pqfe * hPa2inHg) if settings:IsMetric() then - _Pqnh=string.format("%.1f mmHg", Pqnh * PSEUDOATC.unit.hPa2mmHg) - _Pqfe=string.format("%.1f mmHg", Pqfe * PSEUDOATC.unit.hPa2mmHg) + _Pqnh=string.format("%.1f mmHg", Pqnh * hPa2mmHg) + _Pqfe=string.format("%.1f mmHg", Pqfe * hPa2mmHg) end -- Message text. text=text..string.format("QFE %.1f hPa = %s.\n", Pqfe, _Pqfe) text=text..string.format("QNH %.1f hPa = %s.\n", Pqnh, _Pqnh) - --- convert celsius to fahrenheit - local function celsius2fahrenheit(degC) - return degC*1.8+32 - end - -- Get temperature at position in degrees Celsius. local T=position:GetTemperature() -- Correct unit system. - local _T=string.format('%d°F', celsius2fahrenheit(T)) + local _T=string.format('%d°F', UTILS.CelciusToFarenheit(T)) if settings:IsMetric() then _T=string.format('%d°C', T) end @@ -696,9 +723,9 @@ function PSEUDOATC:ReportWeather(id, position, location) local Ds = string.format('%03d°', Dir) -- Velocity in player units. - local Vs=string.format('%.1f m/s', Vel) - if settings:IsImperial() then - Vs=string.format("%.1f knots", Vel*1.94384) + local Vs=string.format("%.1f knots", UTILS.MpsToKnots(Vel)) + if settings:IsMetric() then + Vs=string.format('%.1f m/s', Vel) end -- Message text. @@ -709,111 +736,6 @@ function PSEUDOATC:ReportWeather(id, position, location) end ---- Report pressure. --- @param #PSEUDOATC self --- @param #number id Group id to which the report is delivered. --- @param #string Qcode Can be "QNH" for pressure at sea level or "QFE" for pressure at field elevation. Default is QFE or more precisely pressure at position. --- @param Core.Point#COORDINATE position Coordinates at which the pressure is measured. --- @param #string location Name of the location at which the pressure is measured. -function PSEUDOATC:ReportPressure(id, Qcode, position, location) - self:F({id=id, Qcode=Qcode, position=position, location=location}) - - -- Get pressure in hPa. - local P - if Qcode=="QNH" then - P=position:GetPressure(0) -- Get pressure at sea level. - else - P=position:GetPressure() -- Get pressure at (land) height of position. - end - - -- Settings. - local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS - - -- Unit conversion. - local P_inHg=P * PSEUDOATC.unit.hPa2inHg - local P_mmHg=P * PSEUDOATC.unit.hPa2mmHg - - local P_set=string.format("%.2f inHg", P_inHg) - if settings:IsMetric() then - P_set=string.format("%.1f mmHg", P_mmHg) - end - - -- Message text. - local text=string.format("%s at %s: P = %.1f hPa = %s.", Qcode, location, P, P_set) - - -- Send message. - MESSAGE:New(text, self.mdur):ToGroup(self.player[id].group) -end - ---- Report temperature. --- @param #PSEUDOATC self --- @param #number id Group id to the report is delivered. --- @param Core.Point#COORDINATE position Coordinates at which the pressure is measured. --- @param #string location Name of the location at which the pressure is measured. -function PSEUDOATC:ReportTemperature(id, position, location) - self:F({id=id, position=position, location=location}) - - --- convert celsius to fahrenheit - local function celsius2fahrenheit(degC) - return degC*1.8+32 - end - - -- Get temperature at position in degrees Celsius. - local T=position:GetTemperature() - - -- Formatted temperature in Celsius and Fahrenheit. - local Tc=string.format('%d°C', T) - local Tf=string.format('%d°F', celsius2fahrenheit(T)) - - -- Settings. - local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS - - -- Correct unit system. - local _T=string.format('%d°F', celsius2fahrenheit(T)) - if settings:IsMetric() then - _T=string.format('%d°C', T) - end - - -- Message text. - local text=string.format("Temperature at %s is %s", location, _T) - - -- Send message to player group. - MESSAGE:New(text, self.mdur):ToGroup(self.player[id].group) -end - ---- Report wind direction and strength. --- @param #PSEUDOATC self --- @param #number id Group id to the report is delivered. --- @param Core.Point#COORDINATE position Coordinates at which the pressure is measured. --- @param #string location Name of the location at which the pressure is measured. -function PSEUDOATC:ReportWind(id, position, location) - self:F({id=id, position=position, location=location}) - - -- Get wind direction and speed. - local Dir,Vel=position:GetWind() - - -- Get Beaufort wind scale. - local Bn,Bd=UTILS.BeaufortScale(Vel) - - -- Formatted wind direction. - local Ds = string.format('%03d°', Dir) - - -- Player settings. - local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS - - -- Velocity in player units. - local Vs=string.format('%.1f m/s', Vel) - if settings:IsImperial() then - Vs=string.format("%.1f knots", Vel*1.94384) - end - - -- Message text. - local text=string.format("%s: Wind from %s at %s (%s).", location, Ds, Vs, Bd) - - -- Send message to player group. - MESSAGE:New(text, self.mdur):ToGroup(self.player[id].group) -end - --- Report absolute bearing and range form player unit to airport. -- @param #PSEUDOATC self -- @param #number id Group id to the report is delivered. @@ -838,9 +760,10 @@ function PSEUDOATC:ReportBR(id, position, location) -- Settings. local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS - local Rs=string.format("%.1f km", range/1000) - if settings:IsImperial() then - Rs=string.format("%.1f NM", range/1000 * PSEUDOATC.unit.km2nm) + + local Rs=string.format("%.1f NM", UTILS.MetersToNM(range)) + if settings:IsMetric() then + Rs=string.format("%.1f km", range/1000) end -- Message text. @@ -867,11 +790,9 @@ function PSEUDOATC:ReportHeight(id, dt, _clear) -- Return height [m] above ground level. local function get_AGL(p) local agl=0 - if p then - local vec2={x=p.x,y=p.z} - local ground=land.getHeight(vec2) - local agl=p.y-ground - end + local vec2={x=p.x,y=p.z} + local ground=land.getHeight(vec2) + local agl=p.y-ground return agl end @@ -887,16 +808,23 @@ function PSEUDOATC:ReportHeight(id, dt, _clear) -- Settings. local settings=_DATABASE:GetPlayerSettings(self.player[id].playername) or _SETTINGS --Core.Settings#SETTINGS - local Hs=string.format("%d m", height) + env.info("FF height = "..height) + + -- Height string. + local Hs=string.format("%d ft", UTILS.MetersToFeet(height)) if settings:IsMetric() then - Hs=string.format("%d ft", height*PSEUDOATC.unit.meter2feet) + Hs=string.format("%d m", height) end -- Message text. - local _text=string.format("%s: Your altitude is %s AGL.", callsign, Hs) + local _text=string.format("%s, your altitude is %s AGL.", callsign, Hs) + + -- Append flight level. + if _clear==false then + _text=_text..string.format(" FL%03d.", position.y/30.48) + end -- 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 @@ -908,7 +836,7 @@ end ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- Toggle report altitude reporting on/of. +--- Toggle report altitude reporting on/off. -- @param #PSEUDOATC self. -- @param #number id Group id of player unit. function PSEUDOATC:AltidudeTimerToggle(id) @@ -932,8 +860,7 @@ function PSEUDOATC:AltitudeTimeStart(id) -- Debug info. self:T(PSEUDOATC.id..string.format("Starting altitude report timer for player ID %d.", id)) - -- Start timer. - --self.player[id].altimer=timer.scheduleFunction(self.ReportAltTouchdown, self, id, Tnow+2) + -- Start timer. Altitude is reported every ~3 seconds. self.player[id].altimer, self.player[id].altimerid=SCHEDULER:New(nil, self.ReportHeight, {self, id, 0.1, true}, 1, 3) end @@ -946,7 +873,6 @@ function PSEUDOATC:AltitudeTimerStop(id) self:T(PSEUDOATC.id..string.format("Stopping altitude report timer for player ID %d.", id)) -- Stop timer. - --timer.removeFunction(self.player[id].alttimer) if self.player[id].altimerid then self.player[id].altimer:Stop(self.player[id].altimerid) end @@ -1061,3 +987,16 @@ function PSEUDOATC:_DisplayMessageToGroup(_unit, _text, _time, _clear) end +--- Returns a string which consits of this callsign and the player name. +-- @param #RANGE self +-- @param #string unitname Name of the player unit. +function PSEUDOATC:_myname(unitname) + self:F2(unitname) + + local unit=UNIT:FindByName(unitname) + local pname=unit:GetPlayerName() + local csign=unit:GetCallsign() + + return string.format("%s (%s)", csign, pname) +end + diff --git a/Moose Development/Moose/Functional/RAT.lua b/Moose Development/Moose/Functional/RAT.lua index d5e78cdce..91f42eb48 100644 --- a/Moose Development/Moose/Functional/RAT.lua +++ b/Moose Development/Moose/Functional/RAT.lua @@ -42,20 +42,21 @@ -- -- # Demo Missions -- --- ### [RAT Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/Release/RAT%20-%20Random%20Air%20Traffic) --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS) +-- ### [MOOSE - RAT Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/RAT%20-%20Random%20Air%20Traffic) -- -- === -- -- # YouTube Channel -- --- ### [DCS WORLD - MOOSE - RAT - Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO) +-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) +-- ### [MOOSE - RAT - Random Air Traffic](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0u4Zxywtg-mx_ov4vi68CO) -- -- === -- -- ### 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 Rat @@ -116,7 +117,7 @@ -- @field #boolean continuejourney Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination. -- @field #number ngroups Number of groups to be spawned in total. -- @field #number alive Number of groups which are alive. --- @field #boolean f10menu Add an F10 menu for RAT. +-- @field #boolean f10menu If true, add an F10 radiomenu for RAT. Default is false. -- @field #table Menu F10 menu items for this RAT object. -- @field #string SubMenuName Submenu name for RAT object. -- @field #boolean respawn_at_landing Respawn aircraft the moment they land rather than at engine shutdown. @@ -350,7 +351,7 @@ RAT={ continuejourney=false, -- Aircraft will continue their journey, i.e. get respawned at their destination with a new random destination. alive=0, -- Number of groups which are alive. ngroups=nil, -- Number of groups to be spawned in total. - f10menu=true, -- Add an F10 menu for RAT. + f10menu=false, -- Add an F10 menu for RAT. Menu={}, -- F10 menu items for this RAT object. SubMenuName=nil, -- Submenu name for RAT object. respawn_at_landing=false, -- Respawn aircraft the moment they land rather than at engine shutdown. @@ -506,7 +507,7 @@ RAT.id="RAT | " --- RAT version. -- @list version RAT.version={ - version = "2.2.1", + version = "2.2.2", print = true, } @@ -1363,6 +1364,21 @@ function RAT:Immortal() self.immortal=true end +--- Radio menu On. Default is off. +-- @param #RAT self +function RAT:RadioMenuON() + self:F2() + self.f10menu=true +end + +--- Radio menu Off. This is the default setting. +-- @param #RAT self +function RAT:RadioMenuOFF() + self:F2() + self.f10menu=false +end + + --- Activate uncontrolled aircraft. -- @param #RAT self -- @param #number maxactivated Maximal numnber of activated aircraft. Absolute maximum will be the number of spawned groups. Default is 1. diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index bf8cbb193..bce0b8ef1 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -32,12 +32,13 @@ -- -- # Demo Missions -- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS) -- -- === -- -- # YouTube Channel --- +-- +-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) -- ### [MOOSE - On the Range - Demonstration Video](https://www.youtube.com/watch?v=kIXcxNB9_3M) -- -- === diff --git a/Moose Development/Moose/Functional/Suppression.lua b/Moose Development/Moose/Functional/Suppression.lua index e9f42c626..8eb913930 100644 --- a/Moose Development/Moose/Functional/Suppression.lua +++ b/Moose Development/Moose/Functional/Suppression.lua @@ -1,5 +1,5 @@ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- **Functional** - Suppress fire of ground units when they get hit. +--- **Functional** - (R2.4) Suppress fire of ground units when they get hit. -- -- ![Banner Image](..\Presentations\SUPPRESSION\Suppression_Main.png) -- @@ -16,19 +16,19 @@ -- -- # Demo Missions -- --- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS) -- -- ==== -- -- # YouTube Channel -- --- ### [MOOSE YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) +-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) -- -- === -- -- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)** -- --- ### Contributions: **[FlightControl](https://forums.eagle.ru/member.php?u=89536)** +-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- -- ==== -- @module Suppression @@ -194,10 +194,6 @@ -- -- ![Process](..\Presentations\SUPPRESSION\Suppression_Example_01.png) -- --- ## Suppression and Rescure --- This example shows how the event **Retreat** can be captured. Here, a transport is started which picks up the wounded troups and drives them to a safe zone. --- --- ![Process](..\Presentations\SUPPRESSION\Suppression_Rescue.png) -- -- # Customization and Fine Tuning -- The following user functions can be used to change the default values @@ -281,11 +277,11 @@ SUPPRESSION.MenuF10=nil --- Some ID to identify who we are in output of the DCS.log file. -- @field #string id -SUPPRESSION.id="SFX | " +SUPPRESSION.id="SUPPRESSION | " --- PSEUDOATC version. -- @field #number version -SUPPRESSION.version="0.7.0" +SUPPRESSION.version="0.9.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1333,6 +1329,7 @@ end -- @param #SUPPRESSION self -- @param Core.Event#EVENTDATA EventData function SUPPRESSION:_OnEventHit(EventData) + self:F(EventData) local GroupNameSelf=self.Controllable:GetName() local GroupNameTgt=EventData.TgtGroupName @@ -1343,7 +1340,7 @@ function SUPPRESSION:_OnEventHit(EventData) -- Check that correct group was hit. if GroupNameTgt == GroupNameSelf then - self:T2(SUPPRESSION.id..string.format("Hit event at t = %5.1f", timer.getTime())) + self:T(SUPPRESSION.id..string.format("Hit event at t = %5.1f", timer.getTime())) -- Flare unit that was hit. if self.flare or self.Debug then