From df0dbc9108598eeba4b854b0ee4751d8d97791f4 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 8 Feb 2024 11:59:23 +0100 Subject: [PATCH 01/73] PLAYERTASK - small fix for a possibly missing coordinate --- Moose Development/Moose/Ops/PlayerTask.lua | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/PlayerTask.lua b/Moose Development/Moose/Ops/PlayerTask.lua index 643355ed8..e0c7f8c60 100644 --- a/Moose Development/Moose/Ops/PlayerTask.lua +++ b/Moose Development/Moose/Ops/PlayerTask.lua @@ -21,7 +21,7 @@ -- === -- @module Ops.PlayerTask -- @image OPS_PlayerTask.jpg --- @date Last Update Jan 2024 +-- @date Last Update Feb 2024 do @@ -411,6 +411,15 @@ function PLAYERTASK:IsDone() return IsDone end +--- [User] Check if PLAYERTASK has clients assigned to it. +-- @param #PLAYERTASK self +-- @return #boolean hasclients +function PLAYERTASK:HasClients() + self:T(self.lid.."HasClients?") + local hasclients = self:CountClients() > 0 and true or false + return hasclients +end + --- [User] Get client names assigned as table of #strings -- @param #PLAYERTASK self -- @return #table clients @@ -1552,7 +1561,7 @@ PLAYERTASKCONTROLLER.Messages = { --- PLAYERTASK class version. -- @field #string version -PLAYERTASKCONTROLLER.version="0.1.64" +PLAYERTASKCONTROLLER.version="0.1.65" --- Create and run a new TASKCONTROLLER instance. -- @param #PLAYERTASKCONTROLLER self @@ -3173,7 +3182,7 @@ function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Task, Group, Client) local ttsname = self.gettext:GetEntry("TASKNAMETTS",self.locale) local taskname = string.format(tname,task.Type,task.PlayerTaskNr) local ttstaskname = string.format(ttsname,task.TTSType,task.PlayerTaskNr) - local Coordinate = task.Target:GetCoordinate() + local Coordinate = task.Target:GetCoordinate() or COORDINATE:New(0,0,0) local CoordText = "" local CoordTextLLDM = nil if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then From 4b84d227f0d51b856172707c404d50dec91cfbfe Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Mon, 12 Feb 2024 18:34:12 +0100 Subject: [PATCH 02/73] Spawn - reference original template when using SpawnWithAlias in Group.TemplateDonor --- Moose Development/Moose/Core/Spawn.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index c7095dc8f..a6651a7c1 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -1699,6 +1699,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth ) end self.SpawnGroups[self.SpawnIndex].Spawned = true + self.SpawnGroups[self.SpawnIndex].Group.TemplateDonor = self.SpawnTemplatePrefix return self.SpawnGroups[self.SpawnIndex].Group else -- self:E( { self.SpawnTemplatePrefix, "No more Groups to Spawn:", SpawnIndex, self.SpawnMaxGroups } ) From 67e52120d4c0d7d68d604733add59cb2e0f7ee2e Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Mon, 12 Feb 2024 18:35:22 +0100 Subject: [PATCH 03/73] Nicer BASE:I() etc output --- Moose Development/Moose/Core/Base.lua | 51 +++++++-------------- Moose Development/Moose/Utilities/Utils.lua | 18 ++++++-- 2 files changed, 29 insertions(+), 40 deletions(-) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index ce3675189..dede44ad3 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -1144,6 +1144,18 @@ function BASE:TraceClassMethod( Class, Method ) self:I( "Tracing method " .. Method .. " of class " .. Class ) end +--- (Internal) Serialize arguments +-- @param #BASE self +-- @param #table Arguments +-- @return #string Text +function BASE:_Serialize(Arguments) + local text = UTILS.PrintTableToLog({Arguments}, 0, true) + text = string.gsub(text,"\n","") + text = string.gsub(text,"%(%(","%(") + text = string.gsub(text,"%)%)","%)") + return text +end + --- Trace a function call. This function is private. -- @param #BASE self -- @param Arguments A #table or any field. @@ -1168,7 +1180,7 @@ function BASE:_F( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if DebugInfoFrom then LineFrom = DebugInfoFrom.currentline end - env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "F", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) ) + env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "F", self.ClassName, self.ClassID, Function, BASE:_Serialize(Arguments) ) ) end end end @@ -1242,7 +1254,7 @@ function BASE:_T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if DebugInfoFrom then LineFrom = DebugInfoFrom.currentline end - env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s", LineCurrent, LineFrom, "T", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) ) + env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s", LineCurrent, LineFrom, "T", self.ClassName, self.ClassID, BASE:_Serialize(Arguments) ) ) end end end @@ -1314,7 +1326,7 @@ function BASE:E( Arguments ) env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) ) else - env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) ) + env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, BASE:_Serialize(Arguments) ) ) end end @@ -1341,39 +1353,8 @@ function BASE:I( Arguments ) env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) ) else - env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, UTILS.BasicSerialize( Arguments ) ) ) + env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, BASE:_Serialize(Arguments)) ) end end ---- old stuff - --- function BASE:_Destructor() --- --self:E("_Destructor") --- --- --self:EventRemoveAll() --- end - --- THIS IS WHY WE NEED LUA 5.2 ... --- function BASE:_SetDestructor() --- --- -- TODO: Okay, this is really technical... --- -- When you set a proxy to a table to catch __gc, weak tables don't behave like weak... --- -- Therefore, I am parking this logic until I've properly discussed all this with the community. --- --- local proxy = newproxy(true) --- local proxyMeta = getmetatable(proxy) --- --- proxyMeta.__gc = function () --- env.info("In __gc for " .. self:GetClassNameAndID() ) --- if self._Destructor then --- self:_Destructor() --- end --- end --- --- -- keep the userdata from newproxy reachable until the object --- -- table is about to be garbage-collected - then the __gc hook --- -- will be invoked and the destructor called --- rawset( self, '__proxy', proxy ) --- --- end diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 259f6d223..6005dcbce 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -444,10 +444,11 @@ end --- Print a table to log in a nice format -- @param #table table The table to print -- @param #number indent Number of indents +-- @param #boolean noprint Don't log but return text -- @return #string text Text created on the fly of the log output -function UTILS.PrintTableToLog(table, indent) +function UTILS.PrintTableToLog(table, indent, noprint) local text = "\n" - if not table then + if not table or type(table) ~= "table" then env.warning("No table passed!") return nil end @@ -455,11 +456,16 @@ function UTILS.PrintTableToLog(table, indent) for k, v in pairs(table) do if string.find(k," ") then k='"'..k..'"'end if type(v) == "table" then - env.info(string.rep(" ", indent) .. tostring(k) .. " = {") + if not noprint then + env.info(string.rep(" ", indent) .. tostring(k) .. " = {") + end text = text ..string.rep(" ", indent) .. tostring(k) .. " = {\n" text = text .. tostring(UTILS.PrintTableToLog(v, indent + 1)).."\n" - env.info(string.rep(" ", indent) .. "},") + if not noprint then + env.info(string.rep(" ", indent) .. "},") + end text = text .. string.rep(" ", indent) .. "},\n" + elseif type(v) == "function" then else local value if tostring(v) == "true" or tostring(v) == "false" or tonumber(v) ~= nil then @@ -467,7 +473,9 @@ function UTILS.PrintTableToLog(table, indent) else value = '"'..tostring(v)..'"' end - env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n") + if not noprint then + env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n") + end text = text .. string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n" end end From 7dcff7ec9c543cb6f06914b18b15774bdfd00569 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 13 Feb 2024 16:43:45 +0100 Subject: [PATCH 04/73] CommandSetInvisible/CommandSetImmortal right word order --- Moose Development/Moose/Wrapper/Group.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 52741e2c2..a37c32132 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -2780,6 +2780,14 @@ end -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. -- @return #GROUP self function GROUP:SetCommandInvisible(switch) + return self:CommandSetInvisible(switch) +end + +--- Switch on/off invisible flag for the group. +-- @param #GROUP self +-- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. +-- @return #GROUP self +function GROUP:CommandSetInvisible(switch) self:F2( self.GroupName ) if switch==nil then switch=false @@ -2794,6 +2802,14 @@ end -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. -- @return #GROUP self function GROUP:SetCommandImmortal(switch) + return self:CommandSetImmortal(switch) +end + +--- Switch on/off immortal flag for the group. +-- @param #GROUP self +-- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. +-- @return #GROUP self +function GROUP:CommandSetImmortal(switch) self:F2( self.GroupName ) if switch==nil then switch=false From 154026fbf86036061875c4f97844b27397cf4477 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 4 Jan 2024 15:09:48 +0100 Subject: [PATCH 05/73] New guides added --- docs/advanced/basics.md | 80 +++++++++++++++++++++++++++ docs/advanced/desanitize-dcs.md | 2 +- docs/advanced/eclipse-installation.md | 2 +- docs/advanced/text-to-speech.md | 2 +- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 docs/advanced/basics.md diff --git a/docs/advanced/basics.md b/docs/advanced/basics.md new file mode 100644 index 000000000..edf74a23c --- /dev/null +++ b/docs/advanced/basics.md @@ -0,0 +1,80 @@ +--- +title: Basics +parent: Advanced +nav_order: 01 +--- + +If you want to get deeper into Moose, you will encounter a few terms and +concepts that we will explain here. You will need them for the later pages. + +# Git and GitHub + +Moose has about 260.000 lines of code and the amount is increasing each week. +To maintain such a big code base a vcs (version control system) is needed. +Moose uses [Git], a distributed source code management created 2005 by Linus +Torvalds for the development of the Linux kernel. + +As developer platform [GitHub] was choosen as a central place for Moose +to create, store, and manage the code. [GitHub] use [Git] for version control +and provides additional functionality like access control, bug tracking, feature +requests and much more. + +As a Moose you don't need to learn to use [Git]. You can download the files on +[GitHub] with a browser. But using [Git] will ease up the steps to keep the +Moose version on your hard disk up to date. + +You will need to interact with [GitHub]. At least to download the Moose files. +For non developers the page can be confusing. Take your time and read this +documentation. We are not able to explain every single detail on using [GitHub] +and [Git]. Especially because it is changing really quick and this documentaion +will not. So try to uns the help system of [GitHub] or find some videos on +[YouTube]. If you get stuck ask for help in the [Moose Discord]. + +Moose uses more then one repository on [GitHub] which doesn't exactly make it +any clearer. A list can be found on the [reposities] page. + +# Branches: master & develop + +As already explained in the [overview] two branches are used: + +- [master]: Stable release branch. +- [develop]: Newest development with more OPS classes. + +As a starter it is okay to begin your journey with the `master` branch. +If you are interested in some newer classes you need to use the `develop` +branch. The later one is also very stable, but it's missing more detailed +documentation and example missions. + +You can switch between these branches with a drop down in the upper left corner +of th GitHub repository page. The list of branches is long. So it is a best +practise to save a bookmark in your browser with the links above. + +# Build result vs. source files + +Moose consists of more than 140 individual files with the file extension `.lua`. +They are places in a directory tree, which makes it more organized and its +semantic is pre-defined for IntelliSense to work. + +On every change which is pushed to [GitHub] a build job will combine all of +these files to a the single file called `Moose.lua`. In a seconds step all +comments will be removed to decrease the file size and the result will be saved +as `Moose_.lua`. These both files are created for users of Moose to include in +your missions. + +The individual `.lua` files are used by the Mosse developers and power users. +It is complicated to use them, but in combination with an IDE and a debugger it +is very usefull to analyse even complex problems or write new additions to the +Moose framework. + +# Static loading vs. dynamic loading + +# IDE vs. Notepad++ + +# What is a debugger (good for) + +[Git]: https://en.wikipedia.org/wiki/Git +[Moose Discord]: https://discord.gg/gj68fm969S +[overview]: ../index.md +[reposities]: ../repositories.md +[master]: https://github.com/FlightControl-Master/MOOSE/tree/master +[develop]: https://github.com/FlightControl-Master/MOOSE/tree/develop diff --git a/docs/advanced/desanitize-dcs.md b/docs/advanced/desanitize-dcs.md index 91fad46d1..2134802ae 100644 --- a/docs/advanced/desanitize-dcs.md +++ b/docs/advanced/desanitize-dcs.md @@ -1,7 +1,7 @@ --- title: De-Sanitize DCS parent: Advanced -nav_order: 2 +nav_order: 98 --- # De-Sanitize the DCS scripting environment {: .no_toc } diff --git a/docs/advanced/eclipse-installation.md b/docs/advanced/eclipse-installation.md index 0bdcd37cb..942fff30c 100644 --- a/docs/advanced/eclipse-installation.md +++ b/docs/advanced/eclipse-installation.md @@ -1,6 +1,6 @@ --- parent: Advanced -nav_order: 1 +nav_order: 97 --- # Eclipse Installation {: .no_toc } diff --git a/docs/advanced/text-to-speech.md b/docs/advanced/text-to-speech.md index 129039708..c3851da25 100644 --- a/docs/advanced/text-to-speech.md +++ b/docs/advanced/text-to-speech.md @@ -1,6 +1,6 @@ --- parent: Advanced -nav_order: 2 +nav_order: 99 --- # Text to Speech {: .no_toc } From e895642157db05a2161e607ea77f36adbf7b5bee Mon Sep 17 00:00:00 2001 From: kaltokri Date: Fri, 19 Jan 2024 16:57:33 +0100 Subject: [PATCH 06/73] Small fixes in advanced guide --- docs/advanced/basics.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/docs/advanced/basics.md b/docs/advanced/basics.md index edf74a23c..8c1ee4a1b 100644 --- a/docs/advanced/basics.md +++ b/docs/advanced/basics.md @@ -11,17 +11,17 @@ concepts that we will explain here. You will need them for the later pages. Moose has about 260.000 lines of code and the amount is increasing each week. To maintain such a big code base a vcs (version control system) is needed. -Moose uses [Git], a distributed source code management created 2005 by Linus -Torvalds for the development of the Linux kernel. +Moose uses [Git], a distributed source code management system created 2005 by +Linus Torvalds for the development of the Linux kernel. As developer platform [GitHub] was choosen as a central place for Moose -to create, store, and manage the code. [GitHub] use [Git] for version control -and provides additional functionality like access control, bug tracking, feature -requests and much more. +to create, store, and manage the code. [GitHub] use [Git] as version control +system and provides additional functionality like access control, bug tracking, +feature requests and much more. -As a Moose you don't need to learn to use [Git]. You can download the files on -[GitHub] with a browser. But using [Git] will ease up the steps to keep the -Moose version on your hard disk up to date. +As a Moose user you don't need to learn how to use [Git]. You can download the +files on [GitHub] with a browser. But using [Git] will ease up the steps to keep +the Moose version on your hard disk up to date. You will need to interact with [GitHub]. At least to download the Moose files. For non developers the page can be confusing. Take your time and read this @@ -73,6 +73,8 @@ Moose framework. # What is a debugger (good for) [Git]: https://en.wikipedia.org/wiki/Git +[GitHub]: https://github.com/ +[YouTube]: https://www.youtube.com/ [Moose Discord]: https://discord.gg/gj68fm969S [overview]: ../index.md [reposities]: ../repositories.md From 15dd2cf7357d355e95d7f8e95f5c8e9bfa9f302a Mon Sep 17 00:00:00 2001 From: kaltokri Date: Mon, 22 Jan 2024 17:36:32 +0100 Subject: [PATCH 07/73] Renamed basic.md to concepts.md and added more text --- docs/advanced/{basics.md => concepts.md} | 56 ++++++++++++++++++------ 1 file changed, 43 insertions(+), 13 deletions(-) rename docs/advanced/{basics.md => concepts.md} (54%) diff --git a/docs/advanced/basics.md b/docs/advanced/concepts.md similarity index 54% rename from docs/advanced/basics.md rename to docs/advanced/concepts.md index 8c1ee4a1b..b75b5273c 100644 --- a/docs/advanced/basics.md +++ b/docs/advanced/concepts.md @@ -1,5 +1,5 @@ --- -title: Basics +title: Concepts parent: Advanced nav_order: 01 --- @@ -11,13 +11,9 @@ concepts that we will explain here. You will need them for the later pages. Moose has about 260.000 lines of code and the amount is increasing each week. To maintain such a big code base a vcs (version control system) is needed. -Moose uses [Git], a distributed source code management system created 2005 by -Linus Torvalds for the development of the Linux kernel. - -As developer platform [GitHub] was choosen as a central place for Moose -to create, store, and manage the code. [GitHub] use [Git] as version control -system and provides additional functionality like access control, bug tracking, -feature requests and much more. +Moose uses [GitHub] as developer platform to create, store, and manage the code. +[GitHub] uses [Git] as version control system and provides additional +functionality like access control, bug tracking, feature requests and much more. As a Moose user you don't need to learn how to use [Git]. You can download the files on [GitHub] with a browser. But using [Git] will ease up the steps to keep @@ -27,7 +23,7 @@ You will need to interact with [GitHub]. At least to download the Moose files. For non developers the page can be confusing. Take your time and read this documentation. We are not able to explain every single detail on using [GitHub] and [Git]. Especially because it is changing really quick and this documentaion -will not. So try to uns the help system of [GitHub] or find some videos on +will not. So try to use the help system of [GitHub] or find some videos on [YouTube]. If you get stuck ask for help in the [Moose Discord]. Moose uses more then one repository on [GitHub] which doesn't exactly make it @@ -43,20 +39,26 @@ As already explained in the [overview] two branches are used: As a starter it is okay to begin your journey with the `master` branch. If you are interested in some newer classes you need to use the `develop` branch. The later one is also very stable, but it's missing more detailed -documentation and example missions. +documentation and example missions for some of the new OPS classes. You can switch between these branches with a drop down in the upper left corner -of th GitHub repository page. The list of branches is long. So it is a best +of th [GitHub] repository page. The list of branches is long. So it is a best practise to save a bookmark in your browser with the links above. +Both branches are available on most of the different repositories. But because +of a limitation of [GitHub pages], we had to split the documentation in two +different repositories: + +- Documentation of `master` branch: [MOOSE_DOCS] +- Documentation of `develop` branch: [MOOSE_DOCS_DEVELOP] # Build result vs. source files Moose consists of more than 140 individual files with the file extension `.lua`. -They are places in a directory tree, which makes it more organized and its +They are places in a [directory tree], which makes it more organized and its semantic is pre-defined for IntelliSense to work. On every change which is pushed to [GitHub] a build job will combine all of -these files to a the single file called `Moose.lua`. In a seconds step all +these files to a single file called `Moose.lua`. In a second step all comments will be removed to decrease the file size and the result will be saved as `Moose_.lua`. These both files are created for users of Moose to include in your missions. @@ -68,6 +70,30 @@ Moose framework. # Static loading vs. dynamic loading +If you add a script file with a `DO SCRIPT FILE` trigger, like we described in +[Create your own Hello world], the script file will be copied into the mission +file. This mission file (file extension .MIZ) is only a compressed ZIP archive +with another file ending. + +If you change the script file after adding it to the mission, the changes are +not available on mission start. You have to re-add the script after each change. +This can be very annoying and often leads to forgetting to add the change again. +Then you wonder why the script does not deliver the desired result. + +But when the mission is finished you can upload it to your dedicated DCS server +or give it to a friend and it should run without problems. This way of embedding +the scripts do we call `static loading` and the resulting mission is very +portable. + +The other way on loading scripts is by using `DO SCRIPT`. This time the mission +editor don't show a file browse button. Instead you see a (very small) text +field to enter the code directly into it. It is only usefull for very small +script snippets. But we can use it to load a file from our hard drive like this: + +```lua +aaa +``` + # IDE vs. Notepad++ # What is a debugger (good for) @@ -80,3 +106,7 @@ Moose framework. [reposities]: ../repositories.md [master]: https://github.com/FlightControl-Master/MOOSE/tree/master [develop]: https://github.com/FlightControl-Master/MOOSE/tree/develop +[GitHub pages]: https://pages.github.com/ +[MOOSE_DOCS]: https://flightcontrol-master.github.io/MOOSE_DOCS/ +[MOOSE_DOCS_DEVELOP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/ +[directory tree]: https://github.com/FlightControl-Master/MOOSE/tree/master/Moose%20Development/Moose From 0ee7a38c618bec5defc9c70f1590affab7213198 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 1 Feb 2024 10:53:53 +0100 Subject: [PATCH 08/73] Added content to concepts.md and added an empty debugger.md --- docs/advanced/concepts.md | 100 ++++++++++++++++++++++++++++++++++++-- docs/advanced/debugger.md | 8 +++ 2 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 docs/advanced/debugger.md diff --git a/docs/advanced/concepts.md b/docs/advanced/concepts.md index b75b5273c..2b8d733d8 100644 --- a/docs/advanced/concepts.md +++ b/docs/advanced/concepts.md @@ -4,6 +4,12 @@ parent: Advanced nav_order: 01 --- +# Concepts +{: .no_toc } + +1. Table of contents +{:toc} + If you want to get deeper into Moose, you will encounter a few terms and concepts that we will explain here. You will need them for the later pages. @@ -68,7 +74,7 @@ It is complicated to use them, but in combination with an IDE and a debugger it is very usefull to analyse even complex problems or write new additions to the Moose framework. -# Static loading vs. dynamic loading +# Static loading If you add a script file with a `DO SCRIPT FILE` trigger, like we described in [Create your own Hello world], the script file will be copied into the mission @@ -85,18 +91,98 @@ or give it to a friend and it should run without problems. This way of embedding the scripts do we call `static loading` and the resulting mission is very portable. -The other way on loading scripts is by using `DO SCRIPT`. This time the mission +# Dynamic loading of mission scripts + +The other way of loading scripts is by using `DO SCRIPT`. This time the mission editor don't show a file browse button. Instead you see a (very small) text field to enter the code directly into it. It is only usefull for very small -script snippets. But we can use it to load a file from our hard drive like this: +script snippets. But we can use it to load a file from your hard drive like +this: ```lua -aaa +dofile('C:/MyScripts/hello-world.lua') +dofile('C:\\MyScripts\\hello-world.lua') +dofile([[C:\MyScripts\hello-world.lua]]) +``` + +So all lines above do the same. In [Lua] you need to specify the path with +slashes, escape backslashes or use double square brackets around the string. +But double square brackets is usefull, because you can copy paste the path +without any modification. + +If you upload a mission with this code, you need to create the folder +`C:\MyScripts\` on the server file system and upload the newest version of +`hello-world.lua`, too. The same applies if you give the mission to a friend. +This makes the mission less portable, but on the other hand the mission uses the +file on the hard disk without the need to add it to the mission again. +All you need to do is save the file and restart the mission. + +The following can be used to increase portability: + +```lua +dofile(lfs.writedir() .. '/Missions/hello-world.lua') +``` + +The function `lfs.writedir()` will return your [Saved Games folder]. +So you place the scripts in the subfolder Missions. This way the folder +structure is already available on all target systems. But you need to ensure +mission and script are both in sync to avoid problems. If you changed both and +upload only one of them to your server, you may get trouble. + +There is another method you may find usefull to dynamically load scripts: + +```lua +assert(loadfile('C:/MyScripts/hello-world.lua'))() +assert(loadfile('C:\\MyScripts\\hello-world.lua'))() +assert(loadfile([[C:\MyScripts\hello-world.lua]]))() +``` + +It is a little bit harder to read and write because of all these different +brackets. Especially the one on line 3. But it is a little safer then `dofile`. +Because of readability I prefer to use `dofile`. + +# Dynamic loading of Moose + +Of course you can use the same method to load Moose. This way you can place one +Moose file in your [Saved Games folder], which is used by multiple missions. +If you want to update Moose you just need to replace the file and all missions +will use the new version. But I prefer to add Moose by a `DO SCRIPT FILE` +trigger so I can add and test the new version for each mission step by step. + +But we added two different ways to load the Moose source files automatically. +This is usefull for Moose developers and it is a requirement to use a debugger. +This will be explained later in the [Debugger Guide]. + +# Automatic dynamic loading + +```lua +-- Use script file from hard disk instead of the one included in the .miz file +if lfs and io then + MissionScript = lfs.writedir() .. '/Missions/hello-world-autodyn.lua' + -- Check if the running skript is from temp directory to avoid an endless loop + if string.find( debug.getinfo(1).source, lfs.tempdir() ) then + local f=io.open(MissionScript,"r") + if f~=nil then + io.close(f) + + env.info( '*** LOAD MOOSE MISSION SCRIPT FROM HARD DISK *** ' ) + dofile(MissionScript) + do return end + end + end +else + env.error( '*** LOAD MOOSE MISSION SCRIPT FROM HARD DISK FAILED (Desanitize lfs and io)*** ' ) +end + +-- +-- Simple example mission to show the very basics of MOOSE +-- +MESSAGE:New( "Hello World! This messages is printed by MOOSE!", 35, "INFO" ):ToAll():ToLog() ``` # IDE vs. Notepad++ -# What is a debugger (good for) + [Git]: https://en.wikipedia.org/wiki/Git [GitHub]: https://github.com/ @@ -110,3 +196,7 @@ aaa [MOOSE_DOCS]: https://flightcontrol-master.github.io/MOOSE_DOCS/ [MOOSE_DOCS_DEVELOP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/ [directory tree]: https://github.com/FlightControl-Master/MOOSE/tree/master/Moose%20Development/Moose +[Saved Games folder]: ../beginner/tipps-and-tricks.md#find-the-saved-games-folder +[Lua]: https://www.lua.org/ +[Create your own Hello world]: ../beginner/hello-world-build.md +[Debugger Guide]: debugger.md diff --git a/docs/advanced/debugger.md b/docs/advanced/debugger.md new file mode 100644 index 000000000..2c43bff06 --- /dev/null +++ b/docs/advanced/debugger.md @@ -0,0 +1,8 @@ +--- +title: Debugger +parent: Advanced +nav_order: 100 +--- + +{: .warning } +> THIS DOCUMENT IS STILL WORK IN PROGRESS! From 51f134538d3965376640e2be490a46b3f20bfacf Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 15 Feb 2024 16:45:51 +0100 Subject: [PATCH 09/73] Fixing typos and added text for Automatic dynamic loading and IDEs --- docs/advanced/concepts.md | 101 ++++++++++++++++++++++++++++++-------- 1 file changed, 81 insertions(+), 20 deletions(-) diff --git a/docs/advanced/concepts.md b/docs/advanced/concepts.md index 2b8d733d8..a5c73de4d 100644 --- a/docs/advanced/concepts.md +++ b/docs/advanced/concepts.md @@ -26,21 +26,21 @@ files on [GitHub] with a browser. But using [Git] will ease up the steps to keep the Moose version on your hard disk up to date. You will need to interact with [GitHub]. At least to download the Moose files. -For non developers the page can be confusing. Take your time and read this +For non-developers the page can be confusing. Take your time and read this documentation. We are not able to explain every single detail on using [GitHub] -and [Git]. Especially because it is changing really quick and this documentaion +and [Git]. Especially because it is changing really quick and this documentation will not. So try to use the help system of [GitHub] or find some videos on [YouTube]. If you get stuck ask for help in the [Moose Discord]. -Moose uses more then one repository on [GitHub] which doesn't exactly make it +Moose uses more than one repository on [GitHub] which doesn't exactly make it any clearer. A list can be found on the [reposities] page. # Branches: master & develop As already explained in the [overview] two branches are used: -- [master]: Stable release branch. -- [develop]: Newest development with more OPS classes. +- Branch [master]: Stable release branch. +- Branch [develop]: Newest development with more OPS classes. As a starter it is okay to begin your journey with the `master` branch. If you are interested in some newer classes you need to use the `develop` @@ -48,8 +48,8 @@ branch. The later one is also very stable, but it's missing more detailed documentation and example missions for some of the new OPS classes. You can switch between these branches with a drop down in the upper left corner -of th [GitHub] repository page. The list of branches is long. So it is a best -practise to save a bookmark in your browser with the links above. +of the [GitHub] repository page. The list of branches is long. So it is a best +practice to save a bookmark in your browser with the links above. Both branches are available on most of the different repositories. But because of a limitation of [GitHub pages], we had to split the documentation in two different repositories: @@ -61,7 +61,7 @@ different repositories: Moose consists of more than 140 individual files with the file extension `.lua`. They are places in a [directory tree], which makes it more organized and its -semantic is pre-defined for IntelliSense to work. +semantic is pre-defined for [IntelliSense] to work. On every change which is pushed to [GitHub] a build job will combine all of these files to a single file called `Moose.lua`. In a second step all @@ -69,9 +69,9 @@ comments will be removed to decrease the file size and the result will be saved as `Moose_.lua`. These both files are created for users of Moose to include in your missions. -The individual `.lua` files are used by the Mosse developers and power users. +The individual `.lua` files are used by the Moose developers and power users. It is complicated to use them, but in combination with an IDE and a debugger it -is very usefull to analyse even complex problems or write new additions to the +is very useful to analyze even complex problems or write new additions to the Moose framework. # Static loading @@ -84,7 +84,7 @@ with another file ending. If you change the script file after adding it to the mission, the changes are not available on mission start. You have to re-add the script after each change. This can be very annoying and often leads to forgetting to add the change again. -Then you wonder why the script does not deliver the desired result. +Then you wonder why the mission does not deliver the desired result. But when the mission is finished you can upload it to your dedicated DCS server or give it to a friend and it should run without problems. This way of embedding @@ -95,7 +95,7 @@ portable. The other way of loading scripts is by using `DO SCRIPT`. This time the mission editor don't show a file browse button. Instead you see a (very small) text -field to enter the code directly into it. It is only usefull for very small +field to enter the code directly into it. It is only useful for very small script snippets. But we can use it to load a file from your hard drive like this: @@ -107,14 +107,14 @@ dofile([[C:\MyScripts\hello-world.lua]]) So all lines above do the same. In [Lua] you need to specify the path with slashes, escape backslashes or use double square brackets around the string. -But double square brackets is usefull, because you can copy paste the path +Double square brackets are usefull, because you can copy paste the path without any modification. If you upload a mission with this code, you need to create the folder `C:\MyScripts\` on the server file system and upload the newest version of -`hello-world.lua`, too. The same applies if you give the mission to a friend. +`hello-world.lua`, too. The same applies, if you give the mission to a friend. This makes the mission less portable, but on the other hand the mission uses the -file on the hard disk without the need to add it to the mission again. +file on the hard disk, without the need to add it to the mission again. All you need to do is save the file and restart the mission. The following can be used to increase portability: @@ -129,7 +129,7 @@ structure is already available on all target systems. But you need to ensure mission and script are both in sync to avoid problems. If you changed both and upload only one of them to your server, you may get trouble. -There is another method you may find usefull to dynamically load scripts: +There is another method you may find useful to dynamically load scripts: ```lua assert(loadfile('C:/MyScripts/hello-world.lua'))() @@ -138,7 +138,7 @@ assert(loadfile([[C:\MyScripts\hello-world.lua]]))() ``` It is a little bit harder to read and write because of all these different -brackets. Especially the one on line 3. But it is a little safer then `dofile`. +brackets. Especially the one on line 3. But it is a little safer than `dofile`. Because of readability I prefer to use `dofile`. # Dynamic loading of Moose @@ -150,11 +150,31 @@ will use the new version. But I prefer to add Moose by a `DO SCRIPT FILE` trigger so I can add and test the new version for each mission step by step. But we added two different ways to load the Moose source files automatically. -This is usefull for Moose developers and it is a requirement to use a debugger. +This is useful for Moose developers and it is a requirement to use a debugger. This will be explained later in the [Debugger Guide]. # Automatic dynamic loading +With the code below you can have the advantages of both approaches. +- Copy the code into your mission script at the beginning. +- Save the mission script into the folder Missions in your [Saved Games folder]. +- Change script filename in line 2 to match to your script. +- [De-Sanitize] your `MissionScripting.lua`. + +Now the mission will use the script on your hard drive instead of the script +embedded in th MIZ file, as long as it is available. So you can chnge the +script, save it and restart the mission, without the need to readd it after each +change. + +If you reach a stable state in your script development and want to upload the +mission to your server or give it to a friend, then just add the script again +like in the static method and save the mission. + +{: .important } +> Do not forget to readd the script, prior uploading or sharing the mission, +> or it will run with an outdated version of your script and may fail if the +> objects in the mission don't match to this old version. + ```lua -- Use script file from hard disk instead of the one included in the .miz file if lfs and io then @@ -165,13 +185,13 @@ if lfs and io then if f~=nil then io.close(f) - env.info( '*** LOAD MOOSE MISSION SCRIPT FROM HARD DISK *** ' ) + env.info( '*** LOAD MISSION SCRIPT FROM HARD DISK *** ' ) dofile(MissionScript) do return end end end else - env.error( '*** LOAD MOOSE MISSION SCRIPT FROM HARD DISK FAILED (Desanitize lfs and io)*** ' ) + env.error( '*** LOAD MISSION SCRIPT FROM HARD DISK FAILED (Desanitize lfs and io)*** ' ) end -- @@ -182,7 +202,41 @@ MESSAGE:New( "Hello World! This messages is printed by MOOSE!", 35, "INFO" ):ToA # IDE vs. Notepad++ +As a beginner you should start with a good text editor, which supports syntax +highlighting of [Lua] code. This must not be [Notepad++]. It can be any other +powerful editor of your choice. Do yourself a favor and don't use the Windows +editor. +If you are a developer of [Lua] or another programming language, then your are +most likely familiar with an IDE (Integrated Develop Environment). + +Otherwise you should know, that an IDE may help you with code completion, +Refactoring, Autocorrection, Formatting Source Code, showing documentation +as popup on mouse hover over keywords and Debugging. + +There are different IDEs available. And not all IDEs support all features. +The three most important for Moose are: + +- [Eclipse LDT] +- [Visual Studio Code] +- [PyCharm] (or [IntelliJ IDEA]) + +Eclipse has the best support for hover documentation and [IntelliSense] with +Moose. The Inventor of Moose (FlightControl) did an amazing job by adding an +integration to Eclipse LDT (a special version for Lua). +Unfortunately Eclipse LDT is not maintained any longer (last release 2018). +And the debugger doesn't work anymore, since an update of DCS. + +In Visual Studio Code the support of Lua can be added by an addon. +The debugger works with Moose and DCS, but showing the LuaDoc and [IntelliSense] +is very limited. + +PyCharm supports Lua also with an addon. The debugger works with Moose and DCS, +but showing the LuaDoc and [IntelliSense] is very limited. + +It is up to you to choose the IDE according to your taste. Guides on how to +setup Moose with different IDEs and Debuggers are provided later in this +documentation. [Git]: https://en.wikipedia.org/wiki/Git [GitHub]: https://github.com/ @@ -200,3 +254,10 @@ MESSAGE:New( "Hello World! This messages is printed by MOOSE!", 35, "INFO" ):ToA [Lua]: https://www.lua.org/ [Create your own Hello world]: ../beginner/hello-world-build.md [Debugger Guide]: debugger.md +[IntelliSense]: https://en.wikipedia.org/wiki/IntelliSense +[De-Sanitize]: desanitize-dcs.md +[Notepad++]: https://notepad-plus-plus.org/downloads/ +[Eclipse LDT]: https://projects.eclipse.org/projects/tools.ldt +[Visual Studio Code]: https://code.visualstudio.com/ +[PyCharm]: https://www.jetbrains.com/pycharm/ +[IntelliJ IDEA]: https://www.jetbrains.com/idea/ From e5a60a2ef1fcf9271477eea34ca4eed69cb56034 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 15 Feb 2024 18:17:44 +0100 Subject: [PATCH 10/73] #AWACS * Ensure not only one Merged-Call * Enable Tac, Meld, Threat calls also for non-tasked flights --- Moose Development/Moose/Ops/Awacs.lua | 58 ++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 5df0f7f42..c3cfc95d8 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -508,7 +508,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "0.2.61", -- #string + version = "0.2.62", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -2499,13 +2499,22 @@ function AWACS:_CheckMerges() local cpos = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate() local dist = ppos:Get2DDistance(cpos) local distnm = UTILS.Round(UTILS.MetersToNM(dist),0) - if (pilot.IsPlayer or self.debug) and distnm <= 5 and not contact.MergeCallDone then - local label = contact.EngagementTag or "" - if not contact.MergeCallDone or not string.find(label,pcallsign) then + if (pilot.IsPlayer or self.debug) and distnm <= 5 then --and ((not contact.MergeCallDone) or (timer.getTime() - contact.MergeCallDone > 30)) then + --local label = contact.EngagementTag or "" + --if not contact.MergeCallDone or not string.find(label,pcallsign) then self:T(self.lid.."Merged") self:_MergedCall(_id) - contact.MergeCallDone = true - end + --contact.MergeCallDone = true + --end + end + if (pilot.IsPlayer or self.debug) and distnm >5 and distnm <= self.ThreatDistance then + self:_ThreatRangeCall(_id,Contact) + end + if (pilot.IsPlayer or self.debug) and distnm > self.ThreatDistance and distnm <= self.MeldDistance then + self:_MeldRangeCall(_id,Contact) + end + if (pilot.IsPlayer or self.debug) and distnm > self.MeldDistance and distnm <= self.TacDistance then + self:_TACRangeCall(_id,Contact) end end ) @@ -3099,7 +3108,7 @@ function AWACS:_BogeyDope(Group,Tactical) local clean = self.gettext:GetEntry("CLEAN",self.locale) text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true,Tactical) + self:_NewRadioEntry(text,text,GID,Outcome,Outcome,true,false,true,Tactical) else @@ -5467,7 +5476,7 @@ function AWACS:_TACRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local contact = Contact.Contact -- Ops.Intel#INTEL.Contact local contacttag = Contact.TargetGroupNaming - if contact and not Contact.TACCallDone then + if contact then --and not Contact.TACCallDone then local position = contact.position -- Core.Point#COORDINATE if position then local distance = position:Get2DDistance(managedgroup.Group:GetCoordinate()) @@ -5477,6 +5486,15 @@ function AWACS:_TACRangeCall(GID,Contact) local text = string.format("%s. %s. %s %s, %d %s.",self.callsigntxt,pilotcallsign,contacttag,grptxt,distance,miles) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,false,AWACS.TaskStatus.EXECUTING) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self @@ -5495,8 +5513,8 @@ function AWACS:_MeldRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local flightpos = managedgroup.Group:GetCoordinate() local contact = Contact.Contact -- Ops.Intel#INTEL.Contact - local contacttag = Contact.TargetGroupNaming - if contact and not Contact.MeldCallDone then + local contacttag = Contact.TargetGroupNaming or "Bogey" + if contact then --and not Contact.MeldCallDone then local position = contact.position -- Core.Point#COORDINATE if position then local BRATExt = "" @@ -5509,6 +5527,15 @@ function AWACS:_MeldRangeCall(GID,Contact) local text = string.format("%s. %s. %s %s, %s",self.callsigntxt,pilotcallsign,contacttag,grptxt,BRATExt) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,true,AWACS.TaskStatus.EXECUTING) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self @@ -5525,7 +5552,7 @@ function AWACS:_ThreatRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local flightpos = managedgroup.Group:GetCoordinate() or managedgroup.LastKnownPosition local contact = Contact.Contact -- Ops.Intel#INTEL.Contact - local contacttag = Contact.TargetGroupNaming + local contacttag = Contact.TargetGroupNaming or "Bogey" if contact then local position = contact.position or contact.group:GetCoordinate() -- Core.Point#COORDINATE if position then @@ -5539,6 +5566,15 @@ function AWACS:_ThreatRangeCall(GID,Contact) local thrt = self.gettext:GetEntry("THREAT",self.locale) local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self From 6ca459b38cb600f37f8b2efe2500904a0b949aea Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 15 Feb 2024 18:18:19 +0100 Subject: [PATCH 11/73] xx --- Moose Development/Moose/Ops/Awacs.lua | 58 ++++++++++++++++++++++----- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index 5df0f7f42..c3cfc95d8 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -508,7 +508,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "0.2.61", -- #string + version = "0.2.62", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -2499,13 +2499,22 @@ function AWACS:_CheckMerges() local cpos = contact.Cluster.coordinate or contact.Contact.position or contact.Contact.group:GetCoordinate() local dist = ppos:Get2DDistance(cpos) local distnm = UTILS.Round(UTILS.MetersToNM(dist),0) - if (pilot.IsPlayer or self.debug) and distnm <= 5 and not contact.MergeCallDone then - local label = contact.EngagementTag or "" - if not contact.MergeCallDone or not string.find(label,pcallsign) then + if (pilot.IsPlayer or self.debug) and distnm <= 5 then --and ((not contact.MergeCallDone) or (timer.getTime() - contact.MergeCallDone > 30)) then + --local label = contact.EngagementTag or "" + --if not contact.MergeCallDone or not string.find(label,pcallsign) then self:T(self.lid.."Merged") self:_MergedCall(_id) - contact.MergeCallDone = true - end + --contact.MergeCallDone = true + --end + end + if (pilot.IsPlayer or self.debug) and distnm >5 and distnm <= self.ThreatDistance then + self:_ThreatRangeCall(_id,Contact) + end + if (pilot.IsPlayer or self.debug) and distnm > self.ThreatDistance and distnm <= self.MeldDistance then + self:_MeldRangeCall(_id,Contact) + end + if (pilot.IsPlayer or self.debug) and distnm > self.MeldDistance and distnm <= self.TacDistance then + self:_TACRangeCall(_id,Contact) end end ) @@ -3099,7 +3108,7 @@ function AWACS:_BogeyDope(Group,Tactical) local clean = self.gettext:GetEntry("CLEAN",self.locale) text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt) - self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true,Tactical) + self:_NewRadioEntry(text,text,GID,Outcome,Outcome,true,false,true,Tactical) else @@ -5467,7 +5476,7 @@ function AWACS:_TACRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local contact = Contact.Contact -- Ops.Intel#INTEL.Contact local contacttag = Contact.TargetGroupNaming - if contact and not Contact.TACCallDone then + if contact then --and not Contact.TACCallDone then local position = contact.position -- Core.Point#COORDINATE if position then local distance = position:Get2DDistance(managedgroup.Group:GetCoordinate()) @@ -5477,6 +5486,15 @@ function AWACS:_TACRangeCall(GID,Contact) local text = string.format("%s. %s. %s %s, %d %s.",self.callsigntxt,pilotcallsign,contacttag,grptxt,distance,miles) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,false,AWACS.TaskStatus.EXECUTING) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self @@ -5495,8 +5513,8 @@ function AWACS:_MeldRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local flightpos = managedgroup.Group:GetCoordinate() local contact = Contact.Contact -- Ops.Intel#INTEL.Contact - local contacttag = Contact.TargetGroupNaming - if contact and not Contact.MeldCallDone then + local contacttag = Contact.TargetGroupNaming or "Bogey" + if contact then --and not Contact.MeldCallDone then local position = contact.position -- Core.Point#COORDINATE if position then local BRATExt = "" @@ -5509,6 +5527,15 @@ function AWACS:_MeldRangeCall(GID,Contact) local text = string.format("%s. %s. %s %s, %s",self.callsigntxt,pilotcallsign,contacttag,grptxt,BRATExt) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,true,AWACS.TaskStatus.EXECUTING) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self @@ -5525,7 +5552,7 @@ function AWACS:_ThreatRangeCall(GID,Contact) local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup local flightpos = managedgroup.Group:GetCoordinate() or managedgroup.LastKnownPosition local contact = Contact.Contact -- Ops.Intel#INTEL.Contact - local contacttag = Contact.TargetGroupNaming + local contacttag = Contact.TargetGroupNaming or "Bogey" if contact then local position = contact.position or contact.group:GetCoordinate() -- Core.Point#COORDINATE if position then @@ -5539,6 +5566,15 @@ function AWACS:_ThreatRangeCall(GID,Contact) local thrt = self.gettext:GetEntry("THREAT",self.locale) local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt) self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true) + if GID and GID ~= 0 then + --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup + if managedgroup and managedgroup.Group and managedgroup.Group:IsAlive() then + local name = managedgroup.GroupName + if self.TacticalSubscribers[name] then + self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true,true) + end + end + end end end return self From 0cc959bf3484848615da4a67d639c42c0d9e3fc9 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 16 Feb 2024 14:09:14 +0100 Subject: [PATCH 12/73] #STRATEGO * Exclude Ships as they cannot be conquered anyway * Streamline target finding a bit --- .../Moose/Functional/Stratego.lua | 175 +++++++++--------- 1 file changed, 90 insertions(+), 85 deletions(-) diff --git a/Moose Development/Moose/Functional/Stratego.lua b/Moose Development/Moose/Functional/Stratego.lua index 3c48cb7a0..2655500f8 100644 --- a/Moose Development/Moose/Functional/Stratego.lua +++ b/Moose Development/Moose/Functional/Stratego.lua @@ -41,6 +41,7 @@ -- @field #boolean usebudget -- @field #number CaptureUnits -- @field #number CaptureThreatlevel +-- @field #boolean ExcludeShips -- @extends Core.Base#BASE -- @extends Core.Fsm#FSM @@ -176,7 +177,7 @@ STRATEGO = { debug = false, drawzone = false, markzone = false, - version = "0.2.4", + version = "0.2.5", portweight = 3, POIweight = 1, maxrunways = 3, @@ -195,6 +196,7 @@ STRATEGO = { usebudget = false, CaptureUnits = 3, CaptureThreatlevel = 1, + ExcludeShips = true, } --- @@ -256,6 +258,7 @@ function STRATEGO:New(Name,Coalition,MaxDist) self.maxdist = MaxDist or 150 -- km self.disttable = {} self.routexists = {} + self.ExcludeShips = true self.lid = string.format("STRATEGO %s %s | ",self.name,self.version) @@ -427,6 +430,7 @@ function STRATEGO:AnalyseBases() self.bases:ForEach( function(afb) local ab = afb -- Wrapper.Airbase#AIRBASE + if self.ExcludeShips and ab:IsShip() then return end local abname = ab:GetName() local runways = ab:GetRunways() local numrwys = #runways @@ -438,14 +442,14 @@ function STRATEGO:AnalyseBases() local coa = ab:GetCoalition() if coa == nil then return end -- Spawned FARPS issue - these have no tangible data coa = coa+1 - local abtype = "AIRBASE" + local abtype = STRATEGO.Type.AIRBASE if ab:IsShip() then numrwys = 1 - abtype = "SHIP" + abtype = STRATEGO.Type.SHIP end if ab:IsHelipad() then numrwys = 1 - abtype = "FARP" + abtype = STRATEGO.Type.FARP end local coord = ab:GetCoordinate() if debug then @@ -481,10 +485,10 @@ function STRATEGO:UpdateNodeCoalitions() local newtable = {} for _id,_data in pairs(self.airbasetable) do local data = _data -- #STRATEGO.Data - if data.type == "AIRBASE" or data.type == "FARP" then - data.coalition = AIRBASE:FindByName(data.name):GetCoalition() + if data.type == STRATEGO.Type.AIRBASE or data.type == STRATEGO.Type.FARP or data.type == STRATEGO.Type.SHIP then + data.coalition = AIRBASE:FindByName(data.name):GetCoalition() or 0 else - data.coalition = data.opszone:GetOwner() + data.coalition = data.opszone:GetOwner() or 0 end newtable[_id] = _data end @@ -937,11 +941,13 @@ function STRATEGO:FindClosestConsolidationTarget(Startpoint,BaseWeight) local cname = self.easynames[tname] local targetweight = self.airbasetable[cname].baseweight coa = self.airbasetable[cname].coalition + --self:T("Start -> End: "..startpoint.." -> "..cname) if (dist < shortest) and (coa ~= self.coalition) and (BaseWeight >= targetweight) then + self:T("Found Consolidation Target: "..cname) shortest = dist target = cname weight = self.airbasetable[cname].weight - coa = self.airbasetable[cname].coalition + coa = coa end end end @@ -974,8 +980,9 @@ function STRATEGO:FindClosestStrategicTarget(Startpoint,Weight) local coa = self.airbasetable[cname].coalition local tweight = self.airbasetable[cname].baseweight local ttweight = self.airbasetable[cname].weight - self:T("Start -> End: "..startpoint.." -> "..cname) + --self:T("Start -> End: "..startpoint.." -> "..cname) if (dist < shortest) and (coa ~= self.coalition) and (tweight >= Weight) then + self:T("Found Strategic Target: "..cname) shortest = dist target = cname weight = self.airbasetable[cname].weight @@ -996,38 +1003,31 @@ function STRATEGO:FindStrategicTargets() local data = _data -- #STRATEGO.Data if data.coalition == self.coalition then local dist, name, points, coa = self:FindClosestStrategicTarget(data.name,data.weight) - if coa == coalition.side.NEUTRAL and points ~= 0 then - local fpoints = points + self.NeutralBenefit - local tries = 1 - while targets[fpoints] or tries < 100 do - fpoints = points + (self.NeutralBenefit+math.random(1,100)) - tries = tries + 1 - end - targets[fpoints] = { - name = name, - dist = dist, - points = fpoints, - coalition = coa, - coalitionname = UTILS.GetCoalitionName(coa), - coordinate = self.airbasetable[name].coord, - } + if points > 0 then + self:T({dist=dist, name=name, points=points, coa=coa}) end - local enemycoa = self.coalition == coalition.side.BLUE and coalition.side.RED or coalition.side.BLUE - if coa == enemycoa and points ~= 0 then - local fpoints = points - local tries = 1 - while targets[fpoints] or tries < 100 do - fpoints = points + (math.random(1,100)) - tries = tries + 1 + if points ~= 0 then + local enemycoa = self.coalition == coalition.side.BLUE and coalition.side.RED or coalition.side.BLUE + self:T("Enemycoa = "..enemycoa) + if coa == coalition.side.NEUTRAL then + local tdata = {} + tdata.name = name + tdata.dist = dist + tdata.points = points + self.NeutralBenefit + tdata.coalition = coa + tdata.coalitionname = UTILS.GetCoalitionName(coa) + tdata.coordinate = self.airbasetable[name].coord + table.insert(targets,tdata) + else + local tdata = {} + tdata.name = name + tdata.dist = dist + tdata.points = points + tdata.coalition = coa + tdata.coalitionname = UTILS.GetCoalitionName(coa) + tdata.coordinate = self.airbasetable[name].coord + table.insert(targets,tdata) end - targets[fpoints] = { - name = name, - dist = dist, - points = fpoints, - coalition = coa, - coalitionname = UTILS.GetCoalitionName(coa), - coordinate = self.airbasetable[name].coord, - } end end end @@ -1044,38 +1044,31 @@ function STRATEGO:FindConsolidationTargets() local data = _data -- #STRATEGO.Data if data.coalition == self.coalition then local dist, name, points, coa = self:FindClosestConsolidationTarget(data.name,self.maxrunways-1) - if coa == coalition.side.NEUTRAL and points ~= 0 then - local fpoints = points + self.NeutralBenefit - local tries = 1 - while targets[fpoints] or tries < 100 do - fpoints = points - (self.NeutralBenefit+math.random(1,100)) - tries = tries + 1 - end - targets[fpoints] = { - name = name, - dist = dist, - points = fpoints, - coalition = coa, - coalitionname = UTILS.GetCoalitionName(coa), - coordinate = self.airbasetable[name].coord, - } + if points > 0 then + self:T({dist=dist, name=name, points=points, coa=coa}) end - local enemycoa = self.coalition == coalition.side.BLUE and coalition.side.RED or coalition.side.BLUE - if coa == enemycoa and points ~= 0 then - local fpoints = points - local tries = 1 - while targets[fpoints] or tries < 100 do - fpoints = points - (math.random(1,100)) - tries = tries + 1 + if points ~= 0 then + local enemycoa = self.coalition == coalition.side.BLUE and coalition.side.RED or coalition.side.BLUE + self:T("Enemycoa = "..enemycoa) + if coa == coalition.side.NEUTRAL then + local tdata = {} + tdata.name = name + tdata.dist = dist + tdata.points = points + self.NeutralBenefit + tdata.coalition = coa + tdata.coalitionname = UTILS.GetCoalitionName(coa) + tdata.coordinate = self.airbasetable[name].coord + table.insert(targets,tdata) + else + local tdata = {} + tdata.name = name + tdata.dist = dist + tdata.points = points + tdata.coalition = coa + tdata.coalitionname = UTILS.GetCoalitionName(coa) + tdata.coordinate = self.airbasetable[name].coord + table.insert(targets,tdata) end - targets[fpoints] = { - name = name, - dist = dist, - points = fpoints, - coalition = coa, - coalitionname = UTILS.GetCoalitionName(coa), - coordinate = self.airbasetable[name].coord, - } end end end @@ -1245,13 +1238,15 @@ end -- @return #table Target Table with #STRATEGO.Target data or nil if none found. function STRATEGO:FindAffordableStrategicTarget() self:T(self.lid.."FindAffordableStrategicTarget") - local targets = self:FindStrategicTargets() -- #table of #STRATEGO.Target + local Stargets = self:FindStrategicTargets() -- #table of #STRATEGO.Target + --UTILS.PrintTableToLog(Stargets,1) local budget = self.Budget --local leftover = self.Budget - local target = nil -- #STRATEGO.Target + local ftarget = nil -- #STRATEGO.Target local Targets = {} - for _,_data in pairs(targets) do + for _,_data in pairs(Stargets) do local data = _data -- #STRATEGO.Target + self:T("Considering Strategic Target "..data.name) --if data.points <= budget and budget-data.points < leftover then if data.points <= budget then --leftover = budget-data.points @@ -1259,14 +1254,18 @@ function STRATEGO:FindAffordableStrategicTarget() self:T(self.lid.."Affordable strategic target: "..data.name) end end - if not targets then + if #Targets == 0 then self:T(self.lid.."No suitable target found!") return nil end - target = Targets[math.random(1,#Targets)] - if target then - self:T(self.lid.."Final affordable strategic target: "..target.name) - return target + if #Targets > 1 then + ftarget = Targets[math.random(1,#Targets)] + else + ftarget = Targets[1] + end + if ftarget then + self:T(self.lid.."Final affordable strategic target: "..ftarget.name) + return ftarget else return nil end @@ -1277,13 +1276,15 @@ end -- @return #table Target Table with #STRATEGO.Target data or nil if none found. function STRATEGO:FindAffordableConsolidationTarget() self:T(self.lid.."FindAffordableConsolidationTarget") - local targets = self:FindConsolidationTargets() -- #table of #STRATEGO.Target + local Ctargets = self:FindConsolidationTargets() -- #table of #STRATEGO.Target + --UTILS.PrintTableToLog(Ctargets,1) local budget = self.Budget --local leftover = self.Budget - local target = nil -- #STRATEGO.Target + local ftarget = nil -- #STRATEGO.Target local Targets = {} - for _,_data in pairs(targets) do + for _,_data in pairs(Ctargets) do local data = _data -- #STRATEGO.Target + self:T("Considering Consolidation Target "..data.name) --if data.points <= budget and budget-data.points < leftover then if data.points <= budget then --leftover = budget-data.points @@ -1291,14 +1292,18 @@ function STRATEGO:FindAffordableConsolidationTarget() self:T(self.lid.."Affordable consolidation target: "..data.name) end end - if not targets then + if #Targets == 0 then self:T(self.lid.."No suitable target found!") return nil end - target = Targets[math.random(1,#Targets)] - if target then - self:T(self.lid.."Final affordable consolidation target: "..target.name) - return target + if #Targets > 1 then + ftarget = Targets[math.random(1,#Targets)] + else + ftarget = Targets[1] + end + if ftarget then + self:T(self.lid.."Final affordable consolidation target: "..ftarget.name) + return ftarget else return nil end From 5a772ad05e65d563e3a04c39f4c2b8274b3e13a2 Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Sat, 17 Feb 2024 13:10:07 +0100 Subject: [PATCH 13/73] Update Airboss.lua Groove def --- Moose Development/Moose/Ops/Airboss.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 95efbcf27..a930cd0c3 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -9754,7 +9754,7 @@ function AIRBOSS:_Groove( playerData ) local glideslopeError = groovedata.GSE local AoA = groovedata.AoA - if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 or playerData.unit:IsInZone( self:_GetZoneLineup() )) then + if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 and playerData.unit:IsInZone( self:_GetZoneLineup() )) then -- Start time in groove playerData.TIG0 = timer.getTime() From 8d886a75d6108d6527d53d9f7a5b6137d1b59d6b Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Sat, 17 Feb 2024 13:12:25 +0100 Subject: [PATCH 14/73] Update Airboss.lua (#2101) Groove def --- Moose Development/Moose/Ops/Airboss.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 1d2adfbd2..745bf817c 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -9755,7 +9755,7 @@ function AIRBOSS:_Groove( playerData ) local glideslopeError = groovedata.GSE local AoA = groovedata.AoA - if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 or playerData.unit:IsInZone( self:_GetZoneLineup() )) then + if rho <= RXX and playerData.step == AIRBOSS.PatternStep.GROOVE_XX and (math.abs( groovedata.Roll ) <= 4.0 and playerData.unit:IsInZone( self:_GetZoneLineup() )) then -- Start time in groove playerData.TIG0 = timer.getTime() From f8595220522464747870430eb17bf7d20da9dd46 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 17 Feb 2024 18:50:30 +0100 Subject: [PATCH 15/73] Switched link of MSRS missions to MISSION_Demos --- Moose Development/Moose/Sound/SRS.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Sound/SRS.lua b/Moose Development/Moose/Sound/SRS.lua index 9d075dfd0..0d3315dcc 100644 --- a/Moose Development/Moose/Sound/SRS.lua +++ b/Moose Development/Moose/Sound/SRS.lua @@ -14,7 +14,7 @@ -- -- === -- --- ## Example Missions: [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Sound/MSRS). +-- ## Example Missions: [GitHub](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Sound/MSRS). -- -- === -- From 0faa0036ee7d7f35868fb08604ad4334ee69aaa7 Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Sun, 18 Feb 2024 20:13:01 +0100 Subject: [PATCH 16/73] Update Airbase.lua One space too many fix gor Deanland --- Moose Development/Moose/Wrapper/Airbase.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 6f1ecd91a..2799d17e3 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -302,7 +302,7 @@ AIRBASE.Normandy = { ["Fecamp_Benouville"] = "Fecamp-Benouville", ["Farnborough"] = "Farnborough", ["Friston"] = "Friston", - ["Deanland "] = "Deanland ", + ["Deanland"] = "Deanland", ["Triqueville"] = "Triqueville", ["Poix"] = "Poix", ["Orly"] = "Orly", From 3baf52d3075e4a234b739bcc099cf773f9eef7ef Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Sun, 18 Feb 2024 20:13:52 +0100 Subject: [PATCH 17/73] Update Airbase.lua (#2104) One space too many fix gor Deanland --- Moose Development/Moose/Wrapper/Airbase.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 6f1ecd91a..2799d17e3 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -302,7 +302,7 @@ AIRBASE.Normandy = { ["Fecamp_Benouville"] = "Fecamp-Benouville", ["Farnborough"] = "Farnborough", ["Friston"] = "Friston", - ["Deanland "] = "Deanland ", + ["Deanland"] = "Deanland", ["Triqueville"] = "Triqueville", ["Poix"] = "Poix", ["Orly"] = "Orly", From 27ea85ea57acf57a4323178b52fd34912986ad1a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 20 Feb 2024 12:07:34 +0100 Subject: [PATCH 18/73] Minor fixes --- Moose Development/Moose/Core/Spawn.lua | 2 +- Moose Development/Moose/Core/Zone.lua | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index a6651a7c1..c34c8ccbd 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -724,7 +724,7 @@ end -- @param #number Country Country id as number or enumerator: -- -- * @{DCS#country.id.RUSSIA} --- * @{DCS#county.id.USA} +-- * @{DCS#country.id.USA} -- -- @return #SPAWN self function SPAWN:InitCountry( Country ) diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 3317df260..db176e783 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -899,7 +899,8 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) local Point = {} local Vec2 = self:GetVec2() - + local countryID = CountryID or country.id.USA + Points = Points and Points or 360 local Angle @@ -910,7 +911,7 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() - local CountryName = _DATABASE.COUNTRY_NAME[CountryID] + local CountryName = _DATABASE.COUNTRY_NAME[countryID] local Tire = { ["country"] = CountryName, @@ -925,7 +926,7 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) ["heading"] = 0, } -- end of ["group"] - local Group = coalition.addStaticObject( CountryID, Tire ) + local Group = coalition.addStaticObject( countryID, Tire ) if UnBound and UnBound == true then Group:destroy() end From 2eeca4451c593109cb9bc36a03c4acd8f08614d3 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 20 Feb 2024 14:31:53 +0100 Subject: [PATCH 19/73] SPAWN/DATABASE * Try to ensure unique Link16 STN/SADL octal IDs * Added `SPAWN:InitSTN(Octal)` and `SPAWN:InitSADL(Octal)` --- Moose Development/Moose/Core/Database.lua | 93 ++++++++++++++++++++++- Moose Development/Moose/Core/Spawn.lua | 86 ++++++++++++++++----- 2 files changed, 158 insertions(+), 21 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 14b99fc76..8ffedba7b 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -37,6 +37,8 @@ -- @field #table Templates Templates: Units, Groups, Statics, ClientsByName, ClientsByID. -- @field #table CLIENTS Clients. -- @field #table STORAGES DCS warehouse storages. +-- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes. +-- @field #table SADL Used Link16 octal numbers for A10/C-II planes. -- @extends Core.Base#BASE --- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator. @@ -93,6 +95,8 @@ DATABASE = { OPSZONES = {}, PATHLINES = {}, STORAGES = {}, + STNS={}, + SADL={}, } local _DATABASECoalition = @@ -1029,10 +1033,23 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category self.Templates.ClientsByName[UnitTemplate.name].CountryID = CountryID self.Templates.ClientsByID[UnitTemplate.unitId] = UnitTemplate end + + if UnitTemplate.AddPropAircraft then + if UnitTemplate.AddPropAircraft.STN_L16 then + local stn = UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.STN_L16) + self.STNS[stn] = UnitTemplate.name + self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + end + if UnitTemplate.AddPropAircraft.SADL_TN then + local sadl = UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.SADL_TN) + self.SADL[sadl] = UnitTemplate.name + self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) + end + end UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName end - + -- Debug info. self:T( { Group = self.Templates.Groups[GroupTemplateName].GroupName, Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID, @@ -1043,6 +1060,80 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category ) end +--- Get next (consecutive) free STN as octal number. +-- @param #DATABASE self +-- @param #number octal Starting octal. +-- @param #string unitname Name of the associated unit. +-- @return #number Octal +function DATABASE:GetNextSTN(octal,unitname) + local first = UTILS.OctalToDecimal(octal) + if self.STNS[first] == unitname then return octal end + local nextoctal = 77777 + local found = false + if 32767-first < 10 then + first = 0 + end + for i=first+1,32767 do + if self.STNS[i] == nil then + found = true + nextoctal = UTILS.DecimalToOctal(i) + self.STNS[i] = unitname + self:T("Register STN "..tostring(nextoctal).." for ".. unitname) + break + end + end + if not found then + self:E(string.format("WARNING: No next free STN past %05d found!",octal)) + -- cleanup + local NewSTNS = {} + for _id,_name in pairs(self.STNS) do + if self.UNITS[_name] ~= nil then + NewSTNS[_id] = _name + end + end + self.STNS = nil + self.STNS = NewSTNS + end + return nextoctal +end + +--- Get next (consecutive) free SADL as octal number. +-- @param #DATABASE self +-- @param #number octal Starting octal. +-- @param #string unitname Name of the associated unit. +-- @return #number Octal +function DATABASE:GetNextSADL(octal,unitname) + local first = UTILS.OctalToDecimal(octal) + if self.SADL[first] == unitname then return octal end + local nextoctal = 7777 + local found = false + if 4095-first < 10 then + first = 0 + end + for i=first+1,4095 do + if self.STNS[i] == nil then + found = true + nextoctal = UTILS.DecimalToOctal(i) + self.SADL[i] = unitname + self:T("Register SADL "..tostring(nextoctal).." for ".. unitname) + break + end + end + if not found then + self:E(string.format("WARNING: No next free SADL past %04d found!",octal)) + -- cleanup + local NewSTNS = {} + for _id,_name in pairs(self.SADL) do + if self.UNITS[_name] ~= nil then + NewSTNS[_id] = _name + end + end + self.SADL = nil + self.SADL = NewSTNS + end + return nextoctal +end + --- Get group template. -- @param #DATABASE self -- @param #string GroupName Group name. diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index c34c8ccbd..97d30dfe5 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -780,6 +780,34 @@ function SPAWN:InitSkill( Skill ) return self end +--- [Airplane - F15/16/18/AWACS/B1B/Tanker only] Set the STN Link16 starting number of the Group; each unit of the spawned group will have a consecutive STN set. +-- @param #SPAWN self +-- @param #number Octal The octal number (digits 1..7, max 5 digits, i.e. 77777) to set the STN to. Every STN needs to be unique! +-- @return #SPAWN self +function SPAWN:InitSTN(Octal) + self:F( { Octal = Octal } ) + self.SpawnInitSTN = Octal or 77777 + local num = UTILS.OctalToDecimal(Octal) + if _DATABASE.STNS[num] ~= nil then + self:E("WARNING - STN already assigned: "..tostring(Octal).." is used for ".._DATABASE.STNS[Octal]) + end + return self +end + +--- [Airplane - A10-C II only] Set the SADL TN starting number of the Group; each unit of the spawned group will have a consecutive SADL set. +-- @param #SPAWN self +-- @param #number Octal The octal number (digits 1..7, max 4 digits, i.e. 7777) to set the SADL to. Every SADL needs to be unique! +-- @return #SPAWN self +function SPAWN:InitSADL(Octal) + self:F( { Octal = Octal } ) + self.SpawnInitSADL = Octal or 7777 + local num = UTILS.OctalToDecimal(Octal) + if _DATABASE.SADL[num] ~= nil then + self:E("WARNING - SADL already assigned: "..tostring(Octal).." is used for ".._DATABASE.SADL[Octal]) + end + return self +end + --- Sets the radio communication on or off. Same as checking/unchecking the COMM box in the mission editor. -- @param #SPAWN self -- @param #number switch If true (or nil), enables the radio communication. If false, disables the radio for the spawned group. @@ -3400,30 +3428,48 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2 local AddProps = SpawnTemplate.units[UnitID].AddPropAircraft if AddProps then if SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 then - -- 4 digit octal with leading 0 - if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16) ~= nil then - local octal = SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 - local decimal = UTILS.OctalToDecimal(octal)+UnitID-1 - SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",UTILS.DecimalToOctal(decimal)) - else -- ED bug - chars in here - local STN = math.floor(UTILS.RandomGaussian(4088/2,nil,1000,4088)) - STN = STN+UnitID-1 - local OSTN = UTILS.DecimalToOctal(STN) - SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",OSTN) + if self.SpawnInitSTN then + local octal = self.SpawnInitSTN + if UnitID > 1 then + octal = _DATABASE:GetNextSTN(self.SpawnInitSTN,SpawnTemplate.units[UnitID].name) + end + SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",octal) + else + -- 5 digit octal with leading 0 + if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16) ~= nil then + local octal = SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 + local num = UTILS.OctalToDecimal(octal) + if _DATABASE.STNS[num] ~= nil or UnitID > 1 then -- STN taken or next unit + octal = _DATABASE:GetNextSTN(octal,SpawnTemplate.units[UnitID].name) + end + SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",octal) + else -- ED bug - chars in here + local OSTN = _DATABASE:GetNextSTN(1,SpawnTemplate.units[UnitID].name) + SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%05d",OSTN) + end end end -- A10CII if SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN then - -- 3 digit octal with leading 0 - if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN) ~= nil then - local octal = SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN - local decimal = UTILS.OctalToDecimal(octal)+UnitID-1 - SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",UTILS.DecimalToOctal(decimal)) - else -- ED bug - chars in here - local STN = math.floor(UTILS.RandomGaussian(504/2,nil,100,504)) - STN = STN+UnitID-1 - local OSTN = UTILS.DecimalToOctal(STN) - SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",OSTN) + -- 4 digit octal with leading 0 + if self.SpawnInitSADL then + local octal = self.SpawnInitSADL + if UnitID > 1 then + octal = _DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name) + end + SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%04d",octal) + else + if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN) ~= nil then + local octal = SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN + local num = UTILS.OctalToDecimal(octal) + if _DATABASE.SADL[num] ~= nil or UnitID > 1 then -- SADL taken or next unit + octal = _DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name) + end + SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",octal) + else -- ED bug - chars in here + local OSTN = _DATABASE:GetNextSADL(1,SpawnTemplate.units[UnitID].name) + SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",OSTN) + end end end -- VoiceCallsignNumber From 30819dad720d99c17277f149557e4fab90e7ed13 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 22 Feb 2024 09:00:54 +0100 Subject: [PATCH 20/73] Catch for invalid STN/SADL octals --- Moose Development/Moose/Core/Database.lua | 16 ++++++++++++---- Moose Development/Moose/Core/Spawn.lua | 12 ++++++++++-- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 8ffedba7b..47884fae0 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1037,13 +1037,21 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category if UnitTemplate.AddPropAircraft then if UnitTemplate.AddPropAircraft.STN_L16 then local stn = UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.STN_L16) - self.STNS[stn] = UnitTemplate.name - self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + if stn == nil or stn < 1 then + self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + else + self.STNS[stn] = UnitTemplate.name + self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + end end if UnitTemplate.AddPropAircraft.SADL_TN then local sadl = UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.SADL_TN) - self.SADL[sadl] = UnitTemplate.name - self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) + if sadl == nil or sadl < 1 then + self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + else + self.SADL[sadl] = UnitTemplate.name + self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) + end end end diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 97d30dfe5..5de09ed58 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -782,12 +782,16 @@ end --- [Airplane - F15/16/18/AWACS/B1B/Tanker only] Set the STN Link16 starting number of the Group; each unit of the spawned group will have a consecutive STN set. -- @param #SPAWN self --- @param #number Octal The octal number (digits 1..7, max 5 digits, i.e. 77777) to set the STN to. Every STN needs to be unique! +-- @param #number Octal The octal number (digits 1..7, max 5 digits, i.e. 1..77777) to set the STN to. Every STN needs to be unique! -- @return #SPAWN self function SPAWN:InitSTN(Octal) self:F( { Octal = Octal } ) self.SpawnInitSTN = Octal or 77777 local num = UTILS.OctalToDecimal(Octal) + if num == nil or num < 1 then + self:E("WARNING - STN "..tostring(Octal).." is not valid!") + return self + end if _DATABASE.STNS[num] ~= nil then self:E("WARNING - STN already assigned: "..tostring(Octal).." is used for ".._DATABASE.STNS[Octal]) end @@ -796,12 +800,16 @@ end --- [Airplane - A10-C II only] Set the SADL TN starting number of the Group; each unit of the spawned group will have a consecutive SADL set. -- @param #SPAWN self --- @param #number Octal The octal number (digits 1..7, max 4 digits, i.e. 7777) to set the SADL to. Every SADL needs to be unique! +-- @param #number Octal The octal number (digits 1..7, max 4 digits, i.e. 1..7777) to set the SADL to. Every SADL needs to be unique! -- @return #SPAWN self function SPAWN:InitSADL(Octal) self:F( { Octal = Octal } ) self.SpawnInitSADL = Octal or 7777 local num = UTILS.OctalToDecimal(Octal) + if num == nil or num < 1 then + self:E("WARNING - SADL "..tostring(Octal).." is not valid!") + return self + end if _DATABASE.SADL[num] ~= nil then self:E("WARNING - SADL already assigned: "..tostring(Octal).." is used for ".._DATABASE.SADL[Octal]) end From 2ce9f26e26d96061ed49917ff8bae24352da4056 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 22 Feb 2024 09:19:22 +0100 Subject: [PATCH 21/73] Docu --- Moose Development/Moose/Core/Spawn.lua | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 5de09ed58..705da5929 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -199,6 +199,11 @@ -- -- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed. -- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp. +-- +-- ### Link-16 Datalink STN and SADL IDs (limited at the moment to F15/16/18/AWACS/Tanker/B1B, but not the F15E for clients, SADL A10CII only) +-- +-- *{#SPAWN.InitSTN}(): Set the STN of the first unit in the group. All other units will have consecutive STNs, provided they have not been used yet. +-- *{#SPAWN.InitSADL}(): Set the SADL of the first unit in the group. All other units will have consecutive SADLs, provided they have not been used yet. -- -- ## SPAWN **Spawn** methods -- From e8c75b87958da7358e7e74a2f480cd4b9d89f425 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 22 Feb 2024 11:52:43 +0100 Subject: [PATCH 22/73] SPAWN:InitSpeedMPS() etc --- Moose Development/Moose/Core/Base.lua | 1 + Moose Development/Moose/Core/Spawn.lua | 55 ++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index dede44ad3..6ab927288 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -1153,6 +1153,7 @@ function BASE:_Serialize(Arguments) text = string.gsub(text,"\n","") text = string.gsub(text,"%(%(","%(") text = string.gsub(text,"%)%)","%)") + text = string.gsub(text,"(%s+)","") return text end diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 705da5929..65f7dba21 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -204,6 +204,17 @@ -- -- *{#SPAWN.InitSTN}(): Set the STN of the first unit in the group. All other units will have consecutive STNs, provided they have not been used yet. -- *{#SPAWN.InitSADL}(): Set the SADL of the first unit in the group. All other units will have consecutive SADLs, provided they have not been used yet. +-- +-- ### Callsigns +-- +-- *{#SPAWN.InitRandomizeCallsign}(): Set a random callsign name per spawn. +-- *{#SPAWN.SpawnInitCallSign}(): Set a specific callsign for a spawned group. +-- +-- ### Speed +-- +-- *{#SPAWN.InitSpeedMps}(): Set the initial speed on spawning in meters per second. +-- *{#SPAWN.InitSpeedKph}(): Set the initial speed on spawning in kilometers per hour. +-- *{#SPAWN.InitSpeedKnots}(): Set the initial speed on spawning in knots. -- -- ## SPAWN **Spawn** methods -- @@ -821,6 +832,46 @@ function SPAWN:InitSADL(Octal) return self end +--- [Airplane] Set the initial speed on spawning in meters per second. Useful when spawning in-air only. +-- @param #SPAWN self +-- @param #number MPS The speed in MPS to use. +-- @return #SPAWN self +function SPAWN:InitSpeedMps(MPS) +self:F( { MPS = MPS } ) + if MPS == nil or tonumber(MPS)<0 then + MPS=125 + end + self.InitSpeed = MPS + return self +end + +--- [Airplane] Set the initial speed on spawning in knots. Useful when spawning in-air only. +-- @param #SPAWN self +-- @param #number Knots The speed in knots to use. +-- @return #SPAWN self +function SPAWN:InitSpeedKnots(Knots) +self:F( { Knots = Knots } ) + if Knots == nil or tonumber(Knots)<0 then + Knots=300 + end + self.InitSpeed = UTILS.KnotsToMps(Knots) + return self +end + +--- [Airplane] Set the initial speed on spawning in kilometers per hour. Useful when spawning in-air only. +-- @param #SPAWN self +-- @param #number KPH The speed in KPH to use. +-- @return #SPAWN self +function SPAWN:InitSpeedKph(KPH) + self:F( { KPH = KPH } ) + if KPH == nil or tonumber(KPH)<0 then + KPH=UTILS.KnotsToKmph(300) + end + self.InitSpeed = UTILS.KmphToMps(KPH) + return self +end + + --- Sets the radio communication on or off. Same as checking/unchecking the COMM box in the mission editor. -- @param #SPAWN self -- @param #number switch If true (or nil), enables the radio communication. If false, disables the radio for the spawned group. @@ -3437,6 +3488,10 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2 SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex end end + -- Speed + if self.InitSpeed then + SpawnTemplate.units[UnitID].speed = self.InitSpeed + end -- Link16 local AddProps = SpawnTemplate.units[UnitID].AddPropAircraft if AddProps then From 4c2a89ee299ce783bee9f91207c9ef294af12edf Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 22 Feb 2024 12:14:15 +0100 Subject: [PATCH 23/73] Bugfix --- Moose Development/Moose/Core/Database.lua | 2 +- Moose Development/Moose/Core/Spawn.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 47884fae0..65281c860 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1047,7 +1047,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category if UnitTemplate.AddPropAircraft.SADL_TN then local sadl = UTILS.OctalToDecimal(UnitTemplate.AddPropAircraft.SADL_TN) if sadl == nil or sadl < 1 then - self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name) + self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) else self.SADL[sadl] = UnitTemplate.name self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 65f7dba21..68e3a10a8 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -3525,7 +3525,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2 if UnitID > 1 then octal = _DATABASE:GetNextSADL(self.SpawnInitSADL,SpawnTemplate.units[UnitID].name) end - SpawnTemplate.units[UnitID].AddPropAircraft.STN_L16 = string.format("%04d",octal) + SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN = string.format("%04d",octal) else if tonumber(SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN) ~= nil then local octal = SpawnTemplate.units[UnitID].AddPropAircraft.SADL_TN From 5b86bf9605d5e819b4dbed2ac2a4db535f5fb580 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 22 Feb 2024 17:28:44 +0100 Subject: [PATCH 24/73] #AWACS - Added a warning to set up SRS before Tac Radios --- Moose Development/Moose/Ops/Awacs.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index c3cfc95d8..b7bbb1990 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -1384,7 +1384,7 @@ end -- Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically. +--- [User] Set the tactical information option, create 10 radio channels groups can subscribe and get Bogey Dope on a specific frequency automatically. You **need** to set up SRS first before using this! -- @param #AWACS self -- @param #number BaseFreq Base Frequency to use, defaults to 130. -- @param #number Increase Increase to use, defaults to 0.5, thus channels created are 130, 130.5, 131 .. etc. @@ -1394,6 +1394,10 @@ end -- @return #AWACS self function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number) self:T(self.lid.."SetTacticalRadios") + if not self.AwacsSRS then + MESSAGE:New("AWACS: Setup SRS in your code BEFORE trying to add tac radios please!",30,"ERROR",true):ToLog():ToAll() + return self + end self.TacticalMenu = true self.TacticalBaseFreq = BaseFreq or 130 self.TacticalIncrFreq = Increase or 0.5 From 02e59b23c58723b1bf9f790c10cbf469e534cae7 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 23 Feb 2024 11:15:46 +0100 Subject: [PATCH 25/73] #AIRBASE - New Syria airbases added --- Moose Development/Moose/Wrapper/Airbase.lua | 226 ++++++++++---------- 1 file changed, 116 insertions(+), 110 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 2799d17e3..490edcba7 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -427,132 +427,138 @@ AIRBASE.TheChannel = { --- Airbases of the Syria map: -- -- * AIRBASE.Syria.Kuweires --- * AIRBASE.Syria.Marj_Ruhayyil --- * AIRBASE.Syria.Kiryat_Shmona --- * AIRBASE.Syria.Marj_as_Sultan_North --- * AIRBASE.Syria.Eyn_Shemer -- * AIRBASE.Syria.Incirlik --- * AIRBASE.Syria.Damascus --- * AIRBASE.Syria.Bassel_Al_Assad --- * AIRBASE.Syria.Rosh_Pina +-- * AIRBASE.Syria.King_Abdullah_II +-- * AIRBASE.Syria.Akrotiri -- * AIRBASE.Syria.Aleppo --- * AIRBASE.Syria.Al_Qusayr --- * AIRBASE.Syria.Wujah_Al_Hajar --- * AIRBASE.Syria.Al_Dumayr --- * AIRBASE.Syria.Gazipasa +-- * AIRBASE.Syria.Abu_al_Duhur -- * AIRBASE.Syria.Hatay --- * AIRBASE.Syria.Nicosia [Deactivated by ED as of June/2023] --- * AIRBASE.Syria.Pinarbashi -- * AIRBASE.Syria.Paphos +-- * AIRBASE.Syria.At_Tanf +-- * AIRBASE.Syria.Tal_Siman +-- * AIRBASE.Syria.Rayak +-- * AIRBASE.Syria.Muwaffaq_Salti +-- * AIRBASE.Syria.Naqoura +-- * AIRBASE.Syria.Gaziantep +-- * AIRBASE.Syria.Al_Qusayr +-- * AIRBASE.Syria.Al_Dumayr -- * AIRBASE.Syria.Kingsfield --- * AIRBASE.Syria.Thalah +-- * AIRBASE.Syria.Marj_as_Sultan_North +-- * AIRBASE.Syria.Beirut_Rafic_Hariri +-- * AIRBASE.Syria.Palmyra +-- * AIRBASE.Syria.Hama +-- * AIRBASE.Syria.Eyn_Shemer +-- * AIRBASE.Syria.Sanliurfa +-- * AIRBASE.Syria.Amman +-- * AIRBASE.Syria.Deir_ez_Zor +-- * AIRBASE.Syria.Taftanaz +-- * AIRBASE.Syria.Damascus +-- * AIRBASE.Syria.Gazipasa +-- * AIRBASE.Syria.Herzliya +-- * AIRBASE.Syria.H4 +-- * AIRBASE.Syria.Tiyas +-- * AIRBASE.Syria.Lakatamia +-- * AIRBASE.Syria.Kharab_Ishk -- * AIRBASE.Syria.Haifa -- * AIRBASE.Syria.Khalkhalah -- * AIRBASE.Syria.Megiddo --- * AIRBASE.Syria.Lakatamia --- * AIRBASE.Syria.Rayak --- * AIRBASE.Syria.Larnaca +-- * AIRBASE.Syria.An_Nasiriyah +-- * AIRBASE.Syria.Bassel_Al_Assad +-- * AIRBASE.Syria.Ruwayshid -- * AIRBASE.Syria.Mezzeh -- * AIRBASE.Syria.Gecitkale --- * AIRBASE.Syria.Akrotiri --- * AIRBASE.Syria.Naqoura --- * AIRBASE.Syria.Gaziantep --- * AIRBASE.Syria.Sayqal --- * AIRBASE.Syria.Tiyas --- * AIRBASE.Syria.Shayrat --- * AIRBASE.Syria.Taftanaz --- * AIRBASE.Syria.H4 --- * AIRBASE.Syria.King_Hussein_Air_College --- * AIRBASE.Syria.Rene_Mouawad --- * AIRBASE.Syria.Jirah +-- * AIRBASE.Syria.Nicosia -- * AIRBASE.Syria.Ramat_David --- * AIRBASE.Syria.Qabr_as_Sitt --- * AIRBASE.Syria.Minakh --- * AIRBASE.Syria.Adana_Sakirpasa --- * AIRBASE.Syria.Palmyra --- * AIRBASE.Syria.Hama --- * AIRBASE.Syria.Ercan --- * AIRBASE.Syria.Marj_as_Sultan_South --- * AIRBASE.Syria.Tabqa --- * AIRBASE.Syria.Beirut_Rafic_Hariri --- * AIRBASE.Syria.An_Nasiriyah --- * AIRBASE.Syria.Abu_al_Duhur --- * AIRBASE.Syria.At_Tanf --- * AIRBASE.Syria.H3 +-- * AIRBASE.Syria.Tha_lah -- * AIRBASE.Syria.H3_Northwest +-- * AIRBASE.Syria.Sayqal +-- * AIRBASE.Syria.Jirah +-- * AIRBASE.Syria.Shayrat +-- * AIRBASE.Syria.Adana_Sakirpasa +-- * AIRBASE.Syria.Wujah_Al_Hajar +-- * AIRBASE.Syria.Pinarbashi -- * AIRBASE.Syria.H3_Southwest --- * AIRBASE.Syria.Kharab_Ishk --- * AIRBASE.Syria.Raj_al_Issa_East (deleted by ED) --- * AIRBASE.Syria.Raj_al_Issa_West (deleted by ED) --- * AIRBASE.Syria.Ruwayshid --- * AIRBASE.Syria.Sanliurfa --- * AIRBASE.Syria.Tal_Siman --- * AIRBASE.Syria.Deir_ez_Zor +-- * AIRBASE.Syria.Rosh_Pina +-- * AIRBASE.Syria.Kiryat_Shmona +-- * AIRBASE.Syria.H3 +-- * AIRBASE.Syria.Qabr_as_Sitt +-- * AIRBASE.Syria.Prince_Hassan +-- * AIRBASE.Syria.Larnaca +-- * AIRBASE.Syria.King_Hussein_Air_College +-- * AIRBASE.Syria.Ercan +-- * AIRBASE.Syria.Marj_Ruhayyil +-- * AIRBASE.Syria.Tabqa +-- * AIRBASE.Syria.Marj_as_Sultan_South +-- * AIRBASE.Syria.Rene_Mouawad +-- * AIRBASE.Syria.Minakh -- --@field Syria AIRBASE.Syria={ - ["Kuweires"]="Kuweires", - ["Marj_Ruhayyil"]="Marj Ruhayyil", - ["Kiryat_Shmona"]="Kiryat Shmona", - ["Marj_as_Sultan_North"]="Marj as Sultan North", - ["Eyn_Shemer"]="Eyn Shemer", - ["Incirlik"]="Incirlik", - ["Damascus"]="Damascus", - ["Bassel_Al_Assad"]="Bassel Al-Assad", - ["Rosh_Pina"]="Rosh Pina", - ["Aleppo"]="Aleppo", - ["Al_Qusayr"]="Al Qusayr", - ["Wujah_Al_Hajar"]="Wujah Al Hajar", - ["Al_Dumayr"]="Al-Dumayr", - ["Gazipasa"]="Gazipasa", - ["Hatay"]="Hatay", - --["Nicosia"]="Nicosia", - ["Pinarbashi"]="Pinarbashi", - ["Paphos"]="Paphos", - ["Kingsfield"]="Kingsfield", - ["Thalah"]="Tha'lah", - ["Haifa"]="Haifa", - ["Khalkhalah"]="Khalkhalah", - ["Megiddo"]="Megiddo", - ["Lakatamia"]="Lakatamia", - ["Rayak"]="Rayak", - ["Larnaca"]="Larnaca", - ["Mezzeh"]="Mezzeh", - ["Gecitkale"]="Gecitkale", - ["Akrotiri"]="Akrotiri", - ["Naqoura"]="Naqoura", - ["Gaziantep"]="Gaziantep", - ["Sayqal"]="Sayqal", - ["Tiyas"]="Tiyas", - ["Shayrat"]="Shayrat", - ["Taftanaz"]="Taftanaz", - ["H4"]="H4", - ["King_Hussein_Air_College"]="King Hussein Air College", - ["Rene_Mouawad"]="Rene Mouawad", - ["Jirah"]="Jirah", - ["Ramat_David"]="Ramat David", - ["Qabr_as_Sitt"]="Qabr as Sitt", - ["Minakh"]="Minakh", - ["Adana_Sakirpasa"]="Adana Sakirpasa", - ["Palmyra"]="Palmyra", - ["Hama"]="Hama", - ["Ercan"]="Ercan", - ["Marj_as_Sultan_South"]="Marj as Sultan South", - ["Tabqa"]="Tabqa", - ["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri", - ["An_Nasiriyah"]="An Nasiriyah", - ["Abu_al_Duhur"]="Abu al-Duhur", - ["At_Tanf"]="At Tanf", - ["H3"]="H3", - ["H3_Northwest"]="H3 Northwest", - ["H3_Southwest"]="H3 Southwest", - ["Kharab_Ishk"]="Kharab Ishk", - -- ["Raj_al_Issa_East"]="Raj al Issa East", - -- ["Raj_al_Issa_West"]="Raj al Issa West", - ["Ruwayshid"]="Ruwayshid", - ["Sanliurfa"]="Sanliurfa", - ["Tal_Siman"]="Tal Siman", - ["Deir_ez_Zor"] = "Deir ez-Zor", + ["Kuweires"] = "Kuweires", + ["Incirlik"] = "Incirlik", + ["King_Abdullah_II"] = "King Abdullah II", + ["Akrotiri"] = "Akrotiri", + ["Aleppo"] = "Aleppo", + ["Abu_al_Duhur"] = "Abu al-Duhur", + ["Hatay"] = "Hatay", + ["Paphos"] = "Paphos", + ["At_Tanf"] = "At Tanf", + ["Tal_Siman"] = "Tal Siman", + ["Rayak"] = "Rayak", + ["Muwaffaq_Salti"] = "Muwaffaq Salti", + ["Naqoura"] = "Naqoura", + ["Gaziantep"] = "Gaziantep", + ["Al_Qusayr"] = "Al Qusayr", + ["Al_Dumayr"] = "Al-Dumayr", + ["Kingsfield"] = "Kingsfield", + ["Marj_as_Sultan_North"] = "Marj as Sultan North", + ["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri", + ["Palmyra"] = "Palmyra", + ["Hama"] = "Hama", + ["Eyn_Shemer"] = "Eyn Shemer", + ["Sanliurfa"] = "Sanliurfa", + ["Amman"] = "Amman", + ["Deir_ez_Zor"] = "Deir ez-Zor", + ["Taftanaz"] = "Taftanaz", + ["Damascus"] = "Damascus", + ["Gazipasa"] = "Gazipasa", + ["Herzliya"] = "Herzliya", + ["H4"] = "H4", + ["Tiyas"] = "Tiyas", + ["Lakatamia"] = "Lakatamia", + ["Kharab_Ishk"] = "Kharab Ishk", + ["Haifa"] = "Haifa", + ["Khalkhalah"] = "Khalkhalah", + ["Megiddo"] = "Megiddo", + ["An_Nasiriyah"] = "An Nasiriyah", + ["Bassel_Al_Assad"] = "Bassel Al-Assad", + ["Ruwayshid"] = "Ruwayshid", + ["Mezzeh"] = "Mezzeh", + ["Gecitkale"] = "Gecitkale", + ["Nicosia"] = "Nicosia", + ["Ramat_David"] = "Ramat David", + ["Tha_lah"] = "Tha'lah", + ["H3_Northwest"] = "H3 Northwest", + ["Sayqal"] = "Sayqal", + ["Jirah"] = "Jirah", + ["Shayrat"] = "Shayrat", + ["Adana_Sakirpasa"] = "Adana Sakirpasa", + ["Wujah_Al_Hajar"] = "Wujah Al Hajar", + ["Pinarbashi"] = "Pinarbashi", + ["H3_Southwest"] = "H3 Southwest", + ["Rosh_Pina"] = "Rosh Pina", + ["Kiryat_Shmona"] = "Kiryat Shmona", + ["H3"] = "H3", + ["Qabr_as_Sitt"] = "Qabr as Sitt", + ["Prince_Hassan"] = "Prince Hassan", + ["Larnaca"] = "Larnaca", + ["King_Hussein_Air_College"] = "King Hussein Air College", + ["Ercan"] = "Ercan", + ["Marj_Ruhayyil"] = "Marj Ruhayyil", + ["Tabqa"] = "Tabqa", + ["Marj_as_Sultan_South"] = "Marj as Sultan South", + ["Rene_Mouawad"] = "Rene Mouawad", + ["Minakh"] = "Minakh", } --- Airbases of the Mariana Islands map: From ced01a993db12edafdfffc3e55ff22e0ad498053 Mon Sep 17 00:00:00 2001 From: Rolf Geuenich Date: Fri, 23 Feb 2024 11:33:02 +0100 Subject: [PATCH 26/73] Added Links to new demo mission repository --- Moose Development/Moose/Core/Beacon.lua | 4 ++++ Moose Development/Moose/Core/Zone.lua | 4 ++++ Moose Development/Moose/Sound/Radio.lua | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index c3d22b823..de3d58417 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -8,6 +8,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/Beacon) +-- +-- === +-- -- ### Authors: Hugues "Grey_Echo" Bousquet, funkyfranky -- -- @module Core.Beacon diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index db176e783..ea5e1efa1 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -46,6 +46,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/Zone) +-- +-- === +-- -- ### Author: **FlightControl** -- ### Contributions: **Applevangelist**, **FunkyFranky**, **coconutcockpit** -- diff --git a/Moose Development/Moose/Sound/Radio.lua b/Moose Development/Moose/Sound/Radio.lua index 002e6ddaf..68acf2a5a 100644 --- a/Moose Development/Moose/Sound/Radio.lua +++ b/Moose Development/Moose/Sound/Radio.lua @@ -30,6 +30,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Sound/Radio) +-- +-- === +-- -- ### Authors: Hugues "Grey_Echo" Bousquet, funkyfranky -- -- @module Sound.Radio From d13173e33636d50d5646e963ca44005317d724a6 Mon Sep 17 00:00:00 2001 From: Rolf Geuenich Date: Fri, 23 Feb 2024 11:33:02 +0100 Subject: [PATCH 27/73] Added Links to new demo mission repository --- Moose Development/Moose/Core/Beacon.lua | 4 ++++ Moose Development/Moose/Core/Zone.lua | 4 ++++ Moose Development/Moose/Sound/Radio.lua | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index c3d22b823..de3d58417 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -8,6 +8,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/Beacon) +-- +-- === +-- -- ### Authors: Hugues "Grey_Echo" Bousquet, funkyfranky -- -- @module Core.Beacon diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index db176e783..ea5e1efa1 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -46,6 +46,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/Zone) +-- +-- === +-- -- ### Author: **FlightControl** -- ### Contributions: **Applevangelist**, **FunkyFranky**, **coconutcockpit** -- diff --git a/Moose Development/Moose/Sound/Radio.lua b/Moose Development/Moose/Sound/Radio.lua index 002e6ddaf..68acf2a5a 100644 --- a/Moose Development/Moose/Sound/Radio.lua +++ b/Moose Development/Moose/Sound/Radio.lua @@ -30,6 +30,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Sound/Radio) +-- +-- === +-- -- ### Authors: Hugues "Grey_Echo" Bousquet, funkyfranky -- -- @module Sound.Radio From 14d6085b69271332e83b477f4889e02b07db3260 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 24 Feb 2024 14:26:30 +0100 Subject: [PATCH 28/73] Added error message, that AATACAN is depricated --- Moose Development/Moose/Core/Beacon.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index de3d58417..7cc9434d6 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -290,6 +290,7 @@ end -- myBeacon:AATACAN(20, "TEXACO", true) -- Activate the beacon function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration) self:F({TACANChannel, Message, Bearing, BeaconDuration}) + self:E("This method is DEPRECATED! Please use ActivateTACAN() instead.") local IsValid = true From 5eef138507f9ab6ea54f334b1d850ba8eb85c123 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 24 Feb 2024 22:04:10 +0100 Subject: [PATCH 29/73] Enhancement of the docs --- docs/beginner/ask-for-help.md | 41 ++++++++++++++---- docs/beginner/problems.md | 7 +-- ...fomat-logs.png => discord-format-logs.png} | Bin 3 files changed, 37 insertions(+), 11 deletions(-) rename docs/images/beginner/{discord-fomat-logs.png => discord-format-logs.png} (100%) diff --git a/docs/beginner/ask-for-help.md b/docs/beginner/ask-for-help.md index bf8a9c8f6..060f26223 100644 --- a/docs/beginner/ask-for-help.md +++ b/docs/beginner/ask-for-help.md @@ -35,16 +35,24 @@ Please remember when posting a question: - Before posting anything follow the [troubleshooting steps]. - **Read your logs**. +### Formulate a good description + A post should contain the following: -1. A describtion what you expected to happen and what actually happened. - - Do not use vague words this stuff is hard to help with! Be specific. +- A description what you expected to happen and what actually happened. + - Do not use vague words this stuff is hard to help with! Be specific. -2. Describe what happens instead. - - The less detail you offer, the less chance you can be helped. - - Don’t say it doesn’t work. Or is it broken. Say what it actually does. +- Describe what happens instead. + - The less detail you offer, the less chance you can be helped. + - Don't say it doesn't work. Or is it broken. Say what it actually does. -3. Post your code in Discord as formatted code: +### Format your code + +The easier your code is to read, the more likely you are to get a helpful answer. If your code is hard to read, some +people who could help you may not even bother to read your code. Syntax Highlighting makes the code much clearer and +easier to understand. Therefore: + +- Post your code in Discord as formatted code: - Wrap a single line of code in backticks \` like this: @@ -54,14 +62,31 @@ A post should contain the following: ![discord-multi-line-code.png](../images/beginner/discord-multi-line-code.png) -- Post your log lines with the error or warning messages. Format them like this: +### Do not post a screenshot of your code - ![discord-fomat-logs.png](../images/beginner/discord-fomat-logs.png) +Your code is easy to read on a screenshot if you are using a good text editor or IDE, but if someone discovers an error +in your code and wants to post a corrected version, they will have to type out the entire code. This could lead to them +not helping you because it's too much work for them. + +### Post your log + +If the error message in the `dcs.log` does not tell you anything, then post it in the Discord. + +- Post the important log lines with the error or warning messages. Format them like this: + + ![discord-format-logs.png](../images/beginner/discord-format-logs.png) + +### Send your mission when requested + +Please don't just send your mission file. You have to manually extract the script from the file. +It is better to send your script code and log lines beforehand. +If this does not help, you may be asked to send your mission. - Some complex problems need the mission (.miz file) also. - But post your mission only when requested. - Try to simplify your mission if it is complex! + - Try to avoid or delete MODs, because could prevent people from helping you. There are people in the Discord and in the forum, who spend their free time to help you.
diff --git a/docs/beginner/problems.md b/docs/beginner/problems.md index ebc71077a..32357cb67 100644 --- a/docs/beginner/problems.md +++ b/docs/beginner/problems.md @@ -11,10 +11,12 @@ nav_order: 05 ## Something went wrong -If the mission shows not the expected behaviour do the following steps: +If the mission shows not the expected behavior do the following steps: 1. Double check if you added the changed mission script to the mission again! 1. Check if the triggers are configured as requested in the last sections. +1. Double check if you have the right version of MOOSE (some classes need the develop branch). +1. Try the newest version of MOOSE. ## Read the logs @@ -22,8 +24,7 @@ The DCS log is a super important and useful log for the entire of DCS World. All scripting and other errors are recorded here. It is the one stop shop for things that occurred in your mission. It will tell you if there was a mistake. -1. Open the file `dcs.log` in the `Logs` subfolder in your DCS - [Saved Games folder]. +1. Open the file `dcs.log` in the `Logs` subfolder in your DCS [Saved Games folder]. 1. Search for the following line: `*** MOOSE INCLUDE END ***` - If it is included in the log, Moose was loaded. diff --git a/docs/images/beginner/discord-fomat-logs.png b/docs/images/beginner/discord-format-logs.png similarity index 100% rename from docs/images/beginner/discord-fomat-logs.png rename to docs/images/beginner/discord-format-logs.png From c85f57588823e323829dbac63b62cf084f61cd71 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 24 Feb 2024 22:24:20 +0100 Subject: [PATCH 30/73] Enhancement of troubleshooting tips in the docs --- docs/beginner/problems.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/beginner/problems.md b/docs/beginner/problems.md index 32357cb67..ba88276a3 100644 --- a/docs/beginner/problems.md +++ b/docs/beginner/problems.md @@ -14,7 +14,9 @@ nav_order: 05 If the mission shows not the expected behavior do the following steps: 1. Double check if you added the changed mission script to the mission again! -1. Check if the triggers are configured as requested in the last sections. +1. Check if the triggers are configured as requested in the last sections: + - To load MOOSE: `4 MISSION START`, nothing on `CONDITIONS`, `DO SCRIPT FILE` to load `Moose_.lua`. + - To load mission script(s): `1 ONCE`, in `CONDITIONS` add `TIME MORE` = 1, `DO SCRIPT FILE` to load `yourscript.lua`. 1. Double check if you have the right version of MOOSE (some classes need the develop branch). 1. Try the newest version of MOOSE. From 1545add510ea7f6f0529654252a7f003be8a7689 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 24 Feb 2024 22:24:20 +0100 Subject: [PATCH 31/73] Enhancement of troubleshooting tips in the docs --- docs/beginner/problems.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/beginner/problems.md b/docs/beginner/problems.md index 32357cb67..ba88276a3 100644 --- a/docs/beginner/problems.md +++ b/docs/beginner/problems.md @@ -14,7 +14,9 @@ nav_order: 05 If the mission shows not the expected behavior do the following steps: 1. Double check if you added the changed mission script to the mission again! -1. Check if the triggers are configured as requested in the last sections. +1. Check if the triggers are configured as requested in the last sections: + - To load MOOSE: `4 MISSION START`, nothing on `CONDITIONS`, `DO SCRIPT FILE` to load `Moose_.lua`. + - To load mission script(s): `1 ONCE`, in `CONDITIONS` add `TIME MORE` = 1, `DO SCRIPT FILE` to load `yourscript.lua`. 1. Double check if you have the right version of MOOSE (some classes need the develop branch). 1. Try the newest version of MOOSE. From 1f9725530f111a54bd7a660234c0fc3d98e80bc6 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 27 Feb 2024 10:28:00 +0100 Subject: [PATCH 32/73] #CTLD - Added option to inject cargo objects which will not show up in the menu - for inject and move around purposes. --- Moose Development/Moose/Core/Set.lua | 4 +- Moose Development/Moose/Ops/CTLD.lua | 68 ++++++++++++++++++---------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 0045ee7fa..212bfc434 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -2997,7 +2997,7 @@ do -- SET_UNIT local velocity = self:GetVelocity() or 0 Coordinate:SetHeading( heading ) Coordinate:SetVelocity( velocity ) - self:I(UTILS.PrintTableToLog(Coordinate)) + self:T(UTILS.PrintTableToLog(Coordinate)) end return Coordinate @@ -4521,7 +4521,7 @@ do -- SET_CLIENT if Event.IniObjectCategory == Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround() then -- CA Slot entered local ObjectName, Object = self:AddInDatabase( Event ) - self:I( ObjectName, UTILS.PrintTableToLog(Object) ) + self:T( ObjectName, UTILS.PrintTableToLog(Object) ) if Object and self:IsIncludeObject( Object ) then self:Add( ObjectName, Object ) end diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 7adcf3afb..9f5b54d16 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -24,7 +24,7 @@ -- @module Ops.CTLD -- @image OPS_CTLD.jpg --- Last Update December 2023 +-- Last Update February 2024 do @@ -44,6 +44,7 @@ do -- @field #number PerCrateMass Mass in kg. -- @field #number Stock Number of builds available, -1 for unlimited. -- @field #string Subcategory Sub-category name. +-- @field #boolean DontShowInMenu Show this item in menu or not. -- @extends Core.Base#BASE --- @@ -62,6 +63,7 @@ CTLD_CARGO = { PerCrateMass = 0, Stock = nil, Mark = nil, + DontShowInMenu = false, } --- Define cargo types. @@ -97,8 +99,9 @@ CTLD_CARGO = { -- @param #number PerCrateMass Mass in kg -- @param #number Stock Number of builds available, nil for unlimited -- @param #string Subcategory Name of subcategory, handy if using > 10 types to load. + -- @param #boolean DontShowInMenu Show this item in menu or not (default: false == show it). -- @return #CTLD_CARGO self - function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory) + function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory,DontShowInMenu) -- Inherit everything from BASE class. local self=BASE:Inherit(self, BASE:New()) -- #CTLD_CARGO self:T({ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped}) @@ -115,6 +118,7 @@ CTLD_CARGO = { self.Stock = Stock or nil --#number self.Mark = nil self.Subcategory = Subcategory or "Other" + self.DontShowInMenu = DontShowInMenu or false return self end @@ -1228,7 +1232,7 @@ CTLD.UnitTypeCapabilities = { --- CTLD class version. -- @field #string version -CTLD.version="1.0.45" +CTLD.version="1.0.46" --- Instantiate a new CTLD. -- @param #CTLD self @@ -1433,7 +1437,7 @@ function CTLD:New(Coalition, Prefixes, Alias) --- Pseudo Functions --- ------------------------ - --- Triggers the FSM event "Start". Starts the CTLD. Initializes parameters and starts event handlers. + --- Triggers the FSM event "Start". Starts the CTLD. Initializes parameters and starts event handlers. -- @function [parent=#CTLD] Start -- @param #CTLD self @@ -3024,7 +3028,7 @@ end function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template) local Positions = {} local template = _DATABASE:GetGroupTemplate(Template) - UTILS.PrintTableToLog(template) + --UTILS.PrintTableToLog(template) local numbertroops = #template.units local newcenter = Coordinate:Translate(Radius,((Heading+270)%360)) for i=1,360,math.floor(360/numbertroops) do @@ -3038,7 +3042,7 @@ function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template) } table.insert(Positions,p1t) end - UTILS.PrintTableToLog(Positions) + --UTILS.PrintTableToLog(Positions) return Positions end @@ -3700,14 +3704,20 @@ function CTLD:_RefreshF10Menus() for _,_entry in pairs(self.Cargo_Troops) do local entry = _entry -- #CTLD_CARGO local subcat = entry.Subcategory - menucount = menucount + 1 - menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,subcatmenus[subcat],self._LoadTroops, self, _group, _unit, entry) + end end else for _,_entry in pairs(self.Cargo_Troops) do local entry = _entry -- #CTLD_CARGO - menucount = menucount + 1 - menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + menus[menucount] = MENU_GROUP_COMMAND:New(_group,entry.Name,troopsmenu,self._LoadTroops, self, _group, _unit, entry) + end end end local unloadmenu1 = MENU_GROUP_COMMAND:New(_group,"Drop troops",toptroops, self._UnloadTroops, self, _group, _unit):Refresh() @@ -3728,33 +3738,45 @@ function CTLD:_RefreshF10Menus() for _,_entry in pairs(self.Cargo_Crates) do local entry = _entry -- #CTLD_CARGO local subcat = entry.Subcategory - menucount = menucount + 1 - local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) - menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) + end end for _,_entry in pairs(self.Cargo_Statics) do local entry = _entry -- #CTLD_CARGO local subcat = entry.Subcategory - menucount = menucount + 1 - local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) - menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,subcatmenus[subcat],self._GetCrates, self, _group, _unit, entry) + end end else for _,_entry in pairs(self.Cargo_Crates) do local entry = _entry -- #CTLD_CARGO - menucount = menucount + 1 - local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) - menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + end end for _,_entry in pairs(self.Cargo_Statics) do local entry = _entry -- #CTLD_CARGO - menucount = menucount + 1 - local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) - menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + local noshow = entry.DontShowInMenu + if not noshow then + menucount = menucount + 1 + local menutext = string.format("Crate %s (%dkg)",entry.Name,entry.PerCrateMass or 0) + menus[menucount] = MENU_GROUP_COMMAND:New(_group,menutext,cratesmenu,self._GetCrates, self, _group, _unit, entry) + end end end listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit) - removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit) + local removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit) local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit) if not self.nobuildmenu then local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) From f2e22579ed482fee3734de4ab90e14418b92785c Mon Sep 17 00:00:00 2001 From: kaltokri Date: Tue, 27 Feb 2024 16:38:20 +0100 Subject: [PATCH 33/73] Added workaround for PatrolRoute problem Units may stay on initial point and cycle endless if Delay is smaller then 2. --- Moose Development/Moose/Wrapper/Controllable.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 4f291db8e..a7c4e235a 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -2173,7 +2173,7 @@ do -- Patrol methods local Waypoint = Waypoints[#Waypoints] PatrolGroup:SetTaskWaypoint( Waypoint, TaskRoute ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. - PatrolGroup:Route( Waypoints ) -- Move after a random seconds to the Route. See the Route method for details. + PatrolGroup:Route( Waypoints, 2 ) -- Move after a random seconds to the Route. See the Route method for details. end end From 45aebff48e1d537d678324ad01986713ded61f72 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 27 Feb 2024 18:13:55 +0100 Subject: [PATCH 34/73] #BRIGADE Fixes to save/loadback assets for persistence --- Moose Development/Moose/Utilities/Utils.lua | 85 +++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 6005dcbce..ec50854a0 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -3725,3 +3725,88 @@ end function UTILS.OctalToDecimal(Number) return tonumber(Number,8) end + +--- Function to save the position of a set of #OPSGROUP (ARMYGROUP) objects. +-- @param Core.Set#SET_OPSGROUP Set of ops objects to save +-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems. +-- @param #string Filename The name of the file. +-- @param #boolean Structured Append the data with a list of typenames in the group plus their count. +-- @return #boolean outcome True if saving is successful, else false. +function UTILS.SaveSetOfOpsGroups(Set,Path,Filename,Structured) + local filename = Filename or "SetOfGroups" + local data = "--Save SET of groups: (name,legion,template,alttemplate,units,position.x,position.y,position.z,strucdata) "..Filename .."\n" + local List = Set:GetSetObjects() + for _,_group in pairs (List) do + local group = _group:GetGroup() -- Wrapper.Group#GROUP + if group and group:IsAlive() then + local name = group:GetName() + local template = string.gsub(name,"(.AID.%d+$","") + if string.find(template,"#") then + template = string.gsub(name,"#(%d+)$","") + end + local alttemplate = _group.templatename or "none" + local legiono = _group.legion -- Ops.Legion#LEGION + local legion = "none" + if legiono and type(legiono) == "table" and legiono.ClassName then + legion = legiono:GetName() + local asset = legiono:GetAssetByName(name) -- Functional.Warehouse#WAREHOUSE.Assetitem + alttemplate=asset.templatename + end + local units = group:CountAliveUnits() + local position = group:GetVec3() + if Structured then + local structure = UTILS.GetCountPerTypeName(group) + local strucdata = "" + for typen,anzahl in pairs (structure) do + strucdata = strucdata .. typen .. "=="..anzahl..";" + end + data = string.format("%s%s,%s,%s,%s,%d,%d,%d,%d,%s\n",data,name,legion,template,alttemplate,units,position.x,position.y,position.z,strucdata) + else + data = string.format("%s%s,%s,%s,%s,%d,%d,%d,%d\n",data,name,legion,template,alttemplate,units,position.x,position.y,position.z) + end + end + end + -- save the data + local outcome = UTILS.SaveToFile(Path,Filename,data) + return outcome +end + +--- Load back a #OPSGROUP (ARMYGROUP) data from file for use with @{Ops.Brigade#BRIGADE.LoadBackAssetInPosition}() +-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems. +-- @param #string Filename The name of the file. +-- @return #table Returns a table of data entries: `{ groupname=groupname, size=size, coordinate=coordinate, template=template, structure=structure, legion=legion, alttemplate=alttemplate }` +-- Returns nil when the file cannot be read. +function UTILS.LoadSetOfOpsGroups(Path,Filename) + + local filename = Filename or "SetOfGroups" + local datatable = {} + + if UTILS.CheckFileExists(Path,filename) then + local outcome,loadeddata = UTILS.LoadFromFile(Path,Filename) + -- remove header + table.remove(loadeddata, 1) + for _id,_entry in pairs (loadeddata) do + local dataset = UTILS.Split(_entry,",") + -- 1name,2legion,3template,4alttemplate,5units,6position.x,7position.y,8position.z,9strucdata + local groupname = dataset[1] + local legion = dataset[2] + local template = dataset[3] + local alttemplate = dataset[4] + local size = tonumber(dataset[5]) + local posx = tonumber(dataset[6]) + local posy = tonumber(dataset[7]) + local posz = tonumber(dataset[8]) + local structure = dataset[9] + local coordinate = COORDINATE:NewFromVec3({x=posx, y=posy, z=posz}) + if size > 0 then + local data = { groupname=groupname, size=size, coordinate=coordinate, template=template, structure=structure, legion=legion, alttemplate=alttemplate } + table.insert(datatable,data) + end + end + else + return nil + end + + return datatable +end + From 82b5269040dbf2bdb2efbb7b28e9fcfc88073f32 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 27 Feb 2024 18:14:11 +0100 Subject: [PATCH 35/73] #BRIGADE Fixes to save/loadback assets for persistence --- Moose Development/Moose/Ops/Brigade.lua | 6 +++--- Moose Development/Moose/Ops/Legion.lua | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Ops/Brigade.lua b/Moose Development/Moose/Ops/Brigade.lua index 3242dc389..76e442df3 100644 --- a/Moose Development/Moose/Ops/Brigade.lua +++ b/Moose Development/Moose/Ops/Brigade.lua @@ -313,8 +313,8 @@ end -- -- local Path = FilePath or "C:\\Users\\\\Saved Games\\DCS\\Missions\\" -- example path -- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename --- local BlueSaveOps = SET_GROUP:New():FilterCoalitions("blue"):FilterPrefixes("AID"):FilterCategoryGround():FilterOnce() --- UTILS.SaveSetOfGroups(BlueSaveOps,Path,BlueOpsFilename) +-- local BlueSaveOps = SET_OPSGROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterOnce() +-- UTILS.SaveSetOfOpsGroups(BlueSaveOps,Path,BlueOpsFilename) -- -- where Path and Filename are strings, as chosen by you. -- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the @@ -324,7 +324,7 @@ end -- local Path = FilePath or "C:\\Users\\\\Saved Games\\DCS\\Missions\\" -- example path -- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename -- if UTILS.CheckFileExists(Path,BlueOpsFilename) then --- local loadback = UTILS.LoadSetOfGroups(Path,BlueOpsFilename,false) +-- local loadback = UTILS.LoadSetOfOpsGroups(Path,BlueOpsFilename,false) -- for _,_platoondata in pairs (loadback) do -- local groupname = _platoondata.groupname -- #string -- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua index 9c5861800..69c620dd1 100644 --- a/Moose Development/Moose/Ops/Legion.lua +++ b/Moose Development/Moose/Ops/Legion.lua @@ -3190,14 +3190,14 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu elseif (currmission.type==AUFTRAG.Type.ONGUARD or currmission.type==AUFTRAG.Type.PATROLZONE) and (MissionType==AUFTRAG.Type.ARTY or MissionType==AUFTRAG.Type.GROUNDATTACK) then score=score+25 elseif currmission.type==AUFTRAG.Type.NOTHING then - score=score+25 + score=score+30 end end if MissionType==AUFTRAG.Type.OPSTRANSPORT or MissionType==AUFTRAG.Type.AMMOSUPPLY or MissionType==AUFTRAG.Type.AWACS or MissionType==AUFTRAG.Type.FUELSUPPLY or MissionType==AUFTRAG.Type.TANKER then -- TODO: need to check for missions that do not require ammo like transport, recon, awacs, tanker etc. - -- We better take a fresh asset. Sometimes spawned assets to something else, which is difficult to check. + -- We better take a fresh asset. Sometimes spawned assets do something else, which is difficult to check. score=score-10 else -- Combat mission. From 595b9132e846525752f96c319b954f2030db31b8 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Wed, 28 Feb 2024 17:34:40 +0100 Subject: [PATCH 36/73] Added additional information to FOX:AddProtectedGroup method --- Moose Development/Moose/Functional/Fox.lua | 622 ++++++++++----------- 1 file changed, 311 insertions(+), 311 deletions(-) diff --git a/Moose Development/Moose/Functional/Fox.lua b/Moose Development/Moose/Functional/Fox.lua index 0c9c81b67..ee5854474 100644 --- a/Moose Development/Moose/Functional/Fox.lua +++ b/Moose Development/Moose/Functional/Fox.lua @@ -1,14 +1,14 @@ --- **Functional** - Yet Another Missile Trainer. --- --- +-- +-- -- Practice to evade missiles without being destroyed. --- +-- -- -- ## Main Features: --- +-- -- * Handles air-to-air and surface-to-air missiles. -- * Define your own training zones on the map. Players in this zone will be protected. --- * Define launch zones. Only missiles launched in these zones are tracked. +-- * Define launch zones. Only missiles launched in these zones are tracked. -- * Define protected AI groups. -- * F10 radio menu to adjust settings for each player. -- * Alert on missile launch (optional). @@ -16,7 +16,7 @@ -- * Adaptive update of missile-to-player distance. -- * Finite State Machine (FSM) implementation. -- * Easy to use. See examples below. --- +-- -- === -- -- ### Author: **funkyfranky** @@ -47,7 +47,7 @@ -- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec. -- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec. -- @field #number dt01 Time step [sec] for missile position updates if distance to target > 1 km and < 5 km. Default 0.1 sec. --- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec. +-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec. -- @extends Core.Fsm#FSM --- Fox 3! @@ -57,66 +57,66 @@ -- ![Banner Image](..\Presentations\FOX\FOX_Main.png) -- -- # The FOX Concept --- +-- -- As you probably know [Fox](https://en.wikipedia.org/wiki/Fox_\(code_word\)) is a NATO brevity code for launching air-to-air munition. Therefore, the class name is not 100% accurate as this -- script handles air-to-air but also surface-to-air missiles. --- +-- -- # Basic Script --- +-- -- -- Create a new missile trainer object. -- fox=FOX:New() --- +-- -- -- Start missile trainer. -- fox:Start() --- +-- -- # Training Zones --- +-- -- Players are only protected if they are inside one of the training zones. --- +-- -- -- Create a new missile trainer object. -- fox=FOX:New() --- +-- -- -- Add training zones. -- fox:AddSafeZone(ZONE:New("Training Zone Alpha")) -- fox:AddSafeZone(ZONE:New("Training Zone Bravo")) --- +-- -- -- Start missile trainer. -- fox:Start() --- +-- -- # Launch Zones --- +-- -- Missile launches are only monitored if the shooter is inside the defined launch zone. --- +-- -- -- Create a new missile trainer object. -- fox=FOX:New() --- +-- -- -- Add training zones. -- fox:AddLaunchZone(ZONE:New("Launch Zone SA-10 Krim")) -- fox:AddLaunchZone(ZONE:New("Training Zone Bravo")) --- +-- -- -- Start missile trainer. -- fox:Start() --- +-- -- # Protected AI Groups --- +-- -- Define AI protected groups. These groups cannot be harmed by missiles. --- +-- -- ## Add Individual Groups --- +-- -- -- Create a new missile trainer object. -- fox=FOX:New() --- +-- -- -- Add single protected group(s). -- fox:AddProtectedGroup(GROUP:FindByName("A-10 Protected")) -- fox:AddProtectedGroup(GROUP:FindByName("Yak-40")) --- +-- -- -- Start missile trainer. -- fox:Start() --- +-- -- # Notes --- +-- -- The script needs to be running before you enter an airplane slot. If FOX is not available to you, go back to observers and then join a slot again. --- +-- -- @field #FOX FOX = { ClassName = "FOX", @@ -218,17 +218,17 @@ function FOX:New() -- Inherit everthing from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #FOX - + -- Defaults: self:SetDefaultMissileDestruction(true) self:SetDefaultLaunchAlerts(true) self:SetDefaultLaunchMarks(true) - + -- Explosion/destruction defaults. self:SetExplosionDistance() self:SetExplosionDistanceBigMissiles() self:SetExplosionPower() - + -- Start State. self:SetStartState("Stopped") @@ -350,7 +350,7 @@ function FOX:New() -- @param #string To To state. -- @param #FOX.PlayerData player Player data. - + return self end @@ -368,16 +368,16 @@ function FOX:onafterStart(From, Event, To) -- Handle events: self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Shot) - + if self.Debug then self:HandleEvent(EVENTS.Hit) end - + if self.Debug then self:TraceClass(self.ClassName) self:TraceLevel(2) end - + self:__Status(-20) end @@ -395,7 +395,7 @@ function FOX:onafterStop(From, Event, To) -- Handle events: self:UnHandleEvent(EVENTS.Birth) self:UnHandleEvent(EVENTS.Shot) - + if self.Debug then self:UnhandleEvent(EVENTS.Hit) end @@ -437,18 +437,18 @@ function FOX:SetProtectedGroupSet(groupset) return self end ---- Add a group to the protected set. +--- Add a group to the protected set. Works only with AI! -- @param #FOX self -- @param Wrapper.Group#GROUP group Protected group. -- @return #FOX self function FOX:AddProtectedGroup(group) - + if not self.protectedset then self.protectedset=SET_GROUP:New() end - + self.protectedset:AddGroup(group) - + return self end @@ -483,7 +483,7 @@ end function FOX:SetExplosionDistanceBigMissiles(distance, explosivemass) self.explosiondist2=distance or 500 - + self.bigmissilemass=explosivemass or 50 return self @@ -609,18 +609,18 @@ function FOX:onafterStatus(From, Event, To) -- Get FSM state. local fsmstate=self:GetState() - + local time=timer.getAbsTime() local clock=UTILS.SecondsToClock(time) - + -- Status. if self.verbose>=1 then self:I(self.lid..string.format("Missile trainer status %s: %s", clock, fsmstate)) end - + -- Check missile status. self:_CheckMissileStatus() - + -- Check player status. self:_CheckPlayers() @@ -635,39 +635,39 @@ function FOX:_CheckPlayers() for playername,_playersettings in pairs(self.players) do local playersettings=_playersettings --#FOX.PlayerData - + local unitname=playersettings.unitname local unit=UNIT:FindByName(unitname) - + if unit and unit:IsAlive() then - + local coord=unit:GetCoordinate() - + local issafe=self:_CheckCoordSafe(coord) - - + + if issafe then - + ----------------------------- -- Player INSIDE Safe Zone -- ----------------------------- - + if not playersettings.inzone then self:EnterSafeZone(playersettings) playersettings.inzone=true end - + else - + ------------------------------ -- Player OUTSIDE Safe Zone -- - ------------------------------ - + ------------------------------ + if playersettings.inzone==true then self:ExitSafeZone(playersettings) playersettings.inzone=false end - + end end end @@ -686,7 +686,7 @@ function FOX:_RemoveMissile(missile) table.remove(self.missiles, i) return end - end + end end end @@ -699,7 +699,7 @@ function FOX:_CheckMissileStatus() local inactive={} for i,_missile in pairs(self.missiles) do local missile=_missile --#FOX.MissileData - + local targetname="unkown" if missile.targetUnit then targetname=missile.targetUnit:GetName() @@ -712,14 +712,14 @@ function FOX:_CheckMissileStatus() local mtype=missile.missileType local dtype=missile.missileType local range=UTILS.MetersToNM(missile.missileRange) - + if not active then table.insert(inactive,i) end local heading=self:_GetWeapongHeading(missile.weapon) - + text=text..string.format("\n[%d] %s: active=%s, range=%.1f NM, heading=%03d, target=%s, player=%s, missilename=%s", i, mtype, active, range, heading, targetname, playername, missile.missileName) - + end if #self.missiles==0 then text=text.." none" @@ -728,7 +728,7 @@ function FOX:_CheckMissileStatus() self:I(self.lid..text) end - -- Remove inactive missiles. + -- Remove inactive missiles. for i=#self.missiles,1,-1 do local missile=self.missiles[i] --#FOX.MissileData if missile and not missile.active then @@ -747,31 +747,31 @@ function FOX:_IsProtected(targetunit) if not self.protectedset then return false end - + if targetunit and targetunit:IsAlive() then -- Get Group. local targetgroup=targetunit:GetGroup() - + if targetgroup then local targetname=targetgroup:GetName() - + for _,_group in pairs(self.protectedset:GetSet()) do local group=_group --Wrapper.Group#GROUP - + if group then local groupname=group:GetName() - + -- Target belongs to a protected set. if targetname==groupname then return true end end - + end end end - + return false end @@ -784,22 +784,22 @@ function FOX._FuncTrack(weapon, self, missile) -- Missile coordinate. local missileCoord= missile.missileCoord:UpdateFromVec3(weapon.vec3) --COORDINATE:NewFromVec3(_lastBombPos) - + -- Missile velocity in m/s. local missileVelocity=weapon:GetSpeed() --UTILS.VecNorm(_ordnance:getVelocity()) - + -- Update missile target if necessary. self:GetMissileTarget(missile) - + -- Target unit of the missile. - local target=nil --Wrapper.Unit#UNIT - + local target=nil --Wrapper.Unit#UNIT + if missile.targetUnit then - + ----------------------------------- -- Missile has a specific target -- ----------------------------------- - + if missile.targetPlayer then -- Target is a player. if missile.targetPlayer.destroy==true then @@ -811,13 +811,13 @@ function FOX._FuncTrack(weapon, self, missile) target=missile.targetUnit end end - + else - + ------------------------------------ -- Missile has NO specific target -- - ------------------------------------ - + ------------------------------------ + -- TODO: This might cause a problem with wingman. Even if the shooter itself is excluded from the check, it's wingmen are not. -- That would trigger the distance check right after missile launch if things to wrong. -- @@ -825,165 +825,165 @@ function FOX._FuncTrack(weapon, self, missile) -- * Time check: enable this check after X seconds after missile was fired. What is X? -- * Coalition check. But would not work in training situations where blue on blue is valid! -- * At least enable it for surface-to-air missiles. - + local function _GetTarget(_unit) local unit=_unit --Wrapper.Unit#UNIT - + -- Player position. local playerCoord=unit:GetCoordinate() - - -- Distance. + + -- Distance. local dist=missileCoord:Get3DDistance(playerCoord) - + -- Update mindist if necessary. Only include players in range of missile + 50% safety margin. if dist<=self.explosiondist then return unit - end + end end - + -- Distance to closest player. local mindist=nil - + -- Loop over players. for _,_player in pairs(self.players) do local player=_player --#FOX.PlayerData - + -- Check that player was not the one who launched the missile. if player.unitname~=missile.shooterName then - + -- Player position. local playerCoord=player.unit:GetCoordinate() - - -- Distance. + + -- Distance. local dist=missileCoord:Get3DDistance(playerCoord) - + -- Distance from shooter to player. local Dshooter2player=playerCoord:Get3DDistance(missile.shotCoord) - + -- Update mindist if necessary. Only include players in range of missile + 50% safety margin. if (mindist==nil or dist=self.bigmissilemass end - + -- If missile is 150 m from target ==> destroy missile if in safe zone. if destroymissile and self:_CheckCoordSafe(targetVec3) then - + -- Destroy missile. - self:I(self.lid..string.format("Destroying missile %s(%s) fired by %s aimed at %s [player=%s] at distance %.1f m", + self:I(self.lid..string.format("Destroying missile %s(%s) fired by %s aimed at %s [player=%s] at distance %.1f m", missile.missileType, missile.missileName, missile.shooterName, target:GetName(), tostring(missile.targetPlayer~=nil), distance)) weapon:Destroy() - + -- Missile is not active any more. missile.active=false - + -- Debug smoke. if self.Debug then - missileCoord:SmokeRed() + missileCoord:SmokeRed() end - + -- Create event. self:MissileDestroyed(missile) - + -- Little explosion for the visual effect. if self.explosionpower>0 and distance>50 and (distShooter==nil or (distShooter and distShooter>50)) then missileCoord:Explosion(self.explosionpower) end - + -- Target was a player. if missile.targetPlayer then - + -- Message to target. local text=string.format("Destroying missile. %s", self:_DeadText()) MESSAGE:New(text, 10):ToGroup(target:GetGroup()) - + -- Increase dead counter. missile.targetPlayer.dead=missile.targetPlayer.dead+1 end -- We could disable the tracking here but then the impact function would not be called. --weapon.tracking=false - + else - + -- Time step. - local dt=1.0 + local dt=1.0 if distance>50000 then -- > 50 km dt=self.dt50 --=5.0 @@ -1000,17 +1000,17 @@ function FOX._FuncTrack(weapon, self, missile) -- < 1 km dt=self.dt00 --0.01 end - + -- Set time step. weapon:SetTimeStepTrack(dt) end - + else - + -- No current target. self:T(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName)) weapon:SetTimeStepTrack(0.1) - + end end @@ -1021,25 +1021,25 @@ end -- @param #FOX.MissileData missile Fired missile. function FOX._FuncImpact(weapon, self, missile) - if missile.targetPlayer then - + if missile.targetPlayer then + -- Get human player. local player=missile.targetPlayer - + -- Check for player and distance < 10 km. if player and player.unit:IsAlive() then -- and missileCoord and player.unit:GetCoordinate():Get3DDistance(missileCoord)<10*1000 then local text=string.format("Missile defeated. Well done, %s!", player.name) MESSAGE:New(text, 10):ToClient(player.client) - + -- Increase defeated counter. player.defeated=player.defeated+1 end - + end - + -- Missile is not active any more. - missile.active=false - + missile.active=false + --Terminate the timer. self:T(FOX.lid..string.format("Terminating missile track timer.")) weapon.tracking=false @@ -1058,59 +1058,59 @@ function FOX:onafterMissileLaunch(From, Event, To, missile) local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName) self:I(FOX.lid..text) MESSAGE:New(text, 10):ToAllIf(self.Debug) - + -- Loop over players. for _,_player in pairs(self.players) do local player=_player --#FOX.PlayerData - + -- Player position. local playerUnit=player.unit - + -- Check that player is alive and of the opposite coalition. if playerUnit and playerUnit:IsAlive() and player.coalition~=missile.shooterCoalition then - + -- Player missile distance. local distance=playerUnit:GetCoordinate():Get3DDistance(missile.shotCoord) - + -- Player bearing to missile. local bearing=playerUnit:GetCoordinate():HeadingTo(missile.shotCoord) - + -- Alert that missile has been launched. if player.launchalert then - + -- Alert directly targeted players or players that are within missile max range. if (missile.targetPlayer and player.unitname==missile.targetPlayer.unitname) or (distance Target=%s, fuse dist=%s, explosive=%s", tostring(missile.shooterName), tostring(missile.missileType), tostring(missile.missileName), tostring(missile.targetName), tostring(missile.fuseDist), tostring(missile.explosive))) - + -- Only track if target was a player or target is protected. Saw the 9M311 missiles have no target! if missile.targetPlayer or self:_IsProtected(missile.targetUnit) or missile.targetName=="unknown" then - + -- Add missile table. table.insert(self.missiles, missile) - + -- Trigger MissileLaunch event. self:__MissileLaunch(0.1, missile) - + end - + end --if _track - + end --- FOX event handler for event hit. @@ -1340,7 +1340,7 @@ end -- @param Core.Event#EVENTDATA EventData function FOX:OnEventHit(EventData) self:T({eventhit = EventData}) - + -- Nil checks. if EventData.Weapon==nil then return @@ -1351,10 +1351,10 @@ function FOX:OnEventHit(EventData) if EventData.TgtUnit==nil then return end - + local weapon=EventData.Weapon local weaponname=weapon:getName() - + for i,_missile in pairs(self.missiles) do local missile=_missile --#FOX.MissileData if missile.missileName==weaponname then @@ -1375,51 +1375,51 @@ end -- @param #string _unitName Name of player unit. function FOX:_AddF10Commands(_unitName) self:F(_unitName) - + -- Get player unit and name. local _unit, playername = self:_GetPlayerUnitAndName(_unitName) - + -- Check for player unit. if _unit and playername then -- Get group and ID. local group=_unit:GetGroup() local gid=group:GetID() - + if group and gid then - + if not self.menuadded[gid] then - + -- Enable switch so we don't do this twice. self.menuadded[gid]=true - + -- Set menu root path. local _rootPath=nil if FOX.MenuF10Root then ------------------------ -- MISSON LEVEL MENUE -- - ------------------------ - + ------------------------ + -- F10/FOX/... _rootPath=FOX.MenuF10Root - + else ------------------------ -- GROUP LEVEL MENUES -- ------------------------ - + -- Main F10 menu: F10/FOX/ if FOX.MenuF10[gid]==nil then FOX.MenuF10[gid]=missionCommands.addSubMenuForGroup(gid, "FOX") end - + -- F10/FOX/... _rootPath=FOX.MenuF10[gid] - + end - - - -------------------------------- + + + -------------------------------- -- F10/F FOX/F1 Help -------------------------------- --local _helpPath=missionCommands.addSubMenuForGroup(gid, "Help", _rootPath) @@ -1430,12 +1430,12 @@ function FOX:_AddF10Commands(_unitName) ------------------------- -- F10/F FOX/ ------------------------- - + missionCommands.addCommandForGroup(gid, "Destroy Missiles On/Off", _rootPath, self._ToggleDestroyMissiles, self, _unitName) -- F1 missionCommands.addCommandForGroup(gid, "Launch Alerts On/Off", _rootPath, self._ToggleLaunchAlert, self, _unitName) -- F2 missionCommands.addCommandForGroup(gid, "Mark Launch On/Off", _rootPath, self._ToggleLaunchMark, self, _unitName) -- F3 missionCommands.addCommandForGroup(gid, "My Status", _rootPath, self._MyStatus, self, _unitName) -- F4 - + end else self:E(self.lid..string.format("ERROR: Could not find group or group ID in AddF10Menu() function. Unit name: %s.", _unitName or "unknown")) @@ -1452,23 +1452,23 @@ end -- @param #string _unitname Name of the player unit. function FOX:_MyStatus(_unitname) self:F2(_unitname) - + -- Get player unit and player name. local unit, playername = self:_GetPlayerUnitAndName(_unitname) - + -- Check if we have a player. if unit and playername then - - -- Player data. + + -- Player data. local playerData=self.players[playername] --#FOX.PlayerData - + if playerData then - + local m,mtext=self:_GetTargetMissiles(playerData.name) - + local text=string.format("Status of player %s:\n", playerData.name) local safe=self:_CheckCoordSafe(playerData.unit:GetCoordinate()) - + text=text..string.format("Destroy missiles? %s\n", tostring(playerData.destroy)) text=text..string.format("Launch alert? %s\n", tostring(playerData.launchalert)) text=text..string.format("Launch marks? %s\n", tostring(playerData.marklaunch)) @@ -1476,9 +1476,9 @@ function FOX:_MyStatus(_unitname) text=text..string.format("Missiles defeated: %d\n", playerData.defeated) text=text..string.format("Missiles destroyed: %d\n", playerData.dead) text=text..string.format("Me target: %d\n%s", m, mtext) - + MESSAGE:New(text, 10, nil, true):ToClient(playerData.client) - + end end end @@ -1494,12 +1494,12 @@ function FOX:_GetTargetMissiles(playername) local n=0 for _,_missile in pairs(self.missiles) do local missile=_missile --#FOX.MissileData - + if missile.targetPlayer and missile.targetPlayer.name==playername then n=n+1 text=text..string.format("Type %s: active %s\n", missile.missileType, tostring(missile.active)) end - + end return n,text @@ -1510,21 +1510,21 @@ end -- @param #string _unitname Name of the player unit. function FOX:_ToggleLaunchAlert(_unitname) self:F2(_unitname) - + -- Get player unit and player name. local unit, playername = self:_GetPlayerUnitAndName(_unitname) - + -- Check if we have a player. if unit and playername then - - -- Player data. + + -- Player data. local playerData=self.players[playername] --#FOX.PlayerData - + if playerData then - + -- Invert state. playerData.launchalert=not playerData.launchalert - + -- Inform player. local text="" if playerData.launchalert==true then @@ -1533,7 +1533,7 @@ function FOX:_ToggleLaunchAlert(_unitname) text=string.format("%s, missile launch alerts are now DISABLED.", playerData.name) end MESSAGE:New(text, 5):ToClient(playerData.client) - + end end end @@ -1543,21 +1543,21 @@ end -- @param #string _unitname Name of the player unit. function FOX:_ToggleLaunchMark(_unitname) self:F2(_unitname) - + -- Get player unit and player name. local unit, playername = self:_GetPlayerUnitAndName(_unitname) - + -- Check if we have a player. if unit and playername then - - -- Player data. + + -- Player data. local playerData=self.players[playername] --#FOX.PlayerData - + if playerData then - + -- Invert state. playerData.marklaunch=not playerData.marklaunch - + -- Inform player. local text="" if playerData.marklaunch==true then @@ -1566,7 +1566,7 @@ function FOX:_ToggleLaunchMark(_unitname) text=string.format("%s, missile launch marks are now DISABLED.", playerData.name) end MESSAGE:New(text, 5):ToClient(playerData.client) - + end end end @@ -1577,21 +1577,21 @@ end -- @param #string _unitname Name of the player unit. function FOX:_ToggleDestroyMissiles(_unitname) self:F2(_unitname) - + -- Get player unit and player name. local unit, playername = self:_GetPlayerUnitAndName(_unitname) - + -- Check if we have a player. if unit and playername then - - -- Player data. + + -- Player data. local playerData=self.players[playername] --#FOX.PlayerData - + if playerData then - + -- Invert state. playerData.destroy=not playerData.destroy - + -- Inform player. local text="" if playerData.destroy==true then @@ -1600,7 +1600,7 @@ function FOX:_ToggleDestroyMissiles(_unitname) text=string.format("%s, incoming missiles will NOT be DESTROYED.", playerData.name) end MESSAGE:New(text, 5):ToClient(playerData.client) - + end end end @@ -1622,9 +1622,9 @@ function FOX:_DeadText() texts[4]="Well, I guess that was it!" texts[5]="Bye, bye!" texts[6]="Cheers buddy, was nice knowing you!" - + local r=math.random(#texts) - + return texts[r] end @@ -1637,9 +1637,9 @@ function FOX:_CheckCoordSafe(coord) -- No safe zones defined ==> Everything is safe. if #self.safezones==0 then - return true + return true end - + -- Loop over all zones. for _,_zone in pairs(self.safezones) do local zone=_zone --Core.Zone#ZONE @@ -1662,9 +1662,9 @@ function FOX:_CheckCoordLaunch(coord) -- No safe zones defined ==> Everything is safe. if #self.launchzones==0 then - return true + return true end - + -- Loop over all zones. for _,_zone in pairs(self.launchzones) do local zone=_zone --Core.Zone#ZONE @@ -1679,50 +1679,50 @@ function FOX:_CheckCoordLaunch(coord) return false end ---- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned. +--- 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 Heading of weapon in degrees or -1. function FOX:_GetWeapongHeading(weapon) if weapon and weapon:isExist() then - + local wp=weapon:getPosition() - + local wph = math.atan2(wp.x.z, wp.x.x) - + if wph < 0 then wph=wph+2*math.pi end - + wph=math.deg(wph) - + return wph end return -1 end ---- Tell player notching headings. +--- Tell player notching headings. -- @param #FOX self -- @param #FOX.PlayerData playerData Player data. -- @param DCS#Weapon weapon The weapon. function FOX:_SayNotchingHeadings(playerData, weapon) if playerData and playerData.unit and playerData.unit:IsAlive() then - + local nr, nl=self:_GetNotchingHeadings(weapon) - + if nr and nl then - local text=string.format("Notching heading %03d° or %03d°", nr, nl) + local text=string.format("Notching heading %03d° or %03d°", nr, nl) MESSAGE:New(text, 5, "FOX"):ToClient(playerData.client) end - + end end ---- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned. +--- 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°. @@ -1730,22 +1730,22 @@ end function FOX:_GetNotchingHeadings(weapon) if weapon then - + local hdg=self:_GetWeapongHeading(weapon) - + local hdg1=hdg+90 if hdg1>360 then hdg1=hdg1-360 end - + local hdg2=hdg-90 if hdg2<0 then hdg2=hdg2+360 end - + return hdg1, hdg2 - end - + end + return nil, nil end @@ -1755,14 +1755,14 @@ end -- @return #FOX.PlayerData Player data. function FOX:_GetPlayerFromUnitname(unitName) - for _,_player in pairs(self.players) do + for _,_player in pairs(self.players) do local player=_player --#FOX.PlayerData - + if player.unitname==unitName then return player end end - + return nil end @@ -1777,20 +1777,20 @@ function FOX:_GetPlayerFromUnit(unit) -- Name of the unit local unitname=unit:GetName() - for _,_player in pairs(self.players) do + for _,_player in pairs(self.players) do local player=_player --#FOX.PlayerData - + if player.unitname==unitname then return player end end end - + return nil end ---- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned. +--- 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 #string _unitName Name of the player unit. -- @return Wrapper.Unit#UNIT Unit of player or nil. @@ -1799,31 +1799,31 @@ function FOX:_GetPlayerUnitAndName(_unitName) self:F2(_unitName) if _unitName ~= nil then - + -- Get DCS unit from its name. local DCSunit=Unit.getByName(_unitName) - + if DCSunit then - + -- Get player name if any. local playername=DCSunit:getPlayerName() - + -- Unit object. local unit=UNIT:Find(DCSunit) - + -- Debug. self:T2({DCSunit=DCSunit, unit=unit, playername=playername}) - + -- Check if enverything is there. if DCSunit and unit and playername then self:T(self.lid..string.format("Found DCS unit %s with player %s.", tostring(_unitName), tostring(playername))) return unit, playername end - + end - + end - + -- Return nil if we could not find a player. return nil,nil end From 1cbdafda65f39e9574bd020ab036667b53f66ae6 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Wed, 28 Feb 2024 17:39:06 +0100 Subject: [PATCH 37/73] Added link to demo missions for Functional.Fox --- Moose Development/Moose/Functional/Fox.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Moose Development/Moose/Functional/Fox.lua b/Moose Development/Moose/Functional/Fox.lua index ee5854474..5ca6d4e51 100644 --- a/Moose Development/Moose/Functional/Fox.lua +++ b/Moose Development/Moose/Functional/Fox.lua @@ -19,6 +19,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Functional/FOX) +-- +-- === +-- -- ### Author: **funkyfranky** -- @module Functional.Fox -- @image Functional_FOX.png From 74c19f105830399d76d270a5c0879df48bb1e2f8 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Wed, 28 Feb 2024 19:43:08 +0100 Subject: [PATCH 38/73] Added new airfields in Normandy --- Moose Development/Moose/Wrapper/Airbase.lua | 458 ++++++++++---------- 1 file changed, 231 insertions(+), 227 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 490edcba7..ae2d9db16 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -169,163 +169,167 @@ AIRBASE.Nevada = { --- Airbases of the Normandy map: -- --- * AIRBASE.Normandy.Saint_Pierre_du_Mont --- * AIRBASE.Normandy.Lignerolles --- * AIRBASE.Normandy.Cretteville --- * AIRBASE.Normandy.Maupertus --- * AIRBASE.Normandy.Brucheville --- * AIRBASE.Normandy.Meautis --- * AIRBASE.Normandy.Cricqueville_en_Bessin --- * AIRBASE.Normandy.Lessay --- * AIRBASE.Normandy.Sainte_Laurent_sur_Mer --- * AIRBASE.Normandy.Biniville --- * AIRBASE.Normandy.Cardonville --- * AIRBASE.Normandy.Deux_Jumeaux --- * AIRBASE.Normandy.Chippelle --- * AIRBASE.Normandy.Beuzeville --- * AIRBASE.Normandy.Azeville --- * AIRBASE.Normandy.Picauville --- * AIRBASE.Normandy.Le_Molay --- * AIRBASE.Normandy.Longues_sur_Mer --- * AIRBASE.Normandy.Carpiquet --- * AIRBASE.Normandy.Bazenville --- * AIRBASE.Normandy.Sainte_Croix_sur_Mer --- * AIRBASE.Normandy.Beny_sur_Mer --- * AIRBASE.Normandy.Rucqueville --- * AIRBASE.Normandy.Sommervieu --- * AIRBASE.Normandy.Lantheuil --- * AIRBASE.Normandy.Evreux --- * AIRBASE.Normandy.Chailey --- * AIRBASE.Normandy.Needs_Oar_Point --- * AIRBASE.Normandy.Funtington --- * AIRBASE.Normandy.Tangmere --- * AIRBASE.Normandy.Ford --- * AIRBASE.Normandy.Argentan --- * AIRBASE.Normandy.Goulet --- * AIRBASE.Normandy.Barville --- * AIRBASE.Normandy.Essay --- * AIRBASE.Normandy.Hauterive --- * AIRBASE.Normandy.Lymington --- * AIRBASE.Normandy.Vrigny --- * AIRBASE.Normandy.Odiham --- * AIRBASE.Normandy.Conches --- * AIRBASE.Normandy.West_Malling --- * AIRBASE.Normandy.Villacoublay --- * AIRBASE.Normandy.Kenley --- * AIRBASE.Normandy.Beauvais_Tille --- * AIRBASE.Normandy.Cormeilles_en_Vexin --- * AIRBASE.Normandy.Creil --- * AIRBASE.Normandy.Guyancourt --- * AIRBASE.Normandy.Lonrai --- * AIRBASE.Normandy.Dinan_Trelivan --- * AIRBASE.Normandy.Heathrow --- * AIRBASE.Normandy.Fecamp_Benouville --- * AIRBASE.Normandy.Farnborough --- * AIRBASE.Normandy.Friston --- * AIRBASE.Normandy.Deanland --- * AIRBASE.Normandy.Triqueville --- * AIRBASE.Normandy.Poix --- * AIRBASE.Normandy.Orly --- * AIRBASE.Normandy.Stoney_Cross --- * AIRBASE.Normandy.Amiens_Glisy --- * AIRBASE.Normandy.Ronai --- * AIRBASE.Normandy.Rouen_Boos --- * AIRBASE.Normandy.Deauville --- * AIRBASE.Normandy.Saint_Aubin --- * AIRBASE.Normandy.Flers --- * AIRBASE.Normandy.Avranches_Le_Val_Saint_Pere --- * AIRBASE.Normandy.Gravesend --- * AIRBASE.Normandy.Beaumont_le_Roger --- * AIRBASE.Normandy.Broglie --- * AIRBASE.Normandy.Bernay_Saint_Martin --- * AIRBASE.Normandy.Saint_Andre_de_lEure --- * AIRBASE.Normandy.Biggin_Hill --- * AIRBASE.Normandy.Manston --- * AIRBASE.Normandy.Detling --- * AIRBASE.Normandy.Lympne --- * AIRBASE.Normandy.Abbeville_Drucat --- * AIRBASE.Normandy.Merville_Calonne --- * AIRBASE.Normandy.Saint_Omer_Wizernes +-- * AIRBASE.Normandy.Abbeville_Drucat +-- * AIRBASE.Normandy.Amiens_Glisy +-- * AIRBASE.Normandy.Argentan +-- * AIRBASE.Normandy.Avranches_Le_Val_Saint_Pere +-- * AIRBASE.Normandy.Azeville +-- * AIRBASE.Normandy.Barville +-- * AIRBASE.Normandy.Bazenville +-- * AIRBASE.Normandy.Beaumont_le_Roger +-- * AIRBASE.Normandy.Beauvais_Tille +-- * AIRBASE.Normandy.Beny_sur_Mer +-- * AIRBASE.Normandy.Bernay_Saint_Martin +-- * AIRBASE.Normandy.Beuzeville +-- * AIRBASE.Normandy.Biggin_Hill +-- * AIRBASE.Normandy.Biniville +-- * AIRBASE.Normandy.Broglie +-- * AIRBASE.Normandy.Brucheville +-- * AIRBASE.Normandy.Cardonville +-- * AIRBASE.Normandy.Carpiquet +-- * AIRBASE.Normandy.Chailey +-- * AIRBASE.Normandy.Chippelle +-- * AIRBASE.Normandy.Conches +-- * AIRBASE.Normandy.Cormeilles_en_Vexin +-- * AIRBASE.Normandy.Creil +-- * AIRBASE.Normandy.Cretteville +-- * AIRBASE.Normandy.Cricqueville_en_Bessin +-- * AIRBASE.Normandy.Deanland +-- * AIRBASE.Normandy.Deauville +-- * AIRBASE.Normandy.Detling +-- * AIRBASE.Normandy.Deux_Jumeaux +-- * AIRBASE.Normandy.Dinan_Trelivan +-- * AIRBASE.Normandy.Dunkirk_Mardyck +-- * AIRBASE.Normandy.Essay +-- * AIRBASE.Normandy.Evreux +-- * AIRBASE.Normandy.Farnborough +-- * AIRBASE.Normandy.Fecamp_Benouville +-- * AIRBASE.Normandy.Flers +-- * AIRBASE.Normandy.Ford +-- * AIRBASE.Normandy.Friston +-- * AIRBASE.Normandy.Funtington +-- * AIRBASE.Normandy.Goulet +-- * AIRBASE.Normandy.Gravesend +-- * AIRBASE.Normandy.Guyancourt +-- * AIRBASE.Normandy.Hauterive +-- * AIRBASE.Normandy.Heathrow +-- * AIRBASE.Normandy.High_Halden +-- * AIRBASE.Normandy.Kenley +-- * AIRBASE.Normandy.Lantheuil +-- * AIRBASE.Normandy.Le_Molay +-- * AIRBASE.Normandy.Lessay +-- * AIRBASE.Normandy.Lignerolles +-- * AIRBASE.Normandy.Longues_sur_Mer +-- * AIRBASE.Normandy.Lonrai +-- * AIRBASE.Normandy.Lymington +-- * AIRBASE.Normandy.Lympne +-- * AIRBASE.Normandy.Manston +-- * AIRBASE.Normandy.Maupertus +-- * AIRBASE.Normandy.Meautis +-- * AIRBASE.Normandy.Merville_Calonne +-- * AIRBASE.Normandy.Needs_Oar_Point +-- * AIRBASE.Normandy.Odiham +-- * AIRBASE.Normandy.Orly +-- * AIRBASE.Normandy.Picauville +-- * AIRBASE.Normandy.Poix +-- * AIRBASE.Normandy.Ronai +-- * AIRBASE.Normandy.Rouen_Boos +-- * AIRBASE.Normandy.Rucqueville +-- * AIRBASE.Normandy.Saint_Andre_de_lEure +-- * AIRBASE.Normandy.Saint_Aubin +-- * AIRBASE.Normandy.Saint_Omer_Wizernes +-- * AIRBASE.Normandy.Saint_Pierre_du_Mont +-- * AIRBASE.Normandy.Sainte_Croix_sur_Mer +-- * AIRBASE.Normandy.Sainte_Laurent_sur_Mer +-- * AIRBASE.Normandy.Sommervieu +-- * AIRBASE.Normandy.Stoney_Cross +-- * AIRBASE.Normandy.Tangmere +-- * AIRBASE.Normandy.Triqueville +-- * AIRBASE.Normandy.Villacoublay +-- * AIRBASE.Normandy.Vrigny +-- * AIRBASE.Normandy.West_Malling -- -- @field Normandy AIRBASE.Normandy = { - ["Saint_Pierre_du_Mont"] = "Saint Pierre du Mont", - ["Lignerolles"] = "Lignerolles", - ["Cretteville"] = "Cretteville", - ["Maupertus"] = "Maupertus", - ["Brucheville"] = "Brucheville", - ["Meautis"] = "Meautis", - ["Cricqueville_en_Bessin"] = "Cricqueville-en-Bessin", - ["Lessay"] = "Lessay", - ["Sainte_Laurent_sur_Mer"] = "Sainte-Laurent-sur-Mer", - ["Biniville"] = "Biniville", - ["Cardonville"] = "Cardonville", - ["Deux_Jumeaux"] = "Deux Jumeaux", - ["Chippelle"] = "Chippelle", - ["Beuzeville"] = "Beuzeville", - ["Azeville"] = "Azeville", - ["Picauville"] = "Picauville", - ["Le_Molay"] = "Le Molay", - ["Longues_sur_Mer"] = "Longues-sur-Mer", - ["Carpiquet"] = "Carpiquet", - ["Bazenville"] = "Bazenville", - ["Sainte_Croix_sur_Mer"] = "Sainte-Croix-sur-Mer", - ["Beny_sur_Mer"] = "Beny-sur-Mer", - ["Rucqueville"] = "Rucqueville", - ["Sommervieu"] = "Sommervieu", - ["Lantheuil"] = "Lantheuil", - ["Evreux"] = "Evreux", - ["Chailey"] = "Chailey", - ["Needs_Oar_Point"] = "Needs Oar Point", - ["Funtington"] = "Funtington", - ["Tangmere"] = "Tangmere", - ["Ford"] = "Ford", + ["Abbeville_Drucat"] = "Abbeville Drucat", + ["Amiens_Glisy"] = "Amiens-Glisy", ["Argentan"] = "Argentan", - ["Goulet"] = "Goulet", + ["Avranches_Le_Val_Saint_Pere"] = "Avranches Le Val-Saint-Pere", + ["Azeville"] = "Azeville", ["Barville"] = "Barville", - ["Essay"] = "Essay", - ["Hauterive"] = "Hauterive", - ["Lymington"] = "Lymington", - ["Vrigny"] = "Vrigny", - ["Odiham"] = "Odiham", - ["Conches"] = "Conches", - ["West_Malling"] = "West Malling", - ["Villacoublay"] = "Villacoublay", - ["Kenley"] = "Kenley", + ["Bazenville"] = "Bazenville", + ["Beaumont_le_Roger"] = "Beaumont-le-Roger", ["Beauvais_Tille"] = "Beauvais-Tille", + ["Beny_sur_Mer"] = "Beny-sur-Mer", + ["Bernay_Saint_Martin"] = "Bernay Saint Martin", + ["Beuzeville"] = "Beuzeville", + ["Biggin_Hill"] = "Biggin Hill", + ["Biniville"] = "Biniville", + ["Broglie"] = "Broglie", + ["Brucheville"] = "Brucheville", + ["Cardonville"] = "Cardonville", + ["Carpiquet"] = "Carpiquet", + ["Chailey"] = "Chailey", + ["Chippelle"] = "Chippelle", + ["Conches"] = "Conches", ["Cormeilles_en_Vexin"] = "Cormeilles-en-Vexin", ["Creil"] = "Creil", - ["Guyancourt"] = "Guyancourt", - ["Lonrai"] = "Lonrai", - ["Dinan_Trelivan"] = "Dinan-Trelivan", - ["Heathrow"] = "Heathrow", - ["Fecamp_Benouville"] = "Fecamp-Benouville", - ["Farnborough"] = "Farnborough", - ["Friston"] = "Friston", + ["Cretteville"] = "Cretteville", + ["Cricqueville_en_Bessin"] = "Cricqueville-en-Bessin", ["Deanland"] = "Deanland", - ["Triqueville"] = "Triqueville", - ["Poix"] = "Poix", + ["Deauville"] = "Deauville", + ["Detling"] = "Detling", + ["Deux_Jumeaux"] = "Deux Jumeaux", + ["Dinan_Trelivan"] = "Dinan-Trelivan", + ["Dunkirk_Mardyck"] = "Dunkirk-Mardyck", + ["Essay"] = "Essay", + ["Evreux"] = "Evreux", + ["Farnborough"] = "Farnborough", + ["Fecamp_Benouville"] = "Fecamp-Benouville", + ["Flers"] = "Flers", + ["Ford"] = "Ford", + ["Friston"] = "Friston", + ["Funtington"] = "Funtington", + ["Goulet"] = "Goulet", + ["Gravesend"] = "Gravesend", + ["Guyancourt"] = "Guyancourt", + ["Hauterive"] = "Hauterive", + ["Heathrow"] = "Heathrow", + ["High_Halden"] = "High Halden", + ["Kenley"] = "Kenley", + ["Lantheuil"] = "Lantheuil", + ["Le_Molay"] = "Le Molay", + ["Lessay"] = "Lessay", + ["Lignerolles"] = "Lignerolles", + ["Longues_sur_Mer"] = "Longues-sur-Mer", + ["Lonrai"] = "Lonrai", + ["Lymington"] = "Lymington", + ["Lympne"] = "Lympne", + ["Manston"] = "Manston", + ["Maupertus"] = "Maupertus", + ["Meautis"] = "Meautis", + ["Merville_Calonne"] = "Merville Calonne", + ["Needs_Oar_Point"] = "Needs Oar Point", + ["Odiham"] = "Odiham", ["Orly"] = "Orly", - ["Stoney_Cross"] = "Stoney Cross", - ["Amiens_Glisy"] = "Amiens-Glisy", + ["Picauville"] = "Picauville", + ["Poix"] = "Poix", ["Ronai"] = "Ronai", ["Rouen_Boos"] = "Rouen-Boos", - ["Deauville"] = "Deauville", + ["Rucqueville"] = "Rucqueville", + ["Saint_Andre_de_lEure"] = "Saint-Andre-de-lEure", ["Saint_Aubin"] = "Saint-Aubin", - ["Flers"] = "Flers", - ["Avranches_Le_Val_Saint_Pere"] = "Avranches Le Val-Saint-Pere", - ["Gravesend"] = "Gravesend", - ["Beaumont_le_Roger"] = "Beaumont-le-Roger", - ["Broglie"] = "Broglie", - ["Bernay_Saint_Martin"] = "Bernay Saint Martin", - ["Saint_Andre_de_lEure"] = "Saint-Andre-de-lEure", - ["Biggin_Hill"] = "Biggin Hill", - ["Manston"] = "Manston", - ["Detling"] = "Detling", - ["Lympne"] = "Lympne", - ["Abbeville_Drucat"] = "Abbeville Drucat", - ["Merville_Calonne"] = "Merville Calonne", ["Saint_Omer_Wizernes"] = "Saint-Omer Wizernes", + ["Saint_Pierre_du_Mont"] = "Saint Pierre du Mont", + ["Sainte_Croix_sur_Mer"] = "Sainte-Croix-sur-Mer", + ["Sainte_Laurent_sur_Mer"] = "Sainte-Laurent-sur-Mer", + ["Sommervieu"] = "Sommervieu", + ["Stoney_Cross"] = "Stoney Cross", + ["Tangmere"] = "Tangmere", + ["Triqueville"] = "Triqueville", + ["Villacoublay"] = "Villacoublay", + ["Vrigny"] = "Vrigny", + ["West_Malling"] = "West Malling", } --- Airbases of the Persion Gulf Map: @@ -359,7 +363,7 @@ AIRBASE.Normandy = { -- * AIRBASE.PersianGulf.Sirri_Island -- * AIRBASE.PersianGulf.Tunb_Island_AFB -- * AIRBASE.PersianGulf.Tunb_Kochak --- +-- -- @field PersianGulf AIRBASE.PersianGulf = { ["Abu_Dhabi_International_Airport"] = "Abu Dhabi Intl", @@ -407,7 +411,7 @@ AIRBASE.PersianGulf = { -- * AIRBASE.TheChannel.Biggin_Hill -- * AIRBASE.TheChannel.Eastchurch -- * AIRBASE.TheChannel.Headcorn --- +-- -- @field TheChannel AIRBASE.TheChannel = { ["Abbeville_Drucat"] = "Abbeville Drucat", @@ -610,7 +614,7 @@ AIRBASE.MarianaIslands = { -- * AIRBASE.SouthAtlantic.Goose_Green -- * AIRBASE.SouthAtlantic.Hipico -- * AIRBASE.SouthAtlantic.CaletaTortel --- +-- --@field MarianaIslands AIRBASE.SouthAtlantic={ ["Port_Stanley"]="Port Stanley", @@ -674,7 +678,7 @@ AIRBASE.SouthAtlantic={ -- * AIRBASE.Sinai.Ben_Gurion -- * AIRBASE.Sinai.Bir_Hasanah -- * AIRBASE.Sinai.Cairo_West --- +-- -- @field Sinai AIRBASE.Sinai = { ["Hatzerim"] = "Hatzerim", @@ -812,13 +816,13 @@ function AIRBASE:Register(AirbaseName) -- Category. self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME - + -- H2 is bugged --if self.AirbaseName == "H4" and self.descriptors == nil then --self:E("***** H4 on Syria map is currently bugged!") --return nil --end - + -- Set category. if self.category==Airbase.Category.AIRDROME then self.isAirdrome=true @@ -836,10 +840,10 @@ function AIRBASE:Register(AirbaseName) else self:E("ERROR: Unknown airbase category!") end - + -- Init Runways. self:_InitRunways() - + -- Set the active runways based on wind direction. if self.isAirdrome then self:SetActiveRunway() @@ -853,7 +857,7 @@ function AIRBASE:Register(AirbaseName) -- Init coordinate. self:GetCoordinate() - + -- Storage. self.storage=_DATABASE:AddStorage(AirbaseName) @@ -869,7 +873,7 @@ function AIRBASE:Register(AirbaseName) else self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName)) end - + -- Debug info. self:T2(string.format("Registered airbase %s", tostring(self.AirbaseName))) @@ -955,7 +959,7 @@ function AIRBASE:GetWarehouse() return warehouse end ---- Get the warehouse storage of this airbase. The returned `STORAGE` object is the wrapper of the DCS warehouse. +--- Get the warehouse storage of this airbase. The returned `STORAGE` object is the wrapper of the DCS warehouse. -- This allows you to add and remove items such as aircraft, liquids, weapons and other equipment. -- @param #AIRBASE self -- @return Wrapper.Storage#STORAGE The storage. @@ -970,7 +974,7 @@ end function AIRBASE:SetAutoCapture(Switch) local airbase=self:GetDCSObject() - + if airbase then airbase:autoCapture(Switch) end @@ -996,11 +1000,11 @@ end --- Returns whether auto capturing of the airbase is on or off. -- @param #AIRBASE self --- @return #boolean Returns `true` if auto capturing is on, `false` if off and `nil` if the airbase object cannot be retrieved. +-- @return #boolean Returns `true` if auto capturing is on, `false` if off and `nil` if the airbase object cannot be retrieved. function AIRBASE:IsAutoCapture() local airbase=self:GetDCSObject() - + local auto=nil if airbase then auto=airbase:autoCaptureIsOn() @@ -1016,11 +1020,11 @@ end function AIRBASE:SetCoalition(Coal) local airbase=self:GetDCSObject() - + if airbase then airbase:setCoalition(Coal) end - + return self end @@ -1148,7 +1152,7 @@ function AIRBASE:SetParkingSpotBlacklist(TerminalIdBlacklist) return self end ---- Sets the ATC belonging to an airbase object to be silent and unresponsive. This is useful for disabling the award winning ATC behavior in DCS. +--- Sets the ATC belonging to an airbase object to be silent and unresponsive. This is useful for disabling the award winning ATC behavior in DCS. -- Note that this DOES NOT remove the airbase from the list. It just makes it unresponsive and silent to any radio calls to it. -- @param #AIRBASE self -- @param #boolean Silent If `true`, enable silent mode. If `false` or `nil`, disable silent mode. @@ -1157,12 +1161,12 @@ function AIRBASE:SetRadioSilentMode(Silent) -- Get DCS airbase object. local airbase=self:GetDCSObject() - + -- Set mode. if airbase then airbase:setRadioSilentMode(Silent) end - + return self end @@ -1170,18 +1174,18 @@ end -- @param #AIRBASE self -- @return #boolean If `true`, silent mode is enabled. function AIRBASE:GetRadioSilentMode() - + -- Is silent? local silent=nil -- Get DCS airbase object. local airbase=self:GetDCSObject() - + -- Set mode. if airbase then silent=airbase:getRadioSilentMode() end - + return silent end @@ -1365,7 +1369,7 @@ function AIRBASE:_InitParkingSpots() self.NparkingTerminal[terminalType]=0 end - -- Get client coordinates. + -- Get client coordinates. local function isClient(coord) local clients=_DATABASE.CLIENTS for clientname, _client in pairs(clients) do @@ -1854,7 +1858,7 @@ end -- @param #string Name Name of the runway, e.g. "31" or "21L". -- @return #AIRBASE.Runway Runway data. function AIRBASE:GetRunwayByName(Name) - + if Name==nil then return end @@ -1862,10 +1866,10 @@ function AIRBASE:GetRunwayByName(Name) if Name then for _,_runway in pairs(self.runways) do local runway=_runway --#AIRBASE.Runway - + -- Name including L or R, e.g. "31L". local name=self:GetRunwayName(runway) - + if name==Name:upper() then return runway end @@ -1894,19 +1898,19 @@ function AIRBASE:_InitRunways(IncludeInverse) self.runways={} return {} end - + --- Function to create a runway data table. local function _createRunway(name, course, width, length, center) -- Bearing in rad. local bearing=-1*course - + -- Heading in degrees. local heading=math.deg(bearing) - + -- Data table. local runway={} --#AIRBASE.Runway - + local namefromheading = math.floor(heading/10) if self.AirbaseName == AIRBASE.Syria.Beirut_Rafic_Hariri and math.abs(namefromheading-name) > 1 then @@ -1914,12 +1918,12 @@ function AIRBASE:_InitRunways(IncludeInverse) else runway.name=string.format("%02d", tonumber(name)) end - + --runway.name=string.format("%02d", tonumber(name)) runway.magheading=tonumber(runway.name)*10 runway.heading=heading runway.width=width or 0 - runway.length=length or 0 + runway.length=length or 0 runway.center=COORDINATE:NewFromVec3(center) -- Ensure heading is [0,360] @@ -1928,7 +1932,7 @@ function AIRBASE:_InitRunways(IncludeInverse) elseif runway.heading<0 then runway.heading=runway.heading+360 end - + -- For example at Nellis, DCS reports two runways, i.e. 03 and 21, BUT the "course" of both is -0.700 rad = 40 deg! -- As a workaround, I check the difference between the "magnetic" heading derived from the name and the true heading. -- If this is too large then very likely the "inverse" heading is the one we are looking for. @@ -1936,31 +1940,31 @@ function AIRBASE:_InitRunways(IncludeInverse) self:T(string.format("WARNING: Runway %s: heading=%.1f magheading=%.1f", runway.name, runway.heading, runway.magheading)) runway.heading=runway.heading-180 end - + -- Ensure heading is [0,360] if runway.heading>360 then runway.heading=runway.heading-360 elseif runway.heading<0 then runway.heading=runway.heading+360 end - + -- Start and endpoint of runway. runway.position=runway.center:Translate(-runway.length/2, runway.heading) runway.endpoint=runway.center:Translate( runway.length/2, runway.heading) - + local init=runway.center:GetVec3() local width = runway.width/2 local L2=runway.length/2 - + local offset1 = {x = init.x + (math.cos(bearing + math.pi) * L2), y = init.z + (math.sin(bearing + math.pi) * L2)} local offset2 = {x = init.x - (math.cos(bearing + math.pi) * L2), y = init.z - (math.sin(bearing + math.pi) * L2)} - + local points={} points[1] = {x = offset1.x + (math.cos(bearing + (math.pi/2)) * width), y = offset1.y + (math.sin(bearing + (math.pi/2)) * width)} points[2] = {x = offset1.x + (math.cos(bearing - (math.pi/2)) * width), y = offset1.y + (math.sin(bearing - (math.pi/2)) * width)} points[3] = {x = offset2.x + (math.cos(bearing - (math.pi/2)) * width), y = offset2.y + (math.sin(bearing - (math.pi/2)) * width)} points[4] = {x = offset2.x + (math.cos(bearing + (math.pi/2)) * width), y = offset2.y + (math.sin(bearing + (math.pi/2)) * width)} - + -- Runway zone. runway.zone=ZONE_POLYGON_BASE:New(string.format("%s Runway %s", self.AirbaseName, runway.name), points) @@ -1970,54 +1974,54 @@ function AIRBASE:_InitRunways(IncludeInverse) -- Get DCS object. local airbase=self:GetDCSObject() - + if airbase then - + -- Get DCS runways. local runways=airbase:getRunways() - + -- Debug info. self:T2(runways) - + if runways then - + -- Loop over runways. for _,rwy in pairs(runways) do - + -- Debug info. self:T(rwy) - + -- Get runway data. local runway=_createRunway(rwy.Name, rwy.course, rwy.width, rwy.length, rwy.position) --#AIRBASE.Runway - + -- Add to table. table.insert(Runways, runway) - + -- Include "inverse" runway. if IncludeInverse then - + -- Create "inverse". local idx=tonumber(runway.name) local name2=tostring(idx-18) if idx<18 then name2=tostring(idx+18) end - + -- Create "inverse" runway. local runway=_createRunway(name2, rwy.course-math.pi, rwy.width, rwy.length, rwy.position) --#AIRBASE.Runway - + -- Add inverse to table. table.insert(Runways, runway) - + end - + end - + end - + end - + -- Look for identical (parallel) runways, e.g. 03L and 03R at Nellis. local rpairs={} for i,_ri in pairs(Runways) do @@ -2031,44 +2035,44 @@ function AIRBASE:_InitRunways(IncludeInverse) end end end - + local function isLeft(a, b, c) --return ((b.x - a.x)*(c.z - a.z) - (b.z - a.z)*(c.x - a.x)) > 0 return ((b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z)) > 0 end - + for i,j in pairs(rpairs) do local ri=Runways[i] --#AIRBASE.Runway local rj=Runways[j] --#AIRBASE.Runway - + -- Draw arrow. --ri.center:ArrowToAll(rj.center) - + local c0=ri.center - + -- Vector in the direction of the runway. local a=UTILS.VecTranslate(c0, 1000, ri.heading) - + -- Vector from runway i to runway j. - local b=UTILS.VecSubstract(rj.center, ri.center) + local b=UTILS.VecSubstract(rj.center, ri.center) b=UTILS.VecAdd(ri.center, b) - + -- Check if rj is left of ri. local left=isLeft(c0, a, b) - + --env.info(string.format("Found pair %s: i=%d, j=%d, left==%s", ri.name, i, j, tostring(left))) - + if left then ri.isLeft=false rj.isLeft=true else ri.isLeft=true - rj.isLeft=false + rj.isLeft=false end - + --break end - + -- Set runways. self.runways=Runways @@ -2248,9 +2252,9 @@ end -- @param #string Name Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction. -- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right. function AIRBASE:SetActiveRunway(Name, PreferLeft) - + self:SetActiveRunwayTakeoff(Name, PreferLeft) - + self:SetActiveRunwayLanding(Name,PreferLeft) end @@ -2263,17 +2267,17 @@ end function AIRBASE:SetActiveRunwayLanding(Name, PreferLeft) local runway=self:GetRunwayByName(Name) - + if not runway then runway=self:GetRunwayIntoWind(PreferLeft) end - + if runway then self:T(string.format("%s: Setting active runway for landing as %s", self.AirbaseName, self:GetRunwayName(runway))) else self:E("ERROR: Could not set the runway for landing!") end - + self.runwayLanding=runway return runway @@ -2311,17 +2315,17 @@ end function AIRBASE:SetActiveRunwayTakeoff(Name, PreferLeft) local runway=self:GetRunwayByName(Name) - + if not runway then runway=self:GetRunwayIntoWind(PreferLeft) end - + if runway then self:T(string.format("%s: Setting active runway for takeoff as %s", self.AirbaseName, self:GetRunwayName(runway))) else self:E("ERROR: Could not set the runway for takeoff!") end - + self.runwayTakeoff=runway return runway @@ -2334,7 +2338,7 @@ end -- @param #boolean PreferLeft If `true`, perfer the left runway. If `false`, prefer the right runway. If `nil` (default), do not care about left or right. -- @return #AIRBASE.Runway Active runway data table. function AIRBASE:GetRunwayIntoWind(PreferLeft) - + -- Get runway data. local runways=self:GetRunways() @@ -2357,24 +2361,24 @@ function AIRBASE:GetRunwayIntoWind(PreferLeft) local dotmin=nil for i,_runway in pairs(runways) do local runway=_runway --#AIRBASE.Runway - + if PreferLeft==nil or PreferLeft==runway.isLeft then -- Angle in rad. local alpha=math.rad(runway.heading) - + -- Runway vector. local Vrunway={x=math.cos(alpha), y=0, z=math.sin(alpha)} - + -- Dot product: parallel component of the two vectors. local dot=UTILS.VecDot(Vwind, Vrunway) - + -- New min? if dotmin==nil or dot Date: Thu, 29 Feb 2024 09:54:12 +0100 Subject: [PATCH 39/73] #SCORING Additions for SETs --- .../Moose/Functional/Scoring.lua | 44 +++++++++++++++---- Moose Development/Moose/Wrapper/Unit.lua | 2 + 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index b8c7218cf..625103d9e 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -78,7 +78,8 @@ -- ### Authors: **FlightControl** -- -- ### Contributions: --- +-- +-- * **Applevangelist**: Additional functionality, fixes. -- * **Wingthor (TAW)**: Testing & Advice. -- * **Dutch-Baron (TAW)**: Testing & Advice. -- * **Whisper**: Testing and Advice. @@ -116,11 +117,13 @@ -- Special targets can be set that will give extra scores to the players when these are destroyed. -- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Wrapper.Unit}s. -- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Wrapper.Static}s. --- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Wrapper.Group}s. +-- Use the method @{#SCORING.AddScoreSetGroup}() to specify a special additional score for a specific @{Wrapper.Group}s gathered in a @{Core.Set#SET_GROUP}. -- -- local Scoring = SCORING:New( "Scoring File" ) -- Scoring:AddUnitScore( UNIT:FindByName( "Unit #001" ), 200 ) -- Scoring:AddStaticScore( STATIC:FindByName( "Static #1" ), 100 ) +-- local GroupSet = SET_GROUP:New():FilterPrefixes("RAT"):FilterStart() +-- Scoring:AddScoreSetGroup( GroupSet, 100) -- -- The above grants an additional score of 200 points for Unit #001 and an additional 100 points of Static #1 if these are destroyed. -- Note that later in the mission, one can remove these scores set, for example, when the a goal achievement time limit is over. @@ -226,7 +229,7 @@ SCORING = { ClassID = 0, Players = {}, AutoSave = true, - version = "1.17.1" + version = "1.18.1" } local _SCORINGCoalition = { @@ -428,6 +431,31 @@ function SCORING:AddScoreGroup( ScoreGroup, Score ) return self end +--- Specify a special additional score for a @{Core.Set#SET_GROUP}. +-- @param #SCORING self +-- @param Core.Set#SET_GROUP Set The @{Core.Set#SET_GROUP} for which each @{Wrapper.Unit} in each Group a Score is given. +-- @param #number Score The Score value. +-- @return #SCORING +function SCORING:AddScoreSetGroup(Set, Score) + local set = Set:GetSetObjects() + + for _,_group in pairs (set) do + if _group and _group:IsAlive() then + self:AddScoreGroup(_group,Score) + end + end + + local function AddScore(group) + self:AddScoreGroup(group,Score) + end + + function Set:OnAfterAdded(From,Event,To,ObjectName,Object) + AddScore(Object) + end + + return self +end + --- Add a @{Core.Zone} to define additional scoring when any object is destroyed in that zone. -- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced! -- This allows for a dynamic destruction zone evolution within your mission. @@ -1935,9 +1963,9 @@ end --- Handles the event when one player kill another player -- @param #SCORING self --- @param #PLAYER Player the ataching player +-- @param #Wrapper.Client#CLIENT Player the atacking player -- @param #string TargetPlayerName the name of the killed player --- @param #bool IsTeamKill true if this kill was a team kill +-- @param #boolean IsTeamKill true if this kill was a team kill -- @param #number TargetThreatLevel Thread level of the target -- @param #number PlayerThreatLevelThread level of the player -- @param #number Score The score based on both threat levels @@ -1946,12 +1974,12 @@ function SCORING:OnKillPvP(Player, TargetPlayerName, IsTeamKill, TargetThreatLev end --- Handles the event when one player kill another player -- @param #SCORING self --- @param #PLAYER Player the ataching player +-- @param #Wrapper.Client#CLIENT Player the atacking player -- @param #string TargetUnitName the name of the killed unit --- @param #bool IsTeamKill true if this kill was a team kill +-- @param #boolean IsTeamKill true if this kill was a team kill -- @param #number TargetThreatLevel Thread level of the target -- @param #number PlayerThreatLevelThread level of the player -- @param #number Score The score based on both threat levels function SCORING:OnKillPvE(Player, TargetUnitName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score) -end \ No newline at end of file +end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 322d23540..781c71d48 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -1244,7 +1244,9 @@ function UNIT:GetThreatLevel() if Attributes["Fighters"] then ThreatLevel = 10 elseif Attributes["Multirole fighters"] then ThreatLevel = 9 + elseif Attributes["Interceptors"] then ThreatLevel = 9 elseif Attributes["Battleplanes"] then ThreatLevel = 8 + elseif Attributes["Battle airplanes"] then ThreatLevel = 8 elseif Attributes["Attack helicopters"] then ThreatLevel = 7 elseif Attributes["Strategic bombers"] then ThreatLevel = 6 elseif Attributes["Bombers"] then ThreatLevel = 5 From 219353faad28708e5c2d2291a7be1237fd94ac7c Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 29 Feb 2024 10:32:35 +0100 Subject: [PATCH 40/73] Update of all Airbases (uptodate and sorted) --- Moose Development/Moose/Wrapper/Airbase.lua | 693 ++++++++++---------- 1 file changed, 350 insertions(+), 343 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index ae2d9db16..be41aa6c5 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -79,92 +79,92 @@ AIRBASE = { -- -- Airbases of the Caucasus map: -- --- * AIRBASE.Caucasus.Gelendzhik --- * AIRBASE.Caucasus.Krasnodar_Pashkovsky --- * AIRBASE.Caucasus.Sukhumi_Babushara --- * AIRBASE.Caucasus.Gudauta --- * AIRBASE.Caucasus.Batumi --- * AIRBASE.Caucasus.Senaki_Kolkhi --- * AIRBASE.Caucasus.Kobuleti --- * AIRBASE.Caucasus.Kutaisi --- * AIRBASE.Caucasus.Tbilisi_Lochini --- * AIRBASE.Caucasus.Soganlug --- * AIRBASE.Caucasus.Vaziani --- * AIRBASE.Caucasus.Anapa_Vityazevo --- * AIRBASE.Caucasus.Krasnodar_Center --- * AIRBASE.Caucasus.Novorossiysk --- * AIRBASE.Caucasus.Krymsk --- * AIRBASE.Caucasus.Maykop_Khanskaya --- * AIRBASE.Caucasus.Sochi_Adler --- * AIRBASE.Caucasus.Mineralnye_Vody --- * AIRBASE.Caucasus.Nalchik --- * AIRBASE.Caucasus.Mozdok --- * AIRBASE.Caucasus.Beslan +-- * AIRBASE.Caucasus.Anapa_Vityazevo +-- * AIRBASE.Caucasus.Batumi +-- * AIRBASE.Caucasus.Beslan +-- * AIRBASE.Caucasus.Gelendzhik +-- * AIRBASE.Caucasus.Gudauta +-- * AIRBASE.Caucasus.Kobuleti +-- * AIRBASE.Caucasus.Krasnodar_Center +-- * AIRBASE.Caucasus.Krasnodar_Pashkovsky +-- * AIRBASE.Caucasus.Krymsk +-- * AIRBASE.Caucasus.Kutaisi +-- * AIRBASE.Caucasus.Maykop_Khanskaya +-- * AIRBASE.Caucasus.Mineralnye_Vody +-- * AIRBASE.Caucasus.Mozdok +-- * AIRBASE.Caucasus.Nalchik +-- * AIRBASE.Caucasus.Novorossiysk +-- * AIRBASE.Caucasus.Senaki_Kolkhi +-- * AIRBASE.Caucasus.Sochi_Adler +-- * AIRBASE.Caucasus.Soganlug +-- * AIRBASE.Caucasus.Sukhumi_Babushara +-- * AIRBASE.Caucasus.Tbilisi_Lochini +-- * AIRBASE.Caucasus.Vaziani -- -- @field Caucasus AIRBASE.Caucasus = { - ["Gelendzhik"] = "Gelendzhik", - ["Krasnodar_Pashkovsky"] = "Krasnodar-Pashkovsky", - ["Sukhumi_Babushara"] = "Sukhumi-Babushara", - ["Gudauta"] = "Gudauta", - ["Batumi"] = "Batumi", - ["Senaki_Kolkhi"] = "Senaki-Kolkhi", - ["Kobuleti"] = "Kobuleti", - ["Kutaisi"] = "Kutaisi", - ["Tbilisi_Lochini"] = "Tbilisi-Lochini", - ["Soganlug"] = "Soganlug", - ["Vaziani"] = "Vaziani", ["Anapa_Vityazevo"] = "Anapa-Vityazevo", - ["Krasnodar_Center"] = "Krasnodar-Center", - ["Novorossiysk"] = "Novorossiysk", - ["Krymsk"] = "Krymsk", - ["Maykop_Khanskaya"] = "Maykop-Khanskaya", - ["Sochi_Adler"] = "Sochi-Adler", - ["Mineralnye_Vody"] = "Mineralnye Vody", - ["Nalchik"] = "Nalchik", - ["Mozdok"] = "Mozdok", + ["Batumi"] = "Batumi", ["Beslan"] = "Beslan", + ["Gelendzhik"] = "Gelendzhik", + ["Gudauta"] = "Gudauta", + ["Kobuleti"] = "Kobuleti", + ["Krasnodar_Center"] = "Krasnodar-Center", + ["Krasnodar_Pashkovsky"] = "Krasnodar-Pashkovsky", + ["Krymsk"] = "Krymsk", + ["Kutaisi"] = "Kutaisi", + ["Maykop_Khanskaya"] = "Maykop-Khanskaya", + ["Mineralnye_Vody"] = "Mineralnye Vody", + ["Mozdok"] = "Mozdok", + ["Nalchik"] = "Nalchik", + ["Novorossiysk"] = "Novorossiysk", + ["Senaki_Kolkhi"] = "Senaki-Kolkhi", + ["Sochi_Adler"] = "Sochi-Adler", + ["Soganlug"] = "Soganlug", + ["Sukhumi_Babushara"] = "Sukhumi-Babushara", + ["Tbilisi_Lochini"] = "Tbilisi-Lochini", + ["Vaziani"] = "Vaziani", } --- Airbases of the Nevada map: -- --- * AIRBASE.Nevada.Creech_AFB --- * AIRBASE.Nevada.Groom_Lake_AFB --- * AIRBASE.Nevada.McCarran_International_Airport --- * AIRBASE.Nevada.Nellis_AFB --- * AIRBASE.Nevada.Beatty_Airport --- * AIRBASE.Nevada.Boulder_City_Airport --- * AIRBASE.Nevada.Echo_Bay --- * AIRBASE.Nevada.Henderson_Executive_Airport --- * AIRBASE.Nevada.Jean_Airport --- * AIRBASE.Nevada.Laughlin_Airport --- * AIRBASE.Nevada.Lincoln_County --- * AIRBASE.Nevada.Mesquite --- * AIRBASE.Nevada.Mina_Airport --- * AIRBASE.Nevada.North_Las_Vegas --- * AIRBASE.Nevada.Pahute_Mesa_Airstrip --- * AIRBASE.Nevada.Tonopah_Airport --- * AIRBASE.Nevada.Tonopah_Test_Range_Airfield +-- * AIRBASE.Nevada.Beatty +-- * AIRBASE.Nevada.Boulder_City +-- * AIRBASE.Nevada.Creech +-- * AIRBASE.Nevada.Echo_Bay +-- * AIRBASE.Nevada.Groom_Lake +-- * AIRBASE.Nevada.Henderson_Executive +-- * AIRBASE.Nevada.Jean +-- * AIRBASE.Nevada.Laughlin +-- * AIRBASE.Nevada.Lincoln_County +-- * AIRBASE.Nevada.McCarran_International +-- * AIRBASE.Nevada.Mesquite +-- * AIRBASE.Nevada.Mina +-- * AIRBASE.Nevada.Nellis +-- * AIRBASE.Nevada.North_Las_Vegas +-- * AIRBASE.Nevada.Pahute_Mesa +-- * AIRBASE.Nevada.Tonopah +-- * AIRBASE.Nevada.Tonopah_Test_Range -- -- @field Nevada AIRBASE.Nevada = { - ["Creech_AFB"] = "Creech", - ["Groom_Lake_AFB"] = "Groom Lake", - ["McCarran_International_Airport"] = "McCarran International", - ["Nellis_AFB"] = "Nellis", - ["Beatty_Airport"] = "Beatty", - ["Boulder_City_Airport"] = "Boulder City", + ["Beatty"] = "Beatty", + ["Boulder_City"] = "Boulder City", + ["Creech"] = "Creech", ["Echo_Bay"] = "Echo Bay", - ["Henderson_Executive_Airport"] = "Henderson Executive", - ["Jean_Airport"] = "Jean", - ["Laughlin_Airport"] = "Laughlin", + ["Groom_Lake"] = "Groom Lake", + ["Henderson_Executive"] = "Henderson Executive", + ["Jean"] = "Jean", + ["Laughlin"] = "Laughlin", ["Lincoln_County"] = "Lincoln County", + ["McCarran_International"] = "McCarran International", ["Mesquite"] = "Mesquite", - ["Mina_Airport"] = "Mina", + ["Mina"] = "Mina", + ["Nellis"] = "Nellis", ["North_Las_Vegas"] = "North Las Vegas", - ["Pahute_Mesa_Airstrip"] = "Pahute Mesa", - ["Tonopah_Airport"] = "Tonopah", - ["Tonopah_Test_Range_Airfield"] = "Tonopah Test Range", + ["Pahute_Mesa"] = "Pahute Mesa", + ["Tonopah"] = "Tonopah", + ["Tonopah_Test_Range"] = "Tonopah Test Range", } --- Airbases of the Normandy map: @@ -334,31 +334,32 @@ AIRBASE.Normandy = { --- Airbases of the Persion Gulf Map: -- --- * AIRBASE.PersianGulf.Abu_Dhabi_International_Airport --- * AIRBASE.PersianGulf.Abu_Musa_Island_Airport --- * AIRBASE.PersianGulf.Al_Bateen_Airport --- * AIRBASE.PersianGulf.Al_Ain_International_Airport --- * AIRBASE.PersianGulf.Al_Dhafra_AB +-- * AIRBASE.PersianGulf.Abu_Dhabi_Intl +-- * AIRBASE.PersianGulf.Abu_Musa_Island +-- * AIRBASE.PersianGulf.Al_Ain_Intl +-- * AIRBASE.PersianGulf.Al_Bateen +-- * AIRBASE.PersianGulf.Al_Dhafra_AFB -- * AIRBASE.PersianGulf.Al_Maktoum_Intl --- * AIRBASE.PersianGulf.Al_Minhad_AB --- * AIRBASE.PersianGulf.Bandar_e_Jask_airfield +-- * AIRBASE.PersianGulf.Al_Minhad_AFB -- * AIRBASE.PersianGulf.Bandar_Abbas_Intl -- * AIRBASE.PersianGulf.Bandar_Lengeh +-- * AIRBASE.PersianGulf.Bandar_e_Jask -- * AIRBASE.PersianGulf.Dubai_Intl -- * AIRBASE.PersianGulf.Fujairah_Intl -- * AIRBASE.PersianGulf.Havadarya --- * AIRBASE.PersianGulf.Jiroft_Airport --- * AIRBASE.PersianGulf.Kerman_Airport +-- * AIRBASE.PersianGulf.Jiroft +-- * AIRBASE.PersianGulf.Kerman -- * AIRBASE.PersianGulf.Khasab --- * AIRBASE.PersianGulf.Kish_International_Airport --- * AIRBASE.PersianGulf.Lar_Airbase --- * AIRBASE.PersianGulf.Lavan_Island_Airport --- * AIRBASE.PersianGulf.Liwa_Airbase +-- * AIRBASE.PersianGulf.Kish_Intl +-- * AIRBASE.PersianGulf.Lar +-- * AIRBASE.PersianGulf.Lavan_Island +-- * AIRBASE.PersianGulf.Liwa_AFB -- * AIRBASE.PersianGulf.Qeshm_Island --- * AIRBASE.PersianGulf.Ras_Al_Khaimah --- * AIRBASE.PersianGulf.Sas_Al_Nakheel_Airport +-- * AIRBASE.PersianGulf.Quasoura_airport +-- * AIRBASE.PersianGulf.Ras_Al_Khaimah_Intl +-- * AIRBASE.PersianGulf.Sas_Al_Nakheel -- * AIRBASE.PersianGulf.Sharjah_Intl --- * AIRBASE.PersianGulf.Shiraz_International_Airport +-- * AIRBASE.PersianGulf.Shiraz_Intl -- * AIRBASE.PersianGulf.Sir_Abu_Nuayr -- * AIRBASE.PersianGulf.Sirri_Island -- * AIRBASE.PersianGulf.Tunb_Island_AFB @@ -366,31 +367,32 @@ AIRBASE.Normandy = { -- -- @field PersianGulf AIRBASE.PersianGulf = { - ["Abu_Dhabi_International_Airport"] = "Abu Dhabi Intl", - ["Abu_Musa_Island_Airport"] = "Abu Musa Island", - ["Al_Ain_International_Airport"] = "Al Ain Intl", - ["Al_Bateen_Airport"] = "Al-Bateen", - ["Al_Dhafra_AB"] = "Al Dhafra AFB", + ["Abu_Dhabi_Intl"] = "Abu Dhabi Intl", + ["Abu_Musa_Island"] = "Abu Musa Island", + ["Al_Ain_Intl"] = "Al Ain Intl", + ["Al_Bateen"] = "Al-Bateen", + ["Al_Dhafra_AFB"] = "Al Dhafra AFB", ["Al_Maktoum_Intl"] = "Al Maktoum Intl", - ["Al_Minhad_AB"] = "Al Minhad AFB", + ["Al_Minhad_AFB"] = "Al Minhad AFB", ["Bandar_Abbas_Intl"] = "Bandar Abbas Intl", ["Bandar_Lengeh"] = "Bandar Lengeh", - ["Bandar_e_Jask_airfield"] = "Bandar-e-Jask", + ["Bandar_e_Jask"] = "Bandar-e-Jask", ["Dubai_Intl"] = "Dubai Intl", ["Fujairah_Intl"] = "Fujairah Intl", ["Havadarya"] = "Havadarya", - ["Jiroft_Airport"] = "Jiroft", - ["Kerman_Airport"] = "Kerman", + ["Jiroft"] = "Jiroft", + ["Kerman"] = "Kerman", ["Khasab"] = "Khasab", - ["Kish_International_Airport"] = "Kish Intl", - ["Lar_Airbase"] = "Lar", - ["Lavan_Island_Airport"] = "Lavan Island", - ["Liwa_Airbase"] = "Liwa AFB", + ["Kish_Intl"] = "Kish Intl", + ["Lar"] = "Lar", + ["Lavan_Island"] = "Lavan Island", + ["Liwa_AFB"] = "Liwa AFB", ["Qeshm_Island"] = "Qeshm Island", - ["Ras_Al_Khaimah"] = "Ras Al Khaimah Intl", - ["Sas_Al_Nakheel_Airport"] = "Sas Al Nakheel", + ["Quasoura_airport"] = "Quasoura_airport", + ["Ras_Al_Khaimah_Intl"] = "Ras Al Khaimah Intl", + ["Sas_Al_Nakheel"] = "Sas Al Nakheel", ["Sharjah_Intl"] = "Sharjah Intl", - ["Shiraz_International_Airport"] = "Shiraz Intl", + ["Shiraz_Intl"] = "Shiraz Intl", ["Sir_Abu_Nuayr"] = "Sir Abu Nuayr", ["Sirri_Island"] = "Sirri Island", ["Tunb_Island_AFB"] = "Tunb Island AFB", @@ -400,317 +402,322 @@ AIRBASE.PersianGulf = { --- Airbases of The Channel Map: -- -- * AIRBASE.TheChannel.Abbeville_Drucat +-- * AIRBASE.TheChannel.Biggin_Hill +-- * AIRBASE.TheChannel.Detling +-- * AIRBASE.TheChannel.Dunkirk_Mardyck +-- * AIRBASE.TheChannel.Eastchurch +-- * AIRBASE.TheChannel.Hawkinge +-- * AIRBASE.TheChannel.Headcorn +-- * AIRBASE.TheChannel.High_Halden +-- * AIRBASE.TheChannel.Lympne +-- * AIRBASE.TheChannel.Manston -- * AIRBASE.TheChannel.Merville_Calonne -- * AIRBASE.TheChannel.Saint_Omer_Longuenesse --- * AIRBASE.TheChannel.Dunkirk_Mardyck --- * AIRBASE.TheChannel.Manston --- * AIRBASE.TheChannel.Hawkinge --- * AIRBASE.TheChannel.Lympne --- * AIRBASE.TheChannel.Detling --- * AIRBASE.TheChannel.High_Halden --- * AIRBASE.TheChannel.Biggin_Hill --- * AIRBASE.TheChannel.Eastchurch --- * AIRBASE.TheChannel.Headcorn -- -- @field TheChannel AIRBASE.TheChannel = { ["Abbeville_Drucat"] = "Abbeville Drucat", + ["Biggin_Hill"] = "Biggin Hill", + ["Detling"] = "Detling", + ["Dunkirk_Mardyck"] = "Dunkirk Mardyck", + ["Eastchurch"] = "Eastchurch", + ["Hawkinge"] = "Hawkinge", + ["Headcorn"] = "Headcorn", + ["High_Halden"] = "High Halden", + ["Lympne"] = "Lympne", + ["Manston"] = "Manston", ["Merville_Calonne"] = "Merville Calonne", ["Saint_Omer_Longuenesse"] = "Saint Omer Longuenesse", - ["Dunkirk_Mardyck"] = "Dunkirk Mardyck", - ["Manston"] = "Manston", - ["Hawkinge"] = "Hawkinge", - ["Lympne"] = "Lympne", - ["Detling"] = "Detling", - ["High_Halden"] = "High Halden", - ["Biggin_Hill"] = "Biggin Hill", - ["Eastchurch"] = "Eastchurch", - ["Headcorn"] = "Headcorn", } --- Airbases of the Syria map: -- --- * AIRBASE.Syria.Kuweires --- * AIRBASE.Syria.Incirlik --- * AIRBASE.Syria.King_Abdullah_II --- * AIRBASE.Syria.Akrotiri --- * AIRBASE.Syria.Aleppo -- * AIRBASE.Syria.Abu_al_Duhur --- * AIRBASE.Syria.Hatay --- * AIRBASE.Syria.Paphos +-- * AIRBASE.Syria.Adana_Sakirpasa +-- * AIRBASE.Syria.Akrotiri +-- * AIRBASE.Syria.Al_Dumayr +-- * AIRBASE.Syria.Al_Qusayr +-- * AIRBASE.Syria.Aleppo +-- * AIRBASE.Syria.Amman +-- * AIRBASE.Syria.An_Nasiriyah -- * AIRBASE.Syria.At_Tanf --- * AIRBASE.Syria.Tal_Siman --- * AIRBASE.Syria.Rayak +-- * AIRBASE.Syria.Bassel_Al_Assad +-- * AIRBASE.Syria.Beirut_Rafic_Hariri +-- * AIRBASE.Syria.Damascus +-- * AIRBASE.Syria.Deir_ez_Zor +-- * AIRBASE.Syria.Ercan +-- * AIRBASE.Syria.Eyn_Shemer +-- * AIRBASE.Syria.Gaziantep +-- * AIRBASE.Syria.Gazipasa +-- * AIRBASE.Syria.Gecitkale +-- * AIRBASE.Syria.H3 +-- * AIRBASE.Syria.H3_Northwest +-- * AIRBASE.Syria.H3_Southwest +-- * AIRBASE.Syria.H4 +-- * AIRBASE.Syria.Haifa +-- * AIRBASE.Syria.Hama +-- * AIRBASE.Syria.Hatay +-- * AIRBASE.Syria.Herzliya +-- * AIRBASE.Syria.Incirlik +-- * AIRBASE.Syria.Jirah +-- * AIRBASE.Syria.Khalkhalah +-- * AIRBASE.Syria.Kharab_Ishk +-- * AIRBASE.Syria.King_Abdullah_II +-- * AIRBASE.Syria.King_Hussein_Air_College +-- * AIRBASE.Syria.Kingsfield +-- * AIRBASE.Syria.Kiryat_Shmona +-- * AIRBASE.Syria.Kuweires +-- * AIRBASE.Syria.Lakatamia +-- * AIRBASE.Syria.Larnaca +-- * AIRBASE.Syria.Marj_Ruhayyil +-- * AIRBASE.Syria.Marj_as_Sultan_North +-- * AIRBASE.Syria.Marj_as_Sultan_South +-- * AIRBASE.Syria.Megiddo +-- * AIRBASE.Syria.Mezzeh +-- * AIRBASE.Syria.Minakh -- * AIRBASE.Syria.Muwaffaq_Salti -- * AIRBASE.Syria.Naqoura --- * AIRBASE.Syria.Gaziantep --- * AIRBASE.Syria.Al_Qusayr --- * AIRBASE.Syria.Al_Dumayr --- * AIRBASE.Syria.Kingsfield --- * AIRBASE.Syria.Marj_as_Sultan_North --- * AIRBASE.Syria.Beirut_Rafic_Hariri --- * AIRBASE.Syria.Palmyra --- * AIRBASE.Syria.Hama --- * AIRBASE.Syria.Eyn_Shemer --- * AIRBASE.Syria.Sanliurfa --- * AIRBASE.Syria.Amman --- * AIRBASE.Syria.Deir_ez_Zor --- * AIRBASE.Syria.Taftanaz --- * AIRBASE.Syria.Damascus --- * AIRBASE.Syria.Gazipasa --- * AIRBASE.Syria.Herzliya --- * AIRBASE.Syria.H4 --- * AIRBASE.Syria.Tiyas --- * AIRBASE.Syria.Lakatamia --- * AIRBASE.Syria.Kharab_Ishk --- * AIRBASE.Syria.Haifa --- * AIRBASE.Syria.Khalkhalah --- * AIRBASE.Syria.Megiddo --- * AIRBASE.Syria.An_Nasiriyah --- * AIRBASE.Syria.Bassel_Al_Assad --- * AIRBASE.Syria.Ruwayshid --- * AIRBASE.Syria.Mezzeh --- * AIRBASE.Syria.Gecitkale -- * AIRBASE.Syria.Nicosia --- * AIRBASE.Syria.Ramat_David --- * AIRBASE.Syria.Tha_lah --- * AIRBASE.Syria.H3_Northwest --- * AIRBASE.Syria.Sayqal --- * AIRBASE.Syria.Jirah --- * AIRBASE.Syria.Shayrat --- * AIRBASE.Syria.Adana_Sakirpasa --- * AIRBASE.Syria.Wujah_Al_Hajar +-- * AIRBASE.Syria.Palmyra +-- * AIRBASE.Syria.Paphos -- * AIRBASE.Syria.Pinarbashi --- * AIRBASE.Syria.H3_Southwest --- * AIRBASE.Syria.Rosh_Pina --- * AIRBASE.Syria.Kiryat_Shmona --- * AIRBASE.Syria.H3 --- * AIRBASE.Syria.Qabr_as_Sitt -- * AIRBASE.Syria.Prince_Hassan --- * AIRBASE.Syria.Larnaca --- * AIRBASE.Syria.King_Hussein_Air_College --- * AIRBASE.Syria.Ercan --- * AIRBASE.Syria.Marj_Ruhayyil --- * AIRBASE.Syria.Tabqa --- * AIRBASE.Syria.Marj_as_Sultan_South +-- * AIRBASE.Syria.Qabr_as_Sitt +-- * AIRBASE.Syria.Ramat_David +-- * AIRBASE.Syria.Rayak -- * AIRBASE.Syria.Rene_Mouawad --- * AIRBASE.Syria.Minakh +-- * AIRBASE.Syria.Rosh_Pina +-- * AIRBASE.Syria.Ruwayshid +-- * AIRBASE.Syria.Sanliurfa +-- * AIRBASE.Syria.Sayqal +-- * AIRBASE.Syria.Shayrat +-- * AIRBASE.Syria.Tabqa +-- * AIRBASE.Syria.Taftanaz +-- * AIRBASE.Syria.Tal_Siman +-- * AIRBASE.Syria.Tha_lah +-- * AIRBASE.Syria.Tiyas +-- * AIRBASE.Syria.Wujah_Al_Hajar -- --@field Syria AIRBASE.Syria={ - ["Kuweires"] = "Kuweires", - ["Incirlik"] = "Incirlik", - ["King_Abdullah_II"] = "King Abdullah II", - ["Akrotiri"] = "Akrotiri", - ["Aleppo"] = "Aleppo", ["Abu_al_Duhur"] = "Abu al-Duhur", - ["Hatay"] = "Hatay", - ["Paphos"] = "Paphos", + ["Adana_Sakirpasa"] = "Adana Sakirpasa", + ["Akrotiri"] = "Akrotiri", + ["Al_Dumayr"] = "Al-Dumayr", + ["Al_Qusayr"] = "Al Qusayr", + ["Aleppo"] = "Aleppo", + ["Amman"] = "Amman", + ["An_Nasiriyah"] = "An Nasiriyah", ["At_Tanf"] = "At Tanf", - ["Tal_Siman"] = "Tal Siman", - ["Rayak"] = "Rayak", + ["Bassel_Al_Assad"] = "Bassel Al-Assad", + ["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri", + ["Damascus"] = "Damascus", + ["Deir_ez_Zor"] = "Deir ez-Zor", + ["Ercan"] = "Ercan", + ["Eyn_Shemer"] = "Eyn Shemer", + ["Gaziantep"] = "Gaziantep", + ["Gazipasa"] = "Gazipasa", + ["Gecitkale"] = "Gecitkale", + ["H3"] = "H3", + ["H3_Northwest"] = "H3 Northwest", + ["H3_Southwest"] = "H3 Southwest", + ["H4"] = "H4", + ["Haifa"] = "Haifa", + ["Hama"] = "Hama", + ["Hatay"] = "Hatay", + ["Herzliya"] = "Herzliya", + ["Incirlik"] = "Incirlik", + ["Jirah"] = "Jirah", + ["Khalkhalah"] = "Khalkhalah", + ["Kharab_Ishk"] = "Kharab Ishk", + ["King_Abdullah_II"] = "King Abdullah II", + ["King_Hussein_Air_College"] = "King Hussein Air College", + ["Kingsfield"] = "Kingsfield", + ["Kiryat_Shmona"] = "Kiryat Shmona", + ["Kuweires"] = "Kuweires", + ["Lakatamia"] = "Lakatamia", + ["Larnaca"] = "Larnaca", + ["Marj_Ruhayyil"] = "Marj Ruhayyil", + ["Marj_as_Sultan_North"] = "Marj as Sultan North", + ["Marj_as_Sultan_South"] = "Marj as Sultan South", + ["Megiddo"] = "Megiddo", + ["Mezzeh"] = "Mezzeh", + ["Minakh"] = "Minakh", ["Muwaffaq_Salti"] = "Muwaffaq Salti", ["Naqoura"] = "Naqoura", - ["Gaziantep"] = "Gaziantep", - ["Al_Qusayr"] = "Al Qusayr", - ["Al_Dumayr"] = "Al-Dumayr", - ["Kingsfield"] = "Kingsfield", - ["Marj_as_Sultan_North"] = "Marj as Sultan North", - ["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri", - ["Palmyra"] = "Palmyra", - ["Hama"] = "Hama", - ["Eyn_Shemer"] = "Eyn Shemer", - ["Sanliurfa"] = "Sanliurfa", - ["Amman"] = "Amman", - ["Deir_ez_Zor"] = "Deir ez-Zor", - ["Taftanaz"] = "Taftanaz", - ["Damascus"] = "Damascus", - ["Gazipasa"] = "Gazipasa", - ["Herzliya"] = "Herzliya", - ["H4"] = "H4", - ["Tiyas"] = "Tiyas", - ["Lakatamia"] = "Lakatamia", - ["Kharab_Ishk"] = "Kharab Ishk", - ["Haifa"] = "Haifa", - ["Khalkhalah"] = "Khalkhalah", - ["Megiddo"] = "Megiddo", - ["An_Nasiriyah"] = "An Nasiriyah", - ["Bassel_Al_Assad"] = "Bassel Al-Assad", - ["Ruwayshid"] = "Ruwayshid", - ["Mezzeh"] = "Mezzeh", - ["Gecitkale"] = "Gecitkale", ["Nicosia"] = "Nicosia", - ["Ramat_David"] = "Ramat David", - ["Tha_lah"] = "Tha'lah", - ["H3_Northwest"] = "H3 Northwest", - ["Sayqal"] = "Sayqal", - ["Jirah"] = "Jirah", - ["Shayrat"] = "Shayrat", - ["Adana_Sakirpasa"] = "Adana Sakirpasa", - ["Wujah_Al_Hajar"] = "Wujah Al Hajar", + ["Palmyra"] = "Palmyra", + ["Paphos"] = "Paphos", ["Pinarbashi"] = "Pinarbashi", - ["H3_Southwest"] = "H3 Southwest", - ["Rosh_Pina"] = "Rosh Pina", - ["Kiryat_Shmona"] = "Kiryat Shmona", - ["H3"] = "H3", - ["Qabr_as_Sitt"] = "Qabr as Sitt", ["Prince_Hassan"] = "Prince Hassan", - ["Larnaca"] = "Larnaca", - ["King_Hussein_Air_College"] = "King Hussein Air College", - ["Ercan"] = "Ercan", - ["Marj_Ruhayyil"] = "Marj Ruhayyil", - ["Tabqa"] = "Tabqa", - ["Marj_as_Sultan_South"] = "Marj as Sultan South", + ["Qabr_as_Sitt"] = "Qabr as Sitt", + ["Ramat_David"] = "Ramat David", + ["Rayak"] = "Rayak", ["Rene_Mouawad"] = "Rene Mouawad", - ["Minakh"] = "Minakh", + ["Rosh_Pina"] = "Rosh Pina", + ["Ruwayshid"] = "Ruwayshid", + ["Sanliurfa"] = "Sanliurfa", + ["Sayqal"] = "Sayqal", + ["Shayrat"] = "Shayrat", + ["Tabqa"] = "Tabqa", + ["Taftanaz"] = "Taftanaz", + ["Tal_Siman"] = "Tal Siman", + ["Tha_lah"] = "Tha'lah", + ["Tiyas"] = "Tiyas", + ["Wujah_Al_Hajar"] = "Wujah Al Hajar", } --- Airbases of the Mariana Islands map: -- --- * AIRBASE.MarianaIslands.Rota_Intl -- * AIRBASE.MarianaIslands.Andersen_AFB -- * AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl --- * AIRBASE.MarianaIslands.Saipan_Intl --- * AIRBASE.MarianaIslands.Tinian_Intl +-- * AIRBASE.MarianaIslands.North_West_Field -- * AIRBASE.MarianaIslands.Olf_Orote -- * AIRBASE.MarianaIslands.Pagan_Airstrip --- * AIRBASE.MarianaIslands.North_West_Field +-- * AIRBASE.MarianaIslands.Rota_Intl +-- * AIRBASE.MarianaIslands.Saipan_Intl +-- * AIRBASE.MarianaIslands.Tinian_Intl -- -- @field MarianaIslands AIRBASE.MarianaIslands = { - ["Rota_Intl"] = "Rota Intl", ["Andersen_AFB"] = "Andersen AFB", ["Antonio_B_Won_Pat_Intl"] = "Antonio B. Won Pat Intl", - ["Saipan_Intl"] = "Saipan Intl", - ["Tinian_Intl"] = "Tinian Intl", + ["North_West_Field"] = "North West Field", ["Olf_Orote"] = "Olf Orote", ["Pagan_Airstrip"] = "Pagan Airstrip", - ["North_West_Field"] = "North West Field", + ["Rota_Intl"] = "Rota Intl", + ["Saipan_Intl"] = "Saipan Intl", + ["Tinian_Intl"] = "Tinian Intl", } --- Airbases of the South Atlantic map: -- --- * AIRBASE.SouthAtlantic.Port_Stanley --- * AIRBASE.SouthAtlantic.Mount_Pleasant --- * AIRBASE.SouthAtlantic.San_Carlos_FOB --- * AIRBASE.SouthAtlantic.Rio_Grande --- * AIRBASE.SouthAtlantic.Rio_Gallegos --- * AIRBASE.SouthAtlantic.Ushuaia --- * AIRBASE.SouthAtlantic.Ushuaia_Helo_Port --- * AIRBASE.SouthAtlantic.Punta_Arenas --- * AIRBASE.SouthAtlantic.Pampa_Guanaco --- * AIRBASE.SouthAtlantic.San_Julian --- * AIRBASE.SouthAtlantic.Puerto_Williams --- * AIRBASE.SouthAtlantic.Puerto_Natales --- * AIRBASE.SouthAtlantic.El_Calafate --- * AIRBASE.SouthAtlantic.Puerto_Santa_Cruz --- * AIRBASE.SouthAtlantic.Comandante_Luis_Piedrabuena --- * AIRBASE.SouthAtlantic.Aerodromo_De_Tolhuin --- * AIRBASE.SouthAtlantic.Porvenir_Airfield --- * AIRBASE.SouthAtlantic.Almirante_Schroeders --- * AIRBASE.SouthAtlantic.Rio_Turbio --- * AIRBASE.SouthAtlantic.Rio_Chico --- * AIRBASE.SouthAtlantic.Franco_Bianco --- * AIRBASE.SouthAtlantic.Goose_Green --- * AIRBASE.SouthAtlantic.Hipico --- * AIRBASE.SouthAtlantic.CaletaTortel +-- * AIRBASE.Falklands.Almirante_Schroeders +-- * AIRBASE.Falklands.Caleta_Tortel +-- * AIRBASE.Falklands.Comandante_Luis_Piedrabuena +-- * AIRBASE.Falklands.Cullen +-- * AIRBASE.Falklands.El_Calafate +-- * AIRBASE.Falklands.Franco_Bianco +-- * AIRBASE.Falklands.Gobernador_Gregores +-- * AIRBASE.Falklands.Goose_Green +-- * AIRBASE.Falklands.Gull_Point +-- * AIRBASE.Falklands.Hipico_Flying_Club +-- * AIRBASE.Falklands.Mount_Pleasant +-- * AIRBASE.Falklands.O_Higgins +-- * AIRBASE.Falklands.Pampa_Guanaco +-- * AIRBASE.Falklands.Port_Stanley +-- * AIRBASE.Falklands.Porvenir +-- * AIRBASE.Falklands.Puerto_Natales +-- * AIRBASE.Falklands.Puerto_Santa_Cruz +-- * AIRBASE.Falklands.Puerto_Williams +-- * AIRBASE.Falklands.Punta_Arenas +-- * AIRBASE.Falklands.Rio_Chico +-- * AIRBASE.Falklands.Rio_Gallegos +-- * AIRBASE.Falklands.Rio_Grande +-- * AIRBASE.Falklands.Rio_Turbio +-- * AIRBASE.Falklands.San_Carlos_FOB +-- * AIRBASE.Falklands.San_Julian +-- * AIRBASE.Falklands.Tolhuin +-- * AIRBASE.Falklands.Ushuaia +-- * AIRBASE.Falklands.Ushuaia_Helo_Port -- --@field MarianaIslands AIRBASE.SouthAtlantic={ - ["Port_Stanley"]="Port Stanley", - ["Mount_Pleasant"]="Mount Pleasant", - ["San_Carlos_FOB"]="San Carlos FOB", - ["Rio_Grande"]="Rio Grande", - ["Rio_Gallegos"]="Rio Gallegos", - ["Ushuaia"]="Ushuaia", - ["Ushuaia_Helo_Port"]="Ushuaia Helo Port", - ["Punta_Arenas"]="Punta Arenas", - ["Pampa_Guanaco"]="Pampa Guanaco", - ["San_Julian"]="San Julian", - ["Puerto_Williams"]="Puerto Williams", - ["Puerto_Natales"]="Puerto Natales", - ["El_Calafate"]="El Calafate", - ["Puerto_Santa_Cruz"]="Puerto Santa Cruz", - ["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena", - ["Aerodromo_De_Tolhuin"]="Aerodromo De Tolhuin", - ["Porvenir_Airfield"]="Porvenir Airfield", - ["Almirante_Schroeders"]="Almirante Schroeders", - ["Rio_Turbio"]="Rio Turbio", - ["Rio_Chico"] = "Rio Chico", + ["Almirante_Schroeders"] = "Almirante Schroeders", + ["Caleta_Tortel"] = "Caleta Tortel", + ["Comandante_Luis_Piedrabuena"] = "Comandante Luis Piedrabuena", + ["Cullen"] = "Cullen", + ["El_Calafate"] = "El Calafate", ["Franco_Bianco"] = "Franco Bianco", + ["Gobernador_Gregores"] = "Gobernador Gregores", ["Goose_Green"] = "Goose Green", - ["Hipico_Flying_Club"] = "Hipico Flying Club", - ["CaletaTortel"] = "CaletaTortel", - ["Aeropuerto_de_Gobernador_Gregores"] = "Aeropuerto de Gobernador Gregores", - ["Aerodromo_O_Higgins"] = "Aerodromo O'Higgins", - ["Cullen_Airport"] = "Cullen Airport", ["Gull_Point"] = "Gull Point", + ["Hipico_Flying_Club"] = "Hipico Flying Club", + ["Mount_Pleasant"] = "Mount Pleasant", + ["O_Higgins"] = "O'Higgins", + ["Pampa_Guanaco"] = "Pampa Guanaco", + ["Port_Stanley"] = "Port Stanley", + ["Porvenir"] = "Porvenir", + ["Puerto_Natales"] = "Puerto Natales", + ["Puerto_Santa_Cruz"] = "Puerto Santa Cruz", + ["Puerto_Williams"] = "Puerto Williams", + ["Punta_Arenas"] = "Punta Arenas", + ["Rio_Chico"] = "Rio Chico", + ["Rio_Gallegos"] = "Rio Gallegos", + ["Rio_Grande"] = "Rio Grande", + ["Rio_Turbio"] = "Rio Turbio", + ["San_Carlos_FOB"] = "San Carlos FOB", + ["San_Julian"] = "San Julian", + ["Tolhuin"] = "Tolhuin", + ["Ushuaia"] = "Ushuaia", + ["Ushuaia_Helo_Port"] = "Ushuaia Helo Port", } --- Airbases of the Sinai map: -- --- * AIRBASE.Sinai.Abu_Suwayr --- * AIRBASE.Sinai.Sde_Dov --- * AIRBASE.Sinai.AzZaqaziq --- * AIRBASE.Sinai.Hatzor --- * AIRBASE.Sinai.Kedem --- * AIRBASE.Sinai.Nevatim --- * AIRBASE.Sinai.Cairo_International_Airport --- * AIRBASE.Sinai.Al_Ismailiyah --- * AIRBASE.Sinai.As_Salihiyah --- * AIRBASE.Sinai.Fayed --- * AIRBASE.Sinai.Bilbeis_Air_Base --- * AIRBASE.Sinai.Ramon_Airbase --- * AIRBASE.Sinai.Kibrit_Air_Base --- * AIRBASE.Sinai.El_Arish --- * AIRBASE.Sinai.Ovda --- * AIRBASE.Sinai.Melez --- * AIRBASE.Sinai.Al_Mansurah --- * AIRBASE.Sinai.Palmahim --- * AIRBASE.Sinai.Baluza --- * AIRBASE.Sinai.El_Gora --- * AIRBASE.Sinai.Difarsuwar_Airfield --- * AIRBASE.Sinai.Wadi_al_Jandali --- * AIRBASE.Sinai.St_Catherine --- * AIRBASE.Sinai.Tel_Nof --- * AIRBASE.Sinai.Abu_Rudeis --- * AIRBASE.Sinai.Inshas_Airbase --- * AIRBASE.Sinai.Ben_Gurion --- * AIRBASE.Sinai.Bir_Hasanah --- * AIRBASE.Sinai.Cairo_West +-- * AIRBASE.SinaiMap.Abu_Rudeis +-- * AIRBASE.SinaiMap.Abu_Suwayr +-- * AIRBASE.SinaiMap.Al_Ismailiyah +-- * AIRBASE.SinaiMap.Al_Mansurah +-- * AIRBASE.SinaiMap.As_Salihiyah +-- * AIRBASE.SinaiMap.AzZaqaziq +-- * AIRBASE.SinaiMap.Baluza +-- * AIRBASE.SinaiMap.Ben_Gurion +-- * AIRBASE.SinaiMap.Bilbeis_Air_Base +-- * AIRBASE.SinaiMap.Bir_Hasanah +-- * AIRBASE.SinaiMap.Cairo_International_Airport +-- * AIRBASE.SinaiMap.Cairo_West +-- * AIRBASE.SinaiMap.Difarsuwar_Airfield +-- * AIRBASE.SinaiMap.El_Arish +-- * AIRBASE.SinaiMap.El_Gora +-- * AIRBASE.SinaiMap.Fayed +-- * AIRBASE.SinaiMap.Hatzerim +-- * AIRBASE.SinaiMap.Hatzor +-- * AIRBASE.SinaiMap.Inshas_Airbase +-- * AIRBASE.SinaiMap.Kedem +-- * AIRBASE.SinaiMap.Kibrit_Air_Base +-- * AIRBASE.SinaiMap.Melez +-- * AIRBASE.SinaiMap.Nevatim +-- * AIRBASE.SinaiMap.Ovda +-- * AIRBASE.SinaiMap.Palmahim +-- * AIRBASE.SinaiMap.Ramon_Airbase +-- * AIRBASE.SinaiMap.Sde_Dov +-- * AIRBASE.SinaiMap.St_Catherine +-- * AIRBASE.SinaiMap.Tel_Nof +-- * AIRBASE.SinaiMap.Wadi_al_Jandali -- -- @field Sinai AIRBASE.Sinai = { - ["Hatzerim"] = "Hatzerim", + ["Abu_Rudeis"] = "Abu Rudeis", ["Abu_Suwayr"] = "Abu Suwayr", - ["Sde_Dov"] = "Sde Dov", - ["AzZaqaziq"] = "AzZaqaziq", - ["Hatzor"] = "Hatzor", - ["Kedem"] = "Kedem", - ["Nevatim"] = "Nevatim", - ["Cairo_International_Airport"] = "Cairo International Airport", ["Al_Ismailiyah"] = "Al Ismailiyah", - ["As_Salihiyah"] = "As Salihiyah", - ["Fayed"] = "Fayed", - ["Bilbeis_Air_Base"] = "Bilbeis Air Base", - ["Ramon_Airbase"] = "Ramon Airbase", - ["Kibrit_Air_Base"] = "Kibrit Air Base", - ["El_Arish"] = "El Arish", - ["Ovda"] = "Ovda", - ["Melez"] = "Melez", ["Al_Mansurah"] = "Al Mansurah", - ["Palmahim"] = "Palmahim", + ["As_Salihiyah"] = "As Salihiyah", + ["AzZaqaziq"] = "AzZaqaziq", ["Baluza"] = "Baluza", - ["El_Gora"] = "El Gora", + ["Ben_Gurion"] = "Ben-Gurion", + ["Bilbeis_Air_Base"] = "Bilbeis Air Base", + ["Bir_Hasanah"] = "Bir Hasanah", + ["Cairo_International_Airport"] = "Cairo International Airport", + ["Cairo_West"] = "Cairo West", ["Difarsuwar_Airfield"] = "Difarsuwar Airfield", - ["Wadi_al_Jandali"] = "Wadi al Jandali", + ["El_Arish"] = "El Arish", + ["El_Gora"] = "El Gora", + ["Fayed"] = "Fayed", + ["Hatzerim"] = "Hatzerim", + ["Hatzor"] = "Hatzor", + ["Inshas_Airbase"] = "Inshas Airbase", + ["Kedem"] = "Kedem", + ["Kibrit_Air_Base"] = "Kibrit Air Base", + ["Melez"] = "Melez", + ["Nevatim"] = "Nevatim", + ["Ovda"] = "Ovda", + ["Palmahim"] = "Palmahim", + ["Ramon_Airbase"] = "Ramon Airbase", + ["Sde_Dov"] = "Sde Dov", ["St_Catherine"] = "St Catherine", ["Tel_Nof"] = "Tel Nof", - ["Abu_Rudeis"] = "Abu Rudeis", - ["Inshas_Airbase"] = "Inshas Airbase", - ["Ben_Gurion"] = "Ben-Gurion", - ["Bir_Hasanah"] = "Bir Hasanah", - ["Cairo_West"] = "Cairo West", + ["Wadi_al_Jandali"] = "Wadi al Jandali", } --- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". From bff60bdb695f66193bc37634c82ab59fc8c26995 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 29 Feb 2024 10:32:35 +0100 Subject: [PATCH 41/73] Update of all Airbases (uptodate and sorted) --- Moose Development/Moose/Wrapper/Airbase.lua | 693 ++++++++++---------- 1 file changed, 350 insertions(+), 343 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index ae2d9db16..be41aa6c5 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -79,92 +79,92 @@ AIRBASE = { -- -- Airbases of the Caucasus map: -- --- * AIRBASE.Caucasus.Gelendzhik --- * AIRBASE.Caucasus.Krasnodar_Pashkovsky --- * AIRBASE.Caucasus.Sukhumi_Babushara --- * AIRBASE.Caucasus.Gudauta --- * AIRBASE.Caucasus.Batumi --- * AIRBASE.Caucasus.Senaki_Kolkhi --- * AIRBASE.Caucasus.Kobuleti --- * AIRBASE.Caucasus.Kutaisi --- * AIRBASE.Caucasus.Tbilisi_Lochini --- * AIRBASE.Caucasus.Soganlug --- * AIRBASE.Caucasus.Vaziani --- * AIRBASE.Caucasus.Anapa_Vityazevo --- * AIRBASE.Caucasus.Krasnodar_Center --- * AIRBASE.Caucasus.Novorossiysk --- * AIRBASE.Caucasus.Krymsk --- * AIRBASE.Caucasus.Maykop_Khanskaya --- * AIRBASE.Caucasus.Sochi_Adler --- * AIRBASE.Caucasus.Mineralnye_Vody --- * AIRBASE.Caucasus.Nalchik --- * AIRBASE.Caucasus.Mozdok --- * AIRBASE.Caucasus.Beslan +-- * AIRBASE.Caucasus.Anapa_Vityazevo +-- * AIRBASE.Caucasus.Batumi +-- * AIRBASE.Caucasus.Beslan +-- * AIRBASE.Caucasus.Gelendzhik +-- * AIRBASE.Caucasus.Gudauta +-- * AIRBASE.Caucasus.Kobuleti +-- * AIRBASE.Caucasus.Krasnodar_Center +-- * AIRBASE.Caucasus.Krasnodar_Pashkovsky +-- * AIRBASE.Caucasus.Krymsk +-- * AIRBASE.Caucasus.Kutaisi +-- * AIRBASE.Caucasus.Maykop_Khanskaya +-- * AIRBASE.Caucasus.Mineralnye_Vody +-- * AIRBASE.Caucasus.Mozdok +-- * AIRBASE.Caucasus.Nalchik +-- * AIRBASE.Caucasus.Novorossiysk +-- * AIRBASE.Caucasus.Senaki_Kolkhi +-- * AIRBASE.Caucasus.Sochi_Adler +-- * AIRBASE.Caucasus.Soganlug +-- * AIRBASE.Caucasus.Sukhumi_Babushara +-- * AIRBASE.Caucasus.Tbilisi_Lochini +-- * AIRBASE.Caucasus.Vaziani -- -- @field Caucasus AIRBASE.Caucasus = { - ["Gelendzhik"] = "Gelendzhik", - ["Krasnodar_Pashkovsky"] = "Krasnodar-Pashkovsky", - ["Sukhumi_Babushara"] = "Sukhumi-Babushara", - ["Gudauta"] = "Gudauta", - ["Batumi"] = "Batumi", - ["Senaki_Kolkhi"] = "Senaki-Kolkhi", - ["Kobuleti"] = "Kobuleti", - ["Kutaisi"] = "Kutaisi", - ["Tbilisi_Lochini"] = "Tbilisi-Lochini", - ["Soganlug"] = "Soganlug", - ["Vaziani"] = "Vaziani", ["Anapa_Vityazevo"] = "Anapa-Vityazevo", - ["Krasnodar_Center"] = "Krasnodar-Center", - ["Novorossiysk"] = "Novorossiysk", - ["Krymsk"] = "Krymsk", - ["Maykop_Khanskaya"] = "Maykop-Khanskaya", - ["Sochi_Adler"] = "Sochi-Adler", - ["Mineralnye_Vody"] = "Mineralnye Vody", - ["Nalchik"] = "Nalchik", - ["Mozdok"] = "Mozdok", + ["Batumi"] = "Batumi", ["Beslan"] = "Beslan", + ["Gelendzhik"] = "Gelendzhik", + ["Gudauta"] = "Gudauta", + ["Kobuleti"] = "Kobuleti", + ["Krasnodar_Center"] = "Krasnodar-Center", + ["Krasnodar_Pashkovsky"] = "Krasnodar-Pashkovsky", + ["Krymsk"] = "Krymsk", + ["Kutaisi"] = "Kutaisi", + ["Maykop_Khanskaya"] = "Maykop-Khanskaya", + ["Mineralnye_Vody"] = "Mineralnye Vody", + ["Mozdok"] = "Mozdok", + ["Nalchik"] = "Nalchik", + ["Novorossiysk"] = "Novorossiysk", + ["Senaki_Kolkhi"] = "Senaki-Kolkhi", + ["Sochi_Adler"] = "Sochi-Adler", + ["Soganlug"] = "Soganlug", + ["Sukhumi_Babushara"] = "Sukhumi-Babushara", + ["Tbilisi_Lochini"] = "Tbilisi-Lochini", + ["Vaziani"] = "Vaziani", } --- Airbases of the Nevada map: -- --- * AIRBASE.Nevada.Creech_AFB --- * AIRBASE.Nevada.Groom_Lake_AFB --- * AIRBASE.Nevada.McCarran_International_Airport --- * AIRBASE.Nevada.Nellis_AFB --- * AIRBASE.Nevada.Beatty_Airport --- * AIRBASE.Nevada.Boulder_City_Airport --- * AIRBASE.Nevada.Echo_Bay --- * AIRBASE.Nevada.Henderson_Executive_Airport --- * AIRBASE.Nevada.Jean_Airport --- * AIRBASE.Nevada.Laughlin_Airport --- * AIRBASE.Nevada.Lincoln_County --- * AIRBASE.Nevada.Mesquite --- * AIRBASE.Nevada.Mina_Airport --- * AIRBASE.Nevada.North_Las_Vegas --- * AIRBASE.Nevada.Pahute_Mesa_Airstrip --- * AIRBASE.Nevada.Tonopah_Airport --- * AIRBASE.Nevada.Tonopah_Test_Range_Airfield +-- * AIRBASE.Nevada.Beatty +-- * AIRBASE.Nevada.Boulder_City +-- * AIRBASE.Nevada.Creech +-- * AIRBASE.Nevada.Echo_Bay +-- * AIRBASE.Nevada.Groom_Lake +-- * AIRBASE.Nevada.Henderson_Executive +-- * AIRBASE.Nevada.Jean +-- * AIRBASE.Nevada.Laughlin +-- * AIRBASE.Nevada.Lincoln_County +-- * AIRBASE.Nevada.McCarran_International +-- * AIRBASE.Nevada.Mesquite +-- * AIRBASE.Nevada.Mina +-- * AIRBASE.Nevada.Nellis +-- * AIRBASE.Nevada.North_Las_Vegas +-- * AIRBASE.Nevada.Pahute_Mesa +-- * AIRBASE.Nevada.Tonopah +-- * AIRBASE.Nevada.Tonopah_Test_Range -- -- @field Nevada AIRBASE.Nevada = { - ["Creech_AFB"] = "Creech", - ["Groom_Lake_AFB"] = "Groom Lake", - ["McCarran_International_Airport"] = "McCarran International", - ["Nellis_AFB"] = "Nellis", - ["Beatty_Airport"] = "Beatty", - ["Boulder_City_Airport"] = "Boulder City", + ["Beatty"] = "Beatty", + ["Boulder_City"] = "Boulder City", + ["Creech"] = "Creech", ["Echo_Bay"] = "Echo Bay", - ["Henderson_Executive_Airport"] = "Henderson Executive", - ["Jean_Airport"] = "Jean", - ["Laughlin_Airport"] = "Laughlin", + ["Groom_Lake"] = "Groom Lake", + ["Henderson_Executive"] = "Henderson Executive", + ["Jean"] = "Jean", + ["Laughlin"] = "Laughlin", ["Lincoln_County"] = "Lincoln County", + ["McCarran_International"] = "McCarran International", ["Mesquite"] = "Mesquite", - ["Mina_Airport"] = "Mina", + ["Mina"] = "Mina", + ["Nellis"] = "Nellis", ["North_Las_Vegas"] = "North Las Vegas", - ["Pahute_Mesa_Airstrip"] = "Pahute Mesa", - ["Tonopah_Airport"] = "Tonopah", - ["Tonopah_Test_Range_Airfield"] = "Tonopah Test Range", + ["Pahute_Mesa"] = "Pahute Mesa", + ["Tonopah"] = "Tonopah", + ["Tonopah_Test_Range"] = "Tonopah Test Range", } --- Airbases of the Normandy map: @@ -334,31 +334,32 @@ AIRBASE.Normandy = { --- Airbases of the Persion Gulf Map: -- --- * AIRBASE.PersianGulf.Abu_Dhabi_International_Airport --- * AIRBASE.PersianGulf.Abu_Musa_Island_Airport --- * AIRBASE.PersianGulf.Al_Bateen_Airport --- * AIRBASE.PersianGulf.Al_Ain_International_Airport --- * AIRBASE.PersianGulf.Al_Dhafra_AB +-- * AIRBASE.PersianGulf.Abu_Dhabi_Intl +-- * AIRBASE.PersianGulf.Abu_Musa_Island +-- * AIRBASE.PersianGulf.Al_Ain_Intl +-- * AIRBASE.PersianGulf.Al_Bateen +-- * AIRBASE.PersianGulf.Al_Dhafra_AFB -- * AIRBASE.PersianGulf.Al_Maktoum_Intl --- * AIRBASE.PersianGulf.Al_Minhad_AB --- * AIRBASE.PersianGulf.Bandar_e_Jask_airfield +-- * AIRBASE.PersianGulf.Al_Minhad_AFB -- * AIRBASE.PersianGulf.Bandar_Abbas_Intl -- * AIRBASE.PersianGulf.Bandar_Lengeh +-- * AIRBASE.PersianGulf.Bandar_e_Jask -- * AIRBASE.PersianGulf.Dubai_Intl -- * AIRBASE.PersianGulf.Fujairah_Intl -- * AIRBASE.PersianGulf.Havadarya --- * AIRBASE.PersianGulf.Jiroft_Airport --- * AIRBASE.PersianGulf.Kerman_Airport +-- * AIRBASE.PersianGulf.Jiroft +-- * AIRBASE.PersianGulf.Kerman -- * AIRBASE.PersianGulf.Khasab --- * AIRBASE.PersianGulf.Kish_International_Airport --- * AIRBASE.PersianGulf.Lar_Airbase --- * AIRBASE.PersianGulf.Lavan_Island_Airport --- * AIRBASE.PersianGulf.Liwa_Airbase +-- * AIRBASE.PersianGulf.Kish_Intl +-- * AIRBASE.PersianGulf.Lar +-- * AIRBASE.PersianGulf.Lavan_Island +-- * AIRBASE.PersianGulf.Liwa_AFB -- * AIRBASE.PersianGulf.Qeshm_Island --- * AIRBASE.PersianGulf.Ras_Al_Khaimah --- * AIRBASE.PersianGulf.Sas_Al_Nakheel_Airport +-- * AIRBASE.PersianGulf.Quasoura_airport +-- * AIRBASE.PersianGulf.Ras_Al_Khaimah_Intl +-- * AIRBASE.PersianGulf.Sas_Al_Nakheel -- * AIRBASE.PersianGulf.Sharjah_Intl --- * AIRBASE.PersianGulf.Shiraz_International_Airport +-- * AIRBASE.PersianGulf.Shiraz_Intl -- * AIRBASE.PersianGulf.Sir_Abu_Nuayr -- * AIRBASE.PersianGulf.Sirri_Island -- * AIRBASE.PersianGulf.Tunb_Island_AFB @@ -366,31 +367,32 @@ AIRBASE.Normandy = { -- -- @field PersianGulf AIRBASE.PersianGulf = { - ["Abu_Dhabi_International_Airport"] = "Abu Dhabi Intl", - ["Abu_Musa_Island_Airport"] = "Abu Musa Island", - ["Al_Ain_International_Airport"] = "Al Ain Intl", - ["Al_Bateen_Airport"] = "Al-Bateen", - ["Al_Dhafra_AB"] = "Al Dhafra AFB", + ["Abu_Dhabi_Intl"] = "Abu Dhabi Intl", + ["Abu_Musa_Island"] = "Abu Musa Island", + ["Al_Ain_Intl"] = "Al Ain Intl", + ["Al_Bateen"] = "Al-Bateen", + ["Al_Dhafra_AFB"] = "Al Dhafra AFB", ["Al_Maktoum_Intl"] = "Al Maktoum Intl", - ["Al_Minhad_AB"] = "Al Minhad AFB", + ["Al_Minhad_AFB"] = "Al Minhad AFB", ["Bandar_Abbas_Intl"] = "Bandar Abbas Intl", ["Bandar_Lengeh"] = "Bandar Lengeh", - ["Bandar_e_Jask_airfield"] = "Bandar-e-Jask", + ["Bandar_e_Jask"] = "Bandar-e-Jask", ["Dubai_Intl"] = "Dubai Intl", ["Fujairah_Intl"] = "Fujairah Intl", ["Havadarya"] = "Havadarya", - ["Jiroft_Airport"] = "Jiroft", - ["Kerman_Airport"] = "Kerman", + ["Jiroft"] = "Jiroft", + ["Kerman"] = "Kerman", ["Khasab"] = "Khasab", - ["Kish_International_Airport"] = "Kish Intl", - ["Lar_Airbase"] = "Lar", - ["Lavan_Island_Airport"] = "Lavan Island", - ["Liwa_Airbase"] = "Liwa AFB", + ["Kish_Intl"] = "Kish Intl", + ["Lar"] = "Lar", + ["Lavan_Island"] = "Lavan Island", + ["Liwa_AFB"] = "Liwa AFB", ["Qeshm_Island"] = "Qeshm Island", - ["Ras_Al_Khaimah"] = "Ras Al Khaimah Intl", - ["Sas_Al_Nakheel_Airport"] = "Sas Al Nakheel", + ["Quasoura_airport"] = "Quasoura_airport", + ["Ras_Al_Khaimah_Intl"] = "Ras Al Khaimah Intl", + ["Sas_Al_Nakheel"] = "Sas Al Nakheel", ["Sharjah_Intl"] = "Sharjah Intl", - ["Shiraz_International_Airport"] = "Shiraz Intl", + ["Shiraz_Intl"] = "Shiraz Intl", ["Sir_Abu_Nuayr"] = "Sir Abu Nuayr", ["Sirri_Island"] = "Sirri Island", ["Tunb_Island_AFB"] = "Tunb Island AFB", @@ -400,317 +402,322 @@ AIRBASE.PersianGulf = { --- Airbases of The Channel Map: -- -- * AIRBASE.TheChannel.Abbeville_Drucat +-- * AIRBASE.TheChannel.Biggin_Hill +-- * AIRBASE.TheChannel.Detling +-- * AIRBASE.TheChannel.Dunkirk_Mardyck +-- * AIRBASE.TheChannel.Eastchurch +-- * AIRBASE.TheChannel.Hawkinge +-- * AIRBASE.TheChannel.Headcorn +-- * AIRBASE.TheChannel.High_Halden +-- * AIRBASE.TheChannel.Lympne +-- * AIRBASE.TheChannel.Manston -- * AIRBASE.TheChannel.Merville_Calonne -- * AIRBASE.TheChannel.Saint_Omer_Longuenesse --- * AIRBASE.TheChannel.Dunkirk_Mardyck --- * AIRBASE.TheChannel.Manston --- * AIRBASE.TheChannel.Hawkinge --- * AIRBASE.TheChannel.Lympne --- * AIRBASE.TheChannel.Detling --- * AIRBASE.TheChannel.High_Halden --- * AIRBASE.TheChannel.Biggin_Hill --- * AIRBASE.TheChannel.Eastchurch --- * AIRBASE.TheChannel.Headcorn -- -- @field TheChannel AIRBASE.TheChannel = { ["Abbeville_Drucat"] = "Abbeville Drucat", + ["Biggin_Hill"] = "Biggin Hill", + ["Detling"] = "Detling", + ["Dunkirk_Mardyck"] = "Dunkirk Mardyck", + ["Eastchurch"] = "Eastchurch", + ["Hawkinge"] = "Hawkinge", + ["Headcorn"] = "Headcorn", + ["High_Halden"] = "High Halden", + ["Lympne"] = "Lympne", + ["Manston"] = "Manston", ["Merville_Calonne"] = "Merville Calonne", ["Saint_Omer_Longuenesse"] = "Saint Omer Longuenesse", - ["Dunkirk_Mardyck"] = "Dunkirk Mardyck", - ["Manston"] = "Manston", - ["Hawkinge"] = "Hawkinge", - ["Lympne"] = "Lympne", - ["Detling"] = "Detling", - ["High_Halden"] = "High Halden", - ["Biggin_Hill"] = "Biggin Hill", - ["Eastchurch"] = "Eastchurch", - ["Headcorn"] = "Headcorn", } --- Airbases of the Syria map: -- --- * AIRBASE.Syria.Kuweires --- * AIRBASE.Syria.Incirlik --- * AIRBASE.Syria.King_Abdullah_II --- * AIRBASE.Syria.Akrotiri --- * AIRBASE.Syria.Aleppo -- * AIRBASE.Syria.Abu_al_Duhur --- * AIRBASE.Syria.Hatay --- * AIRBASE.Syria.Paphos +-- * AIRBASE.Syria.Adana_Sakirpasa +-- * AIRBASE.Syria.Akrotiri +-- * AIRBASE.Syria.Al_Dumayr +-- * AIRBASE.Syria.Al_Qusayr +-- * AIRBASE.Syria.Aleppo +-- * AIRBASE.Syria.Amman +-- * AIRBASE.Syria.An_Nasiriyah -- * AIRBASE.Syria.At_Tanf --- * AIRBASE.Syria.Tal_Siman --- * AIRBASE.Syria.Rayak +-- * AIRBASE.Syria.Bassel_Al_Assad +-- * AIRBASE.Syria.Beirut_Rafic_Hariri +-- * AIRBASE.Syria.Damascus +-- * AIRBASE.Syria.Deir_ez_Zor +-- * AIRBASE.Syria.Ercan +-- * AIRBASE.Syria.Eyn_Shemer +-- * AIRBASE.Syria.Gaziantep +-- * AIRBASE.Syria.Gazipasa +-- * AIRBASE.Syria.Gecitkale +-- * AIRBASE.Syria.H3 +-- * AIRBASE.Syria.H3_Northwest +-- * AIRBASE.Syria.H3_Southwest +-- * AIRBASE.Syria.H4 +-- * AIRBASE.Syria.Haifa +-- * AIRBASE.Syria.Hama +-- * AIRBASE.Syria.Hatay +-- * AIRBASE.Syria.Herzliya +-- * AIRBASE.Syria.Incirlik +-- * AIRBASE.Syria.Jirah +-- * AIRBASE.Syria.Khalkhalah +-- * AIRBASE.Syria.Kharab_Ishk +-- * AIRBASE.Syria.King_Abdullah_II +-- * AIRBASE.Syria.King_Hussein_Air_College +-- * AIRBASE.Syria.Kingsfield +-- * AIRBASE.Syria.Kiryat_Shmona +-- * AIRBASE.Syria.Kuweires +-- * AIRBASE.Syria.Lakatamia +-- * AIRBASE.Syria.Larnaca +-- * AIRBASE.Syria.Marj_Ruhayyil +-- * AIRBASE.Syria.Marj_as_Sultan_North +-- * AIRBASE.Syria.Marj_as_Sultan_South +-- * AIRBASE.Syria.Megiddo +-- * AIRBASE.Syria.Mezzeh +-- * AIRBASE.Syria.Minakh -- * AIRBASE.Syria.Muwaffaq_Salti -- * AIRBASE.Syria.Naqoura --- * AIRBASE.Syria.Gaziantep --- * AIRBASE.Syria.Al_Qusayr --- * AIRBASE.Syria.Al_Dumayr --- * AIRBASE.Syria.Kingsfield --- * AIRBASE.Syria.Marj_as_Sultan_North --- * AIRBASE.Syria.Beirut_Rafic_Hariri --- * AIRBASE.Syria.Palmyra --- * AIRBASE.Syria.Hama --- * AIRBASE.Syria.Eyn_Shemer --- * AIRBASE.Syria.Sanliurfa --- * AIRBASE.Syria.Amman --- * AIRBASE.Syria.Deir_ez_Zor --- * AIRBASE.Syria.Taftanaz --- * AIRBASE.Syria.Damascus --- * AIRBASE.Syria.Gazipasa --- * AIRBASE.Syria.Herzliya --- * AIRBASE.Syria.H4 --- * AIRBASE.Syria.Tiyas --- * AIRBASE.Syria.Lakatamia --- * AIRBASE.Syria.Kharab_Ishk --- * AIRBASE.Syria.Haifa --- * AIRBASE.Syria.Khalkhalah --- * AIRBASE.Syria.Megiddo --- * AIRBASE.Syria.An_Nasiriyah --- * AIRBASE.Syria.Bassel_Al_Assad --- * AIRBASE.Syria.Ruwayshid --- * AIRBASE.Syria.Mezzeh --- * AIRBASE.Syria.Gecitkale -- * AIRBASE.Syria.Nicosia --- * AIRBASE.Syria.Ramat_David --- * AIRBASE.Syria.Tha_lah --- * AIRBASE.Syria.H3_Northwest --- * AIRBASE.Syria.Sayqal --- * AIRBASE.Syria.Jirah --- * AIRBASE.Syria.Shayrat --- * AIRBASE.Syria.Adana_Sakirpasa --- * AIRBASE.Syria.Wujah_Al_Hajar +-- * AIRBASE.Syria.Palmyra +-- * AIRBASE.Syria.Paphos -- * AIRBASE.Syria.Pinarbashi --- * AIRBASE.Syria.H3_Southwest --- * AIRBASE.Syria.Rosh_Pina --- * AIRBASE.Syria.Kiryat_Shmona --- * AIRBASE.Syria.H3 --- * AIRBASE.Syria.Qabr_as_Sitt -- * AIRBASE.Syria.Prince_Hassan --- * AIRBASE.Syria.Larnaca --- * AIRBASE.Syria.King_Hussein_Air_College --- * AIRBASE.Syria.Ercan --- * AIRBASE.Syria.Marj_Ruhayyil --- * AIRBASE.Syria.Tabqa --- * AIRBASE.Syria.Marj_as_Sultan_South +-- * AIRBASE.Syria.Qabr_as_Sitt +-- * AIRBASE.Syria.Ramat_David +-- * AIRBASE.Syria.Rayak -- * AIRBASE.Syria.Rene_Mouawad --- * AIRBASE.Syria.Minakh +-- * AIRBASE.Syria.Rosh_Pina +-- * AIRBASE.Syria.Ruwayshid +-- * AIRBASE.Syria.Sanliurfa +-- * AIRBASE.Syria.Sayqal +-- * AIRBASE.Syria.Shayrat +-- * AIRBASE.Syria.Tabqa +-- * AIRBASE.Syria.Taftanaz +-- * AIRBASE.Syria.Tal_Siman +-- * AIRBASE.Syria.Tha_lah +-- * AIRBASE.Syria.Tiyas +-- * AIRBASE.Syria.Wujah_Al_Hajar -- --@field Syria AIRBASE.Syria={ - ["Kuweires"] = "Kuweires", - ["Incirlik"] = "Incirlik", - ["King_Abdullah_II"] = "King Abdullah II", - ["Akrotiri"] = "Akrotiri", - ["Aleppo"] = "Aleppo", ["Abu_al_Duhur"] = "Abu al-Duhur", - ["Hatay"] = "Hatay", - ["Paphos"] = "Paphos", + ["Adana_Sakirpasa"] = "Adana Sakirpasa", + ["Akrotiri"] = "Akrotiri", + ["Al_Dumayr"] = "Al-Dumayr", + ["Al_Qusayr"] = "Al Qusayr", + ["Aleppo"] = "Aleppo", + ["Amman"] = "Amman", + ["An_Nasiriyah"] = "An Nasiriyah", ["At_Tanf"] = "At Tanf", - ["Tal_Siman"] = "Tal Siman", - ["Rayak"] = "Rayak", + ["Bassel_Al_Assad"] = "Bassel Al-Assad", + ["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri", + ["Damascus"] = "Damascus", + ["Deir_ez_Zor"] = "Deir ez-Zor", + ["Ercan"] = "Ercan", + ["Eyn_Shemer"] = "Eyn Shemer", + ["Gaziantep"] = "Gaziantep", + ["Gazipasa"] = "Gazipasa", + ["Gecitkale"] = "Gecitkale", + ["H3"] = "H3", + ["H3_Northwest"] = "H3 Northwest", + ["H3_Southwest"] = "H3 Southwest", + ["H4"] = "H4", + ["Haifa"] = "Haifa", + ["Hama"] = "Hama", + ["Hatay"] = "Hatay", + ["Herzliya"] = "Herzliya", + ["Incirlik"] = "Incirlik", + ["Jirah"] = "Jirah", + ["Khalkhalah"] = "Khalkhalah", + ["Kharab_Ishk"] = "Kharab Ishk", + ["King_Abdullah_II"] = "King Abdullah II", + ["King_Hussein_Air_College"] = "King Hussein Air College", + ["Kingsfield"] = "Kingsfield", + ["Kiryat_Shmona"] = "Kiryat Shmona", + ["Kuweires"] = "Kuweires", + ["Lakatamia"] = "Lakatamia", + ["Larnaca"] = "Larnaca", + ["Marj_Ruhayyil"] = "Marj Ruhayyil", + ["Marj_as_Sultan_North"] = "Marj as Sultan North", + ["Marj_as_Sultan_South"] = "Marj as Sultan South", + ["Megiddo"] = "Megiddo", + ["Mezzeh"] = "Mezzeh", + ["Minakh"] = "Minakh", ["Muwaffaq_Salti"] = "Muwaffaq Salti", ["Naqoura"] = "Naqoura", - ["Gaziantep"] = "Gaziantep", - ["Al_Qusayr"] = "Al Qusayr", - ["Al_Dumayr"] = "Al-Dumayr", - ["Kingsfield"] = "Kingsfield", - ["Marj_as_Sultan_North"] = "Marj as Sultan North", - ["Beirut_Rafic_Hariri"] = "Beirut-Rafic Hariri", - ["Palmyra"] = "Palmyra", - ["Hama"] = "Hama", - ["Eyn_Shemer"] = "Eyn Shemer", - ["Sanliurfa"] = "Sanliurfa", - ["Amman"] = "Amman", - ["Deir_ez_Zor"] = "Deir ez-Zor", - ["Taftanaz"] = "Taftanaz", - ["Damascus"] = "Damascus", - ["Gazipasa"] = "Gazipasa", - ["Herzliya"] = "Herzliya", - ["H4"] = "H4", - ["Tiyas"] = "Tiyas", - ["Lakatamia"] = "Lakatamia", - ["Kharab_Ishk"] = "Kharab Ishk", - ["Haifa"] = "Haifa", - ["Khalkhalah"] = "Khalkhalah", - ["Megiddo"] = "Megiddo", - ["An_Nasiriyah"] = "An Nasiriyah", - ["Bassel_Al_Assad"] = "Bassel Al-Assad", - ["Ruwayshid"] = "Ruwayshid", - ["Mezzeh"] = "Mezzeh", - ["Gecitkale"] = "Gecitkale", ["Nicosia"] = "Nicosia", - ["Ramat_David"] = "Ramat David", - ["Tha_lah"] = "Tha'lah", - ["H3_Northwest"] = "H3 Northwest", - ["Sayqal"] = "Sayqal", - ["Jirah"] = "Jirah", - ["Shayrat"] = "Shayrat", - ["Adana_Sakirpasa"] = "Adana Sakirpasa", - ["Wujah_Al_Hajar"] = "Wujah Al Hajar", + ["Palmyra"] = "Palmyra", + ["Paphos"] = "Paphos", ["Pinarbashi"] = "Pinarbashi", - ["H3_Southwest"] = "H3 Southwest", - ["Rosh_Pina"] = "Rosh Pina", - ["Kiryat_Shmona"] = "Kiryat Shmona", - ["H3"] = "H3", - ["Qabr_as_Sitt"] = "Qabr as Sitt", ["Prince_Hassan"] = "Prince Hassan", - ["Larnaca"] = "Larnaca", - ["King_Hussein_Air_College"] = "King Hussein Air College", - ["Ercan"] = "Ercan", - ["Marj_Ruhayyil"] = "Marj Ruhayyil", - ["Tabqa"] = "Tabqa", - ["Marj_as_Sultan_South"] = "Marj as Sultan South", + ["Qabr_as_Sitt"] = "Qabr as Sitt", + ["Ramat_David"] = "Ramat David", + ["Rayak"] = "Rayak", ["Rene_Mouawad"] = "Rene Mouawad", - ["Minakh"] = "Minakh", + ["Rosh_Pina"] = "Rosh Pina", + ["Ruwayshid"] = "Ruwayshid", + ["Sanliurfa"] = "Sanliurfa", + ["Sayqal"] = "Sayqal", + ["Shayrat"] = "Shayrat", + ["Tabqa"] = "Tabqa", + ["Taftanaz"] = "Taftanaz", + ["Tal_Siman"] = "Tal Siman", + ["Tha_lah"] = "Tha'lah", + ["Tiyas"] = "Tiyas", + ["Wujah_Al_Hajar"] = "Wujah Al Hajar", } --- Airbases of the Mariana Islands map: -- --- * AIRBASE.MarianaIslands.Rota_Intl -- * AIRBASE.MarianaIslands.Andersen_AFB -- * AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl --- * AIRBASE.MarianaIslands.Saipan_Intl --- * AIRBASE.MarianaIslands.Tinian_Intl +-- * AIRBASE.MarianaIslands.North_West_Field -- * AIRBASE.MarianaIslands.Olf_Orote -- * AIRBASE.MarianaIslands.Pagan_Airstrip --- * AIRBASE.MarianaIslands.North_West_Field +-- * AIRBASE.MarianaIslands.Rota_Intl +-- * AIRBASE.MarianaIslands.Saipan_Intl +-- * AIRBASE.MarianaIslands.Tinian_Intl -- -- @field MarianaIslands AIRBASE.MarianaIslands = { - ["Rota_Intl"] = "Rota Intl", ["Andersen_AFB"] = "Andersen AFB", ["Antonio_B_Won_Pat_Intl"] = "Antonio B. Won Pat Intl", - ["Saipan_Intl"] = "Saipan Intl", - ["Tinian_Intl"] = "Tinian Intl", + ["North_West_Field"] = "North West Field", ["Olf_Orote"] = "Olf Orote", ["Pagan_Airstrip"] = "Pagan Airstrip", - ["North_West_Field"] = "North West Field", + ["Rota_Intl"] = "Rota Intl", + ["Saipan_Intl"] = "Saipan Intl", + ["Tinian_Intl"] = "Tinian Intl", } --- Airbases of the South Atlantic map: -- --- * AIRBASE.SouthAtlantic.Port_Stanley --- * AIRBASE.SouthAtlantic.Mount_Pleasant --- * AIRBASE.SouthAtlantic.San_Carlos_FOB --- * AIRBASE.SouthAtlantic.Rio_Grande --- * AIRBASE.SouthAtlantic.Rio_Gallegos --- * AIRBASE.SouthAtlantic.Ushuaia --- * AIRBASE.SouthAtlantic.Ushuaia_Helo_Port --- * AIRBASE.SouthAtlantic.Punta_Arenas --- * AIRBASE.SouthAtlantic.Pampa_Guanaco --- * AIRBASE.SouthAtlantic.San_Julian --- * AIRBASE.SouthAtlantic.Puerto_Williams --- * AIRBASE.SouthAtlantic.Puerto_Natales --- * AIRBASE.SouthAtlantic.El_Calafate --- * AIRBASE.SouthAtlantic.Puerto_Santa_Cruz --- * AIRBASE.SouthAtlantic.Comandante_Luis_Piedrabuena --- * AIRBASE.SouthAtlantic.Aerodromo_De_Tolhuin --- * AIRBASE.SouthAtlantic.Porvenir_Airfield --- * AIRBASE.SouthAtlantic.Almirante_Schroeders --- * AIRBASE.SouthAtlantic.Rio_Turbio --- * AIRBASE.SouthAtlantic.Rio_Chico --- * AIRBASE.SouthAtlantic.Franco_Bianco --- * AIRBASE.SouthAtlantic.Goose_Green --- * AIRBASE.SouthAtlantic.Hipico --- * AIRBASE.SouthAtlantic.CaletaTortel +-- * AIRBASE.Falklands.Almirante_Schroeders +-- * AIRBASE.Falklands.Caleta_Tortel +-- * AIRBASE.Falklands.Comandante_Luis_Piedrabuena +-- * AIRBASE.Falklands.Cullen +-- * AIRBASE.Falklands.El_Calafate +-- * AIRBASE.Falklands.Franco_Bianco +-- * AIRBASE.Falklands.Gobernador_Gregores +-- * AIRBASE.Falklands.Goose_Green +-- * AIRBASE.Falklands.Gull_Point +-- * AIRBASE.Falklands.Hipico_Flying_Club +-- * AIRBASE.Falklands.Mount_Pleasant +-- * AIRBASE.Falklands.O_Higgins +-- * AIRBASE.Falklands.Pampa_Guanaco +-- * AIRBASE.Falklands.Port_Stanley +-- * AIRBASE.Falklands.Porvenir +-- * AIRBASE.Falklands.Puerto_Natales +-- * AIRBASE.Falklands.Puerto_Santa_Cruz +-- * AIRBASE.Falklands.Puerto_Williams +-- * AIRBASE.Falklands.Punta_Arenas +-- * AIRBASE.Falklands.Rio_Chico +-- * AIRBASE.Falklands.Rio_Gallegos +-- * AIRBASE.Falklands.Rio_Grande +-- * AIRBASE.Falklands.Rio_Turbio +-- * AIRBASE.Falklands.San_Carlos_FOB +-- * AIRBASE.Falklands.San_Julian +-- * AIRBASE.Falklands.Tolhuin +-- * AIRBASE.Falklands.Ushuaia +-- * AIRBASE.Falklands.Ushuaia_Helo_Port -- --@field MarianaIslands AIRBASE.SouthAtlantic={ - ["Port_Stanley"]="Port Stanley", - ["Mount_Pleasant"]="Mount Pleasant", - ["San_Carlos_FOB"]="San Carlos FOB", - ["Rio_Grande"]="Rio Grande", - ["Rio_Gallegos"]="Rio Gallegos", - ["Ushuaia"]="Ushuaia", - ["Ushuaia_Helo_Port"]="Ushuaia Helo Port", - ["Punta_Arenas"]="Punta Arenas", - ["Pampa_Guanaco"]="Pampa Guanaco", - ["San_Julian"]="San Julian", - ["Puerto_Williams"]="Puerto Williams", - ["Puerto_Natales"]="Puerto Natales", - ["El_Calafate"]="El Calafate", - ["Puerto_Santa_Cruz"]="Puerto Santa Cruz", - ["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena", - ["Aerodromo_De_Tolhuin"]="Aerodromo De Tolhuin", - ["Porvenir_Airfield"]="Porvenir Airfield", - ["Almirante_Schroeders"]="Almirante Schroeders", - ["Rio_Turbio"]="Rio Turbio", - ["Rio_Chico"] = "Rio Chico", + ["Almirante_Schroeders"] = "Almirante Schroeders", + ["Caleta_Tortel"] = "Caleta Tortel", + ["Comandante_Luis_Piedrabuena"] = "Comandante Luis Piedrabuena", + ["Cullen"] = "Cullen", + ["El_Calafate"] = "El Calafate", ["Franco_Bianco"] = "Franco Bianco", + ["Gobernador_Gregores"] = "Gobernador Gregores", ["Goose_Green"] = "Goose Green", - ["Hipico_Flying_Club"] = "Hipico Flying Club", - ["CaletaTortel"] = "CaletaTortel", - ["Aeropuerto_de_Gobernador_Gregores"] = "Aeropuerto de Gobernador Gregores", - ["Aerodromo_O_Higgins"] = "Aerodromo O'Higgins", - ["Cullen_Airport"] = "Cullen Airport", ["Gull_Point"] = "Gull Point", + ["Hipico_Flying_Club"] = "Hipico Flying Club", + ["Mount_Pleasant"] = "Mount Pleasant", + ["O_Higgins"] = "O'Higgins", + ["Pampa_Guanaco"] = "Pampa Guanaco", + ["Port_Stanley"] = "Port Stanley", + ["Porvenir"] = "Porvenir", + ["Puerto_Natales"] = "Puerto Natales", + ["Puerto_Santa_Cruz"] = "Puerto Santa Cruz", + ["Puerto_Williams"] = "Puerto Williams", + ["Punta_Arenas"] = "Punta Arenas", + ["Rio_Chico"] = "Rio Chico", + ["Rio_Gallegos"] = "Rio Gallegos", + ["Rio_Grande"] = "Rio Grande", + ["Rio_Turbio"] = "Rio Turbio", + ["San_Carlos_FOB"] = "San Carlos FOB", + ["San_Julian"] = "San Julian", + ["Tolhuin"] = "Tolhuin", + ["Ushuaia"] = "Ushuaia", + ["Ushuaia_Helo_Port"] = "Ushuaia Helo Port", } --- Airbases of the Sinai map: -- --- * AIRBASE.Sinai.Abu_Suwayr --- * AIRBASE.Sinai.Sde_Dov --- * AIRBASE.Sinai.AzZaqaziq --- * AIRBASE.Sinai.Hatzor --- * AIRBASE.Sinai.Kedem --- * AIRBASE.Sinai.Nevatim --- * AIRBASE.Sinai.Cairo_International_Airport --- * AIRBASE.Sinai.Al_Ismailiyah --- * AIRBASE.Sinai.As_Salihiyah --- * AIRBASE.Sinai.Fayed --- * AIRBASE.Sinai.Bilbeis_Air_Base --- * AIRBASE.Sinai.Ramon_Airbase --- * AIRBASE.Sinai.Kibrit_Air_Base --- * AIRBASE.Sinai.El_Arish --- * AIRBASE.Sinai.Ovda --- * AIRBASE.Sinai.Melez --- * AIRBASE.Sinai.Al_Mansurah --- * AIRBASE.Sinai.Palmahim --- * AIRBASE.Sinai.Baluza --- * AIRBASE.Sinai.El_Gora --- * AIRBASE.Sinai.Difarsuwar_Airfield --- * AIRBASE.Sinai.Wadi_al_Jandali --- * AIRBASE.Sinai.St_Catherine --- * AIRBASE.Sinai.Tel_Nof --- * AIRBASE.Sinai.Abu_Rudeis --- * AIRBASE.Sinai.Inshas_Airbase --- * AIRBASE.Sinai.Ben_Gurion --- * AIRBASE.Sinai.Bir_Hasanah --- * AIRBASE.Sinai.Cairo_West +-- * AIRBASE.SinaiMap.Abu_Rudeis +-- * AIRBASE.SinaiMap.Abu_Suwayr +-- * AIRBASE.SinaiMap.Al_Ismailiyah +-- * AIRBASE.SinaiMap.Al_Mansurah +-- * AIRBASE.SinaiMap.As_Salihiyah +-- * AIRBASE.SinaiMap.AzZaqaziq +-- * AIRBASE.SinaiMap.Baluza +-- * AIRBASE.SinaiMap.Ben_Gurion +-- * AIRBASE.SinaiMap.Bilbeis_Air_Base +-- * AIRBASE.SinaiMap.Bir_Hasanah +-- * AIRBASE.SinaiMap.Cairo_International_Airport +-- * AIRBASE.SinaiMap.Cairo_West +-- * AIRBASE.SinaiMap.Difarsuwar_Airfield +-- * AIRBASE.SinaiMap.El_Arish +-- * AIRBASE.SinaiMap.El_Gora +-- * AIRBASE.SinaiMap.Fayed +-- * AIRBASE.SinaiMap.Hatzerim +-- * AIRBASE.SinaiMap.Hatzor +-- * AIRBASE.SinaiMap.Inshas_Airbase +-- * AIRBASE.SinaiMap.Kedem +-- * AIRBASE.SinaiMap.Kibrit_Air_Base +-- * AIRBASE.SinaiMap.Melez +-- * AIRBASE.SinaiMap.Nevatim +-- * AIRBASE.SinaiMap.Ovda +-- * AIRBASE.SinaiMap.Palmahim +-- * AIRBASE.SinaiMap.Ramon_Airbase +-- * AIRBASE.SinaiMap.Sde_Dov +-- * AIRBASE.SinaiMap.St_Catherine +-- * AIRBASE.SinaiMap.Tel_Nof +-- * AIRBASE.SinaiMap.Wadi_al_Jandali -- -- @field Sinai AIRBASE.Sinai = { - ["Hatzerim"] = "Hatzerim", + ["Abu_Rudeis"] = "Abu Rudeis", ["Abu_Suwayr"] = "Abu Suwayr", - ["Sde_Dov"] = "Sde Dov", - ["AzZaqaziq"] = "AzZaqaziq", - ["Hatzor"] = "Hatzor", - ["Kedem"] = "Kedem", - ["Nevatim"] = "Nevatim", - ["Cairo_International_Airport"] = "Cairo International Airport", ["Al_Ismailiyah"] = "Al Ismailiyah", - ["As_Salihiyah"] = "As Salihiyah", - ["Fayed"] = "Fayed", - ["Bilbeis_Air_Base"] = "Bilbeis Air Base", - ["Ramon_Airbase"] = "Ramon Airbase", - ["Kibrit_Air_Base"] = "Kibrit Air Base", - ["El_Arish"] = "El Arish", - ["Ovda"] = "Ovda", - ["Melez"] = "Melez", ["Al_Mansurah"] = "Al Mansurah", - ["Palmahim"] = "Palmahim", + ["As_Salihiyah"] = "As Salihiyah", + ["AzZaqaziq"] = "AzZaqaziq", ["Baluza"] = "Baluza", - ["El_Gora"] = "El Gora", + ["Ben_Gurion"] = "Ben-Gurion", + ["Bilbeis_Air_Base"] = "Bilbeis Air Base", + ["Bir_Hasanah"] = "Bir Hasanah", + ["Cairo_International_Airport"] = "Cairo International Airport", + ["Cairo_West"] = "Cairo West", ["Difarsuwar_Airfield"] = "Difarsuwar Airfield", - ["Wadi_al_Jandali"] = "Wadi al Jandali", + ["El_Arish"] = "El Arish", + ["El_Gora"] = "El Gora", + ["Fayed"] = "Fayed", + ["Hatzerim"] = "Hatzerim", + ["Hatzor"] = "Hatzor", + ["Inshas_Airbase"] = "Inshas Airbase", + ["Kedem"] = "Kedem", + ["Kibrit_Air_Base"] = "Kibrit Air Base", + ["Melez"] = "Melez", + ["Nevatim"] = "Nevatim", + ["Ovda"] = "Ovda", + ["Palmahim"] = "Palmahim", + ["Ramon_Airbase"] = "Ramon Airbase", + ["Sde_Dov"] = "Sde Dov", ["St_Catherine"] = "St Catherine", ["Tel_Nof"] = "Tel Nof", - ["Abu_Rudeis"] = "Abu Rudeis", - ["Inshas_Airbase"] = "Inshas Airbase", - ["Ben_Gurion"] = "Ben-Gurion", - ["Bir_Hasanah"] = "Bir Hasanah", - ["Cairo_West"] = "Cairo West", + ["Wadi_al_Jandali"] = "Wadi al Jandali", } --- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". From 51911d3292b2f99204f6c075af8ee64bd9fabe52 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 29 Feb 2024 19:00:33 +0100 Subject: [PATCH 42/73] Enhanced documentation of InitRandomizePositionZone InitRandomizePositionZone will not ensure, that every unit is placed within the zone! --- Moose Development/Moose/Wrapper/Group.lua | 743 +++++++++++----------- 1 file changed, 372 insertions(+), 371 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index a37c32132..a8afc6fbe 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -1,9 +1,9 @@ --- **Wrapper** - GROUP wraps the DCS Class Group objects. --- +-- -- === --- +-- -- The @{#GROUP} class is a wrapper class to handle the DCS Group objects. --- +-- -- ## Features: -- -- * Support all DCS Group APIs. @@ -14,27 +14,27 @@ -- **IMPORTANT: ONE SHOULD NEVER SANITIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** -- -- === --- +-- -- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{Core.Spawn} class). --- +-- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. -- -- The GROUP methods will reference the DCS Group object by name when it is needed during API execution. -- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and may log an exception in the DCS.log file. --- +-- -- === --- +-- -- ### Author: **FlightControl** --- --- ### Contributions: --- +-- +-- ### Contributions: +-- -- * **Entropy**, **Afinegan**: Came up with the requirement for AIOnOff(). -- * **Applevangelist**: various --- +-- -- === --- +-- -- @module Wrapper.Group -- @image Wrapper_Group.JPG @@ -45,9 +45,9 @@ --- Wrapper class of the DCS world Group object. --- +-- -- ## Finding groups --- +-- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: -- -- * @{#GROUP.Find}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group object. @@ -57,28 +57,28 @@ -- -- ## Tasking of groups -- --- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}). +-- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}). -- See the @{Wrapper.Controllable} task methods section for a description of the task methods. -- -- But here is an example how a group can be assigned a task. --- +-- -- This test demonstrates the use(s) of the SwitchWayPoint method of the GROUP class. --- +-- -- First we look up the objects. We create a GROUP object `HeliGroup`, using the @{#GROUP:FindByName}() method, looking up the `"Helicopter"` group object. -- Same for the `"AttackGroup"`. --- +-- -- local HeliGroup = GROUP:FindByName( "Helicopter" ) -- local AttackGroup = GROUP:FindByName( "AttackGroup" ) --- --- Now we retrieve the @{Wrapper.Unit#UNIT} objects of the `AttackGroup` object, using the method `:GetUnits()`. --- +-- +-- Now we retrieve the @{Wrapper.Unit#UNIT} objects of the `AttackGroup` object, using the method `:GetUnits()`. +-- -- local AttackUnits = AttackGroup:GetUnits() --- +-- -- Tasks are actually text strings that we build using methods of GROUP. --- So first, we declare an list of `Tasks`. --- +-- So first, we declare an list of `Tasks`. +-- -- local Tasks = {} --- +-- -- Now we loop over the `AttackUnits` using a for loop. -- We retrieve the `AttackUnit` using the `AttackGroup:GetUnit()` method. -- Each `AttackUnit` found, will be attacked by `HeliGroup`, using the method `HeliGroup:TaskAttackUnit()`. @@ -86,74 +86,74 @@ -- The code will assign the task string command to the next element in the `Task` list, using `Tasks[#Tasks+1]`. -- This little code will take the count of `Task` using `#` operator, and will add `1` to the count. -- This result will be the index of the `Task` element. --- +-- -- for i = 1, #AttackUnits do -- local AttackUnit = AttackGroup:GetUnit( i ) -- Tasks[#Tasks+1] = HeliGroup:TaskAttackUnit( AttackUnit ) -- end --- +-- -- Once these tasks have been executed, a function `_Resume` will be called ... --- +-- -- Tasks[#Tasks+1] = HeliGroup:TaskFunction( "_Resume", { "''" } ) --- +-- -- -- @param Wrapper.Group#GROUP HeliGroup -- function _Resume( HeliGroup ) -- env.info( '_Resume' ) --- +-- -- HeliGroup:MessageToAll( "Resuming",10,"Info") -- end --- +-- -- Now here is where the task gets assigned! -- Using `HeliGroup:PushTask`, the task is pushed onto the task queue of the group `HeliGroup`. -- Since `Tasks` is an array of tasks, we use the `HeliGroup:TaskCombo` method to execute the tasks. -- The `HeliGroup:PushTask` method can receive a delay parameter in seconds. -- In the example, `30` is given as a delay. --- --- --- HeliGroup:PushTask( +-- +-- +-- HeliGroup:PushTask( -- HeliGroup:TaskCombo( -- Tasks --- ), 30 --- ) --- +-- ), 30 +-- ) +-- -- That's it! -- But again, please refer to the @{Wrapper.Controllable} task methods section for a description of the different task methods that are available. --- --- +-- +-- -- -- ### Obtain the mission from group templates --- +-- -- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another: --- +-- -- * @{Wrapper.Controllable#CONTROLLABLE.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. -- -- ## GROUP Command methods -- -- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} command methods section for a description of the command methods. --- +-- -- ## GROUP option methods -- -- A GROUP is a @{Wrapper.Controllable}. See the @{Wrapper.Controllable} option methods section for a description of the option methods. --- +-- -- ## GROUP Zone validation methods --- +-- -- The group can be validated whether it is completely, partly or not within a @{Core.Zone}. -- Use the following Zone validation methods on the group: --- +-- -- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Core.Zone}. -- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Core.Zone}. -- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Core.Zone}. --- +-- -- The zone can be of any @{Core.Zone} class derived from @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. --- +-- -- ## GROUP AI methods --- +-- -- A GROUP has AI methods to control the AI activation. --- +-- -- * @{#GROUP.SetAIOnOff}(): Turns the GROUP AI On or Off. -- * @{#GROUP.SetAIOn}(): Turns the GROUP AI On. -- * @{#GROUP.SetAIOff}(): Turns the GROUP AI Off. --- +-- -- @field #GROUP GROUP GROUP = { ClassName = "GROUP", @@ -255,7 +255,7 @@ function GROUP:NewTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID if not _DATABASE.GROUPS[GroupName] then _DATABASE.GROUPS[GroupName] = self - end + end self:SetEventPriority( 4 ) return self @@ -270,9 +270,9 @@ end function GROUP:Register( GroupName ) local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP - + self.GroupName = GroupName - + self:SetEventPriority( 4 ) return self end @@ -308,20 +308,20 @@ end -- -- Find a group with a partial group name -- local grp = GROUP:FindByMatching( "Apple" ) -- -- will return e.g. a group named "Apple-1-1" --- +-- -- -- using a pattern -- local grp = GROUP:FindByMatching( ".%d.%d$" ) -- -- will return the first group found ending in "-1-1" to "-9-9", but not e.g. "-10-1" function GROUP:FindByMatching( Pattern ) local GroupFound = nil - + for name,group in pairs(_DATABASE.GROUPS) do if string.match(name, Pattern ) then GroupFound = group break end end - + return GroupFound end @@ -333,19 +333,19 @@ end -- -- Find all group with a partial group name -- local grptable = GROUP:FindAllByMatching( "Apple" ) -- -- will return all groups with "Apple" in the name --- +-- -- -- using a pattern -- local grp = GROUP:FindAllByMatching( ".%d.%d$" ) -- -- will return the all groups found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10" function GROUP:FindAllByMatching( Pattern ) local GroupsFound = {} - + for name,group in pairs(_DATABASE.GROUPS) do if string.match(name, Pattern ) then GroupsFound[#GroupsFound+1] = group end end - + return GroupsFound end @@ -366,12 +366,12 @@ end --- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. -- @param Wrapper.Positionable#POSITIONABLE self --- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive. +-- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive. function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() self:F2( self.PositionableName ) local DCSPositionable = self:GetDCSObject() - + if DCSPositionable then local unit = DCSPositionable:getUnits()[1] if unit then @@ -380,19 +380,19 @@ function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3 return PositionablePosition end end - + return nil end --- Returns if the group is alive. -- The Group must: --- +-- -- * Exist at run-time. -- * Has at least one unit. --- +-- -- When the first @{Wrapper.Unit} of the group is active, it will return true. -- If the first @{Wrapper.Unit} of the group is inactive, it will return false. --- +-- -- @param #GROUP self -- @return #boolean `true` if the group is alive *and* active, `false` if the group is alive but inactive or `#nil` if the group does not exist anymore. function GROUP:IsAlive() @@ -416,17 +416,17 @@ end --- Returns if the group is activated. -- @param #GROUP self --- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive. +-- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive. function GROUP:IsActive() self:F2( self.GroupName ) local DCSGroup = self:GetDCSObject() -- DCS#Group - + if DCSGroup then local unit = DCSGroup:getUnit(1) if unit then local GroupIsActive = unit:isActive() - return GroupIsActive + return GroupIsActive end end @@ -454,21 +454,21 @@ end -- -- Ship unit example: destroy the Ship silently. -- Ship = GROUP:FindByName( "Ship" ) -- Ship:Destroy() --- +-- -- @usage -- -- Destroy without event generation example. -- Ship = GROUP:FindByName( "Boat" ) -- Ship:Destroy( false ) -- Don't generate an event upon destruction. --- +-- function GROUP:Destroy( GenerateEvent, delay ) self:F2( self.GroupName ) - + if delay and delay>0 then self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent) else local DCSGroup = self:GetDCSObject() - + if DCSGroup then for Index, UnitData in pairs( DCSGroup:getUnits() ) do if GenerateEvent and GenerateEvent == true then @@ -488,19 +488,19 @@ function GROUP:Destroy( GenerateEvent, delay ) DCSGroup = nil end end - + return nil end --- Returns category of the DCS Group. Returns one of --- +-- -- * Group.Category.AIRPLANE -- * Group.Category.HELICOPTER -- * Group.Category.GROUND -- * Group.Category.SHIP -- * Group.Category.TRAIN --- +-- -- @param #GROUP self -- @return DCS#Group.Category The category ID. function GROUP:GetCategory() @@ -584,12 +584,12 @@ function GROUP:HasAttribute(attribute, all) -- Get all units of the group. local _units=self:GetUnits() - + if _units then - + local _allhave=true local _onehas=false - + for _,_unit in pairs(_units) do local _unit=_unit --Wrapper.Unit#UNIT if _unit then @@ -599,17 +599,17 @@ function GROUP:HasAttribute(attribute, all) else _allhave=false end - end + end end - + if all==true then return _allhave else return _onehas end - + end - + return nil end @@ -622,27 +622,27 @@ function GROUP:GetSpeedMax() local DCSGroup = self:GetDCSObject() if DCSGroup then - + local Units=self:GetUnits() - + local speedmax=nil - + for _,unit in pairs(Units) do local unit=unit --Wrapper.Unit#UNIT - + local speed=unit:GetSpeedMax() - + if speedmax==nil or speed threatlevelMax then threatlevelMax=threatlevel @@ -2371,12 +2372,12 @@ end --- Returns true if the first unit of the GROUP is in the air. -- @param Wrapper.Group#GROUP self --- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive. +-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive. function GROUP:InAir() self:F2( self.GroupName ) local DCSGroup = self:GetDCSObject() - + if DCSGroup then local DCSUnit = DCSGroup:getUnit(1) if DCSUnit then @@ -2385,7 +2386,7 @@ function GROUP:InAir() return GroupInAir end end - + return nil end @@ -2398,58 +2399,58 @@ function GROUP:IsAirborne(AllUnits) -- Get all units of the group. local units=self:GetUnits() - + if units then - + if AllUnits then - + --- We want to know if ALL units are airborne. for _,_unit in pairs(units) do local unit=_unit --Wrapper.Unit#UNIT - + if unit then - + -- Unit in air or not. local inair=unit:InAir() - + -- At least one unit is not in air. if not inair then return false end end - + end - + -- All units are in air. return true - + else - + --- We want to know if ANY unit is airborne. for _,_unit in pairs(units) do local unit=_unit --Wrapper.Unit#UNIT - + if unit then - + -- Unit in air or not. local inair=unit:InAir() - + if inair then -- At least one unit is in air. return true end - + end - + -- No unit is in air. return false - + end end end - + return nil end @@ -2458,17 +2459,17 @@ end --- Returns the DCS descriptor table of the nth unit of the group. -- @param #GROUP self -- @param #number n (Optional) The number of the unit for which the dscriptor is returned. --- @return DCS#Object.Desc The descriptor of the first unit of the group or #nil if the group does not exist any more. +-- @return DCS#Object.Desc The descriptor of the first unit of the group or #nil if the group does not exist any more. function GROUP:GetDCSDesc(n) -- Default. n=n or 1 - + local unit=self:GetUnit(n) if unit and unit:IsAlive()~=nil then local desc=unit:GetDesc() return desc end - + return nil end @@ -2530,14 +2531,14 @@ function GROUP:GetAttribute() elseif bomber then attribute=GROUP.Attribute.AIR_BOMBER elseif awacs then - attribute=GROUP.Attribute.AIR_AWACS + attribute=GROUP.Attribute.AIR_AWACS elseif transportplane then attribute=GROUP.Attribute.AIR_TRANSPORTPLANE elseif tanker then attribute=GROUP.Attribute.AIR_TANKER -- helos elseif attackhelicopter then - attribute=GROUP.Attribute.AIR_ATTACKHELO + attribute=GROUP.Attribute.AIR_ATTACKHELO elseif transporthelo then attribute=GROUP.Attribute.AIR_TRANSPORTHELO elseif uav then @@ -2550,15 +2551,15 @@ function GROUP:GetAttribute() elseif aaa then attribute=GROUP.Attribute.GROUND_AAA elseif artillery then - attribute=GROUP.Attribute.GROUND_ARTILLERY + attribute=GROUP.Attribute.GROUND_ARTILLERY elseif tank then - attribute=GROUP.Attribute.GROUND_TANK + attribute=GROUP.Attribute.GROUND_TANK elseif ifv then - attribute=GROUP.Attribute.GROUND_IFV + attribute=GROUP.Attribute.GROUND_IFV elseif apc then attribute=GROUP.Attribute.GROUND_APC elseif infantry then - attribute=GROUP.Attribute.GROUND_INFANTRY + attribute=GROUP.Attribute.GROUND_INFANTRY elseif truck then attribute=GROUP.Attribute.GROUND_TRUCK elseif train then @@ -2591,67 +2592,67 @@ end do -- Route methods - --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. + --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. -- The following things are to be taken into account: - -- + -- -- * The group is respawned to achieve the RTB, there may be side artefacts as a result of this. (Like weapons suddenly come back). -- * A group consisting out of more than one unit, may rejoin formation when respawned. -- * A speed can be given in km/h. If no speed is specified, the maximum speed of the first unit will be taken to return to base. -- * When there is no @{Wrapper.Airbase} object specified, the group will return to the home base if the route of the group is pinned at take-off or at landing to a base. -- * When there is no @{Wrapper.Airbase} object specified and the group route is not pinned to any airbase, it will return to the nearest airbase. - -- + -- -- @param #GROUP self -- @param Wrapper.Airbase#AIRBASE RTBAirbase (optional) The @{Wrapper.Airbase} to return to. If blank, the controllable will return to the nearest friendly airbase. - -- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected. + -- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected. -- @return #GROUP self function GROUP:RouteRTB( RTBAirbase, Speed ) self:F( { RTBAirbase:GetName(), Speed } ) - + local DCSGroup = self:GetDCSObject() - + if DCSGroup then - + if RTBAirbase then - + -- If speed is not given take 80% of max speed. local Speed=Speed or self:GetSpeedMax()*0.8 - + -- Curent (from) waypoint. local coord=self:GetCoordinate() local PointFrom=coord:WaypointAirTurningPoint(nil, Speed) - + -- Airbase coordinate. --local PointAirbase=RTBAirbase:GetCoordinate():SetAltitude(coord.y):WaypointAirTurningPoint(nil ,Speed) - + -- Landing waypoint. More general than prev version since it should also work with FAPRS and ships. - local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase) - + local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase) + -- Waypoint table. local Points={PointFrom, PointLanding} --local Points={PointFrom, PointAirbase, PointLanding} - + -- Debug info. self:T3(Points) -- Get group template. local Template=self:GetTemplate() - + -- Set route points. Template.route.points=Points - + -- Respawn the group. self:Respawn(Template, true) - + -- Route the group or this will not work. self:Route(Points) else - + -- Clear all tasks. self:ClearTasks() - + end end - + return self end @@ -2670,20 +2671,20 @@ do -- Event Handling -- @param #function EventFunction (optional) The function to be called when the event occurs for the GROUP. -- @return #GROUP function GROUP:HandleEvent( Event, EventFunction, ... ) - + self:EventDispatcher():OnEventForGroup( self:GetName(), EventFunction, self, Event, ... ) - + return self end - + --- UnSubscribe to a DCS event. -- @param #GROUP self -- @param Core.Event#EVENTS Event -- @return #GROUP function GROUP:UnHandleEvent( Event ) - + self:EventDispatcher():RemoveEvent( self, Event ) - + return self end @@ -2691,13 +2692,13 @@ do -- Event Handling -- @param #GROUP self -- @return #GROUP function GROUP:ResetEvents() - + self:EventDispatcher():Reset( self ) - + for UnitID, UnitData in pairs( self:GetUnits() ) do UnitData:ResetEvents() end - + return self end @@ -2710,11 +2711,11 @@ do -- Players -- @return #table The group has players, an array of player names is returned. -- @return #nil The group has no players function GROUP:GetPlayerNames() - + local HasPlayers = false - + local PlayerNames = {} - + local Units = self:GetUnits() for UnitID, UnitData in pairs( Units ) do local Unit = UnitData -- Wrapper.Unit#UNIT @@ -2723,14 +2724,14 @@ do -- Players PlayerNames = PlayerNames or {} table.insert( PlayerNames, PlayerName ) HasPlayers = true - end + end end - if HasPlayers == true then + if HasPlayers == true then self:F2( PlayerNames ) return PlayerNames end - + return nil end @@ -2739,35 +2740,35 @@ do -- Players -- @param #GROUP self -- @return #number The amount of players. function GROUP:GetPlayerCount() - + local PlayerCount = 0 - + local Units = self:GetUnits() for UnitID, UnitData in pairs( Units or {} ) do local Unit = UnitData -- Wrapper.Unit#UNIT local PlayerName = Unit:GetPlayerName() if PlayerName and PlayerName ~= "" then PlayerCount = PlayerCount + 1 - end + end end return PlayerCount end - + end --- GROUND - Switch on/off radar emissions for the group. -- @param #GROUP self -- @param #boolean switch If true, emission is enabled. If false, emission is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:EnableEmission(switch) self:F2( self.GroupName ) local switch = switch or false - + local DCSUnit = self:GetDCSObject() - + if DCSUnit then - + DCSUnit:enableEmission(switch) end @@ -2778,7 +2779,7 @@ end --- Switch on/off invisible flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:SetCommandInvisible(switch) return self:CommandSetInvisible(switch) end @@ -2786,7 +2787,7 @@ end --- Switch on/off invisible flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:CommandSetInvisible(switch) self:F2( self.GroupName ) if switch==nil then @@ -2800,7 +2801,7 @@ end --- Switch on/off immortal flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:SetCommandImmortal(switch) return self:CommandSetImmortal(switch) end @@ -2808,7 +2809,7 @@ end --- Switch on/off immortal flag for the group. -- @param #GROUP self -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. --- @return #GROUP self +-- @return #GROUP self function GROUP:CommandSetImmortal(switch) self:F2( self.GroupName ) if switch==nil then @@ -2855,17 +2856,17 @@ function GROUP:GetHighestThreat() if tl>maxtl then maxtl=tl threat=unit - end + end end end - return threat, maxtl + return threat, maxtl end return nil, nil end ---- Get TTS friendly, optionally customized callsign mainly for **player groups**. A customized callsign is taken from the #GROUP name, after an optional '#' sign, e.g. "Aerial 1-1#Ghostrider" resulting in "Ghostrider 9", or, +--- Get TTS friendly, optionally customized callsign mainly for **player groups**. A customized callsign is taken from the #GROUP name, after an optional '#' sign, e.g. "Aerial 1-1#Ghostrider" resulting in "Ghostrider 9", or, -- if that isn't available, from the playername, as set in the mission editor main screen under Logbook, after an optional '|' sign (actually, more of a personal call sign), e.g. "Apple|Moose" results in "Moose 9 1". Options see below. -- @param #GROUP self -- @param #boolean ShortCallsign Return a shortened customized callsign, i.e. "Ghostrider 9" and not "Ghostrider 9 1" @@ -2877,7 +2878,7 @@ end -- -- suppose there are three groups with one (client) unit each: -- -- Slot 1 -- with mission editor callsign Enfield-1 -- -- Slot 2 # Apollo 403 -- with mission editor callsign Enfield-2 --- -- Slot 3 | Apollo -- with mission editor callsign Enfield-3 +-- -- Slot 3 | Apollo -- with mission editor callsign Enfield-3 -- -- Slot 4 | Apollo -- with mission editor callsign Devil-4 -- -- and suppose these Custom CAP Flight Callsigns for use with TTS are set -- mygroup:GetCustomCallSign(true,false,{ @@ -2939,7 +2940,7 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) end return callsign end - + -- AI or not personalized if ShortCallsign then callsign = callsignroot.." "..callnumbermajor -- Uzi/Victory 9 @@ -2949,7 +2950,7 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) --self:I("Generated Callsign = " .. callsign) end - + return callsign end @@ -2963,21 +2964,21 @@ end -- @param #number LastWaypoint (optional) Waypoint number of carrier group that when reached, ends the recovery tanker task. -- @return #GROUP self function GROUP:SetAsRecoveryTanker(CarrierGroup,Speed,ToKIAS,Altitude,Delay,LastWaypoint) - + local speed = ToKIAS == true and UTILS.KnotsToAltKIAS(Speed,Altitude) or Speed speed = UTILS.KnotsToMps(speed) - + local alt = UTILS.FeetToMeters(Altitude) local delay = Delay or 1 - + local task = self:TaskRecoveryTanker(CarrierGroup,speed,alt,LastWaypoint) self:SetTask(task,delay) - + local tankertask = self:EnRouteTaskTanker() self:PushTask(tankertask,delay+2) - - return self + + return self end --- Get a list of Link16 S/TN data from a GROUP. Can (as of Nov 2023) be obtained from F-18, F-16, F-15E (not the user flyable one) and A-10C-II groups. @@ -3040,8 +3041,8 @@ function GROUP:IsAAA() local desc = unit:GetDesc() or {} local attr = desc.attributes or {} if unit:HasSEAD() then return false end - if attr["AAA"] or attr["SAM related"] then - issam = true + if attr["AAA"] or attr["SAM related"] then + issam = true end end return issam From 0f30f3b1a083b46eeb5a12e01477179548d8fbcf Mon Sep 17 00:00:00 2001 From: kaltokri Date: Thu, 29 Feb 2024 19:52:23 +0100 Subject: [PATCH 43/73] Added link to Wrapper/Group demo missions --- Moose Development/Moose/Wrapper/Group.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index a8afc6fbe..6beaa3b00 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -26,6 +26,10 @@ -- -- === -- +-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Group) +-- +-- === +-- -- ### Author: **FlightControl** -- -- ### Contributions: From d64dadd9a9a7fdbebc4ed3824e6bfda024b4314e Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 1 Mar 2024 08:23:28 +0100 Subject: [PATCH 44/73] docu --- Moose Development/Moose/Core/Zone.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index ea5e1efa1..12df09b32 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -1180,7 +1180,7 @@ function ZONE_RADIUS:RemoveJunk() return n end ---- Count the number of different coalitions inside the zone. +--- Get a table of scanned units. -- @param #ZONE_RADIUS self -- @return #table Table of DCS units and DCS statics inside the zone. function ZONE_RADIUS:GetScannedUnits() @@ -1215,7 +1215,7 @@ function ZONE_RADIUS:GetScannedSetUnit() return SetUnit end ---- Get a set of scanned units. +--- Get a set of scanned groups. -- @param #ZONE_RADIUS self -- @return Core.Set#SET_GROUP Set of groups. function ZONE_RADIUS:GetScannedSetGroup() From 71b5492903b749337c4725bfb2b4471e41377867 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 1 Mar 2024 08:34:52 +0100 Subject: [PATCH 45/73] Scoring --- .../Moose/Functional/Scoring.lua | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index 625103d9e..5a8e6d87f 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -229,7 +229,7 @@ SCORING = { ClassID = 0, Players = {}, AutoSave = true, - version = "1.18.1" + version = "1.18.2" } local _SCORINGCoalition = { @@ -1058,7 +1058,7 @@ function SCORING:_EventOnHit( Event ) PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0 PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0 PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT - -- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth + -- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth if PlayerHit.UNIT.ThreatType == nil then PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel() -- if this fails for some reason, set a good default value @@ -1169,7 +1169,7 @@ function SCORING:_EventOnHit( Event ) PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0 PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0 PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT - -- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth + -- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth if PlayerHit.UNIT.ThreatType == nil then PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel() -- if this fails for some reason, set a good default value @@ -1316,17 +1316,17 @@ function SCORING:_EventOnDeadOrCrash( Event ) TargetDestroy.PenaltyDestroy = TargetDestroy.PenaltyDestroy + 1 - self:OnKillPvP(Player, TargetPlayerName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty) + --self:OnKillPvP(PlayerName, TargetPlayerName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty) if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player - self:OnKillPvP(Player, TargetPlayerName, true) + self:OnKillPvP(PlayerName, TargetPlayerName, true) MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. "Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) else - self:OnKillPvE(Player, TargetUnitName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty) + self:OnKillPvE(PlayerName, TargetUnitName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty) MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. "Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) @@ -1963,23 +1963,23 @@ end --- Handles the event when one player kill another player -- @param #SCORING self --- @param #Wrapper.Client#CLIENT Player the atacking player --- @param #string TargetPlayerName the name of the killed player +-- @param #string PlayerName The attacking player +-- @param #string TargetPlayerName The name of the killed player -- @param #boolean IsTeamKill true if this kill was a team kill --- @param #number TargetThreatLevel Thread level of the target --- @param #number PlayerThreatLevelThread level of the player +-- @param #number TargetThreatLevel Threat level of the target +-- @param #number PlayerThreatLevel Threat level of the player -- @param #number Score The score based on both threat levels -function SCORING:OnKillPvP(Player, TargetPlayerName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score) +function SCORING:OnKillPvP(PlayerName, TargetPlayerName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score) end --- Handles the event when one player kill another player -- @param #SCORING self --- @param #Wrapper.Client#CLIENT Player the atacking player +-- @param #string PlayerName The attacking player -- @param #string TargetUnitName the name of the killed unit -- @param #boolean IsTeamKill true if this kill was a team kill --- @param #number TargetThreatLevel Thread level of the target --- @param #number PlayerThreatLevelThread level of the player +-- @param #number TargetThreatLevel Threat level of the target +-- @param #number PlayerThreatLevel Threat level of the player -- @param #number Score The score based on both threat levels -function SCORING:OnKillPvE(Player, TargetUnitName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score) +function SCORING:OnKillPvE(PlayerName, TargetUnitName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score) end From 57ce6bcec2c62de42049c0a4cbc7db387339e5e5 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Fri, 1 Mar 2024 17:22:22 +0100 Subject: [PATCH 46/73] Switched demo mission link in Core/SpawnStatic and Wrapper/Storage --- Moose Development/Moose/Core/SpawnStatic.lua | 150 +++++++++---------- Moose Development/Moose/Wrapper/Storage.lua | 106 ++++++------- 2 files changed, 128 insertions(+), 128 deletions(-) diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index 77543f5fc..f6a082ddf 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -1,36 +1,36 @@ --- **Core** - Spawn statics. --- +-- -- === --- +-- -- ## Features: --- +-- -- * Spawn new statics from a static already defined in the mission editor. -- * Spawn new statics from a given template. -- * Spawn new statics from a given type. -- * Spawn with a custom heading and location. -- * Spawn within a zone. -- * Spawn statics linked to units, .e.g on aircraft carriers. --- --- === --- --- # Demo Missions --- --- ## [SPAWNSTATIC Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Core/SpawnStatic) -- --- -- === --- +-- +-- # Demo Missions +-- +-- ## [SPAWNSTATIC Demo Missions](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Core/SpawnStatic) +-- +-- +-- === +-- -- # YouTube Channel --- +-- -- ## No videos yet! --- +-- -- === --- +-- -- ### Author: **FlightControl** -- ### Contributions: **funkyfranky** --- +-- -- === --- +-- -- @module Core.SpawnStatic -- @image Core_Spawnstatic.JPG @@ -58,37 +58,37 @@ --- Allows to spawn dynamically new @{Wrapper.Static}s into your mission. --- --- Through creating a copy of an existing static object template as defined in the Mission Editor (ME), SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), +-- +-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME), SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), -- and "copy" these properties to create a new static object and place it at the desired coordinate. --- --- New spawned @{Wrapper.Static}s get **the same name** as the name of the template Static, or gets the given name when a new name is provided at the Spawn method. +-- +-- New spawned @{Wrapper.Static}s get **the same name** as the name of the template Static, or gets the given name when a new name is provided at the Spawn method. -- By default, spawned @{Wrapper.Static}s will follow a naming convention at run-time: --- +-- -- * Spawned @{Wrapper.Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**, and _nnn_ is a **counter from 0 to 99999**. --- +-- -- # SPAWNSTATIC Constructors --- +-- -- Firstly, we need to create a SPAWNSTATIC object that will be used to spawn new statics into the mission. There are three ways to do this. --- +-- -- ## Use another Static --- +-- -- A new SPAWNSTATIC object can be created using another static by the @{#SPAWNSTATIC.NewFromStatic}() function. All parameters such as position, heading, country will be initialized -- from the static. --- +-- -- ## From a Template --- +-- -- A SPAWNSTATIC object can also be created from a template table using the @{#SPAWNSTATIC.NewFromTemplate}(SpawnTemplate, CountryID) function. All parameters are taken from the template. --- +-- -- ## From a Type --- +-- -- A very basic method is to create a SPAWNSTATIC object by just giving the type of the static. All parameters must be initialized from the InitXYZ functions described below. Otherwise default values -- are used. For example, if no spawn coordinate is given, the static will be created at the origin of the map. --- +-- -- # Setting Parameters --- +-- -- Parameters such as the spawn position, heading, country etc. can be set via :Init*XYZ* functions. Note that these functions must be given before the actual spawn command! --- +-- -- * @{#SPAWNSTATIC.InitCoordinate}(Coordinate) Sets the coordinate where the static is spawned. Statics are always spawnd on the ground. -- * @{#SPAWNSTATIC.InitHeading}(Heading) sets the orientation of the static. -- * @{#SPAWNSTATIC.InitLivery}(LiveryName) sets the livery of the static. Not all statics support this. @@ -99,17 +99,17 @@ -- * @{#SPAWNSTATIC.InitLinkToUnit}(Unit, OffsetX, OffsetY, OffsetAngle) links the static to a unit, e.g. to an aircraft carrier. -- -- # Spawning the Statics --- +-- -- Once the SPAWNSTATIC object is created and parameters are initialized, the spawn command can be given. There are different methods where some can be used to directly set parameters -- such as position and heading. --- +-- -- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**! --- +-- -- @field #SPAWNSTATIC SPAWNSTATIC --- +-- SPAWNSTATIC = { ClassName = "SPAWNSTATIC", SpawnIndex = 0, @@ -139,9 +139,9 @@ SPAWNSTATIC = { function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID) local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC - + local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate(SpawnTemplateName) - + if TemplateStatic then self.SpawnTemplatePrefix = SpawnTemplateName self.TemplateStaticUnit = UTILS.DeepCopy(TemplateStatic.units[1]) @@ -166,11 +166,11 @@ end function SPAWNSTATIC:NewFromTemplate(SpawnTemplate, CountryID) local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC - + self.TemplateStaticUnit = UTILS.DeepCopy(SpawnTemplate) self.SpawnTemplatePrefix = SpawnTemplate.name self.CountryID = CountryID or country.id.USA - + return self end @@ -189,7 +189,7 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID) self.InitStaticCategory=StaticCategory self.CountryID=CountryID or country.id.USA self.SpawnTemplatePrefix=self.InitStaticType - + self.InitStaticCoordinate=COORDINATE:New(0, 0, 0) self.InitStaticHeading=0 @@ -291,7 +291,7 @@ function SPAWNSTATIC:InitCountry(CountryID) return self end ---- Initialize name prefix statics get. This will be appended by "#0001", "#0002" etc. +--- Initialize name prefix statics get. This will be appended by "#0001", "#0002" etc. -- @param #SPAWNSTATIC self -- @param #string NamePrefix Name prefix of statics spawned. Will append #0001, etc to the name. -- @return #SPAWNSTATIC self @@ -327,13 +327,13 @@ function SPAWNSTATIC:Spawn(Heading, NewName) if Heading then self.InitStaticHeading=Heading end - + if NewName then self.InitStaticName=NewName end return self:_SpawnStatic(self.TemplateStaticUnit, self.CountryID) - + end --- Creates a new @{Wrapper.Static} from a POINT_VEC2. @@ -347,7 +347,7 @@ function SPAWNSTATIC:SpawnFromPointVec2(PointVec2, Heading, NewName) local vec2={x=PointVec2:GetX(), y=PointVec2:GetY()} local Coordinate=COORDINATE:NewFromVec2(vec2) - + return self:SpawnFromCoordinate(Coordinate, Heading, NewName) end @@ -362,11 +362,11 @@ function SPAWNSTATIC:SpawnFromCoordinate(Coordinate, Heading, NewName) -- Set up coordinate. self.InitStaticCoordinate=Coordinate - + if Heading then self.InitStaticHeading=Heading end - + if NewName then self.InitStaticName=NewName end @@ -385,7 +385,7 @@ function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName) -- Spawn the new static at the center of the zone. local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName ) - + return Static end @@ -399,45 +399,45 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID) Template=Template or {} local CountryID=CountryID or self.CountryID - + if self.InitStaticType then Template.type=self.InitStaticType end - + if self.InitStaticCategory then Template.category=self.InitStaticCategory end - - if self.InitStaticCoordinate then - Template.x = self.InitStaticCoordinate.x + + if self.InitStaticCoordinate then + Template.x = self.InitStaticCoordinate.x Template.y = self.InitStaticCoordinate.z - Template.alt = self.InitStaticCoordinate.y + Template.alt = self.InitStaticCoordinate.y end - + if self.InitStaticHeading then - Template.heading = math.rad(self.InitStaticHeading) + Template.heading = math.rad(self.InitStaticHeading) end if self.InitStaticShape then Template.shape_name=self.InitStaticShape end - + if self.InitStaticLivery then Template.livery_id=self.InitStaticLivery end - + if self.InitStaticDead~=nil then Template.dead=self.InitStaticDead end - + if self.InitStaticCargo~=nil then Template.canCargo=self.InitStaticCargo end - + if self.InitStaticCargoMass~=nil then Template.mass=self.InitStaticCargoMass end - + if self.InitLinkUnit then Template.linkUnit=self.InitLinkUnit:GetID() Template.linkOffset=true @@ -446,45 +446,45 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID) Template.offsets.x=self.InitOffsetX Template.offsets.angle=self.InitOffsetAngle and math.rad(self.InitOffsetAngle) or 0 end - + if self.InitFarp then Template.heliport_callsign_id = self.InitFarpCallsignID Template.heliport_frequency = self.InitFarpFreq Template.heliport_modulation = self.InitFarpModu Template.unitId=nil end - + -- Increase spawn index counter. self.SpawnIndex = self.SpawnIndex + 1 - + -- Name of the spawned static. Template.name = self.InitStaticName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex) -- Add and register the new static. local mystatic=_DATABASE:AddStatic(Template.name) - + -- Debug output. self:T(Template) - + -- Add static to the game. local Static=nil --DCS#StaticObject - + if self.InitFarp then - - local TemplateGroup={} + + local TemplateGroup={} TemplateGroup.units={} TemplateGroup.units[1]=Template - + TemplateGroup.visible=true TemplateGroup.hidden=false TemplateGroup.x=Template.x TemplateGroup.y=Template.y TemplateGroup.name=Template.name - self:T("Spawning FARP") + self:T("Spawning FARP") self:T({Template=Template}) self:T({TemplateGroup=TemplateGroup}) - + -- ED's dirty way to spawn FARPS. Static=coalition.addGroup(CountryID, -1, TemplateGroup) @@ -499,10 +499,10 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID) world.onEvent(Event) else - self:T("Spawning Static") - self:T2({Template=Template}) + self:T("Spawning Static") + self:T2({Template=Template}) Static=coalition.addStaticObject(CountryID, Template) end - + return mystatic end diff --git a/Moose Development/Moose/Wrapper/Storage.lua b/Moose Development/Moose/Wrapper/Storage.lua index 7d4b6da12..04210136a 100644 --- a/Moose Development/Moose/Wrapper/Storage.lua +++ b/Moose Development/Moose/Wrapper/Storage.lua @@ -8,7 +8,7 @@ -- -- ## Example Missions: -- --- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Wrapper/Storage). +-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Storage). -- -- === -- @@ -33,93 +33,93 @@ -- === -- -- # The STORAGE Concept --- --- The STORAGE class offers an easy-to-use wrapper interface to all DCS API functions of DCS warehouses. +-- +-- The STORAGE class offers an easy-to-use wrapper interface to all DCS API functions of DCS warehouses. -- We named the class STORAGE, because the name WAREHOUSE is already taken by another MOOSE class. --- +-- -- This class allows you to add and remove items to a DCS warehouse, such as aircraft, liquids, weapons and other equipment. --- +-- -- # Constructor --- +-- -- A DCS warehouse is associated with an airbase. Therefore, a `STORAGE` instance is automatically created, once an airbase is registered and added to the MOOSE database. --- --- You can get the `STORAGE` object from the --- --- -- Create a STORAGE instance of the Batumi warehouse +-- +-- You can get the `STORAGE` object from the +-- +-- -- Create a STORAGE instance of the Batumi warehouse -- local storage=STORAGE:FindByName("Batumi") --- +-- -- An other way to get the `STORAGE` object is to retrieve it from the AIRBASE function `AIRBASE:GetStorage()` --- +-- -- -- Get storage instance of Batumi airbase -- local Batumi=AIRBASE:FindByName("Batumi") -- local storage=Batumi:GetStorage() --- +-- -- # Aircraft, Weapons and Equipment --- +-- -- ## Adding Items --- +-- -- To add aircraft, weapons and/or othe equipment, you can use the @{#STORAGE.AddItem}() function --- +-- -- storage:AddItem("A-10C", 3) -- storage:AddItem("weapons.missiles.AIM_120C", 10) --- +-- -- This will add three A-10Cs and ten AIM-120C missiles to the warehouse inventory. --- +-- -- ## Setting Items --- +-- -- You can also explicitly set, how many items are in the inventory with the @{#STORAGE.SetItem}() function. --- +-- -- ## Removing Items --- +-- -- Items can be removed from the inventory with the @{#STORAGE.RemoveItem}() function. --- +-- -- ## Getting Amount --- +-- -- The number of items currently in the inventory can be obtained with the @{#STORAGE.GetItemAmount}() function --- +-- -- local N=storage:GetItemAmount("A-10C") -- env.info(string.format("We currently have %d A-10Cs available", N)) --- +-- -- # Liquids --- +-- -- Liquids can be added and removed by slightly different functions as described below. Currently there are four types of liquids --- +-- -- * Jet fuel `STORAGE.Liquid.JETFUEL` -- * Aircraft gasoline `STORAGE.Liquid.GASOLINE` -- * MW 50 `STORAGE.Liquid.MW50` -- * Diesel `STORAGE.Liquid.DIESEL` --- +-- -- ## Adding Liquids --- +-- -- To add a certain type of liquid, you can use the @{#STORAGE.AddItem}(Type, Amount) function --- +-- -- storage:AddLiquid(STORAGE.Liquid.JETFUEL, 10000) -- storage:AddLiquid(STORAGE.Liquid.DIESEL, 20000) --- +-- -- This will add 10,000 kg of jet fuel and 20,000 kg of diesel to the inventory. --- +-- -- ## Setting Liquids --- +-- -- You can also explicitly set the amount of liquid with the @{#STORAGE.SetLiquid}(Type, Amount) function. --- +-- -- ## Removing Liquids --- +-- -- Liquids can be removed with @{#STORAGE.RemoveLiquid}(Type, Amount) function. --- +-- -- ## Getting Amount --- +-- -- The current amount of a certain liquid can be obtained with the @{#STORAGE.GetLiquidAmount}(Type) function --- +-- -- local N=storage:GetLiquidAmount(STORAGE.Liquid.DIESEL) -- env.info(string.format("We currently have %d kg of Diesel available", N)) --- --- +-- +-- -- # Inventory --- +-- -- The current inventory of the warehouse can be obtained with the @{#STORAGE.GetInventory}() function. This returns three tables with the aircraft, liquids and weapons: --- +-- -- local aircraft, liquids, weapons=storage:GetInventory() --- +-- -- UTILS.PrintTableToLog(aircraft) -- UTILS.PrintTableToLog(liquids) -- UTILS.PrintTableToLog(weapons) @@ -168,7 +168,7 @@ function STORAGE:New(AirbaseName) local self=BASE:Inherit(self, BASE:New()) -- #STORAGE self.airbase=Airbase.getByName(AirbaseName) - + if Airbase.getWarehouse then self.warehouse=self.airbase:getWarehouse() end @@ -322,7 +322,7 @@ end function STORAGE:GetLiquidName(Type) local name="Unknown" - + if Type==STORAGE.Liquid.JETFUEL then name = "Jet fuel" elseif Type==STORAGE.Liquid.GASOLINE then @@ -411,25 +411,25 @@ function STORAGE:IsUnlimited(Type) -- Get current amount of type. local N=self:GetAmount(Type) - + local unlimited=false - + if N>0 then - + -- Remove one item. self:RemoveAmount(Type, 1) - + -- Get amount. local n=self:GetAmount(Type) - + -- If amount did not change, it is unlimited. unlimited=n==N - + -- Add item back. if not unlimited then self:AddAmount(Type, 1) end - + -- Debug info. self:I(self.lid..string.format("Type=%s: unlimited=%s (N=%d n=%d)", tostring(Type), tostring(unlimited), N, n)) end @@ -523,7 +523,7 @@ end function STORAGE:GetInventory(Item) local inventory=self.warehouse:getInventory(Item) - + return inventory.aircraft, inventory.liquids, inventory.weapon end From 091083b5aaf99ece316ee532361ecbcaa3b3731f Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 2 Mar 2024 14:24:39 +0100 Subject: [PATCH 47/73] #AWACS * Fix tac radios when using an AWACS plane * AWACS info shows STN set --- Moose Development/Moose/Ops/Awacs.lua | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua index b7bbb1990..1fd51026b 100644 --- a/Moose Development/Moose/Ops/Awacs.lua +++ b/Moose Development/Moose/Ops/Awacs.lua @@ -508,7 +508,7 @@ do -- @field #AWACS AWACS = { ClassName = "AWACS", -- #string - version = "0.2.62", -- #string + version = "0.2.63", -- #string lid = "", -- #string coalition = coalition.side.BLUE, -- #number coalitiontxt = "blue", -- #string @@ -1411,7 +1411,7 @@ function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number) self.TacticalFrequencies[freq] = freq end if self.AwacsSRS then - self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation) + self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Backend) self.TacticalSRS:SetCoalition(self.coalition) self.TacticalSRS:SetGender(self.Gender) self.TacticalSRS:SetCulture(self.Culture) @@ -2089,8 +2089,9 @@ end -- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest) -- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here. -- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here. +-- @param #string Backend (Optional) Your MSRS Backend if different from your config file settings, e.g. MSRS.Backend.SRSEXE or MSRS.Backend.GRPC -- @return #AWACS self -function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey) +function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Backend) self:T(self.lid.."SetSRS") self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" self.Gender = Gender or MSRS.gender or "male" @@ -2100,8 +2101,9 @@ function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey self.PathToGoogleKey = PathToGoogleKey self.AccessKey = AccessKey self.Volume = Volume or 1.0 - - self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation) + self.Backend = Backend or MSRS.backend + BASE:I({backend = self.Backend}) + self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation,self.Backend) self.AwacsSRS:SetCoalition(self.coalition) self.AwacsSRS:SetGender(self.Gender) self.AwacsSRS:SetCulture(self.Culture) @@ -3154,9 +3156,13 @@ end function AWACS:_ShowAwacsInfo(Group) self:T(self.lid.."_ShowAwacsInfo") local report = REPORT:New("Info") + local STN = self.STN report:Add("====================") report:Add(string.format("AWACS %s",self.callsigntxt)) report:Add(string.format("Radio: %.3f %s",self.Frequency,UTILS.GetModulationName(self.Modulation))) + if STN then + report:Add(string.format("Link-16 STN: %s",STN)) + end report:Add(string.format("Bulls Alias: %s",self.AOName)) report:Add(string.format("Coordinate: %s",self.AOCoordinate:ToStringLLDDM())) report:Add("====================") @@ -5993,6 +5999,10 @@ function AWACS:_CheckAwacsStatus() local awacs = nil -- Wrapper.Group#GROUP if self.AwacsFG then awacs = self.AwacsFG:GetGroup() -- Wrapper.Group#GROUP + local unit = awacs:GetUnit(1) + if unit then + self.STN = tostring(unit:GetSTN()) + end end local monitoringdata = self.MonitoringData -- #AWACS.MonitoringData @@ -6672,7 +6682,7 @@ function AWACS:onafterCheckTacticalQueue(From,Event,To) end -- end while - if self:Is("Running") then + if not self:Is("Stopped") then self:__CheckTacticalQueue(-self.TacticalInterval) end return self From 5621579b5eecf64e192967bbe1d6a64c549b9d3d Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 2 Mar 2024 14:24:51 +0100 Subject: [PATCH 48/73] fix --- Moose Development/Moose/Functional/Scoring.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index 5a8e6d87f..15d23ba84 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -1354,14 +1354,14 @@ function SCORING:_EventOnDeadOrCrash( Event ) else Player.PlayerKills = 1 end - self:OnKillPvP(Player, TargetPlayerName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore) + self:OnKillPvP(PlayerName, TargetPlayerName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore) MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. "Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) :ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() ) :ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() ) else - self:OnKillPvE(Player, TargetUnitName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore) + self:OnKillPvE(PlayerName, TargetUnitName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore) MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " .. "Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty, MESSAGE.Type.Information ) From 3953f0e7fcad5349f2fa416481407ae2d30662cd Mon Sep 17 00:00:00 2001 From: kaltokri Date: Sat, 2 Mar 2024 15:07:45 +0100 Subject: [PATCH 49/73] Moved demo missions of Wrapper.Weapon to new repo --- Moose Development/Moose/Wrapper/Weapon.lua | 250 ++++++++++----------- 1 file changed, 125 insertions(+), 125 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Weapon.lua b/Moose Development/Moose/Wrapper/Weapon.lua index 42fffded4..5c9ebc53d 100644 --- a/Moose Development/Moose/Wrapper/Weapon.lua +++ b/Moose Development/Moose/Wrapper/Weapon.lua @@ -14,7 +14,7 @@ -- -- ## Additional Material: -- --- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Wrapper/Weapon) +-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Weapon) -- * **YouTube videos:** None -- * **Guides:** None -- @@ -69,77 +69,77 @@ -- === -- -- # The WEAPON Concept --- +-- -- The WEAPON class offers an easy-to-use wrapper interface to all DCS API functions. --- +-- -- Probably, the most striking highlight is that the position of the weapon can be tracked and its impact position can be determined, which is not -- possible with the native DCS scripting engine functions. -- -- **Note** that this wrapper class is different from most others as weapon objects cannot be found with a DCS API function like `getByName()`. -- They can only be found in DCS events like the "Shot" event, where the weapon object is contained in the event data. --- +-- -- # Tracking --- +-- -- The status of the weapon can be tracked with the @{#WEAPON.StartTrack} function. This function will try to determin the position of the weapon in (normally) relatively -- small time steps. The time step can be set via the @{#WEAPON.SetTimeStepTrack} function and is by default set to 0.01 seconds. --- +-- -- Once the position cannot be retrieved any more, the weapon has impacted (or was destroyed otherwise) and the last known position is safed as the impact point. -- The impact point can be accessed with the @{#WEAPON.GetImpactVec3} or @{#WEAPON.GetImpactCoordinate} functions. --- +-- -- ## Impact Point Marking --- +-- -- You can mark the impact point on the F10 map with @{#WEAPON.SetMarkImpact}. --- +-- -- You can also trigger coloured smoke at the impact point via @{#WEAPON.SetSmokeImpact}. --- +-- -- ## Callback functions --- +-- -- It is possible to define functions that are called during the tracking of the weapon and upon impact, which help you to customize further actions. --- +-- -- ### Callback on Impact --- +-- -- The function called on impact can be set with @{#WEAPON.SetFuncImpact} --- +-- -- ### Callback when Tracking --- +-- -- The function called each time the weapon status is tracked can be set with @{#WEAPON.SetFuncTrack} --- +-- -- # Target --- --- If the weapon has a specific target, you can get it with the @{#WEAPON.GetTarget} function. Note that the object, which is returned can vary. Normally, it is a UNIT +-- +-- If the weapon has a specific target, you can get it with the @{#WEAPON.GetTarget} function. Note that the object, which is returned can vary. Normally, it is a UNIT -- but it could also be a STATIC object. --- +-- -- Also note that the weapon does not always have a target, it can loose a target and re-aquire it and the target might change to another unit. --- +-- -- You can get the target name with the @{#WEAPON.GetTargetName} function. --- +-- -- The distance to the target is returned by the @{#WEAPON.GetTargetDistance} function. --- +-- -- # Category --- +-- -- The category (bomb, rocket, missile, shell, torpedo) of the weapon can be retrieved with the @{#WEAPON.GetCategory} function. --- --- You can check if the weapon is a --- +-- +-- You can check if the weapon is a +-- -- * bomb with @{#WEAPON.IsBomb} -- * rocket with @{#WEAPON.IsRocket} -- * missile with @{#WEAPON.IsMissile} -- * shell with @{#WEAPON.IsShell} -- * torpedo with @{#WEAPON.IsTorpedo} --- +-- -- # Parameters --- +-- -- You can get various parameters of the weapon, *e.g.* --- +-- -- * position: @{#WEAPON.GetVec3}, @{#WEAPON.GetVec2 }, @{#WEAPON.GetCoordinate} -- * speed: @{#WEAPON.GetSpeed} -- * coalition: @{#WEAPON.GetCoalition} -- * country: @{#WEAPON.GetCountry} --- +-- -- # Dependencies --- +-- -- This class is used (at least) in the MOOSE classes: --- +-- -- * RANGE (to determine the impact points of bombs and missiles) -- * ARTY (to destroy and replace shells with smoke or illumination) -- * FOX (to destroy the missile before it hits the target) @@ -181,48 +181,48 @@ function WEAPON:New(WeaponObject) -- Inherit everything from FSM class. local self=BASE:Inherit(self, POSITIONABLE:New("Weapon")) -- #WEAPON - + -- Set DCS weapon object. self.weapon=WeaponObject - + -- Descriptors containing a lot of info. self.desc=WeaponObject:getDesc() -- This gives the object category which is always Object.Category.WEAPON! --self.category=WeaponObject:getCategory() - + -- Weapon category: 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X) self.category = self.desc.category - if self:IsMissile() and self.desc.missileCategory then + if self:IsMissile() and self.desc.missileCategory then self.categoryMissile=self.desc.missileCategory end - + -- Get type name. self.typeName=WeaponObject:getTypeName() or "Unknown Type" - + -- Get name of object. Usually a number like "1234567". self.name=WeaponObject:getName() - + -- Get coaliton of weapon. self.coalition=WeaponObject:getCoalition() - + -- Get country of weapon. self.country=WeaponObject:getCountry() - + -- Get DCS unit of the launcher. self.launcher=WeaponObject:getLauncher() - + -- Get launcher of weapon. self.launcherName="Unknown Launcher" if self.launcher then self.launcherName=self.launcher:getName() self.launcherUnit=UNIT:Find(self.launcher) end - + -- Init the coordinate of the weapon from that of the launcher. self.coordinate=COORDINATE:NewFromVec3(self.launcher:getPoint()) - + -- Set log ID. self.lid=string.format("[%s] %s | ", self.typeName, self.name) @@ -237,12 +237,12 @@ function WEAPON:New(WeaponObject) -- Set default parameters self:SetTimeStepTrack() self:SetDistanceInterceptPoint() - + -- Debug info. - local text=string.format("Weapon v%s\nName=%s, TypeName=%s, Category=%s, Coalition=%d, Country=%d, Launcher=%s", + local text=string.format("Weapon v%s\nName=%s, TypeName=%s, Category=%s, Coalition=%d, Country=%d, Launcher=%s", self.version, self.name, self.typeName, self.category, self.coalition, self.country, self.launcherName) self:T(self.lid..text) - + -- Descriptors. self:T2(self.desc) @@ -312,13 +312,13 @@ function WEAPON:SetSmokeImpact(Switch, SmokeColor) else self.impactSmoke=true end - + self.impactSmokeColor=SmokeColor or SMOKECOLOR.Red return self end ---- Set callback function when weapon is tracked and still alive. The first argument will be the WEAPON object. +--- Set callback function when weapon is tracked and still alive. The first argument will be the WEAPON object. -- Note that this can be called many times per second. So be careful for performance reasons. -- @param #WEAPON self -- @param #function FuncTrack Function called during tracking. @@ -335,19 +335,19 @@ end -- @param #function FuncImpact Function called once the weapon impacted. -- @param ... Optional function arguments. -- @return #WEAPON self --- +-- -- @usage -- -- Function called on impact. -- local function OnImpact(Weapon) -- Weapon:GetImpactCoordinate():MarkToAll("Impact Coordinate of weapon") -- end --- +-- -- -- Set which function to call. -- myweapon:SetFuncImpact(OnImpact) --- +-- -- -- Start tracking. -- myweapon:Track() --- +-- function WEAPON:SetFuncImpact(FuncImpact, ...) self.impactFunc=FuncImpact self.impactArg=arg or {} @@ -368,37 +368,37 @@ end function WEAPON:GetTarget() local target=nil --Wrapper.Object#OBJECT - + if self.weapon then - + -- Get the DCS target object, which can be a Unit, Weapon, Static, Scenery, Airbase. local object=self.weapon:getTarget() - + if object then - + -- Get object category. local category=Object.getCategory(object) - + --Target name local name=object:getName() - + -- Debug info. - self:T(self.lid..string.format("Got Target Object %s, category=%d", object:getName(), category)) - + self:T(self.lid..string.format("Got Target Object %s, category=%d", object:getName(), category)) + if category==Object.Category.UNIT then - + target=UNIT:FindByName(name) - + elseif category==Object.Category.STATIC then - + target=STATIC:FindByName(name, false) - + elseif category==Object.Category.SCENERY then self:E(self.lid..string.format("ERROR: Scenery target not implemented yet!")) else self:E(self.lid..string.format("ERROR: Object category=%d is not implemented yet!", category)) end - + end end @@ -413,25 +413,25 @@ function WEAPON:GetTargetDistance(ConversionFunction) -- Get the target of the weapon. local target=self:GetTarget() --Wrapper.Unit#UNIT - + local distance=nil if target then -- Current position of target. local tv3=target:GetVec3() - + -- Current position of weapon. local wv3=self:GetVec3() - + if tv3 and wv3 then distance=UTILS.VecDist3D(tv3, wv3) - + if ConversionFunction then distance=ConversionFunction(distance) end - + end - + end return distance @@ -445,10 +445,10 @@ function WEAPON:GetTargetName() -- Get the target of the weapon. local target=self:GetTarget() --Wrapper.Unit#UNIT - + local name="None" if target then - name=target:GetName() + name=target:GetName() end return name @@ -476,13 +476,13 @@ function WEAPON:GetSpeed(ConversionFunction) if self.weapon then local v=self:GetVelocityVec3() - + speed=UTILS.VecNorm(v) - + if ConversionFunction then speed=ConversionFunction(speed) end - + end return speed @@ -508,11 +508,11 @@ end function WEAPON:GetVec2() local vec3=self:GetVec3() - + if vec3 then - + local vec2={x=vec3.x, y=vec3.z} - + return vec2 end @@ -521,28 +521,28 @@ end --- Get type name. -- @param #WEAPON self --- @return #string The type name. +-- @return #string The type name. function WEAPON:GetTypeName() return self.typeName end --- Get coalition. -- @param #WEAPON self --- @return #number Coalition ID. +-- @return #number Coalition ID. function WEAPON:GetCoalition() return self.coalition end --- Get country. -- @param #WEAPON self --- @return #number Country ID. +-- @return #number Country ID. function WEAPON:GetCountry() return self.country end --- Get DCS object. -- @param #WEAPON self --- @return DCS#Weapon The weapon object. +-- @return DCS#Weapon The weapon object. function WEAPON:GetDCSObject() -- This polymorphic function is used in Wrapper.Identifiable#IDENTIFIABLE return self.weapon @@ -675,23 +675,23 @@ end function WEAPON:Destroy(Delay) if Delay and Delay>0 then - self:ScheduleOnce(Delay, WEAPON.Destroy, self, 0) + self:ScheduleOnce(Delay, WEAPON.Destroy, self, 0) else if self.weapon then self:T(self.lid.."Destroying Weapon NOW!") self:StopTrack() self.weapon:destroy() - end + end end - + return self end --- Start tracking the weapon until it impacts or is destroyed otherwise. --- The position of the weapon is monitored in small time steps. Once the position cannot be determined anymore, the monitoring is stopped and the last known position is --- the (approximate) impact point. Of course, the smaller the time step, the better the position can be determined. However, this can hit the performance as many +-- The position of the weapon is monitored in small time steps. Once the position cannot be determined anymore, the monitoring is stopped and the last known position is +-- the (approximate) impact point. Of course, the smaller the time step, the better the position can be determined. However, this can hit the performance as many -- calculations per second need to be carried out. --- @param #WEAPON self +-- @param #WEAPON self -- @param #number Delay Delay in seconds before the tracking starts. Default 0.001 sec. -- @return #WEAPON self function WEAPON:StartTrack(Delay) @@ -700,8 +700,8 @@ function WEAPON:StartTrack(Delay) Delay=math.max(Delay or 0.001, 0.001) -- Debug info. - self:T(self.lid..string.format("Start tracking weapon in %.4f sec", Delay)) - + self:T(self.lid..string.format("Start tracking weapon in %.4f sec", Delay)) + -- Weapon is not yet "alife" just yet. Start timer in 0.001 seconds. self.trackScheduleID=timer.scheduleFunction(WEAPON._TrackWeapon, self, timer.getTime() + Delay) @@ -710,7 +710,7 @@ end --- Stop tracking the weapon by removing the scheduler function. --- @param #WEAPON self +-- @param #WEAPON self -- @param #number Delay (Optional) Delay in seconds before the tracking is stopped. -- @return #WEAPON self function WEAPON:StopTrack(Delay) @@ -719,13 +719,13 @@ function WEAPON:StopTrack(Delay) -- Delayed call. self:ScheduleOnce(Delay, WEAPON.StopTrack, self, 0) else - + if self.trackScheduleID then timer.removeFunction(self.trackScheduleID) end - + end return self @@ -762,10 +762,10 @@ function WEAPON:_TrackWeapon(time) -- Update last known position. self.pos3 = pos3 - + -- Update last known vec3. self.vec3 = UTILS.DeepCopy(self.pos3.p) - + -- Update coordinate. self.coordinate:UpdateFromVec3(self.vec3) @@ -774,70 +774,70 @@ function WEAPON:_TrackWeapon(time) -- Keep on tracking by returning the next time below. self.tracking=true - + -- Callback function. if self.trackFunc then self.trackFunc(self, unpack(self.trackArg)) end - + -- Verbose output. if self.verbose>=5 then - + -- Get vec2 of current position. local vec2={x=self.vec3.x, y=self.vec3.z} - + -- Land hight. local height=land.getHeight(vec2) - -- Current height above ground level. + -- Current height above ground level. local agl=self.vec3.y-height - + -- Estimated IP (if any) local ip=self:_GetIP(self.distIP) - + -- Distance between positon and estimated impact. local d=0 if ip then d=UTILS.VecDist3D(self.vec3, ip) end - + -- Output. self:I(self.lid..string.format("T=%.3f: Height=%.3f m AGL=%.3f m, dIP=%.3f", time, height, agl, d)) - + end else - + --------------------------- -- Weapon does NOT exist -- - --------------------------- - + --------------------------- + -- Get intercept point from position (p) and direction (x) in 50 meters. local ip = self:_GetIP(self.distIP) - + if self.verbose>=10 and ip then - + -- Output. self:I(self.lid.."Got intercept point!") - + -- Coordinate of the impact point. local coord=COORDINATE:NewFromVec3(ip) - + -- Mark coordinate. coord:MarkToAll("Intercept point") coord:SmokeBlue() - + -- Distance to last known pos. local d=UTILS.VecDist3D(ip, self.vec3) - + -- Output. self:I(self.lid..string.format("FF d(ip, vec3)=%.3f meters", d)) - + end - + -- Safe impact vec3. self.impactVec3=ip or self.vec3 - + -- Safe impact coordinate. self.impactCoord=COORDINATE:NewFromVec3(self.vec3) @@ -848,22 +848,22 @@ function WEAPON:_TrackWeapon(time) if self.impactMark then self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s", self.name, self.typeName, self.launcherName)) end - + -- Smoke on impact point. if self.impactSmoke then self.impactCoord:Smoke(self.impactSmokeColor) end - + -- Call callback function. if self.impactFunc then self.impactFunc(self, unpack(self.impactArg or {})) end - + -- Stop tracking by returning nil below. self.tracking=false - + end - + -- Return next time the function is called or nil to stop the scheduler. if self.tracking then if self.dtTrack and self.dtTrack>=0.00001 then @@ -885,12 +885,12 @@ function WEAPON:_GetIP(Distance) Distance=Distance or 50 local ip=nil --DCS#Vec3 - + if Distance>0 and self.pos3 then -- Get intercept point from position (p) and direction (x) in 20 meters. ip = land.getIP(self.pos3.p, self.pos3.x, Distance or 20) --DCS#Vec3 - + end return ip From 3652376d4223a68176cb5982fbb7f99b3ac80a74 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 5 Mar 2024 10:34:11 +0100 Subject: [PATCH 50/73] #CTLD - Slight position spawn variation in case you drop > 1 troop groups --- Moose Development/Moose/Ops/CTLD.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 9f5b54d16..9124f3c94 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1232,7 +1232,7 @@ CTLD.UnitTypeCapabilities = { --- CTLD class version. -- @field #string version -CTLD.version="1.0.46" +CTLD.version="1.0.47" --- Instantiate a new CTLD. -- @param #CTLD self @@ -3030,7 +3030,8 @@ function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template) local template = _DATABASE:GetGroupTemplate(Template) --UTILS.PrintTableToLog(template) local numbertroops = #template.units - local newcenter = Coordinate:Translate(Radius,((Heading+270)%360)) + local slightshift = math.abs(math.random(0,200)/100) + local newcenter = Coordinate:Translate(Radius+slightshift,((Heading+270)%360)) for i=1,360,math.floor(360/numbertroops) do local phead = ((Heading+270+i)%360) local post = newcenter:Translate(Radius,phead) From fd0e6053eeab61e361355af48963d5adf63edb7f Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Tue, 5 Mar 2024 16:36:11 +0100 Subject: [PATCH 51/73] #COMMANDER - remove dual AltToKIAS calc for TankerZone etc --- Moose Development/Moose/Ops/Commander.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Ops/Commander.lua b/Moose Development/Moose/Ops/Commander.lua index 046d5ddc0..1c649dd85 100644 --- a/Moose Development/Moose/Ops/Commander.lua +++ b/Moose Development/Moose/Ops/Commander.lua @@ -140,7 +140,7 @@ COMMANDER = { --- COMMANDER class version. -- @field #string version -COMMANDER.version="0.1.3" +COMMANDER.version="0.1.4" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -675,7 +675,8 @@ function COMMANDER:AddCapZone(Zone, Altitude, Speed, Heading, Leg) patrolzone.zone=Zone patrolzone.altitude=Altitude or 12000 patrolzone.heading=Heading or 270 - patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude) + --patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude) + patrolzone.speed=Speed or 350 patrolzone.leg=Leg or 30 patrolzone.mission=nil --patrolzone.marker=MARKER:New(patrolzone.zone:GetCoordinate(), "CAP Zone"):ToCoalition(self:GetCoalition()) @@ -700,7 +701,8 @@ function COMMANDER:AddGciCapZone(Zone, Altitude, Speed, Heading, Leg) patrolzone.zone=Zone patrolzone.altitude=Altitude or 12000 patrolzone.heading=Heading or 270 - patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude) + --patrolzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, patrolzone.altitude) + patrolzone.speed=Speed or 350 patrolzone.leg=Leg or 30 patrolzone.mission=nil --patrolzone.marker=MARKER:New(patrolzone.zone:GetCoordinate(), "GCICAP Zone"):ToCoalition(self:GetCoalition()) @@ -745,7 +747,9 @@ function COMMANDER:AddAwacsZone(Zone, Altitude, Speed, Heading, Leg) awacszone.zone=Zone awacszone.altitude=Altitude or 12000 awacszone.heading=Heading or 270 - awacszone.speed=UTILS.KnotsToAltKIAS(Speed or 350, awacszone.altitude) + --awacszone.speed=UTILS.KnotsToAltKIAS(Speed or 350, awacszone.altitude) + awacszone.speed=Speed or 350 + awacszone.speed=Speed or 350 awacszone.leg=Leg or 30 awacszone.mission=nil --awacszone.marker=MARKER:New(awacszone.zone:GetCoordinate(), "AWACS Zone"):ToCoalition(self:GetCoalition()) @@ -791,7 +795,8 @@ function COMMANDER:AddTankerZone(Zone, Altitude, Speed, Heading, Leg, RefuelSyst tankerzone.zone=Zone tankerzone.altitude=Altitude or 12000 tankerzone.heading=Heading or 270 - tankerzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, tankerzone.altitude) + --tankerzone.speed=UTILS.KnotsToAltKIAS(Speed or 350, tankerzone.altitude) -- speed translation to alt will be done by AUFTRAG anyhow + tankerzone.speed = Speed or 350 tankerzone.leg=Leg or 30 tankerzone.refuelsystem=RefuelSystem tankerzone.mission=nil From bfa8719ec3b8a78184984457f90e65011ecfaee8 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Tue, 5 Mar 2024 22:11:20 +0100 Subject: [PATCH 52/73] Updated versions of all GitHub actions --- .github/workflows/gh-pages.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index db74f8ab0..d1b13a31c 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -33,7 +33,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Ruby uses: ruby/setup-ruby@v1 with: @@ -43,7 +43,7 @@ jobs: working-directory: docs/ - name: Setup Pages id: pages - uses: actions/configure-pages@v3 + uses: actions/configure-pages@v4 - name: Build with Jekyll # Outputs to the './_site' directory by default run: bundle exec jekyll build --baseurl "${{ steps.pages.outputs.base_path }}" @@ -52,7 +52,7 @@ jobs: working-directory: docs/ - name: Upload artifact # Automatically uploads an artifact from the './_site' directory by default - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v3 with: path: docs/_site/ @@ -66,13 +66,13 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v4 check: runs-on: ubuntu-latest needs: deploy steps: - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 - run: npm install linkinator - run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)" --retry-errors --retry-errors-count 3 --retry-errors-jitter From 1e15509001ab95eea0783465e31442905e0659c0 Mon Sep 17 00:00:00 2001 From: kaltokri Date: Tue, 5 Mar 2024 22:29:28 +0100 Subject: [PATCH 53/73] Fixed broken link to demo mission --- .../Moose/Wrapper/Controllable.lua | 382 +++++++++--------- 1 file changed, 191 insertions(+), 191 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index a7c4e235a..89b2e995e 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -99,7 +99,7 @@ -- This method can also be used to **embed a function call when a certain waypoint has been reached**. -- See below the **Tasks at Waypoints** section. -- --- Demonstration Mission: [GRP-502 - Route at waypoint to random point](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/Wrapper/Group/GRP-502%20-%20Route%20at%20waypoint%20to%20random%20point) +-- Demonstration Mission: [GRP-502 - Route at waypoint to random point](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Group/502-Route-at-waypoint-to-random-point) -- -- ## 2.5) Tasks at Waypoints -- @@ -527,7 +527,7 @@ end -- @return DCS#Task function CONTROLLABLE:TaskEmptyTask() - local DCSTaskWrappedAction = { + local DCSTaskWrappedAction = { ["id"] = "WrappedAction", ["params"] = { ["action"] = { @@ -699,12 +699,12 @@ end function CONTROLLABLE:CommandActivateACLS( UnitID, Name, Delay ) -- Command to activate ACLS system. - local CommandActivateACLS= { - id = 'ActivateACLS', + local CommandActivateACLS= { + id = 'ActivateACLS', params = { - unitId = UnitID or self:GetID(), - name = Name or "ACL", - } + unitId = UnitID or self:GetID(), + name = Name or "ACL", + } } self:T({CommandActivateACLS}) @@ -726,9 +726,9 @@ end function CONTROLLABLE:CommandDeactivateACLS( Delay ) -- Command to activate ACLS system. - local CommandDeactivateACLS= { - id = 'DeactivateACLS', - params = { } + local CommandDeactivateACLS= { + id = 'DeactivateACLS', + params = { } } if Delay and Delay > 0 then @@ -778,9 +778,9 @@ end -- @param #number Delay (Optional) Delay in seconds before the LINK4 is activated. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandActivateLink4(Frequency, UnitID, Callsign, Delay) - + local freq = Frequency or 336 - + -- Command to activate Link4 system. local CommandActivateLink4= { id = "ActivateLink4", @@ -790,9 +790,9 @@ function CONTROLLABLE:CommandActivateLink4(Frequency, UnitID, Callsign, Delay) ["name"] = Callsign or "LNK", } } - + self:T({CommandActivateLink4}) - + if Delay and Delay>0 then SCHEDULER:New(nil, self.CommandActivateLink4, {self, Frequency, UnitID, Callsign}, Delay) else @@ -918,10 +918,10 @@ end function CONTROLLABLE:CommandSetUnlimitedFuel(OnOff, Delay) local CommandSetFuel = { - id = 'SetUnlimitedFuel', - params = { - value = OnOff - } + id = 'SetUnlimitedFuel', + params = { + value = OnOff + } } if Delay and Delay > 0 then @@ -966,7 +966,7 @@ end -- @param #number Frequency Radio frequency in MHz. -- @param #number Modulation Radio modulation. Default `radio.modulation.AM`. -- @param #number Power (Optional) Power of the Radio in Watts. Defaults to 10. --- @param #UnitID UnitID (Optional, if your object is a UNIT) The UNIT ID this is for. +-- @param #UnitID UnitID (Optional, if your object is a UNIT) The UNIT ID this is for. -- @param #number Delay (Optional) Delay in seconds before the frequency is set. Default is immediately. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandSetFrequencyForUnit(Frequency,Modulation,Power,UnitID,Delay) @@ -1144,19 +1144,19 @@ end -- attacker:SetTask(task,2) function CONTROLLABLE:TaskStrafing( Vec2, AttackQty, Length, WeaponType, WeaponExpend, Direction, GroupAttack ) - local DCSTask = { - id = 'Strafing', - params = { + local DCSTask = { + id = 'Strafing', + params = { point = Vec2, -- req weaponType = WeaponType or 1073741822, - expend = WeaponExpend or "Auto", + expend = WeaponExpend or "Auto", attackQty = AttackQty or 1, -- req attackQtyLimit = AttackQty >1 and true or false, - direction = Direction and math.rad(Direction) or 0, + direction = Direction and math.rad(Direction) or 0, directionEnabled = Direction and true or false, - groupAttack = GroupAttack or false, - length = Length, - } + groupAttack = GroupAttack or false, + length = Length, + } } return DCSTask @@ -1495,20 +1495,20 @@ end -- @param #number LastWptNumber (optional) Waypoint of carrier group that when reached, ends the recovery tanker task -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskRecoveryTanker(CarrierGroup, Speed, Altitude, LastWptNumber) - + local LastWptFlag = type(LastWptNumber) == "number" and true or false - - local DCSTask = { + + local DCSTask = { id = "RecoveryTanker", params = { groupId = CarrierGroup:GetID(), - speed = Speed, - altitude = Altitude, - lastWptIndexFlag = LastWptFlag, + speed = Speed, + altitude = Altitude, + lastWptIndexFlag = LastWptFlag, lastWptIndex = LastWptNumber } } - + return DCSTask end @@ -1618,7 +1618,7 @@ function CONTROLLABLE:TaskGroundEscort( FollowControllable, LastWaypointIndex, O groupId = FollowControllable and FollowControllable:GetID() or nil, engagementDistMax = OrbitDistance or 2000, lastWptIndexFlag = LastWaypointIndex and true or false, - lastWptIndex = LastWaypointIndex, + lastWptIndex = LastWaypointIndex, targetTypes = TargetTypes or {"Ground vehicles"}, lastWptIndexFlagChangedManually = true, }, @@ -1811,7 +1811,7 @@ function CONTROLLABLE:EnRouteTaskAntiShip(TargetTypes, Priority) id = 'EngageTargets', key = "AntiShip", --auto = false, - --enabled = true, + --enabled = true, params = { targetTypes = TargetTypes or {"Ships"}, priority = Priority or 0 @@ -1832,7 +1832,7 @@ function CONTROLLABLE:EnRouteTaskSEAD(TargetTypes, Priority) id = 'EngageTargets', key = "SEAD", --auto = false, - --enabled = true, + --enabled = true, params = { targetTypes = TargetTypes or {"Air Defence"}, priority = Priority or 0 @@ -1853,7 +1853,7 @@ function CONTROLLABLE:EnRouteTaskCAP(TargetTypes, Priority) id = 'EngageTargets', key = "CAP", --auto = true, - enabled = true, + enabled = true, params = { targetTypes = TargetTypes or {"Air"}, priority = Priority or 0 @@ -1863,7 +1863,7 @@ function CONTROLLABLE:EnRouteTaskCAP(TargetTypes, Priority) return DCSTask end ---- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; +--- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; -- it just allows the unit/controllable to engage the target controllable as well as other assigned targets. -- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_engageGroup). -- @param #CONTROLLABLE self @@ -2004,7 +2004,7 @@ function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponT frequency = (Frequency or 133)*1000000, modulation = Modulation or radio.modulation.AM, callname = CallsignID, - number = CallsignNumber, + number = CallsignNumber, priority = Priority or 0, }, } @@ -2013,7 +2013,7 @@ function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponT end --- (AIR + GROUND) The task makes the controllable/unit a FAC and lets the FAC to choose a targets (enemy ground controllable) around as well as other assigned targets. --- Assigns the controlled group to act as a Forward Air Controller or JTAC. Any detected targets will be assigned as targets to the player via the JTAC radio menu. +-- Assigns the controlled group to act as a Forward Air Controller or JTAC. Any detected targets will be assigned as targets to the player via the JTAC radio menu. -- Target designation is set to auto and is dependent on the circumstances. -- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_fac). -- @param #CONTROLLABLE self @@ -2031,7 +2031,7 @@ function CONTROLLABLE:EnRouteTaskFAC( Frequency, Modulation, CallsignID, Callsig frequency = (Frequency or 133)*1000000, modulation = Modulation or radio.modulation.AM, callname = CallsignID, - number = CallsignNumber, + number = CallsignNumber, priority = Priority or 0 } } @@ -2328,7 +2328,7 @@ function CONTROLLABLE:TaskRoute( Points ) route = {points = Points}, }, } - + return DCSTask end @@ -3800,7 +3800,7 @@ function CONTROLLABLE:OptionProhibitAfterburner( Prohibit ) return self end ---- [Air] Defines the usage of Electronic Counter Measures by airborne forces. +--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. -- @param #CONTROLLABLE self -- @param #number ECMvalue Can be - 0=Never on, 1=if locked by radar, 2=if detected by radar, 3=always on, defaults to 1 -- @return #CONTROLLABLE self @@ -3825,7 +3825,7 @@ end -- @return #CONTROLLABLE self function CONTROLLABLE:OptionECM_Never() self:F2( { self.ControllableName } ) - + self:OptionECM(0) return self @@ -4184,10 +4184,10 @@ function CONTROLLABLE:IsSubmarine() end ---- Sets the controlled group to go at the specified speed in meters per second. +--- Sets the controlled group to go at the specified speed in meters per second. -- @param #CONTROLLABLE self -- @param #number Speed Speed in meters per second --- @param #boolean Keep (Optional) When set to true, will maintain the speed on passing waypoints. If not present or false, the controlled group will return to the speed as defined by their route. +-- @param #boolean Keep (Optional) When set to true, will maintain the speed on passing waypoints. If not present or false, the controlled group will return to the speed as defined by their route. -- @return #CONTROLLABLE self function CONTROLLABLE:SetSpeed(Speed, Keep) self:F2( { self.ControllableName } ) @@ -4206,7 +4206,7 @@ end --- [AIR] Sets the controlled aircraft group to fly at the specified altitude in meters. -- @param #CONTROLLABLE self -- @param #number Altitude Altitude in meters. --- @param #boolean Keep (Optional) When set to true, will maintain the altitude on passing waypoints. If not present or false, the controlled group will return to the altitude as defined by their route. +-- @param #boolean Keep (Optional) When set to true, will maintain the altitude on passing waypoints. If not present or false, the controlled group will return to the altitude as defined by their route. -- @param #string AltType (Optional) Specifies the altitude type used. If nil, the altitude type of the current waypoint will be used. Accepted values are "BARO" and "RADIO". -- @return #CONTROLLABLE self function CONTROLLABLE:SetAltitude(Altitude, Keep, AltType) @@ -4231,7 +4231,7 @@ end -- @usage -- local plane = GROUP:FindByName("Aerial-1") -- -- get a task shell --- local aerotask = plane:TaskAerobatics() +-- local aerotask = plane:TaskAerobatics() -- -- add a series of maneuvers -- aerotask = plane:TaskAerobaticsHorizontalEight(aerotask,1,5000,850,true,false,1,70) -- aerotask = plane:TaskAerobaticsWingoverFlight(aerotask,1,0,0,true,true,20) @@ -4246,7 +4246,7 @@ function CONTROLLABLE:TaskAerobatics() ["maneuversSequency"] = {}, }, ["enabled"] = true, - ["auto"] = false, + ["auto"] = false, } return DCSTaskAerobatics @@ -4262,15 +4262,15 @@ end -- @param #boolean StartImmediately (Optional) If true, start immediately and ignore InitAltitude and InitSpeed. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsCandle(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local CandleTask = { ["name"] = "CANDLE", ["params"] = { @@ -4298,9 +4298,9 @@ function CONTROLLABLE:TaskAerobaticsCandle(TaskAerobatics,Repeats,InitAltitude,I } } } - + table.insert(TaskAerobatics.params["maneuversSequency"],CandleTask) - + return TaskAerobatics end @@ -4316,20 +4316,20 @@ end -- @param #number Side (Optional) On which side to fly, 0 == left, 1 == right side, defaults to 0. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsEdgeFlight(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,FlightTime,Side) - + local maxrepeats = 10 local maxflight = 200 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local flighttime = FlightTime or 10 - + if flighttime > 200 then maxflight = flighttime end - + local EdgeTask = { ["name"] = "EDGE_FLIGHT", ["params"] = { @@ -4368,9 +4368,9 @@ function CONTROLLABLE:TaskAerobaticsEdgeFlight(TaskAerobatics,Repeats,InitAltitu }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],EdgeTask) - + return TaskAerobatics end @@ -4385,20 +4385,20 @@ end -- @param #number FlightTime (Optional) Time to fly this manoever in seconds, defaults to 10. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsWingoverFlight(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,FlightTime) - + local maxrepeats = 10 local maxflight = 200 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local flighttime = FlightTime or 10 - + if flighttime > 200 then maxflight = flighttime end - + local WingoverTask = { ["name"] = "WINGOVER_FLIGHT", ["params"] = { @@ -4433,9 +4433,9 @@ function CONTROLLABLE:TaskAerobaticsWingoverFlight(TaskAerobatics,Repeats,InitAl }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],WingoverTask) - + return TaskAerobatics end @@ -4449,15 +4449,15 @@ end -- @param #boolean StartImmediately (Optional) If true, start immediately and ignore InitAltitude and InitSpeed. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsLoop(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local LoopTask = { ["name"] = "LOOP", ["params"] = { @@ -4485,9 +4485,9 @@ function CONTROLLABLE:TaskAerobaticsLoop(TaskAerobatics,Repeats,InitAltitude,Ini } } } - + table.insert(TaskAerobatics.params["maneuversSequency"],LoopTask) - + return TaskAerobatics end @@ -4503,15 +4503,15 @@ end -- @param #number RollDeg (Optional) Roll degrees for Roll 1 and 2, defaults to 60. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsHorizontalEight(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side,RollDeg) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local LoopTask = { ["name"] = "HORIZONTAL_EIGHT", ["params"] = { @@ -4549,12 +4549,12 @@ function CONTROLLABLE:TaskAerobaticsHorizontalEight(TaskAerobatics,Repeats,InitA ["order"] = 8, ["value"] = RollDeg or 60, }, - + } } - + table.insert(TaskAerobatics.params["maneuversSequency"],LoopTask) - + return TaskAerobatics end @@ -4569,15 +4569,15 @@ end -- @param #number Side (Optional) On which side to fly, 0 == left, 1 == right side, defaults to 0. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsHammerhead(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "HUMMERHEAD", ["params"] = { @@ -4606,12 +4606,12 @@ function CONTROLLABLE:TaskAerobaticsHammerhead(TaskAerobatics,Repeats,InitAltitu ["SIDE"] = { ["order"] = 6, ["value"] = Side or 0, - }, + }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4627,15 +4627,15 @@ end -- @param #number RollDeg (Optional) Roll degrees for Roll 1 and 2, defaults to 60. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsSkewedLoop(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side,RollDeg) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "SKEWED_LOOP", ["params"] = { @@ -4668,12 +4668,12 @@ function CONTROLLABLE:TaskAerobaticsSkewedLoop(TaskAerobatics,Repeats,InitAltitu ["SIDE"] = { ["order"] = 7, ["value"] = Side or 0, - }, + }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4691,15 +4691,15 @@ end -- @param #number Angle (Optional) How many degrees to turn, defaults to 180. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsTurn(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side,RollDeg,Pull,Angle) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "TURN", ["params"] = { @@ -4740,12 +4740,12 @@ function CONTROLLABLE:TaskAerobaticsTurn(TaskAerobatics,Repeats,InitAltitude,Ini ["SIDE"] = { ["order"] = 9, ["value"] = Side or 0, - }, + }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4761,19 +4761,19 @@ end -- @param #number FinalAltitude (Optional) Final altitude in meters, defaults to 1000. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsDive(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Angle,FinalAltitude) - + local maxrepeats = 10 - + local angle = Angle - + if angle < 15 then angle = 15 elseif angle > 90 then angle = 90 end - + if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "DIVE", ["params"] = { @@ -4809,12 +4809,12 @@ function CONTROLLABLE:TaskAerobaticsDive(TaskAerobatics,Repeats,InitAltitude,Ini ["FinalAltitude"] = { ["order"] = 7, ["value"] = FinalAltitude or 1000, - }, + }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4828,15 +4828,15 @@ end -- @param #boolean StartImmediately (Optional) If true, start immediately and ignore InitAltitude and InitSpeed. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsMilitaryTurn(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "MILITARY_TURN", ["params"] = { @@ -4864,9 +4864,9 @@ function CONTROLLABLE:TaskAerobaticsMilitaryTurn(TaskAerobatics,Repeats,InitAlti } } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4880,15 +4880,15 @@ end -- @param #boolean StartImmediately (Optional) If true, start immediately and ignore InitAltitude and InitSpeed. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsImmelmann(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "IMMELMAN", ["params"] = { @@ -4916,9 +4916,9 @@ function CONTROLLABLE:TaskAerobaticsImmelmann(TaskAerobatics,Repeats,InitAltitud } } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -4933,23 +4933,23 @@ end -- @param #number FlightTime (Optional) Time to fly this manoever in seconds, defaults to 10. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsStraightFlight(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,FlightTime) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local maxflight = 200 if Repeats > maxrepeats then maxrepeats = Repeats end - + local flighttime = FlightTime or 10 - + if flighttime > 200 then maxflight = flighttime end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "STRAIGHT_FLIGHT", ["params"] = { @@ -4984,9 +4984,9 @@ function CONTROLLABLE:TaskAerobaticsStraightFlight(TaskAerobatics,Repeats,InitAl }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5002,15 +5002,15 @@ end -- @param #number FinalAltitude (Optional) Altitude to climb to in meters. Defaults to 5000m. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsClimb(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Angle,FinalAltitude) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "CLIMB", ["params"] = { @@ -5049,9 +5049,9 @@ function CONTROLLABLE:TaskAerobaticsClimb(TaskAerobatics,Repeats,InitAltitude,In }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5070,17 +5070,17 @@ end -- @param #number Angle (Optional) Angle to spiral. Can be between 15 and 90 degrees. Defaults to 45 degrees. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsSpiral(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,TurnAngle,Roll,Side,UpDown,Angle) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 local updown = UpDown and 1 or 0 local side = Side and 1 or 0 - + local Task = { ["name"] = "SPIRAL", ["params"] = { @@ -5121,7 +5121,7 @@ function CONTROLLABLE:TaskAerobaticsSpiral(TaskAerobatics,Repeats,InitAltitude,I ["UPDOWN"] = { ["order"] = 9, ["value"] = updown or 0, - }, + }, ["Angle"] = { ["max_v"] = 90, ["min_v"] = 15, @@ -5131,9 +5131,9 @@ function CONTROLLABLE:TaskAerobaticsSpiral(TaskAerobatics,Repeats,InitAltitude,I }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5148,21 +5148,21 @@ end -- @param #number FinalSpeed (Optional) Final speed to reach in KPH. Defaults to 500 kph. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsSplitS(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,FinalSpeed) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local maxflight = 200 if Repeats > maxrepeats then maxrepeats = Repeats end - + local finalspeed = FinalSpeed or 500 - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "SPLIT_S", ["params"] = { @@ -5194,9 +5194,9 @@ function CONTROLLABLE:TaskAerobaticsSplitS(TaskAerobatics,Repeats,InitAltitude,I }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5214,19 +5214,19 @@ end -- @param #number FixAngle (Optional) No idea what this does, can be between 0 and 180 degrees, defaults to 180. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsAileronRoll(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side,RollRate,TurnAngle,FixAngle) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local maxflight = 200 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "AILERON_ROLL", ["params"] = { @@ -5276,9 +5276,9 @@ function CONTROLLABLE:TaskAerobaticsAileronRoll(TaskAerobatics,Repeats,InitAltit }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5296,18 +5296,18 @@ end -- @param #number MinSpeed (Optional) Minimum speed to keep in kph, defaults to 250 kph. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsForcedTurn(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,TurnAngle,Side,FlightTime,MinSpeed) - + local maxrepeats = 10 local flighttime = FlightTime or 30 local maxtime = 200 if flighttime > 200 then maxtime = flighttime end - + if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "FORCED_TURN", ["params"] = { @@ -5357,9 +5357,9 @@ function CONTROLLABLE:TaskAerobaticsForcedTurn(TaskAerobatics,Repeats,InitAltitu }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end @@ -5376,15 +5376,15 @@ end -- @param #number TurnAngle (Optional) Turn angle, defaults to 360 degrees. -- @return DCS#Task function CONTROLLABLE:TaskAerobaticsBarrelRoll(TaskAerobatics,Repeats,InitAltitude,InitSpeed,UseSmoke,StartImmediately,Side,RollRate,TurnAngle) - + local maxrepeats = 10 if Repeats > maxrepeats then maxrepeats = Repeats end - + local usesmoke = UseSmoke and 1 or 0 - + local startimmediately = StartImmediately and 1 or 0 - + local Task = { ["name"] = "BARREL_ROLL", ["params"] = { @@ -5413,7 +5413,7 @@ function CONTROLLABLE:TaskAerobaticsBarrelRoll(TaskAerobatics,Repeats,InitAltitu ["SIDE"] = { ["order"] = 6, ["value"] = Side or 0, - }, + }, ["RollRate"] = { ["max_v"] = 450, ["min_v"] = 15, @@ -5427,13 +5427,13 @@ function CONTROLLABLE:TaskAerobaticsBarrelRoll(TaskAerobatics,Repeats,InitAltitu }, } } - + table.insert(TaskAerobatics.params["maneuversSequency"],Task) - + return TaskAerobatics end - + --- [Air] Make an airplane or helicopter patrol between two points in a racetrack - resulting in a much tighter track around the start and end points. -- @param #CONTROLLABLE self -- @param Core.Point#COORDINATE Point1 Start point. @@ -5447,23 +5447,23 @@ end function CONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation, AGL, Delay) local PatrolGroup = self -- Wrapper.Group#GROUP - + if not self:IsInstanceOf( "GROUP" ) then PatrolGroup = self:GetGroup() -- Wrapper.Group#GROUP end - + local delay = Delay or 1 - + self:F( { PatrolGroup = PatrolGroup:GetName() } ) - - if PatrolGroup:IsAir() then + + if PatrolGroup:IsAir() then if Formation then PatrolGroup:SetOption(AI.Option.Air.id.FORMATION,Formation) -- https://wiki.hoggitworld.com/view/DCS_option_formation end - + local FromCoord = PatrolGroup:GetCoordinate() local ToCoord = Point1:GetCoordinate() - + -- Calculate the new Route if Altitude then local asl = true @@ -5471,16 +5471,16 @@ function CONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation FromCoord:SetAltitude(Altitude, asl) ToCoord:SetAltitude(Altitude, asl) end - + -- Create a "air waypoint", which is a "point" structure that can be given as a parameter to a Task - local Route = {} + local Route = {} Route[#Route + 1] = FromCoord:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true, nil, DCSTasks, description, timeReFuAr ) Route[#Route + 1] = ToCoord:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true, nil, DCSTasks, description, timeReFuAr ) - + local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRaceTrack", Point2, Point1, Altitude, Speed, Formation, Delay ) PatrolGroup:SetTaskWaypoint( Route[#Route], TaskRouteToZone ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone. PatrolGroup:Route( Route, Delay ) -- Move after delay seconds to the Route. See the Route method for details. end - + return self end From cb61177252919124cb8ac538a39ea9f862b83e06 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 7 Mar 2024 10:20:27 +0100 Subject: [PATCH 54/73] CSAR/CTLD basic support for MH-60R --- Moose Development/Moose/Ops/CSAR.lua | 3 ++- Moose Development/Moose/Ops/CTLD.lua | 3 ++- Moose Development/Moose/Utilities/Utils.lua | 5 +++++ Moose Development/Moose/Wrapper/Controllable.lua | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 5ecc2c4c8..f1d366ca4 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -290,10 +290,11 @@ CSAR.AircraftType["Bell-47"] = 2 CSAR.AircraftType["UH-60L"] = 10 CSAR.AircraftType["AH-64D_BLK_II"] = 2 CSAR.AircraftType["Bronco-OV-10A"] = 2 +CSAR.AircraftType["MH-60R"] = 10 --- CSAR class version. -- @field #string version -CSAR.version="1.0.19" +CSAR.version="1.0.20" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 9124f3c94..e571e5cd0 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1226,13 +1226,14 @@ CTLD.UnitTypeCapabilities = { ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers. --Actually it's longer, but the center coord is off-center of the model. ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats + ["MH-60R"] = {type="MH-60R", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats ["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450}, } --- CTLD class version. -- @field #string version -CTLD.version="1.0.47" +CTLD.version="1.0.48" --- Instantiate a new CTLD. -- @param #CTLD self diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index ec50854a0..25cfb7853 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -2237,6 +2237,11 @@ function UTILS.IsLoadingDoorOpen( unit_name ) return true -- no doors on this one ;) end + if type_name == "MH-60R" and (unit:getDrawArgumentValue(403) > 0 or unit:getDrawArgumentValue(403) == -1) then + BASE:T(unit_name .. " cargo door is open") + return true + end + return false end -- nil diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 89b2e995e..696cdb15b 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -3871,6 +3871,10 @@ end -- @param #CONTROLLABLE self -- @param #table WayPoints If WayPoints is given, then use the route. -- @return #CONTROLLABLE self +-- @usage Intended Workflow is: +-- mygroup:WayPointInitialize() +-- mygroup:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) +-- mygroup:WayPointExecute() function CONTROLLABLE:WayPointInitialize( WayPoints ) self:F( { WayPoints } ) @@ -3902,9 +3906,15 @@ end -- @param #number WayPointIndex When defining multiple WayPoint functions for one WayPoint, use WayPointIndex to set the sequence of actions. -- @param #function WayPointFunction The waypoint function to be called when the controllable moves over the waypoint. The waypoint function takes variable parameters. -- @return #CONTROLLABLE self +-- @usage Intended Workflow is: +-- mygroup:WayPointInitialize() +-- mygroup:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) +-- mygroup:WayPointExecute() function CONTROLLABLE:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) self:F2( { WayPoint, WayPointIndex, WayPointFunction } ) - + if not self.WayPoints then + self:WayPointInitialize() + end table.insert( self.WayPoints[WayPoint].task.params.tasks, WayPointIndex ) self.WayPoints[WayPoint].task.params.tasks[WayPointIndex] = self:TaskFunction( WayPointFunction, arg ) return self @@ -3917,6 +3927,10 @@ end -- @param #number WayPoint The WayPoint from where to execute the mission. -- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #CONTROLLABLE self +-- @usage Intended Workflow is: +-- mygroup:WayPointInitialize() +-- mygroup:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) +-- mygroup:WayPointExecute() function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) self:F( { WayPoint, WaitTime } ) From ab14fbd11c99666b2aa2676b3023c208e1e82dcc Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 8 Mar 2024 10:06:16 +0100 Subject: [PATCH 55/73] #MARKEROPS - Added Coalition on FSM events --- .../Moose/Core/MarkerOps_Base.lua | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Moose Development/Moose/Core/MarkerOps_Base.lua b/Moose Development/Moose/Core/MarkerOps_Base.lua index b39250c8c..664ad3c03 100644 --- a/Moose Development/Moose/Core/MarkerOps_Base.lua +++ b/Moose Development/Moose/Core/MarkerOps_Base.lua @@ -17,7 +17,7 @@ -- ### Author: **Applevangelist** -- -- Date: 5 May 2021 --- Last Update: Feb 2023 +-- Last Update: Mar 2023 -- -- === --- @@ -50,7 +50,7 @@ MARKEROPS_BASE = { ClassName = "MARKEROPS", Tag = "mytag", Keywords = {}, - version = "0.1.1", + version = "0.1.2", debug = false, Casesensitive = true, } @@ -114,6 +114,8 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text -- @param Core.Point#COORDINATE Coord Coordinate of the marker. + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator --- On after "MarkChanged" event. Triggered when a Marker is changed on the F10 map. -- @function [parent=#MARKEROPS_BASE] OnAfterMarkChanged @@ -124,7 +126,8 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text -- @param Core.Point#COORDINATE Coord Coordinate of the marker. - -- @param #number idx DCS Marker ID + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator --- On after "MarkDeleted" event. Triggered when a Marker is deleted from the F10 map. -- @function [parent=#MARKEROPS_BASE] OnAfterMarkDeleted @@ -133,7 +136,7 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Event The Event called -- @param #string To The To state - --- "Stop" trigger. Used to stop the function an unhandle events + --- "Stop" trigger. Used to stop the function an unhandle events -- @function [parent=#MARKEROPS_BASE] Stop end @@ -155,6 +158,7 @@ function MARKEROPS_BASE:OnEventMark(Event) local text = tostring(Event.text) local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll() end + local coalition = Event.IniCoalition -- decision if Event.id==world.event.S_EVENT_MARK_ADDED then self:T({event="S_EVENT_MARK_ADDED", carrier=self.groupname, vec3=Event.pos}) @@ -163,7 +167,7 @@ function MARKEROPS_BASE:OnEventMark(Event) if Eventtext~=nil then if self:_MatchTag(Eventtext) then local matchtable = self:_MatchKeywords(Eventtext) - self:MarkAdded(Eventtext,matchtable,coord) + self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition) end end elseif Event.id==world.event.S_EVENT_MARK_CHANGE then @@ -173,7 +177,7 @@ function MARKEROPS_BASE:OnEventMark(Event) if Eventtext~=nil then if self:_MatchTag(Eventtext) then local matchtable = self:_MatchKeywords(Eventtext) - self:MarkChanged(Eventtext,matchtable,coord,Event.idx) + self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition) end end elseif Event.id==world.event.S_EVENT_MARK_REMOVED then @@ -230,8 +234,10 @@ end -- @param #string To The To state -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator -- @param Core.Point#COORDINATE Coord Coordinate of the marker. -function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord) +function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber) self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()}) end @@ -242,8 +248,10 @@ end -- @param #string To The To state -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator -- @param Core.Point#COORDINATE Coord Coordinate of the marker. -function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord) +function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber) self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()}) end From 52869266093067c3294bede47187129ed9b980ae Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 8 Mar 2024 10:06:31 +0100 Subject: [PATCH 56/73] xx --- .../Moose/Core/MarkerOps_Base.lua | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Moose Development/Moose/Core/MarkerOps_Base.lua b/Moose Development/Moose/Core/MarkerOps_Base.lua index b39250c8c..664ad3c03 100644 --- a/Moose Development/Moose/Core/MarkerOps_Base.lua +++ b/Moose Development/Moose/Core/MarkerOps_Base.lua @@ -17,7 +17,7 @@ -- ### Author: **Applevangelist** -- -- Date: 5 May 2021 --- Last Update: Feb 2023 +-- Last Update: Mar 2023 -- -- === --- @@ -50,7 +50,7 @@ MARKEROPS_BASE = { ClassName = "MARKEROPS", Tag = "mytag", Keywords = {}, - version = "0.1.1", + version = "0.1.2", debug = false, Casesensitive = true, } @@ -114,6 +114,8 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text -- @param Core.Point#COORDINATE Coord Coordinate of the marker. + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator --- On after "MarkChanged" event. Triggered when a Marker is changed on the F10 map. -- @function [parent=#MARKEROPS_BASE] OnAfterMarkChanged @@ -124,7 +126,8 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text -- @param Core.Point#COORDINATE Coord Coordinate of the marker. - -- @param #number idx DCS Marker ID + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator --- On after "MarkDeleted" event. Triggered when a Marker is deleted from the F10 map. -- @function [parent=#MARKEROPS_BASE] OnAfterMarkDeleted @@ -133,7 +136,7 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive) -- @param #string Event The Event called -- @param #string To The To state - --- "Stop" trigger. Used to stop the function an unhandle events + --- "Stop" trigger. Used to stop the function an unhandle events -- @function [parent=#MARKEROPS_BASE] Stop end @@ -155,6 +158,7 @@ function MARKEROPS_BASE:OnEventMark(Event) local text = tostring(Event.text) local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll() end + local coalition = Event.IniCoalition -- decision if Event.id==world.event.S_EVENT_MARK_ADDED then self:T({event="S_EVENT_MARK_ADDED", carrier=self.groupname, vec3=Event.pos}) @@ -163,7 +167,7 @@ function MARKEROPS_BASE:OnEventMark(Event) if Eventtext~=nil then if self:_MatchTag(Eventtext) then local matchtable = self:_MatchKeywords(Eventtext) - self:MarkAdded(Eventtext,matchtable,coord) + self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition) end end elseif Event.id==world.event.S_EVENT_MARK_CHANGE then @@ -173,7 +177,7 @@ function MARKEROPS_BASE:OnEventMark(Event) if Eventtext~=nil then if self:_MatchTag(Eventtext) then local matchtable = self:_MatchKeywords(Eventtext) - self:MarkChanged(Eventtext,matchtable,coord,Event.idx) + self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition) end end elseif Event.id==world.event.S_EVENT_MARK_REMOVED then @@ -230,8 +234,10 @@ end -- @param #string To The To state -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator -- @param Core.Point#COORDINATE Coord Coordinate of the marker. -function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord) +function MARKEROPS_BASE:onbeforeMarkAdded(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber) self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()}) end @@ -242,8 +248,10 @@ end -- @param #string To The To state -- @param #string Text The text on the marker -- @param #table Keywords Table of matching keywords found in the Event text + -- @param #number MarkerID Id of this marker + -- @param #number CoalitionNumber Coalition of the marker creator -- @param Core.Point#COORDINATE Coord Coordinate of the marker. -function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord) +function MARKEROPS_BASE:onbeforeMarkChanged(From,Event,To,Text,Keywords,Coord,MarkerID,CoalitionNumber) self:T({self.lid,From,Event,To,Text,Keywords,Coord:ToStringLLDDM()}) end From 7c9cf96d2eacfd9d26b230d8380348f87afe318c Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 9 Mar 2024 17:24:15 +0100 Subject: [PATCH 57/73] OPSGROUP extra check --- Moose Development/Moose/Ops/OpsGroup.lua | 64 +++++++++++++----------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index aa50ece1d..2298aba18 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -508,7 +508,7 @@ OPSGROUP.CargoStatus={ --- OpsGroup version. -- @field #string version -OPSGROUP.version="1.0.0" +OPSGROUP.version="1.0.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -535,7 +535,7 @@ OPSGROUP.version="1.0.0" -- @param Wrapper.Group#GROUP group The GROUP object. Can also be given by its group name as `#string`. -- @return #OPSGROUP self function OPSGROUP:New(group) - + -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #OPSGROUP @@ -554,10 +554,15 @@ function OPSGROUP:New(group) -- Check if group exists. if self.group then if not self:IsExist() then - self:T(self.lid.."ERROR: GROUP does not exist! Returning nil") + self:E(self.lid.."ERROR: GROUP does not exist! Returning nil") return nil end end + + if UTILS.IsInstanceOf(group,"OPSGROUP") then + self:E(self.lid.."ERROR: GROUP is already an OPSGROUP: "..tostring(self.groupname).."!") + return group + end -- Set the template. self:_SetTemplate() @@ -591,33 +596,34 @@ function OPSGROUP:New(group) if units then local masterunit=units[1] --Wrapper.Unit#UNIT - - -- Get Descriptors. - self.descriptors=masterunit:GetDesc() - - -- Set type name. - self.actype=masterunit:GetTypeName() - - -- Is this a submarine. - self.isSubmarine=masterunit:HasAttribute("Submarines") - - -- Has this a datalink? - self.isEPLRS=masterunit:HasAttribute("Datalink") - - if self:IsFlightgroup() then - - self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000 - - self.ceiling=self.descriptors.Hmax - - self.tankertype=select(2, masterunit:IsTanker()) - self.refueltype=select(2, masterunit:IsRefuelable()) - - --env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE)) - --env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE)) - + + if unit then + -- Get Descriptors. + self.descriptors=masterunit:GetDesc() + + -- Set type name. + self.actype=masterunit:GetTypeName() + + -- Is this a submarine. + self.isSubmarine=masterunit:HasAttribute("Submarines") + + -- Has this a datalink? + self.isEPLRS=masterunit:HasAttribute("Datalink") + + if self:IsFlightgroup() then + + self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000 + + self.ceiling=self.descriptors.Hmax + + self.tankertype=select(2, masterunit:IsTanker()) + self.refueltype=select(2, masterunit:IsRefuelable()) + + --env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE)) + --env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE)) + + end end - end -- Init set of detected units. From bd3042410bd0e0039390f45ec980b1c2f63c72bb Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 9 Mar 2024 17:24:32 +0100 Subject: [PATCH 58/73] ccc --- Moose Development/Moose/Ops/OpsGroup.lua | 62 +++++++++++++----------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index aa50ece1d..a9a66c331 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -535,7 +535,7 @@ OPSGROUP.version="1.0.0" -- @param Wrapper.Group#GROUP group The GROUP object. Can also be given by its group name as `#string`. -- @return #OPSGROUP self function OPSGROUP:New(group) - + -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #OPSGROUP @@ -554,10 +554,15 @@ function OPSGROUP:New(group) -- Check if group exists. if self.group then if not self:IsExist() then - self:T(self.lid.."ERROR: GROUP does not exist! Returning nil") + self:E(self.lid.."ERROR: GROUP does not exist! Returning nil") return nil end end + + if UTILS.IsInstanceOf(group,"OPSGROUP") then + self:E(self.lid.."ERROR: GROUP is already an OPSGROUP: "..tostring(self.groupname).."!") + return group + end -- Set the template. self:_SetTemplate() @@ -591,33 +596,34 @@ function OPSGROUP:New(group) if units then local masterunit=units[1] --Wrapper.Unit#UNIT - - -- Get Descriptors. - self.descriptors=masterunit:GetDesc() - - -- Set type name. - self.actype=masterunit:GetTypeName() - - -- Is this a submarine. - self.isSubmarine=masterunit:HasAttribute("Submarines") - - -- Has this a datalink? - self.isEPLRS=masterunit:HasAttribute("Datalink") - - if self:IsFlightgroup() then - - self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000 - - self.ceiling=self.descriptors.Hmax - - self.tankertype=select(2, masterunit:IsTanker()) - self.refueltype=select(2, masterunit:IsRefuelable()) - - --env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE)) - --env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE)) - + + if unit then + -- Get Descriptors. + self.descriptors=masterunit:GetDesc() + + -- Set type name. + self.actype=masterunit:GetTypeName() + + -- Is this a submarine. + self.isSubmarine=masterunit:HasAttribute("Submarines") + + -- Has this a datalink? + self.isEPLRS=masterunit:HasAttribute("Datalink") + + if self:IsFlightgroup() then + + self.rangemax=self.descriptors.range and self.descriptors.range*1000 or 500*1000 + + self.ceiling=self.descriptors.Hmax + + self.tankertype=select(2, masterunit:IsTanker()) + self.refueltype=select(2, masterunit:IsRefuelable()) + + --env.info("DCS Unit BOOM_AND_RECEPTACLE="..tostring(Unit.RefuelingSystem.BOOM_AND_RECEPTACLE)) + --env.info("DCS Unit PROBE_AND_DROGUE="..tostring(Unit.RefuelingSystem.PROBE_AND_DROGUE)) + + end end - end -- Init set of detected units. From 4d8abe7f57f31e6373b23bc2147318095234ae96 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 10 Mar 2024 16:20:06 +0100 Subject: [PATCH 59/73] #MARKEROPS_BASE * Fix event coalition --- Moose Development/Moose/Core/Event.lua | 1 + Moose Development/Moose/Core/MarkerOps_Base.lua | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index d3a105631..5908c032b 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -1378,6 +1378,7 @@ function EVENT:onEvent( Event ) Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos) Event.MarkText=Event.text Event.MarkCoalition=Event.coalition + Event.IniCoalition=Event.coalition Event.MarkGroupID = Event.groupID end diff --git a/Moose Development/Moose/Core/MarkerOps_Base.lua b/Moose Development/Moose/Core/MarkerOps_Base.lua index 664ad3c03..3bc950416 100644 --- a/Moose Development/Moose/Core/MarkerOps_Base.lua +++ b/Moose Development/Moose/Core/MarkerOps_Base.lua @@ -50,7 +50,7 @@ MARKEROPS_BASE = { ClassName = "MARKEROPS", Tag = "mytag", Keywords = {}, - version = "0.1.2", + version = "0.1.3", debug = false, Casesensitive = true, } @@ -158,10 +158,10 @@ function MARKEROPS_BASE:OnEventMark(Event) local text = tostring(Event.text) local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll() end - local coalition = Event.IniCoalition + local coalition = Event.MarkCoalition -- decision if Event.id==world.event.S_EVENT_MARK_ADDED then - self:T({event="S_EVENT_MARK_ADDED", carrier=self.groupname, vec3=Event.pos}) + self:T({event="S_EVENT_MARK_ADDED", carrier=Event.IniGroupName, vec3=Event.pos}) -- Handle event local Eventtext = tostring(Event.text) if Eventtext~=nil then @@ -171,7 +171,7 @@ function MARKEROPS_BASE:OnEventMark(Event) end end elseif Event.id==world.event.S_EVENT_MARK_CHANGE then - self:T({event="S_EVENT_MARK_CHANGE", carrier=self.groupname, vec3=Event.pos}) + self:T({event="S_EVENT_MARK_CHANGE", carrier=Event.IniGroupName, vec3=Event.pos}) -- Handle event. local Eventtext = tostring(Event.text) if Eventtext~=nil then @@ -181,7 +181,7 @@ function MARKEROPS_BASE:OnEventMark(Event) end end elseif Event.id==world.event.S_EVENT_MARK_REMOVED then - self:T({event="S_EVENT_MARK_REMOVED", carrier=self.groupname, vec3=Event.pos}) + self:T({event="S_EVENT_MARK_REMOVED", carrier=Event.IniGroupName, vec3=Event.pos}) -- Hande event. local Eventtext = tostring(Event.text) if Eventtext~=nil then From 11acb578f684e4d352821843632ab01fdda6bd35 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 10 Mar 2024 16:52:46 +0100 Subject: [PATCH 60/73] #SPAWN * Fix an issue for SPAWN:NewFromTemplate when re-using same template over and again --- Moose Development/Moose/Core/Database.lua | 2 +- Moose Development/Moose/Core/Spawn.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 65281c860..cbfa62555 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -932,7 +932,7 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.CountryID = nil SpawnTemplate.CategoryID = nil - self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID ) + self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID, SpawnTemplate.name ) self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 68e3a10a8..01b8d11d9 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -536,7 +536,7 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr end if SpawnTemplate then - self.SpawnTemplate = SpawnTemplate -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! + self.SpawnTemplate = UTILS.DeepCopy(SpawnTemplate) -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!! self.SpawnTemplatePrefix = SpawnTemplatePrefix self.SpawnAliasPrefix = SpawnAliasPrefix or SpawnTemplatePrefix self.SpawnTemplate.name = SpawnTemplatePrefix From 10edd2f9d0c5bb7c196212a908fd83eb3dd3f24b Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 10 Mar 2024 17:59:26 +0100 Subject: [PATCH 61/73] xxx --- Moose Development/Moose/Core/Database.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index cbfa62555..6374b56b6 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -932,7 +932,7 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.CountryID = nil SpawnTemplate.CategoryID = nil - self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID, SpawnTemplate.name ) + self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID) self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) From 176bd0eb8b9b9263d89a51563615498879f46790 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Mon, 11 Mar 2024 08:29:56 +0100 Subject: [PATCH 62/73] xx --- Moose Development/Moose/Core/Database.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 6374b56b6..cbfa62555 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -932,7 +932,7 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.CountryID = nil SpawnTemplate.CategoryID = nil - self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID) + self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID, SpawnTemplate.name ) self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) From 8cf11de774e7800ca38f3fd53e04685722b9d25d Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Mon, 11 Mar 2024 18:18:50 +0100 Subject: [PATCH 63/73] #SPAWN * Small change to keep unitnames when using Razbam's setting IFF via unit names --- Moose Development/Moose/Core/Spawn.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index 01b8d11d9..19af529b0 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -3396,7 +3396,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2 end end end - + if self.SpawnInitKeepUnitNames == false then for UnitID = 1, #SpawnTemplate.units do SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID ) @@ -3404,9 +3404,17 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2 end else for UnitID = 1, #SpawnTemplate.units do - local UnitPrefix, Rest = string.match( SpawnTemplate.units[UnitID].name, "^([^#]+)#?" ):gsub( "^%s*(.-)%s*$", "%1" ) - self:T( { UnitPrefix, Rest } ) - + local SpawnInitKeepUnitIFF = false + if string.find(SpawnTemplate.units[UnitID].name,"#IFF_",1,true) then --Razbam IFF hack for F15E etc + SpawnInitKeepUnitIFF = true + end + local UnitPrefix, Rest + if SpawnInitKeepUnitIFF == false then + UnitPrefix, Rest = string.match( SpawnTemplate.units[UnitID].name, "^([^#]+)#?" ):gsub( "^%s*(.-)%s*$", "%1" ) + self:T( { UnitPrefix, Rest } ) + else + UnitPrefix=SpawnTemplate.units[UnitID].name + end SpawnTemplate.units[UnitID].name = string.format( '%s#%03d-%02d', UnitPrefix, SpawnIndex, UnitID ) SpawnTemplate.units[UnitID].unitId = nil end From 2f81fcb0c01d0d11a7bb28ea98fa05be7c4f9ad6 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Mon, 11 Mar 2024 18:19:19 +0100 Subject: [PATCH 64/73] #STATIC * Add :FindByMatching() and :FindAllByMatching() --- Moose Development/Moose/Wrapper/Static.lua | 60 ++++++++++++++++++++-- 1 file changed, 55 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 933052517..916b78a84 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -12,7 +12,8 @@ -- @image Wrapper_Static.JPG ---- @type STATIC +--- +-- @type STATIC -- @extends Wrapper.Positionable#POSITIONABLE --- Wrapper class to handle Static objects. @@ -236,7 +237,7 @@ function STATIC:SpawnAt(Coordinate, Heading, Delay) end ---- Respawn the @{Wrapper.Unit} at the same location with the same properties. +--- Respawn the @{Wrapper.Static} at the same location with the same properties. -- This is useful to respawn a cargo after it has been destroyed. -- @param #STATIC self -- @param DCS#country.id CountryID (Optional) The country ID used for spawning the new static. Default is same as currently. @@ -248,7 +249,7 @@ function STATIC:ReSpawn(CountryID, Delay) else CountryID=CountryID or self:GetCountry() - + local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, CountryID) SpawnStatic:Spawn(nil, self.StaticName) @@ -270,8 +271,8 @@ function STATIC:ReSpawnAt(Coordinate, Heading, Delay) if Delay and Delay>0 then SCHEDULER:New(nil, self.ReSpawnAt, {self, Coordinate, Heading}, Delay) - else - + else + local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, self:GetCountry()) SpawnStatic:SpawnFromCoordinate(Coordinate, Heading, self.StaticName) @@ -280,3 +281,52 @@ function STATIC:ReSpawnAt(Coordinate, Heading, Delay) return self end + +--- Find the first(!) STATIC matching using patterns. Note that this is **a lot** slower than `:FindByName()`! +-- @param #STATIC self +-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA. +-- @return #STATIC The STATIC. +-- @usage +-- -- Find a static with a partial static name +-- local grp = STATIC:FindByMatching( "Apple" ) +-- -- will return e.g. a static named "Apple-1-1" +-- +-- -- using a pattern +-- local grp = STATIC:FindByMatching( ".%d.%d$" ) +-- -- will return the first static found ending in "-1-1" to "-9-9", but not e.g. "-10-1" +function STATIC:FindByMatching( Pattern ) + local GroupFound = nil + + for name,static in pairs(_DATABASE.STATICS) do + if string.match(name, Pattern ) then + GroupFound = static + break + end + end + + return GroupFound +end + +--- Find all STATIC objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`! +-- @param #STATIC self +-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA. +-- @return #table Groups Table of matching #STATIC objects found +-- @usage +-- -- Find all static with a partial static name +-- local grptable = STATIC:FindAllByMatching( "Apple" ) +-- -- will return all statics with "Apple" in the name +-- +-- -- using a pattern +-- local grp = STATIC:FindAllByMatching( ".%d.%d$" ) +-- -- will return the all statics found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10" +function STATIC:FindAllByMatching( Pattern ) + local GroupsFound = {} + + for name,static in pairs(_DATABASE.STATICS) do + if string.match(name, Pattern ) then + GroupsFound[#GroupsFound+1] = static + end + end + + return GroupsFound +end From aca4e4d7caccb4daa48cdef34a50e4193529b721 Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:49:06 +0100 Subject: [PATCH 65/73] Update Controllable.lua (#2105) Added setting of AI radio options --- .../Moose/Wrapper/Controllable.lua | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 696cdb15b..46556ef21 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -4116,6 +4116,74 @@ function CONTROLLABLE:SetOptionRadarUsingForContinousSearch() return self end +--- [AIR] Set if the AI is reporting passing of waypoints +-- @param #CONTROLLABLE self +-- @param #boolean OnOff If true or nil, AI will report passing waypoints, if false, it will not. +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionWaypointPassReport(OnOff) + self:F2( { self.ControllableName } ) + local onoff = (OnOff == nil or OnOff == true) and false or true + if self:IsAir() then + self:SetOption(AI.Option.Air.id.PROHIBIT_WP_PASS_REPORT,onoff) + end + return self +end + +--- [AIR] Set the AI to not report anything over the radio - radio silence +-- @param #CONTROLLABLE self +-- @param #boolean OnOff If true or nil, radio is set to silence, if false radio silence is lifted. +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioSilence(OnOff) + local onoff = (OnOff == true or OnOff == nil) and true or false + self:F2( { self.ControllableName } ) + if self:IsAir() then + self:SetOption(AI.Option.Air.id.SILENCE,onoff) + end + return self +end + +--- [AIR] Set the AI to report contact for certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioContact(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_CONTACT,Objects) + end + return self +end + +--- [AIR] Set the AI to report engaging certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioEngage(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_ENGAGE,Objects) + end + return self +end + +--- [AIR] Set the AI to report killing certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioKill(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_KILL,Objects) + end + return self +end + --- (GROUND) Relocate controllable to a random point within a given radius; use e.g.for evasive actions; Note that not all ground controllables can actually drive, also the alarm state of the controllable might stop it from moving. -- @param #CONTROLLABLE self -- @param #number speed Speed of the controllable, default 20 From 77c4fd7696e6ed001cff3cfbb74eac42f02d0afc Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:20:57 +0100 Subject: [PATCH 66/73] Update Controllable.lua (#2105) (#2106) Added setting of AI radio options --- .../Moose/Wrapper/Controllable.lua | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 696cdb15b..46556ef21 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -4116,6 +4116,74 @@ function CONTROLLABLE:SetOptionRadarUsingForContinousSearch() return self end +--- [AIR] Set if the AI is reporting passing of waypoints +-- @param #CONTROLLABLE self +-- @param #boolean OnOff If true or nil, AI will report passing waypoints, if false, it will not. +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionWaypointPassReport(OnOff) + self:F2( { self.ControllableName } ) + local onoff = (OnOff == nil or OnOff == true) and false or true + if self:IsAir() then + self:SetOption(AI.Option.Air.id.PROHIBIT_WP_PASS_REPORT,onoff) + end + return self +end + +--- [AIR] Set the AI to not report anything over the radio - radio silence +-- @param #CONTROLLABLE self +-- @param #boolean OnOff If true or nil, radio is set to silence, if false radio silence is lifted. +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioSilence(OnOff) + local onoff = (OnOff == true or OnOff == nil) and true or false + self:F2( { self.ControllableName } ) + if self:IsAir() then + self:SetOption(AI.Option.Air.id.SILENCE,onoff) + end + return self +end + +--- [AIR] Set the AI to report contact for certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioContact(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_CONTACT,Objects) + end + return self +end + +--- [AIR] Set the AI to report engaging certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioEngage(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_ENGAGE,Objects) + end + return self +end + +--- [AIR] Set the AI to report killing certain types of objects. +-- @param #CONTROLLABLE self +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOptionRadioKill(Objects) + self:F2( { self.ControllableName } ) + if not Objects then Objects = {"Air"} end + if type(Objects) ~= "table" then Objects = {Objects} end + if self:IsAir() then + self:SetOption(AI.Option.Air.id.OPTION_RADIO_USAGE_KILL,Objects) + end + return self +end + --- (GROUND) Relocate controllable to a random point within a given radius; use e.g.for evasive actions; Note that not all ground controllables can actually drive, also the alarm state of the controllable might stop it from moving. -- @param #CONTROLLABLE self -- @param #number speed Speed of the controllable, default 20 From 3dd069d7d67470afcde7dbe47fd997159858bd83 Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:25:33 +0100 Subject: [PATCH 67/73] Update Controllable.lua Docu adjustments --- Moose Development/Moose/Wrapper/Controllable.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 46556ef21..df538f28f 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -4144,7 +4144,7 @@ end --- [AIR] Set the AI to report contact for certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioContact(Objects) self:F2( { self.ControllableName } ) @@ -4158,7 +4158,7 @@ end --- [AIR] Set the AI to report engaging certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioEngage(Objects) self:F2( { self.ControllableName } ) @@ -4172,7 +4172,7 @@ end --- [AIR] Set the AI to report killing certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioKill(Objects) self:F2( { self.ControllableName } ) From 241b31fcec3b87701816c677183cd356a93d8a4c Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:26:59 +0100 Subject: [PATCH 68/73] Update Controllable.lua --- Moose Development/Moose/Wrapper/Controllable.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index df538f28f..2817147e4 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -4172,7 +4172,7 @@ end --- [AIR] Set the AI to report killing certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioKill(Objects) self:F2( { self.ControllableName } ) From 470c4ef13c21f4de63138e4ff8b0221682744a6b Mon Sep 17 00:00:00 2001 From: Thomas <72444570+Applevangelist@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:54:44 +0100 Subject: [PATCH 69/73] Update Controllable.lua --- Moose Development/Moose/Wrapper/Controllable.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 46556ef21..25869adcb 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -4144,7 +4144,7 @@ end --- [AIR] Set the AI to report contact for certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioContact(Objects) self:F2( { self.ControllableName } ) @@ -4158,7 +4158,7 @@ end --- [AIR] Set the AI to report engaging certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioEngage(Objects) self:F2( { self.ControllableName } ) @@ -4172,7 +4172,7 @@ end --- [AIR] Set the AI to report killing certain types of objects. -- @param #CONTROLLABLE self --- @param #table Table of attribute names for which AI reports contact. Defaults to {"Air"}. See [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) +-- @param #table Objects Table of attribute names for which AI reports contact. Defaults to {"Air"}, see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_attributes) -- @return #CONTROLLABLE self function CONTROLLABLE:SetOptionRadioKill(Objects) self:F2( { self.ControllableName } ) From f7f28877da96397be6ae7e5356ffb5c4d007e38a Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Wed, 13 Mar 2024 07:39:56 +0100 Subject: [PATCH 70/73] Fix for speed nil in ops groups --- Moose Development/Moose/Ops/ArmyGroup.lua | 2 +- Moose Development/Moose/Ops/FlightGroup.lua | 2 +- Moose Development/Moose/Ops/NavyGroup.lua | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index cdd686524..0e10ab195 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -2069,7 +2069,7 @@ function ARMYGROUP:_InitGroup(Template) self.speedMax=self.group:GetSpeedMax() -- Is group mobile? - if self.speedMax>3.6 then + if self.speedMax and self.speedMax>3.6 then self.isMobile=true else self.isMobile=false diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 1d40e3383..cae49ff7d 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -3799,7 +3799,7 @@ function FLIGHTGROUP:_InitGroup(Template) self.speedMax=group:GetSpeedMax() -- Is group mobile? - if self.speedMax>3.6 then + if self.speedMax and self.speedMax>3.6 then self.isMobile=true else self.isMobile=false diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index 929225ee6..a3d5ebaa8 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -1800,7 +1800,7 @@ function NAVYGROUP:_InitGroup(Template) self.speedMax=self.group:GetSpeedMax() -- Is group mobile? - if self.speedMax>3.6 then + if self.speedMax and self.speedMax>3.6 then self.isMobile=true else self.isMobile=false From 378e76e45b0a1c84766287adff66e258bc386f0d Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Wed, 13 Mar 2024 09:08:39 +0100 Subject: [PATCH 71/73] Added UTILS.ClockHeadingString(refHdg,tgtHdg) thanks to @statua --- Moose Development/Moose/Utilities/Utils.lua | 28 +++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 25cfb7853..6bf7e1fc9 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -3815,3 +3815,31 @@ function UTILS.LoadSetOfOpsGroups(Path,Filename) return datatable end +--- Get the clock position from a relative heading +-- @param #number refHdg The heading of the reference object (such as a Wrapper.UNIT) in 0-360 +-- @param #number tgtHdg The absolute heading from the reference object to the target object/point in 0-360 +-- @return #string text Text in clock heading such as "4 O'CLOCK" +-- @usage Display the range and clock distance of a BTR in relation to REAPER 1-1's heading: +-- +-- myUnit = UNIT:FindByName( "REAPER 1-1" ) +-- myTarget = GROUP:FindByName( "BTR-1" ) +-- +-- coordUnit = myUnit:GetCoordinate() +-- coordTarget = myTarget:GetCoordinate() +-- +-- hdgUnit = myUnit:GetHeading() +-- hdgTarget = coordUnit:HeadingTo( coordTarget ) +-- distTarget = coordUnit:Get3DDistance( coordTarget ) +-- +-- clockString = UTILS.ClockHeadingString( hdgUnit, hdgTarget ) +-- +-- -- Will show this message to REAPER 1-1 in-game: Contact BTR at 3 o'clock for 1134m! +-- MESSAGE:New("Contact BTR at " .. clockString .. " for " .. distTarget .. "m!):ToUnit( myUnit ) +function UTILS.ClockHeadingString(refHdg,tgtHdg) + local relativeAngle = tgtHdg - refHdg + if relativeAngle < 0 then + relativeAngle = relativeAngle + 360 + end + local clockPos = math.ceil((relativeAngle % 360) / 30) + return clockPos.." o'clock" +end From 244abe2bbbfec9dbc38d56d626d34d287db14467 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Fri, 15 Mar 2024 10:25:40 +0100 Subject: [PATCH 72/73] #Minor Fixes --- Moose Development/Moose/Core/Set.lua | 22 +++++++++++++++++++-- Moose Development/Moose/Core/Zone.lua | 22 ++++++++++----------- Moose Development/Moose/Functional/Sead.lua | 3 --- Moose Development/Moose/Wrapper/Group.lua | 2 +- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 212bfc434..af0dfe661 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -1097,6 +1097,7 @@ do GroupPrefixes = nil, Zones = nil, Functions = nil, + Alive = nil, }, FilterMeta = { Coalitions = { @@ -1470,7 +1471,7 @@ do end - --- Builds a set of groups that are only active. + --- Builds a set of groups that are active, ie in the mission but not yet activated (false) or actived (true). -- Only the groups that are active will be included within the set. -- @param #SET_GROUP self -- @param #boolean Active (Optional) Include only active groups to the set. @@ -1495,6 +1496,14 @@ do self.Filter.Active = Active return self end + + --- Build a set of groups that are alive. + -- @param #SET_GROUP self + -- @return #SET_GROUP self + function SET_GROUP:FilterAlive() + self.Filter.Alive = true + return self + end --- Starts the filtering. -- @param #SET_GROUP self @@ -1993,7 +2002,16 @@ do function SET_GROUP:IsIncludeObject( MGroup ) self:F2( MGroup ) local MGroupInclude = true - + + if self.Filter.Alive == true then + local MGroupAlive = false + self:F( { Active = self.Filter.Active } ) + if MGroup and MGroup:IsAlive() then + MGroupAlive = true + end + MGroupInclude = MGroupInclude and MGroupAlive + end + if self.Filter.Active ~= nil then local MGroupActive = false self:F( { Active = self.Filter.Active } ) diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 12df09b32..d2432703a 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -330,14 +330,14 @@ function ZONE_BASE:GetRandomVec2() return nil end ---- Define a random @{Core.Point#POINT_VEC2} within the zone. +--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_BASE self -- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. function ZONE_BASE:GetRandomPointVec2() return nil end ---- Define a random @{Core.Point#POINT_VEC3} within the zone. +--- Define a random @{Core.Point#POINT_VEC3} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. -- @param #ZONE_BASE self -- @return Core.Point#POINT_VEC3 The PointVec3 coordinates. function ZONE_BASE:GetRandomPointVec3() @@ -1515,7 +1515,7 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes) return point end ---- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. +--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_RADIUS self -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. @@ -1546,7 +1546,7 @@ function ZONE_RADIUS:GetRandomVec3( inner, outer ) end ---- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone. +--- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. -- @param #ZONE_RADIUS self -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. @@ -1990,7 +1990,7 @@ function ZONE_GROUP:GetRandomVec2() return Point end ---- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. +--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_GROUP self -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. @@ -2834,7 +2834,7 @@ function ZONE_POLYGON_BASE:GetRandomVec2() end end ---- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone. +--- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_POLYGON_BASE self -- @return @{Core.Point#POINT_VEC2} function ZONE_POLYGON_BASE:GetRandomPointVec2() @@ -2847,7 +2847,7 @@ function ZONE_POLYGON_BASE:GetRandomPointVec2() return PointVec2 end ---- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. +--- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. -- @param #ZONE_POLYGON_BASE self -- @return @{Core.Point#POINT_VEC3} function ZONE_POLYGON_BASE:GetRandomPointVec3() @@ -3835,18 +3835,18 @@ function ZONE_OVAL:GetRandomVec2() return {x=rx, y=ry} end ---- Define a random @{Core.Point#POINT_VEC2} within the zone. +--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_OVAL self -- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. function ZONE_OVAL:GetRandomPointVec2() return POINT_VEC2:NewFromVec2(self:GetRandomVec2()) end ---- Define a random @{Core.Point#POINT_VEC2} within the zone. +--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table. -- @param #ZONE_OVAL self -- @return Core.Point#POINT_VEC2 The PointVec2 coordinates. function ZONE_OVAL:GetRandomPointVec3() - return POINT_VEC2:NewFromVec3(self:GetRandomVec2()) + return POINT_VEC3:NewFromVec3(self:GetRandomVec2()) end --- Draw the zone on the F10 map. @@ -3986,7 +3986,7 @@ do -- ZONE_AIRBASE return ZoneVec2 end - --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. + --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table. -- @param #ZONE_AIRBASE self -- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. diff --git a/Moose Development/Moose/Functional/Sead.lua b/Moose Development/Moose/Functional/Sead.lua index 7b1958fbb..c50e2d310 100644 --- a/Moose Development/Moose/Functional/Sead.lua +++ b/Moose Development/Moose/Functional/Sead.lua @@ -320,9 +320,6 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG end local seadset = SET_GROUP:New():FilterPrefixes(self.SEADGroupPrefixes):FilterZones({targetzone}):FilterOnce() - local tgtcoord = targetzone:GetRandomPointVec2() - --if tgtcoord and tgtcoord.ClassName == "COORDINATE" then - --local tgtgrp = seadset:FindNearestGroupFromPointVec2(tgtcoord) local tgtgrp = seadset:GetRandom() local _targetgroup = nil local _targetgroupname = "none" diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 6beaa3b00..a15005b3c 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -426,7 +426,7 @@ function GROUP:IsActive() local DCSGroup = self:GetDCSObject() -- DCS#Group - if DCSGroup then + if DCSGroup and DCSGroup:isExist() then local unit = DCSGroup:getUnit(1) if unit then local GroupIsActive = unit:isActive() From 3389d3284a4409b6c334671388947108cfc4b8a5 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 16 Mar 2024 12:37:11 +0100 Subject: [PATCH 73/73] Fix self.speedmax for immobile groups --- Moose Development/Moose/Ops/ArmyGroup.lua | 1 + Moose Development/Moose/Ops/FlightGroup.lua | 1 + Moose Development/Moose/Ops/NavyGroup.lua | 1 + 3 files changed, 3 insertions(+) diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 0e10ab195..9fe627e13 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -2073,6 +2073,7 @@ function ARMYGROUP:_InitGroup(Template) self.isMobile=true else self.isMobile=false + self.speedMax = 0 end -- Cruise speed in km/h diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index cae49ff7d..8a0095954 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -3803,6 +3803,7 @@ function FLIGHTGROUP:_InitGroup(Template) self.isMobile=true else self.isMobile=false + self.speedMax = 0 end -- Cruise speed limit 380 kts for fixed and 110 knots for rotary wings. diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index a3d5ebaa8..0ed715fc9 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -1804,6 +1804,7 @@ function NAVYGROUP:_InitGroup(Template) self.isMobile=true else self.isMobile=false + self.speedMax = 0 end -- Cruise speed: 70% of max speed.