Merge pull request #524 from FlightControl-Master/master

Release 2.1 preparation
This commit is contained in:
Sven Van de Velde 2017-05-17 06:11:25 +02:00 committed by GitHub
commit da842491d0
537 changed files with 90010 additions and 9339 deletions

2
.gitignore vendored
View File

@ -5,7 +5,6 @@
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
@ -45,7 +44,6 @@ local.properties
[Rr]elease/
x64/
build/
[Bb]in/
[Oo]bj/
# MSTest test Results

View File

@ -1,163 +0,0 @@
.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
lua \- Lua interpreter
.SH SYNOPSIS
.B lua
[
.I options
]
[
.I script
[
.I args
]
]
.SH DESCRIPTION
.B lua
is the stand-alone Lua interpreter.
It loads and executes Lua programs,
either in textual source form or
in precompiled binary form.
(Precompiled binaries are output by
.BR luac ,
the Lua compiler.)
.B lua
can be used as a batch interpreter and also interactively.
.LP
The given
.I options
(see below)
are executed and then
the Lua program in file
.I script
is loaded and executed.
The given
.I args
are available to
.I script
as strings in a global table named
.BR arg .
If these arguments contain spaces or other characters special to the shell,
then they should be quoted
(but note that the quotes will be removed by the shell).
The arguments in
.B arg
start at 0,
which contains the string
.RI ' script '.
The index of the last argument is stored in
.BR arg.n .
The arguments given in the command line before
.IR script ,
including the name of the interpreter,
are available in negative indices in
.BR arg .
.LP
At the very start,
before even handling the command line,
.B lua
executes the contents of the environment variable
.BR LUA_INIT ,
if it is defined.
If the value of
.B LUA_INIT
is of the form
.RI '@ filename ',
then
.I filename
is executed.
Otherwise, the string is assumed to be a Lua statement and is executed.
.LP
Options start with
.B '\-'
and are described below.
You can use
.B "'\--'"
to signal the end of options.
.LP
If no arguments are given,
then
.B "\-v \-i"
is assumed when the standard input is a terminal;
otherwise,
.B "\-"
is assumed.
.LP
In interactive mode,
.B lua
prompts the user,
reads lines from the standard input,
and executes them as they are read.
If a line does not contain a complete statement,
then a secondary prompt is displayed and
lines are read until a complete statement is formed or
a syntax error is found.
So, one way to interrupt the reading of an incomplete statement is
to force a syntax error:
adding a
.B ';'
in the middle of a statement is a sure way of forcing a syntax error
(except inside multiline strings and comments; these must be closed explicitly).
If a line starts with
.BR '=' ,
then
.B lua
displays the values of all the expressions in the remainder of the
line. The expressions must be separated by commas.
The primary prompt is the value of the global variable
.BR _PROMPT ,
if this value is a string;
otherwise, the default prompt is used.
Similarly, the secondary prompt is the value of the global variable
.BR _PROMPT2 .
So,
to change the prompts,
set the corresponding variable to a string of your choice.
You can do that after calling the interpreter
or on the command line
(but in this case you have to be careful with quotes
if the prompt string contains a space; otherwise you may confuse the shell.)
The default prompts are "> " and ">> ".
.SH OPTIONS
.TP
.B \-
load and execute the standard input as a file,
that is,
not interactively,
even when the standard input is a terminal.
.TP
.BI \-e " stat"
execute statement
.IR stat .
You need to quote
.I stat
if it contains spaces, quotes,
or other characters special to the shell.
.TP
.B \-i
enter interactive mode after
.I script
is executed.
.TP
.BI \-l " name"
call
.BI require(' name ')
before executing
.IR script .
Typically used to load libraries.
.TP
.B \-v
show version information.
.SH "SEE ALSO"
.BR luac (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
R. Ierusalimschy,
L. H. de Figueiredo,
and
W. Celes
.\" EOF

View File

@ -1,136 +0,0 @@
.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
.SH NAME
luac \- Lua compiler
.SH SYNOPSIS
.B luac
[
.I options
] [
.I filenames
]
.SH DESCRIPTION
.B luac
is the Lua compiler.
It translates programs written in the Lua programming language
into binary files that can be later loaded and executed.
.LP
The main advantages of precompiling chunks are:
faster loading,
protecting source code from accidental user changes,
and
off-line syntax checking.
.LP
Pre-compiling does not imply faster execution
because in Lua chunks are always compiled into bytecodes before being executed.
.B luac
simply allows those bytecodes to be saved in a file for later execution.
.LP
Pre-compiled chunks are not necessarily smaller than the corresponding source.
The main goal in pre-compiling is faster loading.
.LP
The binary files created by
.B luac
are portable only among architectures with the same word size and byte order.
.LP
.B luac
produces a single output file containing the bytecodes
for all source files given.
By default,
the output file is named
.BR luac.out ,
but you can change this with the
.B \-o
option.
.LP
In the command line,
you can mix
text files containing Lua source and
binary files containing precompiled chunks.
This is useful to combine several precompiled chunks,
even from different (but compatible) platforms,
into a single precompiled chunk.
.LP
You can use
.B "'\-'"
to indicate the standard input as a source file
and
.B "'\--'"
to signal the end of options
(that is,
all remaining arguments will be treated as files even if they start with
.BR "'\-'" ).
.LP
The internal format of the binary files produced by
.B luac
is likely to change when a new version of Lua is released.
So,
save the source files of all Lua programs that you precompile.
.LP
.SH OPTIONS
Options must be separate.
.TP
.B \-l
produce a listing of the compiled bytecode for Lua's virtual machine.
Listing bytecodes is useful to learn about Lua's virtual machine.
If no files are given, then
.B luac
loads
.B luac.out
and lists its contents.
.TP
.BI \-o " file"
output to
.IR file ,
instead of the default
.BR luac.out .
(You can use
.B "'\-'"
for standard output,
but not on platforms that open standard output in text mode.)
The output file may be a source file because
all files are loaded before the output file is written.
Be careful not to overwrite precious files.
.TP
.B \-p
load files but do not generate any output file.
Used mainly for syntax checking and for testing precompiled chunks:
corrupted files will probably generate errors when loaded.
Lua always performs a thorough integrity test on precompiled chunks.
Bytecode that passes this test is completely safe,
in the sense that it will not break the interpreter.
However,
there is no guarantee that such code does anything sensible.
(None can be given, because the halting problem is unsolvable.)
If no files are given, then
.B luac
loads
.B luac.out
and tests its contents.
No messages are displayed if the file passes the integrity test.
.TP
.B \-s
strip debug information before writing the output file.
This saves some space in very large chunks,
but if errors occur when running a stripped chunk,
then the error messages may not contain the full information they usually do.
For instance,
line numbers and names of local variables are lost.
.TP
.B \-v
show version information.
.SH FILES
.TP 15
.B luac.out
default output file
.SH "SEE ALSO"
.BR lua (1)
.br
http://www.lua.org/
.SH DIAGNOSTICS
Error messages should be self explanatory.
.SH AUTHORS
L. H. de Figueiredo,
R. Ierusalimschy and
W. Celes
.\" EOF

View File

@ -1,246 +0,0 @@
; MooseDevelopmentEnvironmentSetup.exe
; ------------------------------------
; This program sets up the Moose Development Evironment for Testers and Developers.
; The goal is to make it easy to use the Dynamic Loading Moose.lua, which is more suitable for rapid development and regular changes
; than its static counterpart.
;
; Author : Hugues "GreyEcho" Bousquet
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <MsgBoxConstants.au3>
#include <FileConstants.au3>
#include <EditConstants.au3>
#Include <GUIEdit.au3>
#Include <ScrollBarConstants.au3>
#include <File.au3>
Global $7zipPath
Global $DCSWorldPath
Global $RepoPath
Global $DCSWorldScriptsMoosePath
Global $MooseDevFolderPath
Global $Log
Global $ProgramFilesDir = @HomeDrive & '\Program Files\'
Func CleanExit()
_FileWriteLog($Log, 'INFO:'&@TAB&'Program exited cleanly'&@CRLF)
FileClose($Log)
Exit
EndFunc
Func Welcome()
#Region ### START Koda GUI section ### Form=
$Form2 = GUICreate("Welcome", 532, 150, 620, 457)
$Label1 = GUICtrlCreateLabel("Welcome to Moose ! ", 120, 16, 217, 33)
GUICtrlSetFont(-1, 18, 800, 0, "Calibri")
$Label2 = GUICtrlCreateLabel("This tool is designed to help you setup your Moose development environment.", 104, 56, 370, 17)
$Button1 = GUICtrlCreateButton("&OK", 268, 115, 75, 25)
$Button2 = GUICtrlCreateButton("&Cancel", 187, 116, 75, 25)
$Label3 = GUICtrlCreateLabel("Before you proceed, please make sure that you correctly installed GitHub, as well as 7-zip.", 104, 80, 423, 17)
$Pic1 = GUICtrlCreatePic("C:\Users\Hugues\Desktop\Moose\MOOSE_Logo_Primary_Color.jpg", 8, 8, 89, 89)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
_FileWriteLog($Log, 'INFO:'&@TAB&'In window "Welcome"'&@CRLF)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
case $GUI_EVENT_CLOSE
GUIDelete()
CleanExit()
case $Button2
GUIDelete()
CleanExit()
case $Button1
GUIDelete()
ExitLoop
EndSwitch
WEnd
EndFunc
Func FoldersLocation()
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Location of your Folders", 603, 237, 585, 425)
$GroupBox1 = GUICtrlCreateGroup("Folder Locations ", 8, 9, 585, 185)
$Input1 = GUICtrlCreateInput("C:\Program Files\7-Zip\", 24, 48, 505, 21)
$Label1 = GUICtrlCreateLabel("7-Zip Location", 24, 32, 72, 17)
$Input2 = GUICtrlCreateInput("C:\Program Files\Eagle Dynamics\DCS World\", 24, 104, 505, 21)
$Label2 = GUICtrlCreateLabel("DCS World Install Location", 24, 88, 131, 17)
$Input3 = GUICtrlCreateInput("C:\Users\Hugues\Documents\GitHub\MOOSE\", 24, 160, 505, 21)
$Label3 = GUICtrlCreateLabel("MOOSE Local Repository Location", 24, 144, 169, 17)
$Button3 = GUICtrlCreateButton("Browse", 528, 48, 57, 21)
$Button4 = GUICtrlCreateButton("Browse", 528, 104, 57, 21)
$Button5 = GUICtrlCreateButton("Browse", 528, 160, 57, 21)
GUICtrlCreateGroup("", -99, -99, 1, 1)
$Button1 = GUICtrlCreateButton("&OK", 308, 203, 75, 25)
$Button2 = GUICtrlCreateButton("&Cancel", 219, 204, 75, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
_FileWriteLog($Log, 'INFO:'&@TAB&'In window "Folders Location"'&@CRLF)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
case $GUI_EVENT_CLOSE
GUIDelete()
CleanExit()
case $Button2
GUIDelete()
CleanExit()
; Browse buttons
case $Button3
$7zipPath = FileSelectFolder("Select the 7-Zip Installation Folder", $ProgramFilesDir)
If $7zipPath Then
GUICtrlSetData($Input1, $7zipPath)
EndIf
case $Button4
$DCSWorldPath = FileSelectFolder("Select the DCS World Installation Folder", $ProgramFilesDir)
If $DCSWorldPath Then
GUICtrlSetData($Input2, $DCSWorldPath)
EndIf
case $Button5
$RepoPath = FileSelectFolder("Select the local MOOSE GitHub Repository Folder", @MyDocumentsDir)
If $RepoPath Then
GUICtrlSetData($Input3, $RepoPath)
EndIf
; ok !
case $Button1
If FileExists(GUICtrlRead($Input1)) and FileExists(GUICtrlRead($Input2)) and FileExists(GUICtrlRead($Input3)) Then
$7zipPath = GUICtrlRead($Input1)
$DCSWorldPath = GUICtrlRead($Input2)
$RepoPath = GUICtrlRead($Input3)
; add trailing '\' when necessary
If StringRight($7zipPath, 1) <> "\" Then
$7zipPath &= "\"
EndIf
If StringRight($DCSWorldPath, 1) <> "\" Then
$DCSWorldPath &= "\"
EndIf
If StringRight($RepoPath, 1) <> "\" Then
$RepoPath &= "\"
EndIf
DirCreate($DCSWorldPath&'Scripts\Moose\')
$DCSWorldScriptsMoosePath = $DCSWorldPath & 'Scripts\Moose\'
$MooseDevFolderPath = $RepoPath & 'Moose Development\Moose\'
_FileWriteLog($Log, 'INFO:'&@TAB&'7Zip Path : '&$7zipPath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'DCS World Path : '&$DCSWorldPath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'Moose Repo Path : '&$RepoPath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'DCS World Scripts Path : '&$DCSWorldScriptsMoosePath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'Moose Development Folder Path : '&$MooseDevFolderPath&@CRLF)
GUIDelete()
ExitLoop
Else
MsgBox(16, "Error", "One of the file paths is invalid, please check again.") ; TODO : Which one is wrong ?
_FileWriteLog($Log, 'ERROR:'&@TAB&'One of the paths is invalid'&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'7Zip Path : '&$7zipPath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'DCS World Path : '&$DCSWorldPath&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'Moose Repo Path : '&$RepoPath&@CRLF)
EndIf
EndSwitch
Wend
EndFunc
Func SetupInProgress()
#Region ### START Koda GUI section ### Form=
$Form3 = GUICreate("Setup In Progress", 522, 237, 638, 427)
$Button1 = GUICtrlCreateButton("&OK", 223, 203, 75, 25)
$Edit1 = GUICtrlCreateEdit("", 8, 8, 505, 185)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUICtrlSetState($Button1, $GUI_DISABLE)
local $InstallSuccessfull = 1
_FileWriteLog($Log, 'INFO:'&@TAB&'In window "SetupInProgress"'&@CRLF)
local $TrimmedMooseDevFolderPath = StringTrimRight($MooseDevFolderPath, 1)
; Create the Dynamic Link
If FileCreateNTFSLink($TrimmedMooseDevFolderPath, $DCSWorldScriptsMoosePath, $FC_OVERWRITE) Then
_FileWriteLog($Log, 'INFO:'&@TAB&"Hard Link created for "&$TrimmedMooseDevFolderPath&" in "&$DCSWorldScriptsMoosePath&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "Hard Link Ccreated... Ok!"&@CRLF)
Else
_FileWriteLog($Log, 'ERROR:'&@TAB&"Couldn't create a hard link for "&$TrimmedMooseDevFolderPath&" in "&$DCSWorldScriptsMoosePath&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "ERROR : Couldn't create a hard link for "&$TrimmedMooseDevFolderPath&" in "&$DCSWorldScriptsMoosePath&@CRLF)
$InstallSuccessfull = 0
EndIf
; Get the current PATH and append 7Zip's path to it
local $NewPathContent = EnvGet("PATH")
If StringRight($NewPathContent, 1) <> ";" Then
$NewPathContent &= ";"
EndIf
$NewPathContent &= $7zipPath
; Add the 7zip folder path to %PATH%
If Not StringInStr(EnvGet("PATH"), "7-Zip") Then
If RegWrite("HKEY_CURRENT_USER\Environment", "Path", "REG_SZ", $NewPathContent) Then
_FileWriteLog($Log, 'INFO:'&@TAB&$7zipPath&" added to %PATH%. PATH = "&EnvGet("PATH")&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "%PATH% Evrionment Variable updated... Ok!"&@CRLF)
Else
_FileWriteLog($Log, 'ERROR:'&@TAB&$7zipPath&" could not to %PATH%. Command :"&'"' & @ComSpec & '" /k ' & 'setx /M PATH "%PATH%;' & $7zipPath&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "ERROR : Couldn't add "&$7zipPath&" to %PATH%"&@CRLF)
$InstallSuccessfull = 0
EndIf
Else
_FileWriteLog($Log, 'INFO:'&@TAB&$7zipPath&" is already set in %PATH%. PATH = "&EnvGet("PATH")&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "INFO : %PATH% already stores the 7-Zip folder path, no need to modify"&@CRLF)
EndIf
; Copy lua folder to ProgramFiles
local $TrimmedLuaPath = @ScriptDir&"\LuaFiles"
local $TrimmedProgramFilesDir = StringTrimRight($ProgramFilesDir, 1)
If DirCopy($TrimmedLuaPath, $TrimmedProgramFilesDir, $FC_OVERWRITE) Then
_FileWriteLog($Log, 'INFO:'&@TAB&$TrimmedLuaPath&" successfully copied to "&$TrimmedProgramFilesDir&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "Lua 5.1 Installation... Ok!"&@CRLF)
Else
_FileWriteLog($Log, 'ERROR:'&@TAB&"Could not copy "&$TrimmedLuaPath&" to "&$TrimmedProgramFilesDir&@CRLF)
_GUICtrlEdit_AppendText($Edit1, "ERROR : Could not install lua 5.1 in "&$ProgramFilesDir&" Please retry, running this program is admin"&@CRLF)
$InstallSuccessfull = 0
EndIf
; Succesfull Message
If $InstallSuccessfull Then
_GUICtrlEdit_AppendText($Edit1, "Setup Complete !"&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'Setup Successful. Please reboot the computer.'&@CRLF)
Else
_GUICtrlEdit_AppendText($Edit1, "Setup finished, but some problem occured. Please fix them manually or retry the installation process."&@CRLF)
_FileWriteLog($Log, 'INFO:'&@TAB&'Setup finished, but some error occured'&@CRLF)
EndIf
GUICtrlSetState($Button1, $GUI_ENABLE)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
case $GUI_EVENT_CLOSE
GUIDelete()
CleanExit()
case $Button1
MsgBox(64, "Reboot", "You need to reboot your system to be able to use the automated .miz manipualtion tools") ; TODO : Automtically reboot ?
GUIDelete()
CleanExit()
EndSwitch
WEnd
EndFunc
While 1
$Log = FileOpen(@ScriptDir & "\mdes.log", 1)
FileWrite($Log, @CRLF&'New Session !'&@CRLF&'============='&@CRLF)
Welcome()
FoldersLocation()
SetupInProgress()
WEnd

View File

@ -3,7 +3,6 @@
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${system_path:luadocumentor.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose\Core\*.lua&quot; &#13;&#10;&quot;Moose\Wrapper\*.lua&quot; &#13;&#10;&quot;Moose\Actions\*.lua&quot; &#13;&#10;&quot;Moose\Functional\*.lua&quot; &#13;&#10;&quot;Moose\Tasking\*.lua&quot; &#13;&#10;&quot;Moose\Utilities\*.lua&quot; &#13;&#10;&quot;Moose\AI\*.lua&quot; &#13;&#10;--dir &quot;${workspace_loc:/Moose_Framework/docs/Documentation}&#13;&#10;--style ${workspace_loc:/Moose_Framework/docs/Stylesheet/stylesheet.css}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Development}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/GenerateDocumentations.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Utils}"/>
</launchConfiguration>

View File

@ -3,7 +3,7 @@
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${system_path:lua.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose_Create.lua&quot; &#13;&#10;&quot;D&quot;&#13;&#10;&quot;${current_date}&quot; &#13;&#10;&quot;${workspace_loc:/Moose_Framework//Moose Development/Moose}&quot; &#13;&#10;&quot;${workspace_loc:/Moose_Framework/Moose Mission Setup}&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
</launchConfiguration>

View File

@ -3,7 +3,7 @@
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${system_path:lua.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Utils/luarocks/lua5.1.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose_Create.lua&quot; &#13;&#10;&quot;S&quot;&#13;&#10;&quot;${current_date}&quot; &#13;&#10;&quot;${workspace_loc:/Moose_Framework//Moose Development/Moose}&quot; &#13;&#10;&quot;${workspace_loc:/Moose_Framework/Moose Mission Setup}&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup}"/>
</launchConfiguration>

View File

@ -4,6 +4,5 @@
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${workspace_loc:/Moose_Framework/Moose Test Missions}&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Missions}"/>
</launchConfiguration>

View File

@ -4,6 +4,6 @@
<listEntry value="org.eclipse.ui.externaltools.launchGroup"/>
</listAttribute>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="${selected_resource_loc}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;${selected_resource_loc}&quot;"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework/Moose Mission Setup/Moose Mission Update}"/>
</launchConfiguration>

Binary file not shown.

View File

@ -0,0 +1,674 @@
--- **AI** -- **Provide Battlefield Air Interdiction (bombing).**
--
-- ![Banner Image](..\Presentations\AI_BAI\Dia1.JPG)
--
-- ===
--
-- AI_BAI classes makes AI Controllables execute bombing tasks.
--
-- There are the following types of BAI classes defined:
--
-- * @{#AI_BAI_ZONE}: Perform a BAI in a zone.
--
-- ====
--
-- # Demo Missions
--
-- ### [AI_BAI Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/BOMB%20-%20Close%20Air%20Support)
--
-- ### [AI_BAI Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BOMB%20-%20Close%20Air%20Support)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [AI_BAI YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2)
--
-- ===
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- 2017-01-15: Initial class and API.
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
--
-- @module AI_Bai
--- AI_BAI_ZONE class
-- @type AI_BAI_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # AI_BAI_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE}
--
-- AI_BAI_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
--
-- The AI_BAI_ZONE class implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
--
-- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG)
--
-- The AI_BAI_ZONE is assigned a @{Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event.
--
-- ![Start Event](..\Presentations\AI_BAI\Dia4.JPG)
--
-- Upon started, The AI will **Route** itself towards the random 3D point within a patrol zone,
-- using a random speed within the given altitude and speed limits.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
-- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
--
-- ![Route Event](..\Presentations\AI_BAI\Dia5.JPG)
--
-- When the AI is commanded to provide BattleGround Air Interdiction (through the event **Engage**), the AI will fly towards the Engage Zone.
-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia6.JPG)
--
-- The AI will detect the targets and will only destroy the targets within the Engage Zone.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia7.JPG)
--
-- Every target that is destroyed, is reported< by the AI.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia8.JPG)
--
-- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia9.JPG)
--
-- Until it is notified through the event **Accomplish**, which is to be triggered by an observing party:
--
-- * a FAC
-- * a timed event
-- * a menu option selected by a human
-- * a condition
-- * others ...
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia10.JPG)
--
-- When the AI has accomplished the Bombing, it will fly back to the Patrol Zone.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia11.JPG)
--
-- It will keep patrolling there, until it is notified to RTB or move to another BOMB Zone.
-- It can be notified to go RTB through the **RTB** event.
--
-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
--
-- ![Engage Event](..\Presentations\AI_BAI\Dia12.JPG)
--
-- # 1. AI_BAI_ZONE constructor
--
-- * @{#AI_BAI_ZONE.New}(): Creates a new AI_BAI_ZONE object.
--
-- ## 2. AI_BAI_ZONE is a FSM
--
-- ![Process](..\Presentations\AI_BAI\Dia2.JPG)
--
-- ### 2.1. AI_BAI_ZONE States
--
-- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing BOMB.
-- * **Returning** ( Group ): The AI is returning to Base..
--
-- ### 2.2. AI_BAI_ZONE Events
--
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
-- * **@{#AI_BAI_ZONE.Engage}**: Engage the AI to provide BOMB in the Engage Zone, destroying any target it finds.
-- * **@{#AI_BAI_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
-- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Unit}.
-- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the BOMB task.
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
--
-- ## 3. Modify the Engage Zone behaviour to pinpoint a **map object** or **scenery object**
--
-- Use the method @{#AI_BAI_ZONE.SearchOff}() to specify that the EngageZone is not to be searched for potential targets (UNITs), but that the center of the zone
-- is the point where a map object is to be destroyed (like a bridge).
--
-- Example:
--
-- -- Tell the BAI not to search for potential targets in the BAIEngagementZone, but rather use the center of the BAIEngagementZone as the bombing location.
-- AIBAIZone:SearchOff()
--
-- Searching can be switched back on with the method @{#AI_BAI_ZONE.SearchOn}(). Use the method @{#AI_BAI_ZONE.SearchOnOff}() to flexibily switch searching on or off.
--
-- ===
--
-- @field #AI_BAI_ZONE
AI_BAI_ZONE = {
ClassName = "AI_BAI_ZONE",
}
--- Creates a new AI_BAI_ZONE object
-- @param #AI_BAI_ZONE self
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
-- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen.
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
-- @return #AI_BAI_ZONE self
function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType )
-- Inherits from BASE
local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_BAI_ZONE
self.EngageZone = EngageZone
self.Accomplished = false
self:SetDetectionZone( self.EngageZone )
self:SearchOn()
self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
--- OnBefore Transition Handler for Event Engage.
-- @function [parent=#AI_BAI_ZONE] OnBeforeEngage
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Engage.
-- @function [parent=#AI_BAI_ZONE] OnAfterEngage
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Engage.
-- @function [parent=#AI_BAI_ZONE] Engage
-- @param #AI_BAI_ZONE self
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- Asynchronous Event Trigger for Event Engage.
-- @function [parent=#AI_BAI_ZONE] __Engage
-- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
--- OnLeave Transition Handler for State Engaging.
-- @function [parent=#AI_BAI_ZONE] OnLeaveEngaging
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Engaging.
-- @function [parent=#AI_BAI_ZONE] OnEnterEngaging
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
self:AddTransition( "Engaging", "Target", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
--- OnBefore Transition Handler for Event Fired.
-- @function [parent=#AI_BAI_ZONE] OnBeforeFired
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Fired.
-- @function [parent=#AI_BAI_ZONE] OnAfterFired
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Fired.
-- @function [parent=#AI_BAI_ZONE] Fired
-- @param #AI_BAI_ZONE self
--- Asynchronous Event Trigger for Event Fired.
-- @function [parent=#AI_BAI_ZONE] __Fired
-- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds.
self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
--- OnBefore Transition Handler for Event Destroy.
-- @function [parent=#AI_BAI_ZONE] OnBeforeDestroy
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Destroy.
-- @function [parent=#AI_BAI_ZONE] OnAfterDestroy
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Destroy.
-- @function [parent=#AI_BAI_ZONE] Destroy
-- @param #AI_BAI_ZONE self
--- Asynchronous Event Trigger for Event Destroy.
-- @function [parent=#AI_BAI_ZONE] __Destroy
-- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
--- OnBefore Transition Handler for Event Abort.
-- @function [parent=#AI_BAI_ZONE] OnBeforeAbort
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Abort.
-- @function [parent=#AI_BAI_ZONE] OnAfterAbort
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Abort.
-- @function [parent=#AI_BAI_ZONE] Abort
-- @param #AI_BAI_ZONE self
--- Asynchronous Event Trigger for Event Abort.
-- @function [parent=#AI_BAI_ZONE] __Abort
-- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE.
--- OnBefore Transition Handler for Event Accomplish.
-- @function [parent=#AI_BAI_ZONE] OnBeforeAccomplish
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event Accomplish.
-- @function [parent=#AI_BAI_ZONE] OnAfterAccomplish
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- Synchronous Event Trigger for Event Accomplish.
-- @function [parent=#AI_BAI_ZONE] Accomplish
-- @param #AI_BAI_ZONE self
--- Asynchronous Event Trigger for Event Accomplish.
-- @function [parent=#AI_BAI_ZONE] __Accomplish
-- @param #AI_BAI_ZONE self
-- @param #number Delay The delay in seconds.
return self
end
--- Set the Engage Zone where the AI is performing BOMB. Note that if the EngageZone is changed, the AI needs to re-detect targets.
-- @param #AI_BAI_ZONE self
-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing BOMB.
-- @return #AI_BAI_ZONE self
function AI_BAI_ZONE:SetEngageZone( EngageZone )
self:F2()
if EngageZone then
self.EngageZone = EngageZone
else
self.EngageZone = nil
end
end
--- Specifies whether to search for potential targets in the zone, or let the center of the zone be the bombing coordinate.
-- AI_BAI_ZONE will search for potential targets by default.
-- @param #AI_BAI_ZONE self
-- @return #AI_BAI_ZONE
function AI_BAI_ZONE:SearchOnOff( Search )
self.Search = Search
return self
end
--- If Search is Off, the current zone coordinate will be the center of the bombing.
-- @param #AI_BAI_ZONE self
-- @return #AI_BAI_ZONE
function AI_BAI_ZONE:SearchOff()
self:SearchOnOff( false )
return self
end
--- If Search is On, BAI will search for potential targets in the zone.
-- @param #AI_BAI_ZONE self
-- @return #AI_BAI_ZONE
function AI_BAI_ZONE:SearchOn()
self:SearchOnOff( true )
return self
end
--- onafter State Transition for Event Start.
-- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_BAI_ZONE:onafterStart( Controllable, From, Event, To )
-- Call the parent Start event handler
self:GetParent(self).onafterStart( self, Controllable, From, Event, To )
self:HandleEvent( EVENTS.Dead )
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
end
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
function _NewEngageRoute( AIControllable )
AIControllable:T( "NewEngageRoute" )
local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_BAI#AI_BAI_ZONE
EngageZone:__Engage( 1, EngageZone.EngageSpeed, EngageZone.EngageAltitude, EngageZone.EngageWeaponExpend, EngageZone.EngageAttackQty, EngageZone.EngageDirection )
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_BAI_ZONE:onbeforeEngage( Controllable, From, Event, To )
if self.Accomplished == true then
return false
end
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_BAI_ZONE:onafterTarget( Controllable, From, Event, To )
self:F({"onafterTarget",self.Search,Controllable:IsAlive()})
if Controllable:IsAlive() then
local AttackTasks = {}
if self.Search == true then
for DetectedUnit, Detected in pairs( self.DetectedUnits ) do
local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
if DetectedUnit:IsAlive() then
if DetectedUnit:IsInZone( self.EngageZone ) then
if Detected == true then
self:F( {"Target: ", DetectedUnit } )
self.DetectedUnits[DetectedUnit] = false
local AttackTask = Controllable:TaskAttackUnit( DetectedUnit, false, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil )
self.Controllable:PushTask( AttackTask, 1 )
end
end
else
self.DetectedUnits[DetectedUnit] = nil
end
end
else
self:F("Attack zone")
local AttackTask = Controllable:TaskAttackMapObject(
self.EngageZone:GetPointVec2():GetVec2(),
true,
self.EngageWeaponExpend,
self.EngageAttackQty,
self.EngageDirection,
self.EngageAltitude
)
self.Controllable:PushTask( AttackTask, 1 )
end
self:__Target( -10 )
end
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_BAI_ZONE:onafterAbort( Controllable, From, Event, To )
Controllable:ClearTasks()
self:__Route( 1 )
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
EngageSpeed,
EngageAltitude,
EngageWeaponExpend,
EngageAttackQty,
EngageDirection )
self:F("onafterEngage")
self.EngageSpeed = EngageSpeed or 400
self.EngageAltitude = EngageAltitude or 2000
self.EngageWeaponExpend = EngageWeaponExpend
self.EngageAttackQty = EngageAttackQty
self.EngageDirection = EngageDirection
if Controllable:IsAlive() then
local EngageRoute = {}
--- Calculate the current route point.
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
self.EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = CurrentRoutePoint
local AttackTasks = {}
if self.Search == true then
for DetectedUnitID, DetectedUnitData in pairs( self.DetectedUnits ) do
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
self:T( DetectedUnit )
if DetectedUnit:IsAlive() then
if DetectedUnit:IsInZone( self.EngageZone ) then
self:F( {"Engaging ", DetectedUnit } )
AttackTasks[#AttackTasks+1] = Controllable:TaskBombing(
DetectedUnit:GetPointVec2():GetVec2(),
true,
EngageWeaponExpend,
EngageAttackQty,
EngageDirection,
EngageAltitude
)
end
else
self.DetectedUnits[DetectedUnit] = nil
end
end
else
self:F("Attack zone")
AttackTasks[#AttackTasks+1] = Controllable:TaskAttackMapObject(
self.EngageZone:GetPointVec2():GetVec2(),
true,
EngageWeaponExpend,
EngageAttackQty,
EngageDirection,
EngageAltitude
)
end
EngageRoute[#EngageRoute].task = Controllable:TaskCombo( AttackTasks )
--- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
--- Find a random 2D point in EngageZone.
local ToTargetVec2 = self.EngageZone:GetRandomVec2()
self:T2( ToTargetVec2 )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
self.EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
Controllable:OptionROEOpenFire()
Controllable:OptionROTVertical()
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
Controllable:WayPointInitialize( EngageRoute )
--- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
Controllable:SetState( Controllable, "EngageZone", self )
Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" )
--- NOW ROUTE THE GROUP!
Controllable:WayPointExecute( 1 )
self:SetDetectionInterval( 2 )
self:SetDetectionActivated()
self:__Target( -2 ) -- Start Targetting
end
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
function AI_BAI_ZONE:onafterAccomplish( Controllable, From, Event, To )
self.Accomplished = true
self:SetDetectionDeactivated()
end
--- @param #AI_BAI_ZONE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Core.Event#EVENTDATA EventData
function AI_BAI_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
if EventData.IniUnit then
self.DetectedUnits[EventData.IniUnit] = nil
end
end
--- @param #AI_BAI_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_BAI_ZONE:OnEventDead( EventData )
self:F( { "EventDead", EventData } )
if EventData.IniDCSUnit then
if self.DetectedUnits and self.DetectedUnits[EventData.IniUnit] then
self:__Destroy( 1, EventData )
end
end
end

View File

@ -4,62 +4,22 @@
--
-- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG)
--
-- ===
-- ====
--
-- # 1) @{AI_Balancer#AI_BALANCER} class, extends @{Fsm#FSM_SET}
-- # Demo Missions
--
-- The @{AI_Balancer#AI_BALANCER} class monitors and manages as many replacement AI groups as there are
-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players.
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
-- ### [AI_BALANCER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/AIB%20-%20AI%20Balancing)
--
-- The parent class @{Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods.
-- An explanation about state and event transition methods can be found in the @{FSM} module documentation.
-- ### [AI_BALANCER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AIB%20-%20AI%20Balancing)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following:
-- ====
--
-- * **@{#AI_BALANCER.OnAfterSpawned}**( AISet, From, Event, To, AIGroup ): Define to add extra logic when an AI is spawned.
-- # YouTube Channel
--
-- ## 1.1) AI_BALANCER construction
-- ### [AI_BALANCER YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl2CJVIrL1TdAumuVS8n64B7)
--
-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New}() method:
--
-- ## 1.2) AI_BALANCER is a FSM
--
-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG)
--
-- ### 1.2.1) AI_BALANCER States
--
-- * **Monitoring** ( Set ): Monitoring the Set if all AI is spawned for the Clients.
-- * **Spawning** ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference.
-- * **Spawned** ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
-- * **Destroying** ( Set, AIGroup ): The AI is being destroyed.
-- * **Returning** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any.
--
-- ### 1.2.2) AI_BALANCER Events
--
-- * **Monitor** ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set.
-- * **Spawn** ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference.
-- * **Spawned** ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
-- * **Destroy** ( Set, AIGroup ): The AI is being destroyed.
-- * **Return** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods.
--
-- ## 1.3) AI_BALANCER spawn interval for replacement AI
--
-- Use the method @{#AI_BALANCER.InitSpawnInterval}() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned.
--
-- ## 1.4) AI_BALANCER returns AI to Airbases
--
-- By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default.
-- However, there are 2 additional options that you can use to customize the destroy behaviour.
-- When a human player joins a slot, you can configure to let the AI return to:
--
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Airbase#AIRBASE}.
--
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
--
-- ===
--
-- # **API CHANGE HISTORY**
@ -90,12 +50,68 @@
--
-- @module AI_Balancer
--- AI_BALANCER class
-- @type AI_BALANCER
--- @type AI_BALANCER
-- @field Core.Set#SET_CLIENT SetClient
-- @field Functional.Spawn#SPAWN SpawnAI
-- @field Wrapper.Group#GROUP Test
-- @extends Core.Fsm#FSM_SET
--- # AI_BALANCER class, extends @{Fsm#FSM_SET}
--
-- The AI_BALANCER class monitors and manages as many replacement AI groups as there are
-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players.
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
--
-- The parent class @{Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods.
-- An explanation about state and event transition methods can be found in the @{FSM} module documentation.
--
-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following:
--
-- * @{#AI_BALANCER.OnAfterSpawned}( AISet, From, Event, To, AIGroup ): Define to add extra logic when an AI is spawned.
--
-- ## 1. AI_BALANCER construction
--
-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New}() method:
--
-- ## 2. AI_BALANCER is a FSM
--
-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG)
--
-- ### 2.1. AI_BALANCER States
--
-- * **Monitoring** ( Set ): Monitoring the Set if all AI is spawned for the Clients.
-- * **Spawning** ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference.
-- * **Spawned** ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
-- * **Destroying** ( Set, AIGroup ): The AI is being destroyed.
-- * **Returning** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any.
--
-- ### 2.2. AI_BALANCER Events
--
-- * **Monitor** ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set.
-- * **Spawn** ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference.
-- * **Spawned** ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
-- * **Destroy** ( Set, AIGroup ): The AI is being destroyed.
-- * **Return** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods.
--
-- ## 3. AI_BALANCER spawn interval for replacement AI
--
-- Use the method @{#AI_BALANCER.InitSpawnInterval}() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned.
--
-- ## 4. AI_BALANCER returns AI to Airbases
--
-- By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default.
-- However, there are 2 additional options that you can use to customize the destroy behaviour.
-- When a human player joins a slot, you can configure to let the AI return to:
--
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Airbase#AIRBASE}.
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Airbase#AIRBASE}.
--
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
--
-- @field #AI_BALANCER
AI_BALANCER = {
ClassName = "AI_BALANCER",
PatrolZones = {},

View File

@ -11,6 +11,22 @@
-- * @{#AI_CAP_ZONE}: Perform a CAP in a zone.
--
-- ====
--
-- # Demo Missions
--
-- ### [AI_CAP Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol)
--
-- ### [AI_CAP Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAP%20-%20Combat%20Air%20Patrol)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [AI_CAP YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1YCyPxJgoZn-CfhwyeW65L)
--
-- ====
--
-- # **API CHANGE HISTORY**
--
@ -48,9 +64,9 @@
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # 1) @{#AI_CAP_ZONE} class, extends @{AI_CAP#AI_PATROL_ZONE}
--- # AI_CAP_ZONE class, extends @{AI_CAP#AI_PATROL_ZONE}
--
-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
-- The AI_CAP_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
--
-- ![Process](..\Presentations\AI_CAP\Dia3.JPG)
@ -81,22 +97,22 @@
--
-- ![Process](..\Presentations\AI_CAP\Dia13.JPG)
--
-- ## 1.1) AI_CAP_ZONE constructor
-- ## 1. AI_CAP_ZONE constructor
--
-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object.
--
-- ## 1.2) AI_CAP_ZONE is a FSM
-- ## 2. AI_CAP_ZONE is a FSM
--
-- ![Process](..\Presentations\AI_CAP\Dia2.JPG)
--
-- ### 1.2.1) AI_CAP_ZONE States
-- ### 2.1 AI_CAP_ZONE States
--
-- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Engaging** ( Group ): The AI is engaging the bogeys.
-- * **Returning** ( Group ): The AI is returning to Base..
--
-- ### 1.2.2) AI_CAP_ZONE Events
-- ### 2.2 AI_CAP_ZONE Events
--
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
@ -109,7 +125,7 @@
-- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
--
-- ## 1.3) Set the Range of Engagement
-- ## 3. Set the Range of Engagement
--
-- ![Range](..\Presentations\AI_CAP\Dia11.JPG)
--
@ -119,7 +135,7 @@
-- The range is applied at the position of the AI.
-- Use the method @{AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range.
--
-- ## 1.4) Set the Zone of Engagement
-- ## 4. Set the Zone of Engagement
--
-- ![Zone](..\Presentations\AI_CAP\Dia12.JPG)
--
@ -129,8 +145,7 @@
--
-- ===
--
-- @field #AI_CAP_ZONE AI_CAP_ZONE
--
-- @field #AI_CAP_ZONE
AI_CAP_ZONE = {
ClassName = "AI_CAP_ZONE",
}

View File

@ -10,19 +10,22 @@
--
-- * @{#AI_CAS_ZONE}: Perform a CAS in a zone.
--
-- ===
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- 2017-01-15: Initial class and API.
-- ====
--
-- # Demo Missions
--
-- ### [AI_CAS Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support)
--
-- ### [AI_CAS Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAS%20-%20Close%20Air%20Support)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [AI_CAS YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2)
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
@ -46,11 +49,11 @@
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
--- # 1) @{#AI_CAS_ZONE} class, extends @{AI_Patrol#AI_PATROL_ZONE}
--- # AI_CAS_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE}
--
-- @{#AI_CAS_ZONE} derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
-- AI_CAS_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
--
-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
-- The AI_CAS_ZONE class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
--
-- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG)
@ -104,22 +107,22 @@
--
-- ![Engage Event](..\Presentations\AI_CAS\Dia12.JPG)
--
-- # 1.1) AI_CAS_ZONE constructor
-- # 1. AI_CAS_ZONE constructor
--
-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object.
--
-- ## 1.2) AI_CAS_ZONE is a FSM
-- ## 2. AI_CAS_ZONE is a FSM
--
-- ![Process](..\Presentations\AI_CAS\Dia2.JPG)
--
-- ### 1.2.1) AI_CAS_ZONE States
-- ### 2.1. AI_CAS_ZONE States
--
-- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS.
-- * **Returning** ( Group ): The AI is returning to Base..
--
-- ### 1.2.2) AI_CAS_ZONE Events
-- ### 2.2. AI_CAS_ZONE Events
--
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
@ -134,8 +137,7 @@
--
-- ===
--
-- @field #AI_CAS_ZONE AI_CAS_ZONE
--
-- @field #AI_CAS_ZONE
AI_CAS_ZONE = {
ClassName = "AI_CAS_ZONE",
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,22 @@
--
-- ====
--
-- # Demo Missions
--
-- ### [AI_PATROL Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/PAT%20-%20Patrolling)
--
-- ### [AI_PATROL Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/PAT%20-%20Patrolling)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [AI_PATROL YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl35HvYZKA6G22WMt7iI3zky)
--
-- ====
--
-- # **OPEN ISSUES**
--
-- 2017-01-17: When Spawned AI is located at an airbase, it will be routed first back to the airbase after take-off.
@ -64,9 +80,9 @@
-- @field Functional.Spawn#SPAWN CoordTest
-- @extends Core.Fsm#FSM_CONTROLLABLE
--- # 1) @{#AI_PATROL_ZONE} class, extends @{Fsm#FSM_CONTROLLABLE}
--- # AI_PATROL_ZONE class, extends @{Fsm#FSM_CONTROLLABLE}
--
-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
-- The AI_PATROL_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
--
-- ![Process](..\Presentations\AI_PATROL\Dia3.JPG)
--
@ -97,15 +113,15 @@
--
-- ![Process](..\Presentations\AI_PATROL\Dia11.JPG)
--
-- ## 1.1) AI_PATROL_ZONE constructor
-- ## 1. AI_PATROL_ZONE constructor
--
-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object.
--
-- ## 1.2) AI_PATROL_ZONE is a FSM
-- ## 2. AI_PATROL_ZONE is a FSM
--
-- ![Process](..\Presentations\AI_PATROL\Dia2.JPG)
--
-- ### 1.2.1) AI_PATROL_ZONE States
-- ### 2.1. AI_PATROL_ZONE States
--
-- * **None** ( Group ): The process is not started yet.
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
@ -113,7 +129,7 @@
-- * **Stopped** ( Group ): The process is stopped.
-- * **Crashed** ( Group ): The AI has crashed or is dead.
--
-- ### 1.2.2) AI_PATROL_ZONE Events
-- ### 2.2. AI_PATROL_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Stop** ( Group ): Stop the process.
@ -123,17 +139,17 @@
-- * **Detected** ( Group ): The AI has detected new targets.
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
--
-- ## 1.3) Set or Get the AI controllable
-- ## 3. Set or Get the AI controllable
--
-- * @{#AI_PATROL_ZONE.SetControllable}(): Set the AIControllable.
-- * @{#AI_PATROL_ZONE.GetControllable}(): Get the AIControllable.
--
-- ## 1.4) Set the Speed and Altitude boundaries of the AI controllable
-- ## 4. Set the Speed and Altitude boundaries of the AI controllable
--
-- * @{#AI_PATROL_ZONE.SetSpeed}(): Set the patrol speed boundaries of the AI, for the next patrol.
-- * @{#AI_PATROL_ZONE.SetAltitude}(): Set altitude boundaries of the AI, for the next patrol.
--
-- ## 1.5) Manage the detection process of the AI controllable
-- ## 5. Manage the detection process of the AI controllable
--
-- The detection process of the AI controllable can be manipulated.
-- Detection requires an amount of CPU power, which has an impact on your mission performance.
@ -150,7 +166,7 @@
-- Note that when the zone is too far away, or the AI is not heading towards the zone, or the AI is too high, no targets may be detected
-- according the weather conditions.
--
-- ## 1.6) Manage the "out of fuel" in the AI_PATROL_ZONE
-- ## 6. Manage the "out of fuel" in the AI_PATROL_ZONE
--
-- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base.
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
@ -159,7 +175,7 @@
-- Once the time is finished, the old AI will return to the base.
-- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this proces in place.
--
-- ## 1.7) Manage "damage" behaviour of the AI in the AI_PATROL_ZONE
-- ## 7. Manage "damage" behaviour of the AI in the AI_PATROL_ZONE
--
-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on.
-- Therefore, when the damage treshold is reached, the AI will return immediately to the home base (RTB).
@ -167,8 +183,7 @@
--
-- ===
--
-- @field #AI_PATROL_ZONE AI_PATROL_ZONE
--
-- @field #AI_PATROL_ZONE
AI_PATROL_ZONE = {
ClassName = "AI_PATROL_ZONE",
}

View File

@ -173,8 +173,6 @@ do -- ACT_ASSIGN_ACCEPT
local ProcessGroup = ProcessUnit:GetGroup()
self:Message( "You are assigned to the task " .. self.Task:GetName() )
self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() )
end

View File

@ -82,6 +82,7 @@ do -- ACT_ROUTE
-- @field Tasking.Task#TASK TASK
-- @field Wrapper.Unit#UNIT ProcessUnit
-- @field Core.Zone#ZONE_BASE Zone
-- @field Core.Point#COORDINATE Coordinate
-- @extends Core.Fsm#FSM_PROCESS
ACT_ROUTE = {
ClassName = "ACT_ROUTE",
@ -96,12 +97,13 @@ do -- ACT_ROUTE
-- Inherits from BASE
local self = BASE:Inherit( self, FSM_PROCESS:New( "ACT_ROUTE" ) ) -- Core.Fsm#FSM_PROCESS
self:AddTransition( "*", "Reset", "None" )
self:AddTransition( "None", "Start", "Routing" )
self:AddTransition( "*", "Report", "Reporting" )
self:AddTransition( "*", "Route", "Routing" )
self:AddTransition( "*", "Report", "*" )
self:AddTransition( "Routing", "Route", "Routing" )
self:AddTransition( "Routing", "Pause", "Pausing" )
self:AddTransition( "*", "Abort", "Aborted" )
self:AddTransition( "Routing", "Arrive", "Arrived" )
self:AddTransition( "*", "Cancel", "Cancelled" )
self:AddTransition( "Arrived", "Success", "Success" )
self:AddTransition( "*", "Fail", "Failed" )
self:AddTransition( "", "", "" )
@ -109,11 +111,79 @@ do -- ACT_ROUTE
self:AddEndState( "Arrived" )
self:AddEndState( "Failed" )
self:AddEndState( "Cancelled" )
self:SetStartState( "None" )
self:SetStartState( "None" )
self:SetRouteMode( "C" )
return self
end
--- Set a Cancel Menu item.
-- @param #ACT_ROUTE self
-- @return #ACT_ROUTE
function ACT_ROUTE:SetMenuCancel( MenuGroup, MenuText, ParentMenu, MenuTime )
MENU_GROUP_COMMAND:New(
MenuGroup,
MenuText,
ParentMenu,
self.MenuCancel,
self
):SetTime(MenuTime)
return self
end
--- Set the route mode.
-- There are 2 route modes supported:
--
-- * SetRouteMode( "B" ): Route mode is Bearing and Range.
-- * SetRouteMode( "C" ): Route mode is LL or MGRS according coordinate system setup.
--
-- @param #ACT_ROUTE self
-- @return #ACT_ROUTE
function ACT_ROUTE:SetRouteMode( RouteMode )
self.RouteMode = RouteMode
return self
end
--- Get the routing text to be displayed.
-- The route mode determines the text displayed.
-- @param #ACT_ROUTE self
-- @return #string
function ACT_ROUTE:GetRouteText( FromCoordinate )
local RouteText = ""
if self.Coordinate and self.RouteMode == "B" then
RouteText = "Route to " .. FromCoordinate:GetBRText( self.Coordinate ) .. " km."
end
if self.Coordinate and self.RouteMode == "C" then
RouteText = "Route to " .. self.Coordinate:ToString()
end
if self.Zone and self.RouteMode == "B" then
local Coordinate = self.Zone:GetCoordinate()
RouteText = "Route to zone bearing " .. FromCoordinate:GetBRText( Coordinate ) .. " km."
end
if self.Zone and self.RouteMode == "C" then
local Coordinate = self.Zone:GetCoordinate()
RouteText = "Route to zone at " .. Coordinate:ToString()
end
return RouteText
end
function ACT_ROUTE:MenuCancel()
self:Cancel()
end
--- Task Events
@ -189,15 +259,15 @@ do -- ACT_ROUTE_POINT
--- Creates a new routing state machine.
-- The task will route a controllable to a PointVec2 until the controllable is within the Range.
-- The task will route a controllable to a Coordinate until the controllable is within the Range.
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 The PointVec2 to Target.
-- @param Core.Point#COORDINATE The Coordinate to Target.
-- @param #number Range The Distance to Target.
-- @param Core.Zone#ZONE_BASE Zone
function ACT_ROUTE_POINT:New( PointVec2, Range )
function ACT_ROUTE_POINT:New( Coordinate, Range )
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_POINT
self.PointVec2 = PointVec2
self.Coordinate = Coordinate
self.Range = Range or 0
self.DisplayInterval = 30
@ -208,34 +278,38 @@ do -- ACT_ROUTE_POINT
return self
end
--- Creates a new routing state machine.
-- The task will route a controllable to a Coordinate until the controllable is within the Range.
-- @param #ACT_ROUTE_POINT self
function ACT_ROUTE_POINT:Init( FsmRoute )
self.PointVec2 = FsmRoute.PointVec2
self.Coordinate = FsmRoute.Coordinate
self.Range = FsmRoute.Range or 0
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
self:SetStartState("None")
end
--- Set PointVec2
--- Set Coordinate
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
function ACT_ROUTE_POINT:SetPointVec2( PointVec2 )
self:F2( { PointVec2 } )
self.PointVec2 = PointVec2
-- @param Core.Point#COORDINATE Coordinate The Coordinate to route to.
function ACT_ROUTE_POINT:SetCoordinate( Coordinate )
self:F2( { Coordinate } )
self.Coordinate = Coordinate
end
--- Get PointVec2
--- Get Coordinate
-- @param #ACT_ROUTE_POINT self
-- @return Core.Point#POINT_VEC2 PointVec2 The PointVec2 to route to.
function ACT_ROUTE_POINT:GetPointVec2()
self:F2( { self.PointVec2 } )
return self.PointVec2
-- @return Core.Point#COORDINATE Coordinate The Coordinate to route to.
function ACT_ROUTE_POINT:GetCoordinate()
self:F2( { self.Coordinate } )
return self.Coordinate
end
--- Set Range around PointVec2
--- Set Range around Coordinate
-- @param #ACT_ROUTE_POINT self
-- @param #number Range The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:SetRange( Range )
@ -243,7 +317,7 @@ do -- ACT_ROUTE_POINT
self.Range = Range or 10000
end
--- Get Range around PointVec2
--- Get Range around Coordinate
-- @param #ACT_ROUTE_POINT self
-- @return #number The Range to consider the arrival. Default is 10000 meters.
function ACT_ROUTE_POINT:GetRange()
@ -257,7 +331,7 @@ do -- ACT_ROUTE_POINT
function ACT_ROUTE_POINT:onfuncHasArrived( ProcessUnit )
if ProcessUnit:IsAlive() then
local Distance = self.PointVec2:Get2DDistance( ProcessUnit:GetPointVec2() )
local Distance = self.Coordinate:Get2DDistance( ProcessUnit:GetCoordinate() )
if Distance <= self.Range then
local RouteText = "You have arrived."
@ -277,10 +351,10 @@ do -- ACT_ROUTE_POINT
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE_POINT:onenterReporting( ProcessUnit, From, Event, To )
function ACT_ROUTE_POINT:onafterReport( ProcessUnit, From, Event, To )
local TaskUnitPointVec2 = ProcessUnit:GetPointVec2()
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( self.PointVec2 ) .. " km."
local TaskUnitCoordinate = ProcessUnit:GetCoordinate()
local RouteText = self:GetRouteText( TaskUnitCoordinate )
self:Message( RouteText )
end
@ -362,13 +436,13 @@ do -- ACT_ROUTE_ZONE
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE_ZONE:onenterReporting( ProcessUnit, From, Event, To )
function ACT_ROUTE_ZONE:onafterReport( ProcessUnit, From, Event, To )
local ZoneVec2 = self.Zone:GetVec2()
local ZonePointVec2 = POINT_VEC2:New( ZoneVec2.x, ZoneVec2.y )
local ZoneCoordinate = COORDINATE:New( ZoneVec2.x, ZoneVec2.y )
local TaskUnitVec2 = ProcessUnit:GetVec2()
local TaskUnitPointVec2 = POINT_VEC2:New( TaskUnitVec2.x, TaskUnitVec2.y )
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( ZonePointVec2 ) .. " km."
local TaskUnitCoordinate = COORDINATE:New( TaskUnitVec2.x, TaskUnitVec2.y )
local RouteText = self:GetRouteText( TaskUnitCoordinate )
self:Message( RouteText )
end

View File

@ -219,16 +219,17 @@ local _ClassID = 0
BASE = {
ClassName = "BASE",
ClassID = 0,
_Private = {},
Events = {},
States = {}
States = {},
_ = {},
}
--- The Formation Class
-- @type FORMATION
-- @field Cone A cone formation.
FORMATION = {
Cone = "Cone"
Cone = "Cone",
Vee = "Vee"
}
@ -360,7 +361,7 @@ do -- Event Handling
-- @param #BASE self
-- @return #number The @{Event} processing Priority.
function BASE:GetEventPriority()
return self._Private.EventPriority or 5
return self._.EventPriority or 5
end
--- Set the Class @{Event} processing Priority.
@ -370,7 +371,7 @@ do -- Event Handling
-- @param #number EventPriority The @{Event} processing Priority.
-- @return self
function BASE:SetEventPriority( EventPriority )
self._Private.EventPriority = EventPriority
self._.EventPriority = EventPriority
end
--- Remove all subscribed events
@ -453,6 +454,12 @@ do -- Event Handling
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when an object is dead.
-- initiator : The unit that is dead.
-- @function [parent=#BASE] OnEventDead
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when an object is completely destroyed.
-- initiator : The unit that is was destroyed.
-- @function [parent=#BASE] OnEvent

File diff suppressed because it is too large Load Diff

View File

@ -6,12 +6,14 @@
-- ===================================================
-- Mission designers can use the DATABASE class to refer to:
--
-- * STATICS
-- * UNITS
-- * GROUPS
-- * CLIENTS
-- * AIRPORTS
-- * AIRBASES
-- * PLAYERSJOINED
-- * PLAYERS
-- * CARGOS
--
-- On top, for internal MOOSE administration purposes, the DATBASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
--
@ -44,15 +46,18 @@ DATABASE = {
Templates = {
Units = {},
Groups = {},
Statics = {},
ClientsByName = {},
ClientsByID = {},
},
UNITS = {},
UNITS_Index = {},
STATICS = {},
GROUPS = {},
PLAYERS = {},
PLAYERSJOINED = {},
CLIENTS = {},
CARGOS = {},
AIRBASES = {},
COUNTRY_ID = {},
COUNTRY_NAME = {},
@ -84,16 +89,18 @@ local _DATABASECategory =
function DATABASE:New()
-- Inherits from BASE
local self = BASE:Inherit( self, BASE:New() )
local self = BASE:Inherit( self, BASE:New() ) -- #DATABASE
self:SetEventPriority( 1 )
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.NewCargo )
self:HandleEvent( EVENTS.DeleteCargo )
-- Follow alive players and clients
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
-- self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
self:_RegisterTemplates()
@ -102,6 +109,33 @@ function DATABASE:New()
self:_RegisterStatics()
self:_RegisterPlayers()
self:_RegisterAirbases()
self.UNITS_Position = 0
--- @param #DATABASE self
local function CheckPlayers( self )
local UNITS_Count = #self.UNITS_Index
if UNITS_Count > 0 then
self.UNITS_Position = ( ( self.UNITS_Position <= UNITS_Count ) and self.UNITS_Position + 1 ) or 1
local PlayerUnit = self.UNITS[self.UNITS_Index[self.UNITS_Position]]
if PlayerUnit then
local UnitName = PlayerUnit:GetName()
local PlayerName = PlayerUnit:GetPlayerName()
--self:E( { UNITS_Count, self.UNITS_Position, UnitName, PlayerName } )
if PlayerName and PlayerName ~= "" then
if self.PLAYERS[PlayerName] == nil or self.PLAYERS[PlayerName] ~= UnitName then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self:AddPlayer( UnitName, PlayerName )
--_EVENTDISPATCHER:CreateEventPlayerEnterUnit( PlayerUnit )
end
end
end
end
end
self:E( "Scheduling" )
--local PlayerCheckSchedule = SCHEDULER:New( nil, CheckPlayers, { self }, 2, 0.1 )
return self
end
@ -124,6 +158,8 @@ function DATABASE:AddUnit( DCSUnitName )
if not self.UNITS[DCSUnitName] then
local UnitRegister = UNIT:Register( DCSUnitName )
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
table.insert( self.UNITS_Index, DCSUnitName )
end
return self.UNITS[DCSUnitName]
@ -134,7 +170,7 @@ end
-- @param #DATABASE self
function DATABASE:DeleteUnit( DCSUnitName )
--self.UNITS[DCSUnitName] = nil
self.UNITS[DCSUnitName] = nil
end
--- Adds a Static based on the Static Name in the DATABASE.
@ -166,22 +202,24 @@ end
--- Adds a Airbase based on the Airbase Name in the DATABASE.
-- @param #DATABASE self
function DATABASE:AddAirbase( DCSAirbaseName )
-- @param #string AirbaseName The name of the airbase
function DATABASE:AddAirbase( AirbaseName )
if not self.AIRBASES[DCSAirbaseName] then
self.AIRBASES[DCSAirbaseName] = AIRBASE:Register( DCSAirbaseName )
if not self.AIRBASES[AirbaseName] then
self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName )
end
end
--- Deletes a Airbase from the DATABASE based on the Airbase Name.
-- @param #DATABASE self
function DATABASE:DeleteAirbase( DCSAirbaseName )
-- @param #string AirbaseName The name of the airbase
function DATABASE:DeleteAirbase( AirbaseName )
--self.AIRBASES[DCSAirbaseName] = nil
self.AIRBASES[AirbaseName] = nil
end
--- Finds a AIRBASE based on the AirbaseName.
--- Finds an AIRBASE based on the AirbaseName.
-- @param #DATABASE self
-- @param #string AirbaseName
-- @return Wrapper.Airbase#AIRBASE The found AIRBASE.
@ -191,6 +229,35 @@ function DATABASE:FindAirbase( AirbaseName )
return AirbaseFound
end
--- Adds a Cargo based on the Cargo Name in the DATABASE.
-- @param #DATABASE self
-- @param #string CargoName The name of the airbase
function DATABASE:AddCargo( Cargo )
if not self.CARGOS[Cargo.Name] then
self.CARGOS[Cargo.Name] = Cargo
end
end
--- Deletes a Cargo from the DATABASE based on the Cargo Name.
-- @param #DATABASE self
-- @param #string CargoName The name of the airbase
function DATABASE:DeleteCargo( CargoName )
self.CARGOS[CargoName] = nil
end
--- Finds an CARGO based on the CargoName.
-- @param #DATABASE self
-- @param #string CargoName
-- @return Wrapper.Cargo#CARGO The found CARGO.
function DATABASE:FindCargo( CargoName )
local CargoFound = self.CARGOS[CargoName]
return CargoFound
end
--- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self
@ -244,7 +311,7 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
if PlayerName then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self.PLAYERS[PlayerName] = self:FindUnit( UnitName )
self.PLAYERS[PlayerName] = UnitName
self.PLAYERSJOINED[PlayerName] = PlayerName
end
end
@ -282,7 +349,7 @@ function DATABASE:Spawn( SpawnTemplate )
SpawnTemplate.CountryID = nil
SpawnTemplate.CategoryID = nil
self:_RegisterTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
self:T3( SpawnTemplate )
coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate )
@ -318,7 +385,7 @@ end
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
@ -396,6 +463,54 @@ function DATABASE:GetGroupTemplate( GroupName )
return GroupTemplate
end
--- Private method that registers new Static Templates within the DATABASE Object.
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
local TraceTable = {}
local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name)
self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
StaticTemplate.CategoryID = CategoryID
StaticTemplate.CoalitionID = CoalitionID
StaticTemplate.CountryID = CountryID
self.Templates.Statics[StaticTemplateName].StaticName = StaticTemplateName
self.Templates.Statics[StaticTemplateName].GroupTemplate = StaticTemplate
self.Templates.Statics[StaticTemplateName].UnitTemplate = StaticTemplate.units[1]
self.Templates.Statics[StaticTemplateName].CategoryID = CategoryID
self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID
self.Templates.Statics[StaticTemplateName].CountryID = CountryID
TraceTable[#TraceTable+1] = "Static"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].GroupName
TraceTable[#TraceTable+1] = "Coalition"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CoalitionID
TraceTable[#TraceTable+1] = "Category"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CategoryID
TraceTable[#TraceTable+1] = "Country"
TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CountryID
self:E( TraceTable )
end
--- @param #DATABASE self
function DATABASE:GetStaticUnitTemplate( StaticName )
local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate
StaticTemplate.SpawnCoalitionID = self.Templates.Statics[StaticName].CoalitionID
StaticTemplate.SpawnCategoryID = self.Templates.Statics[StaticName].CategoryID
StaticTemplate.SpawnCountryID = self.Templates.Statics[StaticName].CountryID
return StaticTemplate
end
function DATABASE:GetGroupNameFromUnitName( UnitName )
return self.Templates.Units[UnitName].GroupName
end
@ -663,9 +778,22 @@ function DATABASE:ForEach( IteratorFunction, FinalizeFunction, arg, Set )
end
--- Iterate the DATABASE and call an iterator function for each **alive** STATIC, providing the STATIC and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a STATIC parameter.
-- @return #DATABASE self
function DATABASE:ForEachStatic( IteratorFunction, FinalizeFunction, ... ) --R2.1
self:F2( arg )
self:ForEach( IteratorFunction, FinalizeFunction, arg, self.STATICS )
return self
end
--- Iterate the DATABASE and call an iterator function for each **alive** UNIT, providing the UNIT and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the database. The function needs to accept a UNIT parameter.
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachUnit( IteratorFunction, FinalizeFunction, ... )
self:F2( arg )
@ -675,9 +803,10 @@ function DATABASE:ForEachUnit( IteratorFunction, FinalizeFunction, ... )
return self
end
--- Iterate the DATABASE and call an iterator function for each **alive** GROUP, providing the GROUP and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the database. The function needs to accept a GROUP parameter.
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a GROUP parameter.
-- @return #DATABASE self
function DATABASE:ForEachGroup( IteratorFunction, ... )
self:F2( arg )
@ -690,7 +819,7 @@ end
--- Iterate the DATABASE and call an iterator function for each **ALIVE** player, providing the player name and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an player in the database. The function needs to accept the player name.
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept the player name.
-- @return #DATABASE self
function DATABASE:ForEachPlayer( IteratorFunction, ... )
self:F2( arg )
@ -703,7 +832,7 @@ end
--- Iterate the DATABASE and call an iterator function for each player who has joined the mission, providing the Unit of the player and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is was a player in the database. The function needs to accept a UNIT parameter.
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachPlayerJoined( IteratorFunction, ... )
self:F2( arg )
@ -715,7 +844,7 @@ end
--- Iterate the DATABASE and call an iterator function for each CLIENT, providing the CLIENT to the function and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database. The function needs to accept a CLIENT parameter.
-- @param #function IteratorFunction The function that will be called object in the database. The function needs to accept a CLIENT parameter.
-- @return #DATABASE self
function DATABASE:ForEachClient( IteratorFunction, ... )
self:F2( arg )
@ -725,7 +854,44 @@ function DATABASE:ForEachClient( IteratorFunction, ... )
return self
end
--- Iterate the DATABASE and call an iterator function for each CARGO, providing the CARGO object to the function and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a CLIENT parameter.
-- @return #DATABASE self
function DATABASE:ForEachCargo( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.CARGOS )
return self
end
--- Handles the OnEventNewCargo event.
-- @param #DATABASE self
-- @param Core.Event#EVENTDATA EventData
function DATABASE:OnEventNewCargo( EventData )
self:F2( { EventData } )
if EventData.Cargo then
self:AddCargo( EventData.Cargo )
end
end
--- Handles the OnEventDeleteCargo.
-- @param #DATABASE self
-- @param Core.Event#EVENTDATA EventData
function DATABASE:OnEventDeleteCargo( EventData )
self:F2( { EventData } )
if EventData.Cargo then
self:DeleteCargo( EventData.Cargo.Name )
end
end
--- @param #DATABASE self
function DATABASE:_RegisterTemplates()
self:F2()
@ -781,11 +947,18 @@ function DATABASE:_RegisterTemplates()
--self.Units[coa_name][countryName][category] = {}
for group_num, GroupTemplate in pairs(obj_type_data.group) do
for group_num, Template in pairs(obj_type_data.group) do
if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group
self:_RegisterTemplate(
GroupTemplate,
if obj_type_name ~= "static" and Template and Template.units and type(Template.units) == 'table' then --making sure again- this is a valid group
self:_RegisterGroupTemplate(
Template,
CoalitionSide,
_DATABASECategory[string.lower(CategoryName)],
CountryID
)
else
self:_RegisterStaticTemplate(
Template,
CoalitionSide,
_DATABASECategory[string.lower(CategoryName)],
CountryID

View File

@ -1,4 +1,4 @@
--- **Core** - EVENT models DCS **event dispatching** using a **publish-subscribe** model.
--- **Core R2.1** - EVENT models DCS **event dispatching** using a **publish-subscribe** model.
--
-- ![Banner Image](..\Presentations\EVENT\Dia1.JPG)
--
@ -197,6 +197,9 @@ EVENT = {
ClassID = 0,
}
world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000
world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001
--- The different types of events supported by MOOSE.
-- Use this structure to subscribe to events using the @{Base#BASE.HandleEvent}() method.
-- @type EVENTS
@ -224,13 +227,15 @@ EVENTS = {
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
ShootingStart = world.event.S_EVENT_SHOOTING_START,
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
NewCargo = world.event.S_EVENT_NEW_CARGO,
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
}
--- The Event structure
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
--
-- * A (Object.Category.)UNIT : A UNIT object type is involved in the Event.
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
-- * A (Object.Category.)STATIC : A STATIC object type is involved in the Event.µ
--
-- @type EVENTDATA
-- @field #number id The identifier of the event.
@ -271,122 +276,156 @@ EVENTS = {
-- @field WeaponTgtDCSUnit
local _EVENTMETA = {
[world.event.S_EVENT_SHOT] = {
Order = 1,
Side = "I",
Event = "OnEventShot",
Text = "S_EVENT_SHOT"
},
[world.event.S_EVENT_HIT] = {
Order = 1,
Side = "T",
Event = "OnEventHit",
Text = "S_EVENT_HIT"
},
[world.event.S_EVENT_TAKEOFF] = {
Order = 1,
Side = "I",
Event = "OnEventTakeoff",
Text = "S_EVENT_TAKEOFF"
},
[world.event.S_EVENT_LAND] = {
Order = 1,
Side = "I",
Event = "OnEventLand",
Text = "S_EVENT_LAND"
},
[world.event.S_EVENT_CRASH] = {
Order = -1,
Side = "I",
Event = "OnEventCrash",
Text = "S_EVENT_CRASH"
},
[world.event.S_EVENT_EJECTION] = {
Order = 1,
Side = "I",
Event = "OnEventEjection",
Text = "S_EVENT_EJECTION"
},
[world.event.S_EVENT_REFUELING] = {
Order = 1,
Side = "I",
Event = "OnEventRefueling",
Text = "S_EVENT_REFUELING"
},
[world.event.S_EVENT_DEAD] = {
Order = -1,
Side = "I",
Event = "OnEventDead",
Text = "S_EVENT_DEAD"
},
[world.event.S_EVENT_PILOT_DEAD] = {
Order = 1,
Side = "I",
Event = "OnEventPilotDead",
Text = "S_EVENT_PILOT_DEAD"
},
[world.event.S_EVENT_BASE_CAPTURED] = {
Order = 1,
Side = "I",
Event = "OnEventBaseCaptured",
Text = "S_EVENT_BASE_CAPTURED"
},
[world.event.S_EVENT_MISSION_START] = {
Order = 1,
Side = "N",
Event = "OnEventMissionStart",
Text = "S_EVENT_MISSION_START"
},
[world.event.S_EVENT_MISSION_END] = {
Order = 1,
Side = "N",
Event = "OnEventMissionEnd",
Text = "S_EVENT_MISSION_END"
},
[world.event.S_EVENT_TOOK_CONTROL] = {
Order = 1,
Side = "N",
Event = "OnEventTookControl",
Text = "S_EVENT_TOOK_CONTROL"
},
[world.event.S_EVENT_REFUELING_STOP] = {
Order = 1,
Side = "I",
Event = "OnEventRefuelingStop",
Text = "S_EVENT_REFUELING_STOP"
},
[world.event.S_EVENT_BIRTH] = {
Order = 1,
Side = "I",
Event = "OnEventBirth",
Text = "S_EVENT_BIRTH"
},
[world.event.S_EVENT_HUMAN_FAILURE] = {
Order = 1,
Side = "I",
Event = "OnEventHumanFailure",
Text = "S_EVENT_HUMAN_FAILURE"
},
[world.event.S_EVENT_ENGINE_STARTUP] = {
Order = 1,
Side = "I",
Event = "OnEventEngineStartup",
Text = "S_EVENT_ENGINE_STARTUP"
},
[world.event.S_EVENT_ENGINE_SHUTDOWN] = {
Order = 1,
Side = "I",
Event = "OnEventEngineShutdown",
Text = "S_EVENT_ENGINE_SHUTDOWN"
},
[world.event.S_EVENT_PLAYER_ENTER_UNIT] = {
Order = 1,
Side = "I",
Event = "OnEventPlayerEnterUnit",
Text = "S_EVENT_PLAYER_ENTER_UNIT"
},
[world.event.S_EVENT_PLAYER_LEAVE_UNIT] = {
Order = -1,
Side = "I",
Event = "OnEventPlayerLeaveUnit",
Text = "S_EVENT_PLAYER_LEAVE_UNIT"
},
[world.event.S_EVENT_PLAYER_COMMENT] = {
Order = 1,
Side = "I",
Event = "OnEventPlayerComment",
Text = "S_EVENT_PLAYER_COMMENT"
},
[world.event.S_EVENT_SHOOTING_START] = {
Order = 1,
Side = "I",
Event = "OnEventShootingStart",
Text = "S_EVENT_SHOOTING_START"
},
[world.event.S_EVENT_SHOOTING_END] = {
Order = 1,
Side = "I",
Event = "OnEventShootingEnd",
Text = "S_EVENT_SHOOTING_END"
},
[EVENTS.NewCargo] = {
Order = 1,
Event = "OnEventNewCargo",
Text = "S_EVENT_NEW_CARGO"
},
[EVENTS.DeleteCargo] = {
Order = 1,
Event = "OnEventDeleteCargo",
Text = "S_EVENT_DELETE_CARGO"
},
}
@ -401,13 +440,6 @@ function EVENT:New()
return self
end
function EVENT:EventText( EventID )
local EventText = _EVENTMETA[EventID].Text
return EventText
end
--- Initializes the Events structure for the event
-- @param #EVENT self
@ -419,7 +451,7 @@ function EVENT:Init( EventID, EventClass )
if not self.Events[EventID] then
-- Create a WEAK table to ensure that the garbage collector is cleaning the event links when the object usage is cleaned.
self.Events[EventID] = setmetatable( {}, { __mode = "k" } )
self.Events[EventID] = {}
end
-- Each event has a subtable of EventClasses, ordered by EventPriority.
@ -429,53 +461,56 @@ function EVENT:Init( EventID, EventClass )
end
if not self.Events[EventID][EventPriority][EventClass] then
self.Events[EventID][EventPriority][EventClass] = setmetatable( {}, { __mode = "v" } )
self.Events[EventID][EventPriority][EventClass] = {}
end
return self.Events[EventID][EventPriority][EventClass]
end
--- Removes an Events entry
--- Removes a subscription
-- @param #EVENT self
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:Remove( EventClass, EventID )
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
local EventClass = EventClass
self:E( { "Removing subscription for class: ", EventClass:GetClassNameAndID() } )
local EventPriority = EventClass:GetEventPriority()
self.EventsDead = self.EventsDead or {}
self.EventsDead[EventID] = self.EventsDead[EventID] or {}
self.EventsDead[EventID][EventPriority] = self.EventsDead[EventID][EventPriority] or {}
self.EventsDead[EventID][EventPriority][EventClass] = self.Events[EventID][EventPriority][EventClass]
self.Events[EventID][EventPriority][EventClass] = nil
end
--- Removes an Events entry for a UNIT.
--- Resets subscriptions
-- @param #EVENT self
-- @param #string UnitName The name of the UNIT.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:RemoveForUnit( UnitName, EventClass, EventID )
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
function EVENT:Reset( EventObject ) --R2.1
local EventClass = EventClass
local EventPriority = EventClass:GetEventPriority()
local Event = self.Events[EventID][EventPriority][EventClass]
Event.EventUnit[UnitName] = nil
self:E( { "Resetting subscriptions for class: ", EventObject:GetClassNameAndID() } )
local EventPriority = EventObject:GetEventPriority()
for EventID, EventData in pairs( self.Events ) do
if self.EventsDead then
if self.EventsDead[EventID] then
if self.EventsDead[EventID][EventPriority] then
if self.EventsDead[EventID][EventPriority][EventObject] then
self.Events[EventID][EventPriority][EventObject] = self.EventsDead[EventID][EventPriority][EventObject]
end
end
end
end
end
end
--- Removes an Events entry for a GROUP.
-- @param #EVENT self
-- @param #string GroupName The name of the GROUP.
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
-- @param Dcs.DCSWorld#world.event EventID
-- @return #EVENT.Events
function EVENT:RemoveForGroup( GroupName, EventClass, EventID )
self:F3( { EventClass, _EVENTMETA[EventID].Text } )
local EventClass = EventClass
local EventPriority = EventClass:GetEventPriority()
local Event = self.Events[EventID][EventPriority][EventClass]
Event.EventGroup[GroupName] = nil
end
--- Clears all event subscriptions for a @{Base#BASE} derived object.
-- @param #EVENT self
@ -519,7 +554,6 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
local EventData = self:Init( EventID, EventClass )
EventData.EventFunction = EventFunction
EventData.EventClass = EventClass
return self
end
@ -536,12 +570,8 @@ function EVENT:OnEventForUnit( UnitName, EventFunction, EventClass, EventID )
self:F2( UnitName )
local EventData = self:Init( EventID, EventClass )
if not EventData.EventUnit then
EventData.EventUnit = {}
end
EventData.EventUnit[UnitName] = {}
EventData.EventUnit[UnitName].EventFunction = EventFunction
EventData.EventUnit[UnitName].EventClass = EventClass
EventData.EventUnit = true
EventData.EventFunction = EventFunction
return self
end
@ -556,12 +586,8 @@ function EVENT:OnEventForGroup( GroupName, EventFunction, EventClass, EventID )
self:F2( GroupName )
local Event = self:Init( EventID, EventClass )
if not Event.EventGroup then
Event.EventGroup = {}
end
Event.EventGroup[GroupName] = {}
Event.EventGroup[GroupName].EventFunction = EventFunction
Event.EventGroup[GroupName].EventClass = EventClass
Event.EventGroup = true
Event.EventFunction = EventFunction
return self
end
@ -672,6 +698,54 @@ do -- OnEngineShutDown
end
do -- Event Creation
--- Creation of a New Cargo Event.
-- @param #EVENT self
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
function EVENT:CreateEventNewCargo( Cargo )
self:F( { Cargo } )
local Event = {
id = EVENTS.NewCargo,
time = timer.getTime(),
cargo = Cargo,
}
world.onEvent( Event )
end
--- Creation of a Cargo Deletion Event.
-- @param #EVENT self
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
function EVENT:CreateEventDeleteCargo( Cargo )
self:F( { Cargo } )
local Event = {
id = EVENTS.DeleteCargo,
time = timer.getTime(),
cargo = Cargo,
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
-- @param #EVENT self
-- @param Wrapper.Unit#UNIT PlayerUnit.
function EVENT:CreateEventPlayerEnterUnit( PlayerUnit )
self:F( { PlayerUnit } )
local Event = {
id = EVENTS.PlayerEnterUnit,
time = timer.getTime(),
initiator = PlayerUnit:GetDCSObject()
}
world.onEvent( Event )
end
end
--- @param #EVENT self
-- @param #EVENTDATA Event
@ -687,10 +761,10 @@ function EVENT:onEvent( Event )
return errmsg
end
self:E( _EVENTMETA[Event.id].Text, Event )
local EventMeta = _EVENTMETA[Event.id]
if self and self.Events and self.Events[Event.id] then
if Event.initiator then
@ -795,12 +869,17 @@ function EVENT:onEvent( Event )
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end
local PriorityOrder = _EVENTMETA[Event.id].Order
if Event.cargo then
Event.Cargo = Event.cargo
Event.CargoName = Event.cargo.Name
end
local PriorityOrder = EventMeta.Order
local PriorityBegin = PriorityOrder == -1 and 5 or 1
local PriorityEnd = PriorityOrder == -1 and 1 or 5
if Event.IniObjectCategory ~= 3 then
self:E( { _EVENTMETA[Event.id].Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
if Event.IniObjectCategory ~= Object.Category.STATIC then
self:E( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
@ -810,186 +889,146 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
if Event.IniObjectCategory ~= Object.Category.STATIC then
--self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
end
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if ( Event.IniDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.IniDCSUnitName] ) or
( Event.TgtDCSUnitName and EventData.EventUnit and EventData.EventUnit[Event.TgtDCSUnitName] ) then
if EventData.EventUnit then
if EventData.EventUnit[Event.IniDCSUnitName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventUnit[Event.IniDCSUnitName].EventFunction then
-- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
if EventClass:IsAlive() or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventUnit[Event.IniDCSUnitName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
local UnitName = EventClass:GetName()
if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
( EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName ) then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
return EventData.EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
if EventData.EventUnit[Event.TgtDCSUnitName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventUnit[Event.TgtDCSUnitName].EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventUnit[Event.TgtDCSUnitName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ EventMeta.Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
else
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
self:Remove( EventClass, Event.id )
end
else
-- If the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
if ( Event.IniDCSUnitName and Event.IniDCSGroupName and Event.IniGroupName and EventData.EventGroup and EventData.EventGroup[Event.IniGroupName] ) or
( Event.TgtDCSUnitName and Event.TgtDCSGroupName and Event.TgtGroupName and EventData.EventGroup and EventData.EventGroup[Event.TgtGroupName] ) then
if EventData.EventGroup then
if EventData.EventGroup[Event.IniGroupName] then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventGroup[Event.IniGroupName].EventFunction then
-- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
if EventClass:IsAlive() or
Event.id == EVENTS.Crash or
Event.id == EVENTS.Dead then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventGroup[Event.IniGroupName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
-- We can get the name of the EventClass, which is now always a GROUP object.
local GroupName = EventClass:GetName()
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then
if EventData.EventGroup[Event.TgtGroupName] then
if EventData.EventGroup[Event.TgtGroupName].EventFunction then
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.TgtUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventGroup[Event.TgtGroupName].EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if (Event.IniDCSUnit or Event.WeaponUNIT) and not EventData.EventUnit then
if EventClass == EventData.EventClass then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then
-- There is an EventFunction defined, so call the EventFunction.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
self:E( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ _EVENTMETA[Event.id].Event ]
local EventFunction = EventClass[ EventMeta.Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. _EVENTMETA[Event.id].Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
self:E( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
local Result, Value = EventFunction( EventClass, Event )
return Result, Value
return EventFunction( EventClass, Event )
end, ErrorHandler )
end
end
end
else
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
self:Remove( EventClass, Event.id )
end
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if not EventData.EventUnit then
-- First test if a EventFunction is Set, otherwise search for the default function
if EventData.EventFunction then
-- There is an EventFunction defined, so call the EventFunction.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
return EventData.EventFunction( EventClass, Event )
end, ErrorHandler )
else
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
local EventFunction = EventClass[ EventMeta.Event ]
if EventFunction and type( EventFunction ) == "function" then
-- Now call the default event function.
if Event.IniObjectCategory ~= 3 then
self:E( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
end
local Result, Value = xpcall(
function()
local Result, Value = EventFunction( EventClass, Event )
return Result, Value
end, ErrorHandler )
end
end
end
end
end
@ -997,7 +1036,7 @@ function EVENT:onEvent( Event )
end
end
else
self:E( { _EVENTMETA[Event.id].Text, Event } )
self:E( { EventMeta.Text, Event } )
end
Event = nil

View File

@ -5,6 +5,8 @@
--
-- ===
--
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
--
-- A FSM can only be in one of a finite number of states.
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**.
@ -90,8 +92,43 @@ do -- FSM
-- @extends Core.Base#BASE
--- # 1) FSM class, extends @{Base#BASE}
--- # FSM class, extends @{Base#BASE}
--
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
--
-- A FSM can only be in one of a finite number of states.
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**.
-- An **FSM implementation** is defined by **a list of its states**, **its initial state**, and **the triggering events** for **each possible transition**.
-- An FSM implementation is composed out of **two parts**, a set of **state transition rules**, and an implementation set of **state transition handlers**, implementing those transitions.
--
-- The FSM class supports a **hierarchical implementation of a Finite State Machine**,
-- that is, it allows to **embed existing FSM implementations in a master FSM**.
-- FSM hierarchies allow for efficient FSM re-use, **not having to re-invent the wheel every time again** when designing complex processes.
--
-- ![Workflow Example](..\Presentations\FSM\Dia2.JPG)
--
-- The above diagram shows a graphical representation of a FSM implementation for a **Task**, which guides a Human towards a Zone,
-- orders him to destroy x targets and account the results.
-- Other examples of ready made FSM could be:
--
-- * route a plane to a zone flown by a human
-- * detect targets by an AI and report to humans
-- * account for destroyed targets by human players
-- * handle AI infantry to deploy from or embark to a helicopter or airplane or vehicle
-- * let an AI patrol a zone
--
-- The **MOOSE framework** uses extensively the FSM class and derived FSM\_ classes,
-- because **the goal of MOOSE is to simplify mission design complexity for mission building**.
-- By efficiently utilizing the FSM class and derived classes, MOOSE allows mission designers to quickly build processes.
-- **Ready made FSM-based implementations classes** exist within the MOOSE framework that **can easily be re-used,
-- and tailored** by mission designers through **the implementation of Transition Handlers**.
-- Each of these FSM implementation classes start either with:
--
-- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class.
-- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class.
-- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class.
--
-- ![Transition Rules and Transition Handlers and Event Triggers](..\Presentations\FSM\Dia3.JPG)
--
-- The FSM class is the base class of all FSM\_ derived classes. It implements the main functionality to define and execute Finite State Machines.
@ -114,13 +151,13 @@ do -- FSM
-- As explained above, a FSM supports **Linear State Transitions** and **Hierarchical State Transitions**, and both can be mixed to make a comprehensive FSM implementation.
-- The below documentation has a seperate chapter explaining both transition modes, taking into account the **Transition Rules**, **Transition Handlers** and **Event Triggers**.
--
-- ## 1.1) FSM Linear Transitions
-- ## FSM Linear Transitions
--
-- Linear Transitions are Transition Rules allowing an FSM to transition from one or multiple possible **From** state(s) towards a **To** state upon a Triggered **Event**.
-- The Lineair transition rule evaluation will always be done from the **current state** of the FSM.
-- If no valid Transition Rule can be found in the FSM, the FSM will log an error and stop.
--
-- ### 1.1.1) FSM Transition Rules
-- ### FSM Transition Rules
--
-- The FSM has transition rules that it follows and validates, as it walks the process.
-- These rules define when an FSM can transition from a specific state towards an other specific state upon a triggered event.
@ -145,7 +182,7 @@ do -- FSM
-- * It can be switched **Off** by triggering event **SwitchOff**.
-- * Note that once the Switch is **On** or **Middle**, it can only be switched **Off**.
--
-- ### Some additional comments:
-- #### Some additional comments:
--
-- Note that Linear Transition Rules **can be declared in a few variations**:
--
@ -156,7 +193,7 @@ do -- FSM
--
-- FsmSwitch:AddTransition( { "On", "Middle" }, "SwitchOff", "Off" )
--
-- ### 1.1.2) Transition Handling
-- ### Transition Handling
--
-- ![Transition Handlers](..\Presentations\FSM\Dia4.JPG)
--
@ -178,7 +215,7 @@ do -- FSM
--
-- On top, each of these methods can have a variable amount of parameters passed. See the example in section [1.1.3](#1.1.3\)-event-triggers).
--
-- ### 1.1.3) Event Triggers
-- ### Event Triggers
--
-- ![Event Triggers](..\Presentations\FSM\Dia5.JPG)
--
@ -216,7 +253,7 @@ do -- FSM
--
-- Because ... When Event was asynchronously processed after 5 seconds, Amount was set to 2. So be careful when processing and passing values and objects in asynchronous processing!
--
-- ### 1.1.4) Linear Transition Example
-- ### Linear Transition Example
--
-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua)
--
@ -298,7 +335,7 @@ do -- FSM
-- So... When FsmDemo:Stop() is being triggered, the state of FsmDemo will transition from Red or Green to Stopped.
-- And there is no transition handling method defined for that transition, thus, no new event is being triggered causing the FsmDemo process flow to halt.
--
-- ## 1.5) FSM Hierarchical Transitions
-- ## FSM Hierarchical Transitions
--
-- Hierarchical Transitions allow to re-use readily available and implemented FSMs.
-- This becomes in very useful for mission building, where mission designers build complex processes and workflows,
@ -966,15 +1003,20 @@ do -- FSM_PROCESS
-- @param #FSM_PROCESS self
-- @return #FSM_PROCESS
function FSM_PROCESS:Remove()
self:T( { self:GetClassNameAndID() } )
self:F( { self:GetClassNameAndID() } )
self:F( "Clearing Schedules" )
self.CallScheduler:Clear()
-- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do
self:E( { Process} )
Process.fsm:Remove()
Process.fsm = nil
if Process.fsm then
Process.fsm:Remove()
Process.fsm = nil
end
end
return self
end
@ -1079,7 +1121,7 @@ end
self:T( { ProcessUnit, From, Event, To, Dummy, self:IsTrace() } )
if self:IsTrace() then
MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
--MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
end
self:T( { Scores = self._Scores, To = To } )

View File

@ -27,109 +27,26 @@
--
-- ===
--
-- The above menus classes **are derived** from 2 main **abstract** classes defined within the MOOSE framework (so don't use these):
-- # **AUTHORS and CONTRIBUTIONS**
--
-- 1) MENU_ BASE abstract base classes (don't use them)
-- ====================================================
-- The underlying base menu classes are **NOT** to be used within your missions.
-- These are simply abstract base classes defining a couple of fields that are used by the
-- derived MENU_ classes to manage menus.
-- ### Contributions:
--
-- 1.1) @{#MENU_BASE} class, extends @{Base#BASE}
-- --------------------------------------------------
-- The @{#MENU_BASE} class defines the main MENU class where other MENU classes are derived from.
--
-- 1.2) @{#MENU_COMMAND_BASE} class, extends @{Base#BASE}
-- ----------------------------------------------------------
-- The @{#MENU_COMMAND_BASE} class defines the main MENU class where other MENU COMMAND_ classes are derived from, in order to set commands.
--
-- ===
--
-- **The next menus define the MENU classes that you can use within your missions.**
--
-- 2) MENU MISSION classes
-- ======================
-- The underlying classes manage the menus for a complete mission file.
--
-- 2.1) @{#MENU_MISSION} class, extends @{Menu#MENU_BASE}
-- ---------------------------------------------------------
-- The @{Menu#MENU_MISSION} class manages the main menus for a complete mission.
-- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}.
--
-- 2.2) @{#MENU_MISSION_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- -------------------------------------------------------------------------
-- The @{Menu#MENU_MISSION_COMMAND} class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}.
--
-- ===
--
-- 3) MENU COALITION classes
-- =========================
-- The underlying classes manage the menus for whole coalitions.
--
-- 3.1) @{#MENU_COALITION} class, extends @{Menu#MENU_BASE}
-- ------------------------------------------------------------
-- The @{Menu#MENU_COALITION} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.
--
-- 3.2) @{Menu#MENU_COALITION_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- ----------------------------------------------------------------------------
-- The @{Menu#MENU_COALITION_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}.
--
-- ===
--
-- 4) MENU GROUP classes
-- =====================
-- The underlying classes manage the menus for groups. Note that groups can be inactive, alive or can be destroyed.
--
-- 4.1) @{Menu#MENU_GROUP} class, extends @{Menu#MENU_BASE}
-- --------------------------------------------------------
-- The @{Menu#MENU_GROUP} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
--
-- 4.2) @{Menu#MENU_GROUP_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- ------------------------------------------------------------------------
-- The @{Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}.
--
-- ===
--
-- 5) MENU CLIENT classes
-- ======================
-- The underlying classes manage the menus for units with skill level client or player.
--
-- 5.1) @{Menu#MENU_CLIENT} class, extends @{Menu#MENU_BASE}
-- ---------------------------------------------------------
-- The @{Menu#MENU_CLIENT} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_CLIENT.New} method, which constructs a MENU_CLIENT object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT.Remove}.
--
-- 5.2) @{Menu#MENU_CLIENT_COMMAND} class, extends @{Menu#MENU_COMMAND_BASE}
-- -------------------------------------------------------------------------
-- The @{Menu#MENU_CLIENT_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_CLIENT_COMMAND.New} method, which constructs a MENU_CLIENT_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT_COMMAND.Remove}.
--
-- ===
--
-- ### Contributions: -
-- ### Authors: FlightControl : Design & Programming
-- ### Authors:
--
-- * **FlightControl**: Design & Programming
--
-- @module Menu
do -- MENU_BASE
--- The MENU_BASE class
-- @type MENU_BASE
--- @type MENU_BASE
-- @extends Base#BASE
--- # MENU_BASE class, extends @{Base#BASE}
-- The MENU_BASE class defines the main MENU class where other MENU classes are derived from.
-- This is an abstract class, so don't use it.
-- @field #MENU_BASE
MENU_BASE = {
ClassName = "MENU_BASE",
MenuPath = nil,
@ -165,7 +82,7 @@ do -- MENU_BASE
-- @param #string MenuText The text of the child menu.
-- @return #MENU_BASE
function MENU_BASE:GetMenu( MenuText )
self:F( { self.Menus, MenuText } )
self:F2( { Menu = self.Menus[MenuText] } )
return self.Menus[MenuText]
end
@ -174,7 +91,7 @@ do -- MENU_BASE
-- @param #boolean RemoveParent If true, the parent menu is automatically removed when this menu is the last child menu of that parent @{Menu}.
-- @return #MENU_BASE
function MENU_BASE:SetRemoveParent( RemoveParent )
self:F( { RemoveParent } )
self:F2( { RemoveParent } )
self.MenuRemoveParent = RemoveParent
return self
end
@ -193,10 +110,15 @@ end
do -- MENU_COMMAND_BASE
--- The MENU_COMMAND_BASE class
-- @type MENU_COMMAND_BASE
--- @type MENU_COMMAND_BASE
-- @field #function MenuCallHandler
-- @extends Core.Menu#MENU_BASE
--- # MENU_COMMAND_BASE class, extends @{Base#BASE}
-- ----------------------------------------------------------
-- The MENU_COMMAND_BASE class defines the main MENU class where other MENU COMMAND_
-- classes are derived from, in order to set commands.
-- @field #MENU_COMMAND_BASE
MENU_COMMAND_BASE = {
ClassName = "MENU_COMMAND_BASE",
CommandMenuFunction = nil,
@ -224,9 +146,15 @@ end
do -- MENU_MISSION
--- The MENU_MISSION class
-- @type MENU_MISSION
--- @type MENU_MISSION
-- @extends Core.Menu#MENU_BASE
--- # MENU_MISSION class, extends @{Menu#MENU_BASE}
--
-- The MENU_MISSION class manages the main menus for a complete mission.
-- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}.
-- @field #MENU_MISSION
MENU_MISSION = {
ClassName = "MENU_MISSION"
}
@ -291,9 +219,16 @@ end
do -- MENU_MISSION_COMMAND
--- The MENU_MISSION_COMMAND class
-- @type MENU_MISSION_COMMAND
--- @type MENU_MISSION_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_MISSION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
--
-- The MENU_MISSION_COMMAND class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}.
--
-- @field #MENU_MISSION_COMMAND
MENU_MISSION_COMMAND = {
ClassName = "MENU_MISSION_COMMAND"
}
@ -341,9 +276,16 @@ end
do -- MENU_COALITION
--- The MENU_COALITION class
-- @type MENU_COALITION
--- @type MENU_COALITION
-- @extends Core.Menu#MENU_BASE
--- # MENU_COALITION class, extends @{Menu#MENU_BASE}
--
-- The @{Menu#MENU_COALITION} class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.
--
--
-- @usage
-- -- This demo creates a menu structure for the planes within the red coalition.
-- -- To test, join the planes, then look at the other radio menus (Option F10).
@ -380,6 +322,8 @@ do -- MENU_COALITION
--
-- local MenuAdd = MENU_COALITION_COMMAND:New( coalition.side.RED, "Add Status Menu", MenuCoalitionRed, AddStatusMenu )
-- local MenuRemove = MENU_COALITION_COMMAND:New( coalition.side.RED, "Remove Status Menu", MenuCoalitionRed, RemoveStatusMenu )
--
-- @field #MENU_COALITION
MENU_COALITION = {
ClassName = "MENU_COALITION"
}
@ -446,9 +390,16 @@ end
do -- MENU_COALITION_COMMAND
--- The MENU_COALITION_COMMAND class
-- @type MENU_COALITION_COMMAND
--- @type MENU_COALITION_COMMAND
-- @extends Core.Menu#MENU_COMMAND_BASE
--- # MENU_COALITION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
--
-- The MENU_COALITION_COMMAND class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}.
--
-- @field #MENU_COALITION_COMMAND
MENU_COALITION_COMMAND = {
ClassName = "MENU_COALITION_COMMAND"
}
@ -506,6 +457,14 @@ do -- MENU_CLIENT
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
-- @type MENU_CLIENT
-- @extends Core.Menu#MENU_BASE
--- # MENU_CLIENT class, extends @{Menu#MENU_BASE}
--
-- The MENU_CLIENT class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_CLIENT.New} method, which constructs a MENU_CLIENT object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT.Remove}.
--
-- @usage
-- -- This demo creates a menu structure for the two clients of planes.
-- -- Each client will receive a different menu structure.
@ -555,6 +514,8 @@ do -- MENU_CLIENT
-- MENU_CLIENT_COMMAND:New( PlaneClient, "Remove Status Menu Plane 2", MenuManage, RemoveStatusMenu, PlaneClient )
-- end
-- end, {}, 10, 10 )
--
-- @field #MENU_CLIENT
MENU_CLIENT = {
ClassName = "MENU_CLIENT"
}
@ -644,9 +605,16 @@ do -- MENU_CLIENT
end
--- The MENU_CLIENT_COMMAND class
-- @type MENU_CLIENT_COMMAND
--- @type MENU_CLIENT_COMMAND
-- @extends Core.Menu#MENU_COMMAND
--- # MENU_CLIENT_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
--
-- The MENU_CLIENT_COMMAND class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_CLIENT_COMMAND.New} method, which constructs a MENU_CLIENT_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_CLIENT_COMMAND.Remove}.
--
-- @field #MENU_CLIENT_COMMAND
MENU_CLIENT_COMMAND = {
ClassName = "MENU_CLIENT_COMMAND"
}
@ -730,9 +698,16 @@ do
-- These menu classes are handling this logic with this variable.
local _MENUGROUPS = {}
--- The MENU_GROUP class
-- @type MENU_GROUP
--- @type MENU_GROUP
-- @extends Core.Menu#MENU_BASE
--- #MENU_GROUP class, extends @{Menu#MENU_BASE}
--
-- The MENU_GROUP class manages the main menus for coalitions.
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
--
-- @usage
-- -- This demo creates a menu structure for the two groups of planes.
-- -- Each group will receive a different menu structure.
@ -783,6 +758,7 @@ do
-- end
-- end, {}, 10, 10 )
--
-- @field #MENU_GROUP
MENU_GROUP = {
ClassName = "MENU_GROUP"
}
@ -804,7 +780,9 @@ do
self = MenuGroup._Menus[Path]
else
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
MenuGroup._Menus[Path] = self
--if MenuGroup:IsAlive() then
MenuGroup._Menus[Path] = self
--end
self.MenuGroup = MenuGroup
self.Path = Path
@ -832,9 +810,9 @@ do
-- @param MenuTime
-- @return #MENU_GROUP self
function MENU_GROUP:RemoveSubMenus( MenuTime )
self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
--self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
for MenuText, Menu in pairs( self.Menus ) do
Menu:Remove( MenuTime )
end
@ -847,7 +825,7 @@ do
-- @param MenuTime
-- @return #nil
function MENU_GROUP:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
self:RemoveSubMenus( MenuTime )
@ -861,12 +839,12 @@ do
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self:T2( "Removing Parent Menu " )
self.ParentMenu:Remove()
end
end
end
self:T( { "Removing Group Menu:", self.MenuGroup:GetName(), self.MenuGroup._Menus[self.Path].Path } )
self:T( { "Removing Group Menu:", MenuGroup = self.MenuGroup:GetName(), MenuPath = self.MenuGroup._Menus[self.Path].Path } )
self.MenuGroup._Menus[self.Path] = nil
self = nil
end
@ -876,9 +854,16 @@ do
end
--- The MENU_GROUP_COMMAND class
-- @type MENU_GROUP_COMMAND
--- @type MENU_GROUP_COMMAND
-- @extends Core.Menu#MENU_BASE
--- # MENU_GROUP_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
--
-- The @{Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
-- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference.
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}.
--
-- @field #MENU_GROUP_COMMAND
MENU_GROUP_COMMAND = {
ClassName = "MENU_GROUP_COMMAND"
}
@ -897,10 +882,13 @@ do
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
if MenuGroup._Menus[Path] then
self = MenuGroup._Menus[Path]
self:T( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
self:F2( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
else
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
MenuGroup._Menus[Path] = self
--if MenuGroup:IsAlive() then
MenuGroup._Menus[Path] = self
--end
self.Path = Path
self.MenuGroup = MenuGroup
@ -908,13 +896,13 @@ do
self.MenuText = MenuText
self.ParentMenu = ParentMenu
self:T( { "Adding Group Command Menu:", MenuGroup:GetName(), MenuText, self.MenuParentPath } )
self:F( { "Adding Group Command Menu:", MenuGroup = MenuGroup:GetName(), MenuText = MenuText, MenuPath = self.MenuParentPath } )
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
if self.ParentMenu and self.ParentMenu.Menus then
self.ParentMenu.Menus[MenuText] = self
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
self:F( { ParentMenu.Menus, MenuText } )
self:F2( { ParentMenu.Menus, MenuText } )
end
end
@ -926,20 +914,20 @@ do
-- @param MenuTime
-- @return #nil
function MENU_GROUP_COMMAND:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
if not MenuTime or self.MenuTime ~= MenuTime then
if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path]
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
self:T( { "Removing Group Command Menu:", self.MenuGroup:GetName(), self.MenuText, self.Path, self.MenuGroup._Menus[self.Path].Path } )
self:T( { "Removing Group Command Menu:", MenuGroup = self.MenuGroup:GetName(), MenuText = self.MenuText, MenuPath = self.Path } )
self.ParentMenu.Menus[self.MenuText] = nil
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self:T2( "Removing Parent Menu " )
self.ParentMenu:Remove()
end
end

View File

@ -4,18 +4,24 @@
--
-- ===
--
-- # 1) @{Message#MESSAGE} class, extends @{Base#BASE}
-- @module Message
--- The MESSAGE class
-- @type MESSAGE
-- @extends Core.Base#BASE
--- # MESSAGE class, extends @{Base#BASE}
--
-- Message System to display Messages to Clients, Coalitions or All.
-- Messages are shown on the display panel for an amount of seconds, and will then disappear.
-- Messages can contain a category which is indicating the category of the message.
--
-- ## 1.1) MESSAGE construction
-- ## MESSAGE construction
--
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
-- To send messages, you need to use the To functions.
--
-- ## 1.2) Send messages to an audience
-- ## Send messages to an audience
--
-- Messages are sent:
--
@ -26,19 +32,14 @@
-- * To the blue coalition using @{Message#MESSAGE.ToBlue}().
-- * To all Players using @{Message#MESSAGE.ToAll}().
--
-- ## 1.3) Send conditionally to an audience
-- ## Send conditionally to an audience
--
-- Messages can be sent conditionally to an audience (when a condition is true):
--
-- * To all players using @{Message#MESSAGE.ToAllIf}().
-- * To a coalition using @{Message#MESSAGE.ToCoalitionIf}().
--
--
-- @module Message
--- The MESSAGE class
-- @type MESSAGE
-- @extends Core.Base#BASE
-- @field #MESSAGE
MESSAGE = {
ClassName = "MESSAGE",
MessageCategory = 0,

View File

@ -1,91 +1,22 @@
--- **Core** - **POINT\_VEC** classes define an **extensive API** to **manage 3D points** in the simulation space.
--
-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE}
-- ==================================================
-- The @{Point#POINT_VEC3} class defines a 3D point in the simulator.
--
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author, I want to emphasize that the of the MIST framework was created by Grimes, who you can find on the Eagle Dynamics Forums.
--
-- ## 1.1) POINT_VEC3 constructor
--
-- A new POINT_VEC3 instance can be created with:
--
-- * @{Point#POINT_VEC3.New}(): a 3D point.
-- * @{Point#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{DCSTypes#Vec3}.
--
-- ## 1.2) Manupulate the X, Y, Z coordinates of the point
--
-- A POINT_VEC3 class works in 3D space. It contains internally an X, Y, Z coordinate.
-- Methods exist to manupulate these coordinates.
--
-- The current X, Y, Z axis can be retrieved with the methods @{#POINT_VEC3.GetX}(), @{#POINT_VEC3.GetY}(), @{#POINT_VEC3.GetZ}() respectively.
-- The methods @{#POINT_VEC3.SetX}(), @{#POINT_VEC3.SetY}(), @{#POINT_VEC3.SetZ}() change the respective axis with a new value.
-- The current axis values can be changed by using the methods @{#POINT_VEC3.AddX}(), @{#POINT_VEC3.AddY}(), @{#POINT_VEC3.AddZ}()
-- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current POINT_VEC3 object, so these manipulation methods can be chained... For example:
--
-- local Vec3 = PointVec3:AddX( 100 ):AddZ( 150 ):GetVec3()
--
-- ## 1.3) Create waypoints for routes
--
-- A POINT_VEC3 can prepare waypoints for Ground, Air and Naval groups to be embedded into a Route.
--
--
-- ## 1.5) Smoke, flare, explode, illuminate
--
-- At the point a smoke, flare, explosion and illumination bomb can be triggered. Use the following methods:
--
-- ### 1.5.1) Smoke
--
-- * @{#POINT_VEC3.Smoke}(): To smoke the point in a certain color.
-- * @{#POINT_VEC3.SmokeBlue}(): To smoke the point in blue.
-- * @{#POINT_VEC3.SmokeRed}(): To smoke the point in red.
-- * @{#POINT_VEC3.SmokeOrange}(): To smoke the point in orange.
-- * @{#POINT_VEC3.SmokeWhite}(): To smoke the point in white.
-- * @{#POINT_VEC3.SmokeGreen}(): To smoke the point in green.
--
-- ### 1.5.2) Flare
--
-- * @{#POINT_VEC3.Flare}(): To flare the point in a certain color.
-- * @{#POINT_VEC3.FlareRed}(): To flare the point in red.
-- * @{#POINT_VEC3.FlareYellow}(): To flare the point in yellow.
-- * @{#POINT_VEC3.FlareWhite}(): To flare the point in white.
-- * @{#POINT_VEC3.FlareGreen}(): To flare the point in green.
--
-- ### 1.5.3) Explode
--
-- * @{#POINT_VEC3.Explosion}(): To explode the point with a certain intensity.
--
-- ### 1.5.4) Illuminate
--
-- * @{#POINT_VEC3.IlluminationBomb}(): To illuminate the point.
--
--
-- 2) @{Point#POINT_VEC2} class, extends @{Point#POINT_VEC3}
-- =========================================================
-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
-- ![Banner Image](..\Presentations\POINT\Dia1.JPG)
--
-- ====
--
-- 2.1) POINT_VEC2 constructor
-- ---------------------------
-- A new POINT_VEC2 instance can be created with:
-- # Demo Missions
--
-- * @{Point#POINT_VEC2.New}(): a 2D point, taking an additional height parameter.
-- * @{Point#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{DCSTypes#Vec2}.
-- ### [POINT_VEC Demo Missions source code]()
--
-- ## 1.2) Manupulate the X, Altitude, Y coordinates of the 2D point
-- ### [POINT_VEC Demo Missions, only for beta testers]()
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- A POINT_VEC2 class works in 2D space, with an altitude setting. It contains internally an X, Altitude, Y coordinate.
-- Methods exist to manupulate these coordinates.
-- ====
--
-- The current X, Altitude, Y axis can be retrieved with the methods @{#POINT_VEC2.GetX}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetY}() respectively.
-- The methods @{#POINT_VEC2.SetX}(), @{#POINT_VEC2.SetAlt}(), @{#POINT_VEC2.SetY}() change the respective axis with a new value.
-- The current Lat(itude), Alt(itude), Lon(gitude) values can also be retrieved with the methods @{#POINT_VEC2.GetLat}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetLon}() respectively.
-- The current axis values can be changed by using the methods @{#POINT_VEC2.AddX}(), @{#POINT_VEC2.AddAlt}(), @{#POINT_VEC2.AddY}()
-- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current POINT_VEC2 object, so these manipulation methods can be chained... For example:
-- # YouTube Channel
--
-- local Vec2 = PointVec2:AddX( 100 ):AddY( 2000 ):GetVec2()
-- ### [POINT_VEC YouTube Channel]()
--
-- ===
--
@ -133,6 +64,125 @@
-- @field #POINT_VEC3.RoutePointType RoutePointType
-- @field #POINT_VEC3.RoutePointAction RoutePointAction
-- @extends Core.Base#BASE
--- # POINT_VEC3 class, extends @{Base#BASE}
--
-- POINT_VEC3 defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
--
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author,
-- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors,
-- who you can find on the Eagle Dynamics Forums.
--
--
-- ## POINT_VEC3 constructor
--
-- A new POINT_VEC3 object can be created with:
--
-- * @{#POINT_VEC3.New}(): a 3D point.
-- * @{#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{DCSTypes#Vec3}.
--
--
-- ## Manupulate the X, Y, Z coordinates of the POINT_VEC3
--
-- A POINT_VEC3 class works in 3D space. It contains internally an X, Y, Z coordinate.
-- Methods exist to manupulate these coordinates.
--
-- The current X, Y, Z axis can be retrieved with the methods @{#POINT_VEC3.GetX}(), @{#POINT_VEC3.GetY}(), @{#POINT_VEC3.GetZ}() respectively.
-- The methods @{#POINT_VEC3.SetX}(), @{#POINT_VEC3.SetY}(), @{#POINT_VEC3.SetZ}() change the respective axis with a new value.
-- The current axis values can be changed by using the methods @{#POINT_VEC3.AddX}(), @{#POINT_VEC3.AddY}(), @{#POINT_VEC3.AddZ}()
-- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current POINT_VEC3 object, so these manipulation methods can be chained... For example:
--
-- local Vec3 = PointVec3:AddX( 100 ):AddZ( 150 ):GetVec3()
--
--
-- ## Create waypoints for routes
--
-- A POINT_VEC3 can prepare waypoints for Ground and Air groups to be embedded into a Route.
--
-- * @{#POINT_VEC3.RoutePointAir}(): Build an air route point.
-- * @{#POINT_VEC3.RoutePointGround}(): Build a ground route point.
--
-- Route points can be used in the Route methods of the @{Group#GROUP} class.
--
--
-- ## Smoke, flare, explode, illuminate
--
-- At the point a smoke, flare, explosion and illumination bomb can be triggered. Use the following methods:
--
-- ### Smoke
--
-- * @{#POINT_VEC3.Smoke}(): To smoke the point in a certain color.
-- * @{#POINT_VEC3.SmokeBlue}(): To smoke the point in blue.
-- * @{#POINT_VEC3.SmokeRed}(): To smoke the point in red.
-- * @{#POINT_VEC3.SmokeOrange}(): To smoke the point in orange.
-- * @{#POINT_VEC3.SmokeWhite}(): To smoke the point in white.
-- * @{#POINT_VEC3.SmokeGreen}(): To smoke the point in green.
--
-- ### Flare
--
-- * @{#POINT_VEC3.Flare}(): To flare the point in a certain color.
-- * @{#POINT_VEC3.FlareRed}(): To flare the point in red.
-- * @{#POINT_VEC3.FlareYellow}(): To flare the point in yellow.
-- * @{#POINT_VEC3.FlareWhite}(): To flare the point in white.
-- * @{#POINT_VEC3.FlareGreen}(): To flare the point in green.
--
-- ### Explode
--
-- * @{#POINT_VEC3.Explosion}(): To explode the point with a certain intensity.
--
-- ### Illuminate
--
-- * @{#POINT_VEC3.IlluminationBomb}(): To illuminate the point.
--
--
-- ## 3D calculation methods
--
-- Various calculation methods exist to use or manipulate 3D space. Find below a short description of each method:
--
-- ### Distance
--
-- * @{#POINT_VEC3.Get3DDistance}(): Obtain the distance from the current 3D point to the provided 3D point in 3D space.
-- * @{#POINT_VEC3.Get2DDistance}(): Obtain the distance from the current 3D point to the provided 3D point in 2D space.
--
-- ### Angle
--
-- * @{#POINT_VEC3.GetAngleDegrees}(): Obtain the angle in degrees from the current 3D point with the provided 3D direction vector.
-- * @{#POINT_VEC3.GetAngleRadians}(): Obtain the angle in radians from the current 3D point with the provided 3D direction vector.
-- * @{#POINT_VEC3.GetDirectionVec3}(): Obtain the 3D direction vector from the current 3D point to the provided 3D point.
--
-- ### Translation
--
-- * @{#POINT_VEC3.Translate}(): Translate the current 3D point towards an other 3D point using the given Distance and Angle.
--
-- ### Get the North correction of the current location
--
-- * @{#POINT_VEC3.GetNorthCorrection}(): Obtains the north correction at the current 3D point.
--
--
-- ## Point Randomization
--
-- Various methods exist to calculate random locations around a given 3D point.
--
-- * @{#POINT_VEC3.GetRandomPointVec2InRadius}(): Provides a random 2D point around the current 3D point, in the given inner to outer band.
-- * @{#POINT_VEC3.GetRandomPointVec3InRadius}(): Provides a random 3D point around the current 3D point, in the given inner to outer band.
-- * @{#POINT_VEC3.GetRandomVec2InRadius}(): Provides a random 2D vector around the current 3D point, in the given inner to outer band.
-- * @{#POINT_VEC3.GetRandomVec3InRadius}(): Provides a random 3D vector around the current 3D point, in the given inner to outer band.
--
--
-- ## Metric system
--
-- * @{#POINT_VEC3.IsMetric}(): Returns if the 3D point is Metric or Nautical Miles.
-- * @{#POINT_VEC3.SetMetric}(): Sets the 3D point to Metric or Nautical Miles.
--
--
-- ## Coorinate text generation
--
-- * @{#POINT_VEC3.ToStringBR}(): Generates a Bearing & Range text in the format of DDD for DI where DDD is degrees and DI is distance.
-- * @{#POINT_VEC3.ToStringLL}(): Generates a Latutude & Longutude text.
--
-- @field #POINT_VEC3
POINT_VEC3 = {
ClassName = "POINT_VEC3",
Metric = true,
@ -149,16 +199,85 @@ POINT_VEC3 = {
},
}
--- The POINT_VEC2 class
-- @type POINT_VEC2
--- @type POINT_VEC2
-- @field Dcs.DCSTypes#Distance x The x coordinate in meters.
-- @field Dcs.DCSTypes#Distance y the y coordinate in meters.
-- @extends Core.Point#POINT_VEC3
--- # POINT_VEC2 class, extends @{Point#POINT_VEC3}
--
-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
--
-- ## POINT_VEC2 constructor
--
-- A new POINT_VEC2 instance can be created with:
--
-- * @{Point#POINT_VEC2.New}(): a 2D point, taking an additional height parameter.
-- * @{Point#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{DCSTypes#Vec2}.
--
-- ## Manupulate the X, Altitude, Y coordinates of the 2D point
--
-- A POINT_VEC2 class works in 2D space, with an altitude setting. It contains internally an X, Altitude, Y coordinate.
-- Methods exist to manupulate these coordinates.
--
-- The current X, Altitude, Y axis can be retrieved with the methods @{#POINT_VEC2.GetX}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetY}() respectively.
-- The methods @{#POINT_VEC2.SetX}(), @{#POINT_VEC2.SetAlt}(), @{#POINT_VEC2.SetY}() change the respective axis with a new value.
-- The current Lat(itude), Alt(itude), Lon(gitude) values can also be retrieved with the methods @{#POINT_VEC2.GetLat}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetLon}() respectively.
-- The current axis values can be changed by using the methods @{#POINT_VEC2.AddX}(), @{#POINT_VEC2.AddAlt}(), @{#POINT_VEC2.AddY}()
-- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current POINT_VEC2 object, so these manipulation methods can be chained... For example:
--
-- local Vec2 = PointVec2:AddX( 100 ):AddY( 2000 ):GetVec2()
--
-- @field #POINT_VEC2
POINT_VEC2 = {
ClassName = "POINT_VEC2",
}
--- @type COORDINATE
-- @field #number LL_Accuracy
-- @field #boolean LL_DMS
-- @field #number MGRS_Accuracy
-- @field #string System
-- @extends Core.Point#POINT_VEC2
--- # COORDINATE class, extends @{Point#COORDINATE}
--
-- The COORDINATE class defines a 2D coordinate in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
-- A COORDINATE can be expressed in LL or in MGRS.
--
-- ## COORDINATE constructor
--
-- A new COORDINATE instance can be created with:
--
-- * @{Point#COORDINATE.New}(): a 2D point, taking an additional height parameter.
-- * @{Point#COORDINATE.NewFromVec2}(): a 2D point created from a @{DCSTypes#Vec2}.
--
-- ## Manupulate the X, Altitude, Y coordinates of the 2D point
--
-- A COORDINATE class works in 2D space, with an altitude setting. It contains internally an X, Altitude, Y coordinate.
-- Methods exist to manupulate these coordinates.
--
-- The current X, Altitude, Y axis can be retrieved with the methods @{#COORDINATE.GetX}(), @{#COORDINATE.GetAlt}(), @{#COORDINATE.GetY}() respectively.
-- The methods @{#COORDINATE.SetX}(), @{#COORDINATE.SetAlt}(), @{#COORDINATE.SetY}() change the respective axis with a new value.
-- The current Lat(itude), Alt(itude), Lon(gitude) values can also be retrieved with the methods @{#COORDINATE.GetLat}(), @{#COORDINATE.GetAlt}(), @{#COORDINATE.GetLon}() respectively.
-- The current axis values can be changed by using the methods @{#COORDINATE.AddX}(), @{#COORDINATE.AddAlt}(), @{#COORDINATE.AddY}()
-- to add or substract a value from the current respective axis value.
-- Note that the Set and Add methods return the current COORDINATE object, so these manipulation methods can be chained... For example:
--
-- local Vec2 = PointVec2:AddX( 100 ):AddY( 2000 ):GetVec2()
--
-- @field #COORDINATE
COORDINATE = {
ClassName = "COORDINATE",
LL_Accuracy = 2,
LL_DMS = true,
MGRS_Accuracy = 5,
System = "MGRS",
}
do -- POINT_VEC3
--- RoutePoint AltTypes
@ -399,11 +518,11 @@ function POINT_VEC3:GetNorthCorrectionRadians()
end
--- Return a direction in radians from the POINT_VEC3 using a direction vector in Vec3 format.
--- Return an angle in radians from the POINT_VEC3 using a direction vector in Vec3 format.
-- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The direction in radians.
function POINT_VEC3:GetDirectionRadians( DirectionVec3 )
-- @return #number DirectionRadians The angle in radians.
function POINT_VEC3:GetAngleRadians( DirectionVec3 )
local DirectionRadians = math.atan2( DirectionVec3.z, DirectionVec3.x )
--DirectionRadians = DirectionRadians + self:GetNorthCorrectionRadians()
if DirectionRadians < 0 then
@ -412,6 +531,17 @@ function POINT_VEC3:GetDirectionRadians( DirectionVec3 )
return DirectionRadians
end
--- Return an angle in degrees from the POINT_VEC3 using a direction vector in Vec3 format.
-- @param #POINT_VEC3 self
-- @param Dcs.DCSTypes#Vec3 DirectionVec3 The direction vector in Vec3 format.
-- @return #number DirectionRadians The angle in degrees.
function POINT_VEC3:GetAngleDegrees( DirectionVec3 )
local AngleRadians = self:GetAngleRadians(DirectionVec3)
local Angle = UTILS.ToDegree( AngleRadians )
return Angle
end
--- Return the 2D distance in meters between the target POINT_VEC3 and the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #POINT_VEC3 TargetPointVec3 The target POINT_VEC3.
@ -453,17 +583,6 @@ function POINT_VEC3:ToStringBR( AngleRadians, Distance )
return s
end
--- Provides a Bearing / Range string
-- @param #POINT_VEC3 self
-- @param #number AngleRadians The angle in randians
-- @param #number Distance The distance
-- @return #string The BR Text
function POINT_VEC3:ToStringLL( acc, DMS )
acc = acc or 3
local lat, lon = coord.LOtoLL( self:GetVec3() )
return UTILS.tostringLL(lat, lon, acc, DMS)
end
--- Return the altitude text of the POINT_VEC3.
-- @param #POINT_VEC3 self
@ -482,7 +601,7 @@ end
-- @return #string The BR text.
function POINT_VEC3:GetBRText( TargetPointVec3 )
local DirectionVec3 = self:GetDirectionVec3( TargetPointVec3 )
local AngleRadians = self:GetDirectionRadians( DirectionVec3 )
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
local Distance = self:Get2DDistance( TargetPointVec3 )
return self:ToStringBR( AngleRadians, Distance )
end
@ -700,6 +819,25 @@ function POINT_VEC3:FlareRed( Azimuth )
self:Flare( FLARECOLOR.Red, Azimuth )
end
--- Returns if a PointVec3 has Line of Sight (LOS) with the ToPointVec3.
-- @param #POINT_VEC3 self
-- @param #POINT_VEC3 ToPointVec3
-- @return #boolean true If the ToPointVec3 has LOS with the PointVec3, otherwise false.
function POINT_VEC3:IsLOS( ToPointVec3 ) --R2.1
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each PointVec3.
local FromVec3 = self:GetVec3()
FromVec3.y = FromVec3.y + 2
local ToVec3 = ToPointVec3:GetVec3()
ToVec3.y = ToVec3.y + 2
local IsLOS = land.isVisible( FromVec3, ToVec3 )
return IsLOS
end
end
do -- POINT_VEC2
@ -898,7 +1036,7 @@ end
--- Return no text for the altitude of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #string Empty string.
function POINT_VEC2:GetAltitudeText()
function POINT_VEC2:GetAltitudeText()
return ''
end
@ -907,7 +1045,7 @@ end
-- @param Dcs.DCSTypes#Distance Distance The Distance to be added in meters.
-- @param Dcs.DCSTypes#Angle Angle The Angle in degrees.
-- @return #POINT_VEC2 The new calculated POINT_VEC2.
function POINT_VEC2:Translate( Distance, Angle )
function POINT_VEC2:Translate( Distance, Angle )
local SX = self:GetX()
local SY = self:GetY()
local Radians = Angle / 180 * math.pi
@ -919,4 +1057,159 @@ end
end
do -- COORDINATE
--- COORDINATE constructor.
-- @param #COORDINATE self
-- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North.
-- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return Core.Point#COORDINATE
function COORDINATE:New( x, y, LandHeightAdd ) --R2.1 Fixes issue #424.
self = BASE:Inherit( self, POINT_VEC2:New( x, y, LandHeightAdd ) ) -- Core.Point#COORDINATE
self:F2( self )
return self
end
--- Create a new COORDINATE object from Vec2 coordinates.
-- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 point.
-- @param Dcs.DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
-- @return Core.Point#COORDINATE self
function COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) --R2.1 Fixes issue #424.
self = BASE:Inherit( self, POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd ) ) -- Core.Point#COORDINATE
self:F2( self )
return self
end
--- Create a new COORDINATE object from Vec3 coordinates.
-- @param #COORDINATE self
-- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#COORDINATE self
function COORDINATE:NewFromVec3( Vec3 ) --R2.1 Fixes issue #424.
self = BASE:Inherit( self, POINT_VEC2:NewFromVec3( Vec3 ) ) -- Core.Point#COORDINATE
self:F2( self )
return self
end
--- Provides a Lat Lon string
-- @param #COORDINATE self
-- @param #number LL_Accuracy The accurancy of significant numbers behind the comma... So Accurancy of 2 is 0.01.
-- @param #boolean LL_DMS true = Degrees, Minutes, Seconds; false = Degrees, Minutes
-- @return #string The LL Text
function COORDINATE:ToStringLL( LL_Accuracy, LL_DMS ) --R2.1 Fixes issue #424.
LL_Accuracy = LL_Accuracy or self.LL_Accuracy
LL_DMS = LL_DMS or self.LL_DMS
local lat, lon = coord.LOtoLL( self:GetVec3() )
return "LL:" .. UTILS.tostringLL( lat, lon, LL_Accuracy, LL_DMS )
end
--- Provides a MGRS string
-- @param #COORDINATE self
-- @param #number MGRS_Accuracy of the 5 digit code.
-- Precision depends on the Accuracy choosen:
-- * 0 = no digits - precision level 100 km
-- * 1 = 1 digits - precision level 10 km
-- * 2 = 2 digits - precision level 1 km
-- * 3 = 3 digits - precision level 100 m
-- * 4 = 4 digits - precision level 10 m.
-- @return #string The MGRS Text
function COORDINATE:ToStringMGRS( MGRS_Accuracy ) --R2.1 Fixes issue #424.
MGRS_Accuracy = MGRS_Accuracy or self.MGRS_Accuracy
local lat, lon = coord.LOtoLL( self:GetVec3() )
local MGRS = coord.LLtoMGRS( lat, lon )
return "MGRS:" .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
end
--- Provides a coordinate string of the point, based on a coordinate format system:
-- * Uses default settings in COORDINATE.
-- * Can be overridden if for a GROUP containing x clients, a menu was selected to override the default.
--
-- @param #COORDINATE self
-- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToString() --R2.1 Fixes issue #424.
local Coordinate = COORDINATE -- Core.Point#COORDINATE
local CoordSystem = Coordinate.System
if CoordSystem == "LL" then
return self:ToStringLL( Coordinate.LL_Accuracy, Coordinate.LL_DMS )
end
if CoordSystem == "MGRS" then
return self:ToStringMGRS( Coordinate.MGRS_Accuracy )
end
return nil
end
--- @param #COORDINATE self
-- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:CoordinateMenu( RootMenu ) --R2.1 Fixes issue #424.
if self.SystemMenu then
self.SystemMenu:Remove()
self.SystemMenu = nil
end
self.SystemMenu = MENU_MISSION:New( "System Settings" )
local CoordinateMenu = MENU_MISSION:New( "Coordinates", self.SystemMenu )
local Coordinate = COORDINATE
if Coordinate.System == "LL" then
MENU_MISSION_COMMAND:New( "Activate MGRS", CoordinateMenu, Coordinate.MenuSystem, Coordinate, "MGRS" )
MENU_MISSION_COMMAND:New( "LL Accuracy 1", CoordinateMenu, Coordinate.MenuLL_Accuracy, Coordinate, 1 )
MENU_MISSION_COMMAND:New( "LL Accuracy 2", CoordinateMenu, Coordinate.MenuLL_Accuracy, Coordinate, 2 )
MENU_MISSION_COMMAND:New( "LL Accuracy 3", CoordinateMenu, Coordinate.MenuLL_Accuracy, Coordinate, 3 )
MENU_MISSION_COMMAND:New( "LL Decimal On", CoordinateMenu, Coordinate.MenuLL_DMS, Coordinate, true )
MENU_MISSION_COMMAND:New( "LL Decimal Off", CoordinateMenu, Coordinate.MenuLL_DMS, Coordinate, false )
end
if Coordinate.System == "MGRS" then
MENU_MISSION_COMMAND:New( "Activate LL", CoordinateMenu, Coordinate.MenuSystem, Coordinate, "LL" )
MENU_MISSION_COMMAND:New( "MGRS Accuracy 1", CoordinateMenu, Coordinate.MenuMGRS_Accuracy, Coordinate, 1 )
MENU_MISSION_COMMAND:New( "MGRS Accuracy 2", CoordinateMenu, Coordinate.MenuMGRS_Accuracy, Coordinate, 2 )
MENU_MISSION_COMMAND:New( "MGRS Accuracy 3", CoordinateMenu, Coordinate.MenuMGRS_Accuracy, Coordinate, 3 )
MENU_MISSION_COMMAND:New( "MGRS Accuracy 4", CoordinateMenu, Coordinate.MenuMGRS_Accuracy, Coordinate, 4 )
MENU_MISSION_COMMAND:New( "MGRS Accuracy 5", CoordinateMenu, Coordinate.MenuMGRS_Accuracy, Coordinate, 5 )
end
end
--- @param #COORDINATE self
function COORDINATE:MenuSystem( System ) --R2.1 Fixes issue #424.
self.System = System
self:CoordinateMenu()
end
--- @param #COORDINATE self
function COORDINATE:MenuLL_Accuracy( LL_Accuracy ) --R2.1 Fixes issue #424.
self.LL_Accuracy = LL_Accuracy
self:CoordinateMenu()
end
--- @param #COORDINATE self
function COORDINATE:MenuLL_DMS( LL_DMS ) --R2.1 Fixes issue #424.
self.LL_DMS = LL_DMS
self:CoordinateMenu()
end
--- @param #COORDINATE self
function COORDINATE:MenuMGRS_Accuracy( MGRS_Accuracy ) --R2.1 Fixes issue #424.
self.MGRS_Accuracy = MGRS_Accuracy
self:CoordinateMenu()
end
end

View File

@ -1,9 +1,11 @@
--- **Core** - The RADIO class is responsible for **transmitting radio communications**.
--
-- --- bitmap
--- **Core** - The RADIO Module is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio transmissions...
--
-- ![Banner Image](..\Presentations\RADIO\Dia1.JPG)
--
-- ===
--
-- The Radio contains 2 classes : RADIO and BEACON
--
-- What are radio communications in DCS ?
--
-- * Radio transmissions consist of **sound files** that are broadcasted on a specific **frequency** (e.g. 115MHz) and **modulation** (e.g. AM),
@ -23,37 +25,39 @@
--
-- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft,
-- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below).
-- If a FC3 airacraft is used, it will **hear every communication, whatever the frequency and the modulation** is set to.
-- If a FC3 airacraft is used, it will **hear every communication, whatever the frequency and the modulation** is set to. The same is true for TACAN beacons. If your aircaft isn't compatible,
-- you won't hear/be able to use the TACAN beacon informations.
--
-- ===
--
-- ### Authors: Hugues "Grey_Echo" Bousquet
-- ### Author: Hugues "Grey_Echo" Bousquet
--
-- @module Radio
--- # 1) RADIO class, extends @{Base#BASE}
--- # RADIO class, extends @{Base#BASE}
--
-- ## 1.1) RADIO usage
-- ## RADIO usage
--
-- There are 3 steps to a successful radio transmission.
--
-- * First, you need to **"add" a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
-- * First, you need to **"add a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
-- * Then, you will **set the relevant parameters** to the transmission (see below),
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{Positionable#POSITIONABLE.Broadcast}() function.
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
--
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE}
--
-- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"),
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission,
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission.
-- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission.
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead...
--
-- Additional Methods to set relevant parameters if the transmiter is a @{Unit#UNIT} or a @{Group#GROUP}
--
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped,
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
--
-- Additional Methods to set relevant parameters if the transmiter is any other @{Wrapper.Positionable#POSITIONABLE}
-- Additional Methods to set relevant parameters if the transmiter is any other @{Positionable#POSITIONABLE}
--
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
@ -68,7 +72,7 @@
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
--
-- @type RADIO
-- @field Wrapper.Positionable#POSITIONABLE Positionable The transmiter
-- @field Positionable#POSITIONABLE Positionable The transmiter
-- @field #string FileName Name of the sound file
-- @field #number Frequency Frequency of the transmission in Hz
-- @field #number Modulation Modulation of the transmission (either radio.modulation.AM or radio.modulation.FM)
@ -89,12 +93,11 @@ RADIO = {
}
--- Create a new RADIO Object. This doesn't broadcast a transmission, though, use @{#RADIO.Broadcast} to actually broadcast
-- If you want to create a RADIO, you probably should use @{Positionable#POSITIONABLE.GetRadio}() instead
-- @param #RADIO self
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
-- @return #RADIO Radio
-- @return #nil If Positionable is invalid
-- @usage
-- -- If you want to create a RADIO, you probably should use @{Positionable#POSITIONABLE.GetRadio}() instead
function RADIO:New(Positionable)
local self = BASE:Inherit( self, BASE:New() ) -- Core.Radio#RADIO
@ -203,12 +206,18 @@ function RADIO:SetLoop(Loop)
end
--- Check validity of the subtitle and the subtitleDuration passed and sets RADIO.subtitle and RADIO.subtitleDuration
-- Both parameters are mandatory, since it wouldn't make much sense to change the Subtitle and not its duration
-- @param #RADIO self
-- @param #string Subtitle
-- @param #number SubtitleDuration in s
-- @return #RADIO self
-- @usage
-- -- Both parameters are mandatory, since it wouldn't make much sense to change the Subtitle and not its duration
-- -- create the broadcaster and attaches it a RADIO
-- local MyUnit = UNIT:FindByName("MyUnit")
-- local MyUnitRadio = MyUnit:GetRadio()
--
-- -- add a subtitle for the next transmission, which will be up for 10s
-- MyUnitRadio:SetSubtitle("My Subtitle, 10)
function RADIO:SetSubtitle(Subtitle, SubtitleDuration)
self:F2({Subtitle, SubtitleDuration})
if type(Subtitle) == "string" then
@ -228,29 +237,32 @@ function RADIO:SetSubtitle(Subtitle, SubtitleDuration)
end
--- Create a new transmission, that is to say, populate the RADIO with relevant data
-- In this function the data is especially relevant if the broadcaster is anything but a UNIT or a GROUP,
-- but it will work with a UNIT or a GROUP anyway.
-- Only the #RADIO and the Filename are mandatory
-- @param #RADIO self
-- @param #string FileName
-- @param #number Frequency in MHz
-- @param #number Modulation either radio.modulation.AM or radio.modulation.FM
-- @param #number Power in W
-- @return #RADIO self
-- @usage
-- -- In this function the data is especially relevant if the broadcaster is anything but a UNIT or a GROUP,
-- but it will work with a UNIT or a GROUP anyway
-- -- Only the RADIO and the Filename are mandatory
function RADIO:NewGenericTransmission(FileName, Frequency, Modulation, Power)
function RADIO:NewGenericTransmission(FileName, Frequency, Modulation, Power, Loop)
self:F({FileName, Frequency, Modulation, Power})
self:SetFileName(FileName)
if Frequency then self:SetFrequency(Frequency) end
if Modulation then self:SetModulation(Modulation) end
if Power then self:SetPower(Power) end
if Loop then self:SetLoop(Loop) end
return self
end
--- Create a new transmission, that is to say, populate the RADIO with relevant data
-- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
-- but it will work for any @{Positionable#POSITIONABLE}.
-- Only the RADIO and the Filename are mandatory.
-- @param #RADIO self
-- @param #string FileName
-- @param #string Subtitle
@ -259,10 +271,6 @@ end
-- @param #number Modulation either radio.modulation.AM or radio.modulation.FM
-- @param #boolean Loop
-- @return #RADIO self
-- @usage
-- -- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
-- but it will work for any POSITIONABLE
-- -- Only the RADIO and the Filename are mandatory
function RADIO:NewUnitTransmission(FileName, Subtitle, SubtitleDuration, Frequency, Modulation, Loop)
self:F({FileName, Subtitle, SubtitleDuration, Frequency, Modulation, Loop})
@ -277,16 +285,15 @@ function RADIO:NewUnitTransmission(FileName, Subtitle, SubtitleDuration, Frequen
end
--- Actually Broadcast the transmission
-- * The Radio has to be populated with the new transmission before broadcasting.
-- * Please use RADIO setters or either @{Radio#RADIO.NewGenericTransmission} or @{Radio#RADIO.NewUnitTransmission}
-- * This class is in fact pretty smart, it determines the right DCS function to use depending on the type of POSITIONABLE
-- * If the POSITIONABLE is not a UNIT or a GROUP, we use the generic (but limited) trigger.action.radioTransmission()
-- * If the POSITIONABLE is a UNIT or a GROUP, we use the "TransmitMessage" Command
-- * If your POSITIONABLE is a UNIT or a GROUP, the Power is ignored.
-- * If your POSITIONABLE is not a UNIT or a GROUP, the Subtitle, SubtitleDuration are ignored
-- @param #RADIO self
-- @return #RADIO self
-- @usage
-- -- The Radio has to be populated with the new transmission before broadcasting.
-- -- Please use RADIO setters or either @{Radio#RADIO.NewGenericTransmission} or @{Radio#RADIO.NewUnitTransmission}
-- -- This class is in fact pretty smart, it determines the right DCS function to use depending on the type of POSITIONABLE
-- -- If the POSITIONABLE is not a UNIT or a GROUP, we use the generic (but limited) trigger.action.radioTransmission()
-- -- If the POSITIONABLE is a UNIT or a GROUP, we use the "TransmitMessage" Command
-- -- If your POSITIONABLE is a UNIT or a GROUP, the Power is ignored.
-- -- If your POSITIONABLE is not a UNIT or a GROUP, the Subtitle, SubtitleDuration and Loop are ignored
function RADIO:Broadcast()
self:F()
-- If the POSITIONABLE is actually a UNIT or a GROUP, use the more complicated DCS command system
@ -303,18 +310,17 @@ function RADIO:Broadcast()
})
else
-- If the POSITIONABLE is anything else, we revert to the general singleton function
-- I need to give it a unique name, so that the transmission can be stopped later. I use the class ID
self:T2("Broadcasting from a POSITIONABLE")
trigger.action.radioTransmission(self.FileName, self.Positionable:GetPositionVec3(), self.Modulation, false, self.Frequency, self.Power)
trigger.action.radioTransmission(self.FileName, self.Positionable:GetPositionVec3(), self.Modulation, self.Loop, self.Frequency, self.Power, tostring(self.ID))
end
return self
end
--- Stops a transmission
-- This function is especially usefull to stop the broadcast of looped transmissions
-- @param #RADIO self
-- @return #RADIO self
-- @usage
-- -- Especially usefull to stop the broadcast of looped transmissions
-- -- Only works with broadcasts from UNIT or GROUP
function RADIO:StopBroadcast()
self:F()
-- If the POSITIONABLE is a UNIT or a GROUP, stop the transmission with the DCS "StopTransmission" command
@ -324,7 +330,257 @@ function RADIO:StopBroadcast()
params = {}
})
else
self:E("This broadcast can't be stopped. It's not looped either, so please wait for the end of the sound file playback")
-- Else, we use the appropriate singleton funciton
trigger.action.stopRadioTransmission(tostring(self.ID))
end
return self
end
--- # BEACON class, extends @{Base#BASE}
--
-- After attaching a @{#BEACON} to your @{Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
-- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon.
-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is
-- attach to a cargo crate, for exemple.
--
-- ## AA TACAN Beacon usage
--
-- This beacon only works with airborne @{Unit#UNIT} or a @{Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
-- Use @#BEACON:StopAATACAN}() to stop it.
--
-- ## General Purpose Radio Beacon usage
--
-- This beacon will work with any @{Positionable#POSITIONABLE}, but **it won't follow the @{Positionable#POSITIONABLE}** ! This means that you should only use it with
-- @{Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
-- Use @{#BEACON:StopRadioBeacon}() to stop it.
--
-- @type BEACON
-- @extends Core.Base#BASE
BEACON = {
ClassName = "BEACON",
}
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.AATACAN} or @{#BEACON.Generic}
-- If you want to create a BEACON, you probably should use @{Positionable#POSITIONABLE.GetBeacon}() instead.
-- @param #BEACON self
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
-- @return #BEACON Beacon
-- @return #nil If Positionable is invalid
function BEACON:New(Positionable)
local self = BASE:Inherit(self, BASE:New())
self:F(Positionable)
if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid
self.Positionable = Positionable
return self
end
self:E({"The passed positionable is invalid, no BEACON created", Positionable})
return nil
end
--- Converts a TACAN Channel/Mode couple into a frequency in Hz
-- @param #BEACON self
-- @param #number TACANChannel
-- @param #string TACANMode
-- @return #number Frequecy
-- @return #nil if parameters are invalid
function BEACON:_TACANToFrequency(TACANChannel, TACANMode)
self:F3({TACANChannel, TACANMode})
if type(TACANChannel) ~= "number" then
if TACANMode ~= "X" and TACANMode ~= "Y" then
return nil -- error in arguments
end
end
-- This code is largely based on ED's code, in DCS World\Scripts\World\Radio\BeaconTypes.lua, line 137.
-- I have no idea what it does but it seems to work
local A = 1151 -- 'X', channel >= 64
local B = 64 -- channel >= 64
if TACANChannel < 64 then
B = 1
end
if TACANMode == 'Y' then
A = 1025
if TACANChannel < 64 then
A = 1088
end
else -- 'X'
if TACANChannel < 64 then
A = 962
end
end
return (A + TACANChannel - B) * 1000000
end
--- Activates a TACAN BEACON on an Aircraft.
-- @param #BEACON self
-- @param #number TACANChannel (the "10" part in "10Y"). Note that AA TACAN are only available on Y Channels
-- @param #string Message The Message that is going to be coded in Morse and broadcasted by the beacon
-- @param #boolean Bearing Can the BEACON be homed on ?
-- @param #number BeaconDuration How long will the beacon last in seconds. Omit for forever.
-- @return #BEACON self
-- @usage
-- -- Let's create a TACAN Beacon for a tanker
-- local myUnit = UNIT:FindByName("MyUnit")
-- local myBeacon = myUnit:GetBeacon() -- Creates the beacon
--
-- myBeacon:AATACAN(20, "TEXACO", true) -- Activate the beacon
function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration)
self:F({TACANChannel, Message, Bearing, BeaconDuration})
local IsValid = true
if not self.Positionable:IsAir() then
self:E({"The POSITIONABLE you want to attach the AA Tacan Beacon is not an aircraft ! The BEACON is not emitting", self.Positionable})
IsValid = false
end
local Frequency = self:_TACANToFrequency(TACANChannel, "Y")
if not Frequency then
self:E({"The passed TACAN channel is invalid, the BEACON is not emitting"})
IsValid = false
end
-- I'm using the beacon type 4 (BEACON_TYPE_TACAN). For System, I'm using 5 (TACAN_TANKER_MODE_Y) if the bearing shows its bearing
-- or 14 (TACAN_AA_MODE_Y) if it does not
local System
if Bearing then
System = 5
else
System = 14
end
if IsValid then -- Starts the BEACON
self:T2({"AA TACAN BEACON started !"})
self.Positionable:SetCommand({
id = "ActivateBeacon",
params = {
type = 4,
system = System,
callsign = Message,
frequency = Frequency,
}
})
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
SCHEDULER:New( nil,
function()
self:StopAATACAN()
end, {}, BeaconDuration)
end
end
return self
end
--- Stops the AA TACAN BEACON
-- @param #BEACON self
-- @return #BEACON self
function BEACON:StopAATACAN()
self:F()
if not self.Positionable then
self:E({"Start the beacon first before stoping it !"})
else
self.Positionable:SetCommand({
id = 'DeactivateBeacon',
params = {
}
})
end
end
--- Activates a general pupose Radio Beacon
-- This uses the very generic singleton function "trigger.action.radioTransmission()" provided by DCS to broadcast a sound file on a specific frequency.
-- Although any frequency could be used, only 2 DCS Modules can home on radio beacons at the time of writing : the Huey and the Mi-8.
-- They can home in on these specific frequencies :
-- * **Mi8**
-- * R-828 -> 20-60MHz
-- * ARKUD -> 100-150MHz (canal 1 : 114166, canal 2 : 114333, canal 3 : 114583, canal 4 : 121500, canal 5 : 123100, canal 6 : 124100) AM
-- * ARK9 -> 150-1300KHz
-- * **Huey**
-- * AN/ARC-131 -> 30-76 Mhz FM
-- @param #BEACON self
-- @param #string FileName The name of the audio file
-- @param #number Frequency in MHz
-- @param #number Modulation either radio.modulation.AM or radio.modulation.FM
-- @param #number Power in W
-- @param #number BeaconDuration How long will the beacon last in seconds. Omit for forever.
-- @return #BEACON self
-- @usage
-- -- Let's create a beacon for a unit in distress.
-- -- Frequency will be 40MHz FM (home-able by a Huey's AN/ARC-131)
-- -- The beacon they use is battery-powered, and only lasts for 5 min
-- local UnitInDistress = UNIT:FindByName("Unit1")
-- local UnitBeacon = UnitInDistress:GetBeacon()
--
-- -- Set the beacon and start it
-- UnitBeacon:RadioBeacon("MySoundFileSOS.ogg", 40, radio.modulation.FM, 20, 5*60)
function BEACON:RadioBeacon(FileName, Frequency, Modulation, Power, BeaconDuration)
self:F({FileName, Frequency, Modulation, Power, BeaconDuration})
local IsValid = false
-- Check the filename
if type(FileName) == "string" then
if FileName:find(".ogg") or FileName:find(".wav") then
if not FileName:find("l10n/DEFAULT/") then
FileName = "l10n/DEFAULT/" .. FileName
end
IsValid = true
end
end
if not IsValid then
self:E({"File name invalid. Maybe something wrong with the extension ? ", FileName})
end
-- Check the Frequency
if type(Frequency) ~= "number" and IsValid then
self:E({"Frequency invalid. ", Frequency})
IsValid = false
end
Frequency = Frequency * 1000000 -- Conversion to Hz
-- Check the modulation
if Modulation ~= radio.modulation.AM and Modulation ~= radio.modulation.FM and IsValid then --TODO Maybe make this future proof if ED decides to add an other modulation ?
self:E({"Modulation is invalid. Use DCS's enum radio.modulation.", Modulation})
IsValid = false
end
-- Check the Power
if type(Power) ~= "number" and IsValid then
self:E({"Power is invalid. ", Power})
IsValid = false
end
Power = math.floor(math.abs(Power)) --TODO Find what is the maximum power allowed by DCS and limit power to that
if IsValid then
self:T2({"Activating Beacon on ", Frequency, Modulation})
-- Note that this is looped. I have to give this transmission a unique name, I use the class ID
trigger.action.radioTransmission(FileName, self.Positionable:GetPositionVec3(), Modulation, true, Frequency, Power, tostring(self.ID))
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
SCHEDULER:New( nil,
function()
self:StopRadioBeacon()
end, {}, BeaconDuration)
end
end
end
--- Stops the AA TACAN BEACON
-- @param #BEACON self
-- @return #BEACON self
function BEACON:StopRadioBeacon()
self:F()
-- The unique name of the transmission is the class ID
trigger.action.stopRadioTransmission(tostring(self.ID))
end

View File

@ -191,7 +191,7 @@ function SCHEDULEDISPATCHER:Start( Scheduler, CallID )
)
end
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Start( Scheduler, CallID ) -- Recursive
end
end
@ -209,7 +209,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
Schedule[CallID].ScheduleID = nil
end
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end
@ -218,7 +218,7 @@ end
function SCHEDULEDISPATCHER:Clear( Scheduler )
self:F2( { Scheduler = Scheduler } )
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end

View File

@ -4,31 +4,30 @@
--
-- ===
--
-- # 1) @{Scheduler#SCHEDULER} class, extends @{Base#BASE}
-- SCHEDULER manages the **scheduling of functions**:
--
-- The @{Scheduler#SCHEDULER} class creates schedule.
--
-- ## 1.1) SCHEDULER constructor
--
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
--
-- * @{Scheduler#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
-- * @{Scheduler#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
-- * @{Scheduler#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
-- * @{Scheduler#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
--
-- ## 1.2) SCHEDULER timer stopping and (re-)starting.
--
-- The SCHEDULER can be stopped and restarted with the following methods:
--
-- * @{Scheduler#SCHEDULER.Start}(): (Re-)Start the schedules within the SCHEDULER object. If a CallID is provided to :Start(), only the schedule referenced by CallID will be (re-)started.
-- * @{Scheduler#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
--
-- ## 1.3) Create a new schedule
--
-- With @{Scheduler#SCHEDULER.Schedule}() a new time event can be scheduled. This function is used by the :New() constructor when a new schedule is planned.
-- * optionally in an optional specified time interval,
-- * optionally **repeating** with a specified time repeat interval,
-- * optionally **randomizing** with a specified time interval randomization factor,
-- * optionally **stop** the repeating after a specified time interval.
--
-- ===
--
-- # Demo Missions
--
-- ### [SCHEDULER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SCH%20-%20Scheduler)
--
-- ### [SCHEDULER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [SCHEDULER YouTube Channel (none)]()
--
-- ====
--
-- ### Contributions:
--
@ -38,10 +37,6 @@
--
-- * FlightControl : Design & Programming
--
-- ### Test Missions:
--
-- * SCH - Scheduler
--
-- ===
--
-- @module Scheduler
@ -51,6 +46,153 @@
-- @type SCHEDULER
-- @field #number ScheduleID the ID of the scheduler.
-- @extends Core.Base#BASE
--- # SCHEDULER class, extends @{Base#BASE}
--
-- The SCHEDULER class creates schedule.
--
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
-- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{SCHEDULER.Start}() and @{SCHEDULER.Stop}(),
-- which can start and stop specific repeating schedules respectively within a SCHEDULER object.
--
-- ## SCHEDULER constructor
--
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
--
-- The @{#SCHEDULER.New}() method returns 2 variables:
--
-- 1. The SCHEDULER object reference.
-- 2. The first schedule planned in the SCHEDULER object.
--
-- To clarify the different appliances, lets have a look at the following examples:
--
-- ### Construct a SCHEDULER object without a persistent schedule.
--
-- * @{#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
--
-- SchedulerObject = SCHEDULER:New()
-- SchedulerID = SchedulerObject:Schedule( nil, ScheduleFunction, {} )
--
-- The above example creates a new SchedulerObject, but does not schedule anything.
-- A separate schedule is created by using the SchedulerObject using the method :Schedule..., which returns a ScheduleID
--
-- ### Construct a SCHEDULER object without a volatile schedule, but volatile to the Object existence...
--
-- * @{#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
--
-- ZoneObject = ZONE:New( "ZoneName" )
-- SchedulerObject = SCHEDULER:New( ZoneObject )
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
-- ...
-- ZoneObject = nil
-- garbagecollect()
--
-- The above example creates a new SchedulerObject, but does not schedule anything, and is bound to the existence of ZoneObject, which is a ZONE.
-- A separate schedule is created by using the SchedulerObject using the method :Schedule()..., which returns a ScheduleID
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
-- As a result, the ScheduleObject will cancel any planned schedule.
--
-- ### Construct a SCHEDULER object with a persistent schedule.
--
-- * @{#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
--
-- SchedulerObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
--
-- The above example creates a new SchedulerObject, and does schedule the first schedule as part of the call.
-- Note that 2 variables are returned here: SchedulerObject, ScheduleID...
--
-- ### Construct a SCHEDULER object without a schedule, but volatile to the Object existence...
--
-- * @{#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
--
-- ZoneObject = ZONE:New( "ZoneName" )
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
-- ...
-- ZoneObject = nil
-- garbagecollect()
--
-- The above example creates a new SchedulerObject, and schedules a method call (ScheduleFunction),
-- and is bound to the existence of ZoneObject, which is a ZONE object (ZoneObject).
-- Both a ScheduleObject and a SchedulerID variable are returned.
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
-- As a result, the ScheduleObject will cancel the planned schedule.
--
-- ## SCHEDULER timer stopping and (re-)starting.
--
-- The SCHEDULER can be stopped and restarted with the following methods:
--
-- * @{#SCHEDULER.Start}(): (Re-)Start the schedules within the SCHEDULER object. If a CallID is provided to :Start(), only the schedule referenced by CallID will be (re-)started.
-- * @{#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
--
-- ZoneObject = ZONE:New( "ZoneName" )
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 10 )
-- ...
-- SchedulerObject:Stop( SchedulerID )
-- ...
-- SchedulerObject:Start( SchedulerID )
--
-- The above example creates a new SchedulerObject, and does schedule the first schedule as part of the call.
-- Note that 2 variables are returned here: SchedulerObject, ScheduleID...
-- Later in the logic, the repeating schedule with SchedulerID is stopped.
-- A bit later, the repeating schedule with SchedulerId is (re)-started.
--
-- ## Create a new schedule
--
-- With the method @{#SCHEDULER.Schedule}() a new time event can be scheduled.
-- This method is used by the :New() constructor when a new schedule is planned.
--
-- Consider the following code fragment of the SCHEDULER object creation.
--
-- ZoneObject = ZONE:New( "ZoneName" )
-- SchedulerObject = SCHEDULER:New( ZoneObject )
--
-- Several parameters can be specified that influence the behaviour of a Schedule.
--
-- ### A single schedule, immediately executed
--
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
--
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within milleseconds ...
--
-- ### A single schedule, planned over time
--
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10 )
--
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds ...
--
-- ### A schedule with a repeating time interval, planned over time
--
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60 )
--
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
-- and repeating 60 every seconds ...
--
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization
--
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5 )
--
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
-- and repeating 60 seconds, with a 50% time interval randomization ...
-- So the repeating time interval will be randomized using the **0.5**,
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
-- which is in this example between **30** and **90** seconds.
--
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization, and stop after a time interval
--
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5, 300 )
--
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
-- The schedule will repeat every 60 seconds.
-- So the repeating time interval will be randomized using the **0.5**,
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
-- which is in this example between **30** and **90** seconds.
-- The schedule will stop after **300** seconds.
--
-- @field #SCHEDULER
SCHEDULER = {
ClassName = "SCHEDULER",
Schedules = {},

View File

@ -124,7 +124,7 @@ end
-- @param Core.Base#BASE Object
-- @return Core.Base#BASE The added BASE Object.
function SET_BASE:Add( ObjectName, Object )
self:F2( ObjectName )
self:F( ObjectName )
local t = { _ = Object }
@ -140,7 +140,7 @@ function SET_BASE:Add( ObjectName, Object )
self.List.Count = self.List.Count + 1
self.Set[ObjectName] = t._
self.Set[ObjectName] = Object
table.insert( self.Index, ObjectName )
@ -165,11 +165,10 @@ end
-- @param #SET_BASE self
-- @param #string ObjectName
function SET_BASE:Remove( ObjectName )
self:F( ObjectName )
local t = self.Set[ObjectName]
self:E( { ObjectName, t } )
self:F3( { ObjectName, t } )
if t then
if t._next then
@ -342,6 +341,26 @@ function SET_BASE:_FilterStart()
return self
end
--- Starts the filtering of the Dead events for the collection.
-- @param #SET_BASE self
-- @return #SET_BASE self
function SET_BASE:FilterDeads() --R2.1 allow deads to be filtered to automatically handle deads in the collection.
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
return self
end
--- Starts the filtering of the Crash events for the collection.
-- @param #SET_BASE self
-- @return #SET_BASE self
function SET_BASE:FilterCrashes() --R2.1 allow crashes to be filtered to automatically handle crashes in the collection.
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
return self
end
--- Stops the filtering for the defined collection.
-- @param #SET_BASE self
-- @return #SET_BASE self
@ -430,7 +449,7 @@ function SET_BASE:_EventOnDeadOrCrash( Event )
if Event.IniDCSUnit then
local ObjectName, Object = self:FindInDatabase( Event )
if ObjectName and Object ~= nil then
if ObjectName then
self:Remove( ObjectName )
end
end
@ -465,7 +484,7 @@ function SET_BASE:_EventOnPlayerLeaveUnit( Event )
local PlayerCount = 0
for _, DCSUnit in pairs( GroupUnits ) do
if DCSUnit ~= Event.IniDCSUnit then
if DCSUnit:getPlayer() ~= nil then
if DCSUnit:getPlayerName() ~= nil then
PlayerCount = PlayerCount + 1
end
end
@ -736,6 +755,31 @@ function SET_GROUP:FindGroup( GroupName )
return GroupFound
end
--- Iterate the SET_GROUP while identifying the nearest object from a @{Point#POINT_VEC2}.
-- @param #SET_GROUP self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @return Wrapper.Group#GROUP The closest group.
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 )
self:F2( PointVec2 )
local NearestGroup = nil
local ClosestDistance = nil
for ObjectID, ObjectData in pairs( self.Set ) do
if NearestGroup == nil then
NearestGroup = ObjectData
ClosestDistance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
else
local Distance = PointVec2:DistanceFromVec2( ObjectData:GetVec2() )
if Distance < ClosestDistance then
NearestGroup = ObjectData
ClosestDistance = Distance
end
end
end
return NearestGroup
end
--- Builds a set of groups of coalitions.
@ -936,6 +980,185 @@ function SET_GROUP:ForEachGroupNotInZone( ZoneObject, IteratorFunction, ... )
return self
end
--- Iterate the SET_GROUP and return true if all the @{Wrapper.Group#GROUP} are completely in the @{Core.Zone#ZONE}
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if all the @{Wrapper.Group#GROUP} are completly in the @{Core.Zone#ZONE}, false otherwise
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- if MySetGroup:AllCompletelyInZone(MyZone) then
-- MESSAGE:New("All the SET's GROUP are in zone !", 10):ToAll()
-- else
-- MESSAGE:New("Some or all SET's GROUP are outside zone !", 10):ToAll()
-- end
function SET_GROUP:AllCompletelyInZone(Zone)
self:F2(Zone)
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if not GroupData:IsCompletelyInZone(Zone) then
return false
end
end
return true
end
--- Iterate the SET_GROUP and return true if at least one of the @{Wrapper.Group#GROUP} is completely inside the @{Core.Zone#ZONE}
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is completly inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- if MySetGroup:AnyCompletelyInZone(MyZone) then
-- MESSAGE:New("At least one GROUP is completely in zone !", 10):ToAll()
-- else
-- MESSAGE:New("No GROUP is completely in zone !", 10):ToAll()
-- end
function SET_GROUP:AnyCompletelyInZone(Zone)
self:F2(Zone)
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if GroupData:IsCompletelyInZone(Zone) then
return true
end
end
return false
end
--- Iterate the SET_GROUP and return true if at least one @{#UNIT} of one @{GROUP} of the @{SET_GROUP} is in @{ZONE}
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- if MySetGroup:AnyPartlyInZone(MyZone) then
-- MESSAGE:New("At least one GROUP has at least one UNIT in zone !", 10):ToAll()
-- else
-- MESSAGE:New("No UNIT of any GROUP is in zone !", 10):ToAll()
-- end
function SET_GROUP:AnyInZone(Zone)
self:F2(Zone)
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if GroupData:IsPartlyInZone(Zone) or GroupData:IsCompletelyInZone(Zone) then
return true
end
end
return false
end
--- Iterate the SET_GROUP and return true if at least one @{GROUP} of the @{SET_GROUP} is partly in @{ZONE}.
-- Will return false if a @{GROUP} is fully in the @{ZONE}
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if at least one of the @{Wrapper.Group#GROUP} is partly or completly inside the @{Core.Zone#ZONE}, false otherwise.
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- if MySetGroup:AnyPartlyInZone(MyZone) then
-- MESSAGE:New("At least one GROUP is partially in the zone, but none are fully in it !", 10):ToAll()
-- else
-- MESSAGE:New("No GROUP are in zone, or one (or more) GROUP is completely in it !", 10):ToAll()
-- end
function SET_GROUP:AnyPartlyInZone(Zone)
self:F2(Zone)
local IsPartlyInZone = false
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if GroupData:IsCompletelyInZone(Zone) then
return false
elseif GroupData:IsPartlyInZone(Zone) then
IsPartlyInZone = true -- at least one GROUP is partly in zone
end
end
if IsPartlyInZone then
return true
else
return false
end
end
--- Iterate the SET_GROUP and return true if no @{GROUP} of the @{SET_GROUP} is in @{ZONE}
-- This could also be achieved with `not SET_GROUP:AnyPartlyInZone(Zone)`, but it's easier for the
-- mission designer to add a dedicated method
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #boolean true if no @{Wrapper.Group#GROUP} is inside the @{Core.Zone#ZONE} in any way, false otherwise.
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- if MySetGroup:NoneInZone(MyZone) then
-- MESSAGE:New("No GROUP is completely in zone !", 10):ToAll()
-- else
-- MESSAGE:New("No UNIT of any GROUP is in zone !", 10):ToAll()
-- end
function SET_GROUP:NoneInZone(Zone)
self:F2(Zone)
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if not GroupData:IsNotInZone(Zone) then -- If the GROUP is in Zone in any way
return false
end
end
return true
end
--- Iterate the SET_GROUP and count how many GROUPs are completely in the Zone
-- That could easily be done with SET_GROUP:ForEachGroupCompletelyInZone(), but this function
-- provides an easy to use shortcut...
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #number the number of GROUPs completely in the Zone
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- MESSAGE:New("There are " .. MySetGroup:CountInZone(MyZone) .. " GROUPs in the Zone !", 10):ToAll()
function SET_GROUP:CountInZone(Zone)
self:F2(Zone)
local Count = 0
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
if GroupData:IsCompletelyInZone(Zone) then
Count = Count + 1
end
end
return Count
end
--- Iterate the SET_GROUP and count how many UNITs are completely in the Zone
-- @param #SET_GROUP self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
-- @return #number the number of GROUPs completely in the Zone
-- @usage
-- local MyZone = ZONE:New("Zone1")
-- local MySetGroup = SET_GROUP:New()
-- MySetGroup:AddGroupsByName({"Group1", "Group2"})
--
-- MESSAGE:New("There are " .. MySetGroup:CountUnitInZone(MyZone) .. " UNITs in the Zone !", 10):ToAll()
function SET_GROUP:CountUnitInZone(Zone)
self:F2(Zone)
local Count = 0
local Set = self:GetSet()
for GroupID, GroupData in pairs(Set) do -- For each GROUP in SET_GROUP
Count = Count + GroupData:CountInZone(Zone)
end
return Count
end
----- Iterate the SET_GROUP and call an interator function for each **alive** player, providing the Group of the player and optional parameters.
---- @param #SET_GROUP self
@ -1113,6 +1336,11 @@ SET_UNIT = {
}
--- Get the first unit from the set.
-- @function [parent=#SET_UNIT] GetFirst
-- @param #SET_UNIT self
-- @return Wrapper.Unit#UNIT The UNIT object.
--- Creates a new SET_UNIT object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #SET_UNIT self
-- @return #SET_UNIT
@ -1122,7 +1350,7 @@ SET_UNIT = {
function SET_UNIT:New()
-- Inherits from BASE
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.UNITS ) )
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.UNITS ) ) -- Core.Set#SET_UNIT
return self
end
@ -1344,7 +1572,7 @@ end
-- @return #string The name of the UNIT
-- @return #table The UNIT
function SET_UNIT:FindInDatabase( Event )
self:E( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
self:F2( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
return Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName]
@ -1362,6 +1590,54 @@ function SET_UNIT:ForEachUnit( IteratorFunction, ... )
return self
end
--- Iterate the SET_UNIT **sorted *per Threat Level** and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters.
--
-- @param #SET_UNIT self
-- @param #number FromThreatLevel The TreatLevel to start the evaluation **From** (this must be a value between 0 and 10).
-- @param #number ToThreatLevel The TreatLevel to stop the evaluation **To** (this must be a value between 0 and 10).
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
-- @return #SET_UNIT self
-- @usage
--
-- UnitSet:ForEachUnitPerThreatLevel( 10, 0,
-- -- @param Wrapper.Unit#UNIT UnitObject The UNIT object in the UnitSet, that will be passed to the local function for evaluation.
-- function( UnitObject )
-- .. logic ..
-- end
-- )
--
function SET_UNIT:ForEachUnitPerThreatLevel( FromThreatLevel, ToThreatLevel, IteratorFunction, ... ) --R2.1 Threat Level implementation
self:F2( arg )
local ThreatLevelSet = {}
if self:Count() ~= 0 then
for UnitName, UnitObject in pairs( self.Set ) do
local Unit = UnitObject -- Wrapper.Unit#UNIT
local ThreatLevel = Unit:GetThreatLevel()
ThreatLevelSet[ThreatLevel] = ThreatLevelSet[ThreatLevel] or {}
ThreatLevelSet[ThreatLevel].Set = ThreatLevelSet[ThreatLevel].Set or {}
ThreatLevelSet[ThreatLevel].Set[UnitName] = UnitObject
self:E( { ThreatLevel = ThreatLevel, ThreatLevelSet = ThreatLevelSet[ThreatLevel].Set } )
end
local ThreatLevelIncrement = FromThreatLevel <= ToThreatLevel and 1 or -1
for ThreatLevel = FromThreatLevel, ToThreatLevel, ThreatLevelIncrement do
self:E( { ThreatLevel = ThreatLevel } )
local ThreatLevelItem = ThreatLevelSet[ThreatLevel]
if ThreatLevelItem then
self:ForEach( IteratorFunction, arg, ThreatLevelItem.Set )
end
end
end
return self
end
--- Iterate the SET_UNIT and call an iterator function for each **alive** UNIT presence completely in a @{Zone}, providing the UNIT and optional parameters to the called function.
-- @param #SET_UNIT self
-- @param Core.Zone#ZONE ZoneObject The Zone to be tested for.
@ -1374,7 +1650,7 @@ function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ...
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
if UnitObject:IsCompletelyInZone( ZoneObject ) then
if UnitObject:IsInZone( ZoneObject ) then
return true
else
return false
@ -2391,3 +2667,346 @@ function SET_AIRBASE:IsIncludeObject( MAirbase )
self:T2( MAirbaseInclude )
return MAirbaseInclude
end
--- @type SET_CARGO
-- @extends Core.Set#SET_BASE
--- # (R2.1) SET_CARGO class, extends @{Set#SET_BASE}
--
-- Mission designers can use the @{Set#SET_CARGO} class to build sets of cargos optionally belonging to certain:
--
-- * Coalitions
-- * Types
-- * Name or Prefix
--
-- ## SET_CARGO constructor
--
-- Create a new SET_CARGO object with the @{#SET_CARGO.New} method:
--
-- * @{#SET_CARGO.New}: Creates a new SET_CARGO object.
--
-- ## Add or Remove CARGOs from SET_CARGO
--
-- CARGOs can be added and removed using the @{Set#SET_CARGO.AddCargosByName} and @{Set#SET_CARGO.RemoveCargosByName} respectively.
-- These methods take a single CARGO name or an array of CARGO names to be added or removed from SET_CARGO.
--
-- ## SET_CARGO filter criteria
--
-- You can set filter criteria to automatically maintain the SET_CARGO contents.
-- Filter criteria are defined by:
--
-- * @{#SET_CARGO.FilterCoalitions}: Builds the SET_CARGO with the cargos belonging to the coalition(s).
-- * @{#SET_CARGO.FilterPrefixes}: Builds the SET_CARGO with the cargos containing the prefix string(s).
-- * @{#SET_CARGO.FilterTypes}: Builds the SET_CARGO with the cargos belonging to the cargo type(s).
-- * @{#SET_CARGO.FilterCountries}: Builds the SET_CARGO with the cargos belonging to the country(ies).
--
-- Once the filter criteria have been set for the SET_CARGO, you can start filtering using:
--
-- * @{#SET_CARGO.FilterStart}: Starts the filtering of the cargos within the SET_CARGO.
--
-- ## SET_CARGO iterators
--
-- Once the filters have been defined and the SET_CARGO has been built, you can iterate the SET_CARGO with the available iterator methods.
-- The iterator methods will walk the SET_CARGO set, and call for each cargo within the set a function that you provide.
-- The following iterator methods are currently available within the SET_CARGO:
--
-- * @{#SET_CARGO.ForEachCargo}: Calls a function for each cargo it finds within the SET_CARGO.
--
-- @field #SET_CARGO SET_CARGO
--
SET_CARGO = {
ClassName = "SET_CARGO",
Cargos = {},
Filter = {
Coalitions = nil,
Types = nil,
Countries = nil,
ClientPrefixes = nil,
},
FilterMeta = {
Coalitions = {
red = coalition.side.RED,
blue = coalition.side.BLUE,
neutral = coalition.side.NEUTRAL,
},
},
}
--- (R2.1) Creates a new SET_CARGO object, building a set of cargos belonging to a coalitions and categories.
-- @param #SET_CARGO self
-- @return #SET_CARGO self
-- @usage
-- -- Define a new SET_CARGO Object. The DatabaseSet will contain a reference to all Cargos.
-- DatabaseSet = SET_CARGO:New()
function SET_CARGO:New() --R2.1
-- Inherits from BASE
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.CARGOS ) )
return self
end
--- (R2.1) Add CARGOs to SET_CARGO.
-- @param Core.Set#SET_CARGO self
-- @param #string AddCargoNames A single name or an array of CARGO names.
-- @return self
function SET_CARGO:AddCargosByName( AddCargoNames ) --R2.1
local AddCargoNamesArray = ( type( AddCargoNames ) == "table" ) and AddCargoNames or { AddCargoNames }
for AddCargoID, AddCargoName in pairs( AddCargoNamesArray ) do
self:Add( AddCargoName, CARGO:FindByName( AddCargoName ) )
end
return self
end
--- (R2.1) Remove CARGOs from SET_CARGO.
-- @param Core.Set#SET_CARGO self
-- @param Wrapper.Cargo#CARGO RemoveCargoNames A single name or an array of CARGO names.
-- @return self
function SET_CARGO:RemoveCargosByName( RemoveCargoNames ) --R2.1
local RemoveCargoNamesArray = ( type( RemoveCargoNames ) == "table" ) and RemoveCargoNames or { RemoveCargoNames }
for RemoveCargoID, RemoveCargoName in pairs( RemoveCargoNamesArray ) do
self:Remove( RemoveCargoName.CargoName )
end
return self
end
--- (R2.1) Finds a Cargo based on the Cargo Name.
-- @param #SET_CARGO self
-- @param #string CargoName
-- @return Wrapper.Cargo#CARGO The found Cargo.
function SET_CARGO:FindCargo( CargoName ) --R2.1
local CargoFound = self.Set[CargoName]
return CargoFound
end
--- (R2.1) Builds a set of cargos of coalitions.
-- Possible current coalitions are red, blue and neutral.
-- @param #SET_CARGO self
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
-- @return #SET_CARGO self
function SET_CARGO:FilterCoalitions( Coalitions ) --R2.1
if not self.Filter.Coalitions then
self.Filter.Coalitions = {}
end
if type( Coalitions ) ~= "table" then
Coalitions = { Coalitions }
end
for CoalitionID, Coalition in pairs( Coalitions ) do
self.Filter.Coalitions[Coalition] = Coalition
end
return self
end
--- (R2.1) Builds a set of cargos of defined cargo types.
-- Possible current types are those types known within DCS world.
-- @param #SET_CARGO self
-- @param #string Types Can take those type strings known within DCS world.
-- @return #SET_CARGO self
function SET_CARGO:FilterTypes( Types ) --R2.1
if not self.Filter.Types then
self.Filter.Types = {}
end
if type( Types ) ~= "table" then
Types = { Types }
end
for TypeID, Type in pairs( Types ) do
self.Filter.Types[Type] = Type
end
return self
end
--- (R2.1) Builds a set of cargos of defined countries.
-- Possible current countries are those known within DCS world.
-- @param #SET_CARGO self
-- @param #string Countries Can take those country strings known within DCS world.
-- @return #SET_CARGO self
function SET_CARGO:FilterCountries( Countries ) --R2.1
if not self.Filter.Countries then
self.Filter.Countries = {}
end
if type( Countries ) ~= "table" then
Countries = { Countries }
end
for CountryID, Country in pairs( Countries ) do
self.Filter.Countries[Country] = Country
end
return self
end
--- (R2.1) Builds a set of cargos of defined cargo prefixes.
-- All the cargos starting with the given prefixes will be included within the set.
-- @param #SET_CARGO self
-- @param #string Prefixes The prefix of which the cargo name starts with.
-- @return #SET_CARGO self
function SET_CARGO:FilterPrefixes( Prefixes ) --R2.1
if not self.Filter.CargoPrefixes then
self.Filter.CargoPrefixes = {}
end
if type( Prefixes ) ~= "table" then
Prefixes = { Prefixes }
end
for PrefixID, Prefix in pairs( Prefixes ) do
self.Filter.CargoPrefixes[Prefix] = Prefix
end
return self
end
--- (R2.1) Starts the filtering.
-- @param #SET_CARGO self
-- @return #SET_CARGO self
function SET_CARGO:FilterStart() --R2.1
if _DATABASE then
self:_FilterStart()
end
self:HandleEvent( EVENTS.NewCargo )
self:HandleEvent( EVENTS.DeleteCargo )
return self
end
--- (R2.1) Handles the Database to check on an event (birth) that the Object was added in the Database.
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
-- @param #SET_CARGO self
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the CARGO
-- @return #table The CARGO
function SET_CARGO:AddInDatabase( Event ) --R2.1
self:F3( { Event } )
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end
--- (R2.1) Handles the Database to check on any event that Object exists in the Database.
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
-- @param #SET_CARGO self
-- @param Core.Event#EVENTDATA Event
-- @return #string The name of the CARGO
-- @return #table The CARGO
function SET_CARGO:FindInDatabase( Event ) --R2.1
self:F3( { Event } )
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
end
--- (R2.1) Iterate the SET_CARGO and call an interator function for each CARGO, providing the CARGO and optional parameters.
-- @param #SET_CARGO self
-- @param #function IteratorFunction The function that will be called when there is an alive CARGO in the SET_CARGO. The function needs to accept a CARGO parameter.
-- @return #SET_CARGO self
function SET_CARGO:ForEachCargo( IteratorFunction, ... ) --R2.1
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.Set )
return self
end
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo#CARGO} from a @{Point#POINT_VEC2}.
-- @param #SET_CARGO self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Cargo#CARGO}.
-- @return Wrapper.Cargo#CARGO The closest @{Cargo#CARGO}.
function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 ) --R2.1
self:F2( PointVec2 )
local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 )
return NearestCargo
end
--- (R2.1)
-- @param #SET_CARGO self
-- @param AI.AI_Cargo#AI_CARGO MCargo
-- @return #SET_CARGO self
function SET_CARGO:IsIncludeObject( MCargo ) --R2.1
self:F2( MCargo )
local MCargoInclude = true
if MCargo then
local MCargoName = MCargo:GetName()
if self.Filter.Coalitions then
local MCargoCoalition = false
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
local CargoCoalitionID = MCargo:GetCoalition()
self:T3( { "Coalition:", CargoCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == CargoCoalitionID then
MCargoCoalition = true
end
end
self:T( { "Evaluated Coalition", MCargoCoalition } )
MCargoInclude = MCargoInclude and MCargoCoalition
end
if self.Filter.Types then
local MCargoType = false
for TypeID, TypeName in pairs( self.Filter.Types ) do
self:T3( { "Type:", MCargo:GetType(), TypeName } )
if TypeName == MCargo:GetType() then
MCargoType = true
end
end
self:T( { "Evaluated Type", MCargoType } )
MCargoInclude = MCargoInclude and MCargoType
end
if self.Filter.CargoPrefixes then
local MCargoPrefix = false
for CargoPrefixId, CargoPrefix in pairs( self.Filter.CargoPrefixes ) do
self:T3( { "Prefix:", string.find( MCargo.Name, CargoPrefix, 1 ), CargoPrefix } )
if string.find( MCargo.Name, CargoPrefix, 1 ) then
MCargoPrefix = true
end
end
self:T( { "Evaluated Prefix", MCargoPrefix } )
MCargoInclude = MCargoInclude and MCargoPrefix
end
end
self:T2( MCargoInclude )
return MCargoInclude
end
--- (R2.1) Handles the OnEventNewCargo event for the Set.
-- @param #SET_CARGO self
-- @param Core.Event#EVENTDATA EventData
function SET_CARGO:OnEventNewCargo( EventData ) --R2.1
if EventData.Cargo then
if EventData.Cargo and self:IsIncludeObject( EventData.Cargo ) then
self:Add( EventData.Cargo.Name , EventData.Cargo )
end
end
end
--- (R2.1) Handles the OnDead or OnCrash event for alive units set.
-- @param #SET_CARGO self
-- @param Core.Event#EVENTDATA EventData
function SET_CARGO:OnEventDeleteCargo( EventData ) --R2.1
self:F3( { EventData } )
if EventData.Cargo then
local Cargo = _DATABASE:FindCargo( EventData.Cargo.Name )
if Cargo and Cargo.Name then
self:Remove( Cargo.Name )
end
end
end

View File

@ -0,0 +1,177 @@
--- (R2.1) **Core** -- Spawn dynamically new STATICs in your missions.
--
-- ![Banner Image](..\Presentations\SPAWNSTATIC\Dia1.JPG)
--
-- ====
--
-- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation.
--
-- ====
--
-- # Demo Missions
--
-- ### [SPAWNSTATIC Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPS - Spawning Statics)
--
-- ### [SPAWNSTATIC Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPS%20-%20Spawning%20Statics)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [SPAWNSTATIC YouTube Channel]()
--
-- ====
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- ### Authors:
--
-- * **FlightControl**: Design & Programming
--
-- @module SpawnStatic
--- @type SPAWNSTATIC
-- @extends Core.Base#BASE
--- # SPAWNSTATIC class, extends @{Base#BASE}
--
-- The SPAWNSTATIC class allows to spawn dynamically new @{Static}s.
-- 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 @{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 @{Static}s will follow a naming convention at run-time:
--
-- * Spawned @{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 construction methods
--
-- Create a new SPAWNSTATIC object with the @{#SPAWNSTATIC.NewFromStatic}():
--
-- * @{#SPAWNSTATIC.NewFromStatic}(): Creates a new SPAWNSTATIC object given a name that is used as the base of the naming of each spawned Static.
--
-- ## **Spawn** methods
--
-- Groups can be spawned at different times and methods:
--
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(): Spawn a new group from a POINT_VEC2 coordinate.
-- (The group will be spawned at land height ).
-- * @{#SPAWNSTATIC.SpawnFromZone}(): Spawn a new group in a @{Zone}.
--
-- @field #SPAWNSTATIC SPAWNSTATIC
--
SPAWNSTATIC = {
ClassName = "SPAWNSTATIC",
}
--- @type SPAWNSTATIC.SpawnZoneTable
-- @list <Core.Zone#ZONE_BASE> SpawnZone
--- Creates the main object to spawn a @{Static} defined in the ME.
-- @param #SPAWNSTATIC self
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID ) --R2.1
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
self:F( { SpawnTemplatePrefix } )
local TemplateStatic = StaticObject.getByName( SpawnTemplatePrefix )
if TemplateStatic then
self.SpawnTemplatePrefix = SpawnTemplatePrefix
self.CountryID = CountryID
self.SpawnIndex = 0
else
error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
end
self:SetEventPriority( 5 )
return self
end
--- Creates the main object to spawn a @{Static} based on a type name.
-- @param #SPAWNSTATIC self
-- @param #string SpawnTypeName is the name of the type.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, CountryID ) --R2.1
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
self:F( { SpawnTypeName } )
self.SpawnTypeName = SpawnTypeName
self.CountryID = CountryID
self.SpawnIndex = 0
self:SetEventPriority( 5 )
return self
end
--- Creates a new @{Static} from a POINT_VEC2.
-- @param #SPAWNSTATIC self
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @param #string (optional) The name of the new static.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
self:F( { PointVec2, Heading, NewName } )
local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID]
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
StaticTemplate.x = PointVec2:GetLat()
StaticTemplate.y = PointVec2:GetLon()
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
StaticTemplate.heading = ( Heading / 180 ) * math.pi
StaticTemplate.CountryID = nil
StaticTemplate.CoalitionID = nil
StaticTemplate.CategoryID = nil
local Static = coalition.addStaticObject( self.CountryID, StaticTemplate )
self.SpawnIndex = self.SpawnIndex + 1
return Static
end
--- Creates a new @{Static} from a @{Zone}.
-- @param #SPAWNSTATIC self
-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @param #string (optional) The name of the new static.
-- @return #SPAWNSTATIC
function SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName ) --R2.1
self:F( { Zone, Heading, NewName } )
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
return Static
end

View File

@ -0,0 +1,295 @@
--- **Core 2.1** -- Management of SPOT logistics, that can be transported from and to transportation carriers.
--
-- ![Banner Image](..\Presentations\SPOT\Dia1.JPG)
--
-- ===
--
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
--
-- * Spot for a defined duration.
-- * wiggle the spot at the target.
-- * Provide a @{Unit} as a target, instead of a point.
-- * Implement a status machine, LaseOn, LaseOff.
--
-- ====
--
-- # Demo Missions
--
-- ### [SPOT Demo Missions source code]()
--
-- ### [SPOT Demo Missions, only for beta testers]()
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [SPOT YouTube Channel]()
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script.
-- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing
-- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing
--
--
-- ### Authors:
--
-- * **FlightControl**: Design & Programming
--
-- @module Spot
do
--- @type SPOT
-- @extends Core.Fsm#FSM
--- # SPOT class, extends @{Fsm#FSM}
--
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
--
-- * Mark targets for a defined duration.
-- * wiggle the spot at the target.
-- * Provide a @{Unit} as a target, instead of a point.
-- * Implement a status machine, LaseOn, LaseOff.
--
-- ## 1. SPOT constructor
--
-- * @{#SPOT.New}(..\Presentations\SPOT\Dia2.JPG): Creates a new SPOT object.
--
-- ## 2. SPOT is a FSM
--
-- ![Process]()
--
-- ### 2.1 SPOT States
--
-- * **Off**: Lasing is switched off.
-- * **On**: Lasing is switched on.
-- * **Destroyed**: Target is destroyed.
--
-- ### 2.2 SPOT Events
--
-- * **@{#SPOT.LaseOn}(Target, LaserCode, Duration)**: Lase to a target.
-- * **@{#SPOT.LaseOff}()**: Stop lasing the target.
-- * **@{#SPOT.Lasing}()**: Target is being lased.
-- * **@{#SPOT.Destroyed}()**: Triggered when target is destroyed.
--
-- ## 3. Check if a Target is being lased
--
-- The method @{#SPOT.IsLasing}() indicates whether lasing is on or off.
--
-- @field #SPOT
SPOT = {
ClassName = "SPOT",
}
--- SPOT Constructor.
-- @param #SPOT self
-- @param Wrapper.Unit#UNIT Recce
-- @param #number LaserCode
-- @param #number Duration
-- @return #SPOT
function SPOT:New( Recce )
local self = BASE:Inherit( self, FSM:New() ) -- #SPOT
self:F( {} )
self:SetStartState( "Off" )
self:AddTransition( "Off", "LaseOn", "On" )
--- LaseOn Handler OnBefore for SPOT
-- @function [parent=#SPOT] OnBeforeLaseOn
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- LaseOn Handler OnAfter for SPOT
-- @function [parent=#SPOT] OnAfterLaseOn
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
--- LaseOn Trigger for SPOT
-- @function [parent=#SPOT] LaseOn
-- @param #SPOT self
--- LaseOn Asynchronous Trigger for SPOT
-- @function [parent=#SPOT] __LaseOn
-- @param #SPOT self
-- @param #number Delay
self:AddTransition( "On", "Lasing", "On" )
self:AddTransition( { "On", "Destroyed" } , "LaseOff", "Off" )
--- LaseOff Handler OnBefore for SPOT
-- @function [parent=#SPOT] OnBeforeLaseOff
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- LaseOff Handler OnAfter for SPOT
-- @function [parent=#SPOT] OnAfterLaseOff
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
--- LaseOff Trigger for SPOT
-- @function [parent=#SPOT] LaseOff
-- @param #SPOT self
--- LaseOff Asynchronous Trigger for SPOT
-- @function [parent=#SPOT] __LaseOff
-- @param #SPOT self
-- @param #number Delay
self:AddTransition( "*" , "Destroyed", "Destroyed" )
--- Destroyed Handler OnBefore for SPOT
-- @function [parent=#SPOT] OnBeforeDestroyed
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Destroyed Handler OnAfter for SPOT
-- @function [parent=#SPOT] OnAfterDestroyed
-- @param #SPOT self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Destroyed Trigger for SPOT
-- @function [parent=#SPOT] Destroyed
-- @param #SPOT self
--- Destroyed Asynchronous Trigger for SPOT
-- @function [parent=#SPOT] __Destroyed
-- @param #SPOT self
-- @param #number Delay
self.Recce = Recce
self.LaseScheduler = SCHEDULER:New( self )
self:SetEventPriority( 5 )
self.Lasing = false
return self
end
--- @param #SPOT self
-- @param From
-- @param Event
-- @param To
-- @param Wrapper.Positionable#POSITIONABLE Target
-- @param #number LaserCode
-- @param #number Duration
function SPOT:onafterLaseOn( From, Event, To, Target, LaserCode, Duration )
self:E( { "LaseOn", Target, LaserCode, Duration } )
local function StopLase( self )
self:LaseOff()
end
self.Target = Target
self.LaserCode = LaserCode
self.Lasing = true
local RecceDcsUnit = self.Recce:GetDCSObject()
self.SpotIR = Spot.createInfraRed( RecceDcsUnit, { x = 0, y = 2, z = 0 }, Target:GetPointVec3():AddY(1):GetVec3() )
self.SpotLaser = Spot.createLaser( RecceDcsUnit, { x = 0, y = 2, z = 0 }, Target:GetPointVec3():AddY(1):GetVec3(), LaserCode )
if Duration then
self.ScheduleID = self.LaseScheduler:Schedule( self, StopLase, {self}, Duration )
end
self:HandleEvent( EVENTS.Dead )
self:__Lasing( -0.2 )
end
--- @param #SPOT self
-- @param Core.Event#EVENTDATA EventData
function SPOT:OnEventDead(EventData)
self:E( { Dead = EventData.IniDCSUnitName, Target = self.Target } )
if self.Target then
if EventData.IniDCSUnitName == self.Target:GetName() then
self:E( {"Target dead ", self.Target:GetName() } )
self:Destroyed()
self:LaseOff()
end
end
end
--- @param #SPOT self
-- @param From
-- @param Event
-- @param To
function SPOT:onafterLasing( From, Event, To )
if self.Target:IsAlive() then
self.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/100):AddX(math.random(-100,100)/100):GetVec3() )
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
self:__Lasing( -0.2 )
else
self:E( { "Target is not alive", self.Target:IsAlive() } )
end
end
--- @param #SPOT self
-- @param From
-- @param Event
-- @param To
-- @return #SPOT
function SPOT:onafterLaseOff( From, Event, To )
self:E( {"Stopped lasing for ", self.Target:GetName() , SpotIR = self.SportIR, SpotLaser = self.SpotLaser } )
self.Lasing = false
self.SpotIR:destroy()
self.SpotLaser:destroy()
self.SpotIR = nil
self.SpotLaser = nil
if self.ScheduleID then
self.LaseScheduler:Stop(self.ScheduleID)
end
self.ScheduleID = nil
self.Target = nil
return self
end
--- Check if the SPOT is lasing
-- @param #SPOT self
-- @return #boolean true if it is lasing
function SPOT:IsLasing()
return self.Lasing
end
end

View File

@ -66,48 +66,53 @@
-- @module Zone
--- The ZONE_BASE class
-- @type ZONE_BASE
--- @type ZONE_BASE
-- @field #string ZoneName Name of the zone.
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
-- @extends Core.Base#BASE
--- # 1) ZONE_BASE class, extends @{Base#BASE}
--- # ZONE_BASE class, extends @{Base#BASE}
--
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
-- ## 1.1) Each zone has a name:
-- ## Each zone has a name:
--
-- * @{#ZONE_BASE.GetName}(): Returns the name of the zone.
--
-- ## 1.2) Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
--
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a Vec2 is within the zone.
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a Vec3 is within the zone.
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone.
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone.
-- * @{#ZONE_BASE.IsPointVec2InZone}(): Returns if a 2D point vector is within the zone.
-- * @{#ZONE_BASE.IsPointVec3InZone}(): Returns if a 3D point vector is within the zone.
--
-- ## 1.3) A zone has a probability factor that can be set to randomize a selection between zones:
-- ## A zone has a probability factor that can be set to randomize a selection between zones:
--
-- * @{#ZONE_BASE.SetRandomizeProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.GetRandomizeProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.SetZoneProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.GetZoneProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% )
-- * @{#ZONE_BASE.GetZoneMaybe}(): Get the zone taking into account the randomization probability. nil is returned if this zone is not a candidate.
--
-- ## 1.4) A zone manages Vectors:
-- ## A zone manages vectors:
--
-- * @{#ZONE_BASE.GetVec2}(): Returns the @{DCSTypes#Vec2} coordinate of the zone.
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random @{DCSTypes#Vec2} within the zone.
-- * @{#ZONE_BASE.GetVec2}(): Returns the 2D vector coordinate of the zone.
-- * @{#ZONE_BASE.GetVec3}(): Returns the 3D vector coordinate of the zone.
-- * @{#ZONE_BASE.GetPointVec2}(): Returns the 2D point vector coordinate of the zone.
-- * @{#ZONE_BASE.GetPointVec3}(): Returns the 3D point vector coordinate of the zone.
-- * @{#ZONE_BASE.GetRandomVec2}(): Define a random 2D vector within the zone.
-- * @{#ZONE_BASE.GetRandomPointVec2}(): Define a random 2D point vector within the zone.
-- * @{#ZONE_BASE.GetRandomPointVec3}(): Define a random 3D point vector within the zone.
--
-- ## 1.5) A zone has a bounding square:
-- ## A zone has a bounding square:
--
-- * @{#ZONE_BASE.GetBoundingSquare}(): Get the outer most bounding square of the zone.
--
-- ## 1.6) A zone can be marked:
-- ## A zone can be marked:
--
-- * @{#ZONE_BASE.SmokeZone}(): Smokes the zone boundaries in a color.
-- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color.
--
-- ===
-- @field #ZONE_BASE ZONE_BASE
-- @field #ZONE_BASE
ZONE_BASE = {
ClassName = "ZONE_BASE",
ZoneName = "",
@ -144,20 +149,21 @@ function ZONE_BASE:GetName()
return self.ZoneName
end
--- Returns if a location is within the zone.
--- Returns if a Vec2 is within the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone.
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 to test.
-- @return #boolean true if the Vec2 is within the zone.
function ZONE_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 )
return false
end
--- Returns if a point is within the zone.
--- Returns if a Vec3 is within the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone.
-- @return #boolean true if the Vec3 is within the zone.
function ZONE_BASE:IsVec3InZone( Vec3 )
self:F2( Vec3 )
@ -166,6 +172,31 @@ function ZONE_BASE:IsVec3InZone( Vec3 )
return InZone
end
--- Returns if a PointVec2 is within the zone.
-- @param #ZONE_BASE self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test.
-- @return #boolean true if the PointVec2 is within the zone.
function ZONE_BASE:IsPointVec2InZone( PointVec2 )
self:F2( PointVec2 )
local InZone = self:IsVec2InZone( PointVec2:GetVec2() )
return InZone
end
--- Returns if a PointVec3 is within the zone.
-- @param #ZONE_BASE self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test.
-- @return #boolean true if the PointVec3 is within the zone.
function ZONE_BASE:IsPointVec3InZone( PointVec3 )
self:F2( PointVec3 )
local InZone = self:IsPointVec2InZone( PointVec3 )
return InZone
end
--- Returns the @{DCSTypes#Vec2} coordinate of the zone.
-- @param #ZONE_BASE self
-- @return #nil.
@ -192,6 +223,23 @@ function ZONE_BASE:GetPointVec2()
end
--- Returns a @{Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#COORDINATE The Coordinate of the zone.
function ZONE_BASE:GetCoordinate()
self:F2( self.ZoneName )
local Vec2 = self:GetVec2()
local Coordinate = COORDINATE:NewFromVec2( Vec2 )
self:T2( { Coordinate } )
return Coordinate
end
--- Returns the @{DCSTypes#Vec3} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
@ -226,6 +274,22 @@ function ZONE_BASE:GetPointVec3( Height )
return PointVec3
end
--- Returns a @{Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#COORDINATE The Coordinate of the zone.
function ZONE_BASE:GetCoordinate( Height ) --R2.1
self:F2( self.ZoneName )
local Vec3 = self:GetVec3( Height )
local PointVec3 = COORDINATE:NewFromVec3( Vec3 )
self:T2( { PointVec3 } )
return PointVec3
end
--- Define a random @{DCSTypes#Vec2} within the zone.
-- @param #ZONE_BASE self
@ -310,29 +374,29 @@ end
-- @type ZONE_RADIUS
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone.
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone.
-- @extends Core.Zone#ZONE_BASE
-- @extends #ZONE_BASE
--- # 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE}
--- # ZONE_RADIUS class, extends @{Zone#ZONE_BASE}
--
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
-- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties.
--
-- ## 2.1) @{Zone#ZONE_RADIUS} constructor
-- ## ZONE_RADIUS constructor
--
-- * @{#ZONE_RADIUS.New}(): Constructor.
--
-- ## 2.2) Manage the radius of the zone
-- ## Manage the radius of the zone
--
-- * @{#ZONE_RADIUS.SetRadius}(): Sets the radius of the zone.
-- * @{#ZONE_RADIUS.GetRadius}(): Returns the radius of the zone.
--
-- ## 2.3) Manage the location of the zone
-- ## Manage the location of the zone
--
-- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCSTypes#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCSTypes#Vec2} of the zone.
-- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCSTypes#Vec3} of the zone, taking an additional height parameter.
--
-- ## 2.4) Zone point randomization
-- ## Zone point randomization
--
-- Various functions exist to find random points within the zone.
--
@ -340,10 +404,7 @@ end
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
--
-- ===
--
-- @field #ZONE_RADIUS ZONE_RADIUS
--
-- @field #ZONE_RADIUS
ZONE_RADIUS = {
ClassName="ZONE_RADIUS",
}
@ -615,19 +676,16 @@ end
-- @type ZONE
-- @extends Core.Zone#ZONE_RADIUS
--- @type ZONE
-- @extends #ZONE_RADIUS
--- # 3) ZONE class, extends @{Zone#ZONE_RADIUS}
--- # ZONE class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- @field #ZONE ZONE
--
-- @field #ZONE
ZONE = {
ClassName="ZONE",
}
@ -655,20 +713,16 @@ function ZONE:New( ZoneName )
end
--- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
-- @type ZONE_UNIT
--- @type ZONE_UNIT
-- @field Wrapper.Unit#UNIT ZoneUNIT
-- @extends Core.Zone#ZONE_RADIUS
--- # 4) #ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
--- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- @field #ZONE_UNIT ZONE_UNIT
--
-- @field #ZONE_UNIT
ZONE_UNIT = {
ClassName="ZONE_UNIT",
}
@ -694,7 +748,7 @@ end
-- @param #ZONE_UNIT self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location.
function ZONE_UNIT:GetVec2()
self:F( self.ZoneName )
self:F2( self.ZoneName )
local ZoneVec2 = self.ZoneUNIT:GetVec2()
if ZoneVec2 then
@ -704,7 +758,7 @@ function ZONE_UNIT:GetVec2()
return self.LastVec2
end
self:T( { ZoneVec2 } )
self:T2( { ZoneVec2 } )
return nil
end
@ -750,19 +804,15 @@ function ZONE_UNIT:GetVec3( Height )
end
--- @type ZONE_GROUP
-- @field Wrapper.Group#GROUP ZoneGROUP
-- @extends Core.Zone#ZONE_RADIUS
-- @extends #ZONE_RADIUS
--- # 5) #ZONE_GROUP class, extends @{Zone#ZONE_RADIUS}
--- # ZONE_GROUP class, extends @{Zone#ZONE_RADIUS}
--
-- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- @field #ZONE_GROUP ZONE_GROUP
--
-- @field #ZONE_GROUP
ZONE_GROUP = {
ClassName="ZONE_GROUP",
}
@ -777,7 +827,7 @@ function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) )
self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } )
self.ZoneGROUP = ZoneGROUP
self._.ZoneGROUP = ZoneGROUP
return self
end
@ -789,7 +839,7 @@ end
function ZONE_GROUP:GetVec2()
self:F( self.ZoneName )
local ZoneVec2 = self.ZoneGROUP:GetVec2()
local ZoneVec2 = self._.ZoneGROUP:GetVec2()
self:T( { ZoneVec2 } )
@ -803,7 +853,7 @@ function ZONE_GROUP:GetRandomVec2()
self:F( self.ZoneName )
local Point = {}
local Vec2 = self.ZoneGROUP:GetVec2()
local Vec2 = self._.ZoneGROUP:GetVec2()
local angle = math.random() * math.pi*2;
Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
@ -817,17 +867,17 @@ end
--- @type ZONE_POLYGON_BASE
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
-- @extends Core.Zone#ZONE_BASE
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
-- @extends #ZONE_BASE
--- # 6) ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE}
--- # ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE}
--
-- The ZONE_POLYGON_BASE class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
--
-- ## 6.1) Zone point randomization
-- ## Zone point randomization
--
-- Various functions exist to find random points within the zone.
--
@ -835,10 +885,7 @@ end
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
--
-- ===
--
-- @field #ZONE_POLYGON_BASE ZONE_POLYGON_BASE
--
-- @field #ZONE_POLYGON_BASE
ZONE_POLYGON_BASE = {
ClassName="ZONE_POLYGON_BASE",
}
@ -859,24 +906,35 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
local i = 0
self.Polygon = {}
self._.Polygon = {}
for i = 1, #PointsArray do
self.Polygon[i] = {}
self.Polygon[i].x = PointsArray[i].x
self.Polygon[i].y = PointsArray[i].y
self._.Polygon[i] = {}
self._.Polygon[i].x = PointsArray[i].x
self._.Polygon[i].y = PointsArray[i].y
end
return self
end
--- Returns the center location of the polygon.
-- @param #ZONE_GROUP self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location.
function ZONE_POLYGON_BASE:GetVec2()
self:F( self.ZoneName )
local Bounds = self:GetBoundingSquare()
return { x = ( Bounds.x2 + Bounds.x1 ) / 2, y = ( Bounds.y2 + Bounds.y1 ) / 2 }
end
--- Flush polygon coordinates as a table in DCS.log.
-- @param #ZONE_POLYGON_BASE self
-- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:Flush()
self:F2()
self:E( { Polygon = self.ZoneName, Coordinates = self.Polygon } )
self:E( { Polygon = self.ZoneName, Coordinates = self._.Polygon } )
return self
end
@ -892,17 +950,17 @@ function ZONE_POLYGON_BASE:BoundZone( UnBound )
local Segments = 10
i = 1
j = #self.Polygon
j = #self._.Polygon
while i <= #self.Polygon do
self:T( { i, j, self.Polygon[i], self.Polygon[j] } )
while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
local DeltaX = self.Polygon[j].x - self.Polygon[i].x
local DeltaY = self.Polygon[j].y - self.Polygon[i].y
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments )
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
local Tire = {
["country"] = "USA",
["category"] = "Fortifications",
@ -942,17 +1000,17 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor )
local Segments = 10
i = 1
j = #self.Polygon
j = #self._.Polygon
while i <= #self.Polygon do
self:T( { i, j, self.Polygon[i], self.Polygon[j] } )
while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
local DeltaX = self.Polygon[j].x - self.Polygon[i].x
local DeltaY = self.Polygon[j].y - self.Polygon[i].y
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments )
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor )
end
j = i
@ -978,12 +1036,12 @@ function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
local InPolygon = false
Next = 1
Prev = #self.Polygon
Prev = #self._.Polygon
while Next <= #self.Polygon do
self:T( { Next, Prev, self.Polygon[Next], self.Polygon[Prev] } )
if ( ( ( self.Polygon[Next].y > Vec2.y ) ~= ( self.Polygon[Prev].y > Vec2.y ) ) and
( Vec2.x < ( self.Polygon[Prev].x - self.Polygon[Next].x ) * ( Vec2.y - self.Polygon[Next].y ) / ( self.Polygon[Prev].y - self.Polygon[Next].y ) + self.Polygon[Next].x )
while Next <= #self._.Polygon do
self:T( { Next, Prev, self._.Polygon[Next], self._.Polygon[Prev] } )
if ( ( ( self._.Polygon[Next].y > Vec2.y ) ~= ( self._.Polygon[Prev].y > Vec2.y ) ) and
( Vec2.x < ( self._.Polygon[Prev].x - self._.Polygon[Next].x ) * ( Vec2.y - self._.Polygon[Next].y ) / ( self._.Polygon[Prev].y - self._.Polygon[Next].y ) + self._.Polygon[Next].x )
) then
InPolygon = not InPolygon
end
@ -1054,17 +1112,17 @@ end
-- @return #ZONE_POLYGON_BASE.BoundingSquare The bounding square.
function ZONE_POLYGON_BASE:GetBoundingSquare()
local x1 = self.Polygon[1].x
local y1 = self.Polygon[1].y
local x2 = self.Polygon[1].x
local y2 = self.Polygon[1].y
local x1 = self._.Polygon[1].x
local y1 = self._.Polygon[1].y
local x2 = self._.Polygon[1].x
local y2 = self._.Polygon[1].y
for i = 2, #self.Polygon do
self:T2( { self.Polygon[i], x1, y1, x2, y2 } )
x1 = ( x1 > self.Polygon[i].x ) and self.Polygon[i].x or x1
x2 = ( x2 < self.Polygon[i].x ) and self.Polygon[i].x or x2
y1 = ( y1 > self.Polygon[i].y ) and self.Polygon[i].y or y1
y2 = ( y2 < self.Polygon[i].y ) and self.Polygon[i].y or y2
for i = 2, #self._.Polygon do
self:T2( { self._.Polygon[i], x1, y1, x2, y2 } )
x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1
x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2
y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1
y2 = ( y2 < self._.Polygon[i].y ) and self._.Polygon[i].y or y2
end
@ -1073,18 +1131,15 @@ end
--- @type ZONE_POLYGON
-- @extends Core.Zone#ZONE_POLYGON_BASE
-- @extends #ZONE_POLYGON_BASE
--- # 7) ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE}
--- # ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE}
--
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
--
-- ===
--
-- @field #ZONE_POLYGON ZONE_POLYGON
--
-- @field #ZONE_POLYGON
ZONE_POLYGON = {
ClassName="ZONE_POLYGON",
}
@ -1100,7 +1155,7 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup )
local GroupPoints = ZoneGroup:GetTaskRoute()
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, GroupPoints ) )
self:F( { ZoneName, ZoneGroup, self.Polygon } )
self:F( { ZoneName, ZoneGroup, self._.Polygon } )
return self
end

View File

@ -0,0 +1,924 @@
--- **Funtional R2.1** -- Management of target **Designation**.
--
-- --![Banner Image](..\Presentations\DESIGNATE\Dia1.JPG)
--
-- ===
--
-- DESIGNATE is orchestrating the designation of potential targets executed by a Recce group,
-- and communicates these to a dedicated attacking group of players,
-- so that following a dynamically generated menu system,
-- each detected set of potential targets can be lased or smoked...
--
-- Targets can be:
--
-- * **Lased** for a period of time.
-- * **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.)
-- * **Illuminated** through an illumination bomb. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script.
-- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing
-- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing
--
--
-- ### Authors:
--
-- * **FlightControl**: Design & Programming
--
-- @module Designate
do -- DESIGNATE
--- @type DESIGNATE
-- @extends Core.Fsm#FSM_PROCESS
--- # DESIGNATE class, extends @{Fsm#FSM}
--
-- DESIGNATE is orchestrating the designation of potential targets executed by a Recce group,
-- and communicates these to a dedicated attacking group of players,
-- so that following a dynamically generated menu system,
-- each detected set of potential targets can be lased or smoked...
--
-- Targets can be:
--
-- * **Lased** for a period of time.
-- * **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.)
-- * **Illuminated** through an illumination bomb. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.
--
-- The following terminology is being used throughout this document:
--
-- * The **DesignateObject** is the object of the DESIGNATE class, which is this class explained in the document.
-- * The **DetectionObject** is the object of a DETECTION_ class (DETECTION_TYPES, DETECTION_AREAS, DETECTION_UNITS), which is executing the detection and grouping of Targets into _DetectionItems_.
-- * **DetectionItems** is the list of detected target groupings by the _DetectionObject_. Each _DetectionItem_ contains a _TargetSet_.
-- * **DetectionItem** is one element of the _DetectionItems_ list, and contains a _TargetSet_.
-- * The **TargetSet** is a SET_UNITS collection of _Targets_, that have been detected by the _DetectionObject_.
-- * A **Target** is a detected UNIT object by the _DetectionObject_.
-- * A **Threat Level** is a number from 0 to 10 that is calculated based on the threat of the Target in an Air to Ground battle scenario.
-- * The **RecceSet** is a SET_GROUP collection that contains the **RecceGroups**.
-- * A **RecceGroup** is a GROUP object containing the **Recces**.
-- * A **Recce** is a UNIT object executing the reconnaissance as part the _DetectionObject_. A Recce can be of any UNIT type.
-- * An **AttackGroup** is a GROUP object that contain _Players_.
-- * A **Player** is an active CLIENT object containing a human player.
-- * A **Designate Menu** is the menu that is dynamically created during the designation process for each _AttackGroup_.
--
-- The RecceSet is continuously detecting for potential Targets, executing its task as part of the DetectionObject.
-- Once Targets have been detected, the DesignateObject will trigger the **Detect Event**.
--
-- As part of the Detect Event, the DetectionItems list is used by the DesignateObject to provide the Players with:
--
-- * The RecceGroups are reporting to each AttackGroup, sending **Messages** containing the Threat Level and the TargetSet composition.
-- * **Menu options** are created and updated for each AttackGroup, containing the Threat Level and the TargetSet composition.
--
-- A Player can then select an action from the Designate Menu.
--
-- **Note that each selected action will be executed for a TargetSet, thus the Target grouping done by the DetectionObject.**
--
-- Each **Menu Option** in the Designate Menu has two modes:
--
-- 1. If the TargetSet **is not being designated**, then the **Designate Menu** option for the target Set will provide options to **Lase** or **Smoke** the targets.
-- 2. If the Target Set **is being designated**, then the **Designate Menu** option will provide an option to stop or cancel the designation.
--
-- While designating, the RecceGroups will report any change in TargetSet composition or Target presence.
--
-- The following logic is executed when a TargetSet is selected to be *lased* from the Designation Menu:
--
-- * The RecceSet is searched for any Recce that is within *designation distance* from a Target in the TargetSet that is currently not being designated.
-- * If there is a Recce found that is currently no designating a target, and is within designation distance from the Target, then that Target will be designated.
-- * During designation, any Recce that does not have Line of Sight (LOS) and is not within disignation distance from the Target, will stop designating the Target, and a report is given.
-- * When a Recce is designating a Target, and that Target is destroyed, then the Recce will stop designating the Target, and will report the event.
-- * When a Recce is designating a Target, and that Recce is destroyed, then the Recce will be removed from the RecceSet and designation will stop without reporting.
-- * When all RecceGroups are destroyed from the RecceSet, then the DesignationObject will stop functioning, and nothing will be reported.
--
-- In this way, the DesignationObject assists players to designate ground targets for a coordinated attack!
--
-- Have FUN!
--
-- ## 1. DESIGNATE constructor
--
-- * @{#DESIGNATE.New}(): Creates a new DESIGNATE object.
--
-- ## 2. DESIGNATE is a FSM
--
-- ![Process](..\Presentations\DESIGNATE\Dia2.JPG)
--
-- ### 2.1 DESIGNATE States
--
-- * **Designating** ( Group ): The process is not started yet.
--
-- ### 2.2 DESIGNATE Events
--
-- * **@{#DESIGNATE.Detect}**: Detect targets.
-- * **@{#DESIGNATE.LaseOn}**: Lase the targets with the specified Index.
-- * **@{#DESIGNATE.LaseOff}**: Stop lasing the targets with the specified Index.
-- * **@{#DESIGNATE.Smoke}**: Smoke the targets with the specified Index.
-- * **@{#DESIGNATE.Status}**: Report designation status.
--
-- ## 3. Laser codes
--
-- ### 3.1 Set possible laser codes
--
-- An array of laser codes can be provided, that will be used by the DESIGNATE when lasing.
-- The laser code is communicated by the Recce when it is lasing a larget.
-- Note that the default laser code is 1113.
-- Working known laser codes are: 1113,1462,1483,1537,1362,1214,1131,1182,1644,1614,1515,1411,1621,1138,1542,1678,1573,1314,1643,1257,1467,1375,1341,1275,1237
--
-- Use the method @{#DESIGNATE.SetLaserCodes}() to set the possible laser codes to be selected from.
-- One laser code can be given or an sequence of laser codes through an table...
--
-- Designate:SetLaserCodes( 1214 )
--
-- The above sets one laser code with the value 1214.
--
-- Designate:SetLaserCodes( { 1214, 1131, 1614, 1138 } )
--
-- The above sets a collection of possible laser codes that can be assigned. **Note the { } notation!**
--
-- ### 3.2 Auto generate laser codes
--
-- Use the method @{#DESIGNATE.GenerateLaserCodes}() to generate all possible laser codes. Logic implemented and advised by Ciribob!
--
-- ## 4. Autolase to automatically lase detected targets.
--
-- DetectionItems can be auto lased once detected by Recces. As such, there is almost no action required from the Players using the Designate Menu.
-- The **auto lase** function can be activated through the Designation Menu.
-- Use the method @{#DESIGNATE.SetAutoLase}() to activate or deactivate the auto lase function programmatically.
-- Note that autolase will automatically activate lasing for ALL DetectedItems. Individual items can be switched-off if required using the Designation Menu.
--
-- Designate:SetAutoLase( true )
--
-- Activate the auto lasing.
--
-- ## 5. Target prioritization on threat level
--
-- Targets can be detected of different types in one DetectionItem. Depending on the type of the Target, a different threat level applies in an Air to Ground combat context.
-- SAMs are of a higher threat than normal tanks. So, if the Target type was recognized, the Recces will select those targets that form the biggest threat first,
-- and will continue this until the remaining vehicles with the lowest threat have been reached.
--
-- This threat level prioritization can be activated using the method @{#DESIGNATE.SetThreatLevelPrioritization}().
-- If not activated, Targets will be selected in a random order, but most like those first which are the closest to the Recce marking the Target.
--
-- Designate:SetThreatLevelPrioritization( true )
--
-- The example will activate the threat level prioritization for this the Designate object. Threats will be marked based on the threat level of the Target.
--
-- ## 6. Status Report
--
-- A status report is available that displays the current Targets detected, grouped per DetectionItem, and a list of which Targets are currently being marked.
--
-- * The status report can be shown by selecting "Status" -> "Report Status" from the Designation menu .
-- * The status report can be automatically flashed by selecting "Status" -> "Flash Status On".
-- * The automatic flashing of the status report can be deactivated by selecting "Status" -> "Flash Status Off".
-- * The flashing of the status menu is disabled by default.
-- * The method @{#DESIGNATE.FlashStatusMenu}() can be used to enable or disable to flashing of the status menu.
--
-- Designate:FlashStatusMenu( true )
--
-- The example will activate the flashing of the status menu for this Designate object.
--
-- @field #DESIGNATE
--
DESIGNATE = {
ClassName = "DESIGNATE",
}
--- DESIGNATE Constructor. This class is an abstract class and should not be instantiated.
-- @param #DESIGNATE self
-- @param Tasking.CommandCenter#COMMANDCENTER CC
-- @param Functional.Detection#DETECTION_BASE Detection
-- @param Core.Set#SET_GROUP AttackSet The Attack collection of GROUP objects to designate and report for.
-- @return #DESIGNATE
function DESIGNATE:New( CC, Detection, AttackSet )
local self = BASE:Inherit( self, FSM:New() ) -- #DESIGNATE
self:F( { Detection } )
self:SetStartState( "Designating" )
self:AddTransition( "*", "Detect", "*" )
--- Detect Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE] OnBeforeDetect
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Detect Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE] OnAfterDetect
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Detect Trigger for DESIGNATE
-- @function [parent=#DESIGNATE] Detect
-- @param #DESIGNATE self
--- Detect Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE] __Detect
-- @param #DESIGNATE self
-- @param #number Delay
self:AddTransition( "*", "LaseOn", "Lasing" )
--- LaseOn Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE ] OnBeforeLaseOn
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- LaseOn Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE ] OnAfterLaseOn
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- LaseOn Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] LaseOn
-- @param #DESIGNATE self
--- LaseOn Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] __LaseOn
-- @param #DESIGNATE self
-- @param #number Delay
self:AddTransition( "Lasing", "Lasing", "Lasing" )
self:AddTransition( "*", "LaseOff", "Designate" )
--- LaseOff Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE ] OnBeforeLaseOff
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- LaseOff Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE ] OnAfterLaseOff
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- LaseOff Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] LaseOff
-- @param #DESIGNATE self
--- LaseOff Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] __LaseOff
-- @param #DESIGNATE self
-- @param #number Delay
self:AddTransition( "*", "Smoke", "*" )
--- Smoke Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE ] OnBeforeSmoke
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Smoke Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE ] OnAfterSmoke
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Smoke Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] Smoke
-- @param #DESIGNATE self
--- Smoke Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] __Smoke
-- @param #DESIGNATE self
-- @param #number Delay
self:AddTransition( "*", "Illuminate", "*" )
--- Illuminate Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE] OnBeforeIlluminate
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Illuminate Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE] OnAfterIlluminate
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Illuminate Trigger for DESIGNATE
-- @function [parent=#DESIGNATE] Illuminate
-- @param #DESIGNATE self
--- Illuminate Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE] __Illuminate
-- @param #DESIGNATE self
-- @param #number Delay
self:AddTransition( "*", "Done", "*" )
self:AddTransition( "*", "Status", "*" )
--- Status Handler OnBefore for DESIGNATE
-- @function [parent=#DESIGNATE ] OnBeforeStatus
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @return #boolean
--- Status Handler OnAfter for DESIGNATE
-- @function [parent=#DESIGNATE ] OnAfterStatus
-- @param #DESIGNATE self
-- @param #string From
-- @param #string Event
-- @param #string To
--- Status Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] Status
-- @param #DESIGNATE self
--- Status Asynchronous Trigger for DESIGNATE
-- @function [parent=#DESIGNATE ] __Status
-- @param #DESIGNATE self
-- @param #number Delay
self.CC = CC
self.Detection = Detection
self.AttackSet = AttackSet
self.RecceSet = Detection:GetDetectionSetGroup()
self.Recces = {}
self.Designating = {}
self.LaseDuration = 60
self:SetFlashStatusMenu( false )
self:SetDesignateMenu()
self:SetLaserCodes( 1688 ) -- set self.LaserCodes
self:SetAutoLase( false ) -- set self.Autolase
self:SetThreatLevelPrioritization( false ) -- self.ThreatLevelPrioritization, default is threat level priorization off
self.LaserCodesUsed = {}
self.Detection:__Start( 2 )
return self
end
--- Set the flashing of the status menu.
-- @param #DESIGNATE self
-- @param #boolean FlashMenu true: the status menu will be flashed every detection run; false: no flashing of the menu.
-- @return #DESIGNATE
function DESIGNATE:SetFlashStatusMenu( FlashMenu ) --R2.1
self.FlashStatusMenu = {}
self.AttackSet:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupReport
function( AttackGroup )
self.FlashStatusMenu[AttackGroup] = FlashMenu
end
)
return self
end
--- Set an array of possible laser codes.
-- Each new lase will select a code from this table.
-- @param #DESIGNATE self
-- @param #list<#number> LaserCodes
-- @return #DESIGNATE
function DESIGNATE:SetLaserCodes( LaserCodes ) --R2.1
self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes }
self:E(self.LaserCodes)
self.LaserCodesUsed = {}
return self
end
--- Generate an array of possible laser codes.
-- Each new lase will select a code from this table.
-- The entered value can range from 1111 - 1788,
-- -- but the first digit of the series must be a 1 or 2
-- -- and the last three digits must be between 1 and 8.
-- The range used to be bugged so its not 1 - 8 but 0 - 7.
-- function below will use the range 1-7 just in case
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:GenerateLaserCodes() --R2.1
self.LaserCodes = {}
local function containsDigit(_number, _numberToFind)
local _thisNumber = _number
local _thisDigit = 0
while _thisNumber ~= 0 do
_thisDigit = _thisNumber % 10
_thisNumber = math.floor(_thisNumber / 10)
if _thisDigit == _numberToFind then
return true
end
end
return false
end
-- generate list of laser codes
local _code = 1111
local _count = 1
while _code < 1777 and _count < 30 do
while true do
_code = _code + 1
if not containsDigit(_code, 8)
and not containsDigit(_code, 9)
and not containsDigit(_code, 0) then
self:T(_code)
table.insert( self.LaserCodes, _code )
break
end
end
_count = _count + 1
end
self.LaserCodesUsed = {}
return self
end
--- Set auto lase.
-- Auto lase will start lasing targets immediately when these are in range.
-- @param #DESIGNATE self
-- @param #boolean AutoLase
-- @return #DESIGNATE
function DESIGNATE:SetAutoLase( AutoLase ) --R2.1
self.AutoLase = AutoLase
local AutoLaseOnOff = ( AutoLase == true ) and "On" or "Off"
local CC = self.CC:GetPositionable()
if CC then
CC:MessageToSetGroup( "Auto Lase " .. AutoLaseOnOff .. ".", 15, self.AttackSet )
end
self:ActivateAutoLase()
self:SetDesignateMenu()
return self
end
--- Set priorization of Targets based on the **Threat Level of the Target** in an Air to Ground context.
-- @param #DESIGNATE self
-- @param #boolean Prioritize
-- @return #DESIGNATE
function DESIGNATE:SetThreatLevelPrioritization( Prioritize ) --R2.1
self.ThreatLevelPrioritization = Prioritize
return self
end
---
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterDetect()
self:__Detect( -60 )
self:ActivateAutoLase()
self:SendStatus()
self:SetDesignateMenu()
return self
end
--- Sends the status to the Attack Groups.
-- @param #DESIGNATE self
-- @param Wrapper.Group#GROUP AttackGroup
-- @param #number Duration The time in seconds the report should be visible.
-- @return #DESIGNATE
function DESIGNATE:SendStatus( MenuAttackGroup, Duration )
Duration = Duration or 10
self.AttackSet:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupReport
function( AttackGroup )
if self.FlashStatusMenu[AttackGroup] or ( MenuAttackGroup and ( AttackGroup:GetName() == MenuAttackGroup:GetName() ) ) then
local DetectedReport = REPORT:New( "Targets designated:\n" )
local DetectedItems = self.Detection:GetDetectedItems()
for Index, DetectedItemData in pairs( DetectedItems ) do
local Report = self.Detection:DetectedItemReportSummary( Index )
DetectedReport:Add(" - " .. Report)
end
local CC = self.CC:GetPositionable()
CC:MessageToGroup( DetectedReport:Text( "\n" ), Duration, AttackGroup )
local DesignationReport = REPORT:New( "Targets marked:\n" )
self.RecceSet:ForEachGroup(
function( RecceGroup )
local RecceUnits = RecceGroup:GetUnits()
for UnitID, RecceData in pairs( RecceUnits ) do
local Recce = RecceData -- Wrapper.Unit#UNIT
if Recce:IsLasing() then
DesignationReport:Add( " - " .. Recce:GetMessageText( "Marking " .. Recce:GetSpot().Target:GetTypeName() .. " with laser " .. Recce:GetSpot().LaserCode .. "." ) )
end
end
end
)
CC:MessageToGroup( DesignationReport:Text(), Duration, AttackGroup )
end
end
)
return self
end
--- Coordinates the Auto Lase.
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:ActivateAutoLase()
self.AttackSet:Flush()
self.AttackSet:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupReport
function( AttackGroup )
local DetectedItems = self.Detection:GetDetectedItems()
for Index, DetectedItemData in pairs( DetectedItems ) do
if self.AutoLase then
if not self.Designating[Index] then
self:LaseOn( Index, self.LaseDuration )
end
end
end
end
)
return self
end
--- Sets the Designate Menu.
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:SetDesignateMenu()
self.AttackSet:Flush()
self.AttackSet:ForEachGroup(
--- @param Wrapper.Group#GROUP GroupReport
function( AttackGroup )
local DesignateMenu = AttackGroup:GetState( AttackGroup, "DesignateMenu" ) -- Core.Menu#MENU_GROUP
if DesignateMenu then
DesignateMenu:Remove()
DesignateMenu = nil
self:E("Remove Menu")
end
DesignateMenu = MENU_GROUP:New( AttackGroup, "Designate" )
self:E(DesignateMenu)
AttackGroup:SetState( AttackGroup, "DesignateMenu", DesignateMenu )
-- Set Menu option for auto lase
if self.AutoLase then
MENU_GROUP_COMMAND:New( AttackGroup, "Auto Lase Off", DesignateMenu, self.MenuAutoLase, self, false )
else
MENU_GROUP_COMMAND:New( AttackGroup, "Auto Lase On", DesignateMenu, self.MenuAutoLase, self, true )
end
local StatusMenu = MENU_GROUP:New( AttackGroup, "Status", DesignateMenu )
MENU_GROUP_COMMAND:New( AttackGroup, "Report Status 15s", StatusMenu, self.MenuStatus, self, AttackGroup, 15 )
MENU_GROUP_COMMAND:New( AttackGroup, "Report Status 30s", StatusMenu, self.MenuStatus, self, AttackGroup, 30 )
MENU_GROUP_COMMAND:New( AttackGroup, "Report Status 60s", StatusMenu, self.MenuStatus, self, AttackGroup, 60 )
if self.FlashStatusMenu[AttackGroup] then
MENU_GROUP_COMMAND:New( AttackGroup, "Flash Status Report Off", StatusMenu, self.MenuFlashStatus, self, AttackGroup, false )
else
MENU_GROUP_COMMAND:New( AttackGroup, "Flash Status Report On", StatusMenu, self.MenuFlashStatus, self, AttackGroup, true )
end
local DetectedItems = self.Detection:GetDetectedItems()
for Index, DetectedItemData in pairs( DetectedItems ) do
local Report = self.Detection:DetectedItemMenu( Index )
if not self.Designating[Index] then
local DetectedMenu = MENU_GROUP:New( AttackGroup, Report, DesignateMenu )
MENU_GROUP_COMMAND:New( AttackGroup, "Lase target 60 secs", DetectedMenu, self.MenuLaseOn, self, Index, 60 )
MENU_GROUP_COMMAND:New( AttackGroup, "Lase target 120 secs", DetectedMenu, self.MenuLaseOn, self, Index, 120 )
MENU_GROUP_COMMAND:New( AttackGroup, "Smoke red", DetectedMenu, self.MenuSmoke, self, Index, SMOKECOLOR.Red )
MENU_GROUP_COMMAND:New( AttackGroup, "Smoke blue", DetectedMenu, self.MenuSmoke, self, Index, SMOKECOLOR.Blue )
MENU_GROUP_COMMAND:New( AttackGroup, "Smoke green", DetectedMenu, self.MenuSmoke, self, Index, SMOKECOLOR.Green )
MENU_GROUP_COMMAND:New( AttackGroup, "Smoke white", DetectedMenu, self.MenuSmoke, self, Index, SMOKECOLOR.White )
MENU_GROUP_COMMAND:New( AttackGroup, "Smoke orange", DetectedMenu, self.MenuSmoke, self, Index, SMOKECOLOR.Orange )
MENU_GROUP_COMMAND:New( AttackGroup, "Illuminate", DetectedMenu, self.MenuIlluminate, self, Index )
else
if self.Designating[Index] == "Laser" then
Report = "Lasing " .. Report
elseif self.Designating[Index] == "Smoke" then
Report = "Smoking " .. Report
elseif self.Designating[Index] == "Illuminate" then
Report = "Illuminating " .. Report
end
local DetectedMenu = MENU_GROUP:New( AttackGroup, Report, DesignateMenu )
if self.Designating[Index] == "Laser" then
MENU_GROUP_COMMAND:New( AttackGroup, "Stop lasing", DetectedMenu, self.MenuLaseOff, self, Index )
else
end
end
end
end
)
return self
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuStatus( AttackGroup, Duration )
self:E("Status")
self:SendStatus( AttackGroup, Duration )
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuFlashStatus( AttackGroup, Flash )
self:E("Flash Status")
self.FlashStatusMenu[AttackGroup] = Flash
self:SetDesignateMenu()
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuAutoLase( AutoLase )
self:E("AutoLase")
self:SetAutoLase( AutoLase )
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuSmoke( Index, Color )
self:E("Designate through Smoke")
self.Designating[Index] = "Smoke"
self:__Smoke( 1, Index, Color )
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuIlluminate( Index )
self:E("Designate through Illumination")
self.Designating[Index] = "Illuminate"
self:__Illuminate( 1, Index )
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuLaseOn( Index, Duration )
self:E("Designate through Lase")
self:__LaseOn( 1, Index, Duration )
end
---
-- @param #DESIGNATE self
function DESIGNATE:MenuLaseOff( Index, Duration )
self:E("Lasing off")
self.Designating[Index] = nil
self:__LaseOff( 1, Index )
end
---
-- @param #DESIGNATE self
function DESIGNATE:onafterLaseOn( From, Event, To, Index, Duration )
self.Designating[Index] = "Laser"
self:Lasing( Index, Duration )
end
---
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterLasing( From, Event, To, Index, Duration )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
TargetSetUnit:Flush()
for TargetUnit, RecceData in pairs( self.Recces ) do
local Recce = RecceData -- Wrapper.Unit#UNIT
if not Recce:IsLasing() then
local LaserCode = Recce:GetLaserCode() --(Not deleted when stopping with lasing).
self.LaserCodesUsed[LaserCode] = nil
self.Recces[TargetUnit] = nil
end
end
TargetSetUnit:ForEachUnitPerThreatLevel( 10, 0,
--- @param Wrapper.Unit#UNIT SmokeUnit
function( TargetUnit )
self:E("In procedure")
if TargetUnit:IsAlive() then
local Recce = self.Recces[TargetUnit]
if not Recce then
for RecceGroupID, RecceGroup in pairs( self.RecceSet:GetSet() ) do
for UnitID, UnitData in pairs( RecceGroup:GetUnits() or {} ) do
local RecceUnit = UnitData -- Wrapper.Unit#UNIT
if RecceUnit:IsLasing() == false then
if RecceUnit:IsDetected( TargetUnit ) and RecceUnit:IsLOS( TargetUnit ) then
local LaserCodeIndex = math.random( 1, #self.LaserCodes )
local LaserCode = self.LaserCodes[LaserCodeIndex]
if not self.LaserCodesUsed[LaserCode] then
self.LaserCodesUsed[LaserCode] = LaserCodeIndex
local Spot = RecceUnit:LaseUnit( TargetUnit, LaserCode, Duration )
local AttackSet = self.AttackSet
function Spot:OnAfterDestroyed( From, Event, To )
self:E( "Destroyed Message" )
self.Recce:MessageToSetGroup( "Target " .. TargetUnit:GetTypeName() .. " destroyed. " .. TargetSetUnit:Count() .. " targets left.", 5, AttackSet )
end
self.Recces[TargetUnit] = RecceUnit
RecceUnit:MessageToSetGroup( "Marking " .. TargetUnit:GetTypeName() .. " with laser " .. RecceUnit:GetSpot().LaserCode .. " for " .. Duration .. "s.", 5, self.AttackSet )
break
end
else
RecceUnit:MessageToSetGroup( "Can't mark " .. TargetUnit:GetTypeName(), 5, self.AttackSet )
end
else
-- The Recce is lasing, but the Target is not detected or within LOS. So stop lasing and send a report.
if not RecceUnit:IsDetected( TargetUnit ) or not RecceUnit:IsLOS( TargetUnit ) then
local Recce = self.Recces[TargetUnit] -- Wrapper.Unit#UNIT
if Recce then
Recce:LaseOff()
Recce:MessageToGroup( "Target " .. TargetUnit:GetTypeName() "out of LOS. Cancelling lase!", 5, self.AttackSet )
end
end
end
end
end
else
Recce:MessageToSetGroup( "Marking " .. TargetUnit:GetTypeName() .. " with laser " .. Recce.LaserCode .. ".", 5, self.AttackSet )
end
end
end
)
self:__Lasing( 15, Index, Duration )
self:SetDesignateMenu()
end
---
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterLaseOff( From, Event, To, Index )
local CC = self.CC:GetPositionable()
if CC then
CC:MessageToSetGroup( "Stopped lasing.", 5, self.AttackSet )
end
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
local Recces = self.Recces
for TargetID, RecceData in pairs( Recces ) do
local Recce = RecceData -- Wrapper.Unit#UNIT
Recce:MessageToSetGroup( "Stopped lasing " .. Recce:GetSpot().Target:GetTypeName() .. ".", 5, self.AttackSet )
Recce:LaseOff()
end
Recces = nil
self.Recces = {}
self.LaserCodesUsed = {}
self:SetDesignateMenu()
end
---
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterSmoke( From, Event, To, Index, Color )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
local TargetSetUnitCount = TargetSetUnit:Count()
TargetSetUnit:ForEachUnit(
--- @param Wrapper.Unit#UNIT SmokeUnit
function( SmokeUnit )
self:E("In procedure")
if math.random( 1, TargetSetUnitCount ) == math.random( 1, TargetSetUnitCount ) then
local RecceGroup = self.RecceSet:FindNearestGroupFromPointVec2(SmokeUnit:GetPointVec2())
local RecceUnit = RecceGroup:GetUnit( 1 )
if RecceUnit then
RecceUnit:MessageToSetGroup( "Smoking " .. SmokeUnit:GetTypeName() .. ".", 5, self.AttackSet )
SCHEDULER:New( self,
function()
if SmokeUnit:IsAlive() then
SmokeUnit:Smoke( Color, 150 )
end
self:Done( Index )
end, {}, math.random( 5, 20 )
)
end
end
end
)
end
--- Illuminating
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterIlluminate( From, Event, To, Index )
local TargetSetUnit = self.Detection:GetDetectedSet( Index )
local TargetUnit = TargetSetUnit:GetFirst()
if TargetUnit then
local RecceGroup = self.RecceSet:FindNearestGroupFromPointVec2(TargetUnit:GetPointVec2())
local RecceUnit = RecceGroup:GetUnit( 1 )
if RecceUnit then
RecceUnit:MessageToSetGroup( "Illuminating " .. TargetUnit:GetTypeName() .. ".", 5, self.AttackSet )
SCHEDULER:New( self,
function()
if TargetUnit:IsAlive() then
TargetUnit:GetPointVec3():AddY(300):IlluminationBomb()
end
self:Done( Index )
end, {}, math.random( 5, 20 )
)
end
end
end
--- Done
-- @param #DESIGNATE self
-- @return #DESIGNATE
function DESIGNATE:onafterDone( From, Event, To, Index )
self.Designating[Index] = nil
self:SetDesignateMenu()
end
end
-- Help from Ciribob

View File

@ -7,8 +7,25 @@
-- DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
-- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
--
-- Please watch this [youtube video](https://youtu.be/C7p81dUwP-E) that explains the detection concepts.
-- Find the DETECTION classes documentation further in this document in the globals section.
--
-- ====
--
-- # Demo Missions
--
-- ### [DETECTION Demo Missions and Source Code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/DET%20-%20Detection)
--
-- ### [DETECTION Demo Missions, only for Beta Testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
--
-- ### [ALL Demo Missions pack of the Latest Release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- ====
--
-- # YouTube Channel
--
-- ### [DETECTION YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3Cf5jpI6BS0sBOVWK__tji)
--
-- ====
--
-- ### Contributions:
--
@ -23,16 +40,24 @@
do -- DETECTION_BASE
--- # 1) DETECTION_BASE class, extends @{Fsm#FSM}
--- @type DETECTION_BASE
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
-- @field #number DetectionRun
-- @extends Core.Fsm#FSM
--- DETECTION_BASE class, extends @{Fsm#FSM}
--
-- The DETECTION_BASE class defines the core functions to administer detected objects.
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
--
-- ## 1.1) DETECTION_BASE constructor
-- ## DETECTION_BASE constructor
--
-- Construct a new DETECTION_BASE instance using the @{#DETECTION_BASE.New}() method.
--
-- ## 1.2) DETECTION_BASE initialization
-- ## Initialization
--
-- By default, detection will return detected objects with all the detection sensors available.
-- However, you can ask how the objects were found with specific detection methods.
@ -48,7 +73,29 @@ do -- DETECTION_BASE
-- * @{#DETECTION_BASE.InitDetectRWR}(): Detected using RWR.
-- * @{#DETECTION_BASE.InitDetectDLINK}(): Detected using DLINK.
--
-- ## 1.3) DETECTION_BASE derived classes group the detected units into a DetectedItems[] list
-- ## **Filter** detected units based on **category of the unit**
--
-- Filter the detected units based on Unit.Category using the method @{#DETECTION_BASE.FilterCategories}().
-- The different values of Unit.Category can be:
--
-- * Unit.Category.AIRPLANE
-- * Unit.Category.GROUND_UNIT
-- * Unit.Category.HELICOPTER
-- * Unit.Category.SHIP
-- * Unit.Category.STRUCTURE
--
-- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
--
-- Example to filter a single category (Unit.Category.AIRPLANE).
--
-- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
--
-- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
--
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
--
--
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
--
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
-- of grouping of detected units. Each DetectedItem within the DetectedItems[] list contains
@ -67,7 +114,7 @@ do -- DETECTION_BASE
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
-- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
--
-- ## 1.4) Apply additional Filters to fine-tune the detected objects
-- ## **Visual filters** to fine-tune the probability of the detected objects
--
-- By default, DCS World will return any object that is in LOS and within "visual reach", or detectable through one of the electronic detection means.
-- That being said, the DCS World detection algorithm can sometimes be unrealistic.
@ -88,7 +135,8 @@ do -- DETECTION_BASE
-- I advise however, that, when you first use the DETECTION derived classes, that you don't use these filters.
-- Only when you experience unrealistic behaviour in your missions, these filters could be applied.
--
-- ### 1.4.1 ) Distance visual detection probability
--
-- ### Distance visual detection probability
--
-- Upon a **visual** detection, the further away a detected object is, the less likely it is to be detected properly.
-- Also, the speed of accurate detection plays a role.
@ -102,7 +150,7 @@ do -- DETECTION_BASE
--
-- Use the method @{Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
--
-- ### 1.4.2 ) Alpha Angle visual detection probability
-- ### Alpha Angle visual detection probability
--
-- Upon a **visual** detection, the higher the unit is during the detecting process, the more likely the detected unit is to be detected properly.
-- A detection at a 90% alpha angle is the most optimal, a detection at 10% is less and a detection at 0% is less likely to be correct.
@ -114,7 +162,7 @@ do -- DETECTION_BASE
--
-- Use the method @{Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
--
-- ### 1.4.3 ) Cloudy Zones detection probability
-- ### Cloudy Zones detection probability
--
-- Upon a **visual** detection, the more a detected unit is within a cloudy zone, the less likely the detected unit is to be detected successfully.
-- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
@ -129,12 +177,12 @@ do -- DETECTION_BASE
-- Typically, this kind of filter would be applied for very specific areas were a detection needs to be very realisting for
-- AI not to detect so easily targets within a forrest or village rich area.
--
-- ## 1.5 ) Accept / Reject detected units
-- ## Accept / Reject detected units
--
-- DETECTION_BASE can accept or reject successful detections based on the location of the detected object,
-- if it is located in range or located inside or outside of specific zones.
--
-- ### 1.5.1 ) Detection acceptance of within range limit
-- ### Detection acceptance of within range limit
--
-- A range can be set that will limit a successful detection for a unit.
-- Use the method @{Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
@ -142,7 +190,7 @@ do -- DETECTION_BASE
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will accept detected units if the range is below 5000 meters.
-- Detection:SetAcceptRange( 5000 )
@ -151,7 +199,7 @@ do -- DETECTION_BASE
-- Detection:Start()
--
--
-- ### 1.5.2 ) Detection acceptance if within zone(s).
-- ### Detection acceptance if within zone(s).
--
-- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
@ -163,7 +211,7 @@ do -- DETECTION_BASE
-- local ZoneAccept2 = ZONE:New( "AcceptZone2" )
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will accept detected units by Detection when the unit is within ZoneAccept1 OR ZoneAccept2.
-- Detection:SetAcceptZones( { ZoneAccept1, ZoneAccept2 } )
@ -171,7 +219,7 @@ do -- DETECTION_BASE
-- -- Start the Detection.
-- Detection:Start()
--
-- ### 1.5.3 ) Detection rejectance if within zone(s).
-- ### Detection rejectance if within zone(s).
--
-- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
@ -184,7 +232,7 @@ do -- DETECTION_BASE
-- local ZoneReject2 = ZONE:New( "RejectZone2" )
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will reject detected units by Detection when the unit is within ZoneReject1 OR ZoneReject2.
-- Detection:SetRejectZones( { ZoneReject1, ZoneReject2 } )
@ -192,29 +240,24 @@ do -- DETECTION_BASE
-- -- Start the Detection.
-- Detection:Start()
--
-- ## 1.6) DETECTION_BASE is a Finite State Machine
-- ## DETECTION_BASE is a Finite State Machine
--
-- Various Events and State Transitions can be tailored using DETECTION_BASE.
--
-- ### 1.6.1) DETECTION_BASE States
-- ### DETECTION_BASE States
--
-- * **Detecting**: The detection is running.
-- * **Stopped**: The detection is stopped.
--
-- ### 1.6.2) DETECTION_BASE Events
-- ### DETECTION_BASE Events
--
-- * **Start**: Start the detection process.
-- * **Detect**: Detect new units.
-- * **Detected**: New units have been detected.
-- * **Stop**: Stop the detection process.
--
-- @field #DETECTION_BASE DETECTION_BASE
--
-- @type DETECTION_BASE
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
-- @field #number DetectionRun
-- @extends Core.Fsm#FSM
DETECTION_BASE = {
ClassName = "DETECTION_BASE",
DetectionSetGroup = nil,
@ -230,10 +273,16 @@ do -- DETECTION_BASE
--- @type DETECTION_BASE.DetectedObject
-- @field #string Name
-- @field #boolean Visible
-- @field #boolean IsVisible
-- @field #boolean KnowType
-- @field #boolean KnowDistance
-- @field #string Type
-- @field #number Distance
-- @field #boolean Identified
-- @field #number LastTime
-- @field #boolean LastPos
-- @field #number LastVelocity
--- @type DETECTION_BASE.DetectedItems
-- @list <#DETECTION_BASE.DetectedItem>
@ -266,12 +315,20 @@ do -- DETECTION_BASE
self.DetectionInterval = 30
self:InitDetectVisual( true )
self:InitDetectOptical( false )
self:InitDetectRadar( false )
self:InitDetectRWR( false )
self:InitDetectIRST( false )
self:InitDetectDLINK( false )
self:InitDetectVisual( nil )
self:InitDetectOptical( nil )
self:InitDetectRadar( nil )
self:InitDetectRWR( nil )
self:InitDetectIRST( nil )
self:InitDetectDLINK( nil )
self:FilterCategories( {
Unit.Category.AIRPLANE,
Unit.Category.GROUND_UNIT,
Unit.Category.HELICOPTER,
Unit.Category.SHIP,
Unit.Category.STRUCTURE
} )
-- Create FSM transitions.
@ -455,8 +512,6 @@ do -- DETECTION_BASE
self.DetectionRun = 0
self:UnIdentifyAllDetectedObjects() -- Resets the DetectedObjectsIdentified table
self.DetectionSetGroup:Flush()
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
self:E( {DetectionGroupData})
self:__DetectionGroup( DetectDelay, DetectionGroupData ) -- Process each detection asynchronously.
@ -482,6 +537,7 @@ do -- DETECTION_BASE
self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
local DetectionGroupName = DetectionGroup:GetName()
local DetectionUnit = DetectionGroup:GetUnit(1)
local DetectedUnits = {}
@ -498,10 +554,21 @@ do -- DETECTION_BASE
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
local DetectedObject = Detection.object -- Dcs.DCSWrapper.Object#Object
self:T2( DetectedObject )
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
DetectedObject,
self.DetectVisual,
self.DetectOptical,
self.DetectRadar,
self.DetectIRST,
self.DetectRWR,
self.DetectDLINK
)
self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } )
local DetectionAccepted = true
local DetectedObjectName = DetectedObject:getName()
@ -515,10 +582,14 @@ do -- DETECTION_BASE
( DetectedObjectVec3.y - DetectionGroupVec3.y )^2 +
( DetectedObjectVec3.z - DetectionGroupVec3.z )^2
) ^ 0.5 / 1000
local DetectedUnitCategory = DetectedObject:getDesc().category
self:T( { "Detected Target", DetectionGroupName, DetectedObjectName, Distance } )
self:T2( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory } )
-- Calculate Acceptance
DetectionAccepted = self._.FilterCategories[DetectedUnitCategory] ~= nil and DetectionAccepted or false
if self.AcceptRange and Distance > self.AcceptRange then
DetectionAccepted = false
@ -596,12 +667,14 @@ do -- DETECTION_BASE
HasDetectedObjects = true
if not self.DetectedObjects[DetectedObjectName] then
self.DetectedObjects[DetectedObjectName] = {}
end
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
self.DetectedObjects[DetectedObjectName].Visible = Detection.visible
self.DetectedObjects[DetectedObjectName].Type = Detection.type
self.DetectedObjects[DetectedObjectName].IsVisible = TargetIsVisible
self.DetectedObjects[DetectedObjectName].LastTime = TargetLastTime
self.DetectedObjects[DetectedObjectName].LastPos = TargetLastPos
self.DetectedObjects[DetectedObjectName].LastVelocity = TargetLastVelocity
self.DetectedObjects[DetectedObjectName].KnowType = TargetKnowType
self.DetectedObjects[DetectedObjectName].KnowDistance = Detection.distance -- TargetKnowDistance
self.DetectedObjects[DetectedObjectName].Distance = Distance
local DetectedUnit = UNIT:FindByName( DetectedObjectName )
@ -625,15 +698,54 @@ do -- DETECTION_BASE
end
if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
self:__Detect( self.DetectionInterval )
self:T( "--> Create Detection Sets" )
self:CreateDetectionSets()
self:CreateDetectionItems() -- Polymorphic call to Create/Update the DetectionItems list for the DETECTION_ class grouping method.
self:CleanDetectionItems() -- Any DetectionItem that has a Set with zero elements in it, must be removed from the DetectionItems list.
self:__Detect( self.DetectionInterval )
end
end
end
do -- DetectionItems Creation
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
-- @param #DETECTION_BASE self
-- @return #DETECTION_BASE
function DETECTION_BASE:CleanDetectionItems() --R2.1 Clean the DetectionItems list
self:F2()
-- We clean all DetectedItems.
-- if there are any remaining DetectedItems with no Set Objects then the Item in the DetectedItems must be deleted.
for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set
if DetectedSet:Count() == 0 then
self:RemoveDetectedItem(DetectedItemID)
end
end
return self
end
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
-- @param #DETECTION_BASE self
-- @return #DETECTION_BASE
function DETECTION_BASE:CreateDetectionItems()
self:F2()
self:E( "Error, in DETECTION_BASE class..." )
return self
end
end
do -- Initialization methods
@ -645,6 +757,8 @@ do -- DETECTION_BASE
function DETECTION_BASE:InitDetectVisual( DetectVisual )
self.DetectVisual = DetectVisual
return self
end
--- Detect Optical.
@ -655,6 +769,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectOptical = DetectOptical
return self
end
--- Detect Radar.
@ -665,6 +781,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectRadar = DetectRadar
return self
end
--- Detect IRST.
@ -675,6 +793,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectIRST = DetectIRST
return self
end
--- Detect RWR.
@ -685,6 +805,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectRWR = DetectRWR
return self
end
--- Detect DLINK.
@ -695,9 +817,52 @@ do -- DETECTION_BASE
self:F2()
self.DetectDLINK = DetectDLINK
return self
end
end
do -- Filter methods
--- Filter the detected units based on Unit.Category
-- The different values of Unit.Category can be:
--
-- * Unit.Category.AIRPLANE
-- * Unit.Category.GROUND_UNIT
-- * Unit.Category.HELICOPTER
-- * Unit.Category.SHIP
-- * Unit.Category.STRUCTURE
--
-- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
--
-- Example to filter a single category (Unit.Category.AIRPLANE).
--
-- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
--
-- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
--
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
--
-- @param #DETECTION_BASE self
-- @param #list<Dcs.DCSUnit#Unit> FilterCategories The Categories entries
-- @return #DETECTION_BASE self
function DETECTION_BASE:FilterCategories( FilterCategories )
self:F2()
self._.FilterCategories = {}
if type( FilterCategories ) == "table" then
for CategoryID, Category in pairs( FilterCategories ) do
self._.FilterCategories[Category] = Category
end
else
self._.FilterCategories[FilterCategories] = FilterCategories
end
return self
end
end
do
@ -989,7 +1154,7 @@ do -- DETECTION_BASE
-- @param #string ObjectName
-- @return #DETECTION_BASE.DetectedObject
function DETECTION_BASE:GetDetectedObject( ObjectName )
self:F( ObjectName )
self:F2( ObjectName )
if ObjectName then
local DetectedObject = self.DetectedObjects[ObjectName]
@ -1010,10 +1175,11 @@ do -- DETECTION_BASE
--- Adds a new DetectedItem to the DetectedItems list.
-- The DetectedItem is a table and contains a SET_UNIT in the field Set.
-- @param #DETECTION_BASE self
-- @param ItemPrefix
-- @param #string DetectedItemIndex The index of the DetectedItem.
-- @param Core.Set#SET_UNIT Set (optional) The Set of Units to be added.
-- @return #DETECTION_BASE.DetectedItem
function DETECTION_BASE:AddDetectedItem( DetectedItemIndex, Set )
function DETECTION_BASE:AddDetectedItem( ItemPrefix, DetectedItemIndex, Set )
local DetectedItem = {}
self.DetectedItemCount = self.DetectedItemCount + 1
@ -1025,8 +1191,9 @@ do -- DETECTION_BASE
self.DetectedItems[self.DetectedItemCount] = DetectedItem
end
DetectedItem.Set = Set or SET_UNIT:New()
DetectedItem.ItemID = self.DetectedItemMax
DetectedItem.Set = Set or SET_UNIT:New():FilterDeads():FilterCrashes()
DetectedItem.ItemID = ItemPrefix .. "." .. self.DetectedItemMax
DetectedItem.ID = self.DetectedItemMax
DetectedItem.Removed = false
return DetectedItem
@ -1041,7 +1208,7 @@ do -- DETECTION_BASE
-- @return #DETECTION_BASE.DetectedItem
function DETECTION_BASE:AddDetectedItemZone( DetectedItemIndex, Set, Zone )
local DetectedItem = self:AddDetectedItem( DetectedItemIndex, Set )
local DetectedItem = self:AddDetectedItem( "AREA", DetectedItemIndex, Set )
DetectedItem.Zone = Zone
@ -1054,8 +1221,10 @@ do -- DETECTION_BASE
-- @param #number DetectedItemIndex The index or position in the DetectedItems list where the item needs to be removed.
function DETECTION_BASE:RemoveDetectedItem( DetectedItemIndex )
self.DetectedItemCount = self.DetectedItemCount - 1
self.DetectedItems[DetectedItemIndex] = nil
if self.DetectedItems[DetectedItemIndex] then
self.DetectedItemCount = self.DetectedItemCount - 1
self.DetectedItems[DetectedItemIndex] = nil
end
end
@ -1069,7 +1238,7 @@ do -- DETECTION_BASE
--- Get the amount of SETs with detected objects.
-- @param #DETECTION_BASE self
-- @return #number Count
-- @return #number The amount of detected items. Note that the amount of detected items can differ with the reality, because detections are not real-time but doen in intervals!
function DETECTION_BASE:GetDetectedItemsCount()
local DetectedCount = self.DetectedItemCount
@ -1090,6 +1259,34 @@ do -- DETECTION_BASE
return nil
end
--- Get a detected ItemID using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return #string DetectedItemID
function DETECTION_BASE:GetDetectedItemID( Index ) --R2.1
local DetectedItem = self.DetectedItems[Index]
if DetectedItem then
return DetectedItem.ItemID
end
return ""
end
--- Get a detected ID using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return #string DetectedItemID
function DETECTION_BASE:GetDetectedID( Index ) --R2.1
local DetectedItem = self.DetectedItems[Index]
if DetectedItem then
return DetectedItem.ID
end
return ""
end
--- Get the @{Set#SET_UNIT} of a detecttion area using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
@ -1122,7 +1319,16 @@ do -- DETECTION_BASE
end
end
--- Menu of a detected item using a given numeric index.
-- @param #DETECTION_BASE self
-- @param Index
-- @return #string
function DETECTION_BASE:DetectedItemMenu( Index )
self:F( Index )
return nil
end
--- Report summary of a detected item using a given numeric index.
-- @param #DETECTION_BASE self
@ -1143,23 +1349,13 @@ do -- DETECTION_BASE
--- Get the detection Groups.
-- @param #DETECTION_BASE self
-- @return Wrapper.Group#GROUP
-- @return Core.Set#SET_GROUP
function DETECTION_BASE:GetDetectionSetGroup()
local DetectionSetGroup = self.DetectionSetGroup
return DetectionSetGroup
end
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
-- @param #DETECTION_BASE self
-- @return #DETECTION_BASE self
function DETECTION_BASE:CreateDetectionSets()
self:F2()
self:E( "Error, in DETECTION_BASE class..." )
end
--- Schedule the DETECTION construction.
-- @param #DETECTION_BASE self
@ -1254,7 +1450,7 @@ do -- DETECTION_UNITS
-- For each DetectedItem, a one field array is created containing the Unit detected.
-- @param #DETECTION_UNITS self
-- @return #DETECTION_UNITS self
function DETECTION_UNITS:CreateDetectionSets()
function DETECTION_UNITS:CreateDetectionItems()
self:F2( #self.DetectedObjects )
-- Loop the current detected items, and check if each object still exists and is detected.
@ -1262,7 +1458,6 @@ do -- DETECTION_UNITS
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItemSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedTypeName = DetectedItem.Type
for DetectedUnitName, DetectedUnitData in pairs( DetectedItemSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
@ -1277,6 +1472,17 @@ do -- DETECTION_UNITS
-- Yes, the DetectedUnit is still detected or exists. Flag as identified.
self:IdentifyDetectedObject( DetectedObject )
-- Update the detection with the new data provided.
DetectedItem.TypeName = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObject.Name
DetectedItem.IsVisible = DetectedObject.IsVisible
DetectedItem.LastTime = DetectedObject.LastTime
DetectedItem.LastPos = DetectedObject.LastPos
DetectedItem.LastVelocity = DetectedObject.LastVelocity
DetectedItem.KnowType = DetectedObject.KnowType
DetectedItem.KnowDistance = DetectedObject.KnowDistance
DetectedItem.Distance = DetectedObject.Distance
else
-- There was no DetectedObject, remove DetectedUnit from the Set.
self:AddChangeUnit( DetectedItem, "RU", DetectedUnitName )
@ -1300,11 +1506,16 @@ do -- DETECTION_UNITS
local DetectedItem = self:GetDetectedItem( DetectedUnitName )
if not DetectedItem then
self:T( "Added new DetectedItem" )
DetectedItem = self:AddDetectedItem( DetectedUnitName )
DetectedItem.Type = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObjectData.Name
DetectedItem.Visible = DetectedObjectData.Visible
DetectedItem.Distance = DetectedObjectData.Distance
DetectedItem = self:AddDetectedItem( "UNIT", DetectedUnitName )
DetectedItem.TypeName = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObject.Name
DetectedItem.IsVisible = DetectedObject.IsVisible
DetectedItem.LastTime = DetectedObject.LastTime
DetectedItem.LastPos = DetectedObject.LastPos
DetectedItem.LastVelocity = DetectedObject.LastVelocity
DetectedItem.KnowType = DetectedObject.KnowType
DetectedItem.KnowDistance = DetectedObject.KnowDistance
DetectedItem.Distance = DetectedObject.Distance
end
DetectedItem.Set:AddUnit( DetectedUnit )
@ -1323,16 +1534,17 @@ do -- DETECTION_UNITS
end
end
--- Report summary of a DetectedItem using a given numeric index.
--- Menu of a DetectedItem using a given numeric index.
-- @param #DETECTION_UNITS self
-- @param Index
-- @return #string
function DETECTION_UNITS:DetectedItemReportSummary( Index )
function DETECTION_UNITS:DetectedItemMenu( Index )
self:F( Index )
local DetectedItem = self:GetDetectedItem( Index )
local DetectedSet = self:GetDetectedSet( Index )
local DetectedItemID = self:GetDetectedItemID( Index )
self:T( DetectedSet )
if DetectedSet then
@ -1345,29 +1557,76 @@ do -- DETECTION_UNITS
if DetectedItemUnit and DetectedItemUnit:IsAlive() then
self:T(DetectedItemUnit)
local UnitCategoryName = DetectedItemUnit:GetCategoryName() or ""
local UnitCategoryType = DetectedItemUnit:GetTypeName() or ""
local DetectedItemCoordinate = DetectedItemUnit:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
ReportSummary = string.format(
"%s - %s",
DetectedItemID,
DetectedItemCoordText
)
end
self:T( ReportSummary )
return ReportSummary
end
end
if DetectedItem.Type and UnitCategoryName and UnitCategoryType then
UnitCategoryText = UnitCategoryName .. " (" .. UnitCategoryType .. ") at "
--- Report summary of a DetectedItem using a given numeric index.
-- @param #DETECTION_UNITS self
-- @param Index
-- @return #string
function DETECTION_UNITS:DetectedItemReportSummary( Index )
self:F( Index )
local DetectedItem = self:GetDetectedItem( Index )
local DetectedSet = self:GetDetectedSet( Index )
local DetectedItemID = self:GetDetectedItemID( Index )
self:T( DetectedSet )
if DetectedSet then
local ReportSummary = ""
local UnitDistanceText = ""
local UnitCategoryText = ""
local DetectedItemUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
if DetectedItemUnit and DetectedItemUnit:IsAlive() then
self:T(DetectedItemUnit)
if DetectedItem.KnowType then
local UnitCategoryName = DetectedItemUnit:GetCategoryName()
if UnitCategoryName then
UnitCategoryText = UnitCategoryName
end
if DetectedItem.TypeName then
UnitCategoryText = UnitCategoryText .. " (" .. DetectedItem.TypeName .. ")"
end
else
UnitCategoryText = "Unknown target at "
UnitCategoryText = "Unknown"
end
if DetectedItem.Visible == false then
UnitDistanceText = string.format( "%.2f", DetectedItem.Distance ) .. " estimated km"
if DetectedItem.KnowDistance then
if DetectedItem.IsVisible then
UnitDistanceText = " at " .. string.format( "%.2f", DetectedItem.Distance ) .. " km"
end
else
UnitDistanceText = string.format( "%.2f", DetectedItem.Distance ) .. " km, visual contact"
if DetectedItem.IsVisible then
UnitDistanceText = " at +/- " .. string.format( "%.0f", DetectedItem.Distance ) .. " km"
end
end
local DetectedItemPointVec3 = DetectedItemUnit:GetPointVec3()
local DetectedItemPointLL = DetectedItemPointVec3:ToStringLL( 3, true )
local DetectedItemCoordinate = DetectedItemUnit:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
local ThreatLevelA2G = DetectedItemUnit:GetThreatLevel( DetectedItem )
ReportSummary = string.format(
"%s - Threat [%s] (%2d) - %s%s",
DetectedItemPointLL,
"%s - %s - Threat:[%s](%2d) - %s%s",
DetectedItemID,
DetectedItemCoordText,
string.rep( "", ThreatLevelA2G ),
ThreatLevelA2G,
UnitCategoryText,
@ -1380,6 +1639,7 @@ do -- DETECTION_UNITS
return ReportSummary
end
end
--- Report detailed of a detection result.
-- @param #DETECTION_UNITS self
@ -1477,7 +1737,7 @@ do -- DETECTION_TYPES
-- For each DetectedItem, a one field array is created containing the Unit detected.
-- @param #DETECTION_TYPES self
-- @return #DETECTION_TYPES self
function DETECTION_TYPES:CreateDetectionSets()
function DETECTION_TYPES:CreateDetectionItems()
self:F2( #self.DetectedObjects )
-- Loop the current detected items, and check if each object still exists and is detected.
@ -1485,7 +1745,7 @@ do -- DETECTION_TYPES
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItemSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedTypeName = DetectedItem.Type
local DetectedTypeName = DetectedItem.TypeName
for DetectedUnitName, DetectedUnitData in pairs( DetectedItemSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
@ -1521,8 +1781,8 @@ do -- DETECTION_TYPES
local DetectedTypeName = DetectedUnit:GetTypeName()
local DetectedItem = self:GetDetectedItem( DetectedTypeName )
if not DetectedItem then
DetectedItem = self:AddDetectedItem( DetectedTypeName )
DetectedItem.Type = DetectedUnit:GetTypeName()
DetectedItem = self:AddDetectedItem( "TYPE", DetectedTypeName )
DetectedItem.TypeName = DetectedUnit:GetTypeName()
end
DetectedItem.Set:AddUnit( DetectedUnit )
@ -1531,6 +1791,9 @@ do -- DETECTION_TYPES
end
end
-- Check if there are any friendlies nearby.
for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
@ -1541,6 +1804,39 @@ do -- DETECTION_TYPES
end
end
--- Menu of a DetectedItem using a given numeric index.
-- @param #DETECTION_TYPES self
-- @param Index
-- @return #string
function DETECTION_TYPES:DetectedItemMenu( DetectedTypeName )
self:F( DetectedTypeName )
local DetectedItem = self:GetDetectedItem( DetectedTypeName )
local DetectedSet = self:GetDetectedSet( DetectedTypeName )
local DetectedItemID = self:GetDetectedItemID( DetectedTypeName )
self:T( DetectedItem )
if DetectedItem then
local DetectedItemUnit = DetectedSet:GetFirst()
local DetectedItemCoordinate = DetectedItemUnit:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
self:E( { DetectedItemID,
DetectedItemCoordText } )
local ReportSummary = string.format(
"%s - %s",
DetectedItemID,
DetectedItemCoordText
)
self:T( ReportSummary )
return ReportSummary
end
end
--- Report summary of a DetectedItem using a given numeric index.
-- @param #DETECTION_TYPES self
@ -1551,16 +1847,24 @@ do -- DETECTION_TYPES
local DetectedItem = self:GetDetectedItem( DetectedTypeName )
local DetectedSet = self:GetDetectedSet( DetectedTypeName )
local DetectedItemID = self:GetDetectedItemID( DetectedTypeName )
self:T( DetectedItem )
if DetectedItem then
local ThreatLevelA2G = DetectedSet:CalculateThreatLevelA2G()
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemType = DetectedItem.Type
local DetectedItemType = DetectedItem.TypeName
local DetectedItemUnit = DetectedSet:GetFirst()
local DetectedItemCoordinate = DetectedItemUnit:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
local ReportSummary = string.format(
"Threat [%s] (%2d) - %2d of %s",
"%s - %s - Threat:[%s](%2d) - %2d of %s",
DetectedItemID,
DetectedItemCoordText,
string.rep( "", ThreatLevelA2G ),
ThreatLevelA2G,
DetectedItemsCount,
@ -1657,6 +1961,36 @@ do -- DETECTION_AREAS
return self
end
--- Menu of a detected item using a given numeric index.
-- @param #DETECTION_AREAS self
-- @param Index
-- @return #string
function DETECTION_AREAS:DetectedItemMenu( Index )
self:F( Index )
local DetectedItem = self:GetDetectedItem( Index )
local DetectedItemID = self:GetDetectedItemID( Index )
if DetectedItem then
local DetectedSet = self:GetDetectedSet( Index )
local ReportSummaryItem
local DetectedZone = self:GetDetectedZone( Index )
local DetectedItemCoordinate = DetectedZone:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
local ReportSummary = string.format(
"%s - %s",
DetectedItemID,
DetectedItemCoordText
)
return ReportSummary
end
return nil
end
--- Report summary of a detected item using a given numeric index.
-- @param #DETECTION_AREAS self
@ -1666,21 +2000,24 @@ do -- DETECTION_AREAS
self:F( Index )
local DetectedItem = self:GetDetectedItem( Index )
local DetectedItemID = self:GetDetectedItemID( Index )
if DetectedItem then
local DetectedSet = self:GetDetectedSet( Index )
local ReportSummaryItem
local DetectedZone = self:GetDetectedZone( Index )
local DetectedItemPointVec3 = DetectedZone:GetPointVec3()
local DetectedItemPointLL = DetectedItemPointVec3:ToStringLL( 3, true )
local DetectedItemCoordinate = DetectedZone:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
local ThreatLevelA2G = self:GetTreatLevelA2G( DetectedItem )
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemsTypes = DetectedSet:GetTypeNames()
local ReportSummary = string.format(
"%s - Threat [%s] (%2d) - %2d of %s",
DetectedItemPointLL,
"%s - %s - Threat:[%s](%2d)\n %2d of %s",
DetectedItemID,
DetectedItemCoordText,
string.rep( "", ThreatLevelA2G ),
ThreatLevelA2G,
DetectedItemsCount,
@ -1692,6 +2029,25 @@ do -- DETECTION_AREAS
return nil
end
--- Report detailed of a detection result.
-- @param #DETECTION_AREAS self
-- @return #string
function DETECTION_AREAS:DetectedReportDetailed() --R2.1 Fixed missing report
self:F()
local Report = REPORT:New( "Detected areas:" )
for DetectedItemIndex, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItem -- #DETECTION_BASE.DetectedItem
local ReportSummary = self:DetectedItemReportSummary( DetectedItemIndex )
Report:Add( ReportSummary )
end
local ReportText = Report:Text()
return ReportText
end
--- Returns if there are friendlies nearby the FAC units ...
@ -1869,7 +2225,7 @@ do -- DETECTION_AREAS
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
-- @param #DETECTION_AREAS self
-- @return #DETECTION_AREAS self
function DETECTION_AREAS:CreateDetectionSets()
function DETECTION_AREAS:CreateDetectionItems()
self:F2()
@ -2016,7 +2372,7 @@ do -- DETECTION_AREAS
-- New detection area
local DetectedItem = self:AddDetectedItemZone( nil,
SET_UNIT:New(),
SET_UNIT:New():FilterDeads():FilterCrashes(),
ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange )
)
--self:E( DetectedItem.Zone.ZoneUNIT.UnitName )

View File

@ -442,7 +442,7 @@ function MISSILETRAINER._MenuMessages( MenuParameters )
if MenuParameters.Distance ~= nil then
self.Distance = MenuParameters.Distance
MESSAGE:New( "Hit detection distance set to " .. self.Distance .. " meters", 15, "Menu" ):ToAll()
MESSAGE:New( "Hit detection distance set to " .. self.Distance * 1000 .. " meters", 15, "Menu" ):ToAll()
end
end

View File

@ -598,7 +598,7 @@ function SCORING:_AddPlayerFromUnit( UnitData )
end
if self.Players[PlayerName].Penalty > self.Fratricide then
UnitData:Destroy()
--UnitData:Destroy()
MESSAGE:New( "Player '" .. PlayerName .. "' committed FRATRICIDE, he will be COURT MARTIALED and is DISMISSED from this mission!",
10
):ToAll()

View File

@ -1,162 +1,26 @@
--- Single-Player:**Yes** / Multi-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**All** --
-- **Spawn groups of units dynamically in your missions.**
--- **Functional** -- Spawn dynamically new GROUPs in your missions.
--
-- ![Banner Image](..\Presentations\SPAWN\SPAWN.JPG)
--
-- ===
-- ====
--
-- # 1) @{#SPAWN} class, extends @{Base#BASE}
--
-- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned.
-- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object.
-- A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods.
--
-- Within the SPAWN object, there is an internal index that keeps track of which group from the internal group list was spawned.
-- When new groups get spawned by using the SPAWN methods (see below), it will be validated whether the Limits (@{#SPAWN.Limit}) of the SPAWN object are not reached.
-- When all is valid, a new group will be created by the spawning methods, and the internal index will be increased with 1.
--
-- Regarding the name of new spawned groups, a _SpawnPrefix_ will be assigned for each new group created.
-- If you want to have the Spawn Template name to be used as the _SpawnPrefix_ name, use the @{#SPAWN.New} constructor.
-- However, when the @{#SPAWN.NewWithAlias} constructor was used, the Alias name will define the _SpawnPrefix_ name.
-- Groups will follow the following naming structure when spawned at run-time:
--
-- 1. Spawned groups will have the name _SpawnPrefix_#ggg, where ggg is a counter from 0 to 999.
-- 2. Spawned units will have the name _SpawnPrefix_#ggg-uu, where uu is a counter from 0 to 99 for each new spawned unit belonging to the group.
--
-- Some additional notes that need to be remembered:
--
-- * Templates are actually groups defined within the mission editor, with the flag "Late Activation" set. As such, these groups are never used within the mission, but are used by the @{#SPAWN} module.
-- * It is important to defined BEFORE you spawn new groups, a proper initialization of the SPAWN instance is done with the options you want to use.
-- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore.
--
-- ## 1.1) SPAWN construction methods
--
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
--
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition).
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP Template (definition), and gives each spawned @{Group} an different name.
--
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
-- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient.
--
-- ## 1.2) SPAWN initialization methods
--
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
--
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
-- * @{#SPAWN.InitRepeat}(): Re-spawn groups when they land at the home base. Similar methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object.
--
-- ## 1.3) SPAWN spawning methods
--
-- Groups can be spawned at different times and methods:
--
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals. You can use @{#SPAWN.SpawnScheduleStart}() and @{#SPAWN.SpawnScheduleStop}() to start and stop the schedule respectively.
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
--
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object.
-- You can use the @{GROUP} object to do further actions with the DCSGroup.
--
-- ## 1.4) Retrieve alive GROUPs spawned by the SPAWN object
--
-- The SPAWN class administers which GROUPS it has reserved (in stock) or has created during mission execution.
-- Every time a SPAWN object spawns a new GROUP object, a reference to the GROUP object is added to an internal table of GROUPS.
-- SPAWN provides methods to iterate through that internal GROUP object reference table:
--
-- * @{#SPAWN.GetFirstAliveGroup}(): Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
-- * @{#SPAWN.GetNextAliveGroup}(): Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
-- * @{#SPAWN.GetLastAliveGroup}(): Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
--
-- You can use the methods @{#SPAWN.GetFirstAliveGroup}() and sequently @{#SPAWN.GetNextAliveGroup}() to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
-- The method @{#SPAWN.GetGroupFromIndex}() will return the GROUP object reference from the given Index, dead or alive...
--
-- ## 1.5) SPAWN object cleaning
--
-- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive.
-- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't,
-- and it may occur that no new groups are or can be spawned as limits are reached.
-- To prevent this, a @{#SPAWN.InitCleanUp}() initialization method has been defined that will silently monitor the status of each spawned group.
-- Once a group has a velocity = 0, and has been waiting for a defined interval, that group will be cleaned or removed from run-time.
-- There is a catch however :-) If a damaged group has returned to an airbase within the coalition, that group will not be considered as "lost"...
-- In such a case, when the inactive group is cleaned, a new group will Re-spawned automatically.
-- This models AI that has succesfully returned to their airbase, to restart their combat activities.
-- Check the @{#SPAWN.InitCleanUp}() for further info.
--
-- ## 1.6) Catch the @{Group} spawn event in a callback function!
--
-- When using the SpawnScheduled method, new @{Group}s are created following the schedule timing parameters.
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
-- To SPAWN class supports this functionality through the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method, which takes a function as a parameter that you can define locally.
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter.
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
-- The documentation of the SPAWN class can be found further in this document.
--
-- ====
--
-- # **API CHANGE HISTORY**
-- # Demo Missions
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
-- ### [SPAWN Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPA%20-%20Spawning)
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
-- ### [SPAWN Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPA%20-%20Spawning)
--
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
--
-- Hereby the change log:
-- ====
--
-- 2017-03-14: SPAWN:**InitKeepUnitNames()** added.
-- 2017-03-14: SPAWN:**InitRandomizePosition( RandomizePosition, OuterRadious, InnerRadius )** added.
-- # YouTube Channel
--
-- 2017-02-04: SPAWN:InitUnControlled( **UnControlled** ) replaces SPAWN:InitUnControlled().
--
-- 2017-01-24: SPAWN:**InitAIOnOff( AIOnOff )** added.
--
-- 2017-01-24: SPAWN:**InitAIOn()** added.
--
-- 2017-01-24: SPAWN:**InitAIOff()** added.
--
-- 2016-08-15: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ).
--
-- 2016-08-15: SPAWN:**InitRandomizeZones( SpawnZones )** added.
--
-- 2016-08-14: SPAWN:**OnSpawnGroup**( SpawnCallBackFunction, ... ) replaces SPAWN:_SpawnFunction_( SpawnCallBackFunction, ... ).
--
-- 2016-08-14: SPAWN.SpawnInZone( Zone, __RandomizeGroup__, SpawnIndex ) replaces SpawnInZone( Zone, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ).
--
-- 2016-08-14: SPAWN.SpawnFromVec3( Vec3, SpawnIndex ) replaces SpawnFromVec3( Vec3, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- 2016-08-14: SPAWN.SpawnFromVec2( Vec2, SpawnIndex ) replaces SpawnFromVec2( Vec2, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromUnit( SpawnUnit, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- 2016-08-14: SPAWN.SpawnFromUnit( SpawnUnit, SpawnIndex ) replaces SpawnFromStatic( SpawnStatic, _RandomizeUnits, OuterRadius, InnerRadius,_ SpawnIndex ):
--
-- 2016-08-14: SPAWN.**InitRandomizeUnits( RandomizeUnits, OuterRadius, InnerRadius )** added:
--
-- 2016-08-14: SPAWN.**Init**Limit( SpawnMaxUnitsAlive, SpawnMaxGroups ) replaces SPAWN._Limit_( SpawnMaxUnitsAlive, SpawnMaxGroups ):
--
-- 2016-08-14: SPAWN.**Init**Array( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ) replaces SPAWN._Array_( SpawnAngle, SpawnWidth, SpawnDeltaX, SpawnDeltaY ).
--
-- 2016-08-14: SPAWN.**Init**RandomizeRoute( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ) replaces SPAWN._RandomizeRoute_( SpawnStartPoint, SpawnEndPoint, SpawnRadius, SpawnHeight ).
--
-- 2016-08-14: SPAWN.**Init**RandomizeTemplate( SpawnTemplatePrefixTable ) replaces SPAWN._RandomizeTemplate_( SpawnTemplatePrefixTable ).
--
-- 2016-08-14: SPAWN.**Init**UnControlled() replaces SPAWN._UnControlled_().
-- ### [SPAWN YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL)
--
-- ===
--
@ -177,7 +41,6 @@
--- SPAWN Class
-- @type SPAWN
-- @extends Core.Base#BASE
-- @field ClassName
-- @field #string SpawnTemplatePrefix
-- @field #string SpawnAliasPrefix
@ -186,6 +49,214 @@
-- @field #number SpawnIndex
-- @field #number MaxAliveGroups
-- @field #SPAWN.SpawnZoneTable SpawnZoneTable
-- @extends Core.Base#BASE
--- # SPAWN class, extends @{Base#BASE}
--
-- The SPAWN class allows to spawn dynamically new groups.
-- Each SPAWN object needs to be have a related **template group** setup in the Mission Editor (ME),
-- which is a normal group with the **Late Activation** flag set.
-- This template group will never be activated in your mission.
-- SPAWN uses that **template group** to reference to all the characteristics
-- (air, ground, livery, unit composition, formation, skill level etc) of each new group to be spawned.
--
-- Therefore, when creating a SPAWN object, the @{#SPAWN.New} and @{#SPAWN.NewWithAlias} require
-- **the name of the template group** to be given as a string to those constructor methods.
--
-- Initialization settings can be applied on the SPAWN object,
-- which modify the behaviour or the way groups are spawned.
-- These initialization methods have the prefix **Init**.
-- There are also spawn methods with the prefix **Spawn** and will spawn new groups in various ways.
--
-- ### IMPORTANT! The methods with prefix **Init** must be used before any methods with prefix **Spawn** method are used, or unexpected results may appear!!!
--
-- Because SPAWN can spawn multiple groups of a template group,
-- SPAWN has an **internal index** that keeps track
-- which was the latest group that was spawned.
--
-- **Limits** can be set on how many groups can be spawn in each SPAWN object,
-- using the method @{#SPAWN.InitLimit}. SPAWN has 2 kind of limits:
--
-- * The maximum amount of @{Unit}s that can be **alive** at the same time...
-- * The maximum amount of @{Group}s that can be **spawned**... This is more of a **resource**-type of limit.
--
-- When new groups get spawned using the **Spawn** methods,
-- it will be evaluated whether any limits have been reached.
-- When no spawn limit is reached, a new group will be created by the spawning methods,
-- and the internal index will be increased with 1.
--
-- These limits ensure that your mission does not accidentally get flooded with spawned groups.
-- Additionally, it also guarantees that independent of the group composition,
-- at any time, the most optimal amount of groups are alive in your mission.
-- For example, if your template group has a group composition of 10 units, and you specify a limit of 100 units alive at the same time,
-- with unlimited resources = :InitLimit( 100, 0 ) and 10 groups are alive, but two groups have only one unit alive in the group,
-- then a sequent Spawn(Scheduled) will allow a new group to be spawned!!!
--
-- ### IMPORTANT!! If a limit has been reached, it is possible that a **Spawn** method returns **nil**, meaning, no @{Group} had been spawned!!!
--
-- Spawned groups get **the same name** as the name of the template group.
-- Spawned units in those groups keep _by default_ **the same name** as the name of the template group.
-- However, because multiple groups and units are created from the template group,
-- a suffix is added to each spawned group and unit.
--
-- Newly spawned groups will get the following naming structure at run-time:
--
-- 1. Spawned groups will have the name _GroupName_#_nnn_, where _GroupName_ is the name of the **template group**,
-- and _nnn_ is a **counter from 0 to 999**.
-- 2. Spawned units will have the name _GroupName_#_nnn_-_uu_,
-- where _uu_ is a **counter from 0 to 99** for each new spawned unit belonging to the group.
--
-- That being said, there is a way to keep the same unit names!
-- The method @{#SPAWN.InitKeepUnitNames}() will keep the same unit names as defined within the template group, thus:
--
-- 3. Spawned units will have the name _UnitName_#_nnn_-_uu_,
-- where _UnitName_ is the **unit name as defined in the template group*,
-- and _uu_ is a **counter from 0 to 99** for each new spawned unit belonging to the group.
--
-- Some **additional notes that need to be considered!!**:
--
-- * templates are actually groups defined within the mission editor, with the flag "Late Activation" set.
-- As such, these groups are never used within the mission, but are used by the @{#SPAWN} module.
-- * It is important to defined BEFORE you spawn new groups,
-- a proper initialization of the SPAWN instance is done with the options you want to use.
-- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn template(s),
-- or the SPAWN module logic won't work anymore.
--
-- ## SPAWN construction methods
--
-- Create a new SPAWN object with the @{#SPAWN.New}() or the @{#SPAWN.NewWithAlias}() methods:
--
-- * @{#SPAWN.New}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition).
-- * @{#SPAWN.NewWithAlias}(): Creates a new SPAWN object taking the name of the group that represents the GROUP template (definition), and gives each spawned @{Group} an different name.
--
-- It is important to understand how the SPAWN class works internally. The SPAWN object created will contain internally a list of groups that will be spawned and that are already spawned.
-- The initialization methods will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons.
-- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient.
--
-- ## SPAWN **Init**ialization methods
--
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
--
-- ### Unit Names
--
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
--
-- ### Route randomization
--
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
--
-- ### Group composition randomization
--
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
--
-- ### Uncontrolled
--
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
--
-- ### Array formation
--
-- * @{#SPAWN.InitArray}(): Make groups visible before they are actually activated, and order these groups like a batallion in an array.
--
-- ### Position randomization
--
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
--
-- ### Enable / Disable AI when spawning a new @{Group}
--
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object.
--
-- ### Limit scheduled spawning
--
-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
--
-- ### Delay initial scheduled spawn
--
-- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when scheduled spawning the first @{Group} object.
-- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when scheduled spawning the first @{Group} object.
-- * @{#SPAWN.InitDelayOff}(): Turns the inital delay Off when scheduled spawning the first @{Group} object.
--
-- ### Repeat spawned @{Group}s upon landing
--
-- * @{#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.
--
--
-- ## SPAWN **Spawn** methods
--
-- Groups can be spawned at different times and methods:
--
-- ### **Single** spawning methods
--
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
-- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}.
--
-- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object.
-- You can use the @{GROUP} object to do further actions with the DCSGroup.
--
-- ### **Scheduled** spawning methods
--
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals.
-- * @{#SPAWN.SpawnScheduledStart}(): Start or continue to spawn groups at scheduled time intervals.
-- * @{#SPAWN.SpawnScheduledStop}(): Stop the spawning of groups at scheduled time intervals.
--
--
--
-- ## Retrieve alive GROUPs spawned by the SPAWN object
--
-- The SPAWN class administers which GROUPS it has reserved (in stock) or has created during mission execution.
-- Every time a SPAWN object spawns a new GROUP object, a reference to the GROUP object is added to an internal table of GROUPS.
-- SPAWN provides methods to iterate through that internal GROUP object reference table:
--
-- * @{#SPAWN.GetFirstAliveGroup}(): Will find the first alive GROUP it has spawned, and return the alive GROUP object and the first Index where the first alive GROUP object has been found.
-- * @{#SPAWN.GetNextAliveGroup}(): Will find the next alive GROUP object from a given Index, and return a reference to the alive GROUP object and the next Index where the alive GROUP has been found.
-- * @{#SPAWN.GetLastAliveGroup}(): Will find the last alive GROUP object, and will return a reference to the last live GROUP object and the last Index where the last alive GROUP object has been found.
--
-- You can use the methods @{#SPAWN.GetFirstAliveGroup}() and sequently @{#SPAWN.GetNextAliveGroup}() to iterate through the alive GROUPS within the SPAWN object, and to actions... See the respective methods for an example.
-- The method @{#SPAWN.GetGroupFromIndex}() will return the GROUP object reference from the given Index, dead or alive...
--
-- ## Spawned cleaning of inactive groups
--
-- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive.
-- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't,
-- and it may occur that no new groups are or can be spawned as limits are reached.
-- To prevent this, a @{#SPAWN.InitCleanUp}() initialization method has been defined that will silently monitor the status of each spawned group.
-- Once a group has a velocity = 0, and has been waiting for a defined interval, that group will be cleaned or removed from run-time.
-- There is a catch however :-) If a damaged group has returned to an airbase within the coalition, that group will not be considered as "lost"...
-- In such a case, when the inactive group is cleaned, a new group will Re-spawned automatically.
-- This models AI that has succesfully returned to their airbase, to restart their combat activities.
-- Check the @{#SPAWN.InitCleanUp}() for further info.
--
-- ## Catch the @{Group} Spawn Event in a callback function!
--
-- When using the @{#SPAWN.SpawnScheduled)() method, new @{Group}s are created following the spawn time interval parameters.
-- When a new @{Group} is spawned, you maybe want to execute actions with that group spawned at the spawn event.
-- The SPAWN class supports this functionality through the method @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ),
-- which takes a function as a parameter that you can define locally.
-- Whenever a new @{Group} is spawned, the given function is called, and the @{Group} that was just spawned, is given as a parameter.
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
--
-- ## Delay the initial spawning
--
-- When using the @{#SPAWN.SpawnScheduled)() method, the default behaviour of this method will be that it will spawn the initial (first) @{Group}
-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
-- activate a delay before the first @{Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
-- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used.
--
--
-- @field #SPAWN SPAWN
--
SPAWN = {
ClassName = "SPAWN",
SpawnTemplatePrefix = nil,
@ -227,6 +298,7 @@ function SPAWN:New( SpawnTemplatePrefix )
self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else
@ -270,6 +342,7 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else
@ -626,6 +699,36 @@ do -- AI methods
end -- AI methods
do -- Delay methods
--- Turns the Delay On or Off for the first @{Group} scheduled spawning.
-- The default value is that for scheduled spawning, there is an initial delay when spawning the first @{Group}.
-- @param #SPAWN self
-- @param #boolean DelayOnOff A value of true sets the Delay On, a value of false sets the Delay Off.
-- @return #SPAWN The SPAWN object
function SPAWN:InitDelayOnOff( DelayOnOff )
self.DelayOnOff = DelayOnOff
return self
end
--- Turns the Delay On for the @{Group} when spawning.
-- @param #SPAWN self
-- @return #SPAWN The SPAWN object
function SPAWN:InitDelayOn()
return self:InitDelayOnOff( true )
end
--- Turns the Delay Off for the @{Group} when spawning.
-- @param #SPAWN self
-- @return #SPAWN The SPAWN object
function SPAWN:InitDelayOff()
return self:InitDelayOnOff( false )
end
end -- Delay methods
--- Will spawn a group based on the internal index.
-- Note: Uses @{DATABASE} module defined in MOOSE.
-- @param #SPAWN self
@ -669,6 +772,8 @@ function SPAWN:ReSpawn( SpawnIndex )
SpawnGroup:ReSpawnFunction()
end
SpawnGroup:ResetEvents()
return SpawnGroup
end
@ -787,7 +892,11 @@ function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
self:F( { SpawnTime, SpawnTimeVariation } )
if SpawnTime ~= nil and SpawnTimeVariation ~= nil then
self.SpawnScheduler = SCHEDULER:New( self, self._Scheduler, {}, 1, SpawnTime, SpawnTimeVariation )
local InitialDelay = 0
if self.DelayOnOff == true then
InitialDelay = math.random( SpawnTime - SpawnTime * SpawnTimeVariation, SpawnTime + SpawnTime * SpawnTimeVariation )
end
self.SpawnScheduler = SCHEDULER:New( self, self._Scheduler, {}, InitialDelay, SpawnTime, SpawnTimeVariation )
end
return self
@ -795,17 +904,23 @@ end
--- Will re-start the spawning scheduler.
-- Note: This method is only required to be called when the schedule was stopped.
-- @param #SPAWN self
-- @return #SPAWN
function SPAWN:SpawnScheduleStart()
self:F( { self.SpawnTemplatePrefix } )
self.SpawnScheduler:Start()
return self
end
--- Will stop the scheduled spawning scheduler.
-- @param #SPAWN self
-- @return #SPAWN
function SPAWN:SpawnScheduleStop()
self:F( { self.SpawnTemplatePrefix } )
self.SpawnScheduler:Stop()
return self
end
@ -926,7 +1041,7 @@ end
function SPAWN:SpawnFromUnit( HostUnit, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostUnit, SpawnIndex } )
if HostUnit and HostUnit:IsAlive() then -- and HostUnit:getUnit(1):inAir() == false then
if HostUnit and HostUnit:IsAlive() ~= nil then -- and HostUnit:getUnit(1):inAir() == false then
return self:SpawnFromVec3( HostUnit:GetVec3(), SpawnIndex )
end
@ -1480,11 +1595,13 @@ function SPAWN:_OnBirth( EventData )
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits + 1
self:T( "Alive Units: " .. self.AliveUnits )
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits + 1
self:T( "Alive Units: " .. self.AliveUnits )
end
end
end
end
@ -1501,11 +1618,13 @@ function SPAWN:_OnDeadOrCrash( EventData )
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Dead event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Dead event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
end
end
end
end
@ -1519,10 +1638,12 @@ function SPAWN:_OnTakeOff( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "TakeOff event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self:T( "self.Landed = false" )
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false )
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "TakeOff event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self:T( "self.Landed = false" )
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false )
end
end
end
end
@ -1537,16 +1658,18 @@ function SPAWN:_OnLand( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Land event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- TODO: Check if this is the last unit of the group that lands.
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true )
if self.RepeatOnLanding then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Land event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- TODO: Check if this is the last unit of the group that lands.
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true )
if self.RepeatOnLanding then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
end
end
end
@ -1561,16 +1684,18 @@ function SPAWN:_OnEngineShutDown( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "EngineShutdown event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- todo: test if on the runway
local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" )
if Landed and self.RepeatOnEngineShutDown then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "EngineShutdown event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- todo: test if on the runway
local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" )
if Landed and self.RepeatOnEngineShutDown then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
end
end
end

View File

@ -9,5 +9,4 @@ _SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.Timer#SCHEDULEDISPATCHER
--- Declare the main database object, which is used internally by the MOOSE classes.
_DATABASE = DATABASE:New() -- Database#DATABASE
--COORDINATE:CoordinateMenu()

View File

@ -9,6 +9,7 @@
-- @extends Core.Base#BASE
REPORT = {
ClassName = "REPORT",
Title = "",
}
--- Create a new REPORT.
@ -17,23 +18,53 @@ REPORT = {
-- @return #REPORT
function REPORT:New( Title )
local self = BASE:Inherit( self, BASE:New() )
local self = BASE:Inherit( self, BASE:New() ) -- #REPORT
self.Report = {}
Title = Title or ""
if Title then
self.Report[#self.Report+1] = Title
self.Title = Title
end
return self
end
--- Has the REPORT Text?
-- @param #REPORT self
-- @return #boolean
function REPORT:HasText() --R2.1
return #self.Report > 0
end
--- Set indent of a REPORT.
-- @param #REPORT self
-- @param #number Indent
-- @return #REPORT
function REPORT:SetIndent( Indent ) --R2.1
self.Indent = Indent
return self
end
--- Add a new line to a REPORT.
-- @param #REPORT self
-- @param #string Text
-- @return #REPORT
function REPORT:Add( Text )
self.Report[#self.Report+1] = Text
return self.Report[#self.Report]
return self
end
--- Add a new line to a REPORT.
-- @param #REPORT self
-- @param #string Text
-- @return #REPORT
function REPORT:AddIndent( Text ) --R2.1
self.Report[#self.Report+1] = string.rep(" ", self.Indent ) .. Text:gsub("\n","\n"..string.rep( " ", self.Indent ) )
return self
end
--- Produces the text of the report, taking into account an optional delimeter, which is \n by default.
@ -42,7 +73,7 @@ end
-- @return #string The report text.
function REPORT:Text( Delimiter )
Delimiter = Delimiter or "\n"
local ReportText = table.concat( self.Report, Delimiter ) or ""
local ReportText = ( self.Title ~= "" and self.Title .. Delimiter or self.Title ) .. table.concat( self.Report, Delimiter ) or ""
return ReportText
end
@ -81,9 +112,9 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
if EventData.IniObjectCategory == 1 then
local EventGroup = GROUP:Find( EventData.IniDCSGroup )
if EventGroup and self:HasGroup( EventGroup ) then
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup )
local MenuReporting = MENU_GROUP:New( EventGroup, "Missions Reports", self.CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Status Report", MenuReporting, self.ReportMissionsStatus, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Players Report", MenuReporting, self.ReportMissionsPlayers, self, EventGroup )
self:ReportSummary( EventGroup )
end
local PlayerUnit = EventData.IniUnit
@ -117,6 +148,21 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
end
)
-- Handle when a player leaves a slot and goes back to spectators ...
-- The PlayerUnit will be UnAssigned from the Task.
-- When there is no Unit left running the Task, the Task goes into Abort...
self:HandleEvent( EVENTS.MissionEnd,
--- @param #TASK self
-- @param Core.Event#EVENTDATA EventData
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:Stop()
end
end
)
-- Handle when a player leaves a slot and goes back to spectators ...
-- The PlayerUnit will be UnAssigned from the Task.
-- When there is no Unit left running the Task, the Task goes into Abort...
@ -127,7 +173,9 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:AbortUnit( PlayerUnit )
if Mission:IsENGAGED() then
Mission:AbortUnit( PlayerUnit )
end
end
end
)
@ -141,10 +189,15 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
Mission:CrashUnit( PlayerUnit )
local Mission = Mission -- Tasking.Mission#MISSION
if Mission:IsENGAGED() then
Mission:CrashUnit( PlayerUnit )
end
end
end
)
self:SetMenu()
return self
end
@ -203,12 +256,12 @@ function COMMANDCENTER:SetMenu()
self.CommandCenterMenu = self.CommandCenterMenu or MENU_COALITION:New( self.CommandCenterCoalition, "Command Center (" .. self:GetName() .. ")" )
local MenuTime = timer.getTime()
for MissionID, Mission in pairs( self:GetMissions() ) do
for MissionID, Mission in pairs( self:GetMissions() or {} ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:SetMenu( MenuTime )
end
for MissionID, Mission in pairs( self:GetMissions() ) do
for MissionID, Mission in pairs( self:GetMissions() or {} ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:RemoveMenu( MenuTime )
end
@ -219,7 +272,6 @@ end
-- @param #COMMANDCENTER self
-- @return Core.Menu#MENU_COALITION
function COMMANDCENTER:GetMenu()
self:F()
return self.CommandCenterMenu
end
@ -255,12 +307,9 @@ end
-- @param #string Message
-- @param Wrapper.Group#GROUP TaskGroup
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name )
function COMMANDCENTER:MessageToGroup( Message, TaskGroup )
local Prefix = "@ Group"
Prefix = Prefix .. ( Name and " (" .. Name .. "): " or '' )
Message = Prefix .. Message
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() )
self:GetPositionable():MessageToGroup( Message , 15, TaskGroup, self:GetName() )
end
@ -270,7 +319,8 @@ function COMMANDCENTER:MessageToCoalition( Message )
local CCCoalition = self:GetPositionable():GetCoalition()
--TODO: Fix coalition bug!
self:GetPositionable():MessageToCoalition( Message, 20, CCCoalition, self:GetName() )
self:GetPositionable():MessageToCoalition( Message, 15, CCCoalition )
end
@ -278,18 +328,37 @@ end
--- Report the status of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportSummary( ReportGroup )
function COMMANDCENTER:ReportMissionsStatus( ReportGroup )
self:E( ReportGroup )
local Report = REPORT:New()
Report:Add( "Status report of all missions." )
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportStatus() )
end
self:MessageToGroup( Report:Text(), ReportGroup )
end
--- Report the players of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportMissionsPlayers( ReportGroup )
self:E( ReportGroup )
local Report = REPORT:New()
Report:Add( "Players active in all missions." )
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportOverview() )
Report:Add( " - " .. Mission:ReportPlayers() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
self:MessageToGroup( Report:Text(), ReportGroup )
end
--- Report the status of a Task to a Group.
@ -305,6 +374,6 @@ function COMMANDCENTER:ReportDetails( ReportGroup, Task )
Report:Add( " - " .. Mission:ReportDetails() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
self:MessageToGroup( Report:Text(), ReportGroup )
end

View File

@ -76,6 +76,7 @@ do -- DETECTION MANAGER
self:SetReportInterval( 30 )
self:SetReportDisplayTime( 25 )
self:E( { Detection = Detection } )
Detection:__Start( 1 )
return self

View File

@ -12,6 +12,7 @@ MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
AssignedGroups = {},
}
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@ -26,35 +27,47 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM
self:SetStartState( "Idle" )
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self:AddTransition( "Idle", "Start", "Ongoing" )
self.CommandCenter = CommandCenter
CommandCenter:AddMission( self )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
self.Name = MissionName
self.MissionPriority = MissionPriority
self.MissionBriefing = MissionBriefing
self.MissionCoalition = MissionCoalition
self.Tasks = {}
self:SetStartState( "IDLE" )
self:AddTransition( "IDLE", "Start", "ENGAGED" )
--- OnLeave Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnLeaveIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
--- OnEnter Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnEnterIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnLeave Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnLeaveOngoing
--- OnLeave Transition Handler for State ENGAGED.
-- @function [parent=#MISSION] OnLeaveENGAGED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnEnterOngoing
--- OnEnter Transition Handler for State ENGAGED.
-- @function [parent=#MISSION] OnEnterENGAGED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@ -84,18 +97,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Stop", "Idle" )
self:AddTransition( "ENGAGED", "Stop", "IDLE" )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
--- OnLeave Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnLeaveIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
--- OnEnter Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnEnterIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@ -125,18 +138,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Complete", "Completed" )
self:AddTransition( "ENGAGED", "Complete", "COMPLETED" )
--- OnLeave Transition Handler for State Completed.
-- @function [parent=#MISSION] OnLeaveCompleted
--- OnLeave Transition Handler for State COMPLETED.
-- @function [parent=#MISSION] OnLeaveCOMPLETED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Completed.
-- @function [parent=#MISSION] OnEnterCompleted
--- OnEnter Transition Handler for State COMPLETED.
-- @function [parent=#MISSION] OnEnterCOMPLETED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@ -166,18 +179,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "*", "Fail", "Failed" )
self:AddTransition( "*", "Fail", "FAILED" )
--- OnLeave Transition Handler for State Failed.
-- @function [parent=#MISSION] OnLeaveFailed
--- OnLeave Transition Handler for State FAILED.
-- @function [parent=#MISSION] OnLeaveFAILED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Failed.
-- @function [parent=#MISSION] OnEnterFailed
--- OnEnter Transition Handler for State FAILED.
-- @function [parent=#MISSION] OnEnterFAILED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@ -207,56 +220,29 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self.CommandCenter = CommandCenter
CommandCenter:AddMission( self )
self.Name = MissionName
self.MissionPriority = MissionPriority
self.MissionBriefing = MissionBriefing
self.MissionCoalition = MissionCoalition
self.Tasks = {}
-- Private implementations
CommandCenter:SetMenu()
return self
end
-- FSM function for a MISSION
-- @param #MISSION self
-- @param #string From
-- @param #string Event
-- @param #string To
function MISSION:onbeforeComplete( From, Event, To )
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if not Task:IsStateSuccess() and not Task:IsStateFailed() and not Task:IsStateAborted() and not Task:IsStateCancelled() then
return false -- Mission cannot be completed. Other Tasks are still active.
end
end
return true -- Allow Mission completion.
end
-- FSM function for a MISSION
-- @param #MISSION self
-- @param #string From
-- @param #string Event
-- @param #string To
function MISSION:onenterCompleted( From, Event, To )
function MISSION:onenterCOMPLETED( From, Event, To )
self:GetCommandCenter():MessageToCoalition( "Mission " .. self:GetName() .. " has been completed! Good job guys!" )
self:GetCommandCenter():MessageToCoalition( self:GetName() .. " has been completed! Good job guys!" )
end
--- Gets the mission name.
-- @param #MISSION self
-- @return #MISSION self
function MISSION:GetName()
return self.Name
return string.format( 'Mission "%s (%s)"', self.Name, self.MissionPriority )
end
--- Add a Unit to join the Mission.
@ -279,6 +265,8 @@ function MISSION:JoinUnit( PlayerUnit, PlayerGroup )
end
end
self:GetCommandCenter():SetMenu()
return PlayerUnitAdded
end
@ -288,19 +276,17 @@ end
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @return #boolean true if Unit is part of a Task in the Mission.
-- @return #MISSION
function MISSION:AbortUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:AbortUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
local Task = Task -- Tasking.Task#TASK
local PlayerGroup = PlayerUnit:GetGroup()
Task:AbortGroup( PlayerGroup )
end
return PlayerUnitRemoved
return self
end
--- Handles a crash of a PlayerUnit from the Mission.
@ -309,19 +295,17 @@ end
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player crashing.
-- @return #boolean true if Unit is part of a Task in the Mission.
-- @return #MISSION
function MISSION:CrashUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:CrashUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
local Task = Task -- Tasking.Task#TASK
local PlayerGroup = PlayerUnit:GetGroup()
Task:CrashGroup( PlayerGroup )
end
return PlayerUnitRemoved
return self
end
--- Add a scoring to the mission.
@ -365,7 +349,7 @@ end
-- @param #MISSION self
-- @param #number MenuTime
function MISSION:SetMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for _, TaskData in pairs( self:GetTasks() ) do
local Task = TaskData -- Tasking.Task#TASK
@ -377,7 +361,7 @@ end
-- @param #MISSION self
-- @param #number MenuTime
function MISSION:RemoveMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for _, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
@ -386,6 +370,59 @@ function MISSION:RemoveMenu( MenuTime )
end
do -- Group Assignment
--- Returns if the @{Mission} is assigned to the Group.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #boolean
function MISSION:IsGroupAssigned( MissionGroup )
local MissionGroupName = MissionGroup:GetName()
if self.AssignedGroups[MissionGroupName] == MissionGroup then
self:T( { "Mission is assigned to:", MissionGroup:GetName() } )
return true
end
self:T( { "Mission is not assigned to:", MissionGroup:GetName() } )
return false
end
--- Set @{Group} assigned to the @{Mission}.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION
function MISSION:SetGroupAssigned( MissionGroup )
local MissionName = self:GetName()
local MissionGroupName = MissionGroup:GetName()
self.AssignedGroups[MissionGroupName] = MissionGroup
self:E( string.format( "Mission %s is assigned to %s", MissionName, MissionGroupName ) )
return self
end
--- Clear the @{Group} assignment from the @{Mission}.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION
function MISSION:ClearGroupAssignment( MissionGroup )
local MissionName = self:GetName()
local MissionGroupName = MissionGroup:GetName()
self.AssignedGroups[MissionGroupName] = nil
self:E( string.format( "Mission %s is unassigned to %s", MissionName, MissionGroupName ) )
return self
end
end
--- Gets the COMMANDCENTER.
-- @param #MISSION self
-- @return Tasking.CommandCenter#COMMANDCENTER
@ -406,20 +443,37 @@ end
--- Gets the mission menu for the coalition.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return Core.Menu#MENU_COALITION self
function MISSION:GetMenu( TaskGroup )
function MISSION:GetMenu( TaskGroup ) -- R2.1 -- Changed Menu Structure
local CommandCenter = self:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionName = self:GetName()
local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
--local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
return MissionMenu
self.MissionMenu = self.MissionMenu or {}
self.MissionMenu[TaskGroup] = self.MissionMenu[TaskGroup] or {}
local Menu = self.MissionMenu[TaskGroup]
Menu.MainMenu = Menu.MainMenu or MENU_GROUP:New( TaskGroup, self:GetName(), CommandCenterMenu )
Menu.BriefingMenu = Menu.BriefingMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Mission Briefing", Menu.MainMenu, self.MenuReportBriefing, self, TaskGroup )
Menu.ReportsMenu = Menu.ReportsMenu or MENU_GROUP:New( TaskGroup, "Reports", Menu.MainMenu )
Menu.ReportTasksMenu = Menu.ReportTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Tasks", Menu.ReportsMenu, self.MenuReportSummary, self, TaskGroup )
Menu.ReportPlannedTasksMenu = Menu.ReportPlannedTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Planned Tasks", Menu.ReportsMenu, self.MenuReportOverview, self, TaskGroup, "Planned" )
Menu.ReportAssignedTasksMenu = Menu.ReportAssignedTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Assigned Tasks", Menu.ReportsMenu, self.MenuReportOverview, self, TaskGroup, "Assigned" )
Menu.ReportSuccessTasksMenu = Menu.ReportSuccessTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Successful Tasks", Menu.ReportsMenu, self.MenuReportOverview, self, TaskGroup, "Success" )
Menu.ReportFailedTasksMenu = Menu.ReportFailedTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Failed Tasks", Menu.ReportsMenu, self.MenuReportOverview, self, TaskGroup, "Failed" )
Menu.ReportHeldTasksMenu = Menu.ReportHeldTasksMenu or MENU_GROUP_COMMAND:New( TaskGroup, "Report Held Tasks", Menu.ReportsMenu, self.MenuReportOverview, self, TaskGroup, "Hold" )
return Menu.MainMenu
end
--- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions.
-- @param #string TaskName The Name of the @{Task} within the @{Mission}.
-- @return Tasking.Task#TASK The Task
@ -490,39 +544,39 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n
end
--- Is the @{Mission} **Completed**.
--- Is the @{Mission} **COMPLETED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsCompleted()
return self:Is( "Completed" )
function MISSION:IsCOMPLETED()
return self:Is( "COMPLETED" )
end
--- Is the @{Mission} **Idle**.
--- Is the @{Mission} **IDLE**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsIdle()
return self:Is( "Idle" )
function MISSION:IsIDLE()
return self:Is( "IDLE" )
end
--- Is the @{Mission} **Ongoing**.
--- Is the @{Mission} **ENGAGED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing()
return self:Is( "Ongoing" )
function MISSION:IsENGAGED()
return self:Is( "ENGAGED" )
end
--- Is the @{Mission} **Failed**.
--- Is the @{Mission} **FAILED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsFailed()
return self:Is( "Failed" )
function MISSION:IsFAILED()
return self:Is( "FAILED" )
end
--- Is the @{Mission} **Hold**.
--- Is the @{Mission} **HOLD**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsHold()
return self:Is( "Hold" )
function MISSION:IsHOLD()
return self:Is( "HOLD" )
end
--- Validates if the Mission has a Group
@ -542,6 +596,153 @@ function MISSION:HasGroup( TaskGroup )
return Has
end
--- @param #MISSION self
-- @return #number
function MISSION:GetTasksRemaining()
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:IsStateSuccess() or Task:IsStateFailed() then
else
TasksRemaining = TasksRemaining + 1
end
end
return TasksRemaining
end
--- @param #MISSION self
-- @return #number
function MISSION:GetTaskTypes()
-- Determine how many tasks are remaining.
local TaskTypeList = {}
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
local TaskType = Task:GetType()
TaskTypeList[TaskType] = TaskType
end
return TaskTypeList
end
--- Create a briefing report of the Mission.
-- @param #MISSION self
-- @return #string
function MISSION:ReportBriefing()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( "Mission " .. Name .. " - " .. Status .. " - Briefing Report." )
Report:Add( self.MissionBriefing )
return Report:Text()
end
--- Create a status report of the Mission.
-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.
--
-- Mission "<MissionName>" - Status "<MissionStatus>"
-- - Task Types: <TaskType>, <TaskType>
-- - <xx> Planned Tasks (xp)
-- - <xx> Assigned Tasks(xp)
-- - <xx> Success Tasks (xp)
-- - <xx> Hold Tasks (xp)
-- - <xx> Cancelled Tasks (xp)
-- - <xx> Aborted Tasks (xp)
-- - <xx> Failed Tasks (xp)
--
-- @param #MISSION self
-- @return #string
function MISSION:ReportStatus()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
local TaskTypes = self:GetTaskTypes()
Report:Add( string.format( " - Task Types: %s", table.concat(TaskTypes, ", " ) ) )
local TaskStatusList = { "Planned", "Assigned", "Success", "Hold", "Cancelled", "Aborted", "Failed" }
for TaskStatusID, TaskStatus in pairs( TaskStatusList ) do
local TaskCount = 0
local TaskPlayerCount = 0
-- Determine how many tasks are remaining.
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:Is( TaskStatus ) then
TaskCount = TaskCount + 1
TaskPlayerCount = TaskPlayerCount + Task:GetPlayerCount()
end
end
if TaskCount > 0 then
Report:Add( string.format( " - %02d %s Tasks (%dp)", TaskCount, TaskStatus, TaskPlayerCount ) )
end
end
return Report:Text()
end
--- Create a player report of the Mission.
-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.
--
-- Mission "<MissionName>" - Status "<MissionStatus>"
-- - Player "<PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
-- - Player <PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
-- - ..
--
-- @param #MISSION self
-- @return #string
function MISSION:ReportPlayers()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
local PlayerList = {}
-- Determine how many tasks are remaining.
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
local PlayerNames = Task:GetPlayerNames()
for PlayerID, PlayerName in pairs( PlayerNames ) do
PlayerList[PlayerName] = Task:GetName()
end
end
for PlayerName, TaskName in pairs( PlayerList ) do
Report:Add( string.format( ' - Player (%s): Task "%s"', PlayerName, TaskName ) )
end
return Report:Text()
end
--- Create a summary report of the Mission (one line).
-- @param #MISSION self
-- @return #string
@ -554,18 +755,15 @@ function MISSION:ReportSummary()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( "Mission " .. Name .. " - " .. Status .. " - " .. TasksRemaining .. " tasks remaining." )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:IsStateSuccess() or Task:IsStateFailed() then
else
TasksRemaining = TasksRemaining + 1
end
Report:Add( "- " .. Task:ReportSummary() )
end
Report:Add( "Mission " .. Name .. " - " .. Status .. " - " .. TasksRemaining .. " tasks remaining." )
return Report:Text()
end
@ -573,7 +771,7 @@ end
--- Create a overview report of the Mission (multiple lines).
-- @param #MISSION self
-- @return #string
function MISSION:ReportOverview()
function MISSION:ReportOverview( TaskStatus )
local Report = REPORT:New()
@ -582,14 +780,17 @@ function MISSION:ReportOverview()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( "Mission " .. Name .. " - State '" .. Status .. "'" )
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
Report:Add( "- " .. Task:ReportSummary() )
if Task:Is( TaskStatus ) then
Report:Add( "\n - " .. Task:ReportOverview() )
end
end
return Report:Text()
@ -608,7 +809,7 @@ function MISSION:ReportDetails()
-- Determine the status of the mission.
local Status = self:GetState()
Report:Add( "Mission " .. Name .. " - State '" .. Status .. "'" )
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
@ -627,9 +828,33 @@ end
-- Tasks = Mission:GetTasks()
-- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" )
function MISSION:GetTasks()
self:F()
return self.Tasks
end
function MISSION:MenuReportBriefing( ReportGroup )
local Report = self:ReportBriefing()
self:GetCommandCenter():MessageToGroup( Report, ReportGroup )
end
--- @param #MISSION self
-- @param Wrapper.Group#GROUP ReportGroup
function MISSION:MenuReportSummary( ReportGroup )
local Report = self:ReportSummary()
self:GetCommandCenter():MessageToGroup( Report, ReportGroup )
end
--- @param #MISSION self
-- @param #string TaskStatus The status
-- @param Wrapper.Group#GROUP ReportGroup
function MISSION:MenuReportOverview( ReportGroup, TaskStatus )
local Report = self:ReportOverview( TaskStatus )
self:GetCommandCenter():MessageToGroup( Report, ReportGroup )
end

View File

@ -78,6 +78,7 @@ TASK = {
Mission = nil,
CommandCenter = nil,
TimeOut = 0,
AssignedGroups = {},
}
--- FSM PlayerAborted event handler prototype for TASK.
@ -156,14 +157,15 @@ TASK = {
-- @param #string TaskName The name of the Task
-- @param #string TaskType The type of the Task
-- @return #TASK self
function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
local self = BASE:Inherit( self, FSM_TASK:New() ) -- Core.Fsm#FSM_TASK
local self = BASE:Inherit( self, FSM_TASK:New() ) -- Tasking.Task#TASK
self:SetStartState( "Planned" )
self:AddTransition( "Planned", "Assign", "Assigned" )
self:AddTransition( "Assigned", "AssignUnit", "Assigned" )
self:AddTransition( "Assigned", "Success", "Success" )
self:AddTransition( "Assigned", "Hold", "Hold" )
self:AddTransition( "Assigned", "Fail", "Failed" )
self:AddTransition( "Assigned", "Abort", "Aborted" )
self:AddTransition( "Assigned", "Cancel", "Cancelled" )
@ -187,10 +189,11 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
self:SetName( TaskName )
self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences ..
self.TaskBriefing = "You are invited for the task: " .. self.TaskName .. "."
self:SetBriefing( TaskBriefing )
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
self.TaskInfo = {}
return self
end
@ -216,7 +219,7 @@ function TASK:SetUnitProcess( FsmTemplate )
end
--- Add a PlayerUnit to join the Task.
-- For each Group within the Task, the Unit is check if it can join the Task.
-- For each Group within the Task, the Unit is checked if it can join the Task.
-- If the Unit was not part of the Task, false is returned.
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
@ -240,9 +243,9 @@ function TASK:JoinUnit( PlayerUnit, PlayerGroup )
--self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() )
end
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
self:AssignToUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " joined Task " .. self:GetName() )
end
@ -257,14 +260,11 @@ end
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task.
-- @return #boolean true if Unit is part of the Task.
function TASK:AbortUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitAborted = false
-- @return #TASK
function TASK:AbortGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } )
local PlayerGroups = self:GetGroups()
local PlayerGroup = PlayerUnit:GetGroup()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
@ -272,23 +272,39 @@ function TASK:AbortUnit( PlayerUnit )
-- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task.
-- If the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group.
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
self:UnAssignFromUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " aborted Task " .. self:GetName() )
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
if #PlayerGroup:GetUnits() == 1 then
self:UnAssignFromGroup( PlayerGroup )
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
self:RemoveMenuForGroup( PlayerGroup )
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
self:MessageToGroups( PlayerName .. " aborted Task " .. self:GetName() )
self:UnAssignFromGroup( PlayerGroup )
--self:Abort()
-- Now check if the task needs to go to hold...
-- It will go to hold, if there are no players in the mission...
PlayerGroups:Flush()
local IsRemaining = false
for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do
if self:IsGroupAssigned( AssignedGroup ) == true then
IsRemaining = true
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
break
end
end
self:Abort()
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
if IsRemaining == false then
self:Abort()
end
self:PlayerAborted( PlayerGroup:GetUnit(1) )
end
end
end
return PlayerUnitAborted
return self
end
--- A PlayerUnit crashed in a Task. Abort the Player.
@ -296,14 +312,11 @@ end
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task.
-- @return #boolean true if Unit is part of the Task.
function TASK:CrashUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitCrashed = false
-- @return #TASK
function TASK:CrashGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } )
local PlayerGroups = self:GetGroups()
local PlayerGroup = PlayerUnit:GetGroup()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
@ -311,22 +324,38 @@ function TASK:CrashUnit( PlayerUnit )
-- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task.
-- If the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group.
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
self:UnAssignFromUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " crashed in Task " .. self:GetName() )
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
if #PlayerGroup:GetUnits() == 1 then
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
self:RemoveMenuForGroup( PlayerGroup )
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
self:MessageToGroups( PlayerName .. " crashed! " )
self:UnAssignFromGroup( PlayerGroup )
-- Now check if the task needs to go to hold...
-- It will go to hold, if there are no players in the mission...
PlayerGroups:Flush()
local IsRemaining = false
for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do
if self:IsGroupAssigned( AssignedGroup ) == true then
IsRemaining = true
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
break
end
end
self:PlayerCrashed( PlayerUnit )
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
if IsRemaining == false then
self:Abort()
end
self:PlayerCrashed( PlayerGroup:GetUnit(1) )
end
end
end
return PlayerUnitCrashed
return self
end
@ -347,46 +376,156 @@ function TASK:GetGroups()
return self.SetGroup
end
do -- Group Assignment
--- Assign the @{Task} to a @{Group}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:AssignToGroup( TaskGroup )
self:F2( TaskGroup:GetName() )
--- Returns if the @{Task} is assigned to the Group.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #boolean
function TASK:IsGroupAssigned( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
TaskGroup:SetState( TaskGroup, "Assigned", self )
local Mission = self:GetMission()
local MissionMenu = Mission:GetMenu( TaskGroup )
MissionMenu:RemoveSubMenus()
--self:RemoveMenuForGroup( TaskGroup )
self:SetAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
self:E(PlayerName)
if PlayerName ~= nil or PlayerName ~= "" then
self:AssignToUnit( TaskUnit )
local TaskGroupName = TaskGroup:GetName()
if self.AssignedGroups[TaskGroupName] then
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
return true
end
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
return false
end
--- Set @{Group} assigned to the @{Task}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:SetGroupAssigned( TaskGroup )
local TaskName = self:GetName()
local TaskGroupName = TaskGroup:GetName()
self.AssignedGroups[TaskGroupName] = TaskGroup
self:E( string.format( "Task %s is assigned to %s", TaskName, TaskGroupName ) )
-- Set the group to be assigned at mission level. This allows to decide the menu options on mission level for this group.
self:GetMission():SetGroupAssigned( TaskGroup )
local SetAssignedGroups = self:GetGroups()
-- SetAssignedGroups:ForEachGroup(
-- function( AssignedGroup )
-- if self:IsGroupAssigned(AssignedGroup) then
-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to group %s.", TaskName, TaskGroupName ), AssignedGroup )
-- else
-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to your group.", TaskName ), AssignedGroup )
-- end
-- end
-- )
return self
end
--- Clear the @{Group} assignment from the @{Task}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:ClearGroupAssignment( TaskGroup )
local TaskName = self:GetName()
local TaskGroupName = TaskGroup:GetName()
self.AssignedGroups[TaskGroupName] = nil
self:E( string.format( "Task %s is unassigned to %s", TaskName, TaskGroupName ) )
-- Set the group to be assigned at mission level. This allows to decide the menu options on mission level for this group.
self:GetMission():ClearGroupAssignment( TaskGroup )
local SetAssignedGroups = self:GetGroups()
SetAssignedGroups:ForEachGroup(
function( AssignedGroup )
if self:IsGroupAssigned(AssignedGroup) then
self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is unassigned from group %s.", TaskName, TaskGroupName ), AssignedGroup )
else
self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is unassigned from your group.", TaskName ), AssignedGroup )
end
end
)
return self
end
return self
end
do -- Group Assignment
--- Assign the @{Task} to a @{Group}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:AssignToGroup( TaskGroup )
self:F( TaskGroup:GetName() )
local TaskGroupName = TaskGroup:GetName()
local Mission = self:GetMission()
local CommandCenter = Mission:GetCommandCenter()
self:SetGroupAssigned( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
self:E(PlayerName)
if PlayerName ~= nil or PlayerName ~= "" then
self:AssignToUnit( TaskUnit )
CommandCenter:MessageToGroup(
string.format( 'Task "%s": Briefing for player (%s):\n%s',
self:GetName(),
PlayerName,
self:GetBriefing()
), TaskGroup
)
end
end
CommandCenter:SetMenu()
return self
end
--- UnAssign the @{Task} from a @{Group}.
-- @param #TASK self
function TASK:UnAssignFromGroup( TaskGroup )
self:F2( { TaskGroup } )
self:ClearGroupAssignment( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:UnAssignFromUnit( TaskUnit )
end
end
local Mission = self:GetMission()
local CommandCenter = Mission:GetCommandCenter()
CommandCenter:SetMenu()
end
end
---
-- @param #TASK self
-- @param Wrapper.Group#GROUP FindGroup
-- @return #boolean
function TASK:HasGroup( FindGroup )
return self:GetGroups():IsIncludeObject( FindGroup )
local SetAttackGroup = self:GetGroups()
return SetAttackGroup:FindGroup(FindGroup)
end
@ -455,7 +594,7 @@ function TASK:SendBriefingToAssignedGroups()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsAssignedToGroup( TaskGroup ) then
if self:IsGroupAssigned( TaskGroup ) then
TaskGroup:Message( self.TaskBriefing, 60 )
end
end
@ -468,50 +607,14 @@ function TASK:UnAssignFromGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
self:UnAssignFromGroup( TaskGroup )
end
end
--- UnAssign the @{Task} from a @{Group}.
-- @param #TASK self
function TASK:UnAssignFromGroup( TaskGroup )
self:F2( { TaskGroup } )
TaskGroup:SetState( TaskGroup, "Assigned", nil )
self:RemoveAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:UnAssignFromUnit( TaskUnit )
if self:IsGroupAssigned(TaskGroup) then
self:UnAssignFromGroup( TaskGroup )
end
end
end
--- Returns if the @{Task} is assigned to the Group.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #boolean
function TASK:IsAssignedToGroup( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
if self:IsStateAssigned() then
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
return true
end
end
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
return false
end
--- Returns if the @{Task} has still alive and assigned Units.
-- @param #TASK self
-- @return #boolean
@ -520,7 +623,7 @@ function TASK:HasAliveUnits()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsStateAssigned() then
if self:IsAssignedToGroup( TaskGroup ) then
if self:IsGroupAssigned( TaskGroup ) then
for TaskUnitID, TaskUnit in pairs( TaskGroup:GetUnits() ) do
if TaskUnit:IsAlive() then
self:T( { HasAliveUnits = true } )
@ -539,14 +642,19 @@ end
-- @param #TASK self
-- @param #number MenuTime
-- @return #TASK
function TASK:SetMenu( MenuTime )
self:F()
function TASK:SetMenu( MenuTime ) --R2.1 Mission Reports and Task Reports added. Fixes issue #424.
self:F( { self:GetName(), MenuTime } )
self.SetGroup:Flush()
--self.SetGroup:Flush()
for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
if self:IsStatePlanned() or self:IsStateReplanned() then
-- Set Mission Menus
local Mission = self:GetMission()
local MissionMenu = Mission:GetMenu( TaskGroup )
if MissionMenu then
self:SetMenuForGroup( TaskGroup, MenuTime )
end
end
@ -561,12 +669,9 @@ end
-- @return #TASK
function TASK:SetMenuForGroup( TaskGroup, MenuTime )
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName(), MenuTime )
else
if not self:IsAssignedToGroup( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
end
self:SetPlannedMenuForGroup( TaskGroup, MenuTime )
if self:IsGroupAssigned( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
end
end
@ -577,7 +682,7 @@ end
-- @param #string MenuText The menu text.
-- @param #number MenuTime
-- @return #TASK self
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime )
self:E( TaskGroup:GetName() )
local Mission = self:GetMission()
@ -585,14 +690,27 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskType = self:GetType()
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"]
-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "■", TaskThreatLevel ) .. "]" or " []"
local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = Mission:GetMenu( TaskGroup )
--local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
--local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskPlannedMenu = MENU_GROUP:New( TaskGroup, "Planned Tasks", MissionMenu ):SetTime( MenuTime )
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, TaskPlannedMenu ):SetTime( MenuTime ):SetRemoveParent( true )
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskText, TaskTypeMenu ):SetTime( MenuTime ):SetRemoveParent( true )
local ReportTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskTypeMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
if not Mission:IsGroupAssigned( TaskGroup ) then
local JoinTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Join Task" ), TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
end
return self
end
@ -603,15 +721,28 @@ end
-- @param #number MenuTime
-- @return #TASK self
function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime )
self:E( TaskGroup:GetName() )
self:F( { TaskGroup:GetName(), MenuTime } )
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local TaskType = self:GetType()
-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"]
-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "■", TaskThreatLevel ) .. "]" or " []"
local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = Mission:GetMenu( TaskGroup )
-- local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
-- local MissionMenu = Mission:GetMenu( TaskGroup )
self:E( { MissionMenu = MissionMenu } )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime )
local TaskAssignedMenu = MENU_GROUP:New( TaskGroup, string.format( "Assigned Task %s", TaskName ), MissionMenu ):SetTime( MenuTime )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskAssignedMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Abort Group from Task" ), TaskAssignedMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
return self
end
@ -621,14 +752,12 @@ end
-- @param #number MenuTime
-- @return #TASK
function TASK:RemoveMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
if not self:IsAssignedToGroup( TaskGroup ) then
self:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
end
self:RefreshMenus( TaskGroup, MenuTime )
end
end
end
@ -639,24 +768,26 @@ end
-- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime
-- @return #TASK self
function TASK:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
self:F()
function TASK:RefreshMenus( TaskGroup, MenuTime )
self:F( { TaskGroup:GetName(), MenuTime } )
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskName = self:GetName()
local PlannedMenu = MissionMenu:GetMenu( "Planned Tasks" )
local AssignedMenu = MissionMenu:GetMenu( string.format( "Assigned Task %s", TaskName ) )
if MissionMenu then
local TaskType = self:GetType()
local TypeMenu = MissionMenu:GetMenu( TaskType )
if TypeMenu then
local TaskMenu = TypeMenu:GetMenu( self:GetTaskName() )
if TaskMenu then
TaskMenu:Remove( MenuTime )
end
end
if PlannedMenu then
PlannedMenu:Remove( MenuTime )
end
if AssignedMenu then
AssignedMenu:Remove( MenuTime )
end
end
@ -705,7 +836,7 @@ end
-- @param #TASK self
function TASK:MenuTaskAbort( TaskGroup )
self:Abort()
self:AbortGroup( TaskGroup )
end
@ -717,6 +848,13 @@ function TASK:GetTaskName()
return self.TaskName
end
--- Returns the @{Task} briefing.
-- @param #TASK self
-- @return #string Task briefing.
function TASK:GetTaskBriefing()
return self.TaskBriefing
end
@ -776,11 +914,14 @@ end
function TASK:RemoveStateMachine( TaskUnit )
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
self:E( self.Fsm )
for TaskUnitT, Fsm in pairs( self.Fsm ) do
self:E( TaskUnitT )
end
--self:E( self.Fsm )
--for TaskUnitT, Fsm in pairs( self.Fsm ) do
--local Fsm = Fsm -- Core.Fsm#FSM_PROCESS
--self:E( TaskUnitT )
--self.Fsm[TaskUnit] = nil
--end
self.Fsm[TaskUnit]:Remove()
self.Fsm[TaskUnit] = nil
collectgarbage()
@ -838,6 +979,14 @@ function TASK:SetType( TaskType )
self.TaskType = TaskType
end
--- Sets the Information on the Task
-- @param #TASK self
-- @param #string TaskInfo
function TASK:SetInfo( TaskInfo, TaskInfoText )
self.TaskInfo[TaskInfo] = TaskInfoText
end
--- Gets the Type of the Task
-- @param #TASK self
-- @return #string TaskType
@ -975,10 +1124,18 @@ end
-- @param #string TaskBriefing
-- @return #TASK self
function TASK:SetBriefing( TaskBriefing )
self:E(TaskBriefing)
self.TaskBriefing = TaskBriefing
return self
end
--- Gets the @{Task} briefing.
-- @param #TASK self
-- @return #string The briefing text.
function TASK:GetBriefing()
return self.TaskBriefing
end
@ -991,14 +1148,17 @@ function TASK:onenterAssigned( From, Event, To, PlayerUnit, PlayerName )
self:E( { "Task Assigned", self.Dispatcher } )
self:MessageToGroups( "Task " .. self:GetName() .. " has been assigned to your group." )
if self.Dispatcher then
self:E( "Firing Assign event " )
self.Dispatcher:Assign( self, PlayerUnit, PlayerName )
if From ~= "Assigned" then
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is assigned." )
if self.Dispatcher then
self:E( "Firing Assign event " )
self.Dispatcher:Assign( self, PlayerUnit, PlayerName )
end
self:GetMission():__Start( 1 )
self:SetMenu()
end
self:GetMission():__Start( 1 )
end
@ -1014,7 +1174,7 @@ function TASK:onenterSuccess( From, Event, To )
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is successful! Good job!" )
self:UnAssignFromGroups()
self:GetMission():__Complete( 1 )
--self:GetMission():__Complete( 1 )
end
@ -1027,12 +1187,13 @@ end
function TASK:onenterAborted( From, Event, To )
self:E( "Task Aborted" )
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " has been aborted! Task may be replanned." )
self:UnAssignFromGroups()
if From ~= "Aborted" then
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " has been aborted! Task may be replanned." )
self:__Replan( 5 )
self:SetMenu()
end
self:__Replan( 5 )
end
--- FSM function for a TASK
@ -1072,7 +1233,7 @@ end
function TASK:onstatechange( From, Event, To )
if self:IsTrace() then
MESSAGE:New( "@ Task " .. self.TaskName .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
--MESSAGE:New( "@ Task " .. self.TaskName .. " : " .. From .. " changed to " .. To .. " by " .. Event, 2 ):ToAll()
end
if self.Scores[To] then
@ -1127,7 +1288,7 @@ do -- Reporting
-- List the Task Name and Status
-- @param #TASK self
-- @return #string
function TASK:ReportSummary()
function TASK:ReportSummary() --R2.1 fixed report. Now nicely formatted and contains the info required.
local Report = REPORT:New()
@ -1142,12 +1303,11 @@ function TASK:ReportSummary()
return Report:Text()
end
--- Create a detailed report of the Task.
-- List the Task Status, and the Players assigned to the Task.
--- Create an overiew report of the Task.
-- List the Task Name and Status
-- @param #TASK self
-- @return #string
function TASK:ReportDetails()
function TASK:ReportOverview() --R2.1 fixed report. Now nicely formatted and contains the info required.
local Report = REPORT:New()
@ -1157,19 +1317,89 @@ function TASK:ReportDetails()
-- Determine the status of the Task.
local State = self:GetState()
local Detection = self.TaskInfo["Detection"] and " - " .. self.TaskInfo["Detection"] or ""
Report:Add( "Task " .. Name .. Detection )
return Report:Text()
end
--- Create a count of the players in the Task.
-- @param #TASK self
-- @return #number The total number of players in the task.
function TASK:GetPlayerCount() --R2.1 Get a count of the players.
local PlayerCount = 0
-- Loop each Unit active in the Task, and find Player Names.
local PlayerNames = {}
local PlayerReport = REPORT:New( " - Players:" )
for PlayerGroupID, PlayerGroupData in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroupData -- Wrapper.Group#GROUP
PlayerNames = PlayerGroup:GetPlayerNames()
if PlayerNames then
PlayerReport:Add( " -- Group " .. PlayerGroup:GetCallsign() .. ": " .. table.concat( PlayerNames, ", " ) )
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then
local PlayerNames = PlayerGroup:GetPlayerNames()
PlayerCount = PlayerCount + #PlayerNames
end
end
return PlayerCount
end
--- Create a list of the players in the Task.
-- @param #TASK self
-- @return #map<#string,Wrapper.Group#GROUP> A map of the players
function TASK:GetPlayerNames() --R2.1 Get a map of the players.
local PlayerNameMap = {}
-- Loop each Unit active in the Task, and find Player Names.
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then
local PlayerNames = PlayerGroup:GetPlayerNames()
for PlayerNameID, PlayerName in pairs( PlayerNames ) do
PlayerNameMap[PlayerName] = PlayerGroup
end
end
end
return PlayerNameMap
end
--- Create a detailed report of the Task.
-- List the Task Status, and the Players assigned to the Task.
-- @param #TASK self
-- @return #string
function TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and contains the info required.
local Report = REPORT:New():SetIndent( 3 )
-- List the name of the Task.
local Name = self:GetName()
-- Determine the status of the Task.
local State = self:GetState()
-- Loop each Unit active in the Task, and find Player Names.
local PlayerNames = self:GetPlayerNames()
local PlayerReport = REPORT:New()
for PlayerName, PlayerGroup in pairs( PlayerNames ) do
PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. PlayerName )
end
local Players = PlayerReport:Text()
local Detection = self.TaskInfo["Detection"] or ""
local Changes = self.TaskInfo["Changes"] or ""
Report:Add( "Task: " .. Name .. " - " .. State .. " - Detailed Report" )
Report:Add( "\n - Players:" )
Report:AddIndent( Players )
Report:Add( "\n - Detection:" )
Report:AddIndent( Detection )
Report:Add( "\n - Detection Changes:" )
Report:AddIndent( Changes )
-- Loop each Process in the Task, and find Reporting Details.
Report:Add( string.format( " - Task %s\n -- State '%s'\n%s", Name, State, PlayerReport:Text() ) )
return Report:Text()
end

View File

@ -86,15 +86,13 @@ do -- TASK_A2G
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_A2G self
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- Tasking.Task#TASK_A2G
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType, TaskBriefing )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2G
self:F()
self.TargetSetUnit = TargetSetUnit
self.TaskType = TaskType
Mission:AddTask( self )
local Fsm = self:GetUnitProcess()
@ -132,7 +130,7 @@ do -- TASK_A2G
if Task:GetRendezVousZone( TaskUnit ) then
self:__RouteToRendezVousZone( 0.1 )
else
if Task:GetRendezVousPointVec2( TaskUnit ) then
if Task:GetRendezVousCoordinate( TaskUnit ) then
self:__RouteToRendezVousPoint( 0.1 )
else
self:__ArriveAtRendezVous( 0.1 )
@ -175,9 +173,9 @@ do -- TASK_A2G
else
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
local PointVec2 = TargetUnit:GetPointVec2()
self:T( { TargetPointVec2 = PointVec2, PointVec2:GetX(), PointVec2:GetAlt(), PointVec2:GetZ() } )
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
local Coordinate = TargetUnit:GetCoordinate()
self:T( { TargetCoordinate = Coordinate, Coordinate:GetX(), Coordinate:GetAlt(), Coordinate:GetZ() } )
Task:SetTargetCoordinate( TargetUnit:GetCoordinate(), TaskUnit )
end
self:__RouteToTargetPoint( 0.1 )
end
@ -191,7 +189,7 @@ do -- TASK_A2G
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
Task:SetTargetPointVec2( TargetUnit:GetPointVec2(), TaskUnit )
Task:SetTargetCoordinate( TargetUnit:GetCoordinate(), TaskUnit )
end
self:__RouteToTargets( -10 )
end
@ -206,28 +204,28 @@ do -- TASK_A2G
end
--- @param #TASK_A2G self
-- @param Core.Point#POINT_VEC2 RendezVousPointVec2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetRendezVousPointVec2( RendezVousPointVec2, RendezVousRange, TaskUnit )
function TASK_A2G:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteRendezVous:SetPointVec2( RendezVousPointVec2 )
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
ActRouteRendezVous:SetRange( RendezVousRange )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#POINT_VEC2 The PointVec2 object referencing to the 2D point where the RendezVous point is located on the map.
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
function TASK_A2G:GetRendezVousPointVec2( TaskUnit )
function TASK_A2G:GetRendezVousCoordinate( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteRendezVous:GetPointVec2(), ActRouteRendezVous:GetRange()
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
end
@ -255,26 +253,26 @@ do -- TASK_A2G
end
--- @param #TASK_A2G self
-- @param Core.Point#POINT_VEC2 TargetPointVec2 The PointVec2 object where the Target is located on the map.
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2G:SetTargetPointVec2( TargetPointVec2, TaskUnit )
function TASK_A2G:SetTargetCoordinate( TargetCoordinate, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteTarget:SetPointVec2( TargetPointVec2 )
ActRouteTarget:SetCoordinate( TargetCoordinate )
end
--- @param #TASK_A2G self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#POINT_VEC2 The PointVec2 object where the Target is located on the map.
function TASK_A2G:GetTargetPointVec2( TaskUnit )
-- @return Core.Point#COORDINATE The Coordinate object where the Target is located on the map.
function TASK_A2G:GetTargetCoordinate( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteTarget:GetPointVec2()
return ActRouteTarget:GetCoordinate()
end
@ -366,14 +364,28 @@ do -- TASK_SEAD
--- Instantiates a new TASK_SEAD.
-- @param #TASK_SEAD self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT TargetSetUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD" ) ) -- #TASK_SEAD
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD", TaskBriefing ) ) -- #TASK_SEAD
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Suppression of Enemy Air Defenses.\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end
@ -392,17 +404,28 @@ do -- TASK_BAI
--- Instantiates a new TASK_BAI.
-- @param #TASK_BAI self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_BAI self
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI" ) ) -- #TASK_BAI
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI", TaskBriefing ) ) -- #TASK_BAI
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Battlefield Air Interdiction of a group of enemy targets.\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end
@ -421,17 +444,29 @@ do -- TASK_CAS
--- Instantiates a new TASK_CAS.
-- @param #TASK_CAS self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_CAS self
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS" ) ) -- #TASK_CAS
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS", TaskBriefing ) ) -- #TASK_CAS
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Close Air Support for a group of enemy targets.\n" ..
"Beware of friendlies at the vicinity!\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end

View File

@ -55,6 +55,7 @@ do -- TASK_A2G_DISPATCHER
ClassName = "TASK_A2G_DISPATCHER",
Mission = nil,
Detection = nil,
Tasks = {},
}
@ -72,6 +73,8 @@ do -- TASK_A2G_DISPATCHER
self.Detection = Detection
self.Mission = Mission
self.Detection:FilterCategories( Unit.Category.GROUND_UNIT, Unit.Category.SHIP )
self:AddTransition( "Started", "Assign", "Started" )
--- OnAfter Transition Handler for Event Assign.
@ -179,14 +182,16 @@ do -- TASK_A2G_DISPATCHER
-- @param #TASK_A2G_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @param #boolean DetectedItemID
-- @param #boolean DetectedItemChange
-- @return Tasking.Task#TASK
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItem )
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItemID, DetectedItemChanged )
if Task then
if Task:IsStatePlanned() and DetectedItem.Changed == true then
if Task:IsStatePlanned() and DetectedItemChanged == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Task = Mission:RemoveTask( Task )
Mission:RemoveTask( Task )
self.Tasks[DetectedItemID] = nil
end
end
@ -206,94 +211,78 @@ do -- TASK_A2G_DISPATCHER
local ChangeMsg = {}
local Mission = self.Mission
local ReportSEAD = REPORT:New( "- SEAD Tasks:")
local ReportCAS = REPORT:New( "- CAS Tasks:")
local ReportBAI = REPORT:New( "- BAI Tasks:")
local ReportChanges = REPORT:New( " - Changes:" )
--- First we need to the detected targets.
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set -- Functional.Detection#DETECTION_BASE.DetectedSet
local DetectedZone = DetectedItem.Zone
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
DetectedSet:Flush()
local ItemID = DetectedItem.ItemID
-- Evaluate SEAD Tasking
local SEADTask = Mission:GetTask( string.format( "SEAD.%03d", ItemID ) )
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedItem )
if not SEADTask then
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
SEADTask = Mission:AddTask( Task )
end
end
if SEADTask and SEADTask:IsStatePlanned() then
ReportSEAD:Add( string.format( " - %s.%02d - %s", "SEAD", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
if Mission:IsIDLE() or Mission:IsENGAGED() then
local TaskReport = REPORT:New()
-- Evaluate CAS Tasking
local CASTask = Mission:GetTask( string.format( "CAS.%03d", ItemID ) )
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedItem )
if not CASTask then
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
CASTask = Mission:AddTask( Task )
end
end
if CASTask and CASTask:IsStatePlanned() then
ReportCAS:Add( string.format( " - %s.%02d - %s", "CAS", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
-- Evaluate BAI Tasking
local BAITask = Mission:GetTask( string.format( "BAI.%03d", ItemID ) )
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedItem )
if not BAITask then
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
BAITask = Mission:AddTask( Task )
end
end
if BAITask and BAITask:IsStatePlanned() then
ReportBAI:Add( string.format( " - %s.%02d - %s", "BAI", ItemID, Detection:DetectedItemReportSummary(DetectedItemID) ) )
end
--- First we need to the detected targets.
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
-- Loop through the changes ...
local ChangeText = Detection:GetChangeText( DetectedItem )
ReportChanges:Add( ChangeText )
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedZone = DetectedItem.Zone
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
DetectedSet:Flush()
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedItem )
end
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
Mission:GetCommandCenter():MessageToGroup(
string.format( "HQ Reporting - Planned tasks for mission '%s':\n%s\n",
self.Mission:GetName(),
string.format( "%s\n\n%s\n\n%s\n\n%s", ReportSEAD:Text(), ReportCAS:Text(), ReportBAI:Text(), ReportChanges:Text()
)
), TaskGroup
)
local DetectedItemID = DetectedItem.ID
local DetectedItemChanged = DetectedItem.Changed
local Task = self.Tasks[DetectedItemID]
Task = self:EvaluateRemoveTask( Mission, Task, DetectedItemID, DetectedItemChanged ) -- Task will be removed if it is planned and changed.
-- Evaluate SEAD
if not Task then
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", DetectedItemID ), TargetSetUnit )
end
-- Evaluate CAS
if not Task then
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be CASed...
if TargetSetUnit then
Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", DetectedItemID ), TargetSetUnit )
end
-- Evaluate BAI
if not Task then
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be BAIed...
if TargetSetUnit then
Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", DetectedItemID ), TargetSetUnit )
end
end
end
if Task then
self.Tasks[DetectedItemID] = Task
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "ThreatLevel", DetectedSet:CalculateThreatLevelA2G() )
Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) )
Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) )
Mission:AddTask( Task )
else
self:E("This should not happen")
end
end
TaskReport:Add( Task:GetName() )
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedItem )
end
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not Mission:IsGroupAssigned(TaskGroup) then
Mission:GetCommandCenter():MessageToGroup( string.format( "Mission *%s* has tasks %s. Subscribe to a task using the Mission *Overlord* radio menu.", Mission:GetName(), TaskReport:Text(", ") ), TaskGroup )
end
end
end
return true

View File

@ -0,0 +1,916 @@
--- **Tasking (Release 2.1)** -- The TASK_CARGO models tasks for players to transport @{Cargo}.
--
-- ![Banner Image](..\Presentations\TASK_CARGO\Dia1.JPG)
--
-- ====
--
-- The Moose framework provides various CARGO classes that allow DCS phisical or logical objects to be transported or sling loaded by Carriers.
-- The CARGO_ classes, as part of the moose core, are able to Board, Load, UnBoard and UnLoad cargo between Carrier units.
--
-- This collection of classes in this module define tasks for human players to handle these cargo objects.
-- Cargo can be transported, picked-up, deployed and sling-loaded from and to other places.
--
-- The following classes are important to consider:
--
-- * @{#TASK_CARGO_TRANSPORT}: Defines a task for a human player to transport a set of cargo between various zones.
--
-- ==
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- 2017-03-09: Revised version.
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
--
-- @module Task_Cargo
do -- TASK_CARGO
--- @type TASK_CARGO
-- @extends Tasking.Task#TASK
---
-- # TASK_CARGO class, extends @{Task#TASK}
--
-- ## A flexible tasking system
--
-- The TASK_CARGO classes provide you with a flexible tasking sytem,
-- that allows you to transport cargo of various types between various locations
-- and various dedicated deployment zones.
--
-- The cargo in scope of the TASK_CARGO classes must be explicitly given, and is of type SET_CARGO.
-- The SET_CARGO contains a collection of CARGO objects that must be handled by the players in the mission.
--
--
-- ## Task execution experience from the player perspective
--
-- A human player can join the battle field in a client airborne slot or a ground vehicle within the CA module (ALT-J).
-- The player needs to accept the task from the task overview list within the mission, using the radio menus.
--
-- Once the TASK_CARGO is assigned to the player and accepted by the player, the player will obtain
-- an extra **Cargo Handling Radio Menu** that contains the CARGO objects that need to be transported.
--
-- Each CARGO object has a certain state:
--
-- * **UnLoaded**: The CARGO is located within the battlefield. It may still need to be transported.
-- * **Loaded**: The CARGO is loaded within a Carrier. This can be your air unit, or another air unit, or even a vehicle.
-- * **Boarding**: The CARGO is running or moving towards your Carrier for loading.
-- * **UnBoarding**: The CARGO is driving or jumping out of your Carrier and moves to a location in the Deployment Zone.
--
-- Cargo must be transported towards different **Deployment @{Zone}s**.
--
-- The Cargo Handling Radio Menu system allows to execute **various actions** to handle the cargo.
-- In the menu, you'll find for each CARGO, that is part of the scope of the task, various actions that can be completed.
-- Depending on the location of your Carrier unit, the menu options will vary.
--
--
-- ## Cargo Pickup and Boarding
--
-- For cargo boarding, a cargo can only execute the boarding actions if it is within the foreseen **Reporting Range**.
-- Therefore, it is important that you steer your Carrier within the Reporting Range,
-- so that boarding actions can be executed on the cargo.
-- To Pickup and Board cargo, the following menu items will be shown in your carrier radio menu:
--
-- ### Board Cargo
--
-- If your Carrier is within the Reporting Range of the cargo, it will allow to pickup the cargo by selecting this menu option.
-- Depending on the Cargo type, the cargo will either move to your Carrier or you will receive instructions how to handle the cargo
-- pickup. If the cargo moves to your carrier, it will indicate the boarding status.
-- Note that multiple units need to board your Carrier, so it is required to await the full boarding process.
-- Once the cargo is fully boarded within your Carrier, you will be notified of this.
--
-- Note that for airborne Carriers, it is required to land first before the Boarding process can be initiated.
-- If during boarding the Carrier gets airborne, the boarding process will be cancelled.
--
-- ## Pickup Cargo
--
-- If your Carrier is not within the Reporting Range of the cargo, the HQ will guide you to its location.
-- Routing information is shown in flight that directs you to the cargo within Reporting Range.
-- Upon arrival, the Cargo will contact you and further instructions will be given.
-- When your Carrier is airborne, you will receive instructions to land your Carrier.
-- The action will not be completed until you've landed your Carrier.
--
--
-- ## Cargo Deploy and UnBoarding
--
-- Various Deployment Zones can be foreseen in the scope of the Cargo transportation. Each deployment zone can be of varying @{Zone} type.
-- The Cargo Handling Radio Menu provides with menu options to execute an action to steer your Carrier to a specific Zone.
--
-- ### UnBoard Cargo
--
-- If your Carrier is already within a Deployment Zone,
-- then the Cargo Handling Radio Menu allows to **UnBoard** a specific cargo that is
-- loaded within your Carrier group into the Deployment Zone.
-- Note that the Unboarding process takes a while, as the cargo units (infantry or vehicles) must unload from your Carrier.
-- Ensure that you stay at the position or stay on the ground while Unboarding.
-- If any unforeseen manoeuvre is done by the Carrier, then the Unboarding will be cancelled.
--
-- ### Deploy Cargo
--
-- If your Carrier is not within a Deployment Zone, you'll need to fly towards one.
-- Fortunately, the Cargo Handling Radio Menu provides you with menu options to select a specific Deployment Zone to fly towards.
-- Once a Deployment Zone has been selected, your Carrier will receive routing information from HQ towards the Deployment Zone center.
-- Upon arrival, the HQ will provide you with further instructions.
-- When your Carrier is airborne, you will receive instructions to land your Carrier.
-- The action will not be completed until you've landed your Carrier!
--
-- ## Handle TASK_CARGO Events ...
--
-- The TASK_CARGO classes define @{Cargo} transport tasks,
-- based on the tasking capabilities defined in @{Task#TASK}.
--
-- ### Specific TASK_CARGO Events
--
-- Specific Cargo Handling event can be captured, that allow to trigger specific actions!
--
-- * **Boarded**: Triggered when the Cargo has been Boarded into your Carrier.
-- * **UnBoarded**: Triggered when the cargo has been Unboarded from your Carrier and has arrived at the Deployment Zone.
--
-- ### Standard TASK_CARGO Events
--
-- The TASK_CARGO is implemented using a @{Statemachine#FSM_TASK}, and has the following standard statuses:
--
-- * **None**: Start of the process.
-- * **Planned**: The cargo task is planned.
-- * **Assigned**: The cargo task is assigned to a @{Group#GROUP}.
-- * **Success**: The cargo task is successfully completed.
-- * **Failed**: The cargo task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- ===
--
-- @field #TASK_CARGO
--
TASK_CARGO = {
ClassName = "TASK_CARGO",
}
--- Instantiates a new TASK_CARGO.
-- @param #TASK_CARGO self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported.
-- @param #string TaskType The type of Cargo task.
-- @param #string TaskBriefing The Cargo Task briefing.
-- @return #TASK_CARGO self
function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType, TaskBriefing )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- #TASK_CARGO
self:F( {Mission, SetGroup, TaskName, SetCargo, TaskType})
self.SetCargo = SetCargo
self.TaskType = TaskType
self.DeployZones = {} -- setmetatable( {}, { __mode = "v" } ) -- weak table on value
local Fsm = self:GetUnitProcess()
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } )
Fsm:AddTransition( { "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed", "Boarding" }, "SelectAction", "*" )
Fsm:AddTransition( "*", "RouteToPickup", "RoutingToPickup" )
Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup", Cancelled = "CancelRouteToPickup" } )
Fsm:AddTransition( "Arrived", "ArriveAtPickup", "ArrivedAtPickup" )
Fsm:AddTransition( "Cancelled", "CancelRouteToPickup", "WaitingForCommand" )
Fsm:AddTransition( "*", "RouteToDeploy", "RoutingToDeploy" )
Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtDeploy", Cancelled = "CancelRouteToDeploy" } )
Fsm:AddTransition( "Arrived", "ArriveAtDeploy", "ArrivedAtDeploy" )
Fsm:AddTransition( "Cancelled", "CancelRouteToDeploy", "WaitingForCommand" )
Fsm:AddTransition( { "ArrivedAtPickup", "ArrivedAtDeploy", "Landing" }, "Land", "Landing" )
Fsm:AddTransition( "Landing", "Landed", "Landed" )
Fsm:AddTransition( "*", "PrepareBoarding", "AwaitBoarding" )
Fsm:AddTransition( "AwaitBoarding", "Board", "Boarding" )
Fsm:AddTransition( "Boarding", "Boarded", "Boarded" )
Fsm:AddTransition( "*", "PrepareUnBoarding", "AwaitUnBoarding" )
Fsm:AddTransition( "AwaitUnBoarding", "UnBoard", "UnBoarding" )
Fsm:AddTransition( "UnBoarding", "UnBoarded", "UnBoarded" )
Fsm:AddTransition( "Deployed", "Success", "Success" )
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_CARGO#TASK_CARGO Task
function Fsm:onafterSelectAction( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
local MenuTime = timer.getTime()
TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() ):SetTime( MenuTime )
Task.SetCargo:ForEachCargo(
--- @param Core.Cargo#CARGO Cargo
function( Cargo )
if Cargo:IsAlive() then
-- if Task:is( "RoutingToPickup" ) then
-- MENU_GROUP_COMMAND:New(
-- TaskUnit:GetGroup(),
-- "Cancel Route " .. Cargo.Name,
-- TaskUnit.Menu,
-- self.MenuRouteToPickupCancel,
-- self,
-- Cargo
-- ):SetTime(MenuTime)
-- end
if Cargo:IsUnLoaded() then
if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Board cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuBoardCargo,
self,
Cargo
):SetTime(MenuTime)
else
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Route to Pickup cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuRouteToPickup,
self,
Cargo
):SetTime(MenuTime)
end
end
if Cargo:IsLoaded() then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Unboard cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuUnBoardCargo,
self,
Cargo
):SetTime(MenuTime)
-- Deployzones are optional zones that can be selected to request routing information.
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
if not Cargo:IsInZone( DeployZone ) then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Route to Deploy cargo at " .. DeployZoneName,
TaskUnit.Menu,
self.MenuRouteToDeploy,
self,
DeployZone
):SetTime(MenuTime)
end
end
end
end
end
)
TaskUnit.Menu:Remove( MenuTime )
self:__SelectAction( -15 )
--Task:GetMission():GetCommandCenter():MessageToGroup("Cargo menu is ready ...", TaskUnit:GetGroup() )
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:OnLeaveWaitingForCommand( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
TaskUnit.Menu:Remove()
end
function Fsm:MenuBoardCargo( Cargo )
self:__PrepareBoarding( 1.0, Cargo )
end
function Fsm:MenuUnBoardCargo( Cargo, DeployZone )
self:__PrepareUnBoarding( 1.0, Cargo, DeployZone )
end
function Fsm:MenuRouteToPickup( Cargo )
self:__RouteToPickup( 1.0, Cargo )
end
function Fsm:MenuRouteToDeploy( DeployZone )
self:__RouteToDeploy( 1.0, DeployZone )
end
--- Route to Cargo
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
-- @param From
-- @param Event
-- @param To
-- @param Core.Cargo#CARGO Cargo
function Fsm:onafterRouteToPickup( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if Cargo:IsAlive() then
self.Cargo = Cargo -- Core.Cargo#CARGO
Task:SetCargoPickup( self.Cargo, TaskUnit )
self:__RouteToPickupPoint( -0.1 )
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterArriveAtPickup( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if self.Cargo:IsAlive() then
if TaskUnit:IsAir() then
self.Cargo.CargoObject:GetUnit(1):SmokeRed()
self:__Land( -0.1, "Pickup" )
else
self:__SelectAction( -0.1 )
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterCancelRouteToPickup( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self:__SelectAction( -0.1 )
end
--- Route to DeployZone
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
function Fsm:onafterRouteToDeploy( TaskUnit, Task, From, Event, To, DeployZone )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self:E( DeployZone )
self.DeployZone = DeployZone
Task:SetDeployZone( self.DeployZone, TaskUnit )
self:__RouteToDeployZone( -0.1 )
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterArriveAtDeploy( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if TaskUnit:IsAir() then
self:__Land( -0.1, "Deploy" )
else
self:__SelectAction( -0.1 )
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterCancelRouteToDeploy( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self:__SelectAction( -0.1 )
end
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterLand( TaskUnit, Task, From, Event, To, Action )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup() )
self:__Land( -10, Action )
else
Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup() )
self:__Landed( -0.1, Action )
end
else
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
end
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterLanded( TaskUnit, Task, From, Event, To, Action )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
self:__Land( -0.1, Action )
else
self:__SelectAction( -0.1 )
end
else
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
end
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterPrepareBoarding( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if Cargo and Cargo:IsAlive() then
self.Cargo = Cargo -- Core.Cargo#CARGO_GROUP
self:__Board( -0.1 )
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterBoard( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
function self.Cargo:OnEnterLoaded( From, Event, To, TaskUnit, TaskProcess )
self:E({From, Event, To, TaskUnit, TaskProcess })
TaskProcess:__Boarded( 0.1 )
end
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
--- ABORT the boarding. Split group if any and go back to select action.
else
self.Cargo:MessageToGroup( "Boarding ...", TaskUnit:GetGroup() )
self.Cargo:Board( TaskUnit, 20, self )
end
else
--self:__ArriveAtCargo( -0.1 )
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterBoarded( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self.Cargo:MessageToGroup( "Boarded ...", TaskUnit:GetGroup() )
self:__SelectAction( 1 )
-- TODO:I need to find a more decent solution for this.
Task:E( { CargoPickedUp = Task.CargoPickedUp } )
if self.Cargo:IsAlive() then
if Task.CargoPickedUp then
Task:CargoPickedUp( TaskUnit, self.Cargo )
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
-- @param From
-- @param Event
-- @param To
-- @param Cargo
-- @param Core.Zone#ZONE_BASE DeployZone
function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo } )
self.Cargo = Cargo
self.DeployZone = nil
-- Check if the Cargo is at a deployzone... If it is, provide it as a parameter!
if Cargo:IsAlive() then
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
if Cargo:IsInZone( DeployZone ) then
self.DeployZone = DeployZone -- Core.Zone#ZONE_BASE
break
end
end
self:__UnBoard( -0.1, Cargo, self.DeployZone )
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
-- @param From
-- @param Event
-- @param To
-- @param Cargo
-- @param Core.Zone#ZONE_BASE DeployZone
function Fsm:onafterUnBoard( TaskUnit, Task, From, Event, To, Cargo, DeployZone )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo, DeployZone } )
function self.Cargo:OnEnterUnLoaded( From, Event, To, DeployZone, TaskProcess )
self:E({From, Event, To, DeployZone, TaskProcess })
TaskProcess:__UnBoarded( -0.1 )
end
if self.Cargo:IsAlive() then
self.Cargo:MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup() )
if DeployZone then
self.Cargo:UnBoard( DeployZone:GetPointVec2(), 400, self )
else
self.Cargo:UnBoard( TaskUnit:GetPointVec2():AddX(60), 400, self )
end
end
end
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onafterUnBoarded( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self.Cargo:MessageToGroup( "UnBoarded ...", TaskUnit:GetGroup() )
-- TODO:I need to find a more decent solution for this.
Task:E( { CargoDeployed = Task.CargoDeployed } )
if self.Cargo:IsAlive() then
if Task.CargoDeployed then
Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone )
end
end
self:__SelectAction( 1 )
end
return self
end
--- @param #TASK_CARGO self
function TASK_CARGO:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
--- @param #TASK_CARGO self
-- @return Core.Set#SET_CARGO The Cargo Set.
function TASK_CARGO:GetCargoSet()
return self.SetCargo
end
--- @param #TASK_CARGO self
-- @return #list<Core.Zone#ZONE_BASE> The Deployment Zones.
function TASK_CARGO:GetDeployZones()
return self.DeployZones
end
--- @param #TASK_CARGO self
-- @param AI.AI_Cargo#AI_CARGO Cargo The cargo.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetCargoPickup( Cargo, TaskUnit )
self:F({Cargo, TaskUnit})
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteCargo = ProcessUnit:GetProcess( "RoutingToPickup", "RouteToPickupPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteCargo:Reset()
ActRouteCargo:SetCoordinate( Cargo:GetCoordinate() )
ActRouteCargo:SetRange( Cargo:GetBoardingRange() )
ActRouteCargo:SetMenuCancel( TaskUnit:GetGroup(), "Cancel Routing to Cargo " .. Cargo:GetName(), TaskUnit.Menu )
ActRouteCargo:Start()
return self
end
--- @param #TASK_CARGO self
-- @param Core.Zone#ZONE DeployZone
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetDeployZone( DeployZone, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteDeployZone = ProcessUnit:GetProcess( "RoutingToDeploy", "RouteToDeployZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
ActRouteDeployZone:Reset()
ActRouteDeployZone:SetZone( DeployZone )
ActRouteDeployZone:SetMenuCancel( TaskUnit:GetGroup(), "Cancel Routing to Deploy Zone" .. DeployZone:GetName(), TaskUnit.Menu )
ActRouteDeployZone:Start()
return self
end
--- @param #TASK_CARGO self
-- @param Core.Zone#ZONE DeployZone
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:AddDeployZone( DeployZone, TaskUnit )
self.DeployZones[DeployZone:GetName()] = DeployZone
return self
end
--- @param #TASK_CARGO self
-- @param Core.Zone#ZONE DeployZone
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:RemoveDeployZone( DeployZone, TaskUnit )
self.DeployZones[DeployZone:GetName()] = nil
return self
end
--- @param #TASK_CARGO self
-- @param @list<Core.Zone#ZONE> DeployZones
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetDeployZones( DeployZones, TaskUnit )
for DeployZoneID, DeployZone in pairs( DeployZones ) do
self.DeployZones[DeployZone:GetName()] = DeployZone
end
return self
end
--- @param #TASK_CARGO self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Zone#ZONE_BASE The Zone object where the Target is located on the map.
function TASK_CARGO:GetTargetZone( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
return ActRouteTarget:GetZone()
end
--- Set a score when a target in scope of the A2G attack, has been destroyed .
-- @param #TASK_CARGO self
-- @param #string Text The text to display to the player, when the target has been destroyed.
-- @param #number Score The score in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetScoreOnDestroy( Text, Score, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScoreProcess( "Engaging", "Account", "Account", Text, Score )
return self
end
--- Set a score when all the targets in scope of the A2G attack, have been destroyed.
-- @param #TASK_CARGO self
-- @param #string Text The text to display to the player, when all targets hav been destroyed.
-- @param #number Score The score in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetScoreOnSuccess( Text, Score, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScore( "Success", Text, Score )
return self
end
--- Set a penalty when the A2G attack has failed.
-- @param #TASK_CARGO self
-- @param #string Text The text to display to the player, when the A2G attack has failed.
-- @param #number Penalty The penalty in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_CARGO
function TASK_CARGO:SetPenaltyOnFailed( Text, Penalty, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScore( "Failed", Text, Penalty )
return self
end
end
do -- TASK_CARGO_TRANSPORT
--- The TASK_CARGO_TRANSPORT class
-- @type TASK_CARGO_TRANSPORT
-- @extends #TASK_CARGO
TASK_CARGO_TRANSPORT = {
ClassName = "TASK_CARGO_TRANSPORT",
}
--- Instantiates a new TASK_CARGO_TRANSPORT.
-- @param #TASK_CARGO_TRANSPORT self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported.
-- @param #string TaskBriefing The Cargo Task briefing.
-- @return #TASK_CARGO_TRANSPORT self
function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo, TaskBriefing )
local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport", TaskBriefing ) ) -- #TASK_CARGO_TRANSPORT
self:F()
Mission:AddTask( self )
-- Events
self:AddTransition( "*", "CargoPickedUp", "*" )
self:AddTransition( "*", "CargoDeployed", "*" )
--- OnBefore Transition Handler for Event CargoPickedUp.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoPickedUp
-- @param #TASK_CARGO_TRANSPORT self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event CargoPickedUp.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnAfterCargoPickedUp
-- @param #TASK_CARGO_TRANSPORT self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
--- Synchronous Event Trigger for Event CargoPickedUp.
-- @function [parent=#TASK_CARGO_TRANSPORT] CargoPickedUp
-- @param #TASK_CARGO_TRANSPORT self
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
--- Asynchronous Event Trigger for Event CargoPickedUp.
-- @function [parent=#TASK_CARGO_TRANSPORT] __CargoPickedUp
-- @param #TASK_CARGO_TRANSPORT self
-- @param #number Delay The delay in seconds.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
--- OnBefore Transition Handler for Event CargoDeployed.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoDeployed
-- @param #TASK_CARGO_TRANSPORT self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded.
-- @return #boolean Return false to cancel Transition.
--- OnAfter Transition Handler for Event CargoDeployed.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnAfterCargoDeployed
-- @param #TASK_CARGO_TRANSPORT self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded.
--- Synchronous Event Trigger for Event CargoDeployed.
-- @function [parent=#TASK_CARGO_TRANSPORT] CargoDeployed
-- @param #TASK_CARGO_TRANSPORT self
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded.
--- Asynchronous Event Trigger for Event CargoDeployed.
-- @function [parent=#TASK_CARGO_TRANSPORT] __CargoDeployed
-- @param #TASK_CARGO_TRANSPORT self
-- @param #number Delay The delay in seconds.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded.
local Fsm = self:GetUnitProcess()
local CargoReport = REPORT:New( "Transport Cargo. The following cargo needs to be transported including initial positions:")
SetCargo:ForEachCargo(
--- @param Core.Cargo#CARGO Cargo
function( Cargo )
local CargoType = Cargo:GetType()
local CargoName = Cargo:GetName()
local CargoCoordinate = Cargo:GetCoordinate()
CargoReport:Add( string.format( '- "%s" (%s) at %s', CargoName, CargoType, CargoCoordinate:ToString() ) )
end
)
self:SetBriefing(
TaskBriefing or
CargoReport:Text()
)
return self
end
---
-- @param #TASK_CARGO_TRANSPORT self
-- @return #boolean
function TASK_CARGO_TRANSPORT:IsAllCargoTransported()
local CargoSet = self:GetCargoSet()
local Set = CargoSet:GetSet()
local DeployZones = self:GetDeployZones()
local CargoDeployed = true
-- Loop the CargoSet (so evaluate each Cargo in the SET_CARGO ).
for CargoID, CargoData in pairs( Set ) do
local Cargo = CargoData -- Core.Cargo#CARGO
-- Loop the DeployZones set for the TASK_CARGO_TRANSPORT.
for DeployZoneID, DeployZone in pairs( DeployZones ) do
-- If there is a Cargo not in one of DeployZones, then not all Cargo is deployed.
self:T( { Cargo.CargoObject } )
if Cargo:IsInZone( DeployZone ) then
else
CargoDeployed = false
end
end
end
return CargoDeployed
end
end

View File

@ -276,6 +276,16 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
end
end
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
if acc == 0 then
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph
else
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', UTILS.Round(MGRS.Easting/(10^(5-acc)), 0))
.. ' ' .. string.format('%0' .. acc .. 'd', UTILS.Round(MGRS.Northing/(10^(5-acc)), 0))
end
end
--- From http://lua-users.org/wiki/SimpleRound
-- use negative idp for rounding ahead of decimal place, positive for rounding after decimal place

View File

@ -585,36 +585,64 @@ end
--- (AIR) Delivering weapon at the point on the ground.
-- @param #CONTROLLABLE self
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @param #number Altitude (optional) The altitude from where to attack.
-- @param #number WeaponType (optional) The WeaponType.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskBombing( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack )
self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } )
-- Bombing = {
-- id = 'Bombing',
-- params = {
-- point = Vec2,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend,
-- attackQty = number,
-- direction = Azimuth,
-- controllableAttack = boolean,
-- }
-- }
function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType )
self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } )
local DCSTask
DCSTask = { id = 'Bombing',
DCSTask = {
id = 'Bombing',
params = {
point = Vec2,
weaponType = WeaponType,
expend = WeaponExpend,
attackQty = AttackQty,
direction = Direction,
controllableAttack = ControllableAttack,
point = Vec2,
groupAttack = GroupAttack or false,
expend = WeaponExpend or "Auto",
attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty,
directionEnabled = Direction and true or false,
direction = Direction,
altitudeEnabled = Altitude and true or false,
altitude = Altitude or 30,
weaponType = WeaponType,
},
},
self:T3( { DCSTask } )
return DCSTask
end
--- (AIR) Attacking the map object (building, structure, e.t.c).
-- @param #CONTROLLABLE self
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at.
-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #number Altitude (optional) The altitude from where to attack.
-- @param #number WeaponType (optional) The WeaponType.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType )
self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } )
local DCSTask
DCSTask = {
id = 'AttackMapObject',
params = {
point = Vec2,
groupAttack = GroupAttack or false,
expend = WeaponExpend or "Auto",
attackQtyLimit = AttackQty and true or false,
attackQty = AttackQty,
directionEnabled = Direction and true or false,
direction = Direction,
altitudeEnabled = Altitude and true or false,
altitude = Altitude or 30,
weaponType = WeaponType,
},
},
@ -622,6 +650,7 @@ function CONTROLLABLE:TaskBombing( Vec2, WeaponType, WeaponExpend, AttackQty, Di
return DCSTask
end
--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.
-- @param #CONTROLLABLE self
-- @param Dcs.DCSTypes#Vec2 Point The point to hold the position.
@ -700,45 +729,6 @@ end
--- (AIR) Attacking the map object (building, structure, e.t.c).
-- @param #CONTROLLABLE self
-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators.
-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskAttackMapObject( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack )
self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } )
-- AttackMapObject = {
-- id = 'AttackMapObject',
-- params = {
-- point = Vec2,
-- weaponType = number,
-- expend = enum AI.Task.WeaponExpend,
-- attackQty = number,
-- direction = Azimuth,
-- controllableAttack = boolean,
-- }
-- }
local DCSTask
DCSTask = { id = 'AttackMapObject',
params = {
point = Vec2,
weaponType = WeaponType,
expend = WeaponExpend,
attackQty = AttackQty,
direction = Direction,
controllableAttack = ControllableAttack,
},
},
self:T3( { DCSTask } )
return DCSTask
end
--- (AIR) Delivering weapon on the runway.
@ -1774,6 +1764,7 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad
local DetectionRWR = ( DetectRWR and DetectRWR == true ) and Controller.Detection.RWR or nil
local DetectionDLINK = ( DetectDLINK and DetectDLINK == true ) and Controller.Detection.DLINK or nil
self:T( { DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK } )
return self:_GetController():getDetectedTargets( DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK )
end
@ -1781,21 +1772,25 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad
return nil
end
function CONTROLLABLE:IsTargetDetected( DCSObject )
function CONTROLLABLE:IsTargetDetected( DCSObject, DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK )
self:F2( self.ControllableName )
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local DetectionVisual = ( DetectVisual and DetectVisual == true ) and Controller.Detection.VISUAL or nil
local DetectionOptical = ( DetectOptical and DetectOptical == true ) and Controller.Detection.OPTICAL or nil
local DetectionRadar = ( DetectRadar and DetectRadar == true ) and Controller.Detection.RADAR or nil
local DetectionIRST = ( DetectIRST and DetectIRST == true ) and Controller.Detection.IRST or nil
local DetectionRWR = ( DetectRWR and DetectRWR == true ) and Controller.Detection.RWR or nil
local DetectionDLINK = ( DetectDLINK and DetectDLINK == true ) and Controller.Detection.DLINK or nil
local Controller = self:_GetController()
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity
= self:_GetController().isTargetDetected( self:_GetController(), DCSObject,
Controller.Detection.VISUAL,
Controller.Detection.OPTIC,
Controller.Detection.RADAR,
Controller.Detection.IRST,
Controller.Detection.RWR,
Controller.Detection.DLINK
)
= Controller:isTargetDetected( DCSObject, DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK )
return TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity
end

View File

@ -319,6 +319,7 @@ function GROUP:GetUnit( UnitNumber )
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local DCSUnit = DCSGroup:getUnit( UnitNumber )
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
self:T2( UnitFound )
return UnitFound
@ -553,22 +554,23 @@ end
function GROUP:IsPartlyInZone( Zone )
self:F2( { self.GroupName, Zone } )
local PartlyInZone = false
local IsOneUnitInZone = false
local IsOneUnitOutsideZone = false
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsVec3InZone( Unit:GetVec3() ) then
PartlyInZone = true
IsOneUnitInZone = true
else
-- So, if there were groups in the zone found, and suddenly one NOT in the zone,
-- then the group is partialy in the zone :-)
if PartlyInZone == true then
return true
end
IsOneUnitOutsideZone = true
end
end
return false
if IsOneUnitInZone and IsOneUnitOutsideZone then
return true
else
return false
end
end
--- Returns true if none of the group units of the group are within a @{Zone}.
@ -588,6 +590,24 @@ function GROUP:IsNotInZone( Zone )
return true
end
--- Returns the number of UNITs that are in the @{Zone}
-- @param #GROUP self
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #number The number of UNITs that are in the @{Zone}
function GROUP:CountInZone( Zone )
self:F2( {self.GroupName, Zone} )
local Count = 0
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsVec3InZone( Unit:GetVec3() ) then
Count = Count + 1
end
end
return Count
end
--- Returns if the group is of an air category.
-- If the group is a helicopter or a plane, then this method will return true, otherwise false.
-- @param #GROUP self
@ -834,6 +854,9 @@ function GROUP:Respawn( Template )
self:Destroy()
_DATABASE:Spawn( Template )
self:ResetEvents()
end
--- Returns the group template from the @{DATABASE} (_DATABASE object).
@ -1077,7 +1100,21 @@ do -- Event Handling
-- @return #GROUP
function GROUP:UnHandleEvent( Event )
self:EventDispatcher():RemoveForGroup( self:GetName(), self, Event )
self:EventDispatcher():Remove( self, Event )
return self
end
--- Reset the subscriptions.
-- @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
@ -1104,7 +1141,7 @@ do -- Players
end
end
self:F( PlayerNames )
self:F2( PlayerNames )
return PlayerNames
end

View File

@ -1,25 +1,4 @@
--- This module contains the POSITIONABLE class.
--
-- 1) @{Positionable#POSITIONABLE} class, extends @{Identifiable#IDENTIFIABLE}
-- ===========================================================
-- The @{Positionable#POSITIONABLE} class is a wrapper class to handle the POSITIONABLE objects:
--
-- * Support all DCS APIs.
-- * Enhance with POSITIONABLE specific APIs not in the DCS API set.
-- * Manage the "state" of the POSITIONABLE.
--
-- 1.1) POSITIONABLE constructor:
-- ------------------------------
-- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance:
--
-- * @{Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance.
--
-- 1.2) POSITIONABLE methods:
-- --------------------------
-- The following methods can be used to identify an measurable object:
--
-- * @{Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object.
-- * @{Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object.
--- **Wrapper** -- This module contains the POSITIONABLE class.
--
-- ===
--
@ -29,11 +8,36 @@
-- @type POSITIONABLE
-- @extends Wrapper.Identifiable#IDENTIFIABLE
-- @field #string PositionableName The name of the measurable.
-- @field Core.Spot#SPOT Spot The laser Spot.
-- @field #number LaserCode The last assigned laser code.
--- # POSITIONABLE class, extends @{Identifiable#IDENTIFIABLE}
--
-- The POSITIONABLE class is a wrapper class to handle the POSITIONABLE objects:
--
-- * Support all DCS APIs.
-- * Enhance with POSITIONABLE specific APIs not in the DCS API set.
-- * Manage the "state" of the POSITIONABLE.
--
-- ## POSITIONABLE constructor
--
-- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance:
--
-- * @{Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance.
--
-- ## POSITIONABLE methods
--
-- The following methods can be used to identify an measurable object:
--
-- * @{Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object.
-- * @{Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object.
--
--
-- @field #POSITIONABLE
POSITIONABLE = {
ClassName = "POSITIONABLE",
PositionableName = "",
}
--- A DCSPositionable
-- @type DCSPositionable
-- @field id_ The ID of the controllable in DCS
@ -132,6 +136,27 @@ function POSITIONABLE:GetPointVec3()
return nil
end
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetCoordinate()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = self:GetPositionVec3()
local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 )
self:T2( PositionableCoordinate )
return PositionableCoordinate
end
return nil
end
--- Returns a random @{DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
@ -184,6 +209,28 @@ function POSITIONABLE:GetVec3()
return nil
end
--- Get the bounding box of the underlying POSITIONABLE DCS Object.
-- @param #POSITIONABLE self
-- @return Dcs.DCSTypes#Distance The bounding box of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetBoundingBox() --R2.1
self:F2()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableDesc = DCSPositionable:getDesc() --Dcs.DCSTypes#Desc
if PositionableDesc then
local PositionableBox = PositionableDesc.box
return PositionableBox
end
end
return nil
end
--- Returns the altitude of the POSITIONABLE.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Distance The altitude of the POSITIONABLE.
@ -280,6 +327,29 @@ function POSITIONABLE:GetVelocity()
return nil
end
--- Returns the POSITIONABLE height in meters.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Dcs.DCSTypes#Vec3 The height of the positionable.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetHeight() --R2.1
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionablePosition = DCSPositionable:getPosition()
if PositionablePosition then
local PositionableHeight = PositionablePosition.p.y
self:T2( PositionableHeight )
return PositionableHeight
end
end
return nil
end
--- Returns the POSITIONABLE velocity in km/h.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return #number The velocity in km/h
@ -300,18 +370,38 @@ function POSITIONABLE:GetVelocityKMH()
return nil
end
--- Returns the message text with the callsign embedded (if there is one).
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
-- @return #string The message text
function POSITIONABLE:GetMessageText( Message, Name ) --R2.1 added
local DCSObject = self:GetDCSObject()
if DCSObject then
Name = Name and ( " (" .. Name .. ")" ) or ""
local Callsign = string.format( "[%s]", self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName() )
local MessageText = Callsign .. Name .. ": " .. Message
return MessageText
end
return nil
end
--- Returns a message with the callsign embedded (if there is one).
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
-- @return Core.Message#MESSAGE
function POSITIONABLE:GetMessage( Message, Duration, Name )
function POSITIONABLE:GetMessage( Message, Duration, Name ) --R2.1 changed callsign and name and using GetMessageText
local DCSObject = self:GetDCSObject()
if DCSObject then
Name = Name or self:GetTypeName()
return MESSAGE:New( Message, Duration, self:GetCallsign() .. " (" .. Name .. ")" )
local MessageText = self:GetMessageText( Message, Name )
return MESSAGE:New( MessageText, Duration )
end
return nil
@ -340,12 +430,19 @@ end
-- @param #string Message The message text
-- @param Dcs.DCSTYpes#Duration Duration The duration of the message.
-- @param Dcs.DCScoalition#coalition MessageCoalition The Coalition receiving the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition, Name )
function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition )
self:F2( { Message, Duration } )
local Name = ""
local DCSObject = self:GetDCSObject()
if DCSObject then
if MessageCoalition == coalition.side.BLUE then
Name = "Blue coalition"
end
if MessageCoalition == coalition.side.RED then
Name = "Red coalition"
end
self:GetMessage( Message, Duration, Name ):ToCoalition( MessageCoalition )
end
@ -425,6 +522,30 @@ function POSITIONABLE:MessageToGroup( Message, Duration, MessageGroup, Name )
return nil
end
--- Send a message to a @{Set#SET_GROUP}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
-- @param #string Message The message text
-- @param Dcs.DCSTypes#Duration Duration The duration of the message.
-- @param Core.Set#SET_GROUP MessageSetGroup The SET_GROUP collection receiving the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
function POSITIONABLE:MessageToSetGroup( Message, Duration, MessageSetGroup, Name ) --R2.1
self:F2( { Message, Duration } )
local DCSObject = self:GetDCSObject()
if DCSObject then
if DCSObject:isExist() then
MessageSetGroup:ForEachGroup(
function( MessageGroup )
self:GetMessage( Message, Duration, Name ):ToGroup( MessageGroup )
end
)
end
end
return nil
end
--- Send a message to the players in the @{Group}.
-- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message.
-- @param #POSITIONABLE self
@ -446,7 +567,86 @@ end
-- Set parameters with the methods provided, then use RADIO:Broadcast() to actually broadcast the message
-- @param #POSITIONABLE self
-- @return #RADIO Radio
function POSITIONABLE:GetRadio()
function POSITIONABLE:GetRadio() --R2.1
self:F2(self)
return RADIO:New(self)
end
--- Create a @{Radio#BEACON}, to allow this POSITIONABLE to broadcast beacon signals
-- @param #POSITIONABLE self
-- @return #RADIO Radio
function POSITIONABLE:GetBeacon() --R2.1
self:F2(self)
return BEACON:New(self)
end
--- Start Lasing a POSITIONABLE
-- @param #POSITIONABLE self
-- @param #POSITIONABLE Target
-- @param #number LaserCode
-- @param #number Duration
-- @return Core.Spot#SPOT
function POSITIONABLE:LaseUnit( Target, LaserCode, Duration ) --R2.1
self:F2()
LaserCode = LaserCode or math.random( 1000, 9999 )
local RecceDcsUnit = self:GetDCSObject()
local TargetVec3 = Target:GetVec3()
self:E("bulding spot")
self.Spot = SPOT:New( self ) -- Core.Spot#SPOT
self.Spot:LaseOn( Target, LaserCode, Duration)
self.LaserCode = LaserCode
return self.Spot
end
--- Stop Lasing a POSITIONABLE
-- @param #POSITIONABLE self
-- @return #POSITIONABLE
function POSITIONABLE:LaseOff() --R2.1
self:F2()
if self.Spot then
self.Spot:LaseOff()
self.Spot = nil
end
return self
end
--- Check if the POSITIONABLE is lasing a target
-- @param #POSITIONABLE self
-- @return #boolean true if it is lasing a target
function POSITIONABLE:IsLasing() --R2.1
self:F2()
local Lasing = false
if self.Spot then
Lasing = self.Spot:IsLasing()
end
return Lasing
end
--- Get the Spot
-- @param #POSITIONABLE self
-- @return Core.Spot#SPOT The Spot
function POSITIONABLE:GetSpot() --R2.1
return self.Spot
end
--- Get the last assigned laser code
-- @param #POSITIONABLE self
-- @return #number The laser code
function POSITIONABLE:GetLaserCode() --R2.1
return self.LaserCode
end

View File

@ -64,13 +64,18 @@
--
-- The UNIT class contains methods to test the location or proximity against zones or other objects.
--
-- ### Zones
-- ### Zones range
--
-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Zone#ZONE_BASE}.
--
-- ### Units
-- ### Unit range
--
-- * Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method.
--
-- ## Test Line of Sight
--
-- * Use the @{#UNIT.IsLOS}() method to check if the given unit is within line of sight.
--
-- Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method.
--
-- @field #UNIT UNIT
UNIT = {
@ -640,7 +645,7 @@ function UNIT:GetThreatLevel()
"Bomber",
"Strategic Bomber",
"Attack Helicopter",
"Interceptor",
"Battleplane",
"Multirole Fighter",
"Fighter"
}
@ -719,7 +724,7 @@ function UNIT:IsInZone( Zone )
if self:IsAlive() then
local IsInZone = Zone:IsVec3InZone( self:GetVec3() )
self:T( { IsInZone } )
self:T2( { IsInZone } )
return IsInZone
end
@ -859,6 +864,8 @@ function UNIT:SmokeBlue()
trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Blue )
end
-- Is methods
--- Returns if the unit is of an air category.
@ -990,5 +997,42 @@ do -- Event Handling
return self
end
--- Reset the subscriptions.
-- @param #UNIT self
-- @return #UNIT
function UNIT:ResetEvents()
self:EventDispatcher():Reset( self )
return self
end
end
do -- Detection
--- Returns if a unit is detecting the TargetUnit.
-- @param #UNIT self
-- @param #UNIT TargetUnit
-- @return #boolean true If the TargetUnit is detected by the unit, otherwise false.
function UNIT:IsDetected( TargetUnit ) --R2.1
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = self:IsTargetDetected( TargetUnit:GetDCSObject() )
return TargetIsDetected
end
--- Returns if a unit has Line of Sight (LOS) with the TargetUnit.
-- @param #UNIT self
-- @param #UNIT TargetUnit
-- @return #boolean true If the TargetUnit has LOS with the unit, otherwise false.
function UNIT:IsLOS( TargetUnit ) --R2.1
local IsLOS = self:GetPointVec3():IsLOS( TargetUnit:GetPointVec3() )
return IsLOS
end
end

View File

@ -17,7 +17,7 @@ For /R %1 %%M IN (*.miz) do (
copy ..\..\Moose.lua l10n\DEFAULT > NUL:
copy "%%~pM%%~nM.lua" l10n\DEFAULT\*.* > NUL:
rem dir l10n\DEFAULT
7z -bb0 u "%%M" "l10n\DEFAULT\*.lua" > NUL:
"%~dp0..\..\Utils\7-Zip\7z" -bb0 u "%%M" "l10n\DEFAULT\*.lua" > NUL:
cd ..
rmdir /S /Q Temp
)

View File

@ -0,0 +1,31 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170328_0728' )
local base = _G
Include = {}
Include.File = function( IncludeFile )
if not Include.Files[ IncludeFile ] then
Include.Files[IncludeFile] = IncludeFile
env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath )
local f = assert( base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" ) )
if f == nil then
error ("Could not load MOOSE file " .. IncludeFile .. ".lua" )
else
env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath )
return f()
end
end
end
Include.ProgramPath = "Scripts/Moose/"
env.info( "Include.ProgramPath = " .. Include.ProgramPath)
Include.Files = {}
Include.File( "Moose" )
BASE:TraceOnOff( true )
env.info( '*** MOOSE INCLUDE END *** ' )

View File

@ -13,6 +13,9 @@ Core/Point.lua
Core/Message.lua
Core/Fsm.lua
Core/Radio.lua
Core/SpawnStatic.lua
Core/Cargo.lua
Core/Spot.lua
Wrapper/Object.lua
Wrapper/Identifiable.lua
@ -34,12 +37,14 @@ Functional/Escort.lua
Functional/MissileTrainer.lua
Functional/AirbasePolice.lua
Functional/Detection.lua
Functional/Designate.lua
AI/AI_Balancer.lua
AI/AI_Patrol.lua
AI/AI_Cap.lua
AI/AI_Cas.lua
AI/AI_Cargo.lua
AI/AI_Bai.lua
AI/AI_Formation.lua
Actions/Act_Assign.lua
Actions/Act_Route.lua
@ -52,5 +57,6 @@ Tasking/Task.lua
Tasking/DetectionManager.lua
Tasking/Task_A2G_Dispatcher.lua
Tasking/Task_A2G.lua
Tasking/Task_Cargo.lua
Moose.lua

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170401_1103' )
env.info( 'Moose Generation Timestamp: 20170510_1031' )
local base = _G
@ -35,6 +35,9 @@ __Moose.Include( 'Core/Point.lua' )
__Moose.Include( 'Core/Message.lua' )
__Moose.Include( 'Core/Fsm.lua' )
__Moose.Include( 'Core/Radio.lua' )
__Moose.Include( 'Core/SpawnStatic.lua' )
__Moose.Include( 'Core/Cargo.lua' )
__Moose.Include( 'Core/Spot.lua' )
__Moose.Include( 'Wrapper/Object.lua' )
__Moose.Include( 'Wrapper/Identifiable.lua' )
__Moose.Include( 'Wrapper/Positionable.lua' )
@ -54,11 +57,13 @@ __Moose.Include( 'Functional/Escort.lua' )
__Moose.Include( 'Functional/MissileTrainer.lua' )
__Moose.Include( 'Functional/AirbasePolice.lua' )
__Moose.Include( 'Functional/Detection.lua' )
__Moose.Include( 'Functional/Designate.lua' )
__Moose.Include( 'AI/AI_Balancer.lua' )
__Moose.Include( 'AI/AI_Patrol.lua' )
__Moose.Include( 'AI/AI_Cap.lua' )
__Moose.Include( 'AI/AI_Cas.lua' )
__Moose.Include( 'AI/AI_Cargo.lua' )
__Moose.Include( 'AI/AI_Bai.lua' )
__Moose.Include( 'AI/AI_Formation.lua' )
__Moose.Include( 'Actions/Act_Assign.lua' )
__Moose.Include( 'Actions/Act_Route.lua' )
__Moose.Include( 'Actions/Act_Account.lua' )
@ -69,6 +74,7 @@ __Moose.Include( 'Tasking/Task.lua' )
__Moose.Include( 'Tasking/DetectionManager.lua' )
__Moose.Include( 'Tasking/Task_A2G_Dispatcher.lua' )
__Moose.Include( 'Tasking/Task_A2G.lua' )
__Moose.Include( 'Tasking/Task_Cargo.lua' )
__Moose.Include( 'Moose.lua' )
BASE:TraceOnOff( true )
env.info( '*** MOOSE INCLUDE END *** ' )

328
Release 2.1.md Normal file
View File

@ -0,0 +1,328 @@
# MOOSE Release 2.1.0
Find here a new release of MOOSE, **release 2.1.0**!
A lot of work has been into the preparation of this.
You'll find new features as well as a couple of important bug fixes.
Release 2.1 can be downloaded from here.
## Summary
First of all, this release would not have been possible without the help and contribution of many
members of this community. THANK YOU!
This release brings you **an improved tasking mechanism**.
Tasking is the system in MOOSE that allows to:
* Execute **co-op** missions and tasks
* **Detect** targets dynamically
* Define new tasks **dynamically**
* Execute the tasks
* Complete the mission **goals**
* Extensive menu system and briefings/reports for **player interaction**
* Improved Scoring of mission goal achievements, and task achievements.
On top, release brings you new functionality by the introduction of new classes to:
* **Designate targets** (lase, smoke or illuminate targets) by AI, assisting your attack. Allows to drop laser guides bombs.
* A new **tasking** system to **transport cargo** of various types
* Dynamically **spawn static objects**
* Improved **coordinate system**
* Build **large formations**, like bombers flying to a target area
## 1. TASKING SYSTEM!
A lot of work has been done in improving the tasking framework within MOOSE.
**The tasking system comes with TASK DISPATCHING mechanisms, that DYNAMICALLY
allocate new tasks based on the tactical or strategical situation in the mission!!!
These tasks can then be engaged upon by the players!!!**
The [TASK\_A2G\_DISPATCHER](http://flightcontrol-master.github.io/MOOSE/Documentation/Task_A2G_Dispatcher.html) class implements the dynamic dispatching of tasks upon groups of detected units determined a Set of FAC (groups). The FAC will detect units, will group them, and will dispatch Tasks to groups. Depending on the type of target detected, different tasks will be dispatched. Find a summary below describing for which situation a task type is created:
* **CAS Task**: Is created when there are enemy ground units within range of the FAC, while there are friendly units in the FAC perimeter.
* **BAI Task**: Is created when there are enemy ground units within range of the FAC, while there are NO other friendly units within the FAC perimeter.
* **SEAD Task**: Is created when there are enemy ground units wihtin range of the FAC, with air search radars.
More TASK_... dispatcher classes are to come in the future, like A2A, G2G, etc...
Improvements on the TASKING are in summary:
* A COMMANDCENTER has a dedicated menu.
* A MISSION has a dedicated menu system.
* A MISSION has a briefing report.
* A MISSION has dedicated status reports.
* A MISSION has for each TASK TYPE a menu.
* A MISSION has for each TASK TYPE a dedicated menu system for each TASK defined.
* A MISSION has an "assigned" task menu that contains menu actions relevant to the assigned task.
* A TASK (of various types) has a dedicated menu system.
* A TASK has a briefing report.
* A TASK has dedicated status reports.
* Player reports can be retrieved that explain which player is at which task.
* ...
TASKING is vast, and at the moment there is too much to explain.
**The best way to explore the TASKING is to TRY it...**
I suggest you have a look at the [GORI Valley Mission - Iteration 3](https://www.youtube.com/watch?v=v2Us8SS1-44&t=1070s).
## 2. New MOOSE classes have been added.
MOOSE 2.1.0 comes with new classes that extends the functionality of the MOOSE framework and allow you to do new things in your missions:
### 2.1. Target designation by laser, smoke or illumination.
[DESIGNATE](http://flightcontrol-master.github.io/MOOSE/Documentation/Designate.html) is orchestrating the designation of potential targets executed by a Recce group,
and communicates these to a dedicated attacking group of players,
so that following a dynamically generated menu system,
each detected set of potential targets can be lased or smoked...
Targets can be:
* **Lased** for a period of time.
* **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.)
* **Illuminated** through an illumination bomb. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.
[DESIGNATE is demonstrated on youtube](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0dQ9UKQMb7YL8z2sKSqemH)
DESIGNATE Demo Missions: [DES - Designation]()
### 2.2. Build large formations of AI.
[AI_FORMATION](http://flightcontrol-master.github.io/MOOSE/Documentation/AI_Formation.html) makes AI @{GROUP}s fly in formation of various compositions.
The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
The purpose of the class is to:
* Make formation building a process that can be managed while in flight, rather than a task.
* Human players can guide formations, consisting of larget planes.
* Build large formations (like a large bomber field).
* Form formations that DCS does not support off the shelve.
AI_FORMATION Demo Missions: [FOR - AI Group Formation]()
### 2.3. Transport cargo of different types to various locations as a human task within a mission.
The Moose framework provides various CARGO classes that allow DCS physical or logical objects to be transported or sling loaded by Carriers.
The CARGO_ classes, as part of the moose core, are able to Board, Load, UnBoard and UnLoad cargo between Carrier units.
This collection of classes in this module define tasks for human players to handle these cargo objects.
Cargo can be transported, picked-up, deployed and sling-loaded from and to other places.
[TASK\_CARGO\_TRANSPORT](http://flightcontrol-master.github.io/MOOSE/Documentation/Task_Cargo.html#TASK_CARGO_TRANSPORT) defines a task for a human player to transport a set of cargo between various zones.
It is the first class that forms part of the TASK_CARGO classes suite.
The TASK_CARGO classes provide you with a flexible tasking sytem,
that allows you to transport cargo of various types between various locations
and various dedicated deployment zones.
A human player can join the battle field in a client airborne slot or a ground vehicle within the CA module (ALT-J).
The player needs to accept the task from the task overview list within the mission, using the radio menus.
Once the TASK_CARGO is assigned to the player and accepted by the player, the player will obtain
an extra **Cargo Handling Radio Menu** that contains the CARGO objects that need to be transported.
Cargo can be transported towards different **Deployment Zones**, but can also be deployed anywhere within the battle field.
The Cargo Handling Radio Menu system allows to execute **various actions** to handle the cargo.
In the menu, you'll find for each CARGO, that is part of the scope of the task, various actions that can be completed.
Depending on the location of your Carrier unit, the menu options will vary.
The [CARGO_GROUP](http://flightcontrol-master.github.io/MOOSE/Documentation/Cargo.html#CARGO_GROUP) class defines a
cargo that is represented by a GROUP object within the simulator, and can be transported by a carrier.
The [CARGO_UNIT](http://flightcontrol-master.github.io/MOOSE/Documentation/Cargo.html#CARGO_UNIT) class defines a
cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
Mission designers can use the [SET_CARGO](http://flightcontrol-master.github.io/MOOSE/Documentation/Set.html#SET_CARGO)
class to build sets of cargos.
Note 1: **Various other CARGO classes are defined and are WIP**.
Now that the foundation for Cargo handling is getting form, future releases will bring other types of CARGO handling
classes to the MOOSE framework quickly. Sling-loading, package, beacon and other types of CARGO will be released soon.
Note 2: **AI_CARGO has been renamed to CARGO and now forms part of the Core or MOOSE**.
If you were using AI_CARGO in your missions, please rename AI_CARGO with CARGO...
TASK_TRANSPORT_CARGO is demonstrated at the [GORI Valley Mission - Iteration 4](https://www.youtube.com/watch?v=v2Us8SS1-44&t=1070s)
TASK_TRANSPORT_CARGO test missions:
### 2.4. Dynamically spawn STATIC objects into your mission.
The [SPAWNSTATIC](http://flightcontrol-master.github.io/MOOSE/Documentation/SpawnStatic.html#SPAWNSTATIC) class allows to spawn dynamically new Statics.
By 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 Statics 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.
### 2.5. Better coordinate management in MGRS or LLor LLDecimal.
The [COORDINATE](http://flightcontrol-master.github.io/MOOSE/Documentation/Point.html#COORDINATE) class
defines a 2D coordinate in the simulator. A COORDINATE can be expressed in LL or in MGRS.
### 2.6. Improved scoring system
Scoring is implemented throught the [SCORING](http://flightcontrol-master.github.io/MOOSE/Documentation/Scoring.html) class.
The scoring system has been improved a lot! Now, the scoring is correctly counting scores on normal units, statics and scenary objects.
Specific scores can be registered for specific targets. The scoring works together with the tasking system, so players can achieve
additional scores when they achieve goals!
## 3. A lot of components have been reworked and bugs have been fixed.
### 3.1. Better event handling and event dispatching.
The underlying mechanisms to handle DCS events has been improved. Bugs have been fixed.
The MISSION_END event is now also supported.
### 2.2. Cargo handling has been made much better now.
As a result, some of the WIP cargo classes that were defined earlier are still WIP.
But as mentioned earlier, new CARGO classes can be published faster now.
The framework is now more consistent internally.
### 2.3. Beacons and Radio
The Radio contains 2 classes : RADIO and BEACON
What are radio communications in DCS ?
* Radio transmissions consist of **sound files** that are broadcasted on a specific **frequency** (e.g. 115MHz) and **modulation** (e.g. AM),
* They can be **subtitled** for a specific **duration**, the **power** in Watts of the transmiter's antenna can be set, and the transmission can be **looped**.
## 3. A lot of new methods have been defined in several existing or new classes.
AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefing ) --R2.1
AI_FORMATION:TestSmokeDirectionVector( SmokeDirection ) --R2.1
AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) --R2.1
AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) --R2.1
AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, ZLevels ) --R2.1
AI_FORMATION:SetFlightRandomization( FlightRandomization ) --R2.1
AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
CARGO:GetName()
CARGO:GetObjectName()
DATABASE:ForEachStatic( IteratorFunction, FinalizeFunction, ... )
EVENT:Reset( EventObject ) --R2.1
POINT_VEC3:IsLOS( ToPointVec3 ) --R2.1
COORDINATE:New( x, y, LandHeightAdd ) --R2.1 Fixes issue #424.
COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) --R2.1 Fixes issue #424.
COORDINATE:NewFromVec3( Vec3 ) --R2.1 Fixes issue #424.
COORDINATE:ToStringLL( LL_Accuracy, LL_DMS ) --R2.1 Fixes issue #424.
COORDINATE:ToStringMGRS( MGRS_Accuracy ) --R2.1 Fixes issue #424.
COORDINATE:ToString() --R2.1 Fixes issue #424.
COORDINATE:CoordinateMenu( RootMenu ) --R2.1 Fixes issue #424.
COORDINATE:MenuSystem( System ) --R2.1 Fixes issue #424.
COORDINATE:MenuLL_Accuracy( LL_Accuracy ) --R2.1 Fixes issue #424.
COORDINATE:MenuLL_DMS( LL_DMS ) --R2.1 Fixes issue #424.
COORDINATE:MenuMGRS_Accuracy( MGRS_Accuracy ) --R2.1 Fixes issue #424.
SET_BASE:FilterDeads() --R2.1 allow deads to be filtered to automatically handle deads in the collection.
SET_BASE:FilterCrashes() --R2.1 allow crashes to be filtered to automatically handle crashes in the collection.
SET_UNIT:ForEachUnitPerThreatLevel( FromThreatLevel, ToThreatLevel, IteratorFunction, ... ) --R2.1 Threat Level implementation
SET_CARGO:New() --R2.1
SET_CARGO:AddCargosByName( AddCargoNames ) --R2.1
SET_CARGO:RemoveCargosByName( RemoveCargoNames ) --R2.1
SET_CARGO:FindCargo( CargoName ) --R2.1
SET_CARGO:FilterCoalitions( Coalitions ) --R2.1
SET_CARGO:FilterTypes( Types ) --R2.1
SET_CARGO:FilterCountries( Countries ) --R2.1
SET_CARGO:FilterPrefixes( Prefixes ) --R2.1
SET_CARGO:FilterStart() --R2.1
SET_CARGO:AddInDatabase( Event ) --R2.1
SET_CARGO:FindInDatabase( Event ) --R2.1
SET_CARGO:ForEachCargo( IteratorFunction, ... ) --R2.1
SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 ) --R2.1
SET_CARGO:IsIncludeObject( MCargo ) --R2.1
SET_CARGO:OnEventNewCargo( EventData ) --R2.1
SET_CARGO:OnEventDeleteCargo( EventData ) --R2.1 SpawnStatic.lua (5 matches)
SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID ) --R2.1
SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, CountryID ) --R2.1
SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName ) --R2.1
ZONE_BASE:GetCoordinate( Height ) --R2.1
DESIGNATE:SetFlashStatusMenu( FlashMenu ) --R2.1
DESIGNATE:SetLaserCodes( LaserCodes ) --R2.1
DESIGNATE:GenerateLaserCodes() --R2.1
DESIGNATE:SetAutoLase( AutoLase ) --R2.1
DESIGNATE:SetThreatLevelPrioritization( Prioritize ) --R2.1
DETECTION_BASE:CleanDetectionItems() --R2.1 Clean the DetectionItems list
DETECTION_BASE:GetDetectedItemID( Index ) --R2.1
DETECTION_BASE:GetDetectedID( Index ) --R2.1
DETECTION_AREAS:DetectedReportDetailed() --R2.1 Fixed missing report
REPORT:HasText() --R2.1
REPORT:SetIndent( Indent ) --R2.1
REPORT:AddIndent( Text ) --R2.1
MISSION:GetMenu( TaskGroup ) -- R2.1 -- Changed Menu Structure
TASK:SetMenu( MenuTime ) --R2.1 Mission Reports and Task Reports added. Fixes issue #424.
TASK:ReportSummary() --R2.1 fixed report. Now nicely formatted and contains the info required.
TASK:ReportOverview() --R2.1 fixed report. Now nicely formatted and contains the info required.
TASK:GetPlayerCount() --R2.1 Get a count of the players.
TASK:GetPlayerNames() --R2.1 Get a map of the players.
TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and contains the info required.
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
POSITIONABLE:GetBoundingBox() --R2.1
POSITIONABLE:GetHeight() --R2.1
POSITIONABLE:GetMessageText( Message, Name ) --R2.1 added
POSITIONABLE:GetMessage( Message, Duration, Name ) --R2.1 changed callsign and name and using GetMessageText
POSITIONABLE:MessageToSetGroup( Message, Duration, MessageSetGroup, Name ) --R2.1
POSITIONABLE:GetRadio() --R2.1
POSITIONABLE:GetBeacon() --R2.1
POSITIONABLE:LaseUnit( Target, LaserCode, Duration ) --R2.1
POSITIONABLE:LaseOff() --R2.1
POSITIONABLE:IsLasing() --R2.1
POSITIONABLE:GetSpot() --R2.1
POSITIONABLE:GetLaserCode() --R2.1
UNIT:IsDetected( TargetUnit ) --R2.1
UNIT:IsLOS( TargetUnit ) --R2.1

BIN
Utils/7-Zip/7-zip.chm Normal file

Binary file not shown.

BIN
Utils/7-Zip/7-zip.dll Normal file

Binary file not shown.

BIN
Utils/7-Zip/7-zip32.dll Normal file

Binary file not shown.

BIN
Utils/7-Zip/7z.dll Normal file

Binary file not shown.

BIN
Utils/7-Zip/7z.exe Normal file

Binary file not shown.

BIN
Utils/7-Zip/7z.sfx Normal file

Binary file not shown.

BIN
Utils/7-Zip/7zCon.sfx Normal file

Binary file not shown.

BIN
Utils/7-Zip/7zFM.exe Normal file

Binary file not shown.

BIN
Utils/7-Zip/7zG.exe Normal file

Binary file not shown.

View File

@ -1,6 +1,19 @@
HISTORY of the 7-Zip
--------------------
16.04 2016-10-04
-------------------------
- The bug was fixed: 7-Zip 16.03 exe installer under Vista didn't create
links in Start / Programs menu.
- Some bugs were fixed in RAR code.
16.03 2016-09-28
-------------------------
- Installer and SFX modules now use some protection against DLL preloading attack.
- Some bugs were fixed in 7z, NSIS, SquashFS, RAR5 and another code.
16.02 2016-05-21
-------------------------
- 7-Zip now can extract multivolume ZIP archives (z01, z02, ... , zip).

404
Utils/7-Zip/Lang/af.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.09 : Petri Jooste
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Afrikaans
Afrikaans
401
OK
Kanselleer
&Ja
&Nee
A&fsluit
Hulp
&Gaan voort
440
Ja vir &almal
Nee vir a&lmal
Stop
Herbegin
&Agtergrond
&Voorgrond
&Wag
Wagtend
Is u seker dat u wil kanselleer?
500
&Lêer
R&edigeer
&Vertoon
G&unstelinge
&Gereedskap
&Hulp
540
&Open
Open &Binne
Open B&uite
&Wys
R&edigeer
Her&noem
&Kopieer na...
&Verskuif na...
Ve&rwyder
Ver&deel lêer...
Kom&bineer lêers...
E&ienskappe
Komme&ntaar
Maak gids
Maak lêer
A&fsluit
600
Selekteer &alles
Deselekteer a&lles
Keer &seleksie om
Selekteer...
Deselekteer...
Selekteer op Soort
Deselekteer op Soort
700
&Groot ikone
&Klein ikone
&Lys
&Detail
730
Ongesorteer
&2 Panele
&Nutsbalke
Maak wortelgids oop
Een vlak hoër
Gidse geskiedenis...
&Verfris
750
Argiveernutsbalk
Standaardnutsbalk
Groot knoppies
Wys teks op knoppies
800
Voeg gids by gunstelinge &as
Boekmerk
900
&Opsies...
&Normtoetsing
960
&Inhoud...
&Aangaande 7-Zip...
1003
Pad
Naam
Uitgang
Gids
Grootte
Ingepakte grootte
Kenmerke
Gemaak
Laatste toegang
Gewysig
Kompak
Kommentaar
Versleuteld
Verdeel Voor
Verdeel Na
Woordeboek
CRC
Tipe
Anti
Metode
Gasheer BS
Lêersstelsel
Gebruiker
Groep
Blok
Kommentaar
Posisie
Fout
Totale grootte
Vrye ruimte
Klustergrootte
Etiket
Plaaslike naam
Verskaffer
2100
Opsies
Taal
Taal:
Redigeerder
R&edigeerder:
2200
Stelsel
Assosieer 7-Zip met:
2301
Integreer 7-Zip in kontekskeuselys.
Trapsgewyse kontekskeuselys
Kontekskeuselysitems:
2320
<Gids>
<Argief>
Open
Pak lêers uit...
Voeg by argief...
Toets argief
Pak hier uit
Pak uit in {0}
Voeg by {0}
Saampers en e-pos...
Pers saam in {0} en e-pos
2400
Gidse
&Werkgids
&TEMP-gids van het stelsel
&Huidige gids
&Gespesifiseerde gids:
Gebruik slegs vir verwisselbare media.
Spesifiseer die stoorplek vir tydelyke argieflêers.
2500
Instellings
Wys ".." &item
Wys &ware lêerikone
Wys &stelselkeuselys
Wys seleksie oor &hele ry(e)
Wys &roosterlyne
2900
Aangaande 7-Zip
7-Zip is gratis programmatuur. Indien u egter so baie van 7-Zip hou dat u die verdere ontwikkeling wil ondersteun, registreer dan asb. met 'n geldelike donasie aan die 7-Zip Projek.
3000
Daar is geen foute nie
{0} objekt(e) is geselekteer
Kan gids '{0}' nie maak nie
Bywerk-funksie word vir hierdie argief nie ondersteun nie.
Lêer '{0}' is gewysig.\nWil u dit bywerk in die argief?
Kan lêer\n'{0}' nie bywerk nie
Redigeerder nie aan die gang gesit word nie.
Te veel items
3300
Besig om uit te pak
Besig met saampersing
Besig om te toets
Besig om oop te maak...
3400
&Uitpak
U&itpak in:
Gee 'n bestemming vir uitgepakte lêers.
3410
Pad-metode
Volledige padname
Geen padname
3420
Vervang lêers
Vervang slegs met bevestiging
Vervang sonder bevestiging
Slaan bestaande lêers oor
Hernoem outomaties
Hernoem bestaande lêers outomaties
3500
Bevestig lêeroorskrywing
Doelgids bevat alreeds 'n lêer met hierdie naam.
Wil u die bestaande lêer vervang
deur hierdie lêer ?
{0} grepe
O&utomaties hernoem
3700
Nie-ondersteunde saampersmetode vir '{0}'.
Datafout in '{0}'. Lêer is beskadig.
CRC het misluk in '{0}'. Lêer is beskadig.
3800
Tik wagwoord in
Tik wagwoord in:
&Wys wagwoord
&Wagwoord
3900
Tydsduur sovêr:
Oorblywende tyd:
Grootte:
Spoed:
Foute:
4000
Voeg by argief
&Argief:
&Bywerkwyse:
Argie&fformaat:
Saampersingv&lak:
&Saampersmetode:
&Woordeboekgrootte:
&Woordgrootte:
Pa&rameters:
Opsies
Maak SF&X argief
Enkripteer lêer&name
Geheuegebruik vir saampersing:
Geheuegebruik vir uitpakking:
4050
Stoor
Vinnigste
Vinnig
Normaal
Maksimum
Ultra
4060
Lêers byvoeg en vervang
Lêers bywerk en byvoeg
Verfris bestaande lêers
Sinkroniseer lêers
4070
Blaai
Alle lêers
6000
Kopieer
Verskuif
Kopieer na:
Verskuif na:
Besig met kopiëring...
Besig met verskuiwing...
Besig met hernoeming...
Bewerking word nie ondersteun nie.
Fout by hernoeming van lêer of gids
6100
Bevestig lêerverwydering
Bevestig gidsverwydering
Bevestig verwydering van meerdere lêers
Is u seker dat u '{0}' wil verwyder?
Is u seker dat u gids '{0}' asook die inhoud daarvan wil verwyder?
Is u seker dat u hierdie {0} items wil verwyder?
Besig met verwydering...
Fout by verwydering van lêer of gids
6300
Maak gids
Maak lêer
Naam van die gids:
Lêernaam:
Nuwe gids
Nuwe lêer
Fout by maak van gids
Fout by maak van nuwe lêer
6400
Selekteer
Deselekteer
Masker:
6600
Gidse-geskiedenis
Diagnostiese boodskappe
Boodskap
7100
Rekenaar
Network
Stelsel
7200
Voeg by
Pak uit
Toets
Kopiëer
Skuif
Vee uit
Intigting
7300
Verdeel lêer
&Verdeel na:
Verdeel in &volumes, aantal grepe:
Besig met verdeling...
7400
Kombineer lêers
&Kombineer na:
Besig met kombinering...
7500
7600
Meet
Geheuegebruik:
Inpakking
Uitpakking
Gradering
Totale gradering
Huidige
Resultaat
Lopies:

404
Utils/7-Zip/Lang/an.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; : Feliciano Martínez Tur
; 9.07 : Juan Pablo Martínez
;
;
;
;
;
;
;
;
;
0
7-Zip
Aragonese
Aragonés
401
Acceptar
Cancelar
&Sí
&No
&Zarrar
Aduya
&Continar
440
Sí a &tot
No a t&ot
Aturar
Tornar a empecipiar
Se&gundo plano
P&rimer plano
&Pausa
Aturau
Yes seguro que quiers cancelar?
500
&Fichero
&Editar
&Veyer
&Favoritos
&Ferramientas
Ad&uya
540
&Ubrir
Ubrir &adintro
Ubrir &difuera
&Veyer
&Editar
Re&nombrar
&Copiar en...
&Mover ta...
&Borrar
Di&vidir o fichero...
C&ombinar os fichers...
&Propiedatz
Comen&tario
Calcular a suma de comprebación
Diff
Creyar carpeta
Creyar fichero
&Salir
600
Seleccionar-lo &tot
Deseleccionar-lo tot
&Invertir selección
Seleccionar...
Deseleccionar...
Seleccionar por tipo
Deseleccionar por tipo
700
Iconos g&rans
&Iconos chicotz
&Lista
&Detalles
730
Desordenau
Anvista plana
&2 panels
&Barras de ferramientas
Ubrir a carpeta radiz
Carpeta mai
Historial de carpetas...
&Esviellar
750
Barra de ferramientas d'archivo
Barras de ferramientas estandard
Botons grans
Amostrar texto en os botons
800
&Adhibir carpeta a favoritos como
Adhibir a favoritos
900
&Opcions...
&Prebas de referencia (benchmark)
960
&Conteniu...
A&rredol de 7-Zip...
1003
Rota
Nombre
Tipo de fichero
Carpeta
Grandaria
Grandaria comprimida
Atributos
Creyau
Zaguer acceso
Zaguera modificación
Compacto
Comentario
Zifrau
Expandiu antis
Expandiu dimpués
Diccionario
CRC
Tipo
Anti
Metodo
SO d'orichen
Sistema de fichers
Usuario
Grupo
Bloque
Comentario
Posición
Prefixo de rota
Carpeta
Fichers
Versión
Fragmento
Multiframento
Desplazamiento
Vinclos
Bloques
Fragmentos
64-bit
Big-endian
CPU
Grandaria fisica
Grandaria d'as cabeceras
Suma de comprebación
Caracteristicas
Adreza virtual
ID
Nombre curto
Aplicación creyadera
Grandaria de sector
Modo
Vinclo
Error
Espacio total
Espacio libre
Grandaria de sector
Etiqueta
Nombre local
Proveyedor
2100
Opcions
Luenga
Luenga:
Editor
&Editor:
&Diff:
2200
Sistema
Asociar 7-Zip con:
2301
Integrar 7-Zip en o menú contextual de Windows
Menú contextual en cascada
Elementos d'o menú contextual:
2320
<Carpeta>
<Archivo>
Ubrir archivo
Extrayer-ne os fichers...
Adhibir a l'archivo...
Comprebar l'archivo
Extrayer aquí
Extrayer en {0}
Adhibir a {0}
Comprimir y ninviar por correu...
Comprimir en {0} y ninviar por correu
2400
Carpeta
Carpeta de &treballo
Carpeta temporal d'o &sistema
Carpeta &actual
&Especificar una carpeta:
No emplegar que ta dispositivos extrayibles
Especificar una carpeta ta archivos temporals.
2500
Propiedatz
Amostrar l'elemento ".."
Amostrar iconos propios
Amostrar o menú d'o sistema
&Seleccionar ringlera(s) completa(s)
Amostrar as linias d'a &quadricla
Clicar una vegada ta ubrir elemento
Modo de selección &alternativo
Emplegar pachinas de memoria &grans
2900
Arredol de 7-Zip
7-Zip ye un programa libre y gratuito. Si quiers, puetz colaborar en o desembolique de 7-Zip rechistrando-te ta contribuyir a amillorar o programa.
3000
O sistema no ha puesto asignar a cantidat necesaria de memoria
No i hai errors
{0} elemento(s) seleccionau(s)
No se puet creyar a carpeta '{0}'
Ista mena d'archivo no permite actualización.
No se puet ubrir o fichero '{0}' como archivo comprimiu
No se puet ubrir l'archivo zifrau '{0}'. Comprebe si a clau ye incorrecta.
Tipo d'archivo no admeso
O fichero {0} ya existe
O fichero '{0}' s'ha modificau.\nQuiers esviellar-lo en l'archivo?
No se puet esviellar o fichero\n'{0}'
No se puet executar l'editor.
O fichero pareix un virus (o nombre d'o fichero contiene espacios largos).
No se puet execitar ista operación dende una carpeta que tienga una rota larga.
Has de seleccionar un fichero
Has de seleccionar un u más fichers
Masiaus elementos
3300
Extrayendo
comprimindo
Prebando
Ubrindo...
Buscando...
3400
Extrayer
E&xtrayer a:
Selecciona un destín ta os fichers extrayius.
3410
Modo de rota
Rotas completas
Sin rotas
3420
Modo de sobrescritura
Con confirmación
Sin confirmación
Conservar os fichers ya existents
Renombrar automaticament
Renombrar automaticament os fichers ya existents
3500
Confirmar a substitución de fichers
A carpeta de destín ya contiene un fichero con o mesmo nombre.
Quiers substituyir o fichero existent
por iste atro?
{0} bytes
Renombrar a&utomaticament
3700
Metodo de compresión no valido ta '{0}'.
Error de datos en '{0}'. O fichero ye corrompiu.
O CRC ha fallau en '{0}'. O fichero ye corrompiu.
Error de datos en o fichero zifrau '{0}'. Verifica a clau.
Error de CRC en o fichero zifrau '{0}'. Verifica a clau.
3800
Escribe a clau
Escribe a clau:
Torne a escribir a clau:
&Amostrar a clau
As claus son diferents. Por favor, torne a escribir-la.
Emplega en a clau nomás as letras de l'alfabeto anglés, numeros y caracters especials (!, #, $, ...)
A clau ye masiau larga.
Contrasenya
3900
Tiempo transcorriu:
Tiempo pendient:
Grandaria:
Velocidat:
Procesau:
Razón de compresión:
Errors:
Archivos:
4000
Adhibir a l'archivo
&Archivo:
M&odo d'actualización:
&Formato d'archivo:
&Libel de compresión:
&Metodo de compresión:
Grandaria de &diccionario:
Granda&ria d'a parola:
Grandaria de bloque compacto:
Numero de filos d'a CPU:
&Parametros:
Opcions
Creyar archivo SF&X (autoextrayible)
Comprimir fichers compartius
Encriptación
Metodo d'e &zifrau:
Zifrar &nombres de fichero
Memoria emplegada ta comprimir:
Memoria emplegada ta descomprimir:
4050
Sin compresión
A mas rapida
Rapida
Normal
Maxima
Ultra
4060
Adhibir y substituyir fichers
Esviellar y adhibir-ie fichers
Esviellar fichers ya presents
Sincronizar fichers
4070
Explorar
Totz os fichers
No compacto
Compacto
6000
Copiar
Mover
Copiar en:
Mover ta:
Copiando...
Movendo...
Renombrando...
Selecciona a carpeta de destín
Operación no permitida.
Error en enombrar un fichero u carpeta
Confirmar a copia d'o fichero
Yes seguro de que quiers copiar os fichers en l'archivo
6100
Confirmar borrau de fichero
Confirmar borrau de carpeta
Confirmar borrau multiple fichers
Yes seguro que quiers borrar '{0}'?
Yes seguro que quiers borrar a carpeta '{0}' y tot o suyo conteniu?
Yes seguro que quiers borrar istos {0} elementos?
Borrando...
Error borrando fichero u carpeta
O sistema no puet mover un fichero con rota larga ta la Papelera de Reciclache
6300
Creyar carpeta
Creyar fichero
Nombre de'a carpeta:
Nombre de'o fichero:
Carpeta nueva
Fichero nuevo
Error en creyar carpeta
Error en creyar o fichero:
6400
Comentario
&Comentario:
Seleccionar
Deseleccionar
Patrón:
6600
Propiedatz
Historial de carpetas
Mensaches de diagnostico
Mensache
7100
O mío ordinador
Entorno de ret
Documentos
Sistema
7200
Adhibir
Extrayer
Prebar
Copiar
Mover
Borrar
Información
7300
Dividir fichero
Di&vidir a:
Dividir en fra&gmentos (bytes):
Dividindo...
Confirmar a división
Yes seguro que quiers dividir o fichero en {0} fragmentos?
A grandaria d'os fragmentos ha d'estar menor que a d'o fichero orichinal
Grandaria de fragmento incorrecta
Grandaria de fragmento especificada: {0} bytes.\nYe seguro que quiere dividir o fichero en fragmentos d'ixa grandaria?
7400
Combinar fichers
&Combinar en:
Combinando...
Selecciona només o primer fichero
No s'ha puesto detectar o fichero como parti d'un fichero por fragmentos
No s'ha puesto trobar que un fragmento d'o fichero por fragmentos
7500
Calculando a suma de verificación...
Suma de verificación (CRC)
CRC d'os datos:
CRC d'os datos y os nombres:
7600
Prebas de referencia (benchmark)
Emplego de memoria:
Compresión
Descompresión
Taxa
Taxa total
Actual
Resultant
Emplego de CPU
Taxa / Emplego
Pasadas:

495
Utils/7-Zip/Lang/ar.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; 9.07 :ترجمةالاستاذ:عوض ال-عائض الغامدي
; 9.07 : Awadh A Al-Ghaamdi
;
; 15.00 : 2016-08-28 : تعديل وتصحيح الترجمة: سيف حسام الاسدي
; 15.00 : 2016-08-28 : Saif H Al-asadi (edited and corrected)
;
;
;
;
;
;
0
7-Zip
Arabic
عربي
401
حسنا
إلغاء الأمر
&نعم
&لا
&إغلاق
المساعدة
&استمرار
440
نعم للكل
لا للكل
إيقاف
إعادة تشغيل
&بالخلفية
&بالمقدمة
&إيقاف مؤقت
متوقف مؤقتا
هل أنت متأكد من الإلغاء؟
500
&الملف
&التعديل
&العرض
التف&ضيلات
&ألادوات
&المساعدة
540
&فتح
&افتح بالداخل
&افتح للخارج
&عرض
&تعديل
إعادة التسمية
..نسخ إلى
..نقل إلى
&حذف
&تقسيم الملف...
دم&ج الملفات...
الخ&صائص
تعليق&
حساب قيمة التدقيق
فرق
إنشاء مجلد
إنشاء ملف
خروج
الربط
&الجداول البديلة
600
تحديد الكل
عدم تحديد الكل
عكس التحديد
تحديد...
عدم تحديد...
تحديد حسب النوع
عدم تحديد حسب النوع
700
رموز كبيرة
رموز صغيرة
&القائمة
&التفاصيل
730
غير مرتب
العرض الافقي
&مجموعتين
&أشرطة الأدوات
فتح المجلد الرئيسي
للأعلى بمستوى واحد
...محفوظات المجلدات
&تحديث
تحديث تلقائي
750
شريط أدوات الأرشفة
شريط ألادوات قياسي
أزرار كبيرة
إظهار تسميات الازرار
800
&إضافة المجلد للمفضلة باسم
العلامات المرجعية
900
...&الخيارات
&معالج الاداء
960
..&المحتويات
7-Zip &حول...
1003
المسار
الإسم
الإمتداد
المجلد
الحجم
الحجم المضغوط
الخواص
تم انشاءه
تم الدخول
تم تعديله
ثابت
تم التعيلق
مشفر
التقسيم قبل
التقسيم بعد
القاموس
النوع
متعدد
الطريقة
نظام التشغيل
ملفات النظام
المستخدم
المجموعة
التكتل
التعليق
الموقع
بادئة المسار
المجلدات
الملفات
الإصدار
وحدة التخزين
وحدة تخزين متعددة
التعويض
روابط
كتل
وحدات تخزين
64-بت
Big-endian
CPU
الحجم الطبيعي
حجم المقدمات
قيمة التحقق
المميزات
العنوان الظاهري
الهوية
إسم قصير
برنامج الانشاء
حجم القطاع
الوضع
الرابط الرمزي
خطأ
الحجم الكلي
المساحة الحرة
حجم الجزء
العلامة
الإسم المحلي
المجهز
NT أمان
الجداول البديلة
Aux
تم حذفة
التفرعات
خطأ في النوع
اخطاء
اخطاء
تحذيرات
تحذير
الجداول
الجداول البديلة
حجم الجداول البديلة
الحجم الظاهري
حجم الاخراج
الحجم الطبيعي الكلي
دليل الحجم
النوع الفرعي
تعليق قصير
رمز الصفحة
حجم التذييل
حجم العقبات المضمن
الارتباط
الارتباط الصعب
iNode
للقراءة-فقط
2100
الخيارات
اللغة
ترجمةالأستاذ عوض الغامدي -التعديل سيف الاسدي
المحرر
&المحرر:
ال&فرق:
2200
النظام
تكامل البرنامج مع :
جميع المستخدمين
2301
الإندماج مع قائمة الزر الايمن
تتالي قائمة الزر الايمن
عناصر قائمة الزر الايمن :
الايقونات في قائمة الزر الايمن
2320
<مجلد>
<إرشيف>
فتح ارشيف
استخراج الملفات...
إضافة إلى الإرشيف...
فحص الإرشيف
إستخرج هنا
إستخرج إلى {0}ـ
إضافة إلى {0}ـ
ضغط ثم إرسال...
ضغط إلى {0} ثم إرسال
2400
مجلدات
&مجلد العمل
&مجلد النظام المؤقت
&الحالي
&محدد:
الإستخدام فقط للأقراص المتحركة
تحديد موضع للإرشيف المؤقت للملفات
2500
الاعدادات
".." إظهار عنصر
إظهار أيقونات الملف الفعلية
إظهار قائمة النظام
&تحديد الصف بالكامل
إظهار خطوط الشبكة
نقرة واحدة لفتح أي مادة
&نظام تحديد بديل
إستعمال &صفحات ذاكرة كبيرة
2900
حول البرنامج
7-Zip البرنامج مجاني
3000
لا يمكن للنظام تخصيص الكمية المطلوبة للذاكرة
لا يوجد أخطاء
تم تحديد {0} عنصر
'{0}' لا يمكن إنشاء المجلد
تحديث العمليات غير مدعوم لهذا الإرشيف
كأرشيف '{0}' لا يمكن فتح الملف
كلمة المرور خطأ ؟ . '{0}' تعذر فتح الأرشيف المشفر
نوع أرشيف غير معتمد
موجود مسبقا {0} الملف
أتريد تحديثه في الإرشيف ؟\nالملف '{0}' تم تعديله
لا يمكن تحديث الملف\n'{0}'
لا يمكن بدء المحرر
(الملف يشبه فيروس (إسم الملف يحتوي على مسافات طويلة
لا يمكن إستدعاء العملية من مجلد له مسار طويل
يجب تحديد ملف واحد
يجب تحديد ملف واحد أو أكثر
عناصر كثيرة جداً
لايمكن فتح الملف {0} كأرشيف
الملف مفتوح {0} كأرشيف
ان الارشيف مفتوح بطريقة الطباعة بالاوفسيت
3300
استخراج
الضغط
فحص
...فـتـح...
...يتم التفحص
تتم الازالة
3320
يتم الاضافة
يتم التحديث
يتم التحليل
يتم التكرار
يتم اعادة الضغط
يتم التجاهل
يتم الحذف
يتم انشاء المقدمة
3400
استخراج
استخراج إلى:
تحديد الموضع للملفات المستخرجة
3410
حالة المسار
اسم المسار بالكامل
بدون اسم المسار
اسم المسار المطلق
اسم المسار النسبي
3420
حالة إعادة الكتابة
السؤال قبل إعادة الكتابة
إعادة الكتابة بدون تنبيه
تجاوز الملفات المتوفرة
تسمية تلقائية
تسمية الملفات الموجودة تلقائياً
3430
ازالة تكرارات المجلد الرئيسي
استعادة ملف الامان
3500
تأكيد استبدال الملف
المجلد الهدف يحوي مسبقاً الملف
أتريد استبدال الملف الموجود؟
بهذا الملف؟
{0} بايت
إعادة تسمية تلقائية
3700
'{0}'طريقة ضغط غير معتمدة لـ
'{0}'خطأ بيانات في. الملف تالف
'{0}' خطأ بصمة في . الملف تالف
خطأ بيانات في الملف المشفر '{0}' . كلمة المرور غير صحيحة ؟
فشل الفحص الدوري في الملف المشفر '{0}' . كلمة المرور غير صحيحة ؟
3710
كلمة مرور خاطئة?
3721
طريقة ضغط غير مدعومة
بيانات خطأ
CRC فشل
بيانات غير متاحة
النهاية المفاجئة للبيانات
هناك بعض البيانات بعد نهاية بيانات الحمولة
ليس ارشيفاً
مقدمات خطأ
كلمة مرور خاطئة
3763
البداية غير متوفرة للارشيف
البداية غير مؤكدة للارشيف
ميزة غير مدعومة
3800
أدخل كلمة المرور
أدخل كلمة المرور:
إعادة كلمة المرور :
&إظهار كلمة المرور
كلمتا المرور غير متطابقتان
أستخدم فقط حروف إنجليزية و أرقام و علامات خاصة (!,#,,$ ...) لكلمة المرور
كلمة المرور طويلة جدا
كلمة المرور
3900
الزمن المنقضي:
الزمن المتبقي:
الحجم الكلي:
السرعة:
المعالج:
نسبة الضغط:
الأخطاء:
ملفات الإرشيف:
4000
إضافة للإرشيف
&الإرشيف:
&حالة التحديث:
صيغة الإرشيف:
مستوى الضغط&:
طريقة الضغط:
&حجم المعجم:
&حجم الكلمة:
حجم الكتلة الخاصة :
CPU عدد مؤشرات الـ :
&أوامر إضافية:
الخيارات
إنشاء إرشيف ذاتي الإستخراج
ضغط الملفات المشاركة
التشفير
طريقة التشفير :
تشفير أسماء ال&ملفات
إستهلاك الذاكرة للضغط :
إستهلاك الذاكرة لإلغاء الضغط :
حذف الملفات بعد الضغط
4040
خزن الاتباطات الرمزية
خزن الارتباطات الصعبة
خزن جداول البيانات البديلة
خزن ملف الامان
4050
للخزن
ألاسرع
السريع
الطبيعي
المرتفع
ألاقصى
4060
إضافة واستبدال الملفات
تحديث و إضافة الملفات
تجديد الملفات المتوفرة فقط
مزامنة الملفات
4070
إستعراض
كافة الملفات
غير خالص
خالص
6000
نسخ
نقل
نسخ إلى:
نقل إلى:
...نـسـخ...
...نـقـل...
إعادة تسمية...
تحديد مجلد الوجهة
العملية غير معتمدة
حدوث خطأ لدي إعادة تسمية الملف أو المجلد
تأكيد نسخ الملف
هل أنت متأكد من نسخ الملفات للإرشيف؟
6100
تأكيد الحذف للملف
تأكيد الحذف للمجلد
تأكيد الحذف للملفات
'؟ {0}'هل أنت متأكد من حذف
هل أنت متأكد من حذف المجلد '{0}' و كافة محتوياته ؟
؟ {0} هل أنت متأكد من حذف العناصر التالية
حذف...
حدوث خطأ لدي حذف الملف أو المجلد
لا يمكن للنظام نقل ملف له مسار طويل إلى سلة المحذوفات
6300
إنشاء مجلد
إنشاء ملف
اسم المجلد:
اسم الملف:
مجلد جديد
ملف جديد
حدوث خطأ لدي إنشاء المجلد
حدوث خطأ لدي إنشاء الملف
6400
تعليق
&تعليق:
تحديد
عدم تحديد
إخفاء:
6600
خصائص
محفوظات المجلدات
رسائل الفاحص
رسالة
7100
جهاز الكمبيوتر
الشبكة
المستندات
النظام
7200
إضافة
إستخراج
فحص
نسخ
نقل
حذف
معلومات
7300
تقسيم الملف
&التقسيم إلى:
التقسيم لكتل أو بايتات:
تقسيم...
تأكيد التقسيم
هل تريد فعلا تقسيم الملف إلى {0} كتلة ؟
يجب أن يكون حجم الكتلة أصغر من حجم الملف الأصلي
كتلة الحجم غير صحيحة
حجم الكتلة المعين : {0} بايت\nهل تريد فعلا تقسيم الأرشيف إلى مثل هذه الكتل ؟
7400
دمج الملفات
&دمج إلى:
دمج...
حدد فقط الجزء الأول من ملف التقسيم
لا يمكن إكتشاف الملف كجزء من ملف التقسيم
لا يمكن العثور على أكثر من جزء واحد من ملف التقسيم
7500
...يتم حساب مجموعة الإختبار
معلومات مجموعة الإختبار
للبيانات CRC مجموعة الإختبار:
للبيانات و للأسماء CRC مجموعة الإختبار:
7600
تقييم الأداء
إستخدام الذاكرة:
ضغط
فك ضغط
المعدل
المعدل الكلي
الحالي
الناتج
CPU إستهلاك الـ
التقدير / الإستهلاك
العمليات:
7700
الرابط
الارتباط
ربط من:
ربط الى:
7710
نوع الربط
ربط قوي
ربط الملف الرمزي
ربط القاموس الرمزي
قاموس الربط

404
Utils/7-Zip/Lang/ast.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.07 : Dinamiteru
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Asturian
Asturianu
401
Val
Torgar
&Si
&Non
&Zarrar
Axuda
&Siguir
440
Si a &Too
Non a T&oo
Parar
Reentamar
&De fondu
&En primer planu
&Posar
Posao
¿Tas fixu que quies paralo?
500
F&icheru
&Remanar
&Ver
F&avoritos
&Ferramientes
A&xuda
540
&Abrir
Abrir &Dientro
Abrir F&uera
&Ver
&Remanar
Reno&mar
&Copiar a...
&Mover a...
&Borrar
&Partir ficheru...
Com&binar ficheros...
P&ropiedaes
Come&ntariu
Crear carpeta
Crear ficheru
Co&lar
600
Seleicionar &Too
Deseleicionar too
&Invertir seleición
Seleicionar...
Deseleicionar...
Seleicionar por Tipu
Deseleicionar por Tipu
700
Miniatures &Grandes
&Miniatures Pequeñes
&Llista
&Detalles
730
Ensín Ordenar
&2 Paneles
&Barres de Ferramientes
Abrir Carpeta Raiz
Xubir Un Nivel
Hestorial de Carpetes...
Actualiza&r
750
Barra Ferramientes d´Archivu
Barra Ferramientes Normal
Botones Grandes
Amosar Testu nos Botones
800
&Añedir carpeta a Favoritos como
Marca
900
&Opciones...
&Bancu de Pruebes
960
&Conteníos...
&Al rodiu 7-Zip...
1003
Ruta
Nome
Estensión
Carpeta
Tamañu
Tamañu comprimío
Atributos
Creao
Accedío
Cambiao
Sólidu
Comentao
Cifrao
Partir antes
Partir dempués
Diccionariu
CRC
Tipu
Anti
Métodu
S.O. d´Acoyida
Sistema de ficheros
Usuariu
Grupu
Bloque
Comentariu
Posición
Error
Tamañu total
Espaciu llibre
Tamañu del clúster
Etiqueta
Nome llocal
Suministrador
2100
Opciones
Llingua
Llingua:
Remanaor
&Remanaor:
2200
Sistema
Asociar 7-Zip con:
2301
Integrar 7-Zip nel menú contestual
Menú contestual en ´cascada´
Artículos del menú contestual:
2320
<Carpeta>
<Archivu>
Abrir archivu
Estrayer ficheros...
Añedir al archivu...
Probar archivu
Estrayer equí
Estrayer a {0}
Añedir a {0}
Comprimir y mandar per correu...
Comprimir en {0} y mandar per correu
2400
Carpetes
&Carpeta de trabayu
Carpeta &temporal de sistema
&Actual
&Especificar:
Usar sólo pa dispositivos estrayibles
Especificar llocalización pa ficheros d´archivos temporales.
2500
Igües
Amosar ".." artículu
Amosar les miniatures reales del ficheru
Amosar menú del sistema
Seleicionar tola &fila
Amosar les llinies de la &cuadrícula
2900
Al rodiu 7-Zip
7-Zip ye software llibre. De toos moos, tú pues sofitar el desendolcu de 7-Zip rexistrándote.
3000
Ensín errores
{0} oxetu(os) seleicionaos
Nun se puede crear la carpeta '{0}'
Esti archivu nun permite les operaciones d´actualización.
El ficheru '{0}' foi modificáu.\nDo ¿Quies actualizalu nel archivu?
Nun se pudo actualizar l´archivu\n'{0}'
Nun se pudo entamar el Remanaor.
Demasiaos artículos
3300
Estrayendo
Comprimiendo
Probando
Abriendo...
3400
Estrayer
E&strayer a:
Especificar llocalización pa ficheros estrayíos.
3410
Mou de ruta
Nomes de ruta completos
Ensín nomes de ruta
3420
Mou de sobreescritura
Entrugar enantes de sobreescribir
Sobreescribir ensín confirmación
Dexar ficheros esistentes
Auto renomar
Auto renomar ficheros esistentes
3500
Confirmar sustitución de ficheros
La carpeta destín yá tien el ficheru procesáu.
¿Quiés sustituyir el ficheru esistente
con esti otru?
{0} bytes
A&uto Renomar
3700
Métodu de compresión nun permitíu pa '{0}'.
Error de datos en '{0}'. El ficheru ta rotu.
El CRC falló en '{0}'. El ficheru ta rotu.
3800
Introduz clave
Introduz clave:
Amo&sar clave
Clave
3900
Tiempu trescurríu:
Tiempu pa finar:
Tamañu:
Velocidá:
Errores:
4000
Añedir al archivu
&Archivu:
Mo&u d´actualización:
&Formatu del archivu:
Nive&l de compresión:
&Métodu de compresión:
Tamañu del &Diccionariu:
Tamañu de la pa&llabra:
&Parámetros:
Opciones
Crear archivu SF&X
Cifrar &nomes de ficheru
Usu de memoria pa la compresión:
Usu de memoria pa la descompresión:
4050
Nenguna
Más rápida
Rápida
Normal
Másima
Ultra
4060
Añedir y sustituyir ficheros
Actualizar y añedir ficheros
Actualizar ficheros esistentes
Sincronizar ficheros
4070
Agüeyar
Tolos ficheros
6000
Copiar
Mover
Copiar a:
Mover a:
Copiando...
Moviendo...
Renomando...
La operación nun tá permitía.
Error al renomar el ficheru o carpeta
6100
Confirmar Borráu de Ficheru
Confirmar Borráu de Carpeta
Confirmar Borráu Múltiple de Ficheros
¿Tas fixu que quies borrar '{0}'?
¿Tas fixu que quies borrar la carpeta '{0}' y tolos sos conteníos?
¿Tas fixu que quies borrar estos {0} artículos?
Borrando...
Error al borrar el ficheru o carpeta
6300
Crear Carpeta
Crear ficheru
Nome de la carpeta:
Nome del ficheru:
Nueva carpeta
Nuevu ficheru
Error al crear la carpeta
Error al crear el ficheru
6400
Comentariu
&Comentariu:
Seleicionar
Deseleicionar
Mazcarita:
6600
Hestorial de carpetes
Mensaxes de diagnósticu
Mensax
7100
Ordenador
Rede de Trabayu
Sistema
7200
Añedir
Estrayer
Probar
Copiar
Mover
Borrar
Información
7300
Partir Ficheru
&Partir a:
Partir en &cachos, bytes:
Partiendo...
7400
Combinar Ficheros
&Combinar a:
Combinando...
7500
7600
Bancu de Pruebes
Usu de memoria:
Comprimiendo
Descomprimiendo
Valoración
Valoración total
Actual
Resultáu
Correutos:

495
Utils/7-Zip/Lang/az.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; 9.07 : F@rhad
; 15.02 : 22/05/2015 : Г. Гасымов
;
;
;
;
;
;
;
;
;
0
7-Zip
Azerbaijani
Azərbaycanca
401
OLDU
İmtina
&Bəli
&Xeyr
&Bağla
Kömək
&Davam
440
&Hamısına Bəli
Ha&mısına Xeyr
Dayan
Yenidən başla
&Arxa planda
Ö&ndə
F&asilə
Fasilədə
Həqiqətən əməliyyatı dayandırmaq istəyirsiniz?
500
&Fayl
&Düzəliş
&Görünüş
S&eçilmişlər
&Vasitələr
&Arayış
540
&Aç
&Daxildə Aç
B&ayırda aç
&Baxış
&Düzəliş
Ye&nidən Adlandır
&Nüsxələ...
&Köçür...
&Sil
Faylı &Böl...
Faylları B&irləşdir...
X&üsusiyyətlər
Şər&h...
Yoxlama Cəmi
Müqayisə
Qovluq Yarat
Fayl Yarat
Ç&ıxış
İstinad
&Əvəzedici Axınlar
600
&Hamısını Seç
Seçimi Ləğv Et
&Seçimi Çevir
Seç...
Seçimi Ləğv Et...
Növünə Görə Seç
Növünə Görə Seçimi Ləğv Et
700
&Böyük İşarələr
K&içik İşarələr
&Siyahı
&Cədvəl
730
Çeşidsiz
Müstəvi Görünüş
&2 Lövhə
&Alətlər Lövhələri
Kök Qovluğu Aç
Bir Səviyyə Yuxarı
Qovluqlar Tarixçəsi...
&Yenilə
Bilavasitə Yeniləmə
750
Arxivləyicinin Düymələr Lövhəsi
Sadə Düymələr Lövhəsi
Böyük Düymələr
Düymələr Üzərində Mətnlər
800
&Qovluğu Seçilmişlərə Fərqli Əlavə Et
Əlfəcin
900
Tənzimləmələr...
Səmərə Sınağı
960
&Başlıq...
7-Zip &Haqqında...
1003
İstiqamət
Ad
Genişləmə
Qovluq
Ölçü
Sıxılmış
Rəmzlər
Yaranıb
ıq
Dəyişilib
Aramsız
Şərh
Şifrələnib
Əvvəlki parça
Sonrakı parça
Lüğət
Növ
Əleyhinə
Sıxılma Üsulu
Quruluş
Fayl Quruluşu
İstifadəçi
Dəstə
Bölmə
Şərh
Mövqe
İstiqamət
Qovluq
Fayl
Buraxılış
Cild
Çox Cildli
Uzlaşma
İstinad
Bölmə
Cild
Prosessor
Fiziki Ölçü
Başlıqlar Ölçüsü
Yoxlama Cəmi
Xassələr
Xəyali Ünvan
Qısa Ad
Yaradıcı
Sahə Ölçüsü
Vəziyyət
Rəmzi İstinad
Xəta
Cəmi Həcm
Azad Həcm
Toplam Həcm
Nişan
Qısa Ad
Təchizatcı
NT Təhlükəsizlik
Əvəzedici Axın
Silinmiş
Ağac
Xəta Növü
Xətalar
Xətalar
Xəbərdarlıqlar
Xəbərdarlıq
Axınlar
Əvəzedici Axınlar
Əvəzedici Axınlar Ölçüsü
Xəyali Ölçü
Ceşidli Ölçü
Ümumi Fiziki Ölçü
Cild Nömrəsi
Növaltı
Qısa Şərh
Şifrələnmiş Səhifə
Qalıq Ölçüsü
Tətbiq Olunmuş Bölmə Ölçüsü
İstinad
Sərt İstinad
iNode
Yalnız Oxumaq Üçün
2100
Tənzimləmələr
Dil
Dil:
Düzəliş
&Düzəliş:
&Müqayisə:
2200
Quruluş
7-Zip Fayllarla Əlaqələnsin
Bütün İstifadəçilər
2301
7-Zip əhatə təklifinə tətbiq edilsin
Zəncirvari əhatə təklifi
Ünsürlü əhatə təklifi:
Əhatə təklifində nişanlar
2320
<Qovluq>
<Аrxiv>
Arxivi Aç
Çeşidlə
Arxivə Əlavə Et...
Sınaq
Burda Çeşidlə
{0} Çeşidlə
{0} Əlavə Et
Sıx Və E-Poçtla Göndər...
{0} Sıx Və E-Poçtla Göndər
2400
Qovluqlar
&İş Qovluğu
&Müvəqqəti Quruluş Qovluğu
&Cari
&Təyin Et:
Yalnız dəyişkən daşıyıcılar üçün istifadə
Müvəqqəti arxivlər üçün yer göstər.
2500
Tənzimləmələr
".." ünsürünü göstər
Həqiqi fayl işarələri göstər
Quruluş təklifini göstər
Ox bütün sətir üzrə
Ayrıcıları Göstər
Bir Toxunuşla Aç
Əvəzedici vəziyyət işarələnməsi
Böyük yaddaş səhifələri istifadəsi
2900
7-Zip Haqqında
7-Zip Sərbəst Yayılan Proqramdır
3000
Kifayət qədər boş yaddaş yoxdur
Səhvlər tapılmadı
{0} Ayrılmış hədəf
'{0}' Qovluğunu yaratmaq mümkün olmadı
Bu arxiv üçün dəyişiklik əməliyatı dəstəklənmir
'{0}' Faylını arxiv kimi açmaq alınmadı
Şifrələnmiş '{0}' arxivini açmaq alınmadı. Yanlış şifrə?
Dəstəklənməyən arxiv
{0} faylı artıq mövcuddur
'{0}' faylına dəyişiklik edildi.\nSiz onu arxivdə yeniləmək istəyirsiz?
\n'{0}' faylını yeniləmək alınmadı
Redaktəni işə salmaq alınmadı
Fayl zərərvericiyə oxşayır (faylın adı uzun boşluq ardıcıllığı təşkil edir).
Əməliyyat uzun yol təşkil edən qovluqdan icra oluna bilmir.
Siz bir fayl seçməlisiniz
Siz bir və ya bir neçə fayl seçməlisiniz
Həddən çox ünsür
Faylı, '{0}' arxivi kimi açmaq alınmadı
Fayl, {0} arxivi kimi açıldı
Arxiv əvəzlənərək açıldı
3300
Çeşidlənmə
Sıxılma
Sınaq
ılma...
Yoxlama...
Silinmə
3320
Əlavə Etmək
Yenilənmə
Təhlil
Nüsxələnmə
Yenidən Çeşidlənmə
Keçmə İcazəsi
Silinmə
Başlıqlar Yaradılması
3400
Ayır
Ç&eçidlə:
Ayrılan faylların yerini göstərin.
3410
Fayllara istiqamət:
Tam istiqamətlər
İstiqamətsiz
Mütləq istiqamətlər
Nisbi istiqamətlər
3420
Yenidən yazılma:
Təsdiqli
Təsdiqsiz
Ötürmək
Birbaşa yenidən adlandır
Mövcud olanları yenidən adlandır
3430
Kök qovluqla bənzərliyi aradan qaldır
Faylın təhlükəsizlik bərpası
3500
Faylın əvəzlənmə təsdiqi
Qovluq artıq emal olunan fayl təşkil edir.
Mövcud faylı əvəzlə
növbəti faylla?
{0} bayt
Birbaşa yenidən adlandır
3700
'{0}' faylının dəstəklənməyən sıxılma üsulu.
'{0}' məlumatlarında xəta. Fayl korlanıb.
'{0}' CRC xətası. Fayl korlanıb.
'{0}' şifrəli fayl məlumatlarında xəta. Yanlış şifrə?
'{0}' şifrəli faylı üçün CRC xətası. Yanlış şifrə?
3710
Yanlış şifrə?
3721
Dəstəklənməyən sıxılma üsulu
Dəlillərdə xəta
CRC xətası
Mövcud olmayan dəlillər
Dəlillərin gözlənilməz sonu
Bölmənin sonunda faydalı dəlillər olduğuna dəlillər var
Arxiv deyil
Başlıqlarda Xəta
Yanlış şifrə
3763
Arxivin əvvəli mövcud deyil
Təsdiqsiz arxiv əvvəli
Dəstəklənməyən xüsusiyyət
3800
Şifrə daxil etmə
&Şifrə daxil edin:
Şifrəni təkrarlayın:
&Şifrəni göstər
Şifrələr uyğun deyil
Şifrə üçün yalnız latın hərfləri, rəqəmlər və xüsusi rəmzlər istifadə edin (!, #, $, ...)
Şifrə şox uzundur
&Şifrə
3900
Keçdi:
Qalıb:
Cəmi:
Sürət:
Ölçü:
Sıxılma dərəcəsi:
Xəta:
Arxiv:
4000
Arxivə əlavə etmək
&Arxiv:
&Dəyişmə vəziyyəti:
Arxiv &qismi:
Sıxılma &dərəcəsi:
Sıxılma &üsulu:
&Lüğət ölçüsü:
&Söz ölçüsü:
Bölmə ölçüsü:
Axın sayı:
&Nizamlar:
&Seçimlər
SF&X arxiv yarat
Yazılış üçün açıq faylları sıx
Şifrələmə
Şifrələmə üsulu:
Fayl adlarını &şifrələ
Qablaşdırma üçün yaddaş həcmi:
Çeşidləmə üçün yaddaş həcmi:
Sıxılmadan sonra faylları sil
4040
Rəmzli keçidləri saxla
Sərt keçidləri saxla
Əvəzedici axınları saxla
Giriş hüququnu saxla
4050
Sıxılmasız
Sürətli
Cəld
Məqbul
Yüksək
Daha Yüksək (Ultra)
4060
Əlavə et və əvəzlə
Yenilə və əlavə et
Yenilə
Eyniləşdir (Sinxron)
4070
Vərəqlə
Bütün Fayllar
Fayl ölçüsünə görə
Aramsız
6000
Nüsxələ
Köçür
Nüsxələ:
Köçür:
Nüsxələlənmə...
Köçürülmə...
Yenidən adlandırılma...
Qovluğu göstərin.
Əməliyyat bu qovluq üçün dəstəklənmir.
Fayl və ya Qovluğun Yenidən Adlandırılması Zamanı Xəta
Faylların Nüsxələlənmə Təsdiqi
Siz həqiqətən bu faylları arxivə nüsxələmək istəyirsiz
6100
Fayl silinmə təsdiqi
Qovluq silinmə təsdiqi
Fayllar dəstəsinin silinmə təsdiqi
Siz həqiqətən "{0}" silmək istəyirsiz?
Siz həqiqətən "{0}" qovluğunu və onun bütün məzmununu silmək istəyirsiz?
Siz həqiqətən {0} hədəfi silmək istəyirsiz?
Silinmə...
Fayl və ya Qovluq Silinməsi Zamanı Xəta
Quruluş uzun yollu faylların səbətə silinməsi əməliyyatını dəstəkləmir
6300
Qovluq Yarat
Fayl Yarat
Qovluq Adı:
Fayl Adı:
Yeni Qovluq
Yeni Fayl
Qovluq Yaradılması Zamanı Zəta
Fayl Yaradılması Zamanı Zəta
6400
Şərh
&Şərh:
Seçin
Seçimi Ləğv Edin
Üzlük (Maska):
6600
Xassələr
Qovluqlar Tarixçəsi
İsmarıclar
İsmarıc
7100
Kompüter
Şəbəkə
Sənədlər
Quruluş
7200
Əlavə Et
Ayır
Sınaq
Nüsxələ
Köçür
Sil
Məlumat
7300
Fayl Bölmək
&Bölmək:
Cildlərə &bölmək, (bayt) ölçüdə:
Bölünmə...
Bölünmə Təsdiqi
Siz həqiqətən faylı {0} hissəyə bölmək istəyirsiz?
Cild ölçüsü ilkin fayl ölçüsündən kiçik olmalıdır
Cildlərin ölçü təyin etmə sahəsində xəta
Təyin edilmiş cild ölçüsü: {0} bayt.\nSiz həqiqətən arxivi belə cildlərə bölmək istəyirsiniz?
7400
Faylları Birləşdir
&Birləşdirmək:
Birləşmə...
Bölünmüş faylın yalnız birinci hissəsini seçmək lazımdır
Bölünmüş faylın tanınması mümkün olmadı
Bölünmüş faylın birdən çox hissəsini tapmaq mümkün olmadı
7500
Yoxlanma cəminin hesablanması...
Yoxlanma cəmi
Dəlillər üçün CRC yoxlanma cəmi:
Dəlillər və adlar üçün CRC yoxlanma cəmi:
7600
Səmərə Sinağı
Yaddaş Həcmi:
Qablaşdırma
Çeşidlənmə
Dərəcə
Ümumi Dərəcə
Cari
Nəticə
Yüklənmə
Yüklənmə Dərəcəsi
Keçid:
7700
İstinad
Əlaqələndir
Mənbə:
Məqsəd:
7710
İstinad Qismi
Sərt İstinad
Rəmzi İstinad (Fayl)
Rəmzi İstinad (Qovluq)
Bağlantı Nöqtəsi (Qovşaq)

404
Utils/7-Zip/Lang/ba.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 9.20 : Haqmar : www.bashqort.com
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Bashkir
Башҡортса
401
Тамам
Кире ал
&Эйе
&Юҡ
&Яп
Ярҙам
&Дауам
440
Бөтәһенә лә Э&йе
Бө&тәһенә лә Юҡ
Туҡта
Яңынан башла
&Артҡы планда
А&лғы планда
&Туҡтатып тор
Паузала
Был эште ысынлап та өҙөргә теләйһегеҙме?
500
&Файл
Һа&йлау
&Күренеш
Һ&айланмалар
&Сервис
&Белешмә
540
&Асырға
&Эсендә асырға
&Тышта асырға
Ҡа&рау
&Мөхәррирләргә
&Исемен алыштырырға
&Күбәйтергә...
Кү&серергә...
&Юйырға
Файлды &бүл...
Файлдар бер&ләштереү...
Мәғ&лүмәт
Тас&уирлама
Тикшереү һаны
Diff
Яңы папка...
Яңы &файл...
С&ығырға
600
&Бөтәһен дә һайларға
Һай&лауҙы кире алырға
Бил&дәләнгәндәрҙе кире әйләндерергә
Маска менән һайларға...
Һайлауҙы ябырға...
Төр буйынса һайларға
Төр буйынса һайлауҙы ябырға
700
&Эре тамғалар
&Бәләкәй тамғалар
&Исемлек
&Ентекле
730
Тәртип булмаһын
Барыһын да күрһәт
&2 Панель
&Ҡоралдар панеле
Төп папканы ас
Бер кимәл юғары
Папкалар тарихы...
&Яңырт
750
&Архивлау төймәләре
Стандарт төймәләр
Эре төймәләр
Төймәләр аңлатмалы
800
Ғәмәлдәге папканы һайланғандарға өҫтәргә:
Урын
900
&Көйләү...
&Етештереүсәнлекте үлсәү
960
&Эстәлек...
7-Zip &тураhында...
1003
Юл
Исем
Киңәйеүе
Папка
Күләм
Архивдағы күләме
Атрибуттар
Яһалған
Асылған
Үҙгәртелгән
Өҙөлмәгән
Аңлатма
Серләнгән
Алдағы киҫәк
Киләһе киҫәк
Һүҙлек
CRC
Төр
Анти
Ысул
Система
Файл системаһы
Ҡулланыусы
ркөм
Блок
Тасуирлама
Урын
Юл префиксы
Папкалар
Файлдар
Версия
Том
Күп томлы
Шылыу
Һылтанмалар
Блоктар
Томдар
64-bit
Big-endian
Процессор
Физик күләме
Башлыҡтар күләме
Тикшереү суммаһы
Характеристикалар
Виртуаль адрес
ID
Ҡыҫҡа исем
Яһаусы
Сектор күләме
Режим
Һылтанма
Хата
Бар күләм
Буш урын
Кластер күләме
Билдә
Урындағы Исем
Провайдер
2100
Көйләүҙәр
Тел һайлау
Тел:
Мөхәррирләүсе
&Мөхәррирләүсе:
&Diff:
2200
Система
7-Zip менән килештер:
2301
Контекст менюла 7-Zip-ты күрһәтергә
Каскадлы контекст меню
Контекст меню элементтары:
2320
<Папка>
<Архив>
Архивты асырға
Файлдар сығарыу...
Архивғ өҫтәргә...
Архивты һынарға
Бында сығарырға
{0} папкаһына сығарырға
{0} итеп архивла
Архивлап, e-mail менән ебәрергә...
{0} итеп архивларға һәм e-mail менән ебәрергә
2400
Папкалар
&Эш папкаһы
&Ваҡытлыса система папкаһы
&Ағымдағы
&Билдәләргә:
Алмаш ташығыстар өсөн генә ҡулланырға
Ваҡытлыса архивтар өсөн урын күрһәтегеҙ.
2500
Көйләүҙәр
".." элементы күренһен
Файлдарҙың ысын тамғалары күренһен
Система менюһы күренһен
Бөтә юл һайланһын
Һыҙыҡтар күренһен
Бер сиртеү менән асырға
Альтернатив һайлау ысулы
Ҙур хәтер биттәрен ҡуллан
2900
7-Zip тураhында
7-Zip ирекле таратылған программа.
3000
Буш хәтер етмәй
Хата табылманы
{0} объект һайланған
{0} папкаһын яһап булмай
Был архивды үҙгәртеү ғәмәлен үтәп булмай.
'{0}' файлын архив һымаҡ асып булмай
Шифрланған '{0}' файлын асып булманы. Хаталы пароль?
Терәкләнмәгән архив төрө
{0} файлы бар
'{0}' файлы мөхәррирләнде.\nБыл файл архивда яңыртылһынмы?
Файлды яңыртып булманы\n'{0}'
Мөхәррирләүсене асып булманы.
Файл вирусҡа оҡшаған (файл исемендә бер-бер артлы килгән күп бушлыҡтар бар).
Ғәмәлде бындай оҙон юллы папканан үтәп булмай.
Бер файлды һайлау кәрәк
Бер йәки күберәк файлды һайлау кәрәк
Бик күп элемент
3300
Сығарыу бара...
Ҡыҫыу бара...
Һынау
Асыла...
Тарау бара...
3400
Сығар
Бында &сығар:
Сығарыласаҡ файлдар өсөн урын һайлағыҙ.
3410
Юл исемдәре
&Тулы юл исемдәре
Юл исемдәре булмаһын
3420
Өҫтөнә яҙыу
&Өҫтөнә яҙыу алдынан һора
&Өҫтөнә яҙыу алдынан һорама
Булған файлдарҙы үтеп кит
Яңы исем ҡуш
Булған файлдарға яңы исем ҡуш
3500
Файл алмаштырыуҙы раҫлағыҙ
Сығарыласаҡ папкала эшкәртелгән файл бар.
Булған
файлын киләһе менән алыштырырғамы?
{0} байт
&Яңы исем ҡушылһын
3700
'{0}' файлын ҡыҫыу ысулын табып булманы.
'{0}' файлында мәғлүмәт хатаһы бар. Файл боҙоҡ.
'{0}' файлында CRC хатаһы бар. Файл боҙоҡ.
Шифрланған '{0}' файлы мәғлүмәттәрендә хата. Хаталы пароль?
Шифрланған '{0}' файлында CRC хатаһы. Хаталы пароль?
3800
Пароль керетеү
&Паролде керетегеҙ:
Па&ролде яңынан керетегеҙ:
П&ароль күренһен
Паролдәр тап килмәй
Пароль өсөн тик латин хәрефтәрен, һандарҙы һәм махсус символдарҙы (!, #, $, ...) ҡулланығыҙ
Пароль бик оҙон
Пароль
3900
Үткән ваҡыт:
Ҡалған ваҡыт:
Барыһы:
Тиҙлек:
Күләм:
Ҡыҫыу нисбәте:
Хаталар:
Архив:
4000
Архивлау
&Архив:
&Яңыртыу ысулы:
А&рхив төрө:
Ҡыҫыу &дәрәжәһе:
Ҡ&ыҫыу ысулы:
Һүҙ&лек күләме:
Һүҙ күлә&ме:
Блоктар күләме:
Ағымдар һаны:
&Параметрҙар:
&Көйләү
SFX ар&хивын яһау
Яҙыуға асыҡ файлдарҙы ҡыҫырға
Шифрлау
Шифрлау методы:
&Файл исемдәрен шифрла
Ҡыҫҡанда хәтер ҡулланыу:
Сығарғанда хәтер ҡулланыу:
4050
Ҡыҫыуһыҙ
Бик тиҙ
Тиҙ
Ғәҙәти
Максимум
Ультра
4060
Өҫтәргә һәм алмаштырырға
Яңыртырға һәм өҫтәргә
Яңыртырға
Синхронларға
4070
Ҡарау
Бар файлдар
Файл күләме буйынса
Өҙөлмәгән
6000
Копияһын ал
Күсер
Копия ҡуйыласаҡ урын:
Күсереләсәк урын:
Копияһын алыу...
Күсереү...
Яңынан исемләү бара...
Папканы күрһәтегеҙ.
Ғәмәлде үтәп булмай
Файлға йәки папкаға яңы исем биреү хатаһы
Файлдарҙы күбәйтеүҙе раҫлау
Был файлдар архивға ҡуйылһынмы?
6100
Файл юйыуҙы раҫлау
Папка юйыуҙы раҫлау
Берҙән күп файл юйыуҙы раҫлау
'{0}' юйылһынмы?
'{0}' папкаһы һәм эсендәгеләр юйылһынмы?
{0} есеме юйылһынмы?
Юйыу бара...
Файл йәки папка юйыу хатаһы
Оҙон юллы файлдарҙы кәрзингә юйыуҙы система терәкләмәй
6300
Папка яhа
Файл яhа
Папка исеме:
Файл исеме:
Яңы папка
Яңы файл
Папка яһау хатаһы
Файл яһау хатаһы
6400
Тасуирлама
&Асыҡлама:
hайла
Һайлауҙы кире ал
Маска:
6600
Үҙенсәлектәр
Папкалар тарихы
Белдереүҙәр
Белдереү
7100
Компьютер
Селтәр
Документтар
Система
7200
Өҫтәргә
Сығарырға
Һынарға
Копияһын алырға
Күсерергә
Юйырға
Мәғлүмәт
7300
Файлды бүл
&Ошо папкаға бүл:
Киҫәк/&байт итеп бүл:
Бүлеү бара...
Бүлеүҙе раҫлау
Был файлды {0} киҫәккә бүлеүҙе раҫлайһығыҙмы?
Том күләме сығанак файлдан бәләкәй булырға тейеш
Хаталы том күләме
Том күләме : {0} байт.\nФайлды бындай томдарға бүлеүҙе раҫлайһығыҙмы?
7400
Файлдарҙы берләштер
&Ошо папкала берләштер:
Берләштереү бара...
Бүленгән файлдың беренсе киҫәген генә һайлағыҙ
Бүленгән файлды танып булманы
Бүленгән файлдың берҙән күп киҫәген табып булманы
7500
Тикшереү һанын иҫәпләү бара...
Тикшереү һаны
Мәғлүмәттәр өсөн CRC тикшереү һаны:
Мәғлүмәттәр һәм исемдәр өсөн CRC тикшереү һаны:
7600
Етештереүсәнлекте тикшереү
Хәтер ҡулланыу:
Ҡыҫыу
Сығарыу
Рейтинг
Дөйөм рейтинг
Хәҙерге
Һөҙөмтә
Процессор ҡулланыу
Рейтинг / Проц. ҡулл.
Үтеүҙәр:

404
Utils/7-Zip/Lang/be.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; : Kirill Gulyakevitch
; 9.07 : 2011-03-15 : Drive DRKA
;
;
;
;
;
;
;
;
;
0
7-Zip
Belarusian
Беларуская
401
OK
Адмена
&Так
&Не
&Зачыніць
Дапамога
&Працягнуць
440
Так для &усіх
Не для ў&сіх
Стоп
Перазапуск
&Фонам
&На пярэдні план
&Паўза
На паўзе
Вы сапраўды жадаеце перапыніць аперацыю?
500
&Файл
&Праўка
&Выгляд
&Абранае
С&ервіс
&Даведка
540
&Адкрыць
Адкрыць &усярэдзіне
Адкрыць з&вонку
Прагляд
&Рэдагаваць
Пера&назваць
&Капіяваць у...
&Перамясціць у...
&Выдаліць
Ра&збіць файл...
А&б'яднаць файлы...
Сво&йства
Коме&нтар
Кантрольная сума
Diff
&Стварыць папку
Ств&арыць Файл
В&ыхад
600
Вылучыць у&сё
Прыбраць вылучэнне
&Звярнуць в&ыдзяленне
Вылучыць...
Прыбраць вылучэнне...
Вылучыць па тыпе
Прыбраць вылучэнне па тыпе
700
&Буйныя значкі
&Дробныя значкі
Спі&с
&Табліца
730
Без сартавання
Плоскі рэжым
&2 Панэлі
&Панэлі прылад
Адкрыць каранёвую папку
Пераход на адзін узровень уверх
Гісторыя папак...
А&бнавіць
750
Панэль кнопак архіватара
Стандартная панэль кнопак
Вялікія кнопкі
Надпісы на кнопках
800
Дадаць папку ў &абранае як
Закладка
900
Налады...
Тэставанне прадукцыйнасці
960
&Змест...
Аб &праграме...
1003
Шлях
Імя
Пашырэнне
Папка
Памер
Сціснуты
Атрыбуты
Створаны
Адчынены
Зменены
Бесперапынны
Каментар
Зашыфраваны
Пабіты Да
Пабіты Пасля
Слоўнік
CRC
Тып
Анты
Метад
Сістэма
Файлавая Сістэма
Карыстальнік
Група
Блок
Каментар
Пазіцыя
Шлях
Папак
Файлаў
Версія
Тым
Шматтомны
Зрушэнне
Спасылак
Блокаў
Тамоў
64-bit
Big-endian
Працэсар
Фізічны Памер
Памер Загалоўкаў
Кантрольная Сума
Характарыстыкі
Віртуальны Адрас
ID
Кароткае Iмя
Создатель
Памер Сектара
Рэжiм
Ссылка
Памылка
Ёмістасць
Вольна
Памер кластара
Пазнака
Лакальнае імя
Правайдэр
2100
Налады
Мова
Мова:
Рэдактар
&Рэдактар:
&Diff:
2200
Сістэма
Асацыяваць 7-Zip з файламі:
2301
Убудаваць 7-Zip у кантэкстнае меню абалонкі
Каскаднае кантэкстнае меню
Элементы кантэкстнага меню:
2320
<Папка>
<Архіў>
Адкрыць архіў
Распакаваць
Дадаць да архіва...
Тэставаць
Распакаваць тут
Распакаваць у {0}
Дадаць да {0}
Сціснуць і адправіць па email...
Сціснуць у {0} і адправіць па email
2400
Папкі
&Працоўная Папка
&Сістэмная часавая Папка
&Бягучая
&Задаць:
Выкарыстаць толькі для зменных носьбітаў
Пакажыце становішча для часавых архіваў.
2500
Налады
Паказваць элемент ".."
Паказваць рэальныя абразкі файлаў
Паказваць сістэмнае меню
Курсор на ўвесь радок
Паказваць падзельнікі
Адчыняць элемент адным клiкам
Альтэрнатыўны рэжым пазнакі
Выкарыстаць вялікія старонкі памяці
2900
Аб праграме 7-Zip
7-Zip з'яўляецца вольна распаўсюджваемай праграмай. Аднак калі вы жадаеце падтрымаць распрацоўку 7-Zip, вы можаце зарэгістраваць праграму.Праграма перакладена Drive DRKA.Мая электронная скрыня: drka2003@mail.ru.Пераклад зроблен у верасні 2007 года.
3000
Нядосыць вольнай памяці
Памылак не знойдзена
Вылучана аб'ектаў: {0}
Не атрымалася стварыць папку '{0}'
Аперацыі змены не падтрымліваюцца для гэтага архіва.
Не атрымалася адкрыць файл '{0}' як архіў
Не атрымалася адкрыць зашыфраваны архіў '{0}'. Няслушны пароль?
Непадтрымоўваны тып архіва
Файл {0} ужо існуе
Файл '{0}' быў зменены.\nВы жадаеце абнавіць яго ў архіве?
Не атрымалася абнавіць файл\n'{0}'
Не атрымалася запусціць рэдактар
Файл падобны на вірус (імя файла ўтрымоўвае доўгую паслядоўнасць прабелаў).
Аперацыя не можа быць выкананая з папкі, якая мае доўгі шлях.
Вы павінны вылучыць адзін файл
Вы павінны вылучыць адзін або некалькі файлаў
Занадта шмат элементаў
3300
Распакаванне
Кампрэсія
Тэставанне
Адкрыццё...
Сканаванне...
3400
Выняць
&Распакаваць у:
Пакажыце становішча для вымаемых файлаў.
3410
Шляхі
По&ўные шляхі
&Без шляхоў
3420
Перазапіс
&З пацверджаннем
Бы&ез пацверджанні
Прап&ускаць
Пераназваць аўтам.
Переім. аўтам. істот.
3500
Пацверджанне замены файла
Папка ўжо ўтрымоўвае апрацоўваемы файл.
Замяніць наяўны файл
наступным файлам?
{0} байтаў
Пераназваць аўтам.
3700
Непадтрымоўваны метад сціску для файла '{0}'.
Памылка ў дадзеных у '{0}'. Файл сапсаваны.
Памылка CRC у '{0}'. Файл сапсаваны.
Памылка ў дадзеных зашыфраванага файла '{0}'. Няслушны пароль?
Памылка CRC для зашыфраванага файла '{0}'. Няслушны пароль?
3800
Увод пароля
&Увядзіце пароль:
&Паўтарыце пароль:
&Паказаць пароль
Паралі не супадаюць
Для пароля выкарыстайце толькі знакі лацінскага алфавіту, лічбы і адмысловыя знакі (!, #, $, ...)
Пароль занадта доўгі
&Пароль
3900
Мінула:
Засталося:
Усяго:
Хуткасць:
Памер:
Ступень сціску:
Памылак:
Архіваў:
4000
Дадаць да архіва
&Архіў:
&Рэжым змены:
&Фармат архіва:
&Узровень сціску:
&Метад сціску:
Памер &слоўніка:
Памер з&лоўлі:
Памер блока:
Лік струменяў:
&Параметры:
&Опцыі
Стварыць SF&X-архіў
Сціскаць адчыненыя для запісу файлы
Шыфраванне
Метад шыфравання:
&Шыфраваць імёны файлаў
Аб'ём памяці для пакавання:
Аб'ём памяці для распакавання:
4050
Без сціску
Хуткасны
Хуткі
Нармалёвы
Максімальны
Ультра
4060
Дадаць і замяніць
Абнавіць і дадаць
Абнавіць
Сінхранізаваць
4070
Прагартаць
Усе файлы
Па памеры файла
Бесперапынны
6000
Капіяваць
Перамясціць
Капіяваць у:
Перамясціць у:
Капіяванне...
Перамяшчэнне...
Пераназванне...
Пакажыце папку.
Аперацыя не падтрымліваецца для гэтай папкі.
Памылка пры пераназванні файла або папкі
Пацверджанне капіявання файлаў
Вы сапраўды жадаеце скапіяваць гэтыя файлы ў архіў
6100
Пацверджанне выдалення файла
Пацверджанне выдалення папкі
Пацверджанне выдалення групы файлаў
Вы сапраўды жадаеце выдаліць "{0}"?
Вы сапраўды жадаеце выдаліць папку "{0}" і ўсё яе змесціва?
Вы сапраўды жадаеце выдаліць гэтыя аб'екты ({0} шт.)?
Выдаленне...
Памылка пры выдаленні файла або папкі
Сістэма не падтрымлівае аперацыю выдалення файлаў з доўгімі шляхамі ў кошык
6300
Стварыць папку
Стварыць файл
Імя папкі:
Імя файла:
Новая Папка
Новы файл
Памылка пры стварэнні папкі
Памылка пры стварэнні файла
6400
Каментар
&Каментар:
Вылучыць
Прыбраць вылучэнне
Маска:
6600
Уласцівасці
Гісторыя папак
Паведамленні
Паведамленне
7100
Кампутар
Сетка
Дакументы
Сістэма
7200
Дадаць
Выняць
Тэставаць
Капіяваць
Перамясціць
Выдаліць
Інфармацыя
7300
Разбіць файл
&Разбіць у:
Разбіць на &тамы памерам (у байтах):
Разбіццё...
Пацверджанне разбіцця
Вы сапраўды жадаеце разбіць файл на {0} частак?
Памер тома павінен быць менш памеру зыходнага файла
Памылка ў поле для задання памеру тамоў
Усталяваны памер тома: {0} байтаў.\nВы сапраўды жадаеце разбіць архіў на такія тамы?
7400
Аб'яднаць файлы
&Аб'яднаць у:
Аб'яднанне...
Неабходна вылучыць толькі першую частку пабітага файла
Не атрымалася распазнаць пабіты файл
Не атрымалася знайсці больш адной часткі пабітага файла
7500
Вылічэнне кантрольнай сумы...
Кантрольная сума
Кантрольная сума CRC для дадзеных:
Кантрольная сума CRC для дадзеных і імёнаў:
7600
Тэставанне прадукцыйнасці
Аб'ём памяці:
Пакаванне
Распакаванне
Рэйтынг
Агульны рэйтынг
Бягучы
Выніковы
Нагрузка
Рэйтынг / Нагр.
Праходаў:

404
Utils/7-Zip/Lang/bg.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; : chavv
; : icobgr
; 4.65 : Vassia Atanassova
;
;
;
;
;
;
;
;
0
7-Zip
Bulgarian
Български
401
OK
Отказ
&Да
&Не
&Затваряне
Помощ
Пр&одължаване
440
Да за &всички
Не за &всички
Стоп
От начало
&Фонов режим
&Нормален режим
&Пауза
В пауза
Наистина ли желаете да прекратите?
500
&Файл
&Редактиране
&Показване
&Любими
&Инструменти
&Помощ
540
&Отваряне
Отваряне &в
Отваряне &извън
&Показване
&Редактиране
Преи&менуване
&Копиране в...
Пре&местване в...
Из&триване
Р&азделяне на файл...
О&бединяване на файлове...
&Свойства
Ком&ентар
Изчисляване на контролна сума
Създаване на директория
Създаване на файл
Из&ход
600
&Маркиране на всички
&Размаркиране на всички
&Обръщане на избора
Маркиране...
Размаркиране...
Маркиране по тип
Размаркиране по тип
700
&Големи икони
&Малки икони
&Списък
&Детайли
730
Несортиран
Плосък изглед
&2 панела
&Ленти с инструменти
Отваряне на главната директория
Едно ниво нагоре
История на директориите...
&Опресняване
750
Лента на архива
Стандартна лента
Големи бутони
Показване на текст под бутоните
800
&Добавяне на директорията като любима:
Отметка
900
&Настройки...
&Статистика
960
&Съдържание...
&За 7-zip...
1003
Път
Име
Разширение
Директория
Размер
Компресиран размер
Атрибути
Създаден
Отварян
Изменен
Солиден
Коментар
Зашифрован
Разделен до
Разделен след
Речник
CRC
Тип
Анти
Метод
Операционна система
Файлова система
Потребител
Група
Блок
Коментар
Позиция
Префикс на пътя
Директории
Файлове
Версия
Том
Multivolume
Offset
Links
Blocks
Томове
64-битов
Big-endian
CPU
Физически размер
Размер на заглавната част
Контролна сума
Характеристики
Виртуален адрес
Грешка
Пълен размер
Свободно пространство
Размер на клъстер
Етикет
Локално име
Доставчик
2100
Настройки
Език
Език:
Редактор
&Редактор:
2200
Система
Асоцииране на 7-Zip с:
2301
Интегриране на 7-Zip в контекстното меню на шела
Каскадно контекстно меню
Елементи на контекстното меню:
2320
<Директория>
<Архив>
Отваряне на архив
Разархивиране на файловете...
Добавяне към архив...
Проверка на архива
Разархивиране тук
Разархивиране в {0}
Добавяне в {0}
Архивиране и изпращане...
Архивиране в {0} и изпращане
2400
Директории
&Работна директория
&Системната TEMP директория
&Текущата
&Друга:
Използване само за преносими носители
Указване на място за временните архиви.
2500
Настройки
Показване на обекта ".."
Показване на истинските икони на файловете
Показване на системното меню
&Избор на цял ред
Показване на помощни &линии
&Алтернативен режим на избор
Използване на &големи страници от паметта
2900
Информация
7-Zip се разпространява като свободен софтуер. Все пак, можете да подпомогнете разработката на 7-zip, като се регистрирате.
3000
Системата не може да задели необходимото количество памет.
Няма грешки в архива
{0} обект(и) избрани
Не може да бъде създадена директория '{0}'
Този архив не поддържа операции за изменение.
Файлът '{0}' не може да се отвори като архив
Криптираният архив '{0}' не може да се отвори. Грешка в паролата?
Архив от тип, който не се поддържа
Файлът {0} вече съществува
Файлът '{0}' е бил променен.\nИскате ли да обновите копието му в архива?
Не може да бъде обновен файл \n'{0}'
Не може да бъде стартиран редактора.
Файлът прилича на вирус (името му съдържа дълги поредици интервали).
Операцията не може да бъде извикана от директория с толкова дълъг път.
Трябва да се избере един файл
Трябва да се изберат един или повече файлове
Твърде много обекти
3300
Разархивиране
Компресия
Проверка
Отваряне...
Претърсване...
3400
Разархивиране
&Разархивиране в:
Избор на място за разархивираните файлове.
3410
Режим за пътищата
Пълни пътища
Без пътища
3420
Режим за презаписване
Потвърждение преди презаписване
Презаписване без потвърждение
Пропускане на съществуващите файлове
Автоматично преименуване
Автоматично преименуване на съществуващите файлове
3500
Подтвърдете замяната на файла
Директорията вече съдържа файл с такова име.
Желаете ли да замените съществуващия файл
с този файл?
{0} байта
&Автоматично преименуване
3700
Неподдържан метод за компресия във файл '{0}'.
Грешка в данните в '{0}'. Файлът е повреден.
Проверката на цикличния остатък даде грешка в '{0}'. Файлът е повреден.
Грешка в данните в криптирания файл '{0}'. Грешка в паролата?
Проверката на цикличния остатък даде грешка в криптирания файл '{0}'. Грешка в паролата?
3800
Въведете парола
Въведете парола:
Въведете повторно парола:
&Показване на паролата
Двете пароли не съвпадат
За паролата си използвайте само латински букви, цифри и специални символи (!, #, $, ...)
Паролата е твърде дълга
&Парола
3900
Изминало време:
Оставащо време:
Размер:
Скорост:
Обработени:
Коефициент на компресия:
Грешки:
Архиви:
4000
Добавяне към архив
&Архив:
Режим за изменение:
Формат на архива:
&Ниво на компресия:
Метод за компресия:
Размер на &речника:
Размер на &думата:
Размер на непрекъснат блок:
Брой процесорни нишки:
&Параметри:
&Опции
Самора&зархивиращ се архив
Компресирани споделени файлове
Криптиране
Метод за криптиране:
Криптиране на файловите &имена
Използвана памет за архивиране:
Използвана памет за разархивиране:
4050
Без компресия
Най-бърза
Бърза
Нормална
Максимална
Ултра
4060
Добавяне и замяна на файлове
Обновяване и добавяне на файлове
Опресняване на съществуващите файлове
Синхронизиране на файловете
4070
Разглеждане
Всички файлове
Non-solid
Непрекъсната (solid) компресия
6000
Копиране
Преместване
Копиране в:
Преместване в:
Копиране...
Местене...
Преименуване...
Избор на целева директория.
Операцията не се поддържа за тази директория.
Грешка при преименуването на файл или директория
Потвърждение за копирането на файл
Сигурни ли сте, че искате да копирате файлове към архива?
6100
Потвърждение за изтриването на файл
Потвърждение за изтриването на директория
Потвърждение за изтриването на множество файлове
Сигурни ли сте, че искате да изтриете '{0}'?
Сигурни ли сте, че искате да изтриете диркеторията '{0}' с цялото й съдържание?
Сигурни ли сте, че искате да изтриете тези {0} обекта?
Изтриване...
Грешка при изтриване на файл или директория
Системата не може да изтрие файл с толкова дълъг път
6300
Създаване на директория
Създаване на файл
Име на директория:
Име на файл:
Нова директория
Нов файл
Грешка при създаване на директория
Грешка при създаване на файл
6400
Коментар
&Коментар:
Маркиране
Размаркиране
Маска:
6600
Свойства
История на директориите
Диагностични съобщения
Съобщение
7100
Компютър
Мрежа
Документи
Система
7200
Добавяне
Извличане
Тестване
Копиране
Преместване
Изтриване
Информация
7300
Разделяне на файл
&Разделяне на:
Разделяне на &томове, байтове:
Разделяне...
Потвърждение на разделянето
Сигурни ли сте, че искате да разделите файла на {0} тома?
Размерът на том трябва да бъде по-малък от размера на оригиналния файл
Невалиден размер на том
Указан размер на том: {0} байта.\nСигурни ли сте, че искате да разделите архива на томове с такъв размер?
7400
Обединяване на файлове
&Обединяване в:
Обединяване...
Избиране само на първата част от разделения файл
Файлът не се разпознава като част от разделен оригинален файл
Не се открива повече от една част от разделения файл
7500
Изчисляване на контролната сума...
Информация за контролната сума
CRC контролна сума за данни:
CRC контролна сума за данни и имена:
7600
Статистика
Използвана памет:
Архивиране
Разархивиране
Оценка
Обща оценка
Текущо
Резултат
Успешно преминали:

404
Utils/7-Zip/Lang/bn.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.46 : Team Oruddho (Fahad Mohammad Shaon, Mahmud Hassan) : http://www.oruddho.com
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Bangla
বাংলা
401
ঠিক আছে
বাতিল
&হ্যাঁ
&না
&বন্ধ করা
সাহায্য
&চালিয়ে যাওয়া
440
&সবগুলোর জন্য হ্যাঁ
স&বগুলোর জন্য না
বন্ধ
আবার শুরু
&পটভূমি
& সামনে
&বিরতি
বিরতিতে অবস্থানরত
আপনি বাতিল করতে ইচ্ছুক?
500
&ফাইল
&পরিবর্তন
প্রদর্শন&
&প্রিয়
&দরকারি
&সহায়তা
540
&উন্মুক্ত করা
7-zip-এ উন্মুক্ত করা
বাহিরে উন্মুক্ত করা
&প্রদর্শন
&পরিবর্তন
নাম পরিবর্তন
&অনুলিপি হবে...
প্রতিস্থাপন হবে...
&মুছে ফেলা
&ফাইল খন্ডায়ন...
ফাইল সংযোজন...
বৈশিষ্টাবলি
মন্তব্য
Checksum গননা করা
ফোল্ডার সৃষ্টি
ফাইল সৃষ্টি
বাহির
600
সব নির্বাচন
নির্বাচন রদ করা
উল্টো নির্বাচন
নির্বাচন...
নির্বাচন রদ করা...
ধরণ অনুযায়ী নির্বাচন
ধরণ অনুযায়ী নির্বাচন রদ করা
700
বৃহৎ প্রতিক
ছোট্ট প্রতিক
&তালিকা
&বিবরণ
730
অসজ্জিত
সমতল সজ্জা
&ব্যবস্থাপক দ্বিখন্ডন
&দরকারিখুটি
মূল ফোল্ডার উন্মুক্ত করা
এক পর্যায় উপরে ...
ফোল্ডারের অতীত বিবরণ...
&সতেজতা
750
সংকোচোন ব্যবস্থাপক খুটি
সাধারণ খুটি
বৃহৎ বোতাম
বোতামের শিরোনাম প্রদর্শন
800
&প্রিয় ফোল্ডার হিসাবে সংযোজন ...
পছন্দের তালিকা
900
&পছন্দগুলো...
&বেঞ্চমার্ক
960
&সাহায্য...
&7-Zip সর্ম্পকে...
1003
অবস্থান
নাম
পরিচয়
ফোল্ডার
আকার
সংকুচিত আকার
বৈশিষ্ট
সৃষ্টি হয়েছে
ব্যবহার হয়েছে
পরিবর্ধন হয়েছে
দৃঢ়
Commented
আটকানো
খন্ডনের পূর্বে
খন্ডনের পরে
অভিধান
CRC
ধরন
বিরোধী
পদ্ধতি
চলতি অপারেটিং সিস্টেম
ফাইল ব্যবস্থা
ব্যবহারকারী
দল
বাধা
মন্তব্য
অবস্থান
পথের বিশেষায়ণ (Path Prefix)
ত্রুটি
সম্পূর্ণ আকার
অবশিষ্ট জায়গা
ক্লাস্টারের আকার
শিরোনাম
স্থানীয় নাম
বিতরণকারী
2100
পছন্দগুলো
ভাষা
ভাষা:
সম্পাদক
বর্তমান সম্পাদক :
2200
বর্তমান অবস্থা
7-Zip-এর সাথে সম্পর্কিত :
2301
সাহায্যকারী তালিকায় 7-Zip সংযোজন
সাহায্যকারী তালিকায় একের ভিতর সব গুটিয়ে ফেলা
সাহায্যকারী তালিকার বিষয়সমূহ:
2320
<ফোল্ডার>
<সংকুচিত ফাইল>
সংকুচিত ফাইল চালু করা
ফাইল সম্প্রসারণ...
সংকুচিত ফাইলে সংযোজন...
সংকুচিত ফাইল নিরীক্ষণ
এখানেই সম্প্রসারণ
সম্প্রসারণ করা হবে {0}
সযোজন করা হবে {0}
সংকোচন এবং ই-মেইল...
সংকোচন - {0} এবং ই-মেইল
2400
ফোল্ডার
&কার্যরত ফোল্ডার
&অস্থায়ী ফোল্ডার
&প্রচলিত
&নির্দিষ্ট:
অস্থায়ী অংশের জন্য ব্যবহার করা
অস্থায়ী ফোল্ডার নির্বাচন করুন।
2500
পছন্দগুলো
".." ফাইল প্রদর্শন
ফাইলের আসল প্রতিক দেখানো
কম্পিউটার চালকের তালিকা দেখানো
পূর্ণ পর্যায় প্রদর্শন
ছকের লাইন প্রদর্শন
পরিপূরক নিবাচনের পদ্ধতি
বেশি স্মৃতির ব্যবহার
2900
7-Zip সম্পর্কে
7-Zip একটি মুক্ত প্রোগ্রাম কিন্তু এটি 7-Zip এর কতৃপক্ষের কাচে নিবন্ধনের মাধ্যমে আপনি উন্নত সেবা পেতে পারেন
3000
কোন ত্রুটি নেই
{0} ফাইল(সমূহ) নির্বাচিত
'{0}' ফোল্ডার সৃষ্টি করা সম্ভব হচ্ছেনা
এই সংকোচনের ক্ষেত্রে এই সেবা প্রদান করা সম্ভব হচ্ছে না।
'{0}' -কে সংকুচিত ফাইল হিসেবে চালু করা সম্ভব হচ্ছেনা
'{0}' বদ্ধ সংকুচিত ফাইল চালু করা সম্ভব হচ্ছেনা. ভুল পাসওয়ার্ড?
ফাইলটি '{0}' পরিমার্জিত.\nআপনি সংকুচিত ফাইলটি ও পরিমার্জন করতে চান?
পরিমার্জন করা সম্ভব হয়নি\n'{0}'
সম্পাদক চালু করা সম্ভব নয়
অনেক বেশী ফাইল
3300
সম্প্রসারণ করা হচ্ছে
সংকোচায়ন প্রক্রিয়াধীন
নিরক্ষণ করছে ...
উন্মুক্ত করা হচ্ছে...
তথ্য সংগ্রহ চলছে... (Scanning...)
3400
সম্প্রসারণ
&সম্প্রসারণ করা হবে:
ফাইল সম্প্রসারনের ঠিকানা
3410
ঠিকানা নির্বাচন পদ্ধতি
পূর্ণ ঠিকানাসমূহ
ঠিকানাবিহীন
3420
প্রতিস্থাপন পদ্ধতি
প্রতিস্থাপনের পূর্বাভাস
আভাসবিহীন প্রতিস্থাপন
একই পরিচয় প্রাপ্ত ফাইল এড়িয়ে চলা
স্বয়ংক্রিয় পুঃনামকরণ
একই পরিচয় প্রাপ্ত ফাইলের নাম পরিবর্ত্ন
3500
ফাইল প্রতিস্থাপন নিশ্চিত করণ
নির্ধারিত ফোল্ডারে ফাইলটি আগেথেকেই আছে
আপনিকি বর্তমান ফাইলটি প্রতিস্থাপন করতে চান?
এইটির সাথে?
{0} bytesবাইট
স্বয়ংক্রিয় পুঃনামকরণ
3700
অসমর্থিত সংকোচন পদ্ধতি -'{0}'.
'{0}' ফাইলে ত্রুটিপূর্ণ তথ্য. ফাইলটি খন্ডিত
'{0}' ফাইলে CRC ব্যর্থ. ফাইলটি খন্ডিত
'{0}' বদ্ধ ফাইলে তথ্যে ত্রুটি. ভুল পাসওয়ার্ড?
'{0}' বদ্ধ ফাইলে CRC ব্যর্থ. ভুল পাসওয়ার্ড?
3800
পাসওয়ার্ডটি প্রবেশ করুনঃ
পাসওয়ার্ডটি প্রবেশ করুনঃ
আবার পাসওয়ার্ড প্রবেশ করুনঃ
&পাসওয়ার্ড প্রদর্শন
পাসওয়ার্ড দুটি একই নয়
শুধু ইংলিশ বর্ণ, সংখ্যা এবং বিশেষ বর্ণ (!, #, $, ...) পাসওয়ার্ড হিসেবে ব্যবহার করুন
পাসওয়ার্ডটি খুব বেশী বড় হয়েছে
পাসওর্য়াড
3900
অতিবাহিত সময়ঃ
সময় বাকি আছেঃ
আকার:
গতি:
বিফলতা :
4000
সংকোচনে সংযোজন
&সংকোচন
&পরিমার্জন পদ্ধতি:
সংকোচনের & পরিচয়:
সংকোচনের &পর্যায়:
সংকোচন &পদ্ধতি:
&Dictionary size:
&Word size:
Solid block size:
CPU-এর thread-এর সংখ্যা:
&Parameters:
পছন্দনীয়
স্বয়ংক্রিয় সংকোচন প্রোগ্রাম তৈরি
বিনিময়যোগ্য ফাইল সংকোচন
বদ্ধ করা
বদ্ধ করার পদ্ধতি:
ফাইলের নাম &আটকে ফেলা
সংকোচনের জন্য স্মৃতির ব্যবহার:
সম্প্রসারনের জন্য স্মৃতির ব্যবহার:
4050
অতি সংকোচায়ন
অতি দ্রুত
দ্রুত
সাধারন
সর্ব্বোচ্চ
পলকের গতি
4060
সংকোচন ও ফাইল প্রতিস্থাপন
পরিমার্জন ও ফাইল প্রতিস্থাপন
উল্লেখিত ফাইলে সতেজতা প্রদান
ফাইল সাজিয়ে রাখা
4070
বিচরণ
সকল ফাইল
Non-solid
Solid
6000
অনুলিপি গ্রহন
অনুলিপি গ্রহন এবং মুছে ফেলা
অনুলিপি করা হবে:
প্রতিস্থাপিত হবে:
অনুলিপি করা হচ্ছে...
প্রতিস্থাপিত হচ্ছে...
নাম পরিবর্তন...
গন্তব্য ফোল্ডার নির্বাচন.
কার্যটি সম্ভব নয়
ফাইল বা ফোল্ডারের নাম পরিবর্তনে সম্ভব নয়
ফাইল অনুলিপি নিশ্চিতকরণ
আপনি কি ফাইলগুলোকে সংকুচিত ফাইলে অনুলিপি গ্রহণ করতে চান।
6100
ফাইলটি মুছে ফেলতে কি আপনি নিশ্চিত
ফোল্ডারটি মুছে ফেলতে কি আপনি নিশ্চিত
ফাইলটি মুছে ফেলতে কি আপনি নিশ্চিত
মুছে ফেলতে আপনি কি নিশ্চিত - '{0}'?
'{0}' ফোল্ডার এবং এর সব ফাইল আপনি কি মুছে ফেলতে নিশ্চিত?
নির্বাচিত {0} টি ফাইল আপনি কি মুছে ফেলতে নিশ্চিত?
মুছে ফেলা হচ্ছে...
ফাইল বা ফোল্ডার মুছে ফেলাতে সমস্যা হচ্ছে
6300
ফোল্ডার সৃষ্টি
ফাইল সৃষ্টি
ফোল্ডারের নাম:
ফাইল নাম:
নতুন ফোল্ডার
নতুন ধারক
ফোল্ডার সৃষ্টিতে সমস্যা
ফাইল সৃষ্টিতে সমস্যা
6400
মন্তব্য
&মন্তব্য:
নির্বাচন
নির্বাচন রদ করা
আড়াল করা:
6600
ফোল্ডারের অতিত বিবরন
সমস্যা নিরাময় আভাস
আভাস
7100
কম্পিউটার
আন্তঃ সম্পর্ক
কম্পিউটার চালক
7200
সংজোযন
সম্প্রসারন
নিরীক্ষণ
অনুলিপি গ্রহন
প্রতিস্থাপন
মুছে ফেলা
তথ্য
7300
ফাইল খন্ডায়ন
&ফাইল খন্ডায়িত হবে:
volumes(খন্ডে), bytes(বাইটস)-এ খন্ডায়নঃ
ফাইল খন্ডায়ন চলছে...
ফাইল খন্ডায়ন নিশ্চিতকরণ
আপনি কি সংকুচিত ফাইলটিকে {0} খন্ডে খন্ডায়ন করতে চান?
খন্ডের আকার অবশ্যই মূল ফাইলের চেয়ে ছোট হতে হবে
খন্ডের আকারে ভুল
উল্লেক্ষিত খন্ডের আকার : {0} bytes.\nআপনি কি সংকোচিত ফাইলটিকে এ ভাবেই খন্ডে খন্ডায়ন করতে চান?
7400
ফাইল একীভূতি করণ
&একীভূতি করা হবে:
একীভূতি চলছে...
শুধু প্রথম ফাইলটি নির্বাচন করুন
7500
Checksum গননা চলছে...
Checksum তথ্য
তথ্যের জন্য CRC checksum:
তথ্য এবং নামের জন্য CRC checksum:
7600
বেঞ্চমার্ক
ব্যবহৃত স্মৃতি :
সংকোচায়ন ...
সম্প্রসারণ ...
রেটিং
মোট রেটিং
চলতি
ফলাফল
CPU ব্যবহার করছে
Rating / ব্যবহার করছে
সফলতা :

404
Utils/7-Zip/Lang/br.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 3.12 : KAD-Korvigelloù An Drouizig (drouizig.org).
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Breton
Brezhoneg
401
Mat eo
Nullañ
&Ya
&Ket
&Serriñ
Skoazell
&Kenderc'hel
440
Ya be&pred
Ket &bepred
Paouez
Adloc'hañ
&Drekleur
&Rakleur
&Ehan
Ehanet
Ha fellout a ra deoc'h nullañ ?
500
&Restr
&Aozañ
&Gwelout
Di&baboù
&Ostilhoù
&Skoazell
540
&Digeriñ
Digeriñ a-zia&barzh
Digeriñ a-zia&vaez
&Gwelout
&Aozañ
Adenv&el
&Kopiañ diwar...
&Dilec'hiañ diwar...
D&ilemel
&Troc'hañ restr...
&Kendeuziñ restroù...
P&erzhioù
Evezhia&denn
Sevel un teul
Sevel ur restr
&Kuitaat
600
Diuz pep &tra
Diziuz pe tra
Lakaat an &diuzad war an tu gin
Diuz...
Diziuz...
Diuz diouzh ar rizh
Diziuz diouzh ar rizh
700
Arlunioù &bras
Arlunioù &bihan
&Roll
&Munudoù
730
Dirummet
&2 brenestr
&Barrennoù ostilhoù
Digeriñ an teul gwrizienn
Teul kerent
Roll istor an teul...
Fresk&aat
750
Barrenn ziell
Barrenn skouerek
Meudellioù bras
Diskouez an destenn
800
&Ouzhpennañ ar c'havlec'h d'ar sinedoù
Sined
900
&Dibaboù...
&Amprouiñ
960
&Roll ar pennadoù...
A-&zivout 7-Zip...
1003
Treug
Anv
Astenn
Teul
Ment
Gwasket
Doareennoù
Savet d'ar
Stoket d'ar
Kemmet d'ar
Solut
Evezhiadenn
Ennodet
Rannañ a-raok
Rannañ war-lerc'h
Geriadur
CRC
Rizh
Enep
Hentenn
OS ostiz
Reizhiad restroù
Implijour
Strollad
Bloc'h
Evezhiadenn
Lec'hiadur
Fazi
Ment en holl
Egor vak
Ment ar c'hleusteurioù
Skritellig
Anv lec'hel
Pourchaser
2100
Dibaboù
Yezh
Yezh :
Embanner
&Embanner :
2200
Reizhiad
Kenstagañ 7-Zip ouzh :
2301
Lakaat 7-Zip el lañser kemperzhel
Lañser kemperzhel a-steud
Elfennoù al lañser kemperzhel :
2320
<Teul>
<Diell>
Digeriñ
Eztennañ ar restroù...
Ouzhpennañ d'an diell...
Gwiriañ an diell
Eztennañ amañ
Eztennañ diwar {0}
Ouzhpennañ da {0}
Gwaskañ ha kas dre postel...
Gwaskañ diwar {0} ha kas dre postel.
2400
Teulioù
Teulioù &labour
Teul dibadelus ar &reizhiad
Teul &red
Teul &spisaet :
Implijout nemet evit ar mediaoù dilec'hus
Spisait un teul evit lakaat ar restroù diell dibadelus.
2500
Perzhioù
Diskouez an elfenn ".."
Diskouez arlunioù gwirion ar restroù
Diskouez al lañser reizhiad
&Diuz ar bannoù a-bezh
Diskouez al &linennoù kael
2900
Keloù
Digoust eo ar meziant 7-Zip. Mar plij deoc'h 7-zip ha mar fell deoc'h skoazellañ ar raktres-mañ e c'hellit donezoniñ argant da 7-Zip.
3000
N'eus fazi ebet
{0} elfenn ziuzet
N'haller ket sevel ar restr '{0}'
N'haller ket ober gant an oberiadennoù nevesaat evti an diell-mañ.
Kemmet ez eo bet ar restr '{0}'.\nHa fellout a ra deoc'h he nevesaat en diell ?
N'haller ket nevesaat\n'{0}'
N'haller ket loc'hañ an embanner.
Re a elfennoù
3300
Eztennañ
O waskañ
Gwiriañ
O tigeriñ...
3400
Eztennañ
E&ztennañ diwar :
Dibabit un teul evit eztennañ an restroù.
3410
Treugoù
Treugoù klok
Treug ebet
3420
Mod erlec'hiañ
Goulenn a-raok erlec'hiañ
Erlec'hiañ hep goulenn
Lakaat ar restroù a zo anezho a-gostez
Adenvel ent-emgefre ar restroù a zo anezho
3500
Kadarnaat a-raok erlec'hiañ ur restr
Emañ dija ur restr gant ar memes anv en teul bukenn.
Ha fellout a ra deoc'h lakaat e-lec'h
ar restr da heul ?
{0} eizhtet
Adenvel ent-&emgefre
3700
Hentenn waskañ direizh evit '{0}'.
Stlenn faziet e-barzh '{0}'. Gwastet eo ar restr.
Fazi ar reoliñ CRC evit '{0}'. Gwastet eo ar restr.
3800
Roit ar ger-tremen
Roit ar ger-tremen :
&Diskouez ar ger-tremen
Ger-tremen
3900
Amzer dremenet :
Amzer o chom :
Ment :
Tizh :
Fazioù :
4000
Ouzhpennañ d'an diell
&Diell :
&Mod nevesaat :
&Mentrezh an diell :
L&ive gwaskañ :
Rizh &gwaskañ:
&Ment ar geriadur :
Me&nt ar gerioù :
&Perzhioù:
&Dibaboù
Sevel un diell SF&X
Ennodiñ an &anvioù restroù
Memor evit ar waskerezh :
Memor evit an diwaskerezh :
4050
Gwaskañ ebet
Primañ
Prim
Reizh
Uhelañ
Gour
4060
Ouzhpennañ hag erlec'hiañ ar restroù
Nevesaat hag ouzhpennañ ar restroù
Freskaat ar restroù a zo anezho
Goubredañ ar restroù
4070
Furchal
An holl restroù
6000
Kopiañ
Dilec'hiañ
Kopiañ e-barzh :
Dilec'hiañ diwar :
O kopiañ...
O tilec'hiañ...
Oc'h adenvel...
N'haller ket ober an oberiadenn-mañ.
Fazi oc'h adenvel ar restr pe an teul
6100
Kadarnañ a-raok dilemel ar restr
Kadarnañ a-raok dilemel an teul
Kadarnañ a-raok dilemel an holl restroù
Ha fellout a ra deoc'h dilemel '{0}' ?
Ha fellout a ra deoc'h dilemel an teul '{0}' ha pep tra a zo e-barzh ?
Ha fellout a ra deoc'h dilemel ar {0} elfenn-mañ ?
O tilemel...
Fazo o tilemel ar restr pe an teul
6300
Sevel un teul
Sevel ur restr
Anv an teul :
Anv restr :
Teul nevez
Restr nevez
Fazi o sevel an teul
Fazi o sevel ar restr
6400
Evezhiadenn
&Evezhiadenn :
Diuz
Diziuz
Kuzh :
6600
Roll istor an teulioù
Kemennoù yalc'h
Kemenn
7100
Urzhiataer
Rouedad
Reizhiad
7200
Ouzhpennañ
Eztennañ
Amprouiñ
Kopiañ
Dilec'hiañ
Dilemel
Keloù
7300
Troc'hañ restr
&Troc'hañ da :
Troc'hañ e &levrennoù, eizhtetoù :
O troc'hañ...
7400
Kendeuziñ restroù
&Kendeuziñ da :
O kendeuziñ...
7500
7600
Amprouiñ
Implij ar vemor :
Gwaskerezh
Diwaskerezh
Feur
Feur en holl
Red
Da heul
Tremenioù :

404
Utils/7-Zip/Lang/ca.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 9.07 : Josep Casals, Marc Folch
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Catalan
Català
401
D'acord
Cancel.la
&Sí
&No
Tan&ca
Ajuda
&Continua
440
Sí a &tot
No a t&ot
Atura
Reinicia
Rerefons
Primer pla
&Pausa
Aturat
Esteu segur que voleu cancel.lar?
500
&Fitxer
&Edita
&Visualitza
&Preferits
E&ines
Aj&uda
540
&Obre
Obre d&ins
Obre fora
&Visualitza
&Edita
Renom&ena
&Copia a...
&Moure a...
Suprimeix
&Divideix el fitxer...
Com&bina el fitxer...
P&ropietats
Come&ntari
Calcula el checksum
Diff
Crea carpeta
Crea fitxer
Surt
600
Seleccion&a-ho tot
Deselecciona-ho tot
&Inverteix selecció
Selecciona...
Deselecciona...
Selecciona per tipus
Deselecciona per tipus
700
Icones g&rans
Icones petites
&Llista
&Detalls
730
No ordenat
Vista plana
&2 Taules
&Barres d'eines
Obre carpeta arrel
Carpeta pare
Historial de carpetes...
&Actualitza
750
Barra d'eines afegeix/extreu
Barra d'eines estàndard
Botons grans
Mostra botons amb text
800
&Afegeix la carpeta als Preferits com
Personal
900
Opcions...
&Test de referència
960
&Contingut...
Quant a 7-Zip...
1003
Adreça
Nom
Tipus de fitxer
Carpeta
Mida
Mida comprimit
Atributs
Creat
Darrer accés
Darrera modificació
Compacte
Comentari
Xifrat
Expandit abans
Expandit després
Diccionari
CRC
Tipus
Anti
Mètode
SO orígen
Sistema de fitxers
Usuari
Grup
Bloc
Comentari
Posició
Path Prefix
Carpetes
Fitxers
Versió
Volum
Multivolum
Desplaçament
Enllaços
Blocs
Volums
64-bits
Big-endian
CPU
Mida física
Mida capçaleres
Suma de verificació
Característiques
Adreça virtual
ID
Nom curt
Aplicació creadora
Mida del sector
Mode
Enllaç
Error
Mida total
Espai lliure
Mida sector
Etiqueta
Nom local
Proveïdor
2100
Opcions
Llengua
Llengua:
Editor
&Editor:
&Diff:
2200
Sistema
Associa 7-Zip amb:
2301
Integra 7-Zip dins el menú contextual de Windows
Menú contextual en cascada
Objectes del menú contextual:
2320
<Carpeta>
<fitxer>
Obre
Extreu fitxers...
Afegeix al fitxer...
Comprova el fitxer
Extreu a aquesta carpeta
Extreu a {0}
Afegeix a {0}
Comprimeix i envia per correu electrònic...
Comprimeix a {0} i envia per correu electrònic
2400
Carpetes
Carpeta de &treball
Carpeta temporal del &sistema
Carpeta a&ctual
E&specifica una carpeta:
Utilitza únicament per a discs extraïbles
Especifica una carpeta pels fitxers temporals.
2500
Selecció
Mostra l'element ".."
Mostra icones reals dels fitxers
Mostra el menú de sistema
&Selecció de columna completa
Mostra les línies de &graella
Obre amb un sol clic els elements
Mode de selecció &alternatiu
Usa pàgines de memòria &grans
2900
Informació sobre 7-Zip
7-Zip és programari lliure. De totes maneres, podeu col.laborar en el seu desenvolupament registrant el programa.
3000
El sistema no pot assignar la quantitat de memòria requerida
No hi ha errors
{0} objecte(s) seleccionat(s)
No es pot crear la carpeta '{0}'
Aquest tipus de fitxer no permet actualització.
No es pot obrir el fitxe '{0}' com a arxiu
No es pot obrir el fitxer xifrat '{0}'. La contrasenya és incorrecta?
Tipus d'arxiu no admès
El fitxer {0} ja existeix
El fitxer '{0}' ha estat modificat.\nVoleu actualitzar-lo a l'arxiu?
No pot actualitzar-se el fitxer\n'{0}'
No pot executar-se l'editor.
El fitxer sembla un virus (el nom del fitxer conté espais molt llargs al nom).
L'operació no es pot cridar des d'una carpeta amb una ruta llarga.
Heu de seleccionar un fitxer
Heu de seleccionar un o més fitxers
Massa objectes
3300
Extraient
Comprimint
Provant
Obrint...
Scanning...
3400
Extreu
E&xtreu a:
Seleccioneu una destinació pels fitxers extrets.
3410
Mode d'adreça
Adreça completa
Sense adreça
3420
Sobreescriure
Amb confirmació
Sense confirmació
Conserva els fitxers ja existents
Reanomena automàticament
Auto-reanomena fitxers existents
3500
Confirmeu substitució de fitxers
La carpeta de destí conté un fitxer amb el mateix nom.
Voleu substituir el fitxer existent
per aquest altre?
{0} bytes
Renomena a&utomàticament
3700
Mètode de compressió no vàlid per a '{0}'.
Error de dades en '{0}'. El fitxer és corrupte.
CRC ha fallat en '{0}'. El fitxer és corrupte.
Error de dades al fitxer xifrat '{0}'. Contrasenya errònia?
CRC ha fallat al fitxer xifrat '{0}'. Contrasenya errònia?
3800
Introduïu la contrasenya
Introduïu la contrasenya:
Torneu a introduir la contrasenya:
Mo&stra la contrasenya
Les contrasenyes no coincideixen
Utilitza només lletres (sense accents), números i caràcters especials (!, #, $, ...) a la contrasenya
La contrasenya és massa llarga
Contrasenya
3900
Temps transcorregut:
Temps restant:
Mida:
Taxa:
Processat:
Ràtio de compressió:
Errors:
Arxius:
4000
Afegir al fitxer
&Fitxer:
Mode d'act&ualització:
&Format del fitxer:
Nivell de &compressió:
&Tipus de compressió:
Mida del &diccionari:
Mida de la paraula:
Mida de bloc sòlid:
Nombre de fils de la CPU:
&Paràmetres:
Opcions
Crea fitxer SF&X
Comprimeix fitxers compartits
Xifrat
Mètode de xifrat:
Xifra el nom dels fitxers
Ús de memòria per comprimir:
Ús de memòria per descomprimir:
4050
Sense compressió
Ràpida
Normal
Màxima
Ultra
4060
Afegeix i substitueix fitxers
Actualitza i afegeix fitxers
Actualitza fitxers ja presents
Sincronitza fitxers
4070
Visualitza
Tots els fitxers
No sòlid
Sòlid
6000
Copia
Mou
Copia a:
Mou a:
Copiant...
Movent...
Renomenant...
Seleccioneu una carpeta de destí.
Operació no permesa.
Error renomenant fitxer o carpeta
Confirmeu la còpia del fitxer
Esteu segur que voleu copiar els fitxers a l'arxiu
6100
Confirmeu la supressió del fitxer
Confirmeu la supressió de la carpeta
Confirmeu supressió múltiple de fitxers
Esteu segur que voleu suprimir '{0}'?
Esteu segur que voleu suprimir la carpeta '{0}' i tot el seu contingut?
Esteu segur que voleu esborrar aquests {0} elements?
Suprimint...
Error esborrant fitxer o carpeta
El sistema no pot moure un fitxer amb una ruta llarga a la paperea de reciclatge
6300
Crea carpeta
Crea arxiu
Nom de carpeta:
Nom d'arxiu:
Carpeta nova
Fitxer nou
Error creant carpeta
Error creant el fitxer
6400
Comentari
&Comentari:
Selecciona
No selecciona
Màscara:
6600
Properties
Historial de carpetes
Missatges de diagnosi
Missatge
7100
El meu ordinador
Entorn de xarxa
Documents
Sistema
7200
Afegeix
Extreu
Prova
Copia
Mou
Suprimeix
Info
7300
Divideix fitxer
&Divideix a:
Divideix en &volums, bytes:
Dividint...
Confirmació de la divisió
Esteu segur que voleu dividir el fitxer en {0} volums?
La mida del volum ha de ser més petita que la mida del fitxer original
Mida del volum incorrecte
Mida de volum especificada: {0} bytes.\nEsteu segur que voleu dividir el fitxer en aquests volums?
7400
Combina fitxers
&Combina a:
Combinant...
Seleccioneu només el primer fitxer
No es pot detectar un fitxer com a una part del fitxer dividit
No es pot trobar més d'una part del fitxer dividit
7500
Calculant el checksum...
Informació del checksum
CRC checksum per les dades:
CRC checksum per les dades i els noms:
7600
Test de referència
Ús de la memòria:
Comprimint
Decomprimint
Taxa
Taxa total
Actual
Resultant
Ús de la CPU
Taxa / Ús
Passades:

495
Utils/7-Zip/Lang/co.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; 15.00 : Patriccollu di Santa Maria è Sichè
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Corsican
Corsu
401
OK
Abbandunà
&Iè
I&nnò
&Chjode
Aiutu
&Cuntinuà
440
Iè per &Tutti
Innò per T&utti
Piantà
Riavvià
&Arci pianu
P&rimu pianu
&Pausa
In pausa
Site sicuru di vulè abbandunà ?
500
&Schedariu
&Mudificà
&Affissà
&Favuriti
A&ttrezzi
A&iutu
540
&Apre
Apre Den&tru
Apre F&ora
A&ffissà
&Mudificà
&Rinumà
&Cupià Ver Di...
&Dispiazzà Ver Di...
S&quassà
&Sparte u schedariu...
&Unisce i schedarii...
&Pruprietà
Cumme&ntu...
Calculà a somma di cuntrollu
Paragunà e sfarenze
Creà un Cartulare
Creà un Schedariu
&Esce
Leia
Flussi A&lternativi
600
Selezziunà &Tuttu
Ùn selezziunà &Nunda
&Arritrusà a Selezzione
&Selezziunà...
Ùn selezziunà &micca...
Selezziunà da u Tipu
Ùn Selezziunà da u Tipu
700
Icone &Maiò
Icone &Chjuche
&Lista
&Detaglii
730
Non &Ordinatu
&Vista Sparta
&2 Finestre
&Barre d'Attrezzi
Apre u Cartulare di &Radica
Livellu &Superiore
Crunulugia di i Cartulari...
&Attualizà
Attualisazione Autumatica
750
Barra d'Attrezzi d'Archiviu
Barra d'Attrezzi Classica
Buttoni Maiò
Affissà u Testu di i Buttoni
800
&Aghjunghje u cartulare à i Favuriti cum'è
Indetta
900
&Ozzioni...
&Sperimentu di pussibilità
960
&Cuntenutu (in inglese)...
&Apprupositu di 7-Zip...
1003
Passeghju
Nome
Estensione
Cartulare
Dimensione
Dimensione Cumpressa
Attributi
Creatu u
Accessu u
Mudificatu u
Solidu
Cummentatu
Cifratu
Frazziunà Nanzu
Frazziunà Dopu
Dizziunariu
Tipu
Anti
Metoda
OS ospite
Sistema di Schedariu
Utilizatore
Gruppu
Bloccu
Cummentu
Pusizione
Prefissu di Passeghju
Cartulari
Schedarii
Versione
Vulume
Multi-Vulume
Offset
Leie
Blocchi
Vulumi
64-bit
Big-endian
CPU
Dimensione Fisica
Dimensione di l'Intestature
Somma di cuntrollu
Caratteristiche
Indirizzu Virtuale
ID
Nome Cortu
Appiecazione d'Urigine
Dimensione di Settore
Modu
Leia Simbolica
Sbagliu
Dimensione Tutale
Spaziu Liberu
Dimensione di Cluster
Nome di Vulume
Nome Lucale
Furnidore
Sicurità NT
Flussu Alternativu
Ausiliaru
Squassatu
In Arburu
Tipu di Sbagliu
Sbaglii
Sbaglii
Avertimenti
Avertimentu
Flussi
Flussi Alternativi
Dimensione di i Flussi Alternativi
Dimensione Virtuale
Dimensione Senza Compressione
Dimensione Fisica Tutale
Indice di Vulume
SottuTipu
Cummentu Cortu
Pagina di Codice
Dimensione di a Coda
Dimensione di u Mozzicone Incurpuratu
Leia
Leia Solida
iNode
Lettura sola
2100
Ozzioni
Lingua
Lingua :
Editore
&Editore :
Paragunà e sfarenze :
2200
Sistema
Assucià 7-Zip cù :
Tutti l'utilizatori
2301
Integrà 7-Zip à l'interfaccia cuntestuale
Interfaccia cuntestuale in cascata
Elementi di l'interfaccia cuntestuale :
Icone in l'interfaccia cuntestuale
2320
<Cartulare>
<Archiviu>
Apre l'archiviu
Estrae i schedarii...
Aghjunghje à l'archiviu...
Verificà l'archiviu
Estrae Quì
Estrae ver di {0}
Aghjunghje à {0}
Cumprime è mandà da email...
Cumprime ver di {0} è mandà da email.
2400
Cartulari
Cartulare di &travagliu
Cartulare timpurariu di &sistema
&Currente
&Specificatu :
Impiegà solu per i dischi amuvibili
Specificate un cartulare per i schedarii timpurarii d'archiviu.
2500
Preferenze
Affissà l'elementu ".."
Affissà e vere icone di i schedarii
Affissà l'interfaccia sistema
Selezziunà tutta a linea
Affissà linee &quadrittate
Cliccu unicu per apre un elementu
Modu di selezzione &alternativa
Impiegà pagine maiò di memoria
2900
Apprupositu di 7-Zip
7-Zip hè un prugramma liberu.\n\nTraduttu in lingua corsa da Patriccollu di Santa Maria è Sichè.
3000
U sistema ùn pò micca attribuisce a quantità richiesta di memoria
Ùn ci hè micca sbagliu
{0} ughjettu(i) selezziunatu(i)
U cartulare '{0}' ùn pò micca esse creatu
L'azzioni di mudificazione ùn sò micca pussibule per quessu archiviu.
U schedariu '{0}' ùn pò micca esse apertu cum'è un archiviu
L'archiviu cifratu '{0}' ùn pò micca esse apertu. Parolla d'intrata falsa ?
Stu tipu d'archiviu ùn hè micca accettatu
U schedariu {0} esiste dighjà
U schedariu '{0}' hè statu mudificatu.\nVulete cambiallu in l'archiviu ?
Ùn hè micca pussibule di cambià u schedariu\n'{0}'
Ùn hè micca pussibule d'avvià l'editore.
U schedariu hè podasse infettatu da un virus (u so nome cuntene spazii numerosi).
St'azzione ùn pò micca fassi dapoi un cartulare cù u nome di passeghju cusì longu.
Ci vole à selezziunà un schedariu
Ci vole à selezziunà al menu un schedariu
Troppu elementi
Ùn hè micca pussibule d'apre u schedariu cum'è un archiviu {0}
U schedariu hè apertu cum'è un archiviu {0}
L'archiviu hè apertu cù offset
3300
Estrazzione
Cumpressione
Verificazione
Apertura...
Esplurazione...
Cacciatura
3320
Aghjuntu
Mudificazione
Analisa
Riproduzzione
Rimballasgiu
Tralasciamentu
Squassatura
Creazione di l'intestatura in corsu
3400
Estrae
E&strae ver di :
Sciglite un cartulare per l'estrazzione di i schedarii.
3410
Modu di passeghju :
Nomi cumpletti di passeghju
Alcunu nome di passeghju
Nomi assuluti di passeghju
Nomi relativi di passeghju
3420
Modu di rimpiazzamentu :
Cunfirmà nanzu di rimpiazzà
Rimpiazzà senza dumandà
Ignurà i schedarii esistenti
Rinumà autumaticamente
Rinumà autumaticamente i schedarii esistenti
3430
Ùn cupià micca u cartulare di radica
Risturà a sicurità di i schedarii
3500
Cunfirmà u Rimpiazzamentu di Schedariu
U cartulare di distinazione cuntene dighjà un schedariu cù stu nome.
Vulete rimpiazzà u schedariu esistentu
cù quessu ?
{0} ottetti
Rinumà &Autumaticamente
3700
Metoda di cumpressione micca accettatu per '{0}'.
Sbagliu di dati in '{0}'. U schedariu hè alteratu.
Fiascu di l'ispezzione CRC per u schedariu '{0}'. U schedariu hè alteratu.
Sbagliu di dati in u schedariu cifratu '{0}'. Parolla d'intrata falsa ?
Fiascu di l'ispezzione CRC per u schedariu cifratu '{0}'. Parolla d'intrata falsa ?
3710
Parolla d'intrata falsa ?
3721
Metoda di compressione micca accettatu
Sbagliu di dati
Fiascu di CRC
Dati micca dispunibule
Fine inaspettata di dati
Ci hè d'altri dati dopu à a fine di i dati ghjuvevule
Ùn hè un archiviu
Sbagliu d'Intestature
Parolla d'intrata falsa
3763
Principiu di l'archiviu micca dispunibule
Principiu di l'archiviu micca confirmatu
Funzione micca accettata
3800
Scrivite a parolla d'intrata
Scrivite a parolla d'intrata :
Scrivite torna a parolla d'intrata :
&Affissà a parolla d'intrata
E parolle d'intrata sò sfarente
Per a parolla d'intrata, pudete impiegà solu : lettere senza aletta, cifri è segni particulari (!, #, $, ...)
A parolla d'intrata hè troppu longa
Parolla d'intrata
3900
Tempu passatu :
Tempu rimanentu :
Dimensione tutale :
Celerità :
Prucessu :
Reditu di cumpressione :
Sbaglii :
Archivii :
4000
Aghjunghje à l'archiviu
&Archiviu :
Modu di m&udificazione :
&Forma d'archiviu :
&Livellu de cumpressione :
&Metoda di cumpressione :
&Dimensione di u dizziunariu :
Dimensione di &e parolle :
Dimensione di u bloccu solidu :
Numeru di flussi CPU :
&Parametri :
Ozzioni
Creà un archiviu SF&X
Cumprime schedarii sparti
Cifratura
Metoda di cifratura :
Cifrà i &nomi di schedariu
Memoria impiegata da a Cumpressione :
Memoria impiegata da a Scumpressione :
Squassà i schedarii dopu à a cumpressione
4040
Cunservà e leie simboliche
Cunservà e leie solide
Cunservà i flussi di dati alternativi
Cunservà a sicurità di i schedarii
4050
Alcuna
A più rapida
Rapida
Nurmale
Massima
Ultra
4060
Aghjunghje è rimpiazzà i schedarii
Mudificà è aghjunghje i schedarii
Attualizà i schedarii esistenti
Sincrunizà i schedarii
4070
Sfuglià
Tutti i Schedarii
Non-solidu
Solidu
6000
Cupià
Dispiazzà
Cupià ver di :
Dispiazzà ver di :
Copia in corsu...
Dispiazzamentu in corsu...
Cambiamentu di nome in corsu...
Selezziunà u cartulare di distinazione.
St'azzione ùn hè micca accettata per stu cartulare.
Sbagliu durante u Cambiu di Nome di Schedariu o di Cartulare
Cunfirmazione di a Copia di Schedariu
Site sicuru di vulè cupià u(i) schedariu(i) ver di l'archiviu
6100
Cunfirmà a Squassatura di u Schedariu
Cunfirmà a Squassatura di u Cartulare
Cunfirmà a Squassatura di Schedarii Multiplice
Site sicuru di vulè squassà '{0}' ?
Site sicuru di vulè squassà u cartulare '{0}' è tuttu u so cuntenutu ?
Site sicuru di vulè squassà sti {0} elementi ?
Squassatura in corsu...
Sbagliu durante a Squassatura di Schedariu o di Cartulare
U sistema ùn pò micca mette à a Rumenzula un schedariu cù u nome di passeghju cusì longu
6300
Creà un Cartulare
Creà un Schedariu
Nome di cartulare :
Nome di schedariu :
Novu Cartulare
Novu Schedariu
Sbagliu durante a Creazione di Cartulare
Sbagliu durante a Creazione di Schedariu
6400
Cummentu
&Cummentu :
Selezziunà
Ùn Selezziunà
Filtru :
6600
Pruprietà
Crunulugia di i Cartulari
Messaghji di diagnosticu
Messaghju
7100
Urdinatore
Reta
Ducumenti
Sistema
7200
Aghjunghje
Estrae
Verificà
Cupià
Dispiazzà
Squassà
Infurmazione
7300
Sparte u schedariu
&Sparte in :
Sparte in &vulumi, ottetti :
Spartimentu...
Cunfirmà u Spartimentu
Site sicuru di vulè sparte u schedariu in {0} vulumi ?
A dimensione di u vulume deve esse più chjucu chì u schedariu d'urighjine
Dimensione di vulume falsa
Dimensione di vulume specificata : {0} ottetti.\nSite sicuru di vulè taglià l'archiviu in tali vulumi ?
7400
Unisce i Schedarii
&Unisce in :
Unione...
Selezziunà solu a prima parte di l'archiviu spartutu
Ùn si trova alcuna parte d'archiviu spartutu
Ùn si trova micca più d'una parte d'archiviu spartutu
7500
Calculu di a somma di cuntrollu...
Infurmazione nant'à a somma di cuntrollu
Somma di cuntrollu CRC per i dati :
Somma di cuntrollu CRC per i dati è i nomi :
7600
Sperimentu di pussibilità
Memoria impiegata :
Cumpressione
Scumpressione
Percentuale
Percentuale tutale
Attuale
Risultante
Impiegu CPU
Estimatu / Impiegatu
Passagi :
7700
Leia
Ligà
Leia d'urigine :
Leia di distinazione :
7710
Tipu di Leia
Leia Solida
Leia Simbolica di Schedariu
Leia Simbolica di Cartulare
Unione di Cartulare

404
Utils/7-Zip/Lang/cs.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.30 : Milan Hrubý
; 4.33 : Michal Molhanec
; 9.07 : Jiří Malák
;
;
;
;
;
;
;
;
0
7-Zip
Czech
Čeština
401
OK
Storno
&Ano
&Ne
Zavří&t
Nápověda
Po&kračovat
440
Ano na &všechno
N&e na všechno
Zastavit
Spustit znovu
&Pozadí
P&opředí
Po&zastavit
Pozastaveno
Jste si jistí, že to chcete stornovat?
500
&Soubor
Úpr&avy
&Zobrazení
&Oblíbené
&Nástroje
Nápo&věda
540
&Otevřít
Otevřít u&vnitř
Otevřít &mimo
&Zobrazit
&Upravit
&Přejmenovat
Kopírovat &do...
Př&esunout do...
Vymaza&t
&Rozdělit soubor...
&Sloučit soubory...
Vlast&nosti
Poznámk&a
Vypočítat kontrolní součet
Porovnat soubory
Vytvořit složku
Vytvořit soubor
&Konec
600
Vybrat &vše
Zrušit výběr vše
&Invertovat výběr
Vybrat...
Zrušit výběr...
Vybrat podle typu
Zrušit výběr podle typu
700
&Velké ikony
&Malé ikony
&Seznam
&Podrobnosti
730
&Bez třídění
"Ploché" zobrazení
&2 panely
Nástrojové lišty
Otevřít kořenovou složku
O úroveň výš
Historie složek...
&Obnovit
750
Archivační lišta
Standardní lišta
Velká tlačítka
Zobrazovat text tlačítek
800
&Přidat složku do oblíbených jako
Záložka
900
&Možnosti...
&Zkouška výkonu
960
&Obsah...
O progr&amu 7-Zip...
1003
Cesta
Název
Přípona
Složka
Velikost
Komprimovaná velikost
Atributy
Vytvořen
Použit
Změněn
Pevný
S poznámkou
Zakódovaný
Rozdělen do
Rozdělen od
Slovník
CRC
Typ
Anti
Metoda
Hostitelský OS
Souborový systém
Uživatel
Skupina
Blok
Poznámka
Pozice
Cesta
Složky
Soubory
Verze
Díl
Vícedílný
Offset
Odkazy
Bloků
Dílů
64-bit
Big-endian
Pocesor
Fyzická velikost
Velikost hlaviček
Kontrolní součet
Charakteristiky
Virtuální adresa
ID
Krátké jméno
Autor
Velikost sektoru
Režim
Odkaz
Chyba
Celková velikost
Volné místo
Velikost clusteru
Označení
Místní název
Poskytovatel
2100
Možnosti
Jazyk
Jazyk:
Editor
&Editor:
Program pro &porovnání souborů:
2200
Systém
Asociovat 7-Zip s:
2301
&Integrovat 7-Zip do kontextového menu
S&tupňovité kontextové menu
&Položky kontextového menu:
2320
<Složka>
<Archiv>
Otevřít
Rozbalit soubory...
Přidat do archivu...
Zkontrolovat archiv
Rozbalit zde
Rozbalit do {0}
Přidat do {0}
Zkomprimovat a odeslat poštou...
Zkomprimovat do {0} a odeslat poštou
2400
Složky
Pracovní složka
&Systémová složka pro dočasné soubory
&Aktuální
S&ložka:
&Používat pouze pro vyjímatelné disky
Vyberte umístění pro dočasné komprimované soubory.
2500
Nastavení
Zobrazovat položku ".."
Zobrazovat skutečnou ikonu souboru
Zobrazovat systémové menu
&Vybírat celý řádek
Zobrazovat &mřížku
Otevřít položku jedním kliknutím
&Alternativní způsob výběru
&Používat velké stránky paměti
2900
O programu 7-Zip
7-Zip je svobodný software. Nicméně můžete podpořit jeho vývoj registrací.
3000
Systém nemůže přidělit požadovanou velikost paměti
Nedošlo k žádným chybám
vybráno {0} objekt(ů)
Nelze vytvořit složku '{0}'
Aktualizace není podporována pro tento archiv.
Soubor '{0}' nelze otevřít jako archiv
Zakódovaný archiv '{0}' nelze otevřít. Špatné heslo?
Nepodporovaný typ archivu
Soubor {0} již existuje
Soubor '{0}' byl změněn.\nChcete ho aktualizovat v archivu?
Nelze aktualizovat soubor\n'{0}'
Editor nelze spustit.
Soubor se jeví jako virus (ve jménu souboru jsou dlouhé mezery).
Operace nemůže být provedena ze složky s dlouhou cestou.
Musíte vybrat jeden soubor
Musíte vybrat jeden nebo více souborů
Příliš mnoho položek
3300
Rozbalování
Komprimování
Konrola
Otevírání...
Prohledávání...
3400
Rozbalit
&Rozbalit do:
Vyberte umístění pro rozbalené soubory.
3410
Cesty
Plné cesty
Bez cesty
3420
Způsob přepisování
Zeptat se před přepisem
Přepsat bez výzvy
Přeskočit existující soubory
Automatické přejmenování
Automatické přejmenování existujících souborů
3500
Potvrzení nahrazení souboru
Cílová složka již obsahuje zpracovaný soubor.
Chcete nahradit existující soubor
tímto?
{0} bajtů
A&utomaticky přejmenovat
3700
Nepodporovaná komprimační metoda pro '{0}'.
Chyba dat v '{0}'. Soubor je poškozený.
Chyba CRC v '{0}'. Soubor je poškozený.
Chyba dat v zakódovaném souboru '{0}'. Chybné heslo?
Chyba CRC v zakódovaném souboru '{0}'. Chybné heslo?
3800
Vložit heslo
Vložit heslo:
Potvrzení hesla:
Zobrazit he&slo
Heslo nesouhlasí
Pro heslo použíjte pouze anglická písmena, číslice a speciální znaky (!, #, $, ...)
Heslo je příliš dlouhé
Heslo
3900
Uplynulý čas:
Zbývající čas:
Celková velikost:
Rychlost:
Zpracováno:
Komprimační poměr:
Chyb:
Archívy:
4000
Přidat do archivu
&Archiv:
Způsob aktualizace:
&Formát archivu:
Ú&roveň komprese:
&Komprimační metoda:
Ve&likost slovníku:
V&elikost slova:
Velikost bloku:
Počet vláken procesoru:
&Parametry:
Možnosti
Vytvořit SF&X archiv
Zkomprimovat otevřené soubory
Zakódování
Metoda zakódování:
Zakódovat &názvy souborů
Spotřeba paměti pro zabalení:
Spotřeba paměti pro rozbalení:
4050
Skladovací
Nejrychlejší
Rychlá
Normální
Maximální
Ultra
4060
Přidat a nahradit soubory
Aktualizovat a přidat soubory
Aktualizovat existující soubory
Synchronizovat soubory
4070
Procházet
Všechny soubory
Podle velikosti souboru
Pevný
6000
Kopírovat
Přesunout
Kopírovat do:
Přesunout do:
Kopírování...
Přesouvání...
Přejmenování...
Vyberte cílovou složku.
Operace není podporována.
Chyba při přejmenování souboru nebo složky
Potvrzení kopírování souborů
Jste si jistí, že chcete zkopírovat soubory do archivu
6100
Potvrdit vymazání souboru
Potvrdit vymazání složky
Potvrdit mnohonásobné vymazání souboru
Jste si jistí, že chcete vymazat '{0}'?
Jste si jistí, že chcete vymazat složku '{0}' a všechno co obsahuje?
Jste si jistí, že chcete vymazat tyto {0} položky?
Mazání...
Chyba při mazání souboru nebo složky
Systém nepodporuje přesun soubor s dlouhou cestou do Odpadkového koše
6300
Vytvořit složku
Vytvořit soubor
Název složky:
Název souboru:
Nová složka
Nový soubor
Chyba při vytváření složky
Chyba při vytváření souboru
6400
Poznámka
&Poznámka:
Vybrat
Zrušit výběr
Maska:
6600
Vlastnosti
Historie složek
Diagnostické zprávy
Zpráva
7100
Počítač
Síť
Dokumenty
Systém
7200
Přidat
Rozbalit
Zkontrolovat
Kopírovat
Přesunout
Vymazat
Informace
7300
Rozdělit soubor
Rozdělit do:
Rozdělit na díly, bajtů:
Rozdělování...
Potvrdit rozdělování
Jste si jistí, že chcete rozdělit soubor na {0} dílů?
Velikost dílu musí být menší než velikost původního souboru
Nesprávná velikost dílu
Zadaná velikost dílu: {0} bytů.\nJste si jistí, že chcete rozdělit archiv do takových dílů?
7400
Sloučit soubory
Sloučit do:
Slučování...
Musí se vybrat pouze první díl rozděleného soubor
Nepodařilo se rozpoznat rozdělený soubor
Nepodařilo se nalézt více než jeden díl rozděleného souboru
7500
Vypočítávání kontrolního součtu...
Informace o kontrolním součtu
CRC kontrolní součet pro data:
CRC kontrolní součet pro data a jména:
7600
Zkouška výkonu
Spotřeba paměti:
Komprimování
Rozbalování
Výkon
Celkový výkon
Aktuální
Výsledné
Využití procesoru
Výkon / Využití
Průchodů:

404
Utils/7-Zip/Lang/cy.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.37 : Owain Lewis
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Welsh
Cymraeg
401
Iawn
Canslo
&Iawn
&Na
&Cau
Cymorth
P&arhau
440
Iawn i'r &Cwbwl
Na i'r C&wbwl
Stopio
Ailgychwyn
&Cefndir
&Blaendir
&Pwyllo
Pwyllo
Ydych chi am canslo?
500
&Ffeil
&Golygu
Gwe&ld
Ff&efrynnau
&Offer
&Cymorth
540
&Agor
Agor tu &Mewn
Agor tu &Fas
Gwe&ld
&Golygu
A&ilenwi
&Copïo i...
&Symud i...
&Dileu
&Hollti ffeil...
Cy&funo ffeilau...
&Priodweddau
Syl&wad
Cyfrifo swm-gwirio
Creu Ffolder
Creu Ffeil
Alla&n
600
Dewis y C&yfan
Dad-ddewis y Cyfan
Gwrt&hdroi'r Dewis
Dewis...
Dad-ddewis...
Dewis trwy Math
Dad-ddewis trwy Math
700
Eiconau &Mawr
Eiconau &Bach
&Rhestr
Ma&nylion
730
Dad-dosbarthu
Golwg Flat
&2 Paneli
Bariau &Offer
Agor Ffolder Gwraidd
Lan Un Lefel
Hanes Ffolderi...
&Adnewyddu
750
Bar Offer Archif
Bar Offer Arferol
Botwmau Fawr
Dangos Testun Botwmau
800
&Ychwanegu ffolder i Ffefrynnau fel
Llyfrnod
900
&Dewisiadau...
&Meincnod
960
&Cynnwys...
&Manylion 7-Zip...
1003
Llwybr
Enw
Estyniad
Ffolder
Maint
Maint wedi'i Cywasgu
Priodweddau
Crëwyd
Cyrchwyd
Addaswyd
Solet
Sylwad
Amgryptio
Hollti Cyn
Hollti ar Ôl
Geiriadur
CRC
Math
Anti
Dull
SW Cynnal
System Ffeiliau
Ddefnyddiwr
Grŵp
Bloc
Sylwad
Safle
Rhagddodiad y Llwybr
Gwall
Cyfanswm Maint
Lle Rhydd
Maint Clwstwr
Label
Enw Lleol
Darparwr
2100
Dewisiadau
Iaith
Iaith:
Golygydd
&Golygydd:
2200
System
Cysylltu 7-Zip gyda:
2301
Cyfuno 7-Zip mewn i dewislen cyd-destun y cribyn
Dewislen cyd-destun wedi'i rhaeadru
Eitemau dewislen cyd-destun:
2320
<Ffolder>
<Archif>
Agor archif
Echdynnu ffeiliau...
Ychwanegu i'r archif...
Profi archif
Echdynnu Yma
Echdynnu i {0}
Ychwanegu i {0}
Cywasgu ac e-bostio...
Cywasgu i {0} ac e-bostio
2400
Ffolderi
Ffolder &gweithio
Ffolder tymor byr y &system
&Cyfredol
&Penodol:
Defnyddiwch am gyriant symudadwy yn unig
Nodwch lleoliad am ffeiliau archif tymor byr.
2500
Gosodiadau
Dangos eitem ".."
Dangos eicon ffeil go iawn
Dangos dewislen y system
Dethol &holl rhes
Dangos llinellau &grid
Modd dethol &arallddewisiol
Defnyddiwch tudalenau cof &mawr
2900
Manylion 7-Zip
Mae 7-Zip yn meddalwedd am ddim. Ond, gallwch cefnogi y \ndatblygiad o 7-Zip trwy cofrestru.
3000
Mae na ddim wallau
{0} gwrthrych(au) dethol
Ddim yn gallu creu y ffolder '{0}'
Mae gweithrediadau diweddaru ddim yn ateg am yr archif hyn.
Roedd ffeil '{0}' wedi'i addasu.\nWyt ti moen ei diweddaru yn yr \narchif?
Ddim yn gallu diweddaru ffeil\n'{0}'
Ddim yn gallu dechrau golygydd.
Gormod o eitemau
3300
Echdynnu
Cywasgu
Ymbrofi
Agor...
Sganio...
3400
Echdynnu
E&chdynnu i:
Nodwch lleoliad am echdynnu ffeiliau.
3410
Modd llwybr
Enwau llwybr llawn
Dim enwau llwybr
3420
Modd disodli
Gofyn cyn disodli
Disodli heb awgrymeb
Crychneidio ffeiliau presennol
Ailenwu yn awtomatig
Ailenwu ffeiliau presennol yn awtomatig
3500
Cadarnhau Disodli Ffeil
Mae'r ffolder hon eisioes yn cynnwys y ffeil cyrchfan.
Hoffech chi ddisodli'r ffeil sy'n bodoli eisioes
Gyda hon?
{0} beit
Ailenwi A&wtomatig
3700
Modd cywasgu ddim yn dilys am '{0}'.
Gwall data mewn '{0}'. Ffeil wedi'i torri.
CRC wedi'i methu mewn '{0}'. Ffeil wedi'i torri.
3800
Mewnbynnwch cyfrinair
Mewnbynnwch cyfrinair:
&Dangos cyfrinair
Cyfrinair
3900
Wedi treiglo:
Amser a'r ôl:
Maint:
Cyflymder:
Gwallau:
4000
Ychwanegu i'r archif
&Archif:
Modd &diweddaru:
&Fformat yr archif:
&Lefel cywasgu:
Dull &cywasgu:
Maint &geiriadur:
Maint geiria&u:
&Paramedrau:
Dewisiadau
Creu archif SF&X
Amgryptio &enwau ffeiliau
Defnydd cof am Cywasgu:
Defnydd cof am Datgywasgu:
4050
Storio
Cyflymach
Cyflum
Arferol
Uchafswm
Ultra
4060
Ychwanegu ac amnewid ffeiliau
Diweddaru ac ychwanegu ffeiliau
Adnewyddu y ffeiliau presennol
Cyfamseru ffeiliau
4070
Pori
Pob Ffeil
6000
Copïo
Symud
Copïo i:
Symud i:
Copïo...
Symud...
Ailenwi...
Mae'r gweithrediad ddim wedi'i ategu.
Gwall wrth Ailenwi Ffeil neu Ffolder
Cadarnhau Copi Ffeil
Ydych chi'n siŵr eich bod am copïo'r ffeiliau i'r archif
6100
Cadarnhau Dileu Ffeil
Cadarnhau Dileu Ffolder
Cadarnhau Dileu Ffeiliau Amryfal
Ydych chi'n siŵr eich bod am dileu '{0}'?
Ydych chi'n siŵr eich bod am dileu y ffolder '{0}' ac ei holl \ncynnwys?
Ydych chi'n siŵr eich bod am dileu yr eitemau hyn {0}?
Dileu...
Gwall Dileu Ffeil neu Ffolder
6300
Creu Ffolder
Creu Ffeil
Enw Ffolder:
Enw Ffeil:
Ffolder Newydd
Ffeil Newydd
Gwall wrth Creu Ffolder
Gwall wrth Creu Ffeil
6400
Sylwad
&Sylwad:
Dewis
Dad-ddewis
Mwgwd:
6600
Hanes Ffolderi
Neges diagnostig
Neges
7100
Cyfrifiadur
Rhyngrwyd
System
7200
Ychwanegu
Echdynnu
Profi
Copïo
Symud
Dileu
Gwybodaeth
7300
Hollti Ffeil
&Hollti i:
Hollti i &cyfeintiau, beitiau:
Hollti...
7400
Cyfuno Ffeiliau
&Cyfuno i:
Cyfuno...
7500
Cyfrifo swm-gwirio...
Gwybodaeth swm-gwirio
Swm-gwirio CRC am data:
Swm-gwirio CRC am data ac enwau:
7600
Meincnod
Defnyddiad cof:
Cywasgu
Datgywasgu
Amcangyfrif
Amcangyfrif llwyr
Presennol
Canlyniad
Pasio:

495
Utils/7-Zip/Lang/da.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; : Jakob Schmidt
; 9.07 : Kian Andersen, Jørgen Rasmussen
; 15.00 : 2016-08-19 : scootergrisen
;
;
;
;
;
;
;
;
0
7-Zip
Danish
Dansk
401
OK
Annuller
&Ja
&Nej
&Luk
Hjælp
&Fortsæt
440
Ja til &alle
Nej til a&lle
Stop
Genstart
&Baggrund
&Forgrund
&Pause
Pauset
Er du sikker på, at du vil annullere?
500
&Filer
R&ediger
&Vis
F&avoritter
Funk&tioner
&Hjælp
540
&Åbn
Åbn &inden i
Åbn &uden for
&Vis
&Rediger
O&mdøb
&Kopier til...
&Flyt til...
S&let
&Opdel fil...
Kom&biner filer...
&Egenskaber
Komme&ntar...
Udregn checksum
Sammenlign
Opret mappe
Opret fil
&Afslut
Opret/rediger henvisning
&Alternative strømme
600
Vælg &alle
Fravælg alle
&Omvendt markering
Vælg...
Fravælg...
Vælg efter type
Fravælg efter type
700
Sto&re ikoner
S&må ikoner
&Liste
&Detaljer
730
Usorteret
Flad visning
&2 paneler
&Værktøjslinjer
Åbn rodmappe
Et niveau op
Mappehistorik...
&Opdater
Opdater automatisk
750
Arkivlinje
Standardlinje
Store knapper
Vis knappernes tekst
800
&Føj mappe til Favoritter som
Bogmærke
900
&Funktioner...
&Benchmark
960
&Indhold...
&Om 7-Zip...
1003
Sti
Navn
Filtype
Mappe
Størrelse
Pakket størrelse
Attributter
Oprettet
Åbnet
Ændret
Solid
Kommenteret
Krypteret
Opdel før
Opdel efter
Leksikon
Type
Anti
Metode
Vært OS
Filsystem
Bruger
Gruppe
Blok
Kommentar
Placering
Sti præfiks
Mapper
Filer
Version
Bind
Flerbindsarkiv
Forskydning
Henvisning
Blokke
Bind
64-bit
Big-endian
CPU
Fysisk størrelse
Hovedernes størrelse
Checksum
Karakteristika
Virtuel adresse
ID
Kort navn
Oprettende program
Sektorstørrelse
Tilstand
Symbolsk henvisning
Fejl
Samlet størrelse
Fri plads
Klyngestørrelse
Etiket
Lokalt navn
Udbyder
NT Security
Alternativ strøm
Aux
Slettet
Er træ
Fejltype
Fejl
Fejl
Advarsler
Advarsel
Strømme
Alternative strømme
Størrelse på alternative strømme
Virtuel størrelse
Udpakket størrelse
Samlet fysiske størrelse
Bind-indeks
Undertype
Kort kommentar
Tegnsæt
Halestørrelse
Indlejret stumpstørrelse
Henvisning
Fast henvisning
iNode
Skrivebeskyttet
2100
Funktioner
Sprog
Sprog:
Redigering
&Rediger:
&Sammenlign:
2200
System
Knyt 7-Zip til:
Alle brugere
2301
Vis i Windows genvejsmenu
Brug undermenu
Punkter i genvejsmenu:
Ikoner i genvejsmenu
2320
<Mappe>
<Arkiv>
Åbn arkiv
Udpak filer...
Føj til arkiv...
Test arkiv
Udpak her
Udpak til {0}
Føj til {0}
Komprimer og vedhæft i e-mail...
Komprimer til {0} og vedhæft i e-mail
2400
Mapper
&Arbejdsmappe
&Systemets midlertidige mappe
&Aktuelle
&Brugerdefineret:
Brug kun til flytbare drev
Angiv en placering til midlertidige arkivfiler.
2500
Indstillinger
Vis ".."-element
Vis rigtige filikoner
Vis systemmenu
&Marker hele rækken
Vis &gitter
Åbn element med ét klik
&Alternativ markeringsmetode
Brug &store hukommelsessider
2900
Om 7-Zip
7-Zip er fri software
3000
Systemet kan ikke tildele den nødvendige mængde hukommelse
Der er ingen fejl
{0} markerede element(er)
Kan ikke oprette mappen "{0}"
Arkivet understøtter ikke opdateringshandlinger.
Kan ikke åbne filen "{0}" som arkiv
Kan ikke åbne det krypterede arkiv "{0}". Forkert adgangskode?
Arkivtypen er ikke understøttet
Filen {0} findes allerede
Filen "{0}" er blevet ændret.\nVil du opdatere den i arkivet?
Kan ikke opdatere filen\n"{0}"
Kan ikke starte redigering.
Filen ligner en virus (filnavnet indeholder lange mellemrum i navn).
Handlingen kan ikke kaldes fra en mappe som har en lang sti.
Du skal vælge en fil
Du skal vælge en eller flere filer
For mange elementer
Kan ikke åbne filen som {0}-arkiv
Filen er åbnet som {0}-arkiv
Arkivet er åbnet med forskydning
3300
Udpakker
Komprimerer
Tester
Åbner...
Skanner...
Fjerner
3320
Tilføjer
Opdaterer
Analyserer
Replikerer
Ompakker
Springer over
Sletter
Opretter hovede
3400
Udpak
U&dpak til:
Angiv en placering til udpakkede filer.
3410
Stitilstand:
Fulde stinavne
Ingen stinavne
Absolutte stinavne
Relative stinavne
3420
Overskrivningstilstand:
Spørg før overskrivning
Overskriv uden at spørge
Spring eksisterende filer over
Automatisk omdøbning
Automatisk omdøbning af eksisterende filer
3430
Forhindr duplikering af rodmappe
Genskab filsikkerhed
3500
Bekræft filerstatning
Destinationsmappen indeholder allerede behandlet fil.
Vil du erstatte den eksisterende fil
med denne?
{0} byte
A&utomatisk omdøbning
3700
Komprimeringsmetode for "{0}" er ikke understøttet.
Datafejl i "{0}". Filen er ødelagt.
CRC mislykkedes i "{0}". Filen er ødelagt.
Datafejl i den krypterede fil "{0}". Forkert adgangskode?
CRC mislykkedes i den krypterede fil "{0}". Forkert adgangskode?
3710
Forkert adgangskode?
3721
Komprimeringsmetoden er ikke understøttet
Datafejl
CRC mislykkedes
Utilgængelig data
Uventet slutning på data
Der er data efter slutningen af nyttedataene
Ikke et arkiv
Fejl i hoveder
Forkert adgangskode
3763
Utilgængelig begyndelse på arkiv
Ubekræftet begyndelse på arkiv
Faciliteten understøttes ikke
3800
Indtast adgangskode
Indtast adgangskode:
Indtast adgangskode igen:
&Vis adgangskode
Adgangskoderne er ikke ens
Brug kun engelske bogstaver, numre og specialtegn (!, #, $, ...) til adgangskoden
Adgangskoden er for lang
Adgangskode
3900
Forløbet tid:
Resterende tid:
Samlet størrelse:
Hastighed:
Behandlet:
Komprimeringsforhold:
Fejl:
Arkiver:
4000
Føj til arkiv
&Arkiv:
O&pdateringstilstand:
Arkiv&format:
Komprimerings&niveau:
Komprimerings&metode:
Størrelse på or&dbog:
Størrelse på &ord:
Størrelse på solid blok:
Antal CPU-tråde:
Pa&rametre:
Funktioner
Opret SF&X-arkiv
Komprimer delte filer
Kryptering
Krypteringsmetode:
Kr&ypter filnavne
Hukommelsesforbrug ved komprimering:
Hukommelsesforbrug ved udpakning:
Slet filer efter komprimering
4040
Gem symbolske henvisninger
Gem hårde henvisninger
Gem alternative datastrømme
Gem filsikkerhed
4050
Gem
Hurtigst
Hurtig
Normal
Maksimum
Ultra
4060
Tilføj og erstat filer
Opdater og tilføj filer
Opdater eksisterende filer
Synkroniser filer
4070
Gennemse
Alle filer
Ikke-solid
Solid
6000
Kopier
Flyt
Kopier til:
Flyt til:
Kopierer...
Flytter...
Omdøber...
Vælg destinationsmappen.
Handlingen understøttes ikke af denne mappe.
Fejl under omdøbning af fil eller mappe
Bekræft kopiering af fil
Er du sikker på, at du vil kopiere filer til arkiv
6100
Bekræft sletning af fil
Bekræft sletning af mappe
Bekræft sletning af flere filer
Er du sikker på, at du vil slette "{0}"?
Er du sikker på, at du vil slette mappen "{0}" og alt dens indhold?
Er du sikker på, at du vil slette disse {0} elementer?
Sletter...
Fejl under sletning af fil eller mappe
Systemet kan ikke flytte en fil med lang sti til Papirkurven
6300
Opret mappe
Opret fil
Mappenavn:
Filnavn:
Ny mappe
Ny fil
Fejl under oprettelse af mappe
Fejl under oprettelse af fil
6400
Kommentar
&Kommentar:
Vælg
Fravælg
Maske:
6600
Egenskaber
Mappers historik
Diagnostiske meddelelser
Meddelelse
7100
Computer
Netværk
Dokumenter
System
7200
Tilføj
Udpak
Test
Kopier
Flyt
Slet
Info
7300
Opdel fil
&Opdel til:
Opd&el i bind, byte:
Opdeler...
Bekræft opdeling
Er du sikker på, at du vil opdele filen i {0} bind?
Størrelsen på bind skal være mindre end størrelsen på den oprindelige fil
Forkert størrelse på bind
Angivet størrelse på bind: {0} byte.\nEr du sikker på, at du vil opdele arkivet i disse bind?
7400
Kombiner filer
&Kombiner til:
Kombinerer...
Vælg kun første del af opdelt fil
Kan ikke genkende fil, som del af opdelt fil
Kan ikke finde mere end én del af opdelt fil
7500
Beregner checksum...
Checksum information
CRC-checksum for data:
CRC-checksum for data og navne:
7600
Benchmark
Hukommelsesforbrug:
Komprimering
Udpakning
Vurdering
Samlet vurdering
Aktuelt
Resultat
CPU forbrug
Vurdering/forbrug
Gennemløb:
7700
Opret/rediger henvisning
Opret/rediger henvisning
Henvisning fra:
Henvisning til:
7710
Henvisningstype
Fast henvisning
Fil symbolsk henvisning
Mappe symbolsk henvisning
Mappe forbindelsespunkt

495
Utils/7-Zip/Lang/de.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; 2.30 : Soeren Finster
; 4.07 : JAK-Software.DE
; 9.07 : Joachim Henke
;
;
;
;
;
;
;
;
0
7-Zip
German
Deutsch
401
OK
Abbrechen
&Ja
&Nein
&Schließen
Hilfe
&Fortsetzen
440
Ja für &alle
Nein für a&lle
Stopp
Neustart
&Hintergrund
&Vordergrund
&Pause
Pause
Möchten Sie wirklich abbrechen?
500
&Datei
&Bearbeiten
&Ansicht
&Favoriten
&Extras
&Hilfe
540
Ö&ffnen
I&ntern öffnen
E&xtern öffnen
&Ansehen
&Bearbeiten
&Umbenennen
&Kopieren nach...
&Verschieben nach...
&Löschen
Datei auf&splitten...
Dateien &zusammenfügen...
E&igenschaften
K&ommentieren
&Prüfsumme berechnen
Ver&gleichen
Ordner erstellen
Datei erstellen
Be&enden
Verknüpfung...
&Alternative Datenströme
600
Alles &markieren
Alles abwählen
Markierung &umkehren
Auswählen...
Auswahl aufheben...
Nach Typ auswählen
Nach Typ abwählen
700
&Große Symbole
&Kleine Symbole
&Liste
&Details
730
Unsortiert
Alles in einer &Ebene
&Zweigeteiltes Fenster
&Symbolleisten
Wurzelverzeichnis
Übergeordneter Ordner
Ordnerverlauf...
&Aktualisieren
Auto-Aktualisierung
750
Archivfunktionen
Standardfunktionen
Große Schaltflächen
Schaltflächenbeschriftung
800
&Ordner hinzufügen als
Favorit
900
&Optionen...
&Benchmark
960
&Hilfethemen
Ü&ber 7-Zip...
1003
Pfad
Name
Erweiterung
Ordner
Größe
Gepackte Größe
Attribute
Erstellt am
Letzter Zugriff
Geändert am
Kompakt (solid)
Kommentiert
Verschlüsselt
Vorher geteilt
Danach geteilt
Wörterbuch
CRC
Typ
Anti
Verfahren
Herkunft
Dateisystem
Besitzer
Gruppe
Block
Kommentar
Position
Pfad
Ordner
Dateien
Version
Teilarchiv
Mehrteiliges Archiv
Offset
Verknüpfungen
Blöcke
Teilarchive
64 Bit
Big-Endian
CPU
Gesamtgröße
Header-Größe
Prüfsumme
Kenndaten
Virtuelle Adresse
ID
Kurzname
Erstellt durch
Sektorgröße
Zugriffsrechte
Link
Fehler
Gesamtgröße
Freier Speicherplatz
Cluster-Größe
Name
Lokaler Name
Provider
NT-Sicherheit
Alternativer Datenstrom
Aux
Gelöscht
Ist Baum
Fehlertyp
Fehler
Fehler
Warnungen
Warnung
Datenströme
Alternative Datenströme
Größe der alternativen Datenströme
Virtuelle Größe
Entpackte Größe
Gesamte physikalische Größe
Teilstück Index
Untertyp
Kurzkommentar
Code-Seite
Endungsgröße
integrierte Stub-Größe
Verknüpfung
Harte Verknüpfung
iNode
Schreibgeschützt
2100
Optionen
Sprache
Sprache:
Editor
&Editor:
Programm zum &Vergleichen:
2200
System
7-Zip verknüpfen mit:
alle Benutzer
2301
7-Zip in Kontextmenü integrieren
Kontextmenü kaskadieren
Einträge im Kontextmenü:
Symbole im Kontextmenü
2320
<Verzeichnis>
<Archiv>
Öffnen
Dateien entpacken...
Zu einem Archiv hinzufügen...
Archiv überprüfen
Hier entpacken
Entpacken nach {0}
Hinzufügen zu {0}
Archivieren und versenden...
Archivieren in {0} und versenden
2400
Ordner
&Arbeitsverzeichnis
&TEMP-Ordner des Systems
Aktueller &Ordner
&Benutzerdefiniert:
Nur bei &Wechselmedien benutzen
Wählen Sie einen Ordner für temporäre Archivdateien:
2500
Einstellungen
&Verzeichniseintrag ".." anzeigen
Symbole aus &Dateien laden und anzeigen
System-Kontext&menü im Dateimenü anzeigen
Dateiauswahl markiert ganze &Zeile
&Gitternetzlinien anzeigen
Einfacher &Klick zum Öffnen
&Alternativer Dateiauswahl-Modus
Große &Speicherseiten verwenden
2900
Info über 7-Zip
7-Zip ist freie Software. Sie können jedoch das Projekt durch eine Registrierung unterstützen.
3000
Das System kann die benötigte Speichermenge nicht bereit stellen.
Es sind keine Fehler aufgetreten.
{0} Objekt(e) markiert
Kann den Ordner "{0}" nicht erstellen.
Aktualisierungen werden für dieses Archiv nicht unterstützt.
Die Datei "{0}" kann nicht als Archiv geöffnet werden.
Das verschlüsselte Archiv "{0}" kann nicht geöffnet werden. Falsches Passwort?
Typ des Archives wird nicht unterstützt
Die Datei {0} existiert bereits.
Die Datei "{0}" wurde geändert.\nSoll sie im Archiv aktualisiert werden?
Die Datei konnte nicht aktualisiert werden.\n"{0}"
Kann Editor nicht starten
Die Datei scheint ein Virus zu sein (Dateiname enthält lange Reihen von Leerzeichen).
Die Operation kann nicht aus einem Ordner mit langem Pfad aufgerufen werden.
Bitte genau eine Datei auswählen.
Bitte mindestens eine Datei auswählen.
Zu viele Objekte
Die Datei kann nicht als {0}-Archiv geöffnet werden.
Die Datei wurde als {0}-Archiv geöffnet.
Die Datei wurde mit einem Offset geöffnet.
3300
Entpacken
Komprimiere
Überprüfen
Öffne...
Durchsuche...
Entferne
3320
Hinzufügen
Aktualisieren
Analysieren
Replizieren
Neu Packen
Überspringen
Löschen
Header erstellen
3400
Entpacken
&Entpacken nach:
Wählen Sie einen Ordner für die entpackten Dateien:
3410
Verzeichnisstruktur wiederherstellen
Komplette Pfadangaben
Keine Pfadangaben
Absolute Pfadangaben
Relative Pfadangaben
3420
Dateien überschreiben
Nur mit Bestätigung
Ohne Bestätigung
Vorhandene Dateien überspringen
Automatisch umbenennen
Vorhandene Dateien umbenennen
3430
Verdoppelung des Wurzelordners vermeiden
Dateirechte wiederherstellen
3500
Überschreiben bestätigen
Der Zielordner beinhaltet bereits eine Datei diesen Namens.
Wollen Sie diese Datei
durch diese ersetzen?
{0} Bytes
A&utomatisch umbenennen
3700
Das Kompressionsverfahren in "{0}" wird nicht unterstützt.
Datenfehler in "{0}". Die Datei ist beschädigt.
CRC-Prüfsummenfehler. Die Datei "{0}" ist beschädigt.
Datenfehler in der verschlüsselten Datei "{0}". Falsches Passwort?
CRC-Prüfsummenfehler bei verschlüsselter Datei "{0}". Falsches Passwort?
3710
Falsches Passwort?
3721
Nicht unterstützte Kompressionsmethode
Datenfehler
CRC-Fehler
Daten stehen nicht zur Verfügung
Unerwartetes Datenende
Es gibt noch Daten hinter den Hauptdaten
Ist kein Archiv
Headers-Fehler
Falsches Passwort
3763
Anfang des Archivs fehlt
Anfang des Archivs nicht bestätigt
Nicht unterstützte Funktion
3800
Kennworteingabe
Passwort eingeben:
Passwort bestätigen:
Passwort an&zeigen
Die Passwörter stimmen nicht überein.
Bitte nur Buchstaben des englischen Alphabets, Ziffern und Sonderzeichen (!, #, $, ...) im Passwort verwenden!
Das Passwort ist zu lang.
Passwort
3900
Verstrichene Zeit:
Verbleibende Zeit:
Gesamtdatenmenge:
Geschwindigkeit:
Verarbeitet:
Kompressionsrate:
Fehler:
Archive:
4000
Zu Archiv hinzufügen
&Archiv:
Art der Akt&ualisierung:
Archiv&format:
&Kompressionsstärke:
Kompressions&verfahren:
Wörter&buchgröße:
&Wortgröße:
Größe &solider Blöcke:
Anzahl &CPU-Threads:
&Parameter:
Optionen
Selbstentpackendes Archiv (SF&X) erstellen
Zum Schreiben &geöffnete Dateien einbeziehen
Verschlüsselung
Verfahren:
Datei&namen verschlüsseln
Speicherbedarf beim Komprimieren:
Speicherbedarf beim Entpacken:
Dateien nach Komprimierung löschen
4040
Symbolische Verknüpfungen speichern
Harte Verknüpfungen speichern
Alternative Datenströme speichern
Dateirechte speichern
4050
Speichern
Schnellste
Schnell
Normal
Maximum
Ultra
4060
Hinzufügen und Ersetzen
Aktualisieren und Hinzufügen
Vorhandene Dateien aktualisieren
Synchronisieren
4070
Durchsuchen
Alle Dateien
Nicht solide
Solide
6000
Kopieren
Verschieben
Kopieren nach:
Verschieben nach:
Kopiere...
Verschiebe...
Umbenennen...
Zielordner auswählen
Die Operation wird für diesen Ordner nicht unterstützt.
Fehler beim Umbenennen von Datei oder Ordner
Kopieren bestätigen
Sollen die Dateien wirklich in dieses Archiv kopiert werden:
6100
Löschen von Datei bestätigen
Löschen von Ordner bestätigen
Löschen von mehreren Dateien bestätigen
Soll "{0}" wirklich gelöscht werden?
Soll der Ordner "{0}" und sein gesamter Inhalt wirklich gelöscht werden?
Sollen diese {0} Objekte wirklich gelöscht werden?
Lösche...
Fehler beim Löschen von Datei oder Ordner
Das System kann Dateien mit langem Pfad nicht in den Papierkorb verschieben.
6300
Ordner erstellen
Datei erstellen
Ordnername:
Dateiname:
Neuer Ordner
Neue Datei
Fehler beim Erstellen des Ordners
Fehler beim Erstellen der Datei
6400
Kommentar
&Kommentar:
Auswählen
Auswahl aufheben
Filter:
6600
Eigenschaften
Ordnerverlauf
Diagnosemeldungen
Meldung
7100
Arbeitsplatz
Netzwerk
Dokumente
System
7200
Hinzufügen
Entpacken
Überprüfen
Kopieren
Verschieben
Löschen
Eigenschaften
7300
Datei aufsplitten
Teildateien &nach:
In &Teildateien aufsplitten (Bytes):
Aufsplitten...
Aufsplitten bestätigen
Sind Sie sicher, die Datei in {0} Teildateien aufsplitten zu wollen?
Die Größe der Teildateien muss kleiner sein als die der ursprünglichen Datei.
Ungültiger Wert für Dateigrößen
Angegebene Größe für Teildateien: {0} Bytes.\nSind Sie sicher, dass das Archiv dementsprechend aufgesplittet werden soll?
7400
Dateien zusammenfügen
Zieldatei &nach:
Zusammenfügen...
Bitte nur den ersten Teil der Datei auswählen.
Datei nicht als Teil einer aufgesplitteten Datei erkannt
Kann nicht mehr als eine Teildatei finden.
7500
Berechne Prüfsumme...
Prüfsummen-Information
CRC-Prüfsumme über die Daten:
Prüfsumme über Daten und Namen:
7600
Benchmark
Speichernutzung:
Komprimierung
Dekomprimierung
Bewertung
Gesamtwertung
Aktuell
Ergebnis
CPU-Nutzung
Bewert./Nutzung
Durchläufe:
7700
Verknüpfung
Verknüpfung
Verknüpfung von:
Verknüpfung zu:
7710
Verknüpfungsart
Harte Verknüpfung
Datei Symbolische Verknüpfung
Ordner Symbolische Verknüpfung
Ordner Verbindung

495
Utils/7-Zip/Lang/el.txt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; : Vasileios Karakoidas, Jacaranda Bill, Vasilis Kosmidis
; 9.07 : SkyHi [HDManiacs Team]
; 15.00 : 2015-05-07: Pete D
;
;
;
;
;
;
;
;
0
7-Zip
Greek
Ελληνικά
401
OK
Άκυρο
&Ναι
Ό&χι
&Κλείσιμο
Βοήθεια
&Συνέχεια
440
Ναι σε &όλα
Όχι σε ό&λα
&Παύση
Επανεκκίνηση
Στο &παρασκήνιο
Στο &προσκήνιο
&Παύση
Παύθηκε
Είστε σίγουροι ότι θέλετε να ακυρώσετε;
500
&Αρχείο
&Επεξεργασία
Π&ροβολή
Αγα&πημένα
Εργα&λεία
&Βοήθεια
540
Άν&οιγμα
Άνοιγμα στο &ίδιο παράθυρο
Άνοιγμα σε &νέο παράθυρο
Π&ροβολή
Επε&ξεργασία
Με&τονομασία
Αντι&γραφή...
Μετα&κίνηση...
Διαγρα&φή
&Τεμαχισμός αρχείου...
&Συνένωση αρχείων...
&Ιδιότητες
Σχόλιο
Υπολογισμός αθροίσματος ελέγχου
Diff
Δημιουργία φακέλου
Δημιουργία αρχείου
Έ&ξοδος
Σύνδεσμος
&Alternate Streams
600
Ε&πιλογή όλων
Αποεπιλογή όλων
Αντιστροφή επιλογής
Επιλογή...
Αποεπιλογή...
Επιλογή σύμφωνα με τον τύπο αρχείου
Αποεπιλογή σύμφωνα με τον τύπο αρχείου
700
Μεγάλα εικονί&δια
&Μικρά εικονίδια
&Λίστα
Λε&πτομέρειες
730
Χωρίς ταξινόμηση
Επίπεδη προβολή
2 πάνελ
&Γραμμές εργαλείων
Άνοιγμα κεντρικού φακέλου
Μετάβαση ένα επίπεδο πάνω
&Ιστορικό φακέλων...
Α&νανέωση
Αυτόματη ανανέωση
750
Συμπίεσης
Βασική
Μεγάλα εικονίδια
Εμφάνιση κειμένου
800
&Προσθήκη καταλόγου στα Αγαπημένα ως
Σελιδοδείκτης
900
&Ρυθμίσεις...
&Ελεγχος επιδόσεων
960
&Περιεχόμενα...
Π&ερί του 7-Zip...
1003
Θέση
Όνομα
Τύπος
Φάκελος
Μέγεθος
Συμπιεσμένο μέγεθος
Ιδιότητες
Δημιουργήθηκε
Προσπελάστηκε
Τροποποιήθηκε
Συμπαγές
Σχόλιο
Κωδικοποιημένο
Τεμαχισμός πριν
Τεμαχισμός μετά
Λεξικό
Τύπος
Αντί
Μέθοδος
Λειτουργικό
Σύστημα αρχείων
Χρήστης
Ομάδα
Μπλοκ
Σχόλιο
Θέση
Προκαθορισμένη διαδρομή
Φάκελοι
Αρχεία
Έκδοση
Τόμος
Πολυτόμος
Offset
Σύνδεσμοι
Μπλοκ
Τόμοι
64-bit
Big-endian
CPU
Φυσικό μέγεθος
Μέγεθος headers
Άθροισμα ελέγχου
Χαρακτηριστικά
Εικονική διεύθυνση
ID
Σύντομο όνομα
Εφαρμογή δημιουργίας
Μέγεθος τομέα
Κατάσταση λειτουργίας
Σύνδεσμος
Σφάλμα
Συνολικό μέγεθος
Ελεύθερος χώρος
Μέγεθος συμπλέγματος
Ετικέτα
Τοπικό όνομα
Παροχέας
NT Security
Alternate Stream
Aux
Deleted
Is Tree
Τύπος λάθους
Λάθη
Λάθη
Προειδοποιήσεις
Προειδοποίηση
Streams
Alternate Streams
Alternate Streams Size
Εικονικό μέγεθος
Αποσυμπιεσμένο μέγεθος
Συνολικό φυσικό μέγεθος
Ευρετήριο τόμου
SubType
Σύντομο σχόλιο
Κωδικοσελίδα
Tail Size
Embedded Stub Size
Σύνδεσμος
Σταθερός σύνδεσμος
iNode
Ανάγνωση-Μόνο
2100
Ρυθμίσεις
Γλώσσα
Γλώσσα:
Πρόγραμμα επεξεργασίας
&Πρόγραμμα επεξεργασίας:
&Diff:
2200
Σύστημα
Συσχέτιση του 7-Zip με τα αρχεία:
Ολοι οι χρήστες
2301
Ενσωμάτωση του 7-Zip στο λειτουργικό
Με ομαδοποίηση των επιλογών
Στοιχεία του αναδυόμενου μενού:
Εικονίδια στο αναδυόμενο μενού
2320
<Φάκελος>
<Αρχείο Συμπίεσης>
Άνοιγμα
Αποσυμπίεση αρχείων...
Προσθήκη σε αρχείο συμπίεσης...
Έλεγχος αρχείου συμπίεσης
Αποσυμπίεση εδώ
Αποσυμπίεση στο φάκελο {0}
Προσθήκη στο {0}
Συμπίεση και αποστολή με e-mail...
Συμπίεση στο {0} και αποστολή με e-mail
2400
Φάκελοι
&Φάκελος εργασίας
&Προσωρινός φάκελος συστήματος
&Τρέχων φάκελος
&Καθορισμένος:
Χρήση μόνο για αφαιρούμενες μονάδες δίσκου
Καθορίστε μια τοποθεσία για τα προσωρινά αρχεία συμπίεσης.
2500
Επιλογές
Εμφάνιση αντικειμένου ".."
Εμφάνιση των κανονικών εικονιδίων των αρχείων
Εμφάνιση μενού συστήματος
&Επιλογή ολόκληρης διαδρομής
Εμφάνιση γραμμών πλέγματος
Άνοιγμα αντικειμένου με μονό κλικ
Εναλλακτική κατάσταση επιλογής
Χρήση μεγάλων &σελίδων μνήμης
2900
Πληροφορίες για το 7-Zip
Το 7-Zip είναι ελεύθερο λογισμικό. Ωστόσο μπορείτε να υποστηρίξετε την περαιτέρω ανάπτυξη του με την εγγραφή σας.
3000
Το σύστημα δεν μπορεί να διαθέσει την απαιτούμενη ποσότητα μνήμης.
Δεν υπάρχουν σφάλματα
{0} επιλεγμένα στοιχεία
Αδύνατη η δημιουργία του φακέλου '{0}'
Οι λειτουργίες ενημέρωσης δεν είναι διαθέσιμες για αυτόν τον τύπο συμπιεσμένου αρχείου.
Δεν μπορεί να ανοιχθεί το αρχείο '{0}' σαν αρχείο συμπίεσης
Δεν μπορεί να ανοιχθεί το κρυπτογραφημένο αρχείο '{0}'. Λάθος κωδικός;
Μη υποστηριζόμενο αρχείο συμπίεσης.
Το αρχείο {0} ήδη υπάρχει.
Το αρχείο '{0}' τροποποιήθηκε.\nΘέλετε να ενημερώσετε το αρχείο συμπίεσης;
Αδυνατή η ενημέρωση του αρχείου\n'{0}'
Δεν είναι δυνατή η εκκίνηση του προγράμματος επεξεργασίας.
Το αρχείο μοιάζει με ιό (το όνομα του περιέχει μεγάλα κενά).
Η λειτουργία δεν μπορεί να κληθεί από ένα φάκελο που έχει μεγάλη διαδρομή.
Πρέπει να επιλέξετε ένα αρχείο.
Πρέπει να επιλέξετε ένα ή περισσότερα αρχεία.
Πάρα πολλά στοιχεία
Αδυναμία ανοίγματος του αρχείου ως {0} συμπιεσμένο
Το αρχείο είναι ανοιχτό ως {0} συμπιεσμένο
Το συμπιεσμένο αρχείο είναι ανοιχτό με offset
3300
Αποσυμπίεση
Συμπίεση
Έλεγχος
Άνοιγμα...
Σάρωση...
Διαγραφή...
3320
Προσθήκη..
Ενημέρωση..
Ανάλυση..
Αντιγραφή..
Επανασυμπίεση..
Παράλειψη..
Διαγραφή..
Δημιουργία κεφαλίδας..
3400
Αποσυμπίεση
&Αποσυμπίεση στο φάκελο:
Καθορίστε τον φάκελο αποσυμπίεσης.
3410
Επιλογές διαδρομών φακέλων
Πλήρεις διαδρομές φακέλων
Χωρίς διαδρομές φακέλων
Απόλυτες διαδρομές φακέλων
Σχετικές διαδρομές φακέλων
3420
Επιλογές αντικατάστασης αρχείων
Αντικατάσταση με ερώτηση
Αντικατάσταση χωρίς ερώτηση
Παράβλεψη των υπαρχόντων αρχείων
Αυτόματη μετονομασία
Αυτόματη μετονομασία των υπαρχόντων αρχείων
3430
Απαλοιφή ριζικού καταλόγου
Επαναφορά ασφάλειας αρχείου
3500
Επιβεβαίωση αντικατάστασης του αρχείου
Ο φάκελος προορισμού περιέχει ήδη ένα αρχείο με το ίδιο όνομα.
Θέλετε να αντικαταστήσετε το υπάρχον αρχείο
με αυτό;
{0} bytes
Αυτόματη &μετονομασία
3700
Μη υποστηριζόμενη μέθοδος συμπίεσης για το '{0}'.
Λάθος δεδομένων στο {0}. Το αρχείο είναι φθαρμένο.
Ο έλεγχος CRC απέτυχε στο '{0}'. Το αρχείο είναι φθαρμένο.
Λάθος δεδομένων στο κρυπτογραφημένο αρχείο '{0}'. Λάθος κωδικός;
Ο έλεγχος CRC απέτυχε στο κρυπτογραφημένο αρχείο '{0}'. Λάθος κωδικός;
3710
Λάθος κωδικός;
3721
Μη υποστηριζόμενη μέθοδος συμπίεσης
Λάθος δεδομένων
Ο έλεγχος CRC απέτυχε
Μη διαθέσιμα δεδομένα
Απρόβλεπτο τελείωμα δεδομένων
Υπάρχουν μερικα δεδομένα στο τέλος των χρήσιμων δεδομένων
Δεν είναι συμπιεσμένο αρχείο
Λάθος επικεφαλίδων
Λάθος κωδικός
3763
Μη διαθέσιμη αρχή του συμπιεσμένου αρχείου
Ανεπιβεβαίωτη αρχή του συμπιεσμένου αρχείου
Μη υποστηριζόμενη λειτουργία
3800
Εισαγωγή κωδικού πρόσβασης
Κωδικός πρόσβασης:
Επανεισάγετε τον κωδικό πρόσβασης:
&Εμφάνιση κωδικού
Οι κωδικοί δεν ταιριάζουν.
Χρησιμοποιήστε μόνο Αγγλικά γράμματα, αριθμούς και ειδικούς χαρακτήρες (!, #, ...) για κωδικό.
Ο κωδικός είναι πολύ μεγάλος.
Κωδικός πρόσβασης
3900
Διανύθηκε:
Απομένει:
Μέγεθος:
Ταχύτητα:
Επεξεργάσθηκαν:
Αναλογία συμπίεσης
Σφάλματα:
Αρχεία συμπίεσης:
4000
Προσθήκη σε συμπιεσμένο αρχείο
&Όνομα αρχείου συμπίεσης:
&Τρόπος ενημέρωσης:
Συμπίεση στη μορ&φή:
Επίπεδο συμπίεσης:
&Μέθοδος συμπίεσης:
Μέγεθος &λεξικού:
Μέγεθος &λέξης:
Μέγεθος συμπαγούς μπλοκ:
Αριθμός νημάτων CPU
&Παράμετροι:
Επιλογές συμπίεσης
Με αυτόματη αποσυμπίεση (SF&X)
Συμπίεση κοινών αρχείων
Κρυπτογράφηση
Μέθοδος κρυπτογράφησης
Κρυπτογράφηση των &ονομάτων
Χρήση μνήμης για συμπίεση:
Χρήση μνήμης για αποσυμπίεση:
Διαγραφή αρχείων μετά τη συμπίεση
4040
Αποθήκευση συμβολικών συνδέσμων
Αποθήκευση σταθερών συνδέσμων
Αποθήκευση ενναλλακτικών ροών δεδομένων
Αποθήκευση ασφάλειας αρχείου
4050
Αποθήκευση
Πολύ γρήγορη
Γρήγορη
Κανονική
Μέγιστη
Υπερσυμπίεση
4060
Προσθήκη και αντικατάσταση αρχείων
Προσθήκη και ενημέρωση αρχείων
Ενημέρωση των υπαρχόντων αρχείων
Συγχρονισμός αρχείων
4070
Αναζήτηση
Όλα τα αρχεία
Μη-συμπαγές
Συμπαγές
6000
Αντιγραφή
Μετακίνηση
Αντιγραφή στο:
Μετακίνηση στο:
Αντιγραφή...
Μετακίνηση...
Μετονομασία...
Επιλέξτε φάκελο προορισμού.
Η λειτουργία δεν υποστηρίζεται.
Παρουσιάστηκε σφάλμα κατά τη μετονομασία.
Επιβεβαίωση αντιγραφής αρχείων
Είστε βέβαιος ότι θέλετε να αντιγράψετε τα αρχεία στο αρχείο συμπίεσης;
6100
Επιβεβαίωση διαγραφής του αρχείου
Επιβεβαίωση διαγραφής του φακέλου
Επιβεβαίωση διαγραφής πολλών αρχείων
Είστε βέβαιοι ότι θέλετε να διαγράψετε το '{0}' ;
Είστε βέβαιοι ότι θέλετε να διαγράψετε το φάκελο '{0}' και όλα τα περιεχόμενα του;
Είστε βέβαιοι ότι θέλετε να διαγράψετε αυτά τα {0} στοιχεία;
Διαγραφή...
Παρουσιάστηκε σφάλμα κατά τη διαγραφή.
Το σύστημα δεν μπορεί να μετακινήσει ένα αρχείο με μεγάλη διαδρομή στον Κάδο Ανακύκλωσης.
6300
Δημιουργία φακέλου
Δημιουργία αρχείου
Όνομα φακέλου:
Όνομα αρχείου:
Νέος φάκελος
Νέο αρχείο
Σφάλμα κατά την δημιουργία φακέλου.
Σφάλμα κατά την δημιουργία αρχείου.
6400
Σχόλιο
&Σχόλιο:
Επιλογή
Αποεπιλογή
Με όνομα:
6600
Ιδιότητες
Ιστορικό φακέλων
Διαγνωστικά μηνύματα
Μήνυμα
7100
Υπολογιστής
Δικτύο
Έγγραφα
Σύστημα
7200
Προσθήκη
Αποσυμπίεση
Έλεγχος
Αντιγραφή
Μετακίνηση
Διαγραφή
Πληροφορίες
7300
Τεμαχισμός αρχείου
&Τεμαχισμός σε:
Τεμαχισμός σε τόμους:
Τεμαχισμός...
Επιβεβαίωση τεμαχισμού
Είστε βέβαιος ότι θέλετε να τεμαχίσετε το αρχείο σε {0} τόμους;
Το μέγεθος του τόμου πρέπει να είναι μικρότερο από αυτό του αρχικού αρχείου.
Λάθος μέγεθος τόμου
Καθορισμένο μέγεθος τόμου: {0} bytes.\nΕίστε σίγουρος ότι θέλετε να χωρίσετε το αρχείο σε τέτοιους τόμους;
7400
Συνένωση αρχείων
&Συνένωση σε:
Συνένωση...
Επιλέξτε μόνο το πρώτο αρχείο
Το αρχείο δεν μπορεί να ανιχνευθεί ως μέρος τεμαχισμένου αρχείου.
Δεν μπορούν να βρεθούν πάνω από ένα μέρη τεμαχισμένου αρχείου.
7500
Υπολογισμός αθροίσματος ελέγχου...
Πληροφορίες αθροίσματος ελέγχου
Άθροισμα ελέγχου CRC για δεδομένα:
Άθροισμα ελέγχου CRC για δεδομένα και ονόματα:
7600
Αξιολόγηση επιδόσεων
Χρήση μνήμης:
Συμπίεση
Αποσυμπίεση
Εκτίμηση
Συνολ. εκτίμηση
Τρέχων πέρασμα
Αποτέλεσμα
Χρήση CPU
Ταξ/μιση/Χρήση
Περάσματα:
7700
Σύνδεσμος
Σύνδεσμος
Σύνδεσμος από:
Σύνδεσμος έως:
7710
Τύπος συνδέσμου
Σταθερός σύνδεσμος
Συμβολικός σύνδεσμος αρχείου
Συμβολικός σύνδεσμος καταλόγου
Συνένωση καταλόγου

495
Utils/7-Zip/Lang/en.ttt Normal file
View File

@ -0,0 +1,495 @@
;!@Lang2@!UTF-8!
; 15.00 : 2015-03-29 : Igor Pavlov
;
;
;
;
;
;
;
;
;
;
0
7-Zip
English
English
401
OK
Cancel
&Yes
&No
&Close
Help
&Continue
440
Yes to &All
No to A&ll
Stop
Restart
&Background
&Foreground
&Pause
Paused
Are you sure you want to cancel?
500
&File
&Edit
&View
F&avorites
&Tools
&Help
540
&Open
Open &Inside
Open O&utside
&View
&Edit
Rena&me
&Copy To...
&Move To...
&Delete
&Split file...
Com&bine files...
P&roperties
Comme&nt...
Calculate checksum
Diff
Create Folder
Create File
E&xit
Link
&Alternate Streams
600
Select &All
Deselect All
&Invert Selection
Select...
Deselect...
Select by Type
Deselect by Type
700
Lar&ge Icons
S&mall Icons
&List
&Details
730
Unsorted
Flat View
&2 Panels
&Toolbars
Open Root Folder
Up One Level
Folders History...
&Refresh
Auto Refresh
750
Archive Toolbar
Standard Toolbar
Large Buttons
Show Buttons Text
800
&Add folder to Favorites as
Bookmark
900
&Options...
&Benchmark
960
&Contents...
&About 7-Zip...
1003
Path
Name
Extension
Folder
Size
Packed Size
Attributes
Created
Accessed
Modified
Solid
Commented
Encrypted
Split Before
Split After
Dictionary
Type
Anti
Method
Host OS
File System
User
Group
Block
Comment
Position
Path Prefix
Folders
Files
Version
Volume
Multivolume
Offset
Links
Blocks
Volumes
64-bit
Big-endian
CPU
Physical Size
Headers Size
Checksum
Characteristics
Virtual Address
ID
Short Name
Creator Application
Sector Size
Mode
Symbolic Link
Error
Total Size
Free Space
Cluster Size
Label
Local Name
Provider
NT Security
Alternate Stream
Aux
Deleted
Is Tree
Error Type
Errors
Errors
Warnings
Warning
Streams
Alternate Streams
Alternate Streams Size
Virtual Size
Unpack Size
Total Physical Size
Volume Index
SubType
Short Comment
Code Page
Tail Size
Embedded Stub Size
Link
Hard Link
iNode
Read-only
2100
Options
Language
Language:
Editor
&Editor:
&Diff:
2200
System
Associate 7-Zip with:
All users
2301
Integrate 7-Zip to shell context menu
Cascaded context menu
Context menu items:
Icons in context menu
2320
<Folder>
<Archive>
Open archive
Extract files...
Add to archive...
Test archive
Extract Here
Extract to {0}
Add to {0}
Compress and email...
Compress to {0} and email
2400
Folders
&Working folder
&System temp folder
&Current
&Specified:
Use for removable drives only
Specify a location for temporary archive files.
2500
Settings
Show ".." item
Show real file icons
Show system menu
&Full row select
Show &grid lines
Single-click to open an item
&Alternative selection mode
Use &large memory pages
2900
About 7-Zip
7-Zip is free software
3000
The system cannot allocate the required amount of memory
There are no errors
{0} object(s) selected
Cannot create folder '{0}'
Update operations are not supported for this archive.
Can not open file '{0}' as archive
Can not open encrypted archive '{0}'. Wrong password?
Unsupported archive type
File {0} is already exist
File '{0}' was modified.\nDo you want to update it in the archive?
Can not update file\n'{0}'
Cannot start editor.
The file looks like a virus (the file name contains long spaces in name).
The operation cannot be called from a folder that has a long path.
You must select one file
You must select one or more files
Too many items
Can not open the file as {0} archive
The file is open as {0} archive
The archive is open with offset
3300
Extracting
Compressing
Testing
Opening...
Scanning...
Removing
3320
Adding
Updating
Analyzing
Replicating
Repacking
Skipping
Deleting
Header creating
3400
Extract
E&xtract to:
Specify a location for extracted files.
3410
Path mode:
Full pathnames
No pathnames
Absolute pathnames
Relative pathnames
3420
Overwrite mode:
Ask before overwrite
Overwrite without prompt
Skip existing files
Auto rename
Auto rename existing files
3430
Eliminate duplication of root folder
Restore file security
3500
Confirm File Replace
Destination folder already contains processed file.
Would you like to replace the existing file
with this one?
{0} bytes
A&uto Rename
3700
Unsupported compression method for '{0}'.
Data error in '{0}'. File is broken.
CRC failed in '{0}'. File is broken.
Data error in encrypted file '{0}'. Wrong password?
CRC failed in encrypted file '{0}'. Wrong password?
3710
Wrong password?
3721
Unsupported compression method
Data error
CRC failed
Unavailable data
Unexpected end of data
There are some data after the end of the payload data
Is not archive
Headers Error
Wrong password
3763
Unavailable start of archive
Unconfirmed start of archive
Unsupported feature
3800
Enter password
Enter password:
Reenter password:
&Show password
Passwords do not match
Use only English letters, numbers and special characters (!, #, $, ...) for password
Password is too long
Password
3900
Elapsed time:
Remaining time:
Total size:
Speed:
Processed:
Compression ratio:
Errors:
Archives:
4000
Add to archive
&Archive:
&Update mode:
Archive &format:
Compression &level:
Compression &method:
&Dictionary size:
&Word size:
Solid block size:
Number of CPU threads:
&Parameters:
Options
Create SF&X archive
Compress shared files
Encryption
Encryption method:
Encrypt file &names
Memory usage for Compressing:
Memory usage for Decompressing:
Delete files after compression
4040
Store symbolic links
Store hard links
Store alternate data streams
Store file security
4050
Store
Fastest
Fast
Normal
Maximum
Ultra
4060
Add and replace files
Update and add files
Freshen existing files
Synchronize files
4070
Browse
All Files
Non-solid
Solid
6000
Copy
Move
Copy to:
Move to:
Copying...
Moving...
Renaming...
Select destination folder.
The operation is not supported for this folder.
Error Renaming File or Folder
Confirm File Copy
Are you sure you want to copy files to archive
6100
Confirm File Delete
Confirm Folder Delete
Confirm Multiple File Delete
Are you sure you want to delete '{0}'?
Are you sure you want to delete the folder '{0}' and all its contents?
Are you sure you want to delete these {0} items?
Deleting...
Error Deleting File or Folder
The system cannot move a file with long path to the Recycle Bin
6300
Create Folder
Create File
Folder name:
File Name:
New Folder
New File
Error Creating Folder
Error Creating File
6400
Comment
&Comment:
Select
Deselect
Mask:
6600
Properties
Folders History
Diagnostic messages
Message
7100
Computer
Network
Documents
System
7200
Add
Extract
Test
Copy
Move
Delete
Info
7300
Split File
&Split to:
Split to &volumes, bytes:
Splitting...
Confirm Splitting
Are you sure you want to split file into {0} volumes?
Volume size must be smaller than size of original file
Incorrect volume size
Specified volume size: {0} bytes.\nAre you sure you want to split archive into such volumes?
7400
Combine Files
&Combine to:
Combining...
Select only first part of split file
Can not detect file as part of split file
Can not find more than one part of split file
7500
Checksum calculating...
Checksum information
CRC checksum for data:
CRC checksum for data and names:
7600
Benchmark
Memory usage:
Compressing
Decompressing
Rating
Total Rating
Current
Resulting
CPU Usage
Rating / Usage
Passes:
7700
Link
Link
Link from:
Link to:
7710
Link Type
Hard Link
File Symbolic Link
Directory Symbolic Link
Directory Junction

404
Utils/7-Zip/Lang/eo.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 4.37 : Dmitri Gabinski
;
;
;
;
;
;
;
;
;
;
0
7-Zip
Esperanto
Esperanto
401
B&one
Nuligu
&Jes
&Ne
&Fermu
Helpo
&Daŭrigu
440
Jes por ĉ&iuj
Ne por ĉi&uj
&Haltu
Restartigu
&Fono
&Malfono
&Paŭzo
Paŭzita
Ĉu vi vere volas nuligi?
500
&Dosiero
&Redakto
&Vido
&Favoritaj
&Agordoj
&Helpo
540
&Malfermu
Malfermu &ene
Malfermu ek&stere
&Vidigu
&Redaktu
Ŝ&anĝu nomon
&Kopiu en...
M&ovu en...
&Forigu
&Erigu dosierojn...
Komb&inu dosierojn...
A&tributoj
Ko&mentu
Kalkulu kontrolsumon
Kreu &dosierujon
Kre&u dos&ieron
E&liru
600
M&arku ĉiun
Ma&lmarku ĉiun
&Inversigu markon
Marku...
Malmarku...
Marku laŭ tipo
Malmarku laŭ tipo
700
&Grandaj bildetoj
&Malgrandaj bildetoj
&Listo
&Detale
730
&Neordigite
Ununivela vido
&2 paneloj
&Ilobretoj
Malfermu radikan dosierujon
Supren je unu nivelo
Dosierujhistorio...
Ĝ&isdatigu
750
Arĥivo-ilobreto
Norma ilobreto
Grandaj bildetoj
Montru butontekston
800
&Aldonu dosierujon al favorataj kiel
Legosigno
900
&Agordoj...
&Etalono
960
&Enhavo...
&Pri 7-Zip...
1003
Dosierindiko
Nomo
Dosiernoma sufikso
Dosierujo
Grando
Enarĥiva grando
Atributoj
Kreita
Malfermita
Ŝanĝita
Solida
Komento
Ĉifra
Disigita antaŭ
Disigita post
Vortaro
CRC
Tipo
Kontraŭ
Metodo
Gastiga operaciumo
Dosiersistemo
Uzulo
Grupo
Bloko
Komento
Pozicio
Vojprefikso
Eraro
Kapacito
Libera
Faskogrando
Marko
Loka nomo
Provizanto
2100
Agordoj
Lingvo
Lingvo:
Redaktilo
&Redaktilo:
2200
Sistemo
Asociu 7-Zip-on kun dosieroj:
2301
Metu 7-Zip'on en kuntekstan menuon de ŝelo
Kaskada kunteksta menuo
Punktoj de kunteksta menuo:
2320
<Dosierujo>
<Arĥivo>
Malfermu
Elarĥivigu dosierojn...
Enarĥivigu...
Testu arĥivon
Elarĥivigu ĉi-tien
Elarĥivigu en {0}
Aldonu al {0}
Enarĥivigu kaj enretpoŝtigu...
Enarĥivigu en {0} kaj enretpoŝtigu...
2400
Dosierujoj
&Kuranta dosierujo
&Sistema labora dosierujo
&Ĉi tiu
&Specifu:
&Uzi nur por demeteblaj datumportiloj
Specifu ujon por laboraj dosieroj.
2500
Agordoj
Montru ".."-elementon
Montru realajn dosierbildetojn
Montru sisteman menuon
Marku &tutan linion
Montru &kradliniojn
&Alternativa markreĝimo
Uzu &grandajn memorpaĝojn
2900
Informo
7-Zip estas senpaga programo. Tamen, vi povas subteni evoluadon de 7-Zip per enregistriĝo.
3000
Eraroj ne trovitaj
{0} objekto(j) markita(j)
Fiaskis krei dosierujon '{0}'
Ĝisdatigoperacioj ne estas subtenataj por ĉi-tiu arĥivo.
Dosiero '{0}' ŝanĝiĝis.\nĈu vi volas ĝistadigi ĝin enraĥive?
Fiaskis ĝisdatigi dosieron\n'{0}''
Fiaskis startigi redaktilon.
Troaj elementoj
3300
Elarĥivigo
Densigo
Testado
Malfermo...
Analizante...
3400
&Elarĥivigu
E&larĥivigu en:
Specifu ujon por elarĥivendaj dosieroj.
3410
Dosierindikoj
&Absolutaj dosierindikoj
&Sen dosierindikoj
3420
Anstataŭiga skribreĝimo
&Kun konfirmo
&Sen konfirmo
&Preterlasu estantaj dosieroj
Aŭtonomŝanĝo
Aŭtonomŝanĝo de ekzistantaj dosieroj
3500
Konfirmo de nomŝanĝo
Dosierujo jam enhavas prilaboratan dosieron.
Anstataŭigu estantan dosieron
per ĉi-tiu?
{0} bajtoj
&Aŭtonomŝanĝo.
3700
Ne estas subtenata densigmetodo por dosiero '{0}'.
Datumeraro en '{0}'. Difektiĝinta dosiero.
CRC-eraro en '{0}'. Difektiĝinta dosiero.
3800
Pasvorto
Enigu pasvorton:
&Montru pasvorton
&Pasvorto
3900
Pasinta tempo:
Restanta tempo:
Grando:
Rapideco:
Eraroj:
4000
Enarĥivigu
&Arĥivo:
A&nstataŭigreĝimo:
A&rĥivformato:
Densigo&nivelo
&Densigmetodo:
&Vortarogrando:
Vo&rtogrando:
&Parametroj:
Agordoj
Kreu SF&X-arĥivon
Ĉifru dosier&nomojn
Memoruzo por densigo:
Memoruzo por maldensigo:
4050
Sen densigo
Plej rapide
Rapide
Normala densigo
Maksimuma densigo
Ultra
4060
Aldonu kaj anstataŭigu dosierojn
Ĝisdatigu kaj aldonu dosierojn
Refreŝigu estantajn dosierojn
Sinkronigu dosierojn
4070
Foliumu
Ĉiuj dosieroj
6000
Kopiu
Movu
Kopiu en:
Movu en:
Kopio...
Movo...
Nomŝanĝo...
Operacio ne estas subtenata.
Eraro dum nomŝanĝo de dosiero aŭ dosierujo
Konfirmu dosierkopion
Ĉu vere kopii dosierojn enarĥiven
6100
Konfirmo de forigo de dosiero
Konfirmo de forigo de dosierujo
Konfirmo de forigo de dosieraro
Ĉu vi vere volas forigi '{0}'?
Ĉu vi vere volas forigi dosierujon "{0}" kaj tutan ĝian enhavon?
Ĉu vi vere volas forigi ĉi tiajn {0} objektojn?
Forigo...
Eraro dum forigo de dosiero aŭ dosierujo
6300
Kreu dosierujon
Kreu dosieron
Dosierujnomo:
Dosiernomo:
Nova dosierujo
Nova dosiero
Eraro dum dosierujkreo
Eraro dum dosierkreo
6400
Komento
&Komento:
Marku
Malmarku
Masko:
6600
Dosierujhistorio
Diagnozaj mesaĝoj
Mesaĝo
7100
Komputilo
Reto
Sistemo
7200
Enarĥivigu
Elarĥivigu
Testu
Kopiu
Movu
Forigu
Informo
7300
Erigu dosieron
&Erigu en:
&Plurvolumigu, bajtoj:
Erigo...
7400
Kombinu dosierojn
&Kombinu en:
Kombino...
7500
Kalkulante kontrolsumon...
Informo pri kontrolsumo
CRC-kontrolsumo por datumoj:
CRC-kontrolsumo por datumoj kaj nomoj:
7600
Etalono
Memoruzo:
Densigo
Maldensigo
Takso
Tuta takso
Kuranta
Rezulta
Pasoj:

404
Utils/7-Zip/Lang/es.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; : Pablo Rodriguez
; : Jbc25
; : 2007-09-05 : Guillermo Gabrielli
; 9.07 : 2010-06-10 : Purgossu
; 2010-10-23 : Sergi Medina (corrected)
;
;
;
;
;
;
0
7-Zip
Spanish
Español
401
Aceptar
Cancelar
&Sí
&No
&Cerrar
Ayuda
&Continuar
440
Sí a &todo
No a t&odo
Parar
Volver a empezar
Se&gundo plano
P&rimer plano
&Pausa
Pausado
¿Estás seguro de que deseas cancelar?
500
&Archivo
&Editar
&Ver
&Favoritos
&Herramientas
Ay&uda
540
&Abrir
Abrir &dentro
Abrir &fuera
&Ver
&Editar
Re&nombrar
&Copiar a...
&Mover a...
&Borrar
Di&vidir archivo...
C&ombinar archivos...
&Propiedades
Comen&tario
Suma de verificación
Diff
Crear carpeta
Crear archivo
&Salir
600
Seleccionar &todo
Deseleccionar todo
&Invertir selección
Seleccionar...
Deseleccionar...
Seleccionar por tipo
Deseleccionar por tipo
700
Iconos g&randes
&Iconos pequeños
&Lista
&Detalles
730
Desordenado
Vista plana (flat view)
&2 paneles
&Barras de herramientas
Abrir directorio raíz
Subir un directorio
Historia de carpetas...
&Actualizar
750
Barra de herramientas Archivo
Barras de herramientas estándar
Botones grandes
Mostrar texto en los botones
800
&Añadir carpeta a favoritos como
Agregar a favoritos
900
&Opciones...
&Pruebas (benchmark)
960
&Contenido...
&Acerca de 7-Zip...
1003
Ruta
Nombre
Tipo de archivo
Directorio
Tamaño
Tamaño comprimido
Atributos
Creado
Acceso
Modificado
Compacto
Comentado
Encriptado
expandido antes
expandido después
Diccionario
CRC
Tipo
Anti
Método
SO de origen
Sistema de archivos
Usuario
Grupo
Bloque
Comentario
Posición
Ruta
Directorios
Ficheros
Versión
Volumen
Multivolumen
Desplazamiento
Vínculos
Bloques
Volúmenes
64-bit
Big-endian
CPU
Tamaño físico
Tamaño de las cabeceras
Verificación de suma
Características
Dirección virtual
ID
Nombre corto
Aplicación de creación
Tamaño de sector
Modo
Enlace
Error
Espacio total
Espacio libre
Tamaño de clúster
Etiqueta
Nombre local
Proveedor
2100
Opciones
Lengua
Lengua:
Editor
&Editor:
&Diff:
2200
Sistema
Asociar 7-Zip con:
2301
Integrar 7-Zip en el menú contextual de Windows
Menú contextual en cascada
Elementos en el menú contextual:
2320
<Carpeta>
<Archivo>
Abrir comprimido
Extraer ficheros...
Añadir al archivo...
Comprobar archivo
Extraer aquí
Extraer en {0}
Añadir a {0}
Comprimir y enviar por correo...
Comprimir a {0} y enviar por correo
2400
Directorios
Directorio de &trabajo
Directorio temporal del &sistema
Directorio &actual
&Especificar directorio:
Usar solo para dispositivos extraíbles
Especificar un directorio para archivos temporales.
2500
Propiedades
Mostrar el elemento ".."
Mostrar iconos propios
Mostrar menú del sistema
&Seleccionar fila(s) entera(s)
Mostrar &cuadrícula
Clicar una vez para abrir elemento
Modo de selección &alternativo
Usar páginas &grandes de memoria
2900
Acerca de 7-Zip
7-Zip es un programa excelente; además, es libre y gratuito. Tú puedes apoyar el desarrollo de 7-Zip registrándote para contribuir a mejorar el programa.
3000
El sistema no ha podido asignar la cantidad necesaria de memoria
No hay errores
{0} elemento(s) seleccionado(s)
No se puede crear el directorio '{0}'
Este tipo de archivo no permite actualización.
No se puede abrir '{0}' como un archivo comprimido
No se puede abrir el archivo encriptado '{0}'. Verifique la contraseña.
Tipo de archivo no soportado
El fichero {0} ya existe
El fichero '{0}' ha sido modificado.\n¿Quieres actualizarlo en el archivo?
No puede actualizarse el fichero\n'{0}'
No puede ejecutarse el editor.
El fichero parece un virus (el nombre del fichero contiene espacios largos).
No puede realizarse la operación desde una carpeta que tenga una ruta larga.
Debes seleccionar un fichero
Debes seleccionar uno o más ficheros
Demasiados elementos
3300
extrayendo
comprimiendo
probando
abriendo...
Buscando...
3400
Extraer
E&xtraer a:
Selecciona destino para los archivos extraídos.
3410
Modo de directorio
Directorio completo
Sin directorio
3420
Sobreescribir
Con confirmación
Sin confirmación
Conservar archivos existentes
Renombrar automáticamente
Autorrenombrar archivos existentes
3500
Confirmar sustitución de archivos
El directorio ya contiene un archivo con el mismo nombre.
¿Deseas sustituir el archivo existente
por este otro?
{0} bytes
Renombrar a&utomáticamente
3700
Método de compresión no válido para '{0}'.
Error de datos en '{0}'. El archivo está corrupto.
CRC ha fallado en '{0}'. El archivo está corrupto.
Error de datos en el archivo encriptado '{0}'. Verifica la contraseña.
Fallo de CRC en el archivo encriptado '{0}'. Verifica la contraseña.
3800
Introduce la contraseña
E&scribe la contraseña:
Escribe nue&vamente la contraseña:
&Mostrar la contraseña
Las contraseñas son diferentes. Por favor, vuelve a escribirlas.
Usa en la contraseña solamente letras del alfabeto inglés, números y caracteres especiales (!, #, $, ...)
La contraseña es demasiado larga.
Contraseña
3900
Tiempo transcurrido:
Tiempo pendiente:
Tamaño:
Velocidad:
Procesado:
Razón de compresión:
Errores:
Archivos:
4000
Añadir al archivo
&Archivo:
M&odo de actualización:
&Formato de archivo:
Nive&l de compresión:
&Tipo de compresión:
Tamaño de &diccionario:
Tama&ño de la palabra:
Tamaño de bloque compacto:
Número de hilos de la CPU:
&Parámetros:
Opciones
Crear archivo SF&X (autoextraíble)
Comprimir archivos abiertos para escritura
Encriptación
Método de &encriptación:
Encriptar &nombres de fichero
Memoria usada para comprimir:
Memoria usada para descomprimir:
4050
Sin compresión
La más rápida
Rápida
Normal
Máxima
Ultra
4060
Añadir y sustituir archivos
Actualizar y añadir archivos
Solo actualizar archivos
Sincronizar archivos
4070
Explorar
Todos los archivos
No compacto
Sin límite
6000
Copiar
Mover
Copiar a:
Mover a:
copiado...
movido...
Renombrando...
Selecciona la carpeta de destino
Operación no permitida.
Error renombrando fichero o carpeta
Confirmar copia de ficheros
¿Estás seguro de que deseas copiar los ficheros al archivo
6100
Confirmar borrado de archivo
Confirmar borrado de carpeta
Confirmar borrado de numerosos ficheros
¿Estás seguro de querer borrar '{0}'?
¿Estás seguro de querer borrar la carpeta '{0}' y todo su contenido?
¿Estás seguro de querer borrar estos {0} elementos?
Borrando...
Error borrando fichero o carpeta
El sistema no puede mover un fichero con ruta larga a la Papelera de Reciclaje
6300
Crear carpeta
Crear archivo
Nombre de carpeta:
Nombre de archivo:
Carpeta nueva
Archivo nuevo
Error creando carpeta
Error creando archivo
6400
Comentario
&Comentario:
Seleccionar
Deseleccionar
Máscara:
6600
Propiedades
Historial de carpetas
Mensajes de diagnóstico
Mensaje
7100
Mi PC
Entorno de red
Documentos
Sistema
7200
Agregar
Extraer
Probar
Copiar
Mover
Borrar
Información
7300
Dividir archivo
Di&vidir a:
Dividir en fra&gmentos (bytes):
Dividiendo...
Confirmar división
¿Estás seguro de que deseas dividir el archivo en {0} partes?
El tamaño de los fragmentos debe ser menor que el del archivo original
Tamaño de fragmento incorrecto
Tamaño de fragmento especificado: {0} bytes.\n¿Estás seguro de que deseas dividir el archivo en fragmentos de ese tamaño?
7400
Combinar archivos
&Combinar a:
Combinando...
Selecciona solamente el primer archivo
No se ha podido detectar el fichero como parte de un fichero por volúmenes
No se ha podido encontrar más que un fragmento del fichero por volúmenes
7500
Calculando suma de verificación...
Suma de verificación (CRC)
CRC de los datos:
CRC de los datos y nombres:
7600
Pruebas (benchmark)
Uso de memoria:
Compresión
Descompresión
Tasa
Tasa total
Actual
Resultante
Uso de CPU
Resultante/uso
Pasos:

404
Utils/7-Zip/Lang/et.txt Normal file
View File

@ -0,0 +1,404 @@
;!@Lang2@!UTF-8!
; 3.09 : Kaupo Suviste
; 9.07 : Mihkel Tõnnov
;
;
;
;
;
;
;
;
;
0
7-Zip
Estonian
eesti keel
401
OK
Loobu
&Jah
&Ei
&Sulge
Abi
&Jätka
440
Kõigile j&ah
Kõigile e&i
Seiska
Restardi
&Taustal
&Esiplaanile
&Paus
Pausiks peatatud
Kas soovite kindlasti loobuda?
500
&Fail
&Redigeeri
&Vaade
&Lemmikud
&Tööriistad
&Abi
540
&Ava
Ava s&ees
Ava väljasp&ool
Vaat&ur
&Redigeeri
&Nimeta ümber
&Kopeeri asukohta...
&Teisalda asukohta...
Ku&stuta
Tükel&da fail...
Ü&henda failid...
Atri&buudid
Ko&mmentaar...
Arvuta kontrollsumma
Võrdle
Loo kaust
Loo fail
&Välju
600
V&ali kõik
Tühista kõik valikud
&Pööra valik
Vali...
Tühista valik...
Vali tüübi järgi
Tühista tüübi järgi valik
700
&Suured ikoonid
Väik&esed ikoonid
&Loend
Üksikasja&d
730
Sortimata
Lame vaade
&Kaks paani
&Tööriistaribad
Ava juurkaust
Taseme võrra üles
Kaustaajalugu...
&Värskenda
750
Arhiiviriistariba
Standardnupuriba
Suured nupud
Kuva nupusildid
800
&Lisa kaust lemmikute hulka järjehoidjana
Järjehoidja
900
&Häälestus...
&Jõudlustest
960
&Sisukord...
&Teave 7-Zipi kohta...
1003
Tee
Nimi
Laiend
Kaust
Maht
Maht tihendatult
Atribuudid
Loodud
Avatud
Muudetud
Ühtne
Kommenteeritud
Krüptitud
Tükeldatud enne
Tükeldatud pärast
Sõnastik
CRC
Tüüp
Anti
Meetod
Opsüsteem
Failisüsteem
Kasutaja
Rühm
Plokk
Kommentaar
Koht
Tee prefiks
Kaustu
Faile
Versioon
Köide
Mitmeköiteline
Nihe
Linke
Plokke
Köiteid
64-bitine
Big-Endian
Protsessor
Füüsiline maht
Päiste maht
Kontrollsumma
Karakteristikud
Virtuaalaadress
ID
Lühinimi
Loomisrakendus
Sektori maht
Režiim
Link
Tõrge
Kogumaht
Vaba ruum
Klastri suurus
Silt
Kohalik nimi
Teenusepakkuja
2100
Häälestus
Keel
Keel:
Redaktor
&Redaktor:
&Võrdlusprogramm:
2200
Süsteem
Seosta 7-Zip laienditega:
2301
Integreeri 7-Zip kesta hüpikmenüüsse
Kaskaad-hüpikmenüü
Hüpikmenüü käsud:
2320
<Kaust>
<Arhiiv>
Ava arhiiv
Eralda failid...
Lisa arhiivi...
Testi arhiivi
Eralda siia
Eralda kausta {0}
Lisa arhiivi {0}
Tihenda ja meili...
Tihenda arhiiviks {0} ja meili
2400
Kaustad
&Töökaust
&Süsteemi ajutiste failide kaust
&Praegune kaust
&Kasutaja määratud:
Kasuta ainult irddraivide puhul
Määrake ajutiste arhiivifailide asukoht.
2500
Sätted
Kuva element ".."
Kuva tegelikud failiikoonid
Kuva süsteemimenüü
&Vali terve rida
Kuva &ruudujooned
Ava üksus ühe klõpsuga
&Alternatiivne valikurežiim
Kasuta &suuri mälulehekülgi
2900
Teave 7-Zipi kohta
7-Zip on vaba tarkvara. Kuid kui soovite toetada 7-Zipi arendamist, siis saate programmi registreerida.\n\n7-Zipi Eesti koduleht:\nhttp://www.hot.ee/somberg/7zip.html
3000
Süsteem ei saa eraldada nõutavat mälumahtu.
Vigu ei leitud.
{0} üksus(t) valitud
Ei saa luua kausta {0}
Selle arhiivi värskendamistoiminguid ei toetata.
Ei saa avada faili {0} arhiivina.
Ei saa avada krüptitud arhiivi {0}. Kas vale parool?
Toetamata arhiivitüüp.
Fail {0} on juba olemas.
Faili {0} on muudetud.\nKas soovite selle arhiivis värskendada?
Ei saa värskendada faili\n{0}
Ei saa käivitada redaktorit.
See fail sarnaneb viirusega (faili nimi sisaldab pikka tühikute jada).
Toimingut ei saa käivitada kaustast, millel on pikk tee.
Te peate valima ühe faili.
Te peate valima ühe või mitu faili.
Liiga palju üksusi.
3300
välja eraldatud
tihendatud
Testimine
Avamine...
Läbivaatamine...
3400
Väljaeraldamine
&Eralda välja kausta:
Määrake väljaeraldatud failide asukoht.
3410
Teed
&Täielikud teenimed
Teenime&deta
3420
Ülekirjutus
Küsi e&nne ülekirjutamist
Ki&rjuta küsimata üle
&Jäta olemasolevad failid vahele
Nimeta a&utomaatselt ümber
Nimeta &olemasolevad f. autom. ümber
3500
Failiasenduse kinnitamine
Sihtkaust juba sisaldab töödeldavat faili.
Kas soovite asendada olemasoleva faili
selle failiga?
{0} baiti
Nimeta a&utomaatselt ümber
3700
Toetuseta tihendusmeetod failile {0}.
Andmeviga failis {0}. Fail on rikutud.
Tsükkelkoodkontroll (CRC) failis {0} nurjus. Fail on rikutud.
Andmeviga krüptitud failis {0}. Kas vale parool?
Tsükkelkoodkontroll (CRC) krüptitud failis {0} nurjus. Kas vale parool?
3800
Parooli sisestamine
Sisestage parool:
Parooli kordus:
&Kuva parool
Paroolid ei kattu.
Kasutage paroolis ainult inglise keele tähti, numbreid ja erimärke (!, #, $, ...).
Parool on liiga pikk.
&Parool
3900
Kulunud aeg:
Järelejäänud aeg:
Kogumaht:
Kiirus:
Töödeldud:
Tihendussuhe:
Vigu:
Arhiive:
4000
Arhiivi lisamine
&Arhiiv:
Värskend&usrežiim:
Arhiivi&vorming:
&Tihendusaste:
Tihendus&meetod:
Sõnaraamatu ma&ht:
&Sõna maht:
Ühtse ploki maht:
Protsessorilõimede arv:
Pa&rameetrid:
Suvandid
Loo is&eavanev arhiiv
Tihenda kirjutuseks avatud failid
Krüptimine
Krüptimismeetod:
Krüpti faili&nimed
Mälu hõivatus tihendamisel:
Mälu hõivatus hõrendamisel:
4050
Tihenduseta
Kiireim tihendus
Kiirtihendus
Normaaltihendus
Maksimaaltihendus
Ultratihendus
4060
Lisa ja asenda failid
Värskenda ja lisa failid
Värskenda olemasolevad failid
Sünkrooni failid
4070
Sirvi
Kõik failid
Mitteühtne
Ühtne
6000
Kopeerimine
Teisaldamine
Kopeeri asukohta:
Teisalda asukohta:
Kopeerimine...
Teisaldamine...
Ümbernimetamine...
Valige sihtkaust.
See toiming pole selles kaustas toetatud.
Tõrge faili või kausta ümbernimetamisel
Failikopeerimise kinnitamine
Kas soovite kindlasti kopeerida arhiivi järgmised failid:
6100
Failikustutuse kinnitamine
Kaustakustutuse kinnitamine
Mitme faili kustutamise kinnitamine
Kas soovite kindlasti kustutada faili {0}?
Kas soovite kindlasti kustutada kausta {0} ja kogu selle sisu?
Kas soovite kindlasti kustutada need {0} üksust?
Kustutamine...
Tõrge faili või kausta kustutamisel
Süsteem ei saa teisaldada prügikasti pika teega faili.
6300
Kausta loomine
Faili loomine
Kausta nimi:
Faili nimi:
Uus kaust
Uus fail
Tõrge kausta loomisel
Tõrge faili loomisel
6400
- kommentaar
&Kommentaar:
Valimine
Valiku tühistamine
Mask:
6600
Atribuudid
Kaustaajalugu
Diagnostikateated
Teade
7100
Arvuti
Võrk
Dokumendid
Süsteem
7200
Lisa
Eralda välja
Testi
Kopeeri
Teisalda
Kustuta
Teave
7300
Faili tükeldamine:
&Tükelda asukohta:
&Tükelda köideteks (baitides):
Tükeldamine...
Tükeldamise kinnitamine
Kas soovite kindlasti tükeldada faili {0} köiteks?
Köite maht peab olema algfaili mahust väiksem.
Sobimatu köitemaht.
Määratud köitemaht: {0} baiti.\nKas soovite kindlasti tükeldada arhiivi niisugusteks köideteks?
7400
Failide ühendamine:
Ü&henda asukohta:
Ühendamine...
Valige ainult tükeldatud faili esimene osa.
Ei õnnestu tuvastada, et see fail oleks tükeldatud faili osa.
Ei leia rohkem kui ühte tükeldatud faili osa.
7500
Kontrollsumma arvutamine...
Kontrollsumma
Andmete CRC-kontrollsumma:
Andmete ja nimede CRC-kontrollsumma:
7600
Jõudlustest
Mälu hõivatus:
Tihendamine
Hõrendamine
Hinnang
Üldine jõudlushinnang
Praegune:
Lõpptulemus:
CPU hõivatus
Hinnang/hõivatus
Töötiire:

Some files were not shown because too many files have changed in this diff Show More