Merge branch 'FF/Ops' into FF/OpsDev

This commit is contained in:
Frank 2023-11-17 18:06:17 +01:00
commit 4ce6cc7776
188 changed files with 4510 additions and 404 deletions

View File

@ -11,7 +11,7 @@ on:
branches: ["master"] branches: ["master"]
paths: paths:
- 'docs/**' - 'docs/**'
- '.github/workflows/pages.yml' - '.github/workflows/gh-pages.yml'
# Allows you to run this workflow manually from the Actions tab # Allows you to run this workflow manually from the Actions tab
workflow_dispatch: workflow_dispatch:
@ -75,4 +75,4 @@ jobs:
- name: Setup Node - name: Setup Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
- run: npm install linkinator - run: npm install linkinator
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --recurse - run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --verbosity error --timeout 5000 --recurse --skip "(java.com)"

2
.gitignore vendored
View File

@ -42,6 +42,8 @@ local.properties
## Ignore Visual Studio temporary files, build results, and ## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons. ## files generated by popular Visual Studio add-ons.
.vscode
# User-specific files # User-specific files
*.suo *.suo
*.user *.user

View File

@ -20,7 +20,7 @@
-- --
-- @module Core.ClientMenu -- @module Core.ClientMenu
-- @image Core_Menu.JPG -- @image Core_Menu.JPG
-- last change: Sept 2023 -- last change: Oct 2023
-- TODO -- TODO
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------
@ -304,6 +304,8 @@ end
-- @field #table menutree -- @field #table menutree
-- @field #number entrycount -- @field #number entrycount
-- @field #boolean debug -- @field #boolean debug
-- @field #table PlayerMenu
-- @field #number Coalition
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- *As a child my family's menu consisted of two choices: take it, or leave it.* --- *As a child my family's menu consisted of two choices: take it, or leave it.*
@ -345,7 +347,7 @@ end
-- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a) -- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a)
-- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a) -- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a)
-- --
-- menumgr:Propagate() -- menumgr:Propagate() -- propagate **once** to all clients in the SET_CLIENT
-- --
-- ## Remove a single entry's subtree -- ## Remove a single entry's subtree
-- --
@ -386,11 +388,15 @@ end
-- --
-- menumgr:ResetMenuComplete() -- menumgr:ResetMenuComplete()
-- --
-- ## Set to auto-propagate for CLIENTs joining the SET_CLIENT **after** the script is loaded - handy if you have a single menu tree.
--
-- menumgr:InitAutoPropagation()
--
-- @field #CLIENTMENUMANAGER -- @field #CLIENTMENUMANAGER
CLIENTMENUMANAGER = { CLIENTMENUMANAGER = {
ClassName = "CLIENTMENUMANAGER", ClassName = "CLIENTMENUMANAGER",
lid = "", lid = "",
version = "0.1.1", version = "0.1.3",
name = nil, name = nil,
clientset = nil, clientset = nil,
menutree = {}, menutree = {},
@ -399,26 +405,108 @@ CLIENTMENUMANAGER = {
entrycount = 0, entrycount = 0,
rootentries = {}, rootentries = {},
debug = true, debug = true,
PlayerMenu = {},
Coalition = nil,
} }
--- Create a new ClientManager instance. --- Create a new ClientManager instance.
-- @param #CLIENTMENUMANAGER self -- @param #CLIENTMENUMANAGER self
-- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage. -- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage.
-- @param #string Alias The name of this manager. -- @param #string Alias The name of this manager.
-- @param #number Coalition (Optional) Coalition of this Manager, defaults to coalition.side.BLUE
-- @return #CLIENTMENUMANAGER self -- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:New(ClientSet, Alias) function CLIENTMENUMANAGER:New(ClientSet, Alias, Coalition)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER
self.clientset = ClientSet self.clientset = ClientSet
self.PlayerMenu = {}
self.name = Alias or "Nightshift" self.name = Alias or "Nightshift"
self.Coalition = Coalition or coalition.side.BLUE
-- Log id. -- Log id.
self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name) self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name)
if self.debug then if self.debug then
self:T(self.lid.."Created") self:I(self.lid.."Created")
end end
return self return self
end end
--- [Internal] Event handling
-- @param #CLIENTMENUMANAGER self
-- @param Core.Event#EVENTDATA EventData
-- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:_EventHandler(EventData)
self:T(self.lid.."_EventHandler: "..EventData.id)
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
local Client = _DATABASE:FindClient( EventData.IniPlayerName )
if Client then
self:ResetMenu(Client)
end
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
if EventData.IniPlayerName and EventData.IniGroup then
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniPlayerName ))) then
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
return self
end
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
local player = _DATABASE:FindClient( EventData.IniPlayerName )
self:Propagate(player)
end
elseif EventData.id == EVENTS.PlayerEnterUnit then
-- special for CA slots
local grp = GROUP:FindByName(EventData.IniGroupName)
if grp:IsGround() then
self:T(string.format("Player %s entered GROUND unit %s!",EventData.IniPlayerName,EventData.IniUnitName))
local IsPlayer = EventData.IniDCSUnit:getPlayerName()
if IsPlayer then
local client=_DATABASE.CLIENTS[EventData.IniDCSUnitName] --Wrapper.Client#CLIENT
-- Add client in case it does not exist already.
if not client then
-- Debug info.
self:I(string.format("Player '%s' joined ground unit '%s' of group '%s'", tostring(EventData.IniPlayerName), tostring(EventData.IniDCSUnitName), tostring(EventData.IniDCSGroupName)))
client=_DATABASE:AddClient(EventData.IniDCSUnitName)
-- Add player.
client:AddPlayer(EventData.IniPlayerName)
-- Add player.
if not _DATABASE.PLAYERS[EventData.IniPlayerName] then
_DATABASE:AddPlayer( EventData.IniUnitName, EventData.IniPlayerName )
end
-- Player settings.
local Settings = SETTINGS:Set( EventData.IniPlayerName )
Settings:SetPlayerMenu(EventData.IniUnit)
end
--local player = _DATABASE:FindClient( EventData.IniPlayerName )
self:Propagate(client)
end
end
end
return self
end
--- Set this Client Manager to auto-propagate menus to newly joined players. Useful if you have **one** menu structure only.
-- @param #CLIENTMENUMANAGER self
-- @return #CLIENTMENUMANAGER self
function CLIENTMENUMANAGER:InitAutoPropagation()
-- Player Events
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.Crash, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
self:SetEventPriority(5)
return self
end
--- Create a new entry in the generic structure. --- Create a new entry in the generic structure.
-- @param #CLIENTMENUMANAGER self -- @param #CLIENTMENUMANAGER self
-- @param #string Text Text of the F10 menu entry. -- @param #string Text Text of the F10 menu entry.
@ -571,7 +659,7 @@ end
-- @return #CLIENTMENU Entry -- @return #CLIENTMENU Entry
function CLIENTMENUMANAGER:Propagate(Client) function CLIENTMENUMANAGER:Propagate(Client)
self:T(self.lid.."Propagate") self:T(self.lid.."Propagate")
self:T(Client) --self:I(UTILS.PrintTableToLog(Client,1))
local Set = self.clientset.Set local Set = self.clientset.Set
if Client then if Client then
Set = {Client} Set = {Client}
@ -792,4 +880,3 @@ end
-- End ClientMenu -- End ClientMenu
-- --
---------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------

View File

@ -126,6 +126,8 @@ function DATABASE:New()
self:SetEventPriority( 1 ) self:SetEventPriority( 1 )
self:HandleEvent( EVENTS.Birth, self._EventOnBirth ) self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
-- DCS 2.9 fixed CA event for players -- TODO: reset unit when leaving
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
@ -810,6 +812,7 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName ) self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
self.PLAYERSJOINED[PlayerName] = PlayerName self.PLAYERSJOINED[PlayerName] = PlayerName
end end
end end
--- Deletes a player from the DATABASE based on the Player Name. --- Deletes a player from the DATABASE based on the Player Name.
@ -1470,39 +1473,43 @@ function DATABASE:_EventOnDeadOrCrash( Event )
end end
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied). --- Handles the OnPlayerEnterUnit event to fill the active players table for CA units (with the unit filter applied).
-- @param #DATABASE self -- @param #DATABASE self
-- @param Core.Event#EVENTDATA Event -- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnPlayerEnterUnit( Event ) function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
if Event.IniDCSUnit then if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 then -- Player entering a CA slot
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
-- Add unit. local IsPlayer = Event.IniDCSUnit:getPlayerName()
self:AddUnit( Event.IniDCSUnitName ) if IsPlayer then
-- Ini unit. -- Debug info.
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName ) self:I(string.format("Player '%s' joined GROUND unit '%s' of group '%s'", tostring(Event.IniPlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
-- Add group. local client= self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
self:AddGroup( Event.IniDCSGroupName )
-- Get player unit. -- Add client in case it does not exist already.
local PlayerName = Event.IniDCSUnit:getPlayerName() if not client then
client=self:AddClient(Event.IniDCSUnitName)
if PlayerName then
if not self.PLAYERS[PlayerName] then
self:AddPlayer( Event.IniDCSUnitName, PlayerName )
end end
local Settings = SETTINGS:Set( PlayerName ) -- Add player.
client:AddPlayer(Event.IniPlayerName)
-- Add player.
if not self.PLAYERS[Event.IniPlayerName] then
self:AddPlayer( Event.IniUnitName, Event.IniPlayerName )
end
-- Player settings.
local Settings = SETTINGS:Set( Event.IniPlayerName )
Settings:SetPlayerMenu(Event.IniUnit) Settings:SetPlayerMenu(Event.IniUnit)
else
self:E("ERROR: getPlayerName() returned nil for event PlayerEnterUnit")
end end
end end
end end
end end
@ -1514,14 +1521,25 @@ end
function DATABASE:_EventOnPlayerLeaveUnit( Event ) function DATABASE:_EventOnPlayerLeaveUnit( Event )
self:F2( { Event } ) self:F2( { Event } )
local function FindPlayerName(UnitName)
local playername = nil
for _name,_unitname in pairs(self.PLAYERS) do
if _unitname == UnitName then
playername = _name
break
end
end
return playername
end
if Event.IniUnit then if Event.IniUnit then
if Event.IniObjectCategory == 1 then if Event.IniObjectCategory == 1 then
-- Try to get the player name. This can be buggy for multicrew aircraft! -- Try to get the player name. This can be buggy for multicrew aircraft!
local PlayerName = Event.IniUnit:GetPlayerName() local PlayerName = Event.IniUnit:GetPlayerName() or FindPlayerName(Event.IniUnitName)
if PlayerName then --and self.PLAYERS[PlayerName] then if PlayerName then
-- Debug info. -- Debug info.
self:I(string.format("Player '%s' left unit %s", tostring(PlayerName), tostring(Event.IniUnitName))) self:I(string.format("Player '%s' left unit %s", tostring(PlayerName), tostring(Event.IniUnitName)))
@ -2005,8 +2023,6 @@ end
TargetPlayerName = Event.IniPlayerName TargetPlayerName = Event.IniPlayerName
TargetCoalition = Event.IniCoalition TargetCoalition = Event.IniCoalition
--TargetCategory = TargetUnit:getCategory()
--TargetCategory = TargetUnit:getDesc().category -- Workaround
TargetCategory = Event.IniCategory TargetCategory = Event.IniCategory
TargetType = Event.IniTypeName TargetType = Event.IniTypeName

View File

@ -173,7 +173,8 @@
-- @image Core_Event.JPG -- @image Core_Event.JPG
--- @type EVENT ---
-- @type EVENT
-- @field #EVENT.Events Events -- @field #EVENT.Events Events
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@ -282,6 +283,7 @@ EVENTS = {
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object. -- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName). -- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot. -- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
-- @field #string IniPlayerUCID (UNIT) The UCID of the initiating player in case the Unit is a client or player slot and on a multi-player server.
-- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator. -- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator.
-- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator. -- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
-- @field #string IniTypeName (UNIT) The type name of the initiator. -- @field #string IniTypeName (UNIT) The type name of the initiator.
@ -297,6 +299,7 @@ EVENTS = {
-- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object. -- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object.
-- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName). -- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName).
-- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot. -- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot.
-- @field #string TgtPlayerUCID (UNIT) The UCID of the target player in case the Unit is a client or player slot and on a multi-player server.
-- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target. -- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target.
-- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target. -- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target.
-- @field #string TgtTypeName (UNIT) The type name of the target. -- @field #string TgtTypeName (UNIT) The type name of the target.
@ -1080,7 +1083,7 @@ function EVENT:onEvent( Event )
if Event.initiator then if Event.initiator then
Event.IniObjectCategory = Object.getCategory(Event.initiator) --Event.initiator:getCategory() Event.IniObjectCategory = Object.getCategory(Event.initiator)
if Event.IniObjectCategory == Object.Category.STATIC then if Event.IniObjectCategory == Object.Category.STATIC then
--- ---
@ -1143,6 +1146,14 @@ function EVENT:onEvent( Event )
end end
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName() Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
if Event.IniPlayerName then
-- get UUCID
local PID = NET.GetPlayerIDByName(nil,Event.IniPlayerName)
if PID then
Event.IniPlayerUCID = net.get_player_info(tonumber(PID), 'ucid')
--env.info("Event.IniPlayerUCID="..tostring(Event.IniPlayerUCID),false)
end
end
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
@ -1197,7 +1208,7 @@ function EVENT:onEvent( Event )
--- ---
-- Target category. -- Target category.
Event.TgtObjectCategory = Object.getCategory(Event.target) --Event.target:getCategory() Event.TgtObjectCategory = Object.getCategory(Event.target)
if Event.TgtObjectCategory == Object.Category.UNIT then if Event.TgtObjectCategory == Object.Category.UNIT then
--- ---
@ -1215,6 +1226,14 @@ function EVENT:onEvent( Event )
Event.TgtGroupName = Event.TgtDCSGroupName Event.TgtGroupName = Event.TgtDCSGroupName
end end
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName() Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
if Event.TgtPlayerName then
-- get UUCID
local PID = NET.GetPlayerIDByName(nil,Event.TgtPlayerName)
if PID then
Event.TgtPlayerUCID = net.get_player_info(tonumber(PID), 'ucid')
--env.info("Event.TgtPlayerUCID="..tostring(Event.TgtPlayerUCID),false)
end
end
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition() Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName() Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
@ -1283,7 +1302,7 @@ function EVENT:onEvent( Event )
-- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground. -- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground.
--Event.Place=UNIT:Find(Event.place) --Event.Place=UNIT:Find(Event.place)
else else
if Event.place:isExist() and Event.place:getCategory() ~= Object.Category.SCENERY then if Event.place:isExist() and Object.getCategory(Event.place) ~= Object.Category.SCENERY then
Event.Place=AIRBASE:Find(Event.place) Event.Place=AIRBASE:Find(Event.place)
Event.PlaceName=Event.Place:GetName() Event.PlaceName=Event.Place:GetName()
end end

View File

@ -465,7 +465,7 @@ _MESSAGESRS = {}
-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google. -- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google.
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies. -- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. -- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations.
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "male". -- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "female".
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB" -- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB"
-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server! -- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server!
-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL. -- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL.
@ -480,24 +480,42 @@ _MESSAGESRS = {}
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate) function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
_MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency,Modulation,Volume) _MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency or 243,Modulation or radio.modulation.AM,Volume)
_MESSAGESRS.MSRS:SetCoalition(Coalition)
_MESSAGESRS.frequency = Frequency
_MESSAGESRS.modulation = Modulation or radio.modulation.AM
_MESSAGESRS.MSRS:SetCoalition(Coalition or coalition.side.NEUTRAL)
_MESSAGESRS.coalition = Coalition or coalition.side.NEUTRAL
_MESSAGESRS.coordinate = Coordinate
_MESSAGESRS.MSRS:SetCoordinate(Coordinate) _MESSAGESRS.MSRS:SetCoordinate(Coordinate)
_MESSAGESRS.MSRS:SetCulture(Culture) _MESSAGESRS.MSRS:SetCulture(Culture)
_MESSAGESRS.Culture = Culture _MESSAGESRS.Culture = Culture or "en-GB"
--_MESSAGESRS.MSRS:SetFrequencies(Frequency)
_MESSAGESRS.MSRS:SetGender(Gender) _MESSAGESRS.MSRS:SetGender(Gender)
_MESSAGESRS.Gender = Gender _MESSAGESRS.Gender = Gender or "female"
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials) _MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
_MESSAGESRS.google = PathToCredentials
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE") _MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
--_MESSAGESRS.MSRS:SetModulations(Modulation) _MESSAGESRS.label = Label or "MESSAGE"
--_MESSAGESRS.MSRS:SetPath(PathToSRS)
_MESSAGESRS.MSRS:SetPort(Port) _MESSAGESRS.MSRS:SetPort(Port or 5002)
-- _MESSAGESRS.MSRS:SetVolume(Volume) _MESSAGESRS.port = Port or 5002
_MESSAGESRS.MSRS:SetVoice(Voice)
_MESSAGESRS.Voice = Voice _MESSAGESRS.volume = Volume or 1
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
--if _MESSAGESRS.google and not Voice then _MESSAGESRS.Voice = MSRS.Voices.Google.Standard.en_GB_Standard_A end
--_MESSAGESRS.MSRS:SetVoice(Voice or _MESSAGESRS.voice)
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE") _MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
env.info(_MESSAGESRS.MSRS.provider,false)
end end
--- Sends a message via SRS. --- Sends a message via SRS.
@ -505,7 +523,7 @@ end
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. -- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. -- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string culture (optional) Culture, e.g. "en-US". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. -- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`.
@ -519,13 +537,16 @@ end
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() -- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
-- --
function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate) function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate)
local tgender = gender or _MESSAGESRS.Gender
if _MESSAGESRS.SRSQ then if _MESSAGESRS.SRSQ then
_MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.Voice) if voice then
_MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.voice)
end
if coordinate then if coordinate then
_MESSAGESRS.MSRS:SetCoordinate(coordinate) _MESSAGESRS.MSRS:SetCoordinate(coordinate)
end end
local category = string.gsub(self.MessageCategory,":","") local category = string.gsub(self.MessageCategory,":","")
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency,modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,voice or _MESSAGESRS.Voice,volume,category,coordinate) _MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
end end
return self return self
end end

View File

@ -561,7 +561,7 @@ do -- COORDINATE
if ZoneObject then if ZoneObject then
-- Get category of scanned object. -- Get category of scanned object.
local ObjectCategory = ZoneObject:getCategory() local ObjectCategory = Object.getCategory(ZoneObject)
-- Check for unit or static objects -- Check for unit or static objects
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() then if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() then

View File

@ -2425,6 +2425,26 @@ do -- SET_UNIT
return CountU return CountU
end end
--- Gets the alive set.
-- @param #SET_UNIT self
-- @return #table Table of SET objects
-- @return #SET_UNIT AliveSet
function SET_UNIT:GetAliveSet()
local AliveSet = SET_UNIT:New()
-- Clean the Set before returning with only the alive Groups.
for GroupName, GroupObject in pairs(self.Set) do
local GroupObject=GroupObject --Wrapper.Client#CLIENT
if GroupObject and GroupObject:IsAlive() then
AliveSet:Add(GroupName, GroupObject)
end
end
return AliveSet.Set or {}, AliveSet
end
--- [Internal] Private function for use of continous zone filter --- [Internal] Private function for use of continous zone filter
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @return #SET_UNIT self -- @return #SET_UNIT self
@ -2820,7 +2840,13 @@ do -- SET_UNIT
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units. -- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
function SET_UNIT:GetCoordinate() function SET_UNIT:GetCoordinate()
local Coordinate = self:GetRandom():GetCoordinate() local Coordinate = nil
local unit = self:GetRandom()
if self:Count() == 1 and unit then
return unit:GetCoordinate()
end
if unit then
local Coordinate = unit:GetCoordinate()
--self:F({Coordinate:GetVec3()}) --self:F({Coordinate:GetVec3()})
@ -2834,7 +2860,7 @@ do -- SET_UNIT
local AvgHeading = nil local AvgHeading = nil
local MovingCount = 0 local MovingCount = 0
for UnitName, UnitData in pairs( self:GetSet() ) do for UnitName, UnitData in pairs( self:GetAliveSet() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT local Unit = UnitData -- Wrapper.Unit#UNIT
local Coordinate = Unit:GetCoordinate() local Coordinate = Unit:GetCoordinate()
@ -2864,6 +2890,7 @@ do -- SET_UNIT
Coordinate:SetVelocity( MaxVelocity ) Coordinate:SetVelocity( MaxVelocity )
self:F( { Coordinate = Coordinate } ) self:F( { Coordinate = Coordinate } )
end
return Coordinate return Coordinate
end end
@ -4317,6 +4344,8 @@ do -- SET_CLIENT
self:UnHandleEvent(EVENTS.Birth) self:UnHandleEvent(EVENTS.Birth)
self:UnHandleEvent(EVENTS.Dead) self:UnHandleEvent(EVENTS.Dead)
self:UnHandleEvent(EVENTS.Crash) self:UnHandleEvent(EVENTS.Crash)
--self:UnHandleEvent(EVENTS.PlayerEnterUnit)
--self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
self.ZoneTimer:Stop() self.ZoneTimer:Stop()
@ -4335,6 +4364,9 @@ do -- SET_CLIENT
self:HandleEvent( EVENTS.Birth, self._EventOnBirth ) self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash ) self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventPlayerEnterUnit)
--self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventPlayerLeaveUnit)
--self:SetEventPriority(1)
if self.Filter.Zones then if self.Filter.Zones then
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self) self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
local timing = self.ZoneTimerInterval or 30 local timing = self.ZoneTimerInterval or 30
@ -4346,6 +4378,43 @@ do -- SET_CLIENT
return self return self
end end
--- Handle CA slots addition
-- @param #SET_CLIENT self
-- @param Core.Event#EVENTDATA Event
-- @return #SET_CLIENT self
function SET_CLIENT:_EventPlayerEnterUnit(Event)
self:I( "_EventPlayerEnterUnit" )
if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
-- CA Slot entered
local ObjectName, Object = self:AddInDatabase( Event )
self:I( ObjectName, UTILS.PrintTableToLog(Object) )
if Object and self:IsIncludeObject( Object ) then
self:Add( ObjectName, Object )
end
end
end
return self
end
--- Handle CA slots removal
-- @param #SET_CLIENT self
-- @param Core.Event#EVENTDATA Event
-- @return #SET_CLIENT self
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
self:I( "_EventPlayerLeaveUnit" )
if Event.IniDCSUnit then
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
-- CA Slot left
local ObjectName, Object = self:FindInDatabase( Event )
if ObjectName then
self:Remove( ObjectName )
end
end
end
return self
end
--- Handles the Database to check on an event (birth) that the Object was added in the Database. --- 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! -- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
-- @param #SET_CLIENT self -- @param #SET_CLIENT self

View File

@ -329,14 +329,14 @@ do
if self.Lasing then if self.Lasing then
if self.Target and self.Target:IsAlive() then if self.Target and 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.SpotIR:setPoint( self.Target:GetPointVec3():AddY(1):AddY(math.random(-100,100)/200):AddX(math.random(-100,100)/200):GetVec3() )
self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() ) self.SpotLaser:setPoint( self.Target:GetPointVec3():AddY(1):GetVec3() )
self:__Lasing(0.2) self:__Lasing(0.2)
elseif self.TargetCoord then elseif self.TargetCoord then
-- Wiggle the IR spot a bit. -- Wiggle the IR spot a bit.
local irvec3={x=self.TargetCoord.x+math.random(-100,100)/100, y=self.TargetCoord.y+math.random(-100,100)/100, z=self.TargetCoord.z} --#DCS.Vec3 local irvec3={x=self.TargetCoord.x+math.random(-100,100)/200, y=self.TargetCoord.y+math.random(-100,100)/200, z=self.TargetCoord.z} --#DCS.Vec3
local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3 local lsvec3={x=self.TargetCoord.x, y=self.TargetCoord.y, z=self.TargetCoord.z} --#DCS.Vec3
self.SpotIR:setPoint(irvec3) self.SpotIR:setPoint(irvec3)

View File

@ -1107,11 +1107,8 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
--if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5 --if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5
if ZoneObject then if ZoneObject then
local ObjectCategory = ZoneObject:getCategory() -- Get object category.
local ObjectCategory = Object.getCategory(ZoneObject)
--local name=ZoneObject:getName()
--env.info(string.format("Zone object %s", tostring(name)))
--self:E(ZoneObject)
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
@ -2815,7 +2812,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
if ZoneObject then if ZoneObject then
local ObjectCategory = ZoneObject:getCategory() local ObjectCategory = Object.getCategory(ZoneObject)
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then

View File

@ -74,7 +74,7 @@
-- @image Designation.JPG -- @image Designation.JPG
-- --
-- Date: 24 Oct 2021 -- Date: 24 Oct 2021
-- Last Update: Aug 2022 -- Last Update: Oct 2023
-- --
--- Class AUTOLASE --- Class AUTOLASE
-- @type AUTOLASE -- @type AUTOLASE
@ -84,6 +84,9 @@
-- @field #string alias -- @field #string alias
-- @field #boolean debug -- @field #boolean debug
-- @field #string version -- @field #string version
-- @field Core.Set#SET_GROUP RecceSet
-- @field #table LaserCodes
-- @field #table playermenus
-- @extends Ops.Intel#INTEL -- @extends Ops.Intel#INTEL
--- ---
@ -109,9 +112,10 @@ AUTOLASE = {
-- @field #string unittype -- @field #string unittype
-- @field Core.Point#COORDINATE coordinate -- @field Core.Point#COORDINATE coordinate
--- AUTOLASE class version. --- AUTOLASE class version.
-- @field #string version -- @field #string version
AUTOLASE.version = "0.1.21" AUTOLASE.version = "0.1.22"
------------------------------------------------------------------- -------------------------------------------------------------------
-- Begin Functional.Autolase.lua -- Begin Functional.Autolase.lua
@ -196,6 +200,8 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.NoMenus = false self.NoMenus = false
self.minthreatlevel = 0 self.minthreatlevel = 0
self.blacklistattributes = {} self.blacklistattributes = {}
self:SetLaserCodes( { 1688, 1130, 4785, 6547, 1465, 4578 } ) -- set self.LaserCodes
self.playermenus = {}
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown") self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
@ -214,7 +220,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
if PilotSet then if PilotSet then
self.usepilotset = true self.usepilotset = true
self.pilotset = PilotSet self.pilotset = PilotSet
self:HandleEvent(EVENTS.PlayerEnterAircraft) self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
--self:SetPilotMenu() --self:SetPilotMenu()
end end
--self.SetPilotMenu() --self.SetPilotMenu()
@ -298,6 +304,16 @@ end
-- Helper Functions -- Helper Functions
------------------------------------------------------------------- -------------------------------------------------------------------
--- [User] Set a table of possible laser codes.
-- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 } .
-- @param #AUTOLASE self
-- @param #list<#number> LaserCodes
-- @return #AUTOLASE
function AUTOLASE:SetLaserCodes( LaserCodes )
self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes }
return self
end
--- (Internal) Function to set pilot menu. --- (Internal) Function to set pilot menu.
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @return #AUTOLASE self -- @return #AUTOLASE self
@ -308,8 +324,31 @@ function AUTOLASE:SetPilotMenu()
local Unit = _unit -- Wrapper.Unit#UNIT local Unit = _unit -- Wrapper.Unit#UNIT
if Unit and Unit:IsAlive() then if Unit and Unit:IsAlive() then
local Group = Unit:GetGroup() local Group = Unit:GetGroup()
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group,Unit) local unitname = Unit:GetName()
lasemenu:Refresh() if self.playermenus[unitname] then self.playermenus[unitname]:Remove() end
local lasetopm = MENU_GROUP:New(Group,"Autolase",nil)
self.playermenus[unitname] = lasetopm
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Status",lasetopm,self.ShowStatus,self,Group,Unit)
local smoke = (self.smoketargets == true) and "off" or "on"
local smoketext = string.format("Switch smoke targets to %s",smoke)
local smokemenu = MENU_GROUP_COMMAND:New(Group,smoketext,lasetopm,self.SetSmokeTargets,self,(not self.smoketargets))
for _,_grp in pairs(self.RecceSet.Set) do
local grp = _grp -- Wrapper.Group#GROUP
local unit = grp:GetUnit(1)
--local name = grp:GetName()
if unit and unit:IsAlive() then
local name = unit:GetName()
local mname = string.gsub(name,".%d+.%d+$","")
local code = self:GetLaserCode(name)
local unittop = MENU_GROUP:New(Group,"Change laser code for "..mname,lasetopm)
for _,_code in pairs(self.LaserCodes) do
local text = tostring(_code)
if _code == code then text = text.."(*)" end
local changemenu = MENU_GROUP_COMMAND:New(Group,text,unittop,self.SetRecceLaserCode,self,name,_code,true)
end
end
end
--lasemenu:Refresh()
end end
end end
else else
@ -324,7 +363,7 @@ end
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
-- @return #AUTOLASE self -- @return #AUTOLASE self
function AUTOLASE:OnEventPlayerEnterAircraft(EventData) function AUTOLASE:_EventHandler(EventData)
self:SetPilotMenu() self:SetPilotMenu()
return self return self
end end
@ -397,7 +436,7 @@ end
--- (User) Function enable sending messages via SRS. --- (User) Function enable sending messages via SRS.
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param #boolean OnOff Switch usage on and off -- @param #boolean OnOff Switch usage on and off
-- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalon -- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalone
-- @param #number Frequency Frequency to send, e.g. 243 -- @param #number Frequency Frequency to send, e.g. 243
-- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM -- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM
-- @param #string Label (Optional) Short label to be used on the SRS Client Overlay -- @param #string Label (Optional) Short label to be used on the SRS Client Overlay
@ -465,10 +504,20 @@ end
-- @param #AUTOLASE self -- @param #AUTOLASE self
-- @param #string RecceName (Unit!) Name of the Recce -- @param #string RecceName (Unit!) Name of the Recce
-- @param #number Code The lase code -- @param #number Code The lase code
-- @param #boolean Refresh If true, refresh menu entries
-- @return #AUTOLASE self -- @return #AUTOLASE self
function AUTOLASE:SetRecceLaserCode(RecceName, Code) function AUTOLASE:SetRecceLaserCode(RecceName, Code, Refresh)
local code = Code or 1688 local code = Code or 1688
self.RecceLaserCode[RecceName] = code self.RecceLaserCode[RecceName] = code
if Refresh then
self:SetPilotMenu()
if self.notifypilots then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
self:NotifyPilots(string.format("Code for %s set to: %d",RecceName,Code),15)
end
end
return self return self
end end
@ -524,6 +573,9 @@ end
function AUTOLASE:SetSmokeTargets(OnOff,Color) function AUTOLASE:SetSmokeTargets(OnOff,Color)
self.smoketargets = OnOff self.smoketargets = OnOff
self.smokecolor = Color or SMOKECOLOR.Red self.smokecolor = Color or SMOKECOLOR.Red
local smktxt = OnOff == true and "on" or "off"
local Message = "Smoking targets is now "..smktxt.."!"
self:NotifyPilots(Message,10)
return self return self
end end
@ -673,7 +725,7 @@ function AUTOLASE:ShowStatus(Group,Unit)
if playername then if playername then
local settings = _DATABASE:GetPlayerSettings(playername) local settings = _DATABASE:GetPlayerSettings(playername)
if settings then if settings then
--self:I("Get Settings ok!") self:I("Get Settings ok!")
if settings:IsA2G_MGRS() then if settings:IsA2G_MGRS() then
locationstring = entry.coordinate:ToStringMGRS(settings) locationstring = entry.coordinate:ToStringMGRS(settings)
elseif settings:IsA2G_LL_DMS() then elseif settings:IsA2G_LL_DMS() then
@ -995,6 +1047,9 @@ end
function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName) function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName)
self:T({From, Event, To, RecceName}) self:T({From, Event, To, RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("Recce %s KIA!",RecceName) local text = string.format("Recce %s KIA!",RecceName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@ -1029,6 +1084,9 @@ end
function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName) function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName)
self:T({From, Event, To, UnitName,RecceName}) self:T({From, Event, To, UnitName,RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("%s lost sight of unit %s.",RecceName,UnitName) local text = string.format("%s lost sight of unit %s.",RecceName,UnitName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@ -1046,6 +1104,9 @@ end
function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName) function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName)
self:T({From, Event, To, UnitName,RecceName}) self:T({From, Event, To, UnitName,RecceName})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
if string.find(RecceName,"#") then
RecceName = string.match(RecceName,"^(.*)#")
end
local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName) local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName)
self:NotifyPilots(text,self.reporttimeshort) self:NotifyPilots(text,self.reporttimeshort)
end end
@ -1063,8 +1124,7 @@ function AUTOLASE:onbeforeLasing(From,Event,To,LaserSpot)
self:T({From, Event, To, LaserSpot.unittype}) self:T({From, Event, To, LaserSpot.unittype})
if self.notifypilots or self.debug then if self.notifypilots or self.debug then
local laserspot = LaserSpot -- #AUTOLASE.LaserSpot local laserspot = LaserSpot -- #AUTOLASE.LaserSpot
local name = laserspot.reccename local name = laserspot.reccename if string.find(name,"#") then
if string.find(name,"#") then
name = string.match(name,"^(.*)#") name = string.match(name,"^(.*)#")
end end
local text = string.format("%s is lasing %s code %d\nat %s",name,laserspot.unittype,laserspot.lasercode,laserspot.location) local text = string.format("%s is lasing %s code %d\nat %s",name,laserspot.unittype,laserspot.lasercode,laserspot.location)

View File

@ -22,7 +22,7 @@
-- @module Functional.Mantis -- @module Functional.Mantis
-- @image Functional.Mantis.jpg -- @image Functional.Mantis.jpg
-- --
-- Last Update: Sept 2023 -- Last Update: Oct 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE --- **MANTIS** class, extends Core.Base#BASE
@ -103,6 +103,7 @@
-- * Roland -- * Roland
-- * Silkworm (though strictly speaking this is a surface to ship missile) -- * Silkworm (though strictly speaking this is a surface to ship missile)
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19 -- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
-- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!)
-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2 -- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
-- --
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M -- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
@ -373,7 +374,9 @@ MANTIS.SamData = {
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"}, ["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"}, ["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, ["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" } ["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" },
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
} }
--- SAM data HDS --- SAM data HDS
@ -488,6 +491,10 @@ do
-- --
function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones) function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding, Zones)
-- Inherit everything from BASE class.
local self = BASE:Inherit(self, FSM:New()) -- #MANTIS
-- DONE: Create some user functions for these -- DONE: Create some user functions for these
-- DONE: Make HQ useful -- DONE: Make HQ useful
-- DONE: Set SAMs to auto if EWR dies -- DONE: Set SAMs to auto if EWR dies
@ -549,6 +556,10 @@ do
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
self.FilterZones = Zones self.FilterZones = Zones
self.SkateZones = nil
self.SkateNumber = 3
self.shootandscoot = false
self.UseEmOnOff = true self.UseEmOnOff = true
if EmOnOff == false then if EmOnOff == false then
self.UseEmOnOff = false self.UseEmOnOff = false
@ -560,9 +571,6 @@ do
self.advAwacs = false self.advAwacs = false
end end
-- Inherit everything from BASE class.
local self = BASE:Inherit(self, FSM:New()) -- #MANTIS
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("MANTIS %s | ", self.name) self.lid=string.format("MANTIS %s | ", self.name)
@ -623,7 +631,7 @@ do
-- TODO Version -- TODO Version
-- @field #string version -- @field #string version
self.version="0.8.14" self.version="0.8.15"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions --- --- FSM Functions ---
@ -787,6 +795,19 @@ do
return self return self
end end
--- Add a SET_ZONE of zones for Shoot&Scoot - SHORAD units will move around
-- @param #MANTIS self
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
-- @param #number Number Number of closest zones to be considered, defaults to 3.
-- @return #MANTIS self
function MANTIS:AddScootZones(ZoneSet, Number)
self:T(self.lid .. " AddScootZones")
self.SkateZones = ZoneSet
self.SkateNumber = Number or 3
self.shootandscoot = true
return self
end
--- Function to set accept and reject zones. --- Function to set accept and reject zones.
-- @param #MANTIS self -- @param #MANTIS self
-- @param #table AcceptZones Table of @{Core.Zone#ZONE} objects -- @param #table AcceptZones Table of @{Core.Zone#ZONE} objects
@ -1786,6 +1807,10 @@ do
self.Shorad:SetDefenseLimits(80,95) self.Shorad:SetDefenseLimits(80,95)
self.ShoradLink = true self.ShoradLink = true
self.Shorad.Groupset=self.ShoradGroupSet self.Shorad.Groupset=self.ShoradGroupSet
self.Shorad.debug = self.debug
end
if self.shootandscoot and self.SkateZones then
self.Shorad:AddScootZones(self.SkateZones,self.SkateNumber or 3)
end end
self:__Status(-math.random(1,10)) self:__Status(-math.random(1,10))
return self return self

View File

@ -105,6 +105,7 @@
-- @field Sound.SRS#MSRSQUEUE controlsrsQ SRS queue for range controller. -- @field Sound.SRS#MSRSQUEUE controlsrsQ SRS queue for range controller.
-- @field Sound.SRS#MSRS instructmsrs SRS wrapper for range instructor. -- @field Sound.SRS#MSRS instructmsrs SRS wrapper for range instructor.
-- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor. -- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor.
-- @field #number Coalition Coalition side for the menu, if any.
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven --- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven
@ -355,6 +356,7 @@ RANGE = {
targetsheet = nil, targetsheet = nil,
targetpath = nil, targetpath = nil,
targetprefix = nil, targetprefix = nil,
Coalition = nil,
} }
--- Default range parameters. --- Default range parameters.
@ -591,7 +593,7 @@ RANGE.MenuF10Root = nil
--- Range script version. --- Range script version.
-- @field #string version -- @field #string version
RANGE.version = "2.7.1" RANGE.version = "2.7.3"
-- TODO list: -- TODO list:
-- TODO: Verbosity level for messages. -- TODO: Verbosity level for messages.
@ -613,8 +615,9 @@ RANGE.version = "2.7.1"
--- RANGE contructor. Creates a new RANGE object. --- RANGE contructor. Creates a new RANGE object.
-- @param #RANGE self -- @param #RANGE self
-- @param #string RangeName Name of the range. Has to be unique. Will we used to create F10 menu items etc. -- @param #string RangeName Name of the range. Has to be unique. Will we used to create F10 menu items etc.
-- @param #number Coalition (optional) Coalition of the range, if any, e.g. coalition.side.BLUE.
-- @return #RANGE RANGE object. -- @return #RANGE RANGE object.
function RANGE:New( RangeName ) function RANGE:New( RangeName, Coalition )
-- Inherit BASE. -- Inherit BASE.
local self = BASE:Inherit( self, FSM:New() ) -- #RANGE local self = BASE:Inherit( self, FSM:New() ) -- #RANGE
@ -623,6 +626,8 @@ function RANGE:New( RangeName )
-- TODO: make sure that the range name is not given twice. This would lead to problems in the F10 radio menu. -- TODO: make sure that the range name is not given twice. This would lead to problems in the F10 radio menu.
self.rangename = RangeName or "Practice Range" self.rangename = RangeName or "Practice Range"
self.Coalition = Coalition
-- Log id. -- Log id.
self.lid = string.format( "RANGE %s | ", self.rangename ) self.lid = string.format( "RANGE %s | ", self.rangename )
@ -1746,8 +1751,14 @@ function RANGE:OnEventBirth( EventData )
-- Reset current strafe status. -- Reset current strafe status.
self.strafeStatus[_uid] = nil self.strafeStatus[_uid] = nil
if self.Coalition then
if EventData.IniCoalition == self.Coalition then
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName )
end
else
-- Add Menu commands after a delay of 0.1 seconds. -- Add Menu commands after a delay of 0.1 seconds.
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName ) self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName )
end
-- By default, some bomb impact points and do not flare each hit on target. -- By default, some bomb impact points and do not flare each hit on target.
self.PlayerSettings[_playername] = {} -- #RANGE.PlayerData self.PlayerSettings[_playername] = {} -- #RANGE.PlayerData

View File

@ -19,7 +19,7 @@
-- --
-- ### Authors: **FlightControl**, **applevangelist** -- ### Authors: **FlightControl**, **applevangelist**
-- --
-- Last Update: September 2023 -- Last Update: Oct 2023
-- --
-- === -- ===
-- --
@ -34,7 +34,7 @@
-- --
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon. -- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
-- Once a HARM attack is detected, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM -- Once a HARM attack is detected, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the -- vehicles around (*if* they are driveable, that is). There's a component of randomness in detection and evasion, which is based on the
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a -- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
-- period of time to stay defensive, before it takes evasive actions. -- period of time to stay defensive, before it takes evasive actions.
-- --
@ -66,7 +66,6 @@ SEAD = {
-- @field Harms -- @field Harms
SEAD.Harms = { SEAD.Harms = {
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
--["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
["AGM_84"] = "AGM_84", ["AGM_84"] = "AGM_84",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
@ -80,6 +79,7 @@ SEAD = {
["BGM_109"] = "BGM_109", ["BGM_109"] = "BGM_109",
["AGM_154"] = "AGM_154", ["AGM_154"] = "AGM_154",
["HY-2"] = "HY-2", ["HY-2"] = "HY-2",
["ADM_141A"] = "ADM_141A",
} }
--- Missile enumerators - from DCS ME and Wikipedia --- Missile enumerators - from DCS ME and Wikipedia
@ -100,6 +100,7 @@ SEAD = {
["BGM_109"] = {460, 0.705}, --in-game ~465kn ["BGM_109"] = {460, 0.705}, --in-game ~465kn
["AGM_154"] = {130, 0.61}, ["AGM_154"] = {130, 0.61},
["HY-2"] = {90,1}, ["HY-2"] = {90,1},
["ADM_141A"] = {126,0.6},
} }
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles. --- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
@ -143,7 +144,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self:AddTransition("*", "ManageEvasion", "*") self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*") self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.4") self:I("*** SEAD - Started Version 0.4.5")
return self return self
end end
@ -348,8 +349,9 @@ end
-- @param #string SEADWeaponName -- @param #string SEADWeaponName
-- @param Wrapper.Group#GROUP SEADGroup Attacker Group -- @param Wrapper.Group#GROUP SEADGroup Attacker Group
-- @param #number timeoffset Offset for tti calc -- @param #number timeoffset Offset for tti calc
-- @param Wrapper.Weapon#WEAPON Weapon
-- @return #SEAD self -- @return #SEAD self
function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,timeoffset) function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,timeoffset,Weapon)
local timeoffset = timeoffset or 0 local timeoffset = timeoffset or 0
if _targetskill == "Random" then -- when skill is random, choose a skill if _targetskill == "Random" then -- when skill is random, choose a skill
local Skills = { "Average", "Good", "High", "Excellent" } local Skills = { "Average", "Good", "High", "Excellent" }
@ -372,6 +374,10 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
reach = wpndata[1] * 1.1 reach = wpndata[1] * 1.1
local mach = wpndata[2] local mach = wpndata[2]
wpnspeed = math.floor(mach * 340.29) wpnspeed = math.floor(mach * 340.29)
if Weapon then
wpnspeed = Weapon:GetSpeed()
self:T(string.format("*** SEAD - Weapon Speed from WEAPON: %f m/s",wpnspeed))
end
end end
-- time to impact -- time to impact
local _tti = math.floor(_distance / wpnspeed) - timeoffset -- estimated impact time local _tti = math.floor(_distance / wpnspeed) - timeoffset -- estimated impact time
@ -457,6 +463,9 @@ function SEAD:HandleEventShot( EventData )
local SEADWeapon = EventData.Weapon -- Identify the weapon fired local SEADWeapon = EventData.Weapon -- Identify the weapon fired
local SEADWeaponName = EventData.WeaponName -- return weapon type local SEADWeaponName = EventData.WeaponName -- return weapon type
local WeaponWrapper = WEAPON:New(EventData.Weapon)
--local SEADWeaponSpeed = WeaponWrapper:GetSpeed() -- mps
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName) self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
--self:T({ SEADWeapon }) --self:T({ SEADWeapon })
@ -475,7 +484,7 @@ function SEAD:HandleEventShot( EventData )
end end
return self return self
end end
local targetcat = _target:getCategory() -- Identify category local targetcat = Object.getCategory(_target) -- Identify category
local _targetUnit = nil -- Wrapper.Unit#UNIT local _targetUnit = nil -- Wrapper.Unit#UNIT
local _targetgroup = nil -- Wrapper.Group#GROUP local _targetgroup = nil -- Wrapper.Group#GROUP
self:T(string.format("*** Targetcat = %d",targetcat)) self:T(string.format("*** Targetcat = %d",targetcat))
@ -513,7 +522,11 @@ function SEAD:HandleEventShot( EventData )
end end
end end
if SEADGroupFound == true then -- yes we are being attacked if SEADGroupFound == true then -- yes we are being attacked
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup) if string.find(SEADWeaponName,"ADM_141",1,true) then
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
else
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
end
end end
end end
return self return self

View File

@ -21,6 +21,7 @@
-- @image Functional.Shorad.jpg -- @image Functional.Shorad.jpg
-- --
-- Date: Nov 2021 -- Date: Nov 2021
-- Last Update: Nov 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE --- **SHORAD** class, extends Core.Base#BASE
@ -39,8 +40,11 @@
-- @field #boolean DefendHarms Default true, intercept incoming HARMS -- @field #boolean DefendHarms Default true, intercept incoming HARMS
-- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles -- @field #boolean DefendMavs Default true, intercept incoming AG-Missiles
-- @field #number DefenseLowProb Default 70, minimum detection limit -- @field #number DefenseLowProb Default 70, minimum detection limit
-- @field #number DefenseHighProb Default 90, maximim detection limit -- @field #number DefenseHighProb Default 90, maximum detection limit
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green. -- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
-- @field #boolean shootandscoot
-- @field #number SkateNumber
-- @field Core.Set#SET_ZONE SkateZones
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@ -99,7 +103,10 @@ SHORAD = {
DefendMavs = true, DefendMavs = true,
DefenseLowProb = 70, DefenseLowProb = 70,
DefenseHighProb = 90, DefenseHighProb = 90,
UseEmOnOff = false, UseEmOnOff = true,
shootandscoot = false,
SkateNumber = 3,
SkateZones = nil,
} }
----------------------------------------------------------------------- -----------------------------------------------------------------------
@ -112,7 +119,6 @@ do
-- @field Harms -- @field Harms
SHORAD.Harms = { SHORAD.Harms = {
["AGM_88"] = "AGM_88", ["AGM_88"] = "AGM_88",
["AGM_45"] = "AGM_45",
["AGM_122"] = "AGM_122", ["AGM_122"] = "AGM_122",
["AGM_84"] = "AGM_84", ["AGM_84"] = "AGM_84",
["AGM_45"] = "AGM_45", ["AGM_45"] = "AGM_45",
@ -123,6 +129,8 @@ do
["X_25"] = "X_25", ["X_25"] = "X_25",
["X_31"] = "X_31", ["X_31"] = "X_31",
["Kh25"] = "Kh25", ["Kh25"] = "Kh25",
["HY-2"] = "HY-2",
["ADM_141A"] = "ADM_141A",
} }
--- TODO complete list? --- TODO complete list?
@ -134,7 +142,6 @@ do
["Kh29"] = "Kh29", ["Kh29"] = "Kh29",
["Kh31"] = "Kh31", ["Kh31"] = "Kh31",
["Kh66"] = "Kh66", ["Kh66"] = "Kh66",
--["BGM_109"] = "BGM_109",
} }
--- Instantiates a new SHORAD object --- Instantiates a new SHORAD object
@ -146,7 +153,7 @@ do
-- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call -- @param #number ActiveTimer Determines how many seconds the systems stay on red alert after wake-up call
-- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral" -- @param #string Coalition Coalition, i.e. "blue", "red", or "neutral"
-- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch) -- @param #boolean UseEmOnOff Use Emissions On/Off rather than Alarm State Red/Green (default: use Emissions switch)
-- @retunr #SHORAD self -- @return #SHORAD self
function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff) function SHORAD:New(Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition, UseEmOnOff)
local self = BASE:Inherit( self, FSM:New() ) local self = BASE:Inherit( self, FSM:New() )
self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition}) self:T({Name, ShoradPrefix, Samset, Radius, ActiveTimer, Coalition})
@ -165,8 +172,9 @@ do
self.DefendMavs = true self.DefendMavs = true
self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin self.DefenseLowProb = 70 -- probability to detect a missile shot, low margin
self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin self.DefenseHighProb = 90 -- probability to detect a missile shot, high margin
self.UseEmOnOff = UseEmOnOff or false -- Decide if we are using Emission on/off (default) or AlarmState red/green self.UseEmOnOff = true -- Decide if we are using Emission on/off (default) or AlarmState red/green
self:I("*** SHORAD - Started Version 0.3.1") if UseEmOnOff == false then self.UseEmOnOff = UseEmOnOff end
self:I("*** SHORAD - Started Version 0.3.2")
-- Set the string id for output to DCS.log file. -- Set the string id for output to DCS.log file.
self.lid=string.format("SHORAD %s | ", self.name) self.lid=string.format("SHORAD %s | ", self.name)
self:_InitState() self:_InitState()
@ -176,12 +184,14 @@ do
self:SetStartState("Running") self:SetStartState("Running")
self:AddTransition("*", "WakeUpShorad", "*") self:AddTransition("*", "WakeUpShorad", "*")
self:AddTransition("*", "CalculateHitZone", "*") self:AddTransition("*", "CalculateHitZone", "*")
self:AddTransition("*", "ShootAndScoot", "*")
return self return self
end end
--- Initially set all groups to alarm state GREEN --- Initially set all groups to alarm state GREEN
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:_InitState() function SHORAD:_InitState()
self:T(self.lid .. " _InitState") self:T(self.lid .. " _InitState")
local table = {} local table = {}
@ -205,21 +215,36 @@ do
return self return self
end end
--- Add a SET_ZONE of zones for Shoot&Scoot
-- @param #SHORAD self
-- @param Core.Set#SET_ZONE ZoneSet Set of zones to be used. Units will move around to the next (random) zone between 100m and 3000m away.
-- @param #number Number Number of closest zones to be considered, defaults to 3.
-- @return #SHORAD self
function SHORAD:AddScootZones(ZoneSet, Number)
self:T(self.lid .. " AddScootZones")
self.SkateZones = ZoneSet
self.SkateNumber = Number or 3
self.shootandscoot = true
return self
end
--- Switch debug state on --- Switch debug state on
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean debug Switch debug on (true) or off (false) -- @param #boolean debug Switch debug on (true) or off (false)
-- @return #SHORAD self
function SHORAD:SwitchDebug(onoff) function SHORAD:SwitchDebug(onoff)
self:T( { onoff } ) self:T( { onoff } )
if onoff then if onoff then
self:SwitchDebugOn() self:SwitchDebugOn()
else else
self.SwitchDebugOff() self:SwitchDebugOff()
end end
return self return self
end end
--- Switch debug state on --- Switch debug state on
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:SwitchDebugOn() function SHORAD:SwitchDebugOn()
self.debug = true self.debug = true
--tracing --tracing
@ -230,6 +255,7 @@ do
--- Switch debug state off --- Switch debug state off
-- @param #SHORAD self -- @param #SHORAD self
-- @return #SHORAD self
function SHORAD:SwitchDebugOff() function SHORAD:SwitchDebugOff()
self.debug = false self.debug = false
BASE:TraceOff() BASE:TraceOff()
@ -239,6 +265,7 @@ do
--- Switch defense for HARMs --- Switch defense for HARMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
-- @return #SHORAD self
function SHORAD:SwitchHARMDefense(onoff) function SHORAD:SwitchHARMDefense(onoff)
self:T( { onoff } ) self:T( { onoff } )
local onoff = onoff or true local onoff = onoff or true
@ -249,6 +276,7 @@ do
--- Switch defense for AGMs --- Switch defense for AGMs
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean onoff -- @param #boolean onoff
-- @return #SHORAD self
function SHORAD:SwitchAGMDefense(onoff) function SHORAD:SwitchAGMDefense(onoff)
self:T( { onoff } ) self:T( { onoff } )
local onoff = onoff or true local onoff = onoff or true
@ -260,6 +288,7 @@ do
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number low Minimum detection limit, integer 1-100 -- @param #number low Minimum detection limit, integer 1-100
-- @param #number high Maximum detection limit integer 1-100 -- @param #number high Maximum detection limit integer 1-100
-- @return #SHORAD self
function SHORAD:SetDefenseLimits(low,high) function SHORAD:SetDefenseLimits(low,high)
self:T( { low, high } ) self:T( { low, high } )
local low = low or 70 local low = low or 70
@ -278,6 +307,7 @@ do
--- Set the number of seconds a SHORAD site will stay active --- Set the number of seconds a SHORAD site will stay active
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number seconds Number of seconds systems stay active -- @param #number seconds Number of seconds systems stay active
-- @return #SHORAD self
function SHORAD:SetActiveTimer(seconds) function SHORAD:SetActiveTimer(seconds)
self:T(self.lid .. " SetActiveTimer") self:T(self.lid .. " SetActiveTimer")
local timer = seconds or 600 local timer = seconds or 600
@ -291,6 +321,7 @@ do
--- Set the number of meters for the SHORAD defense zone --- Set the number of meters for the SHORAD defense zone
-- @param #SHORAD self -- @param #SHORAD self
-- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active -- @param #number meters Radius of the defense search zone in meters. #SHORADs in this range around a targeted group will go active
-- @return #SHORAD self
function SHORAD:SetDefenseRadius(meters) function SHORAD:SetDefenseRadius(meters)
self:T(self.lid .. " SetDefenseRadius") self:T(self.lid .. " SetDefenseRadius")
local radius = meters or 20000 local radius = meters or 20000
@ -304,6 +335,7 @@ do
--- Set using Emission on/off instead of changing alarm state --- Set using Emission on/off instead of changing alarm state
-- @param #SHORAD self -- @param #SHORAD self
-- @param #boolean switch Decide if we are changing alarm state or AI state -- @param #boolean switch Decide if we are changing alarm state or AI state
-- @return #SHORAD self
function SHORAD:SetUsingEmOnOff(switch) function SHORAD:SetUsingEmOnOff(switch)
self:T(self.lid .. " SetUsingEmOnOff") self:T(self.lid .. " SetUsingEmOnOff")
self.UseEmOnOff = switch or false self.UseEmOnOff = switch or false
@ -375,11 +407,11 @@ do
local shorad = self.Groupset local shorad = self.Groupset
local shoradset = shorad:GetAliveSet() --#table local shoradset = shorad:GetAliveSet() --#table
local returnname = false local returnname = false
--local TDiff = 1
for _,_groups in pairs (shoradset) do for _,_groups in pairs (shoradset) do
local groupname = _groups:GetName() local groupname = _groups:GetName()
if string.find(groupname, tgtgrp, 1, true) then if string.find(groupname, tgtgrp, 1, true) then
returnname = true returnname = true
--_groups:RelocateGroundRandomInRadius(7,100,false,false) -- be a bit evasive
end end
end end
return returnname return returnname
@ -426,6 +458,7 @@ do
-- @param #number Radius Radius of the #ZONE -- @param #number Radius Radius of the #ZONE
-- @param #number ActiveTimer Number of seconds to stay active -- @param #number ActiveTimer Number of seconds to stay active
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC -- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
-- @return #SHORAD self
-- @usage Use this function to integrate with other systems, example -- @usage Use this function to integrate with other systems, example
-- --
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart() -- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
@ -452,28 +485,35 @@ do
local targetzone = ZONE_RADIUS:New("Shorad",targetvec2,Radius) -- create a defense zone to check local targetzone = ZONE_RADIUS:New("Shorad",targetvec2,Radius) -- create a defense zone to check
local groupset = self.Groupset --Core.Set#SET_GROUP local groupset = self.Groupset --Core.Set#SET_GROUP
local shoradset = groupset:GetAliveSet() --#table local shoradset = groupset:GetAliveSet() --#table
-- local function to switch off shorad again -- local function to switch off shorad again
local function SleepShorad(group) local function SleepShorad(group)
if group and group:IsAlive() then
local groupname = group:GetName() local groupname = group:GetName()
self.ActiveGroups[groupname] = nil self.ActiveGroups[groupname] = nil
if self.UseEmOnOff then if self.UseEmOnOff then
group:EnableEmission(false) group:EnableEmission(false)
--group:SetAIOff()
else else
group:OptionAlarmStateGreen() group:OptionAlarmStateGreen()
end end
local text = string.format("Sleeping SHORAD %s", group:GetName()) local text = string.format("Sleeping SHORAD %s", group:GetName())
self:T(text) self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(1,group)
end end
end
end
-- go through set and find the one(s) to activate -- go through set and find the one(s) to activate
local TDiff = 4
for _,_group in pairs (shoradset) do for _,_group in pairs (shoradset) do
if _group:IsAnyInZone(targetzone) then if _group:IsAnyInZone(targetzone) then
local text = string.format("Waking up SHORAD %s", _group:GetName()) local text = string.format("Waking up SHORAD %s", _group:GetName())
self:T(text) self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
if self.UseEmOnOff then if self.UseEmOnOff then
--_group:SetAIOn()
_group:EnableEmission(true) _group:EnableEmission(true)
end end
_group:OptionAlarmStateRed() _group:OptionAlarmStateRed()
@ -481,7 +521,12 @@ do
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
self.ActiveGroups[groupname] = { Timing = ActiveTimer } self.ActiveGroups[groupname] = { Timing = ActiveTimer }
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
timer.scheduleFunction(SleepShorad, _group, endtime) self.ActiveGroups[groupname].Timer = TIMER:New(SleepShorad,_group):Start(endtime)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(TDiff,_group)
TDiff=TDiff+1
end
end end
end end
end end
@ -558,14 +603,46 @@ function SHORAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEA
return self return self
end end
--- (Internal) Shoot and Scoot
-- @param #SHORAD self
-- @param #string From
-- @param #string Event
-- @param #string To
-- @param Wrapper.Group#GROUP Shorad Shorad group
-- @return #SHORAD self
function SHORAD:onafterShootAndScoot(From,Event,To,Shorad)
self:T( { From,Event,To } )
local possibleZones = {}
local mindist = 100
local maxdist = 3000
if Shorad and Shorad:IsAlive() then
local NowCoord = Shorad:GetCoordinate()
for _,_zone in pairs(self.SkateZones.Set) do
local zone = _zone -- Core.Zone#ZONE_RADIUS
local dist = NowCoord:Get2DDistance(zone:GetCoordinate())
if dist >= mindist and dist <= maxdist then
possibleZones[#possibleZones+1] = zone
if #possibleZones == self.SkateNumber then break end
end
end
if #possibleZones > 0 and Shorad:GetVelocityKMH() < 2 then
local rand = math.floor(math.random(1,#possibleZones*1000)/1000+0.5)
if rand == 0 then rand = 1 end
self:T(self.lid .. " ShootAndScoot to zone "..rand)
local ToCoordinate = possibleZones[rand]:GetCoordinate()
Shorad:RouteGroundTo(ToCoordinate,20,"Cone",1)
end
end
return self
end
--- Main function - work on the EventData --- Main function - work on the EventData
-- @param #SHORAD self -- @param #SHORAD self
-- @param Core.Event#EVENTDATA EventData The event details table data set -- @param Core.Event#EVENTDATA EventData The event details table data set
-- @return #SHORAD self
function SHORAD:HandleEventShot( EventData ) function SHORAD:HandleEventShot( EventData )
self:T( { EventData } ) self:T( { EventData } )
self:T(self.lid .. " HandleEventShot") self:T(self.lid .. " HandleEventShot")
--local ShootingUnit = EventData.IniDCSUnit
--local ShootingUnitName = EventData.IniDCSUnitName
local ShootingWeapon = EventData.Weapon -- Identify the weapon fired local ShootingWeapon = EventData.Weapon -- Identify the weapon fired
local ShootingWeaponName = EventData.WeaponName -- return weapon type local ShootingWeaponName = EventData.WeaponName -- return weapon type
-- get firing coalition -- get firing coalition
@ -596,27 +673,18 @@ end
return self return self
end end
local targetcat = targetdata:getCategory() -- Identify category local targetcat = Object.getCategory(targetdata) -- Identify category
self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat))) self:T(string.format("Target Category (3=STATIC, 1=UNIT)= %s",tostring(targetcat)))
self:T({targetdata}) self:T({targetdata})
local targetunit = nil local targetunit = nil
if targetcat == Object.Category.UNIT then -- UNIT if targetcat == Object.Category.UNIT then -- UNIT
targetunit = UNIT:Find(targetdata) targetunit = UNIT:Find(targetdata)
elseif targetcat == Object.Category.STATIC then -- STATIC elseif targetcat == Object.Category.STATIC then -- STATIC
--self:T("Static Target Data")
--self:T({targetdata:isExist()})
--self:T({targetdata:getPoint()})
local tgtcoord = COORDINATE:NewFromVec3(targetdata:getPoint()) local tgtcoord = COORDINATE:NewFromVec3(targetdata:getPoint())
--tgtcoord:MarkToAll("Missile Target",true)
local tgtgrp1 = self.Samset:FindNearestGroupFromPointVec2(tgtcoord) local tgtgrp1 = self.Samset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord1 = tgtgrp1:GetCoordinate() local tgtcoord1 = tgtgrp1:GetCoordinate()
--tgtcoord1:MarkToAll("Close target SAM",true)
local tgtgrp2 = self.Groupset:FindNearestGroupFromPointVec2(tgtcoord) local tgtgrp2 = self.Groupset:FindNearestGroupFromPointVec2(tgtcoord)
local tgtcoord2 = tgtgrp2:GetCoordinate() local tgtcoord2 = tgtgrp2:GetCoordinate()
--tgtcoord2:MarkToAll("Close target SHORAD",true)
local dist1 = tgtcoord:Get2DDistance(tgtcoord1) local dist1 = tgtcoord:Get2DDistance(tgtcoord1)
local dist2 = tgtcoord:Get2DDistance(tgtcoord2) local dist2 = tgtcoord:Get2DDistance(tgtcoord2)
@ -628,10 +696,8 @@ end
targetcat = Object.Category.UNIT targetcat = Object.Category.UNIT
end end
end end
--local targetunitname = Unit.getName(targetdata) -- Unit name
if targetunit and targetunit:IsAlive() then if targetunit and targetunit:IsAlive() then
local targetunitname = targetunit:GetName() local targetunitname = targetunit:GetName()
--local targetgroup = Unit.getGroup(Weapon.getTarget(ShootingWeapon)) --targeted group
local targetgroup = nil local targetgroup = nil
local targetgroupname = "none" local targetgroupname = "none"
if targetcat == Object.Category.UNIT then if targetcat == Object.Category.UNIT then
@ -649,7 +715,6 @@ end
self:T( text ) self:T( text )
local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug) local m = MESSAGE:New(text,10,"Info"):ToAllIf(self.debug)
-- check if we or a SAM site are the target -- check if we or a SAM site are the target
--local TargetGroup = EventData.TgtGroup -- Wrapper.Group#GROUP
local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean local shotatus = self:_CheckShotAtShorad(targetgroupname) --#boolean
local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean local shotatsams = self:_CheckShotAtSams(targetgroupname) --#boolean
-- if being shot at, find closest SHORADs to activate -- if being shot at, find closest SHORADs to activate

View File

@ -2512,7 +2512,7 @@ function ATIS:onafterBroadcast( From, Event, To )
if not self.ATISforFARPs then if not self.ATISforFARPs then
-- Active runway. -- Active runway.
local subtitle local subtitle = ""
if runwayLanding then if runwayLanding then
local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale) local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale)
--subtitle=string.format("Active runway landing %s", runwayLanding) --subtitle=string.format("Active runway landing %s", runwayLanding)

View File

@ -17,7 +17,7 @@
-- === -- ===
-- --
-- ### Author: **applevangelist** -- ### Author: **applevangelist**
-- @date Last Update July 2023 -- @date Last Update Nov 2023
-- @module Ops.AWACS -- @module Ops.AWACS
-- @image OPS_AWACS.jpg -- @image OPS_AWACS.jpg
@ -507,7 +507,7 @@ do
-- @field #AWACS -- @field #AWACS
AWACS = { AWACS = {
ClassName = "AWACS", -- #string ClassName = "AWACS", -- #string
version = "0.2.58", -- #string version = "0.2.59", -- #string
lid = "", -- #string lid = "", -- #string
coalition = coalition.side.BLUE, -- #number coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string coalitiontxt = "blue", -- #string
@ -2988,7 +2988,7 @@ function AWACS:_Picture(Group,IsGeneral)
if clustersAO == 0 and clustersEWR == 0 then if clustersAO == 0 and clustersEWR == 0 then
-- clean -- clean
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false) self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
else else
if clustersAO > 0 then if clustersAO > 0 then

View File

@ -351,7 +351,7 @@ FLIGHTCONTROL.Violation={
--- FlightControl class version. --- FlightControl class version.
-- @field #string version -- @field #string version
FLIGHTCONTROL.version="0.7.4" FLIGHTCONTROL.version="0.7.5"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -4974,11 +4974,21 @@ function FLIGHTCONTROL:SpawnParkingGuard(unit)
-- Length of the unit + 3 meters. -- Length of the unit + 3 meters.
local size, x, y, z=unit:GetObjectSize() local size, x, y, z=unit:GetObjectSize()
local xdiff = 3
--Fix for hangars, puts the guy out front and not on top.
if AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.Shelter) then
xdiff = 27-(x*0.5)
end
if (AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.OpenMed) or AIRBASE._CheckTerminalType(spot.TerminalType, AIRBASE.TerminalType.Shelter)) and self.airbasename == AIRBASE.Sinai.Ramon_Airbase then
xdiff = 12
end
-- Debug message. -- Debug message.
self:T2(self.lid..string.format("Parking guard for %s: heading=%d, distance x=%.1f m", unit:GetName(), heading, x)) self:T2(self.lid..string.format("Parking guard for %s: heading=%d, length x=%.1f m, xdiff=%.1f m", unit:GetName(), heading, x, xdiff))
-- Coordinate for the guard. -- Coordinate for the guard.
local Coordinate=coordinate:Translate(0.75*x+3, heading) local Coordinate=coordinate:Translate(x*0.5+xdiff, heading)
-- Let him face the aircraft. -- Let him face the aircraft.
local lookat=heading-180 local lookat=heading-180

View File

@ -1025,7 +1025,7 @@ function OPSZONE:Scan()
if ZoneObject then if ZoneObject then
-- Object category. -- Object category.
local ObjectCategory=ZoneObject:getCategory() local ObjectCategory=Object.getCategory(ZoneObject)
if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() then if ObjectCategory==Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() then

View File

@ -104,7 +104,7 @@ PLAYERRECCE = {
ClassName = "PLAYERRECCE", ClassName = "PLAYERRECCE",
verbose = true, verbose = true,
lid = nil, lid = nil,
version = "0.0.19", version = "0.0.21",
ViewZone = {}, ViewZone = {},
ViewZoneVisual = {}, ViewZoneVisual = {},
ViewZoneLaser = {}, ViewZoneLaser = {},
@ -268,6 +268,146 @@ function PLAYERRECCE:New(Name, Coalition, PlayerSet)
self:I(self.lid.." Started.") self:I(self.lid.." Started.")
------------------------
--- Pseudo Functions ---
------------------------
--- Triggers the FSM event "Start". Starts the PLAYERRECCE. Note: Start() is called automatically after New().
-- @function [parent=#PLAYERRECCE] Start
-- @param #PLAYERRECCE self
--- Triggers the FSM event "Start" after a delay. Starts the PLAYERRECCE. Note: Start() is called automatically after New().
-- @function [parent=#PLAYERRECCE] __Start
-- @param #PLAYERRECCE self
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "Stop". Stops the PLAYERRECCE and all its event handlers.
-- @param #PLAYERRECCE self
--- Triggers the FSM event "Stop" after a delay. Stops the PLAYERRECCE and all its event handlers.
-- @function [parent=#PLAYERRECCE] __Stop
-- @param #PLAYERRECCE self
-- @param #number delay Delay in seconds.
--- FSM Function OnAfterRecceOnStation. Recce came on station.
-- @function [parent=#PLAYERRECCE] OnAfterRecceOnStation
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterRecceOffStation. Recce went off duty.
-- @function [parent=#PLAYERRECCE] OnAfterRecceOffStation
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetDetected. Targets detected.
-- @function [parent=#PLAYERRECCE] OnAfterTargetDetected
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param #table Targetsbyclock #table with index 1..12 containing a #table of Wrapper.Unit#UNIT objects each.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetsSmoked. Smoke grenade shot.
-- @function [parent=#PLAYERRECCE] OnAfterTargetsSmoked
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetsFlared. Flares shot.
-- @function [parent=#PLAYERRECCE] OnAfterTargetsFlared
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterIllumination. Illumination rocket shot.
-- @function [parent=#PLAYERRECCE] OnAfterIllumination
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param #string Playername
-- @param Core.Set#SET_UNIT TargetSet
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetLasing. Lasing a new target.
-- @function [parent=#PLAYERRECCE] OnAfterTargetLasing
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target
-- @param #number Lasercode
-- @param #number Lasingtime
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetLOSLost. Lost LOS on lased target.
-- @function [parent=#PLAYERRECCE] OnAfterTargetLOSLost
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetReport. Laser target report sent.
-- @function [parent=#PLAYERRECCE] OnAfterTargetReport
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Core.Set#SET_UNIT TargetSet
-- @param Wrapper.Unit#UNIT Target Target currently lased
-- @param #string Text
-- @return #PLAYERRECCE self
--- FSM Function OnAfterTargetReportSent. All targets report sent.
-- @function [parent=#PLAYERRECCE] OnAfterTargetReportSent
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client Client sending the report
-- @param #string Playername Player name
-- @param Core.Set#SET_UNIT TargetSet Set of targets
-- @return #PLAYERRECCE self
--- FSM Function OnAfterShack. Lased target has been destroyed.
-- @function [parent=#PLAYERRECCE] OnAfterShack
-- @param #PLAYERRECCE self
-- @param #string From State.
-- @param #string Event Trigger.
-- @param #string To State.
-- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target The destroyed target (if obtainable)
-- @return #PLAYERRECCE self
return self return self
end end
@ -346,7 +486,7 @@ function PLAYERRECCE:_GetClockDirection(unit, target)
end end
--- [User] Set a table of possible laser codes. --- [User] Set a table of possible laser codes.
-- Each new RECCE can select a code from this table, default is 1688. -- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 }.
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param #list<#number> LaserCodes -- @param #list<#number> LaserCodes
-- @return #PLAYERRECCE -- @return #PLAYERRECCE
@ -399,7 +539,7 @@ end
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Client#CLIENT client -- @param Wrapper.Client#CLIENT client
-- @param #string playername -- @param #string playername
-- @return #boolen OnOff -- @return #boolean OnOff
function PLAYERRECCE:_CameraOn(client,playername) function PLAYERRECCE:_CameraOn(client,playername)
local camera = true local camera = true
local unit = client -- Wrapper.Unit#UNIT local unit = client -- Wrapper.Unit#UNIT
@ -430,26 +570,31 @@ function PLAYERRECCE:_GetGazelleVivianneSight(Gazelle)
local unit = Gazelle -- Wrapper.Unit#UNIT local unit = Gazelle -- Wrapper.Unit#UNIT
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local dcsunit = Unit.getByName(Gazelle:GetName()) local dcsunit = Unit.getByName(Gazelle:GetName())
local vivihorizontal = dcsunit:getDrawArgumentValue(215) or 0 -- (not in MiniGun) 1 to -1 -- zero is straight ahead, 1/-1 = 180 deg local vivihorizontal = dcsunit:getDrawArgumentValue(215) or 0 -- (not in MiniGun) 1 to -1 -- zero is straight ahead, 1/-1 = 180 deg,
local vivivertical = dcsunit:getDrawArgumentValue(216) or 0 -- L/Mistral/Minigun model has no 216, ca 10deg up (=1) and down (=-1) local vivivertical = dcsunit:getDrawArgumentValue(216) or 0 -- L/Mistral/Minigun model has no 216, ca 10deg up (=1) and down (=-1)
-- vertical model limits 1.53846, -1.10731
local vivioff = false local vivioff = false
-- -1 = -180, 1 = 180 -- -1 = -180, 1 = 180
-- Actual view -0,66 to 0,66 -- Actual model view -0,66 to 0,66
-- Nick view -0,98 to 0,98 for +/- 30° -- Nick view 1.53846, -1.10731 for - 30° to +45°
if vivihorizontal < -0.7 then if vivihorizontal < -0.67 then -- model end
vivihorizontal = -0.7 vivihorizontal = -0.67
vivioff = true vivioff = false
return 0,0,0,false --return 0,0,0,false
elseif vivihorizontal > 0.7 then elseif vivihorizontal > 0.67 then -- vivi off
vivihorizontal = 0.7 vivihorizontal = 0.67
vivioff = true vivioff = true
return 0,0,0,false return 0,0,0,false
end end
vivivertical = vivivertical / 1.10731 -- normalize
local horizontalview = vivihorizontal * -180 local horizontalview = vivihorizontal * -180
local verticalview = vivivertical * -30 -- ca +/- 30° local verticalview = vivivertical * 30 -- ca +/- 30°
--self:I(string.format("vivihorizontal=%.5f | vivivertical=%.5f",vivihorizontal,vivivertical))
--self:I(string.format("horizontal=%.5f | vertical=%.5f",horizontalview,verticalview))
local heading = unit:GetHeading() local heading = unit:GetHeading()
local viviheading = (heading+horizontalview)%360 local viviheading = (heading+horizontalview)%360
local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff) local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff)
--self:I(string.format("maxview=%.5f",maxview))
-- visual skew -- visual skew
local factor = 3.15 local factor = 3.15
self.GazelleViewFactors = { self.GazelleViewFactors = {
@ -469,16 +614,18 @@ function PLAYERRECCE:_GetGazelleVivianneSight(Gazelle)
} }
local lfac = UTILS.Round(maxview,-2) local lfac = UTILS.Round(maxview,-2)
if lfac <= 1300 then if lfac <= 1300 then
factor = self.GazelleViewFactors[lfac/100] --factor = self.GazelleViewFactors[lfac/100]
factor = 3.15
maxview = math.ceil((maxview*factor)/100)*100 maxview = math.ceil((maxview*factor)/100)*100
end end
if maxview > 8000 then maxview = 8000 end if maxview > 8000 then maxview = 8000 end
--self:I(string.format("corrected maxview=%.5f",maxview))
return viviheading, verticalview,maxview, not vivioff return viviheading, verticalview,maxview, not vivioff
end end
return 0,0,0,false return 0,0,0,false
end end
--- [Internal] Get the max line of sight based on unit head and camera nod via trigonometrie. Returns 0 if camera is off. --- [Internal] Get the max line of sight based on unit head and camera nod via trigonometry. Returns 0 if camera is off.
-- @param #PLAYERRECCE self -- @param #PLAYERRECCE self
-- @param Wrapper.Unit#UNIT unit The unit which LOS we want -- @param Wrapper.Unit#UNIT unit The unit which LOS we want
-- @param #number vheading Heading where the unit or camera is looking -- @param #number vheading Heading where the unit or camera is looking
@ -488,12 +635,13 @@ end
function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff) function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff)
self:T(self.lid.."_GetActualMaxLOSight") self:T(self.lid.."_GetActualMaxLOSight")
if vivoff then return 0 end if vivoff then return 0 end
--if vnod < -0.03 then vnod = -0.03 end
local maxview = 0 local maxview = 0
if unit and unit:IsAlive() then if unit and unit:IsAlive() then
local typename = unit:GetTypeName() local typename = unit:GetTypeName()
maxview = self.MaxViewDistance[typename] or 8000 maxview = self.MaxViewDistance[typename] or 8000
local CamHeight = self.Cameraheight[typename] or 0 local CamHeight = self.Cameraheight[typename] or 0
if vnod > 0 then if vnod < 0 then
-- Looking down -- Looking down
-- determine max distance we're looking at -- determine max distance we're looking at
local beta = 90 local beta = 90
@ -505,7 +653,7 @@ function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff)
maxview = c*1.2 -- +20% maxview = c*1.2 -- +20%
end end
end end
return maxview return math.abs(maxview)
end end
--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns. --- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns.
@ -768,7 +916,8 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
-- still looking at target? -- still looking at target?
local target=self.LaserTarget[playername] -- Ops.Target#TARGET local target=self.LaserTarget[playername] -- Ops.Target#TARGET
local oldtarget = target:GetObject() --or laser.Target local oldtarget = target:GetObject() --or laser.Target
self:T("Targetstate: "..target:GetState()) --self:I("Targetstate: "..target:GetState())
--self:I("Laser State: "..tostring(laser:IsLasing()))
if not oldtarget or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then if not oldtarget or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
-- lost LOS or dead -- lost LOS or dead
laser:LaseOff() laser:LaseOff()
@ -780,12 +929,20 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
self.LaserTarget[playername] = nil self.LaserTarget[playername] = nil
end end
end end
if oldtarget and (not laser:IsLasing()) then
--self:I("Switching laser back on ..")
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
local lasingtime = self.lasingtime or 60
--local targettype = target:GetTypeName()
laser:LaseOn(oldtarget,lasercode,lasingtime)
--self:__TargetLasing(-1,client,oldtarget,lasercode,lasingtime)
end
elseif not laser:IsLasing() and target then elseif not laser:IsLasing() and target then
local relativecam = self.LaserRelativePos[client:GetTypeName()] local relativecam = self.LaserRelativePos[client:GetTypeName()]
laser:SetRelativeStartPosition(relativecam) laser:SetRelativeStartPosition(relativecam)
local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688 local lasercode = self.UnitLaserCodes[playername] or laser.LaserCode or 1688
local lasingtime = self.lasingtime or 60 local lasingtime = self.lasingtime or 60
local targettype = target:GetTypeName() --local targettype = target:GetTypeName()
laser:LaseOn(target,lasercode,lasingtime) laser:LaseOn(target,lasercode,lasingtime)
self.LaserTarget[playername] = TARGET:New(target) self.LaserTarget[playername] = TARGET:New(target)
self.LaserTarget[playername].TStatus = 9 self.LaserTarget[playername].TStatus = 9
@ -953,9 +1110,13 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
end end
end end
local coordinate = nil
local setthreat = 0
-- smoke everything else -- smoke everything else
if cameraset:CountAlive() > 1 then
local coordinate = cameraset:GetCoordinate() local coordinate = cameraset:GetCoordinate()
local setthreat = cameraset:CalculateThreatLevelA2G() local setthreat = cameraset:CalculateThreatLevelA2G()
end
if coordinate then if coordinate then
local color = lowsmoke local color = lowsmoke
@ -1582,7 +1743,7 @@ end
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #table Targetsbyclock -- @param #table Targetsbyclock. #table with index 1..12 containing a #table of Wrapper.Unit#UNIT objects each.
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
-- @param #string Playername -- @param #string Playername
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
@ -1835,7 +1996,7 @@ function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Laserc
coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings) coordtext = coord:ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings)
end end
local coordtext = coord:ToStringA2G(client,Settings) local coordtext = coord:ToStringA2G(client,Settings)
local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime) local text = string.format("All stations, %s lasing %s\nat %s!\nCode %d, Duration %d plus seconds!",callsign, targettype, coordtext, Lasercode, Lasingtime)
MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client) MESSAGE:New(text,15,self.Name or "FACA"):ToClient(client)
end end
end end
@ -1862,9 +2023,8 @@ end
-- @param #string To -- @param #string To
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client
-- @param Wrapper.Unit#UNIT Target -- @param Wrapper.Unit#UNIT Target
-- @param #string Targettype
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:onafterShack(From, Event, To, Client, Target, Targettype) function PLAYERRECCE:onafterShack(From, Event, To, Client, Target)
self:T({From, Event, To}) self:T({From, Event, To})
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations) local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
@ -1972,7 +2132,6 @@ function PLAYERRECCE:onafterTargetReport(From, Event, To, Client, TargetSet, Tar
end end
end end
end end
--self:__TargetReportSent(-2,Client, TargetSet, Target, Text)
return self return self
end end
@ -1981,12 +2140,11 @@ end
-- @param #string From -- @param #string From
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param Wrapper.Client#CLIENT Client -- @param Wrapper.Client#CLIENT Client Client sending the report
-- @param Core.Set#SET_UNIT TargetSet -- @param #string Playername Player name
-- @param Wrapper.Unit#UNIT Target -- @param Core.Set#SET_UNIT TargetSet Set of targets
-- @param #string Text
-- @return #PLAYERRECCE self -- @return #PLAYERRECCE self
function PLAYERRECCE:onafterTargetReportSent(From, Event, To, Client, TargetSet) function PLAYERRECCE:onafterTargetReportSent(From, Event, To, Client, Playername, TargetSet)
self:T({From, Event, To}) self:T({From, Event, To})
local text = "Upload completed!" local text = "Upload completed!"
if self.UseSRS then if self.UseSRS then

View File

@ -1552,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
--- PLAYERTASK class version. --- PLAYERTASK class version.
-- @field #string version -- @field #string version
PLAYERTASKCONTROLLER.version="0.1.62" PLAYERTASKCONTROLLER.version="0.1.63"
--- Create and run a new TASKCONTROLLER instance. --- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self -- @param #PLAYERTASKCONTROLLER self
@ -1585,7 +1585,7 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.TasksPerPlayer = FIFO:New() -- Utilities.FiFo#FIFO self.TasksPerPlayer = FIFO:New() -- Utilities.FiFo#FIFO
self.PrecisionTasks = FIFO:New() -- Utilities.FiFo#FIFO self.PrecisionTasks = FIFO:New() -- Utilities.FiFo#FIFO
self.PlayerMenu = {} -- #table --self.PlayerMenu = {} -- #table
self.FlashPlayer = {} -- #table self.FlashPlayer = {} -- #table
self.AllowFlash = false self.AllowFlash = false
self.lasttaskcount = 0 self.lasttaskcount = 0
@ -2175,10 +2175,10 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
if EventData.IniPlayerName then if EventData.IniPlayerName then
self:T(self.lid.."Event for player: "..EventData.IniPlayerName) self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
if self.PlayerMenu[EventData.IniPlayerName] then --if self.PlayerMenu[EventData.IniPlayerName] then
self.PlayerMenu[EventData.IniPlayerName]:Remove() --self.PlayerMenu[EventData.IniPlayerName]:Remove()
self.PlayerMenu[EventData.IniPlayerName] = nil --self.PlayerMenu[EventData.IniPlayerName] = nil
end --end
local text = "" local text = ""
if self.TasksPerPlayer:HasUniqueID(EventData.IniPlayerName) then if self.TasksPerPlayer:HasUniqueID(EventData.IniPlayerName) then
local task = self.TasksPerPlayer:PullByID(EventData.IniPlayerName) -- Ops.PlayerTask#PLAYERTASK local task = self.TasksPerPlayer:PullByID(EventData.IniPlayerName) -- Ops.PlayerTask#PLAYERTASK
@ -2187,6 +2187,8 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
task:RemoveClient(Client) task:RemoveClient(Client)
--text = "Task aborted!" --text = "Task aborted!"
text = self.gettext:GetEntry("TASKABORT",self.locale) text = self.gettext:GetEntry("TASKABORT",self.locale)
self.ActiveTaskMenuTemplate:ResetMenu(Client)
self.JoinTaskMenuTemplate:ResetMenu(Client)
else else
task:RemoveClient(nil,EventData.IniPlayerName) task:RemoveClient(nil,EventData.IniPlayerName)
--text = "Task aborted!" --text = "Task aborted!"
@ -2236,8 +2238,8 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation) self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation)
end end
if EventData.IniPlayerName then if EventData.IniPlayerName then
self.PlayerMenu[EventData.IniPlayerName] = nil --self.PlayerMenu[EventData.IniPlayerName] = nil
local player = CLIENT:FindByName(EventData.IniUnitName) local player = _DATABASE:FindClient( EventData.IniUnitName )
self:_SwitchMenuForClient(player,"Info") self:_SwitchMenuForClient(player,"Info")
end end
end end
@ -2949,7 +2951,7 @@ function PLAYERTASKCONTROLLER:_AddTask(Target)
task:HandleEvent(EVENTS.Shot) task:HandleEvent(EVENTS.Shot)
function task:OnEventShot(EventData) function task:OnEventShot(EventData)
local data = EventData -- Core.Event#EVENTDATA EventData local data = EventData -- Core.Event#EVENTDATA EventData
local wcat = data.Weapon:getCategory() -- cat 2 or 3 local wcat = Object.getCategory(data.Weapon) -- cat 2 or 3
local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate() local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate()
local vec2 = coord:GetVec2() or {x=0, y=0} local vec2 = coord:GetVec2() or {x=0, y=0}
local coal = data.IniCoalition local coal = data.IniCoalition

View File

@ -1243,7 +1243,7 @@ function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
self.gender = MSRS_Config.Gender or "male" self.gender = MSRS_Config.Gender or "male"
self.google = MSRS_Config.Google self.google = MSRS_Config.Google
self.Label = MSRS_Config.Label or "MSRS" self.Label = MSRS_Config.Label or "MSRS"
self.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel self.voice = MSRS_Config.Voice --or MSRS.Voices.Microsoft.Hazel
if MSRS_Config.GRPC then if MSRS_Config.GRPC then
self.provider = MSRS_Config.GRPC.DefaultProvider self.provider = MSRS_Config.GRPC.DefaultProvider
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
@ -1267,7 +1267,7 @@ function MSRS:LoadConfigFile(Path,Filename,ConfigLoaded)
MSRS.gender = MSRS_Config.Gender or "male" MSRS.gender = MSRS_Config.Gender or "male"
MSRS.google = MSRS_Config.Google MSRS.google = MSRS_Config.Google
MSRS.Label = MSRS_Config.Label or "MSRS" MSRS.Label = MSRS_Config.Label or "MSRS"
MSRS.voice = MSRS_Config.Voice or MSRS.Voices.Microsoft.Hazel MSRS.voice = MSRS_Config.Voice --or MSRS.Voices.Microsoft.Hazel
if MSRS_Config.GRPC then if MSRS_Config.GRPC then
MSRS.provider = MSRS_Config.GRPC.DefaultProvider MSRS.provider = MSRS_Config.GRPC.DefaultProvider
if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then if MSRS_Config.GRPC[MSRS_Config.GRPC.DefaultProvider] then
@ -1677,7 +1677,7 @@ end
-- @param #MSRSQUEUE self -- @param #MSRSQUEUE self
-- @return #MSRSQUEUE self The MSRSQUEUE object. -- @return #MSRSQUEUE self The MSRSQUEUE object.
function MSRSQUEUE:Clear() function MSRSQUEUE:Clear()
self:I(self.lid.."Clearning MSRSQUEUE") self:I(self.lid.."Clearing MSRSQUEUE")
self.queue={} self.queue={}
return self return self
end end
@ -1778,7 +1778,7 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
transmission.gender = gender transmission.gender = gender
transmission.culture = culture transmission.culture = culture
transmission.voice = voice transmission.voice = voice
transmission.gender = volume transmission.volume = volume
transmission.label = label transmission.label = label
transmission.coordinate = coordinate transmission.coordinate = coordinate

View File

@ -990,7 +990,7 @@ end
function AIRBASE:GetWarehouse() function AIRBASE:GetWarehouse()
local warehouse=nil --DCS#Warehouse local warehouse=nil --DCS#Warehouse
local airbase=self:GetDCSObject() local airbase=self:GetDCSObject()
if airbase then if airbase and Airbase.getWarehouse then
warehouse=airbase:getWarehouse() warehouse=airbase:getWarehouse()
end end
return warehouse return warehouse
@ -1957,7 +1957,7 @@ function AIRBASE:_CheckParkingLists(TerminalID)
end end
--- Helper function to check for the correct terminal type including "artificial" ones. --- Helper function to check for the correct terminal type including "artificial" ones.
-- @param #number Term_Type Termial type from getParking routine. -- @param #number Term_Type Terminal type from getParking routine.
-- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator. -- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator.
-- @return #boolean True if terminal types match. -- @return #boolean True if terminal types match.
function AIRBASE._CheckTerminalType(Term_Type, termtype) function AIRBASE._CheckTerminalType(Term_Type, termtype)

View File

@ -323,7 +323,7 @@ function CLIENT:Alive( CallBackFunction, ... )
return self return self
end end
--- @param #CLIENT self -- @param #CLIENT self
function CLIENT:_AliveCheckScheduler( SchedulerName ) function CLIENT:_AliveCheckScheduler( SchedulerName )
self:F3( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } ) self:F3( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } )
@ -531,8 +531,6 @@ function CLIENT:ShowCargo()
end end
--- The main message driver for the CLIENT. --- The main message driver for the CLIENT.
-- This function displays various messages to the Player logged into the CLIENT through the DCS World Messaging system. -- This function displays various messages to the Player logged into the CLIENT through the DCS World Messaging system.
-- @param #CLIENT self -- @param #CLIENT self
@ -578,3 +576,36 @@ function CLIENT:Message( Message, MessageDuration, MessageCategory, MessageInter
end end
end end
end end
--- [Multi-Player Server] Get UCID from a CLIENT.
-- @param #CLIENT self
-- @return #string UCID
function CLIENT:GetUCID()
local PID = NET.GetPlayerIDByName(nil,self:GetPlayerName())
return net.get_player_info(tonumber(PID), 'ucid')
end
--- [Multi-Player Server] Return a table of attributes from CLIENT. If optional attribute is present, only that value is returned.
-- @param #CLIENT self
-- @param #string Attribute (Optional) The attribute to obtain. List see below.
-- @return #table PlayerInfo or nil if it cannot be found
-- @usage
-- Returned table holds these attributes:
--
-- 'id' : player ID
-- 'name' : player name
-- 'side' : 0 - spectators, 1 - red, 2 - blue
-- 'slot' : slot ID of the player or
-- 'ping' : ping of the player in ms
-- 'ipaddr': IP address of the player, SERVER ONLY
-- 'ucid' : Unique Client Identifier, SERVER ONLY
--
function CLIENT:GetPlayerInfo(Attribute)
local PID = NET.GetPlayerIDByName(nil,self:GetPlayerName())
if PID then
return net.get_player_info(tonumber(PID), Attribute)
else
return nil
end
end

View File

@ -31,6 +31,7 @@
-- ### Contributions: -- ### Contributions:
-- --
-- * **Entropy**, **Afinegan**: Came up with the requirement for AIOnOff(). -- * **Entropy**, **Afinegan**: Came up with the requirement for AIOnOff().
-- * **Applevangelist**: various
-- --
-- === -- ===
-- --
@ -45,12 +46,16 @@
--- Wrapper class of the DCS world Group object. --- Wrapper class of the DCS world Group object.
-- --
-- ## Finding groups
--
-- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance:
-- --
-- * @{#GROUP.Find}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group object. -- * @{#GROUP.Find}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group object.
-- * @{#GROUP.FindByName}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group name. -- * @{#GROUP.FindByName}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group name.
-- * @{#GROUP.FindByMatching}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using pattern matching.
-- * @{#GROUP.FindAllByMatching}(): Find all GROUP instances from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using pattern matching.
-- --
-- # 1. Tasking of groups -- ## Tasking of groups
-- --
-- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}). -- A GROUP is derived from the wrapper class CONTROLLABLE (@{Wrapper.Controllable#CONTROLLABLE}).
-- See the @{Wrapper.Controllable} task methods section for a description of the task methods. -- See the @{Wrapper.Controllable} task methods section for a description of the task methods.
@ -285,7 +290,7 @@ function GROUP:Find( DCSGroup )
return GroupFound return GroupFound
end end
--- Find the created GROUP using the DCS Group Name. --- Find a GROUP using the DCS Group Name.
-- @param #GROUP self -- @param #GROUP self
-- @param #string GroupName The DCS Group Name. -- @param #string GroupName The DCS Group Name.
-- @return #GROUP The GROUP. -- @return #GROUP The GROUP.
@ -295,6 +300,55 @@ function GROUP:FindByName( GroupName )
return GroupFound return GroupFound
end end
--- Find the first(!) GROUP matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #GROUP self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
-- @return #GROUP The GROUP.
-- @usage
-- -- Find a group with a partial group name
-- local grp = GROUP:FindByMatching( "Apple" )
-- -- will return e.g. a group named "Apple-1-1"
--
-- -- using a pattern
-- local grp = GROUP:FindByMatching( ".%d.%d$" )
-- -- will return the first group found ending in "-1-1" to "-9-9", but not e.g. "-10-1"
function GROUP:FindByMatching( Pattern )
local GroupFound = nil
for name,group in pairs(_DATABASE.GROUPS) do
if string.match(name, Pattern ) then
GroupFound = group
break
end
end
return GroupFound
end
--- Find all GROUP objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #GROUP self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
-- @return #table Groups Table of matching #GROUP objects found
-- @usage
-- -- Find all group with a partial group name
-- local grptable = GROUP:FindAllByMatching( "Apple" )
-- -- will return all groups with "Apple" in the name
--
-- -- using a pattern
-- local grp = GROUP:FindAllByMatching( ".%d.%d$" )
-- -- will return the all groups found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10"
function GROUP:FindAllByMatching( Pattern )
local GroupsFound = {}
for name,group in pairs(_DATABASE.GROUPS) do
if string.match(name, Pattern ) then
GroupsFound[#GroupsFound+1] = group
end
end
return GroupsFound
end
-- DCS Group methods support. -- DCS Group methods support.
--- Returns the DCS Group. --- Returns the DCS Group.

View File

@ -5,7 +5,7 @@
-- === -- ===
-- --
-- ### Author: **Applevangelist** -- ### Author: **Applevangelist**
-- # Last Update June 2023 -- # Last Update Oct 2023
-- --
-- === -- ===
-- --
@ -43,7 +43,7 @@ do
-- @field #NET -- @field #NET
NET = { NET = {
ClassName = "NET", ClassName = "NET",
Version = "0.1.2", Version = "0.1.3",
BlockTime = 600, BlockTime = 600,
BlockedPilots = {}, BlockedPilots = {},
BlockedUCIDs = {}, BlockedUCIDs = {},
@ -470,11 +470,9 @@ end
-- @return #number PlayerID or nil -- @return #number PlayerID or nil
function NET:GetPlayerIDByName(Name) function NET:GetPlayerIDByName(Name)
if not Name then return nil end if not Name then return nil end
local playerList = self:GetPlayerList() local playerList = net.get_player_list()
self:T({playerList})
for i=1,#playerList do for i=1,#playerList do
local playerName = net.get_name(i) local playerName = net.get_name(i)
self:T({playerName})
if playerName == Name then if playerName == Name then
return playerList[i] return playerList[i]
end end

View File

@ -4,7 +4,7 @@
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- ### Contributions: -- ### Contributions: **funkyfranky
-- --
-- === -- ===
-- --
@ -12,12 +12,13 @@
-- @image MOOSE.JPG -- @image MOOSE.JPG
--- @type OBJECT --- OBJECT class.
-- @type OBJECT
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
-- @field #string ObjectName The name of the Object. -- @field #string ObjectName The name of the Object.
--- Wrapper class to hendle the DCS Object objects. --- Wrapper class to handle the DCS Object objects.
-- --
-- * Support all DCS Object APIs. -- * Support all DCS Object APIs.
-- * Enhance with Object specific APIs not in the DCS Object API set. -- * Enhance with Object specific APIs not in the DCS Object API set.
@ -43,9 +44,15 @@ OBJECT = {
-- @param #OBJECT self -- @param #OBJECT self
-- @param DCS#Object ObjectName The Object name -- @param DCS#Object ObjectName The Object name
-- @return #OBJECT self -- @return #OBJECT self
function OBJECT:New( ObjectName, Test ) function OBJECT:New( ObjectName)
-- Inherit BASE class.
local self = BASE:Inherit( self, BASE:New() ) local self = BASE:Inherit( self, BASE:New() )
-- Debug output.
self:F2( ObjectName ) self:F2( ObjectName )
-- Set object name.
self.ObjectName = ObjectName self.ObjectName = ObjectName
return self return self
@ -64,15 +71,14 @@ function OBJECT:GetID()
return ObjectID return ObjectID
end end
BASE:E( { "Cannot GetID", Name = self.ObjectName, Class = self:GetClassName() } ) self:E( { "Cannot GetID", Name = self.ObjectName, Class = self:GetClassName() } )
return nil return nil
end end
--- Destroys the OBJECT. --- Destroys the OBJECT.
-- @param #OBJECT self -- @param #OBJECT self
-- @return #boolean true if the object is destroyed. -- @return #boolean Returns `true` if the object is destroyed or #nil if the object is nil.
-- @return #nil The DCS Unit is not existing or alive.
function OBJECT:Destroy() function OBJECT:Destroy()
local DCSObject = self:GetDCSObject() local DCSObject = self:GetDCSObject()
@ -83,7 +89,7 @@ function OBJECT:Destroy()
return true return true
end end
BASE:E( { "Cannot Destroy", Name = self.ObjectName, Class = self:GetClassName() } ) self:E( { "Cannot Destroy", Name = self.ObjectName, Class = self:GetClassName() } )
return nil return nil
end end

View File

@ -169,7 +169,9 @@ function STORAGE:New(AirbaseName)
self.airbase=Airbase.getByName(AirbaseName) self.airbase=Airbase.getByName(AirbaseName)
if Airbase.getWarehouse then
self.warehouse=self.airbase:getWarehouse() self.warehouse=self.airbase:getWarehouse()
end
self.lid = string.format("STORAGE %s", AirbaseName) self.lid = string.format("STORAGE %s", AirbaseName)

View File

@ -13,7 +13,7 @@
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- ### Contributions: **funkyfranky** -- ### Contributions: **funkyfranky**, **Applevangelist**
-- --
-- === -- ===
-- --
@ -42,6 +42,8 @@
-- --
-- * @{#UNIT.Find}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit object. -- * @{#UNIT.Find}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit object.
-- * @{#UNIT.FindByName}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit name. -- * @{#UNIT.FindByName}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit name.
-- * @{#UNIT.FindByMatching}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a pattern.
-- * @{#UNIT.FindAllByMatching}(): Find all UNIT instances from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a pattern.
-- --
-- IMPORTANT: ONE SHOULD NEVER SANITIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). -- IMPORTANT: ONE SHOULD NEVER SANITIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil).
-- --
@ -160,6 +162,55 @@ function UNIT:FindByName( UnitName )
return UnitFound return UnitFound
end end
--- Find the first(!) UNIT matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #UNIT self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
-- @return #UNIT The UNIT.
-- @usage
-- -- Find a group with a partial group name
-- local unit = UNIT:FindByMatching( "Apple" )
-- -- will return e.g. a group named "Apple-1-1"
--
-- -- using a pattern
-- local unit = UNIT:FindByMatching( ".%d.%d$" )
-- -- will return the first group found ending in "-1-1" to "-9-9", but not e.g. "-10-1"
function UNIT:FindByMatching( Pattern )
local GroupFound = nil
for name,group in pairs(_DATABASE.UNITS) do
if string.match(name, Pattern ) then
GroupFound = group
break
end
end
return GroupFound
end
--- Find all UNIT objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #UNIT self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
-- @return #table Units Table of matching #UNIT objects found
-- @usage
-- -- Find all group with a partial group name
-- local unittable = UNIT:FindAllByMatching( "Apple" )
-- -- will return all units with "Apple" in the name
--
-- -- using a pattern
-- local unittable = UNIT:FindAllByMatching( ".%d.%d$" )
-- -- will return the all units found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10"
function UNIT:FindAllByMatching( Pattern )
local GroupsFound = {}
for name,group in pairs(_DATABASE.UNITS) do
if string.match(name, Pattern ) then
GroupsFound[#GroupsFound+1] = group
end
end
return GroupsFound
end
--- Return the name of the UNIT. --- Return the name of the UNIT.
-- @param #UNIT self -- @param #UNIT self
-- @return #string The UNIT name. -- @return #string The UNIT name.

View File

@ -367,7 +367,7 @@ function WEAPON:GetTarget()
if object then if object then
-- Get object category. -- Get object category.
local category=object:getCategory() local category=Object.getCategory(object)
--Target name --Target name
local name=object:getName() local name=object:getName()

View File

@ -1,80 +1,21 @@
[![Moose-Includes](https://github.com/FlightControl-Master/MOOSE/actions/workflows/build-includes.yml/badge.svg?branch=master)](https://github.com/FlightControl-Master/MOOSE/actions/workflows/build-includes.yml) [![Moose-Includes](https://github.com/FlightControl-Master/MOOSE/actions/workflows/build-includes.yml/badge.svg?branch=master)](https://github.com/FlightControl-Master/MOOSE/actions/workflows/build-includes.yml)
# MOOSE framework <img src="https://github.com/FlightControl-Master/MOOSE/blob/master/docs/images/classes/overview.jpg" alt="MOOSE" style="width:600px;"/>
MOOSE is a **M**ission **O**bject **O**riented **S**cripting **E**nvironment, and is meant for mission designers in DCS World. You can find documentation for MOOSE in the following places:
It allows to quickly setup complex missions using pre-scripted scenarios using the available classes within the MOOSE Framework.
- Generated documentation of all MOOSE classes:
- For the `master` branch: [MOOSE_DOCS]
- For the `develop` branch: [MOOSE_DOCS_DEVELOP]
- Documentation:
- The old Guides can be found in our [archive].
- Visit our new documentation at the [MOOSE GitHub page].
- Overview of all [MOOSE repositories] on GitHub.
## MOOSE Framework Goal <br/>
The goal of MOOSE is to allow mission designers to enhance their scripting with mission orchestration objects, which can be instantiated from defined classes within the framework. This will allow to write mission scripts with minimal code embedded. Of course, the richness of the framework will determine the richness of the misson scenarios.
The MOOSE is a service that is produced while being consumed ... , it will evolve further as more classes are developed for the framework, and as more users are using it.
MOOSE is not a one-man show, it is a collaborative effort and meant to evolve within a growing community around the framework.
Within the community, key users will start supporting, documenting, explaining and even creating new classes for the framework.
It is the ambition to grow this framework as a de-facto standard for mission designers to use.
## MOOSE Repositories
The underlying picture documents the different repositories in the MOOSE framework. The white ones are edited and are the source of the framework.
The red ones contain generated artefacts. See further the explanation for each repository.
![Graphic](https://raw.githubusercontent.com/FlightControl-Master/MOOSE_DOCS/master/Configuration/Master.png)
### [MOOSE](https://github.com/FlightControl-Master/MOOSE) - For edit and development
This repository contains the source lua code of the MOOSE framework.
### [MOOSE_INCLUDE](https://github.com/FlightControl-Master/MOOSE_INCLUDE) - For use and generated
This repository contains the Moose.lua file to be included within your missions. Note that the Moose\_.lua is technically the same as Moose.lua, but without any commentary or unnecessary whitespace in it. You only need to load **one** of those at the beginning of your mission.
### [MOOSE_DOCS](https://github.com/FlightControl-Master/MOOSE_DOCS) - Not for use
This repository contains the generated documentation and pictures and other references. The generated documentation is reflected in html and is published at: https://flightcontrol-master.github.io/MOOSE_DOCS/
### [MOOSE_MISSIONS](https://github.com/FlightControl-Master/MOOSE_MISSIONS) - For use and generated
This repository contains all the demonstration missions in packed format (*.miz), and can be used without any further setup in DCS WORLD.
### [MOOSE_MISSIONS_DYNAMIC](https://github.com/FlightControl-Master/MOOSE_MISSIONS_DYNAMIC) - For use and generated
This repository contains all the demonstration missions in packed format (*.miz), but MOOSE is dynamically loaded from your disk! These missions are to be used by beta testers of the MOOSE framework and are not for end uers!!!!
### [MOOSE_MISSIONS_UNPACKED](https://github.com/FlightControl-Master/MOOSE_MISSIONS_UNPACKED) - For edit and development
This repository contains all the demonstration missions in unpacked format. That means that there is no .miz file included, but all the .miz contents are unpacked.
## [MOOSE Web Site](https://flightcontrol-master.github.io/MOOSE_DOCS/)
Documentation on the MOOSE class hierarchy, usage guides and background information can be found here for normal users, beta testers and contributors.
![Click on this link to browse to the MOOSE main web page.](https://raw.githubusercontent.com/FlightControl-Master/MOOSE_DOCS/master/Configuration/Site.png)
## [MOOSE Youtube Tutorials](https://youtube.com/playlist?list=PLLkY2GByvtC2ME0Q9wrKRDE6qnXJYV3iT)
Pene has kindly created a [tutorial series for MOOSE](https://youtube.com/playlist?list=PLLkY2GByvtC2ME0Q9wrKRDE6qnXJYV3iT)
with various videos that you can watch.
## [MOOSE on Discord](https://discord.gg/aQtjcR94Qf)
MOOSE has a living (chat and video) community of users, beta testers and contributors. The gathering point is a service provided by discord.com. If you want to join this community, just click Discord and you'll be on board in no time.
Kind regards,
The Moose Team
[MOOSE_DOCS]: https://flightcontrol-master.github.io/MOOSE_DOCS/Documentation/index.html
[MOOSE_DOCS_DEVELOP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/index.html
[archive]: https://flightcontrol-master.github.io/MOOSE/archive/
[MOOSE GitHub page]: https://flightcontrol-master.github.io/MOOSE/
[MOOSE repositories]: https://flightcontrol-master.github.io/MOOSE/repositories.html

View File

@ -33,4 +33,13 @@ callouts_opacity: 0.4
aux_links: aux_links:
GitHub: https://github.com/FlightControl-Master/MOOSE GitHub: https://github.com/FlightControl-Master/MOOSE
Discord: https://discord.gg/aQtjcR94Qf Discord: https://discord.gg/gj68fm969S
kramdown:
syntax_highlighter_opts:
block:
line_numbers: true
compress_html:
ignore:
envs: all

View File

@ -0,0 +1,93 @@
---
title: De-Sanitize DCS
parent: Advanced
nav_order: 2
---
# De-Sanitize the DCS scripting environment
{: .no_toc }
1. Table of contents
{:toc}
De-Sanitize is the a modification performed by the user which disables some
security features of DCS. Without de-sanitizing not all functions of Moose
are available. Let's take a closer look and explain the details:
- In the File-Explorer, navigate to your DCS main [installation folder].
- Navigate to the folder `Scripts` and open the file `MissionScripting.lua` with
a good editor like [Notepad++]{:target="_blank"}.
The original file should look like this:
```lua
--Initialization script for the Mission lua Environment (SSE)
dofile('Scripts/ScriptingSystem.lua')
-- Sanitize Mission Scripting environment
-- This makes unavailable some unsecure functions.
-- Mission downloaded from server to client may contain potentialy harmful lua code
-- that may use these functions.
-- You can remove the code below and make availble these functions at your own risk.
local function sanitizeModule(name)
_G[name] = nil
package.loaded[name] = nil
end
do
sanitizeModule('os')
sanitizeModule('io')
sanitizeModule('lfs')
_G['require'] = nil
_G['loadlib'] = nil
_G['package'] = nil
end
```
In line 17, 18 and 19 the method `sanitizeModule` disables the modules `os`, `io` and `lfs`.
{: .warning }
> This is a security feature to avoid harmfull actions to be executed from
> inside a mission.
>
> ***Disable this on your own risk!***
If the lines will be disabled the lua code inside of missions can use the
following functionality again:
- `os` (at line 17):
- Execution of commands from the operation system is allowed again.
This is needed by some Classes when using [Text-To-Speech] with [SRS]{:target="_blank"}.
But in theory it can also run harmful commands.
- `io` and `lfs` (at line 18 & 19):
- Different libraries to access files on your hard disk or do other io
operations. This is needed by some clases if you want to save and/or
read data. Like persistance for CSAR.
But it may be abused to access or modify sensitive files owned by the user.
If you put two dashes (`--`) in front of each of the lines 17 - 19 the
protection is disabled and the lower part of the file should look this:
```lua
do
--sanitizeModule('os')
--sanitizeModule('io')
--sanitizeModule('lfs')
_G['require'] = nil
_G['loadlib'] = nil
_G['package'] = nil
end
```
Save the file and it will enable the DCS Lua sandbox to access stuff on your computer.
{: .note }
> After each update of DCS you need to repeat this because each update will
> overwrite this file by default.
[installation folder]: ../beginner/tipps-and-tricks.md#find-the-installation-folder-of-dcs
[Notepad++]: https://notepad-plus-plus.org/downloads/
[Text-To-Speech]: text-to-speech.md
[SRS]: https://github.com/ciribob/DCS-SimpleRadioStandalone/releases/latest

View File

@ -0,0 +1,84 @@
---
parent: Advanced
nav_order: 1
---
# Eclipse Installation
{: .no_toc }
1. Table of contents
{:toc}
This guide describes how to install [Eclipse] and install the necessary [Lua]
environment.
{: .note }
> Note that the [Lua] environment is not actively supported any more
> by Oracle. Especially the LDT plugin is not working when installed from the
> market place. The problem and solution is nicely described [in this topic].
## Prerequisites
* Download Eclipse from [eclipse.org].
* Download [dltk-core].
* Download or clone [MOOSE repository] (select branch you want `master` or `develop`).
## Install Eclipse
First you need to install [Eclipse]. It will ask you what kind of environment
you use, *e.g.* C++ or Java or something else. This does not really matter since
we want to use it for Lua and need to install the plugin for [Lua] later.
## Install dltk-core
Before you can install the LDT plugin, you first need to add dltk-core zip file
to the available software sites. Open eclipse, go to the help menu and follow
the steps in the image:
![eclipse-install-ldk-1](../images/install/eclipse/ldk-1.png)
This should then be in the available software sites.
![eclipse-install-ldk-2](../images/install/eclipse/ldk-2.png)
## Install LDT Plugin
Open eclipse and from the "Help" menu open the "Eclipse Marketplase":
![Eclipse-Install_Lua_1](../images/install/eclipse/lua-1.png)
In the "Search" tab find "lua" and install the "Lua Development Tools 1.4.x":
![Eclipse-Install_Lua_2](../images/install/eclipse/lua-2.png)
## Setup Lua Project for MOOSE
Now that Eclipse and LDT are installed, we need to add MOOSE as a LUA project.
Open Eclipse and from the "File" menu select "Other":
![Eclipse-Lua_Project_1](../images/install/eclipse/project-1.png)
In the wizard window that opens select "Lua Project":
![Eclipse-Lua_Project_2](../images/install/eclipse/project-2.png)
Setup the Lua project as described in the image. You need to specify the path to
where you downloaded the MOOSE repository:
![Eclipse-Lua_Project_3a](../images/install/eclipse/project-3.png)
From the "Project" tab select "Properties" and add `Moose/Moose Development/Moose`
to the build path as shown below:
![Eclipse-Lua_Project_4](../images/install/eclipse/project-4.png)
## Finally
Now you are done!
Check that your script explorer looks like in the image below and that the
intellisense is working when you open a MOOSE file:
![Eclipse-Lua_Project_5](../images/install/eclipse/project-5.png)
[Eclipse]: https://www.eclipse.org
[Lua]: https://www.lua.org/
[eclipse.org]: https://www.eclipse.org/downloads/
[dltk-core]: https://www.eclipse.org/downloads/download.php?file=/technology/dltk/downloads/drops/R5.7/R-5.7.1-201703020501/dltk-core-R-5.7.1-201703020501.zip
[MOOSE repository]: https://github.com/FlightControl-Master/MOOSE/
[in this topic]: https://www.eclipse.org/forums/index.php/t/1101907/

20
docs/advanced/index.md Normal file
View File

@ -0,0 +1,20 @@
---
has_children: true
nav_order: 3
---
# Advanced
In this section we will add the documentation for all subjects that go beyond
the beginner topics, but which are interesting for mission builders or power
users.
{: .note }
> This documentation is WIP (work in progress) and it will take some time to
> fill it with usefull and up to date informations. Please be patient and check
> back here from time to time to see if there is anything new for you.
If you cannot find the information you are looking for here in the new
documentation, please take a look at the [archive].
[archive]: ../archive/index.md

View File

@ -0,0 +1,159 @@
---
parent: Advanced
nav_order: 2
---
# Text to Speech
{: .no_toc }
1. Table of contents
{:toc}
This guide describes how to configure and use [Text-To-Speech{:target="_blank"}
(or TTS) with MOOSE. We use [DCS Simple Radio Standalone] (DCS-SRS) to generate
the audio and send it to the client. SRS is a well known VOIP client simulating
a radio in DCS.
{: .note }
> Only clients which uses SRS are able to hear the generated radio calls.
> This is not compatible with the in game VOIP audio system from Eagle Dynamics!
## Prerequisites
- Download and install [DCS Simple Radio Standalone]{:target="_blank"} (DCS-SRS).
- Use a good text editor like [Notepad++]{:target="_blank"}.
- Create a simple test mission with Moose included and a "... from parking hot"
airplane or helicopter.
- [De-Sanitize the DCS scripting environment].
## Start SR-Server and connect the client
- Navigate to the install directory of SRS.
- As default it should be located here: `C:\Program Files\DCS-SimpleRadio-Standalone`
- We are interested in the executable files:
![srs-executables](../images/install/text-to-speech/srs-executables.png)
- Start the server by double click on `SR-Server.exe`.<br />
It should looks like this:
![srs-server](../images/install/text-to-speech/srs-server.png)
- Start the `SR-ClientRadio.exe`.
- Connect to the local server:
- Use the port shown in the server window (default is 5002).
- Use the ip of the windows loopback device (which is 127.0.0.1).
- Example: `127.0.0.1:5002`
![srs-client](../images/install/text-to-speech/srs-client.png)
- If asked if you want to allow changes to your PC, say yes.
- After you clicked on Connect and some seconds the status should look like this:
![srs-status-1](../images/install/text-to-speech/srs-status-1.png)
- Your server UI now shows 1 connected client.
- Click on „toggle radio overlay“ on the client. A small grey window will pop-up.
## Start DCS World and your test mission
- Jump into a plane or helicopter.
- The connection status on the client UI and overlay should be changing
and shows the available radios of the module and it's frequencies:
![srs-overlay](../images/install/text-to-speech/srs-overlay.png)
- The third green connector on the client UI should be green now:
![srs-status-2](../images/install/text-to-speech/srs-status-2.png)
## Command line test with Power Shell
- Use the search icon in windows to locate and start `PowerShell`, youll get a
blue terminal window:
![powershell-1](../images/install/text-to-speech/powershell-1.png)
- Now navigate in PowerShell to the SRS install folderwith the following command:
`cd 'C:\Program Files\DCS-SimpleRadio-Standalone\'`
{: .note }
> Change the path if you choose another installation directory for SRS.
- Type `dir` and press enter to get a listing of all files in the directory.
- `DCS-SR-ExternalAudio.exe` should be amongst them.
![powershell-2](../images/install/text-to-speech/powershell-2.png)
- Now we are going to create a text-to-speech command which should be sent to
the radio on your airplane or helicopter.
- The parameter `-t` will define the text to send.
- The frequency will be defined with `-f`. Adopt it to match the frequency of
your airplane or helicopter! For example 251.
- And the modulation is set by `-m`. For example AM.
- Define the coalition with `-c`. 0 is Spectator, 1 is Red, 2 is Blue.
`.\DCS-SR-ExternalAudio.exe -t "Hello Moosers" -f 251 -m AM -c 2`
- The console output should look like this:
![powershell-3](../images/install/text-to-speech/powershell-3.png)
**If you can hear the voice on the cockpit radio, you are done!**
If you get UpnP/Network errors, you need to allow DCS-SR-ExternalAudio.exe to
traverse your firewall.
{: .note }
> You can raun `DCS-SR-ExternalAudio.exe` without any parameters to get help.
## Firewall Setup
- On Windows search, type Firewall and open „Firewall- and Network Protection“.
Click on „Extended Setting“ (you need admin rights to do that).
- You will need two incoming and two outgoing rules (4 overall), right-click on
incoming/outgoing rules to create new rules.
- Give the rule a nice name:
- Protocols and Services you need to create ONE rule for TCP and another one
for UDP. Select TCP from the drop down:
- On Programs and Services, enable 'this program' and use search to locate and
select DCS-SR-ExternalAudio.exe:
- Click „ok“ to save and close the rule.
- Repeat for UDP.
- Repeat twice for outgoing, one for TCP and one for UDP.
- Youre done and can return to 'Command line test'.
## Google TTS
- For Google TTS you need to have a Google Cloud Account (a testing one will do).
- You can start here: <https://cloud.google.com/text-to-speech/>
- You need to create a projekt and enable the 'Cloud Text-To-Speech API' in it.
- You also need to create a service-account and create a `.json` key file for it.
Theres a lot of supporting information on the Google Cloud Site to help you
with that. Similar to 'Command line test', you can test your setup on the
command line. Here is an example that assumed your .json key file resides in the
SRS directory:
`.\DCS-SR-ExternalAudio.exe -t "Hello Moosers" -f 251 -m AM -c 2 -z -G .\yourgoogleaccount.json`
[Text-To-Speech]: https://en.wikipedia.org/wiki/Speech_synthesis
[DCS Simple Radio Standalone]: https://github.com/ciribob/DCS-SimpleRadioStandalone/releases/latest
[De-Sanitize the DCS scripting environment]: desanitize-dcs.md
[Notepad++]: https://notepad-plus-plus.org/downloads/

181
docs/archive/classes-ai.md Normal file
View File

@ -0,0 +1,181 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 1
---
# AI classes guide
## 1. A2A Dispatching
### 1.1. [AI A2A Dispatcher]
![AI A2A Dispatcher](../images/classes/ai/a2a-dispatcher.jpg)
Create an **A2A defense system** executed by AI to perform CAP or GCI to defend your airspace.
There are two classes that are important to learn:
* [AI_A2A_GCICAP]
* [AI_A2A_DISPATCHER]
The [AI_A2A_GCICAP] is a class for **novice mission designers**,
so I recommend novice users to start with using this class.
You can quickly configure a working GCICAP process.
But it will provide less flexibility and options.
If you want more options, use the [AI_A2A_DISPATCHER].
**Features:**
* Setup quickly an A2A defense system for a coalition.
* Setup (CAP) Control Air Patrols at defined zones to enhance your A2A defenses.
* Setup (GCI) Ground Control Intercept at defined airbases to enhance your A2A defenses.
* Define and use an EWR (Early Warning Radar) network.
* Define squadrons at airbases.
* Enable airbases for A2A defenses.
* Add different plane types to different squadrons.
* Add multiple squadrons to different airbases.
* Define different ranges to engage upon intruders.
* Establish an automatic in air refuel process for CAP using refuel tankers.
* Setup default settings for all squadrons and A2A defenses.
* Setup specific settings for specific squadrons.
* Quickly setup an A2A defense system using AI_A2A_GCICAP.
* Setup a more advanced defense system using AI_A2A_DISPATCHER.
## 2. AI Cargo Dispatching
Cargo dispatching will make the AI to transport cargo to deploy zones.
Cargo can be transported by APC or trucks, or by helicopters.
**Overall Features:**
* Quickly transport cargo to various deploy zones using different carrier types.
* Various cargo types can be transported. These are infantry groups and crates.
* Define a list of deploy zones of various types to transport the cargo to.
* Multiple carrier groups can be enabled as one collaborating transportation process.
* Different options can be setup to tweak the cargo transporation behaviour.
* Home location that will be used for carrier parking, when all cargo has been transported.
* Automatic activation of carriers when new cargo is to be picked-up (of cargo is spawned for example).
### 2.1. [AI Cargo Dispatching for APC]
![AI_Cargo_Dispatcher_APC](../images/classes/ai/cargo-dispatcher-apc.jpg)
Models the intelligent transportation of infantry and other cargo using **APCs or trucks**.
**Specific Features:**
* The vehicles follow the roads to ensure the fastest possible cargo transportation over the ground.
* Multiple vehicles can transport multiple cargo as one vehicle group.
* Infantry loaded as cargo, will unboard in case enemies are nearby and will help defending the vehicles.
* Different ranges can be setup for enemy defenses.
### 2.2. [AI Cargo Dispatching for Helicopters]
![AI_Cargo_Dispatcher_Helicopter](../images/classes/ai/cargo-dispatcher-helicopters.jpg)
Models the intelligent transportation of infantry and other cargo using **Helicopters**.
**Specific Features:**
* The helicopters will fly towards the pickup locations to pickup the cargo.
* The helicopters will fly towards the deploy zones to deploy the cargo.
* Precision deployment as well as randomized deployment within the deploy zones are possible.
* Helicopters will orbit the deploy zones when there is no space for landing until the deploy zone is free.
## 3. [AI Balancing]
![AI_Balancer](../images/classes/ai/balancer.jpg)
Balance player slots with AI to create an engaging simulation environment, independent of the amount of players.
**Features:**
* Automatically spawn AI as a replacement of free player slots for a coalition.
* Make the AI to perform tasks.
* Define a maximum amount of AI to be active at the same time.
* Configure the behaviour of AI when a human joins a slot for which an AI is active.
## 4. [AI Large Formations]
![AI_Formation](../images/classes/ai/formation.jpg)
Build large airborne formations of aircraft.
**Features:**
* Build in-air formations consisting of more than 40 aircraft as one group.
* Build different formation types.
* Assign a group leader that will guide the large formation path.
## 5. AI engagement
### 5.1. [AI Patrolling]
![AI_Patrol](../images/classes/ai/patrol.jpg)
Peform Air Patrolling for airplanes within a patrol zone.
**Features:**
* Patrol AI airplanes within a given zone.
* Trigger detected events when enemy airplanes are detected.
* Manage a fuel treshold to RTB on time.
### 5.2. [AI Combat Air Patrolling]
![AI_Patrol](../images/classes/ai/cap.jpg)
Peform Combat Air Patrolling (CAP) for airplanes within a patrol zone.
**Features:**
* Patrol AI airplanes within a given zone.
* Trigger detected events when enemy airplanes are detected.
* Manage a fuel treshold to RTB on time.
* Engage the enemy when detected.
### 5.3. [AI Close Air Support]
![AI_Patrol](../images/classes/ai/a2g-cas.jpg)
Peform Close Air Support (CAS) near friendlies within an engagement zone.
**Features:**
* Hold and standby within a patrol zone.
* Engage upon command the enemies within an engagement zone.
* Loop the zone until all enemies are eliminated.
* Trigger different events upon the results achieved.
* After combat, return to the patrol zone and hold.
* RTB when commanded or after out of fuel.
### 5.4. [AI Battlefield Air Interdiction]
![AI_Patrol](../images/classes/ai/bai.jpg)
Peform Battlefield Air Interdiction (BAI) within an engagement zone.
**Features:**
* Hold and standby within a patrol zone.
* Engage upon command the assigned targets within an engagement zone.
* Loop the zone until all targets are eliminated.
* Trigger different events upon the results achieved.
* After combat, return to the patrol zone and hold.
* RTB when commanded or after out of fuel.
[AI A2A Dispatcher]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_A2A_Dispatcher.html
[AI_A2A_GCICAP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_A2A_Dispatcher.html#AI_A2A_GCICAP
[AI_A2A_DISPATCHER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_A2A_Dispatcher.html#AI_A2A_DISPATCHER
[AI Cargo Dispatching for APC]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_APC.html
[AI Cargo Dispatching for Helicopters]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_Helicopter.html
[AI Balancing]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Balancer.html
[AI Large Formations]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Formation.html
[AI Patrolling]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Patrol.html
[AI Combat Air Patrolling]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_CAP.html
[AI Close Air Support]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_CAS.html
[AI Battlefield Air Interdiction]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_BAI.html
[AI Patrolling]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Patrol.html

View File

@ -0,0 +1,263 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 3
---
# Cargo classes guide
![MOOSE CARGO](../images/classes/category-cargo.jpg)
MOOSE implements a whole enhanced mechanism to **create virtual cargo** within your missions.
Within this system, virtual cargo can be represented by:
* Moveable cargo, represented by **groups of units**. It can be **boarded** into **carriers**, which can be
**APCs or vehicles**, **helicopters**, **planes** or **ships**.
* Stationary cargo, reprented by **static objects** or **static cargo objects**. It can be loaded into **carriers**,
which can also be **APCs** or **vehicles**, **helicopters**, **planes** or **ships**.
* Sling loadable cargo, reprented by **static cargo objects**. It can be sling loaded by **helicopter carriers**.
In order to use the MOOSE cargo management system, you'll need to declare cargo objects as part of your mission
script and setup either an **AI or a human cargo (task) dispatcher** to transport this virtual cargo around the
battlefield. For this, several MOOSE classes have been created for cargo dispatchment, which are listed below.
Click on each individual MOOSE class for detailed features and usage explanations, which are part of the detailed MOOSE
class documentation.
## 1. [WAREHOUSE]
![WAREHOUSE](../images/classes/functional/warehouse.jpg)
The MOOSE warehouse concept simulates the organization and implementation of complex operations regarding the flow of
assets between the point of origin and the point of consumption in order to meet requirements of a potential conflict.
In particular, this class is concerned with maintaining army supply lines while disrupting those of the enemy, since an
armed force without resources and transportation is defenseless.
**Features:**
* Holds (virtual) assests in stock and spawns them upon request.
* Manages requests of assets from other warehouses.
* Queueing system with optional priorization of requests.
* Realistic transportation of assets between warehouses.
* Different means of automatic transportation (planes, helicopters, APCs, self propelled).
* Strategic components such as capturing, defending and destroying warehouses and their associated infrastructure.
* Intelligent spawning of aircraft on airports (only if enough parking spots are available).
* Possibility to hook into events and customize actions.
* Can be easily interfaced to other MOOSE classes.
Please note that his class is work in progress and in an **alpha** stage.
**Video:**
[![Warehouse](https://img.youtube.com/vi/e98jzLi5fGk/0.jpg)](https://youtu.be/e98jzLi5fGk "Warehouse")
## 2. [AI_CARGO_DISPATCHER]
![AI_CARGO_DISPATCHER](../images/classes/ai/cargo-dispatcher.jpg)
This section details the classes that you can use to setup an automatic cargo dispatching system that will make
AI carriers transport cargo (automatically) through the battlefield. Depending on the type of AI unit types, various
classes are implemented.
However, this class is the **BASE class** and contains the main functionality for the underlying more detailed
implementation classes. So, please read the documentation of the AI_CARGO_DISPATCHER class first (by clicking on it!)
### 2.1. [AI_CARGO_DISPATCHER_APC]
![AI_Cargo_Dispatcher_APC](../images/classes/ai/cargo-dispatcher-apc.jpg)
Models the intelligent transportation of **infantry** and other **small or lightweight cargo** using **APCs or trucks**.
This class models cargo to be transported between **zones**!
**Features:**
* The vehicles follow the roads to ensure the fastest possible cargo transportation over the ground.
* Multiple vehicles can transport multiple cargo as one vehicle group.
* Infantry loaded as cargo, will unboard in case enemies are nearby and will help defending the vehicles.
* Different ranges can be setup for enemy defenses.
### 2.2. [AI_CARGO_DISPATCHER_HELICOPTER]
![AI_Cargo_Dispatcher_Helicopter](../images/classes/ai/cargo-dispatcher-helicopters.jpg)
Models the intelligent transportation of **infantry** and other **small cargo** using **Helicopters**.
This class models cargo to be transported between **zones**!
**Features:**
* The helicopters will fly towards the pickup locations to pickup the cargo.
* The helicopters will fly towards the deploy zones to deploy the cargo.
* Precision deployment as well as randomized deployment within the deploy zones are possible.
* Helicopters will orbit the deploy zones when there is no space for landing until the deploy zone is free.
### 2.3. [AI_CARGO_DISPATCHER_AIRPLANE]
![AI_Cargo_Dispatcher_Airplane](../images/classes/ai/cargo-dispatcher-airplanes.jpg)
Models the intelligent transportation of **infantry, vehicles** and other **heavy cargo** using **Airplanes**.
This class models cargo to be transported between **airbases**!
**Features:**
* The airplanes will fly towards the pickup airbases to pickup the cargo.
* The airplanes will fly towards the deploy airbases to deploy the cargo.
---
## 3. Human cargo transportation dispatching.
Also **humans can achieve tasks** by to **transporting cargo** as part of a task or mission **goal**.
### 3.1. [TASK_CARGO_DISPATCHER]
![TASK_CARGO_DISPATCHER](../images/classes/tasking/cargo-dispatcher.jpg)
The [TASK_CARGO_DISPATCHER] allows you to setup various tasks for let human players transport cargo as part of a task.
The cargo dispatcher will implement for you mechanisms to create cargo transportation tasks:
* As setup by the mission designer.
* Dynamically create CSAR missions (when a pilot is downed as part of a downed plane).
* Dynamically spawn new cargo and create cargo taskings!
**Features:**
* Creates a task to transport @{Cargo.Cargo} to and between deployment zones.
* Derived from the TASK_CARGO class, which is derived from the TASK class.
* Orchestrate the task flow, so go from Planned to Assigned to Success, Failed or Cancelled.
* Co-operation tasking, so a player joins a group of players executing the same task.
**A complete task menu system to allow players to:**
* Join the task, abort the task.
* Mark the task location on the map.
* Provide details of the target.
* Route to the cargo.
* Route to the deploy zones.
* Load/Unload cargo.
* Board/Unboard cargo.
* Slingload cargo.
* Display the task briefing.
**A complete mission menu system to allow players to:**
* Join a task, abort the task.
* Display task reports.
* Display mission statistics.
* Mark the task locations on the map.
* Provide details of the targets.
* Display the mission briefing.
* Provide status updates as retrieved from the command center.
* Automatically assign a random task as part of a mission.
* Manually assign a specific task as part of a mission.
**A settings system, using the settings menu:**
* Tweak the duration of the display of messages.
* Switch between metric and imperial measurement system.
* Switch between coordinate formats used in messages: BR, BRA, LL DMS, LL DDM, MGRS.
* Different settings modes for A2G and A2A operations.
* Various other options.
---
## 4. The cargo system explained.
The following section provides a detailed explanation on the cargo system, how to use etc.
<https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.Cargo.html>
---
## 5. Cargo management classes.
MOOSE has implemented **a separate system for cargo handling**.
It combines the capabilities of DCS world to combine infantry groups, cargo static objects and static objects
as "cargo" objects. Cargo classes provides a new and enhanced way to handle cargo management and transportation.
In order to use these MOOSE cargo facilities, you'll have to declare those groups and static objects
in a special way within your scripts and/or within the mission editor.
The main [Cargo.Cargo] class is the base class for all the cargo management.
It contains the required functionality to load / board / unload / unboard cargo, and manage the state of each cargo
object. From this CARGO class are other CARGO_ classes derived, which inherit the properties and functions from CARGO,
but implement a specific process to handle specific cargo objects!
It is not the purpose to use directly the CARGO class within your missions.
However, consult the CARGO documention as it provides a comprehensive description on how to manage cargo within your
missions.
### 5.1. [CARGO_GROUP]
![CARGO_GROUP](../images/classes/cargo/cargogroup.jpg)
Management of **moveable** and **grouped** cargo logistics, which are based on a
[Wrapper.Group] object. Typical cargo of this type can be infantry or (small) vehicles.
**Features:**
* Board cargo into a carrier.
* Unboard cargo from a carrier.
* Automatic detection of destroyed cargo.
* Respawn cargo.
* Maintain cargo status.
* Communication of cargo through messages.
* Automatic declaration of group objects to be treated as MOOSE cargo in the mission editor!
### 5.2. [CARGO_CRATE]
![CARGO_CRATE](../images/classes/cargo/cargocrate.jpg)
Management of single cargo crates, which are based on a [Wrapper.Static] object. Typical cargo of this type can be
crates, oil barrels, wooden crates etc. The cargo can be ANY static type! So potentially also other types of static
objects can be treated as cargo! Like flags, tires etc.
**Features:**
* Loading / Unloading of cargo.
* Automatic detection of destroyed cargo.
* Respawn cargo.
* Maintain cargo status.
* Communication of cargo through messages.
* Automatic declaration of group objects to be treated as MOOSE cargo in the mission editor!
### 5.3. [CARGO_SLINGLOAD]
![CARGO_SLINGLOAD](../images/classes/cargo/cargoslingload.jpg)
Management of **sling loadable** cargo crates, which are based on a [Wrapper.Static] object. This cargo can only be
slingloaded.
**Features:**
* Slingload cargo.
* Automatic detection of destroyed cargo.
* Respawn cargo.
* Maintain cargo status.
* Communication of cargo through messages.
* Automatic declaration of group objects to be treated as MOOSE cargo in the mission editor!
### 5.4. [CARGO_UNIT]
Management of **moveable** units, which are based on a [Wrapper.Unit] object.
Note that this is an **Internal** class and is only mentioned here for reference!
[WAREHOUSE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Warehouse.html
[AI_CARGO_DISPATCHER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher.html
[AI_CARGO_DISPATCHER_APC]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_APC.html
[AI_CARGO_DISPATCHER_HELICOPTER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_Helicopter.html
[AI_CARGO_DISPATCHER_HELICOPTER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_Helicopter.html
[AI_CARGO_DISPATCHER_AIRPLANE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/AI.AI_Cargo_Dispatcher_Airplane.html
[TASK_CARGO_DISPATCHER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Tasking.Task_Cargo_Dispatcher.html
[CARGO_GROUP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.CargoGroup.html
[CARGO_CRATE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.CargoCrate.html
[CARGO_SLINGLOAD]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.CargoSlingload.html
[CARGO_UNIT]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.CargoUnit.html
[Cargo.Cargo]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Cargo.Cargo.html
[Wrapper.Group]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Group.html
[Wrapper.Static]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Static.html
[Wrapper.Unit]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Unit.html

View File

@ -0,0 +1,401 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 5
---
# Core classes guide
![MOOSE CORE](../images/classes/category-core.jpg)
This chapter lists the core classes, which enhance existing DCS capabilities, and are used throughout the framework.
Mission designers can use these core classes to enhance their scripting.
## 1. [BASE](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Base.html)
![BASE](../images/classes/core/base.jpg)
Wraps the DCS _Group_ objects.
**Features:**
* The construction and inheritance of MOOSE classes.
* The class naming and numbering system.
* The class hierarchy search system.
* The tracing of information or objects during mission execution for debuggin purposes.
* The subscription to DCS events for event handling in MOOSE objects.
* Object inspection.
**Remember, everything in moose derives from the BASe class.**
## 2. [DATABASE](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Database.html)
![DATABASE](../images/classes/core/database.jpg)
Manages several databases containing templates, mission objects, and mission information.
**Features:**
* During mission startup, scan the mission environment, and create / instantiate intelligently the different objects as defined within the mission.
* Manage database of DCS Group templates (as modelled using the mission editor).
- Group templates.
- Unit templates.
- Statics templates.
* Manage database of [Wrapper.Group] objects alive in the mission.
* Manage database of [Wrapper.Unit] objects alive in the mission.
* Manage database of [Wrapper.Static] objects alive in the mission.
* Manage database of players.
* Manage database of client slots defined using the mission editor.
* Manage database of airbases on the map, and from FARPs and ships as defined using the mission editor.
* Manage database of countries.
* Manage database of zone names.
* Manage database of hits to units and statics.
* Manage database of destroys of units and statics.
* Manage database of [Core.Zone] objects.
**These database contain all objects, you can filter these objects using sets.**
## 3. [EVENT](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Event.html)
![EVENT](../images/classes/core/event.jpg)
Models DCS event dispatching using a publish-subscribe model.
**Features:**
* Capture DCS events and dispatch them to the subscribed objects.
* Generate DCS events to the subscribed objects from within the code.
**Learn the event handling system, it will make your life much more easier while designing missions.**
## 4. [FSM](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Fsm.html)
![FSM](../images/classes/core/fsm.jpg)
FSM (Finite State Machine) are objects that model and control long lasting business processes and workflow.
**Features:**
* Provide a base class to model your own state machines.
* Trigger events synchronously.
* Trigger events asynchronously.
* Handle events before or after the event was triggered.
* Handle state transitions as a result of event before and after the state change.
* For internal moose purposes, further state machines have been designed:
- to handle controllables (groups and units).
- to handle tasks.
- to handle processes.
**Finite State Machines are a great asset within moose, it is used everywhere to create dynamic workflows!**
## 5. [GOAL](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Goal.html)
![GOAL](../images/classes/core/goal.jpg)
Models the process to achieve Goal(s). Derived classes implement the ways how the achievements can be realized.
**Features:**
* Define the goal.
* Monitor the goal achievement.
* Manage goal contribution by players.
**Define goals to provide your players with a challenge.**
## 6. [MENU](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Menu.html)
![MENU](../images/classes/core/menu.jpg)
Manage hierarchical menu structures and commands for players within a mission.
The advantage of using menu classes is that it hides the complexity of dealing with menu management in more advanced
scanerios where you need to set menus and later remove them, and later set them again. You'll find while using use
normal DCS scripting functions, that setting and removing menus is not a easy feat if you have complex menu hierarchies
defined. Using the moose menu classes, the removal and refreshing of menus are nicely being handled within these
classes, and becomes much more easy. On top, moose implements variable parameter passing for command menus, which can
be updated without having to touch the menus.
**Features:**
* Setup mission sub menus.
* Setup mission command menus.
* Setup coalition sub menus.
* Setup coalition command menus.
* Setup group sub menus.
* Setup group command menus.
* Manage menu creation intelligently, avoid double menu creation.
* Only create or delete menus when required, and keep existing menus persistent.
* Update menu structures.
* Refresh menu structures intelligently, based on a time stamp of updates.
- Delete obscolete menus.
- Create new one where required.
- Don't touch the existing ones.
* Provide a variable amount of parameters to menus.
* Update the parameters and the receiving methods, without updating the menu within DCS!
* Provide a great performance boost in menu management.
* Provide a great tool to manage menus in your code.
**Learn the menu system, it has some great hidden features.**
## 7. [MESSAGE](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Message.html)
![MESSAGE](../images/classes/core/message.jpg)
Informs the players using messages during a simulation.
**Features:**
* A more advanced messaging system using the DCS message system.
* Time messages.
* Send messages based on a message type, which has a pre-defined duration that can be tweaked in SETTINGS.
* Send message to all players.
* Send messages to a coalition.
* Send messages to a specific group.
**The message system really helps with the communication to your players.**
## 8. [POINT](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Point.html)
![POINT](../images/classes/core/point.jpg)
Defines an extensive API to manage 3D points in the DCS World 3D simulation space.
**Features:**
* Provides a COORDINATE class, which allows to manage points in 3D space and perform various operations on it.
* Provides a POINT_VEC2 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a
Lat/Lon and Altitude perspective.
* Provides a POINT_VEC3 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a
X, Z and Y vector perspective.
**The coordinate system classes are essential to understand. Learn this!**
## 9. [RADIO](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Sound.Radio.html)
![RADIO](../images/classes/sound/radio.jpg)
Is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio
transmissions.
**Features:**
* Provide radio functionality to broadcast radio transmissions.
* Provide beacon functionality to assist pilots.
**Radio and beacons really enhance game experience for hardened and experienced players and pilots!**
## 10. [REPORT](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Report.html)
![REPORT](../images/classes/core/report.jpg)
Provides a handy means to create messages and reports. This class is extensively used in the tasking mechanism.
**Features:**
* Create text blocks that are formatted.
* Create automatic indents.
* Variate the delimiters between reporting lines.
**Reports are used extensively in moose. Learn it and your messages get structure.**
## 11. [SCHEDULER](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Scheduler.html)
![SCHEDULER](../images/classes/core/scheduler.jpg)
Prepares and handles the execution of functions over scheduled time (intervals).
**Features:**
* Schedule functions over time,
* 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.
**Scheduler is key to control time and timed events.**
**When you lean how to schedule functions, you will be in control of your mission.**
## 12. [SET](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Set.html)
![SET](../images/classes/core/sets.jpg)
Define collections of objects to perform bulk actions and logically group objects.
**Features:**
* Dynamically maintain collections of objects.
* Manually modify the collection, by adding or removing objects.
* Collections of different types.
* Validate the presence of objects in the collection.
* Perform bulk actions on collection.
**Collections are essential to control the objects and data in your missions efficiently.**
## 13. [SETTINGS](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Settings.html)
![SETTINGS](../images/classes/core/settings.jpg)
Manages various settings for running missions, consumed by moose classes and provides a menu system for players to tweak
settings in running missions.
**Features:**
* Provide a settings menu system to the players.
* Provide a player settings menu and an overall mission settings menu.
* Mission settings provide default settings, while player settings override mission settings.
* Provide a menu to select between different coordinate formats for A2G coordinates.
* Provide a menu to select between different coordinate formats for A2A coordinates.
* Provide a menu to select between different message time duration options.
* Provide a menu to select between different metric systems.
**Settings can really enhance game play, especially for non-europeans :-)**
## 14. [SPAWN](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Spawn.html)
![SPAWN](../images/classes/core/spawn.jpg)
Spawn dynamically new groups of units in running missions.
**Features:**
* Spawn new groups in running missions.
* Schedule spawning of new groups.
* Put limits on the amount of groups that can be spawned, and the amount of units that can be alive at the same time.
* Randomize the spawning location between different zones.
* Randomize the intial positions within the zones.
* Spawn in array formation.
* Spawn uncontrolled (for planes or helos only).
* Clean up inactive helicopters that "crashed".
* Place a hook to capture a spawn event, and tailor with customer code.
* Spawn late activated.
* Spawn with or without an initial delay.
* Respawn after landing, on the runway or at the ramp after engine shutdown.
* Spawn with custom heading.
* Spawn with different skills.
* Spawn with different liveries.
* Spawn with an inner and outer radius to set the initial position.
* Spawn with a randomize route.
* Spawn with a randomized template.
* Spawn with a randomized start points on a route.
* Spawn with an alternative name.
* Spawn and keep the unit names.
* Spawn with a different coalition and country.
* Enquiry methods to check on spawn status.
**Spawning groups is a great way of making your missions dynamic!**
## 15. [SPAWNSTATIC](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.SpawnStatic.html)
![SPAWNSTATIC](../images/classes/core/spawnstatic.jpg)
Spawn new statics in your running missions.
**Features:**
* Spawn new statics from a static already defined using the mission editor.
* Spawn new statics from a given template.
* Spawn new statics from a given type.
* Spawn with a custom heading and location.
* Spawn within a zone.
**Spawning statics is a great way of decorating your missions with additional scenery objects!**
## 16. [SPOT](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Spot.html)
![SPOT](../images/classes/core/spot.jpg)
Management of spotting logistics, that can be activated and deactivated upon command.
**Features:**
* Spot for a defined duration.
* Updates of laer spot position every 0.2 seconds for moving targets.
* Wiggle the spot at the target.
* Provide a @{Wrapper.Unit} as a target, instead of a point.
* Implement a status machine, LaseOn, LaseOff.
**Spot is a rather technical class, and is used in designate and warehouse.**
## 17. [USERFLAG](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.UserFlag.html)
![USERFLAG](../images/classes/core/userflag.jpg)
Manage user flags to interact with the mission editor trigger system and server side scripts.
**Features:**
* Set or get DCS user flags within running missions.
**User flags are the method to set or retrieve the value of flags as set in the mission editor.**
## 18. [USERSOUND](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Sound.UserSound.html)
![USERSOUND](../images/classes/sound/usersound.jpg)
Manage user sound.
**Features:**
* Play sounds wihtin running missions.
**User sounds are a great way to enhance your missions with ambient music or sounds upon various events.**
## 19. [VELOCITY](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Velocity.html)
![VELOCITY](../images/classes/core/velocity.jpg)
Models a velocity or speed, which can be expressed in various formats according the settings.
**Features:**
* Convert velocity in various metric systems.
* Set the velocity.
* Create a text in a specific format of a velocity.
**Velocity is an internal class used within the moose framework.**
## 20. [ZONE](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Zone.html)
![ZONE](../images/classes/core/zones.jpg)
Define zones within your mission of various forms, with various capabilities.
**Features:**
* Create radius zones.
* Create trigger zones.
* Create polygon zones.
* Create moving zones around a unit.
* Create moving zones around a group.
* Provide the zone behaviour. Some zones are static, while others are moveable.
* Enquiry if a coordinate is within a zone.
* Smoke zones.
* Set a zone probability to control zone selection.
* Get zone coordinates.
* Get zone properties.
* Get zone bounding box.
* Set/get zone name.
**Zones are very important in mission design, this is definitely a skill to learn to make great missions!**
[Wrapper.Group]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Group.html
[Wrapper.Static]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Static.html
[Wrapper.Unit]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Unit.html
[Core.Zone]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Zone.html

View File

@ -0,0 +1,284 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 4
---
# Functional classes guide
![MOOSE FUNCTIONAL](../images/classes/category-functional.jpg)
This chapter explains functional classes within MOOSE that allows you to enrich or enhance the functionality of your mission scenarios.
## 1. [ATC_GROUND]
![ATC Ground](../images/classes/functional/atc-ground.jpg)
The ATC_GROUND classes monitor airbase traffic and regulate speed while taxiing.
**Features:**
* Monitor speed of the airplanes of players during taxi.
* Communicate ATC ground operations.
* Kick speeding players during taxi.
## 2. [ARTY]
![Arty](../images/classes/functional/artillery.jpg)
Easily assign and manage targets for artillery units using an advanced queueing system.
**Features:**
* Multiple targets can be assigned. No restriction on number of targets.
* Targets can be given a priority. Engagement of targets is executed a according to their priority.
* Engagements can be scheduled, i.e. will be executed at a certain time of the day.
* Multiple relocations of the group can be assigned and scheduled via queueing system.
* Special weapon types can be selected for each attack, e.g. cruise missiles for Naval units.
* Automatic rearming once the artillery is out of ammo (optional).
* Automatic relocation after each firing engagement to prevent counter strikes (optional).
* Automatic relocation movements to get the battery within firing range (optional).
* Simulation of tactical nuclear shells as well as illumination and smoke shells.
* New targets can be added during the mission, e.g. when they are detected by recon units.
* Targets and relocations can be assigned by placing markers on the F10 map.
* Finite state machine implementation. Mission designer can interact when certain events occur.
## 3. [CLEANUP]
![CleanUp](../images/classes/functional/cleanup.jpg)
Keep an airbase clean of crashing or colliding airplanes.
**Features:**
* Try to keep the airbase clean and operational.
* Prevent airplanes from crashing.
* Clean up obstructing airplanes from the runway that are standing still for a period of time.
* Prevent airplanes firing missiles within the airbase zone.
## 4. [DESIGNATE]
![Designate](../images/classes/functional/designation.jpg)
Orchestrate 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...
**Features:**
* Faciliate the communication of detected targets to players.
* Designate targets using lasers, through a menu system.
* Designate targets using smoking, through a menu system.
* Designate targets using illumination, through a menu system.
* Auto lase targets.
* Refresh detection upon specified time intervals.
* Prioritization on threat levels.
* Reporting system of threats.
## 5. [DETECTION]
![Detection](../images/classes/functional/detection.jpg)
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.
**Features:**
* Detection of targets by recce units.
* Group detected targets per unit, type or area (zone).
* Keep persistency of detected targets, if when detection is lost.
* Provide an indication of detected targets.
* Report detected targets.
* Refresh detection upon specified time intervals.
## 6. [ESCORT]
![Escort](../images/classes/functional/escorting.jpg)
Allows you to interact with escorting AI on your flight and take the lead.
Each escorting group can be commanded with a whole set of radio commands (radio menu in your flight, and then F10).
The radio commands will vary according the category of the group. The richest set of commands are with Helicopters and AirPlanes.
Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts.
**Features:**
* Escort navigation commands.
* Escort hold at position commands.
* Escorts reporting detected targets.
* Escorts scanning targets in advance.
* Escorts attacking specific targets.
* Request assistance from other groups for attack.
* Manage rule of engagement of escorts.
* Manage the allowed evasion techniques of escorts.
* Make escort to execute a defined mission or path.
* Escort tactical situation reporting.
## 7. [MISSILE_TRAINER]
![MissileTrainer](../images/classes/functional/missile-trainer.jpg)
be alerted of any missiles fired, and when a missile would hit your aircraft, the class will destroy the missile within a certain range,
to avoid damage to your aircraft. This is a training class for noob pilots, receiving training on missile evasion and detection techniques.
**Features:**
* Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
* Provide alerts of missile launches, including detailed information of the units launching, including bearing, range
* Provide alerts when a missile would have killed your aircraft.
* Provide alerts when the missile self destructs.
* Enable / Disable and Configure the Missile Trainer using the various menu options.
## 8. [RANGE]
![Range](../images/classes/functional/range.jpg)
The RANGE class enables easy set up of bombing and strafing ranges within DCS World.
476th - Air Weapons Range Objects mod is highly recommended for this class.
**Features:**
* Impact points of bombs, rockets and missils are recorded and distance to closest range target is measured and reported to the player.
* Number of hits on strafing passes are counted and reported. Also the percentage of hits w.r.t fired shots is evaluated.
* Results of all bombing and strafing runs are stored and top 10 results can be displayed.
* Range targets can be marked by smoke.
* Range can be illuminated by illumination bombs for night practices.
* Bomb, rocket and missile impact points can be marked by smoke.
* Direct hits on targets can trigger flares.
* Smoke and flare colors can be adjusted for each player via radio menu.
* Range information and weather report at the range can be reported via radio menu.
## 9. [RAT]
![rat](../images/classes/functional/rat.jpg)
Fill the empty DCS world with randomized air traffic and bring more life to your airports.
In particular, it is designed to spawn AI air units at random airports. These units will be assigned a random flight path to another random airport on the map.
Even the mission designer will not know where aircraft will be spawned and which route they follow.
**Features:**
* Very simple interface. Just one unit and two lines of Lua code needed to fill your map.
* High degree of randomization. Aircraft will spawn at random airports, have random routes and random destinations.
* Specific departure and/or destination airports can be chosen.
* Departure and destination airports can be restricted by coalition.
* Planes and helicopters supported. Helicopters can also be send to FARPs and ships.
* Units can also be spawned in air within pre-defined zones of the map.
* Aircraft will be removed when they arrive at their destination (or get stuck on the ground).
* When a unit is removed a new unit with a different flight plan is respawned.
* Aircraft can report their status during the route.
* All of the above can be customized by the user if necessary.
* All current (Caucasus, Nevada, Normandy, Persian Gulf) and future maps are supported.
## 10. [SCORING]
![Scoring](../images/classes/functional/scoring.jpg)
Administers the scoring of player achievements, and creates a CSV file logging the scoring events and results for use at team or squadron websites.
Automatically calculates the threat level of the objects hit and destroyed by players, which can be Wrapper.Unit, Static objects.
Positive score points are granted when enemy or neutral targets are destroyed.
Negative score points or penalties are given when a friendly target is hit or destroyed.
This brings a lot of dynamism in the scoring, where players need to take care to inflict damage on the right target.
By default, penalties weight heavier in the scoring, to ensure that players don't commit fratricide.
The total score of the player is calculated by adding the scores minus the penalties.
**Features:**
* Set the scoring scales based on threat level.
* Positive scores and negative scores.
* A contribution model to score achievements.
* Score goals.
* Score specific achievements.
* Score the hits and destroys of units.
* Score the hits and destroys of statics.
* Score the hits and destroys of scenery.
* Log scores into a CSV file.
* Connect to a remote server using JSON and IP.
## 11. [SEAD]
![Sead](../images/classes/functional/sead.jpg)
Provides defensive behaviour to a set of SAM sites within a running Mission.
**Features:**
* When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible.
* When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars.
## 12. [SUPPRESSION]
![Supporession](../images/classes/functional/suppression.jpg)
When ground units get hit by (suppressive) enemy fire, they will not be able to shoot back for a certain amount of time.
The implementation is based on an idea and script by MBot. See the DCS forum threat for details.
In addition to suppressing the fire, conditions can be specified which let the group retreat to a defined zone, move away from the attacker or hide at a nearby scenery object.
**Features:**
* Hold fire of attacked units when being fired upon.
## 13. [WAREHOUSE]
![Warehouse](../images/classes/functional/warehouse.jpg)
The warehouse concept simulates the organization and implementation of complex operations regarding the flow of assets between the point of origin
and the point of consumption in order to meet requirements of a potential conflict.
In particular, this class is concerned with maintaining army supply lines while disrupting those of the enemy,
since an armed force without resources and transportation is defenseless.
**Features:**
* Holds (virtual) assests in stock and spawns them upon request.
* Manages requests of assets from other warehouses.
* Queueing system with optional priorization of requests.
* Realistic transportation of assets between warehouses.
* Different means of automatic transportation (planes, helicopters, APCs, self propelled).
* Strategic components such as capturing, defending and destroying warehouses and their associated infrastructure.
* Intelligent spawning of aircraft on airports (only if enough parking spots are available).
* Possibility to hook into events and customize actions.
* Can be easily interfaced to other MOOSE classes.
## 14. [ZONE_CAPTURE_COALITION]
![ZoneCaptureCoalition](../images/classes/functional/zonecapturecoalition.jpg)
A very powerful class to models the process to zone guarding, attacking and capturing.
**Features:**
* Models the possible state transitions between the Guarded, Attacked, Empty and Captured states.
* A zone has an owning coalition, that means that at a specific point in time, a zone can be owned by the red or blue coalition.
* Provide event handlers to tailor the actions when a zone changes coalition or state.
[ATC_GROUND]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.ATC_Ground.html
[ARTY]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Artillery.html
[CLEANUP]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.CleanUp.html
[DESIGNATE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Designate.html
[DETECTION]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Detection.html
[ESCORT]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Escort.html
[MISSILE_TRAINER]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.MissileTrainer.html
[RANGE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Range.html
[RAT]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.RAT.html
[SCORING]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Scoring.html
[SEAD]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Sead.html
[SUPPRESSION]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Suppression.html
[WAREHOUSE]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Warehouse.html
[ZONE_CAPTURE_COALITION]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.ZoneCaptureCoalition.html

View File

@ -0,0 +1,103 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 2
---
# Tasking classes guide
![MOOSE TASKING](../images/classes/category-tasking.jpg)
This chapter explains the major principles behind the tasking concepts in MOOSE.
Tasking is achieved through the utilization of various classes that fall in the category Tasking.
MOOSE allows humans to achieve mission goals, through the execution of tasks.
In order to setup the Tasking, you'll have to define:
- At least one command center object for each coalition.
- A mission or multiple missions for each command center.
- A task dispatcher per mission.
**Features:**
* Each coalition must have a command center.
* Each command center can govern multiple missions.
* Each command center owns a player menu.
* Each mission can contain multiple tasks of different categories.
* Each mission has a goal to be achieved.
* Each mission has a state, that indicates the fase of the mission.
* Each task can be joined by multiple human players, thus, a task is done in co-op mode.
* Each task has a state, that indicates the fase of the task.
* Players have their own menu. When a player joins a task, only that player will have the menu of the task.
## 1. [Command Center]
![Tasking Command Center](../images/classes/tasking/commandcenter.jpg)
A command center governs multiple missions, and takes care of the reporting and communications.
**Features:**
* Govern multiple missions.
* Communicate to coalitions, groups.
* Assign tasks.
* Manage the menus.
* Manage reference zones.
## 2. [Mission]
![Tasking Command Center](../images/classes/tasking/mission.jpg)
A mission models a goal to be achieved through the execution and completion of tasks by human players.
**Features:**
* A mission has a goal to be achieved, through the execution and completion of tasks of different categories by human players.
* A mission manages these tasks.
* A mission has a state, that indicates the fase of the mission.
* A mission has a menu structure, that facilitates mission reports and tasking menus.
* A mission can assign a task to a player.
## 3. [A2A Task Dispatcher]
![Tasking A2A Dispatching](../images/classes/tasking/task-a2a-dispatcher.jpg)
Dynamically allocates A2A tasks to human players, based on detected airborne targets through an EWR network.
**Features:**
* Dynamically assign tasks to human players based on detected targets.
* Dynamically change the tasks as the tactical situation evolves during the mission.
* Dynamically assign (CAP) Control Air Patrols tasks for human players to perform CAP.
* Dynamically assign (GCI) Ground Control Intercept tasks for human players to perform GCI.
* Dynamically assign Engage tasks for human players to engage on close-by airborne bogeys.
* Define and use an EWR (Early Warning Radar) network.
* Define different ranges to engage upon intruders.
* Keep task achievements.
* Score task achievements.
## 3. [A2G Task Dispatcher]
![Tasking A2G Dispatching](../images/classes/tasking/task-a2g-dispatcher.jpg)
Dynamically allocates A2G tasks to human players, based on detected ground targets through reconnaissance.
**Features:**
* Dynamically assign tasks to human players based on detected targets.
* Dynamically change the tasks as the tactical situation evolves during the mission.
* Dynamically assign (CAS) Close Air Support tasks for human players.
* Dynamically assign (BAI) Battlefield Air Interdiction tasks for human players.
* Dynamically assign (SEAD) Supression of Enemy Air Defense tasks for human players to eliminate G2A missile threats.
* Define and use an EWR (Early Warning Radar) network.
* Define different ranges to engage upon intruders.
* Keep task achievements.
* Score task achievements.
[Command Center]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Tasking.CommandCenter.html
[Mission]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Tasking.Mission.html
[A2A Task Dispatcher]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Tasking.Task_A2A_Dispatcher.html
[A2G Task Dispatcher]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Tasking.Task_A2G_Dispatcher.html

View File

@ -0,0 +1,65 @@
---
parent: Mission Designers Guide
grand_parent: Archive
nav_order: 5
---
# Wrapper classes guide
![MOOSE WRAPPER](../images/classes/category-wrapper.jpg)
This chapter lists the wrapper classes which enhances the functionality for mission designers on the mission objects.
## 1. [GROUP](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Group.html)
![Group](../images/classes/wrapper/group.jpg)
Wraps the DCS _Group_ objects.
**Features:**
* Support all DCS Group APIs.
* Enhance with Group specific APIs not in the DCS Group API set.
* Handle local Group Controller.
* Manage the "state" of the DCS Group.
## 2. [UNIT](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Unit.html)
![Unit](../images/classes/wrapper/unit.jpg)
Wraps the DCS _Unit_ objects.
**Features:**
* Support all DCS Unit APIs.
* Enhance with Unit specific APIs not in the DCS Unit API set.
* Handle local Unit Controller.
* Manage the "state" of the DCS Unit.
## 3. [STATIC](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Static.html)
![Static](../images/classes/wrapper/static.jpg)
Wraps the DCS _Static_ objects.
Note that Statics are almost the same as Units, but they don't have a controller.
**Features:**
* Wraps the DCS Static objects.
* Support all DCS Static APIs.
* Enhance with Static specific APIs not in the DCS API set.
## 4. [AIRBASE](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Wrapper.Airbase.html)
![Airbase](../images/classes/wrapper/airbase.jpg)
Wraps the DCS _Airbase_ objects.
**Features:**
* Support all DCS Airbase APIs.
* Enhance with Airbase specific APIs not in the DCS Airbase API set.

View File

@ -0,0 +1,173 @@
---
parent: Archive
nav_order: 3
---
# Beta Tester Guide
You are interrested in **testing the bleeding edge functionalities** and features added by contributors every day,
and you are **not afraid of bugs** that will inevitably crop up from time to time ? Then this page is for you !
You are going to learn:
1. **Installation:** How to set up your development environment
2. **Repository:** How is the Moose repository organized
3. **Loading:** How Moose is loaded in the missions and how this can make your workflow more efficient
4. How to use tools to process your .miz files efficiently
5. How Moose's release cycle work
6. How the Issue Tracker is managed
This might be a bit daunting at first, but the rewards in term of simplified workflow and direct access to new features
is well worth the effort! If you have any problem during the setup or at any other point, don't hesitate to ask the
[community](guide-communities.md) for help!
This guide assumes that **you already setup your development environment**, like a "normal" mission designer.
Which means Lua Development Tools (LDT) is installed on your computer, and you already know how to create a mission
using MOOSE. If it is not the case, please follow the instructions [here](guide-usage.md) before proceeding.
## Installation
Get your MOOSE repository installed on your PC and linked with GITHUB
### Install GitHub desktop
Install [GitHub](https://desktop.github.com) desktop.
Since the MOOSE code is evolving very rapidely between Releases, we store the MOOSE code on GitHub, and we use the
GitHub to sync it between the remote repository (the "origin") and your local MOOSE repository. That way, only one
click is needed to update to the latest version of GitHub.
### Link the MOOSE repository
Link the MOOSE repository on GITHUB to your freshly installed GITHUB desktop.
This is done by browing to the [MOOSE repository at GitHub](https://github.com/FlightControl-Master/MOOSE), and
selecting the green button **Clone or Download** -> **Open in Desktop**.
![](../images/archive/installation/GitHub_Clone.JPG)
Specify a local directory on your PC where you want to store the MOOSE repository contents.
Sync the MOOSE repository to a defined local MOOSE directory on your PC using GITHUB desktop (press the sync button).
You now have a copy of the code on computer, which you can update at any time by simply pressing the sync button.
### Install 7-Zip
Install [7-Zip](http://www.7-zip.org/) if you don't already have it. It is a free and open source file archiver program.
Since DCS .miz files are simply renamed .zip files, 7-Zip is very usefull to manimulate them. We are providing the MOOSE
testers and contributors with tools to batch process their .miz files, and they rely on 7-Zip. Keep the path to your
7-Zip installation handy, it will be use in the next step!
# Repository
The MOOSE repository has a couple of folders, but the most important one is the **Moose Development** folder.
This directory contains an other folder called **Moose**. This is the most important folder, as this contains all the
MOOSE source code!
The other directories contained within the repository are for administration and automation of the deployment process.
# Loading the repository within your missions.
## Static Loading
**Moose Static Loading** is what the "normal" mission designer uses.
Simply put, you would include all the code of MOOSE by including **just one Moose.lua file**.
So by executing a DO SCRIPT FILE within your mission, you would load the complete MOOSE code within your mission.
This process is very useful **when you are using a stable Release** of Moose which don't change often,
because it is really easy to set up for the mission designer.
It also allows him to **release missions** which are contained in their entirety in the .miz file.
But in a context in wich Moose changes often, static loading would require the generation of a new Moose.lua
**for every change within the MOOSE framework** and you would need to replace the old Moose.lua in the .miz file you are
using to test the changes. Add to this cumbersome process the fact that the Mission Editor doesn't like changes to the
.miz file while it is open, which means you would need to close and reopen the Mission Editor for every change,
and this process becomes unworkable for both the tester and the contributor.
## Dynamic Loading
So, beyond the Static Loading, there is the Dynamic Loading, which allows a much more smooth proces while testing your
missions.
Enter **Moose Dynamic loading**. In this process, the **Moose.lua** you insert in your .miz file looks for every .lua
which constitute Moose in `DCSWorld\Scripts`, **and asks DCS to load them** during the mission startup.
This way, the latest changes to the MOOSE .lua files in `DCSWorld\Scripts` are automatically taken into account when you
restart the mission, no need to fiddle around with the .miz file or to close the mission editor!
Now, there is still a problem left : you wouldn't want to have to copy the MOOSE .lua files from your local repository
to `DCSWorld\Scripts`, everytime you retrieve a new version of Moose. The solution to this problem is a dynamic link!
Simply put, it makes sure that the folder `DCSWorld\Scripts\Moose` is always in sync with your local MOOSE repository
on your disk. That way, **everytime you want to update to the next Moose, you simply sync your local repository** with
the remote with GitHub, **and restart your mission**!
Note that if you want to **release your missions to end users**, you will need to make it
**use the static loading process**. There is a tool to automate this task, read below.
# Tools to help you manage your .miz files
***TODO : Add a list of the .miz files tools a briefly explain their usages***
# The release cycle
To ensure that the next Release of Moose is as bug-free and feature rich as possible, every Moose contributor respects
a release cycle.
![](../images/archive/installation/MOOSE_Release_Cycle.JPG)
If you are not familiar with Git, this might be a bit criptic, but the idea behind it is simple :
* Most of the time, contributors write code, be it features or bug fixes, and the testers report bugs.
* When a good amount of features are added to the last release, FlightControl decides to enter in a "Feature Freeze"
period. **No new features are added** during this period (but they can still be worked on), and
**every bug must be eliminated**. That is the period during which bug reports are paramount!
* Now that this version of **Moose is stable**, we can release it for every mission designer and go back to the start
for the next cycle.
# The Issue Tracker
## How to report a bug?
If you **encounter** what seem to be a **bug**, which is bound to happen sooner or later since you are testing the brand
new untested features of Moose, you will want to **report it** so that it can be solved by the contributors. We use the
standard GitHub [Issue Tracker](https://github.com/FlightControl-Master/MOOSE/issues). Here is the process to create a
new issue:
* First, do a quick **search on the issue tracker** to see if someone hasn't already reported your issue. If it is the
case, comment on this issue that you are able to reproduce it, and add the informations listed below.
* **Create a new issue**.
* **Add the information** listed below
* Add the **lablel possible bug**
* Thank you for helping us make Moose better!
**_Informations we need to solve the issue_**
* **A descriptive title**, not too long if possible. For exemple, `CTD when calling SPAWN:New()` is a good title.
`I found a bug in MOOSE` is not.
* Explain **what you are trying to do**, as well as **how you expect Moose to be behave**.
* Which **version of Moose** and DCS World you are using. This can be found in `dcs.log`
* Did the code you are using worked in previous version of either DCS World or Moose? Which one?
* The **code** or portion of code **that triggered the problem**. Please put **_\`\`\`lua_** one line before your
code, and **_\`\`\`_** at the end, to make your code readable.
* The relevant part of **`dcs.log`**. Please put **_\`\`\`_** before and after your copy-pasted log to make it readable.
![Example of a great bug report](../images/archive/installation/GitHub_Issue_example.JPG)
## How to add a feature request?
* **A descriptive title**, not too long if possible.
* Explain in detail **what you want Moose to do** in which circonstance.
* If possible, add some pseudocode or a high level design implementation to better explain how your feature would work.
* Add the **lablel enhancment**
## The life and death of an issue
**_What is going to happen next to my issue?_**
* A contributor will set some labels and a milestone to your issue, in order to classify it.
* You might be asked to clarify some part of your issue, please answer as swiftly as possible.
* You might be asked to sync your local repository and try again, if we think we fixed your issue. If we can confirm it
to be fixed the issue is closed.
**_Wait, my issue was closed, and it never got fixed ! / Nobody is paying attention to it !_**
This can happen for multiple reasons:
* Your issue is a duplicate. (There is alredy a issue in our issue tracker for this)
* Nobody was able to reproduce your bug, so we think it's a problem on your end
* Your feature request asks for a feature that already exists
* We think your feature request is a really good idea, but it's a huge time commitment. We therefore postponed it to the
Realease after the next one, or to a later Release.
* We are working hard and simply don't have the time. We will get around to check your issue, please be patient!

View File

@ -0,0 +1,45 @@
---
parent: Archive
nav_order: 7
---
# Communities
MOOSE is broadcasted, documented and supported through various social media channels.
## 1. MOOSE on YouTube
MOOSE has a [broadcast channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) on youtube.
These videos are grouped into playlists, which explain specific MOOSE capabilities,
and gradually build up the "understanding" and "what is possible" to do with the MOOSE framework.
I really, really encourage all to watch the explanation videos.
Some mandatory videos to watch are:
* [MOOSE Introduction](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1JEtVcyf9sazUV5_fGICz4)
* [MOOSE Setup](https://www.youtube.com/watch?v=-Hxae3mTCE8&t=159s&index=1&list=PL7ZUrU4zZUl0riB9ULVh-bZvFlw1_Wym2)
* [MOOSE Spawning](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL)
* [MOOSE Tasking](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3CgxN2iAViiGLTPpQ-Ajdg)
* [MOOSE Task Dispatching](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3I6ieFM-cjey-rncF1ktNI)
## 2. MOOSE on Eagle Dynamics forums
This is a default thread at the Eagle Dynamics forums where the MOOSE framework can be discussed and supported.
The thread is called [MOOSE - Mission Object Oriented Scripting Framework].
## 3. MOOSE development on GitHub
I encourage that you create also a user at [GitHub](https://github.com/FlightControl-Master/MOOSE).
On the GitHub site, you can register issues, feedback and comments in the issues section of the site.
This allows to track this feedback and issues, in order to provide a structured support and create a milestone plan.
In other words, treat this development as a project.
## 4. MOOSE community on Discord
Join our MOOSE community on [Discord](https://discord.gg/gj68fm969S).
A place where mission designers and developers come together to discuss the latest features.
We are now with about 5 people supporting Mission Designers on Discord.
There are currently more than 300 members on our discord MOOSE channel.
[MOOSE - Mission Object Oriented Scripting Framework]: https://forums.eagle.ru/showthread.php?t=138043

View File

@ -0,0 +1,246 @@
---
parent: Archive
nav_order: 5
---
# Contribution
*** UNDER CONSTRUCTION ***
So, you are already familiarized with Lua and you think the best way to get the new feature you want fast is to program
it yourself ? Or you feel like reporting bugs isn't enough, you want to fix them yourself ? Either way, you need some
more information to contribute to Moose.
This guide assumes that **you are already familiar with Moose** and that **you already set up your development**
**environment**. If it is not the case, please go through the [Beta Tester Guide](guide-beta-tester.md) before
proceeding.
In this document, we will review:
1. GitHub/Git organisation
2. Contribution guidelines
3. Coding standards
4. The Luadoc
5. Moose release cycle
6. The Issue Tracker: labels and milestones
# 1) GitHub/Git organisation
You are assumed to be familar with at least the basics of GitHub (branches, commits, pull requests...). If it is not the
case, please at least read [this tutorial](https://guides.github.com/introduction/flow/). If something isn't clear
still, ask us, we'll be glad to explain!
## 1.1) The Repositories
Moose is in fact located on **three repositories** :
* [**MOOSE**](https://github.com/FlightControl-Master/MOOSE) contains the Moose's **code**, the **documentation** and
the file necessary to the **setup**
* [**MOOSE_MISSIONS**](https://github.com/FlightControl-Master/MOOSE_MISSIONS) contains the **demo missions**
* [**MOOSE_PRESENTATIONS**](https://github.com/FlightControl-Master/MOOSE_PRESENTATIONS) contains bits and bob related
to Moose, like Moose's logos and PowerPoint files to present a specific feature of Moose.
## 1.2) Branches
On the [MOOSE](https://github.com/FlightControl-Master/MOOSE) repository, three branches are protected, which means that
you cannot merge or commit directly to them, you need to create a pull request;
* [master](https://github.com/FlightControl-Master/MOOSE/tree/master) stores Moose's current latest semi-stable code.
* master-release stores Mosse's last release code. There is no reason you would want to modify this branch.
* [master-backup](https://github.com/FlightControl-Master/MOOSE/tree/master-backup). We sometime backup the master into
master-backup, in case the worst happen. There is no reason you would want to modify this branch.
You are encourgaed to **create your own branch, named after you pseudonyme**, to test stuff and do some small-scale
bugfixes. When you want to work on bigger features, you should **create a new branch named after the feature** you are
working on. Don't forget to delete it when the feature is merged with master!
## 1.3) Commits
The usual [Git commit](https://chris.beams.io/posts/git-commit/) guidelines apply. Don't overthink it though, time is
better spent coding or managing the Issue Tracker than writing long-form commit descriptions.
## 1.4) Merge/Pull Requests
When the code you are working on is finished, you will want to **resolve the merge conflicts** between your branch and
master, and then **create a pull request**. Explain clearly what your code does (with a link to the relevant issue).
If it meets the requirements below, it will be approved ASAP by FlightControl.
# 2) Contribution guidelines
We try to **follow a contribution process**, to make sure we work efficiently together. It isn't set in stone, but it
gives an idea of what should be done. We wouldn't want two contributors both working on the same issue at the same time,
would we ? This process is more geared towards the implementation of new features, the process for bug fixes is more
flexible and several steps can be overlooked.
1. Think about **what you are trying to achieve.** Writing some pseudocode is a great way to undersatnd the challenges
you are going to face.
2. **Discuss your idea** with the community **on Slack**. Maybe there is a way to do it you didn't even think about, or
maybe you could team up with someone who is already working on it!
3. Create a **high level design document**. It doesn't need to be thorough, but you need to have an idea of which class
do you want to write, which class they should inherit from, which methods are needed in each class...
4. Write an **issue on GitHub** with your high level design document, apply the label "enhancement" to it, and assign it
to yourself.
5. Create a **new branch** named after the feature **on MOOSE's repository** to work on (you will be given contributor
access).
6. **Write your code** in this branch, following the Coding Standards. **Sync** fairly regularly
**this branch with master**, so that you don't have tons of merge conflicts at the end.
7. When done, **write a/some test mission(s)** to showcase how to use your feature to the community.
8. **Generate the Luadoc**.
9. **Relsove merge conflicts** with master and **create a new pull request**.
10. **Delete your branch** if you are not going to use it again.
# 3) Coding Standards
To ensure a good degree of **consistency** in Moose's code, we follow the following standards:
* The code need to be **intellisense/Luadoc compatible**. See below for more information
* The code needs to be **commented**. Remember:
_“Programs must be written for people to read, and only incidentally for machines to execute.”_ - Hal Abelson.
Keep in mind that you code will be red by non-programmers and beginners.
* **Indentation** should be 2 spaces (default in LDT)
* **Class names** should be in **capital letters** (e.g. `SPAWN`)
* **Class should all inherit from `Core.Base#BASE`**
* **Methods** should start by a **capital letter** (e.g. `GetName()`)
* If your **method** is intended for **private use** only, its name should **start with an underscore**
(e.g. `_GetLastIndex()`)
* **Variables** should start with a **capital leter** (e.g. `IndexString`)
* Provide a **trace** for the mission designer at the start of every method, and when it is appropriate.
Trace functions are inherited from `BASE` :
* `F()`, `F2()` and `F3()` for function calls,
* `T()`, `T2()` and `T3()` for function logic,
* `E()` for errors.
# 4) The Luadoc
The **Luadoc system** is not only **useful for the contributor** to understand the code, but
**also the mission designer**, as it used to automatically generate the
[HTML documentation](http://flightcontrol-master.github.io/MOOSE_DOCS/Documentation/index.html).
It thus needs to follow some strict standards.
Keep in mind the following informations:
* Every Luadoc block needs to start with **three minus signs** (`---`).
* The generated html file will use **Markdown**. If you are not familar with it, use this
[reference](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
* You can create **hyperlinks** by writing
* `@{Module#CLASS.Method}` for a method
* `@{Module#CLASS}` for a class
* `Module` can be ommited if the hyperlink points to the same module (e.g. `@{#CLASS}` is valid if CLASS is in the
Module the link is in)
* Luadoc **types the variables**. the following types are available
* `Folder.Module#CLASS` (a Moose class)
* `Dcs.DCSTypes#Class` (a DCS class)
* `#string`
* `#number` (integer or floating point)
* `#boolean`
* `#nil`
## 4.1) Modules
Every new file should contain at least one module, which is documented by a comment block. You can copy paste the
following model and fill in the blanks:
```lua
--- **Name of the Module** - Short Description
--
-- ===
--
-- Long description. Explain the use cases.
-- Remember that this section will be red by non programmers !
--
-- ===
--
-- ### Authors : Your name/pseudnyme
--
-- @module Module
```
## 4.2) Classes
Every class should be documented by a comment block. You can copy paste the following model and fill in the blanks :
```lua
--- **Name of the CLASS** class, extends @{Module#CLASS}
--
-- Long description. Explain the use cases.
-- Remember that this section will be red by non programmers !
--
-- @type CLASSNAME
-- @field #type AttributeName (add a @field for each attribute)
-- @extends Folder.Module#CLASS
```
## 4.3) Methods
Every method should be documented by a comment block. You can copy paste the following model and fill in the blanks :
```lua
--- Description of the method
-- @param #type (add a @param for each parameters, self included, even if it's implied)
-- @return #type (add other @return fields if the method can return different variables)
-- @usage (can be omitted if the usage is obvious)
-- -- Explain how to use this method
-- -- on multiple lines if you need it !
```
# 5) Moose release cycle
To ensure that the next Release of Moose is as bug-free and feature rich as possible, every Moose contributor
**respects a release cycle**.
![](../images/archive/installation/MOOSE_Release_Cycle.JPG)
The key takeways are:
* During "normal" time, **write your features** and correct bugs **as you please**.
* During "Feature Freeze", you can still work on your features, but you are
**strongly encouraged to prioritize bug fixes**, especially if it involves your code.
**No pull request for new features will be accepted during feature freeze !**
* After the Release, it's back to the start for a new cycle.
# 6) The Issue Tracker : labels and milestones
## 6.1) Milestones
You can see Milestone as the GitHub way to say Release. Moose repository has
**three active [Milestone](https://github.com/FlightControl-Master/MOOSE/milestones) at any time**:
* The next milestone (e.g. Moose-2.0)
* The milestone after the next one (e.g. Moose-2.1)
* The "future" milestone (Moose-Future)
Every **bug is assigned to the next milestone**, and should be fixed before the release.
**Features are assigned to any milestone depending on the importance** of it and how hard it is to implement.
Typically, a feature that is currently worked on is assigned to the next milestone, an very long-term feature is
assigned to Moose-Future, and any other feature is assigned to the milestone after the next one, the goal being to have
a nice todo list for the contributor to pick and choose from at the end of feature freeze. If you come accross a issue
that isn't assigned to a milestone, feel free to add it to the correct one!
## 6.2) Labels
We heavily use **GitHub's label system** on the Issue Tracker to categorize each issue.
Each **issue is assigned the relevant label(s) at birth** by a contributor, and they are then updated to reflect the
current state of the issue. If you come accross an untagged issue, feel free label it ! You can consult the
[full list of labels available](https://github.com/FlightControl-Master/MOOSE/labels),
but **please asks the community before adding or removing a label** to the list.
* Bugs
* question : not even a bug report
* possible bug : might be a bug, but hasn't been reproduced yet
* bug : the bug has been confirmed / reproduced
* fixed : We think the bug is fixed. but there is a good reson why we are not closing the issue just yet.
Usually used in conjunction with ready for testing
* Feature requests
* enhancement : this issue is a feature request
* implemented : we implemented this enhancement, but there is a good reson why we are not closing the issue just yet.
Usually used in conjunction with ready for testing
* Documentation work
* documentation
* Urgency
* urgent (fix in a few days) : This is used primarly for bugs found in the latest Release.
* not urgent (can wait)
* Work load (this is merely to help contributer choose issues conpatible with the free time they have)
* hard work
* trivial
* Will not fix
* wontfix
* duplicate : this issue already exists somewhere else
* invalid

343
docs/archive/guide-debug.md Normal file
View File

@ -0,0 +1,343 @@
---
parent: Archive
nav_order: 6
---
# Interactive Debugging
The Lua Development Tools in the Eclipse suite has a possibility to "attach a lua debugger" to your LDT environment.
Read this section to setup a debugger in our DCS World environment.
The people who have used debuggers before, will recognize a lot in this explanation!
How it works:
* Setup a **debug listener** within LDT. When running, it will listen over IP on the local host (127.0.0.1) on a port.
* Attach a **debug client** to your DCS World configuration. This **debug client** will attach itself to the
**debug listener** over IP.
* Modify your mission, so that your source files are loaded **dynamically**. This is very important because DCS World
**renames** unfortunately the name of the source files when it runs a mission!
* Set breakpoints where needed. The debugger will stop at the breakpoints set.
* Run the **debug listener** on LDT.
* Run the DCS World mission, which uses the **debug client** to connect to the **debug listener** over IP.
* The logic will stop at the set breakpoints. Using LDT, you can walk through the logic (statements), while inspecting
variable contents and evaluate expressions.
* You can set breakpoints during the process where you want, you can add / delete variables in the views where you
want.
**This capability will give you a new experience in DCS World mission design!**
**Note:** The assets that are used in this description, were modified to accomodate the debugging, so the LDT
off-the-shelf assets aren't working. So use the assets as listed here, or your debugger won't work!
## 1. Explanation of the LDT debugging environment.
![](../images/archive/debugging/DEBUG_Intro.JPG)
The following pictures outline some of the interesting places in LDT to debug your lua code... A quick manual.
![](../images/archive/debugging/DEBUG_Bug.JPG)
This picture shows a debug view of the LDT environment. You can activate the debug view through the debug icon that is
located in the upper right corner of the LDT.
![](../images/archive/debugging/DEBUG_Tracking.JPG)
Various windows exist to track the content of:
* Variables: local and global variables will appear automatically in the Variables window where used.
* Breakpoints: Breakpoints that are set at lines of various sources, are listed here.
* Expressions: Various expressions can be entered to evaluate a more complex statement.
* Interactive Console: Here you can type in commands that will be executed. Here you can SPAWN for example new groups.
![](../images/archive/debugging/DEBUG_Source.JPG)
This window lists the sources active in Eclipse.
During a debug sessions, the sources where the process is at the moment of debugging, should be loaded automatically.
If not, something is wrong.
All the other sources that are currently open in the LDT are also listed.
![](../images/archive/debugging/DEBUG_Engine.JPG)
This window shows the status of the "attach debug engine".
If this process is running, it will listen to the IP 127.0.0.1 or localhost if setup on your PC.
## 2. Setup your **debug listener** in LDT.
To use the debug enviornment in LDT, you'll need to setup within LDT a " Lua Attach to Application" **debug listener**.
![](../images/archive/debugging/DEBUG_Engine.JPG)
You can access this screen through the LDT editor menu **Run->Debug Configurations...**.
This is the meaning of each field:
* Project: The name of the project that you are debugging within your workspace. You need to have a project registered
here!
* IDE key: this string is used connect the **debug client** to the **debug listener**.
* Timeout: the amount of miliseconds you want DCS World to wait for the **debug listener** to be connecting.
* Source mapping: Select the option "Local Resolution". All the sources are loaded locally from your PC automatically
when debugging.
For the IDE key, this key will be the "link" to the debug connection on the client side!
As will be explained a bit further, `initconnection( "127.0.0.1", 10000, "dcsserver", nil, "win", "" )` will make a
connection on the **debug client**.
Ensure that the IDE key specified matches up in the **debug listener** and the **debug client**.
So in this example, `"dcsserver"` is the IDE key and should match in the debug Configuration panel and the
`initconnection` parameters!
## 3. Setup your **debug client** and attach it to DCS World mission runtime.
This process is essential.
Within the MOOSE repository, there are two important files that you need to consider.
These files are located in the MOOSE repository
[here](https://github.com/FlightControl-Master/MOOSE/tree/master/Moose%20Development/Debugger).
Download the MOOSE repository or the files on your disk, and read further ...
You should have at least on your disk:
* debugger.lua
* READ.ME
* MissionScripting.lua
### 3.1. debugger.lua.
This is the **debug client**. The source is part of the LDT debug suite, but has been modified to work together with the
DCS World scripting engine. You need to copy this file to the root directory of your DCS World installation in
Program Files.
![](../images/archive/debugging/DEBUG_Debugger.JPG)
By example, the location of debugger.lua is here on my DCS World installation PC.
### 3.2. Modify the MissionScripting.lua file.
The READ.ME file is a file that contains an explanation of how to modify the MissionScripting.lua.
But for clarity reasons, I've also attached my version of the MissionScripting.lua.
![](../images/archive/debugging/DEBUG_MissionScripting.JPG)
Take the MissionScripting.lua from the folder, and copy / paste (overwrite) the version in your DCS World installation
directory under the Scripts folder.
If you want, you can first rename the existing MissionScripting.lua file to MissionScripting_old.lua
Don't mistake yourself, a lot of mods/tools modify this file during installation.
Tools like **slmod** etc also change the MissionScripting.lua file (during installation).
So beware that when copying over the file there may be unwanted changes.
If you are using a mod, it is better to do the change manually according the direction in the READ.ME file!
And a validation needs to be done. Once you've modified/overwritten the MissionScripting.lua file, check if the contents
are indeed changed!
Sometimes it seems that the file is saved, but the contents aren't updated due to lack of administration rights and
extra security done by windows.
MissionScripting.lua should contain (at least) the following:
```lua
--Initialization script for the Mission lua Environment (SSE)
dofile('Scripts/ScriptingSystem.lua')
-- Add LuaSocket to the LUAPATH, so that it can be found.
package.path = package.path..";.\\LuaSocket\\?.lua;"
-- Connect to the debugger, first require it.
local initconnection = require("debugger")
-- Now make the connection..
-- "127.0.0.1" is the localhost.
-- 1000 is the timeout in ms on IP level.
-- "dcsserver" is the name of the server. Ensure the same name is used at the
-- Debug Configuration panel! nil (is for transport protocol, but not using this)
-- "win" don't touch. But is important to indicate that we are in a windows
-- environment to the debugger script.
initconnection( "127.0.0.1", 10000, "dcsserver", nil, "win", "" )
-- Sanitize Mission Scripting environment
-- This makes unavailable some unsecure functions.
-- Mission downloaded from server to client may contain potentialy harmful lua
-- code that may use these functions.
-- You can remove the code below and make availble these functions at your own risk.
local function sanitizeModule(name)
_G[name] = nil
package.loaded[name] = nil
end
do
sanitizeModule('os')
--sanitizeModule('io')
sanitizeModule('lfs')
require = nil
loadlib = nil
end
```
Please read through the comment lines for a detailed description what it does.
The io module has been de-sanitized because the debugger.lua needs to use the io module while debugging.
## 4. Setup your .miz file.
When you run a mission in single player in DCS World, a couple of things are happening.
1. The .miz (mission) file that was selected to run, is unzipped in a temp folder on your drive.
2. Each lua file that is included in a DO SCRIPT FILE, is **RENAMED** to a file structure like ~mis__nnnnn__.lua.
This is very bad. Because this prevents you from settings breakpoints at the source file and ensure that the
debugger recognizes the source during run and the location of the breakpoint!
So we need to do something special. The trick is **dynamic loading**.
And believe me, it is the only way to be able to debug your sources.
So this is a little task that you need to learn how to do, but once you understand it, it will become very easy to do.
Instead of executing a DO SCRIPT FILE, you need to add a couple of things in your .miz file.
### 4.1 Conditionalize the DO SCRIPT FILE execution.
Keep the DO SCRIPT FILE line in your mission. Why? Because if you would remove it, and you woudn't debug your code, your
mission file would be deleted. Instead, we are going to put a flag before this part of the execution. A debug flag.
For example, in my mission I put a debug flag 999. When 999 is ON, I would NOT execute the mission file...
Follow this process how to do that... As my recommendation...
![](../images/archive/debugging/DEBUG_Flag.JPG)
Setup a debug flag... If you wanna debug, set flag 999 to ON.
![](../images/archive/debugging/DEBUG_Static.JPG)
Conditionalize the DO SCRIPT FILE execution by evaluating if the 999 is OFF.
### 4.2 Add a dynamic loader to debug your mission script.
Now we are adding a little line.
We are now going to ADD a **dynamic loader** of your mission source.
![](../images/archive/debugging/DEBUG_Dynamic.JPG)
This loads the file dynamically. Instead of a DO SCRIPT FILE, we execute here a DO SCRIPT.
The DO SCRIPT contains a little piece of code that loads your source file from a location on your disk.
![](../images/archive/debugging/DEBUG_Loader.JPG)
This is how my piece of code looks like. I am using a stub of the MOOSE framework to load the file.
`MOOSE.Include( full_path_name, file_name )`
* The `full_path_name` needs to be between quotes, **follows unix folder notation** and **needs to end with a /**
* The `file name` is the full file name, **including the .lua extension**!
If you don't wanna use __Moose.Include, no worries, there is another method.
`_G.loadfile( full_path_name .. file_name )`
The MOOSE.Include loader uses _G.loadfile to load the sources. But it does a bit more checking and logs in dcs.log which
files were dynamically loaded, and from which location!
### 5. Run the **debug listener** on LDT.
Now we are all setup! You've got your **debug listener** setup in LDT, you got your **debug client** setup and connected
to your DCS World environment, and you got your mission file ready for debug!
Now we are going to run a debug. To have a successful debug run, you need to start the listener in LDT.
### 5.1. Setup your debug favorite.
First we setup the Debug as your "favorite", so that it is easy for your to repeat the run easily.
![](../images/archive/debugging/DEBUG_Favorites.JPG)
Click on the "Bug" icon that you'll find in the task bar. The "Bug" icon is the place where you will start your
**debug listener**. However, first, click on Organize Favorites. You need to do this one time only.
![](../images/archive/debugging/DEBUG_Add_Favorites.JPG)
Just click on the Debug Name that you entered (for me DCS 1.5) in the Debug Configuration window and it will be added to
your favorites. I did already that, so it was already added as an example in the previous picture.
### 5.2. Run the **debug listener**.
Now you can easily activate the **debug listener**.
![](../images/archive/debugging/DEBUG_Run_Listener.JPG)
Just click the "Bug" again, and select the **debug listener** that you configured.
![](../images/archive/debugging/DEBUG_Listener.JPG)
When done, you'll see that the **debug listener** is running!
It will be listening quietly to IP 127.0.0.1 on port 100000.
### 6. Set breakpoints.
Open your source file **from the exact location** from where you have specified it to be loaded as part of the
**dynamic loading**. Once it is loaded, you can attach breakpoints within the editor.
![](../images/archive/debugging/DEBUG_Breakpoint.JPG)
How? Right click on the source line number or the grey area before the line, and a pop-up window will appear. Select
"Toggle Breakpoint".
![](../images/archive/debugging/DEBUG_Breakpoint_List.JPG)
As a result, the breakpoint will be listed in the "Breakpoints" list at the debug view, and it will show also the line
number where the breakpoint is set. When your mission runs, the logic will stop at this line!!!
### 7. Run your DCS World mission.
Now it is time to start your DCS World mission. Just run it as you would like have it.
1. The **debug client** (debugger.lua) is loaded as part of the MissionScripting.lua file.
2. The **debug client** connects to the **debug listener** on ldt using 127.0.0.1 using port 10000.
3. Your **mission source** will be **loaded dynamically**.
4. Your mission will start running.
5. Debugger is active and will monitor if a breakpoint has been set at the source currently active during runtime of
your mission.
6. Once it matches a valid breakpoint at a valid source and a specified line, it will stop the logic!
![](../images/archive/debugging/DEBUG_Session.JPG)
### 8. Next steps.
There is a lot to say about debugging and the techniques that you can use how to track the code.
For this, videos will be made in the MOOSE For Dummies video series.
Please consult the youtube channel for more info on debugging.
### 9. Sequel.
When I started to use DCS World (discovered it by accident), I was sold.
After a while I started to discover the SSE capabilities of DCS World and started to code lua.
But a very important piece was missing while developing the MOOSE framework.
**A debugger**.
I've been searching for about 4 years to get this working. There was a huge learning curve.
I had to "hack" myself into the LDT environment and modify the LDT assets to make this work.
There were moments of "clarity" that made me understand how it all fits together.
And now it is there. Wanted to share this for all users of DCS World.
It does require a bit of effort to use this in the DCS World environment, but the little effort
is a small trade against the huge advantages here!
I also encourage you to use the MOOSE Framework, as it brings you a lot of great capabilities
you will never have in any editor. Being able to debug your code, will solve a lot of your questions now!
I hope you will all have fun with the new debug capability and that it may result in greater missions.

View File

@ -0,0 +1,84 @@
---
parent: Archive
nav_order: 2
has_children: true
---
# Mission Designers Guide
MOOSE contains a lot of classes that can be used to enhance your missions.
![MOOSE framework](../images/classes/overview.jpg)
Each section has an overview explanation on the different classes that mission designers can use to design compelling simulation scenarios.
It provides a short explanation of the concepts and its features, as well as important information to know in order to understand how to use the classes.
For more detailed information on the class, you will be guided to more detailed documentation on each individual class.
Click on one of the next section links below to open the guides for each of the major areas that are covered by MOOSE.
## 1. [AI Classes]
AI classes take control over the AI and makes the AI perform various processes.
Some very complicated and enhanced classes are implemented to take control of AI.
It uses the AI to create for you an enhanced simulation experience for your players.
**Apply the AI classes to create a truly dynamic defense and attack system driven by AI.**
## 2. [Tasking Classes]
Tasking classes provide a comprehensive Mission Orchestration System for human players.
Command Centers govern multiple missions to achieve a mission goal.
Within each mission, various tasks are defined, which can be assigned to human players.
Upon completion of each task, a mission goal can be achieved, which will result in score points.
**Join the forces and apply the tasking classes to create a truly dynamic co-operative combat scenario.**
## 3. [Cargo Classes]
Cargo classes provide enhanced means to handle cargo transportation.
Cargo requires a bit more explanation. MOOSE has implemented **a separate system for cargo handling**.
It combines the capabilities of DCS world to combine infantry groups, cargo static objects and static objects
as "cargo" objects.
It also provides you with **AI cargo transportation** classes,
and **Tasking classes for human players**, to transport cargo as part of a mission goal.
In order to use these MOOSE cargo facilities, you'll have to declare those groups and static objects
in a special way within your scripts and/or within the mission editor.
It is not a rocket science, but requires a bit of reading to trying to learn this new method.
Once you've learned this, a new world will open :-)
**Add the cargo capabilities, so that your mission scenarios are dynamically managing the combat resources.**
## 4. [Functional Classes]
MOOSE functional classes provide various functions that are useful in mission design.
These classes vary and enhance the functionality of your simulation scenario.
**Apply various functional classes, to enhance the functionality in your mission scenarios.**
## 5. [Wrapper Classes]
MOOSE wrapper classes provide an object oriented hierarchical mechanism to manage the DCS objects within the simulator.
Wrapper classes provide a greatly enhanced functionality to control groups, units, statics, scenery, airbases etc.
**Make life easy and use the wrapper classes to take control of individual DCS world objects.**
## 6. [Core Classes]
MOOSE core classes define the base building blocks of the MOOSE framework.
The core classes utilize the DCS world core capability and greatly enhance its functionality.
It also provides new mechanisms that provide you with new tools to create your simulation scenarios.
Some of these methods are schedulers, event handlers, menu refreshing, enhanced messaging, sound, flags etc.
**Learn and understand the different core classes, if you want to develop or enhance your mission scenarios.**
[AI Classes]: classes-ai.md
[Tasking Classes]: classes-tasking.md
[Cargo Classes]: classes-cargo.md
[Functional Classes]: classes-functional.md
[Wrapper Classes]: classes-wrapper.md
[Core Classes]: classes-core.md

View File

@ -0,0 +1,76 @@
---
parent: Archive
nav_order: 8
---
# Developers Guide
MOOSE contains a lot of classes that can be used to enhance your missions.
![MOOSE framework](../images/classes/overview.jpg)
Each section has an overview explanation on the different classes that mission designers can use to design compelling simulation scenarios.
It provides a short explanation of the concepts and its features, as well as important information to know in order to understand how to use the classes.
For more detailed information on the class, you will be guided to more detailed documentation on each individual class.
Click on one of the next section links below to open the guides for each of the major areas that are covered by MOOSE.
## 1. [MOOSE AI Classes](classes-ai.md)
AI classes take control over the AI and makes the AI perform various processes.
Some very complicated and enhanced classes are implemented to take control of AI.
It uses the AI to create for you an enhanced simulation experience for your players.
**Apply the AI classes to create a truly dynamic defense and attack system driven by AI.**
## 2. [MOOSE Tasking Classes](classes-tasking.md)
Tasking classes provide a comprehensive Mission Orchestration System for human players.
Command Centers govern multiple missions to achieve a mission goal.
Within each mission, various tasks are defined, which can be assigned to human players.
Upon completion of each task, a mission goal can be achieved, which will result in score points.
**Join the forces and apply the tasking classes to create a truly dynamic co-operative combat scenario.**
## 3. [MOOSE Cargo Classes](classes-cargo.md)
Cargo classes provide enhanced means to handle cargo transportation.
Cargo requires a bit more explanation. MOOSE has implemented **a separate system for cargo handling**.
It combines the capabilities of DCS world to combine infantry groups, cargo static objects and static objects
as "cargo" objects.
It also provides you with **AI cargo transportation** classes,
and **Tasking classes for human players**, to transport cargo as part of a mission goal.
In order to use these MOOSE cargo facilities, you'll have to declare those groups and static objects
in a special way within your scripts and/or within the mission editor.
It is not a rocket science, but requires a bit of reading to trying to learn this new method.
Once you've learned this, a new world will open :-)
**Add the cargo capabilities, so that your mission scenarios are dynamically managing the combat resources.**
## 4. [MOOSE Functional Classes](classes-functional.md)
MOOSE functional classes provide various functions that are useful in mission design.
These classes vary and enhance the functionality of your simulation scenario.
**Apply various functional classes, to enhance the functionality in your mission scenarios.**
## 5. [MOOSE Wrapper Classes](classes-wrapper.md)
MOOSE wrapper classes provide an object oriented hierarchical mechanism to manage the DCS objects within the simulator.
Wrapper classes provide a greatly enhanced functionality to control groups, units, statics, scenery, airbases etc.
**Make life easy and use the wrapper classes to take control of individual DCS world objects.**
## 6. [MOOSE Core Classes](classes-core.md)
MOOSE core classes define the base building blocks of the MOOSE framework.
The core classes utilize the DCS world core capability and greatly enhance its functionality.
It also provides new mechanisms that provide you with new tools to create your simulation scenarios.
Some of these methods are schedulers, event handlers, menu refreshing, enhanced messaging, sound, flags etc.
**Learn and understand the different core classes, if you want to develop or enhance your mission scenarios.**

View File

@ -0,0 +1,339 @@
---
parent: Archive
nav_order: 3
---
# LDT Setup Guide
Using the MOOSE framework is very easy, and this document provides you with a detailed explanation how to install
and use MOOSE within your missions.
## 1.1) MOOSE Framework on GITHUB
For reference, you can find the source code of [MOOSE framework on GitHub].
It is free for download and usage, since it is released under the GNU 3.0 open source license policy.
You don't need to use the source code as an end-user, but it may help to sneak into the code and understand how certain
things are working.
## 1.2) Write your scripts using MOOSE in a normal text editor
You can use the MOOSE framework with a normal text editor. This is perfectly okay.
But you won't have IntelliSense enabled, which is an interactive documentation system that helps you to code correctly!
Therefore, it is highly recommended you use the Eclipse LDT editor, which is explained below.
## 1.2) Eclipse LDT
The LDT environment or "Eclipse Lua Development Tools" is a fully integrated development environment for LUA developers.
It is recommended to use the LDT as your mission design editor using MOOSE.
The MOOSE framework is documented using the lua documentation standard within the MOOSE code.
As a result, every class, method and variable is documented within the source code
and mission designers can write mission script lua code that is **intellisense**(-ed).
What that means is that while you are coding your mission, your object and variables (derived from MOOSE classes)
will list interactively the methods and properties of that class interactively while coding.
![Intellisense](../images/archive/installation/intellisense.jpg)
This highly increases the quality and the speed of your scripting.
## 1.3) LUA training
In order to efficiently use the MOOSE framework, it is highly recommended that you learn a couple of basic principles of
lua. I recommend you learn the basic lua principles following this [lua tutorial](https://www.tutorialspoint.com/lua).
We're not asking you to become an expert in lua, but you'll need to have some basic lua coding knowledge to "understand"
the code, and also, to understand the syntax.
**Therefore, I suggest you walk through this [lua quick guide](https://www.tutorialspoint.com/lua/lua_quick_guide.htm)**.
Ignore the lua environment setup. DCS comes with a pre-defined lua environment.
# 2) Download the latest release of MOOSE
The delivery of MOOSE follows a structured release process.
Over time, new features are added that can be used in your mission.
MOOSE can be downloaded on the main release gage on [GitHub](https://github.com/FlightControl-Master/MOOSE/releases).
**Unzip the files into a directory of your choice, but keep the folder structure intact**.
Also, you'll notice that there are two files included:
- Moose.lua
- Moose_.lua
These are include files that you need to include within your mission.
These files contain ALL the MOOSE code in one file.
See a more detailed explanation below.
# 3) Download the software
## 3.1) Download and install the Eclipse Lua Development Tools **(LDT)**, which is an advanced lua editor.
1. If you don't have JAVA yet, you may have to install [java](https://www.java.com/en/download) first.
2. Download and Install [Eclipse LDT](https://eclipse.org/ldt) on your Windows 64 bit system.
Now you should have a working LDT on your system.
Don't skip this step, LDT is a game-changer.
# 4) Setup the **Moose_Framework project** in LDT.
You need to configure your Eclipse LDT environment and link it with the Moose code.
This will enable you to **start developing mission scripts** in lua, which will be **fully intellisense enabled**!
Please follow the steps outlined!
## 4.1) Create a new **Workspace** in LDT.
The LDT editor has a concept of **Workspaces**, which contains all your settings of your editing environment,
like views, menu options etc and your code. Nothing to pay attention to really, but you need to set it up!
When you open EclipseLDT for the first time, it will ask you where to put your *workspace area*.
1. Open Eclipse LDT.
2. Select the default workspace that LDT suggests.
## 4.2) Setup a **new project** in LDT and name it **Moose_Framework**.
### 4.2.1) Select from the Menu: **File** -> **New** -> **Lua Project**.
![LDT_New_Project](../images/archive/installation/LDT_New_Project.JPG)
Here, we will create a **New Project** called **Moose_Framework** in your LDT environment.
### Important! Name your project **Moose_Framework**
The project details are already defined within the MOOSE framework repository,
which is unzipped in your **local Moose folder** on your PC.
We will link into that directory and **automatically load the Project properties**.
### 4.2.2) Type the Project Name: **Moose_Framework**.
![LDT_Project](../images/archive/installation/LDT_Project.JPG)
### 4.2.3) In the sub-box "Project Contents", select the option **Create Project at existing location** (from existing source).
![LDT_Project](../images/archive/installation/LDT_Project_Existing_Location.JPG)
### 4.2.4) **Browse** to the local MOOSE directory (press on the Browse button) and select the **local Moose folder on your PC, which you unzipped**. Press OK.
### 4.2.5) You're back at the "New Project" dialog box. Press the **Next** button below the dialog box.
__(All the other settings are by default ok)__.
### 4.2.6) You should see now a dialog box with the following properties.
The Moose Development/Moose directory should be flagged as the **Source Directory*. (It is listed totally on top.)
This is important because it will search in the files in this directory and sub directories for lua documentator enabled lua files.
This will enable the intellisense of the MOOSE repository!
![LDT Finish](../images/archive/installation/LDT_Moose_Framework_Finish.JPG)
### 4.2.7) Press the **Finish** button.
As a result, when you browse to the Script Explorer, you'll see the following:
![LDT_Script_Explorer](../images/archive/installation/LDT_Script_Explorer.JPG)
### 4.2.8) **Congratulations! You have now setup your Moose_Framework project LDT environment!**
# 5) Setup a new project **Moose_Missions** in LDT, containing the the Moose demonstration missions.
The framework comes with demonstration missions which can be downloaded
[here](https://github.com/FlightControl-Master/MOOSE_MISSIONS), that you can try out and helps you to code.
These missions provide examples of defined use cases how the MOOSE framework can be utilized.
Each test mission is located in a separate directory, which contains at least one .lua file and .miz file.
The .lua file contains the mission script file that shows how the use case was implemented.
You can copy/paste the code snippets from this .lua file into your missions
This will accellerate your mission developments. You will see, learn and understand how the different MOOSE classes
needs to be applied and how you can create more complex mission scenarios by combining these MOOSE classes into a
complex but powerful mission engine.
Some of these exact test missions are also demonstrated in a video format on the
[YouTube channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg).
- Download the [Moose demonstration missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/) latest release package.
- Unzip the package into a local folder on your PC.
- In LDT, select from the menu **New lua project**, and name it Moose_Missions.
- Select the local folder on your PC, where you saved the demonstration missions contents.
- Press Finish
# 6) Setup Your first mission
## 6.1) Setup a new project in LDT and name it **My_Missions**
In order to design your own missions, it is recommended you create a separate directory on your PC
which contains your mission files. Your mission will be designed consisting possibly
out of a couple of components, which are:
* (Mandatory) An include of the **Moose.lua** file (see chapter 2 above).
* (Mandatory) An include of your lua mission script file(s) (also with a .lua extension).
* (Optionally) Sound files (.ogg) and pictures (.jpg) which are added into your mission.
Using the menu system of the DCS World Mission Editor, you need to include files in your mission (.miz) file.
However, once included, maintaining these files is a tedious task,
having to replace each time manually these files when they change
(due to a new release or a change in your mission script).
Therefore, **the recommendation is that your create for each mission a separate folder**.
The MOOSE test mission folder structure is a good example how this could be organized.
The LDT has been customized and provides a tool to **automatically** maintain your existing .miz files.
### 6.1.1. Select from the Menu: **File** -> **New** -> **Lua Project**.
![LDT_New_Project](../images/archive/installation/LDT_New_Project.JPG)
### 6.1.2. A **New Project** dialog box is shown.
![LDT_Project](../images/archive/installation/LDT_Project.JPG)
### 6.1.3. Type your Project Name: (In my example it is **DCS_Caucasus_Missions**.
Note the indicated options in yellow:
* Note that you can select the option **No execution environment**.
* Deselect the option **Create default project template ready to run**.
![LDT_Project](../images/archive/installation/LDT_Project_My_Missions.JPG)
### 6.1.4. Press **Next >**
### 6.1.5. Click the **Projects** tab at the top of the window.
![LDT_Project](../images/archive/installation/LDT_New_Project_Projects.JPG)
### 6.1.6. Press the **Add...** button.
### 6.1.7. A new windows will be displayed: **Required Project Selection**.
This is an important step. This will _link_ your project to the Moose_Framework project and will activate **intellisense**.
![LDT_Project](../images/archive/installation/LDT_Select_Moose_Framework.JPG)
### 6.1.8. After the selection, press the **OK** button.
### 6.1.9. Watch your newly created project in the Script Explorer of LDT.
You can delete the possibly created SRC directory. You won't need it at all.
![LDT_Project](../images/archive/installation/LDT_Delete_Src.JPG)
### 6.1.10. Within your newly created Missions Project, right click and select **New -> Folder**.
As explained above, each of your missions will be stored in a separate folder. Please follow the explanation how to do that.
![LDT_Project](../images/archive/installation/LDT_Add_Folder.JPG)
### 6.1.11. Type the **Folder Name**.
This can be any descriptive text explaining the title of your mission.
![LDT_Project](../images/archive/installation/LDT_Mission_Folder_Name.JPG)
### 6.1.12. In your newly created **Mission Folder**, right click and select **New -> Lua File**.
This will create your **mission script file**,
the file that contains all the lua code using the Moose framework using your mission.
### 6.1.13. Type the **Lua Mission Script Name**.
![LDT_Project](../images/archive/installation/LDT_Mission_Lua_File_Name.JPG)
## 6.2) Create your first Mission file
In the root of the MOOSE package, a file named **Moose.lua** can be found.
In order to create or design a mission using the MOOSE framework,
you'll have to include this **Moose.lua** file into your missions:
1. Create a new mission in the DCS World Mission Editor.
2. In the mission editor, create a new trigger.
3. Name the trigger Moose Load and let it execute only at MISSION START.
4. Add an action DO SCRIPT FILE (without a condition, so the middle column must be empty).
5. In the action, browse to the **Moose.lua** file and include this file within your mission.
6. Make sure that the "Moose Load" trigger is completely at the top of your mission.
Voila, MOOSE is now included in your mission. During the execution of this mission, all MOOSE classes will be loaded
and all MOOSE initializations will be exectuted before any other mission action is executed.
Find below a detailed explanation of the actions to follow:
### 6.2.1. Open the Mission Editor in DCS, select an empty mission, and click the triggers button.
![LDT_Project](../images/archive/installation/DCS_Triggers_Empty.JPG)
### 6.2.2. Add a new trigger, that will load the Moose.lua file.
Check the cyan colored circles:
* This trigger is loaded at MISSION START.
* It is the first trigger in your mission.
* It contains a DO SCRIPT FILE action.
* No additional conditions!
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Moose_Add.JPG)
### 6.2.3. Select the Moose.lua loader from the **Moose Mission Setup** folder in the Moose_Framework pack.
Additional notes:
* If you've setup a folder link into Saved Games/DCS/Missions/Moose Mission Setup, then you can directly select this
folder from **My Missions**.
* See point ...
Press the **OK** button.
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Moose_Select_File.JPG)
### 6.2.4. Check that the Moose.lua file has been correctly added to your Mission.
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Moose_File_Added.JPG)
### 6.2.5. Add a new trigger, that will load your mission .lua file.
Check the cyan colored circles:
* This trigger is loaded at MISSION START.
* It is the second trigger in your mission.
* It contains a DO SCRIPT FILE action.
* No additional conditions!
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Mission_Add.JPG)
### 6.2.6. Select the mission .lua file from your **missions** folder you just created or already have.
Additional notes:
* If you've setup a folder link into Saved Games/DCS/Missions/Moose Mission Setup, then you can directly select this folder from **My Missions**.
* See point ...
Press the **OK** button.
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Mission_File_Select.JPG)
### 6.2.7. Check that your mission .lua script file has been correctly added to your mission.
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Mission_File_Added.JPG)
## 6.3) Maintain your .miz files
IMPORTANT NOTE: When a new version of MOOSE is released, you'll have to UPDATE the Moose.lua file in EACH OF YOUR MISSION.
This can be a tedious task, and for this purpose, a tool has been developed that will update the Moose.lua files automatically within your missions.
### 6.3.1. Select the **Update SELECTED Mission** from the External Tools in LDT.
This will activate a script that will automatically re-insert your mission .lua file into your mission.
![LDT_Project](../images/archive/installation/DCS_Triggers_Load_Mission_File_Added.JPG)
## 6.4) Create folder links into your "My Missions" folder in Saved Games/DCS/Missions.
***TODO : Detail how hard links work, explain how they help the wworkflow***
This trick will save you a lot of time. You need to install the tool ... to create easily new links.
Select from the following possible links that can be created to save you time while browing through the different folders to include script files:
### 6.4.1. Create a link to your **Moose Mission Setup** folder ...
### 6.4.2. Create a link to your **missions** folder ...
[MOOSE framework on GITHUB]: https://www.github.com/FlightControl-Master/MOOSE/

View File

@ -0,0 +1,78 @@
---
parent: Archive
nav_order: 1
---
# Starters Guide
## 1. MOOSE is an Object Oriented system.
MOOSE is an Object Oriented framework which provides different **classes** that take control of your simulation scenario.
### 1.1. Classes ...
* **AI** - Take control of the AI controlled groups and units to execute specific tasks and processes.
* **Tasking** - Assign tasks to human players, and let them achieve goals for logical missions setup in your simulation scenario.
* **Functional** - Apply additional functionalities on top of the standard DCS simulation capabilities.
* **Cargo** - Declare cargo objects, which are handled by moose in various ways.
* **Wrapper** - The default dcs classes are wrapped by moose wrapper classes, and provide additional funtionality and easier access.
* **Core** - The default dcs simulation capabilities are enhanced by moose, and provide additional functionality and easier access.
You as a mission designer are required to study each class features, and evaluate whether you want to apply
those features as part of your mission scenario.
### 1.2. Objects ...
If you want to apply a class, you need to **instantiate** the class by creating an **object** of that class.
Look at a **class** like the **definition of a process**, and the **object** **applies the process**.
Multiple objects can be created of the same class, and this is the power of an Object Oriented system.
These objects combine the combine **Methods** and **Variables**/**Properties** of the class as one encapsulated structure, that
hold state and work independently from each other!
Look at the following example:
Here we use the SPAWN class, which you can use to spawn new groups into your running simulation scenario.
The SPAWN class simplifies the process of spawning, and it has many methods to spawn new groups.
```lua
-- This creates a new SpawnObject from the SPAWN class,
-- using the constructor :New() to instantiate a new SPAWN object.
-- It will search for the GroupName as the late activated group defined within your Mission Editor.
-- If found, the object "SpawnObject" will now contain a "copy" of the SPAWN class to apply the spawning process.
local SpawnObject = SPAWN:New( "GroupName" )
-- Nothing is spawned yet..., so let's use now the SpawnObject to spawn a new GROUP.
-- We use the method :Spawn() to do that.
-- This method creates a new group from the GroupName template as defined within the Mission Editor.
local SpawnGroup = SpawnObject:Spawn()
```
### 1.3. Inheritance ...
MOOSE classes **derive or inherit** from each other, that means,
within MOOSE there is an **inheritance** structure.
The different moose classes are re-using properties and methods from its **parent classes**.
This powerful concept is used everywhere within the MOOSE framework.
The main (Parent) Class in the MOOSE framework is the BASE class.
Every MOOSE Class is derived from this top BASE Class.
So is also the SPAWN class derived from the BASE class.
The BASE class provides powerful methods for debugging,
event handling and implements the class handling logic.
As a normal MOOSE user, you won't implement any code using inheritance,
but just know that the inheritance structure is omni present in the intellisense and documentation.
You'll need to browse to the right MOOSE Class within the inheritance tree structure,
to identify which methods are properties are defined for which class.
## 2. MOOSE Demonstration Missions
The framework comes with demonstration missions which can be downloaded [here](https://github.com/FlightControl-Master/MOOSE_MISSIONS/), that you can try out and helps you to code.
These missions provide examples of defined use cases how the MOOSE framework can be utilized. Each test mission is located in a separate directory, which contains at least one .lua file and .miz file.
The .lua file contains the mission script file that shows how the use case was implemented.
You can copy/paste code the code snippets from this .lua file into your missions, as it will accellerate your mission developments.
You will learn, see, and understand how the different MOOSE classes need to be applied, and how you can create
more complex mission scenarios by combining these MOOSE classes into a complex but powerful mission engine.
Some of these exact test missions are also demonstrated in a video format on the [YouTube channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg).

159
docs/archive/guide-usage.md Normal file
View File

@ -0,0 +1,159 @@
---
parent: Archive
nav_order: 9
---
# Usage Guide
## 1. MOOSE is an Object Oriented system.
MOOSE is an Object Oriented framework which provides different **classes** that take control of your simulation scenario.
### 1.1. Classes ...
* **AI** - Take control of the AI controlled groups and units to execute specific tasks and processes.
* **Tasking** - Assign tasks to human players, and let them achieve goals for logical missions setup in your
simulation scenario.
* **Functional** - Apply additional functionalities on top of the standard DCS simulation capabilities.
* **Cargo** - Declare cargo objects, which are handled by moose in various ways.
* **Wrapper** - The default dcs classes are wrapped by moose wrapper classes, and provide additional funtionality and
easier access.
* **Core** - The default dcs simulation capabilities are enhanced by moose, and provide additional functionality and
easier access.
You as a mission designer are required to study each class features, and evaluate whether you want to apply
those features as part of your mission scenario.
### 1.2. Objects ...
If you want to apply a class, you need to **instantiate** the class by creating an **object** of that class.
Look at a **class** like the **definition of a process**, and the **object** **applies the process**.
Multiple objects can be created of the same class, and this is the power of an Object Oriented system.
These objects combine the combine **Methods** and **Variables**/**Properties** of the class as one encapsulated
structure, that hold state and work independently from each other!
Look at the following example:
Here we use the SPAWN class, which you can use to spawn new groups into your running simulation scenario.
The SPAWN class simplifies the process of spawning, and it has many methods to spawn new groups.
```lua
-- This creates a new SpawnObject from the SPAWN class,
-- using the constructor :New() to instantiate a new SPAWN object.
-- It will search for the GroupName as the late activated group defined within your Mission Editor.
-- If found, the object "SpawnObject" will now contain a "copy" of the SPAWN class to apply the spawning process.
local SpawnObject = SPAWN:New( "GroupName" )
-- Nothing is spawned yet..., so let's use now the SpawnObject to spawn a new GROUP.
-- We use the method :Spawn() to do that.
-- This method creates a new group from the GroupName template as defined within the Mission Editor.
local SpawnGroup = SpawnObject:Spawn()
```
### 1.3. Inheritance ...
MOOSE classes **derive or inherit** from each other, that means,
within MOOSE there is an **inheritance** structure.
The different moose classes are re-using properties and methods from its **parent classes**.
This powerful concept is used everywhere within the MOOSE framework.
The main (Parent) Class in the MOOSE framework is the BASE class.
Every MOOSE Class is derived from this top BASE Class.
So is also the SPAWN class derived from the BASE class.
The BASE class provides powerful methods for debugging,
event handling and implements the class handling logic.
As a normal MOOSE user, you won't implement any code using inheritance,
but just know that the inheritance structure is omni present in the intellisense and documentation.
You'll need to browse to the right MOOSE Class within the inheritance tree structure,
to identify which methods are properties are defined for which class.
## 2. MOOSE Framework Classes
MOOSE contains a lot of classes that can be used to enhance your missions.
![MOOSE framework](../images/classes/overview.jpg)
Each section has an overview explanation on the different classes that mission designers can use to design compelling
simulation scenarios. It provides a short explanation of the concepts and its features, as well as important information
to know in order to understand how to use the classes.
For more detailed information on the class, you will be guided to more detailed documentation on each individual class.
Click on one of the next section links below to open the guides for each of the major areas that are covered by MOOSE.
### 2.1. [MOOSE AI Classes](classes-ai.md)
AI classes take control over the AI and makes the AI perform various processes.
Some very complicated and enhanced classes are implemented to take control of AI.
It uses the AI to create for you an enhanced simulation experience for your players.
**Apply the AI classes to create a truly dynamic defense and attack system driven by AI.**
### 2.2. [MOOSE Tasking Classes](classes-tasking.md)
Tasking classes provide a comprehensive Mission Orchestration System for human players.
Command Centers govern multiple missions to achieve a mission goal.
Within each mission, various tasks are defined, which can be assigned to human players.
Upon completion of each task, a mission goal can be achieved, which will result in score points.
**Join the forces and apply the tasking classes to create a truly dynamic co-operative combat scenario.**
### 2.3. [MOOSE Cargo Classes](classes-cargo.md)
Cargo classes provide enhanced means to handle cargo transportation.
Cargo requires a bit more explanation. MOOSE has implemented **a separate system for cargo handling**.
It combines the capabilities of DCS world to combine infantry groups, cargo static objects and static objects
as "cargo" objects.
It also provides you with **AI cargo transportation** classes,
and **Tasking classes for human players**, to transport cargo as part of a mission goal.
In order to use these MOOSE cargo facilities, you'll have to declare those groups and static objects
in a special way within your scripts and/or within the mission editor.
It is not a rocket science, but requires a bit of reading to trying to learn this new method.
Once you've learned this, a new world will open :-)
**Add the cargo capabilities, so that your mission scenarios are dynamically managing the combat resources.**
### 2.4. [MOOSE Functional Classes](classes-functional.md)
MOOSE functional classes provide various functions that are useful in mission design.
These classes vary and enhance the functionality of your simulation scenario.
**Apply various functional classes, to enhance the functionality in your mission scenarios.**
### 2.5. [MOOSE Wrapper Classes](classes-wrapper.md)
MOOSE wrapper classes provide an object oriented hierarchical mechanism to manage the DCS objects within the simulator.
Wrapper classes provide a greatly enhanced functionality to control groups, units, statics, scenery, airbases etc.
**Make life easy and use the wrapper classes to take control of individual DCS world objects.**
### 2.6. [MOOSE Core Classes](classes-core.md)
MOOSE core classes define the base building blocks of the MOOSE framework.
The core classes utilize the DCS world core capability and greatly enhance its functionality.
It also provides new mechanisms that provide you with new tools to create your simulation scenarios.
Some of these methods are schedulers, event handlers, menu refreshing, enhanced messaging, sound, flags etc.
**Learn and understand the different core classes, if you want to develop or enhance your mission scenarios.**
## 3. MOOSE Demonstration Missions
The framework comes with demonstration missions which can be downloaded
[here](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases), that you can try out and helps you to code.
These missions provide examples of defined use cases how the MOOSE framework can be utilized. Each test mission is
located in a separate directory, which contains at least one .lua file and .miz file.
The .lua file contains the mission script file that shows how the use case was implemented.
You can copy/paste code the code snippets from this .lua file into your missions, as it will accellerate your mission
developments.
You will learn, see, and understand how the different MOOSE classes need to be applied, and how you can create
more complex mission scenarios by combining these MOOSE classes into a complex but powerful mission engine.
Some of these exact test missions are also demonstrated in a video format on the
[YouTube channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg).

132
docs/archive/index.md Normal file
View File

@ -0,0 +1,132 @@
---
title: Archive
has_children: true
nav_order: 99
has_toc: false
---
# Archive
{: .important }
> This documentation is outdated! We are working on new a documentation.
Here you can find the guides written by FlightControl in the past.
Most of the informations are still valid. But we want to create a more up-to-date
documentation in the future.
The first step to do this, is to consolidate the differents versions of the
documentation from [MOOSE_DOCS] and [MOOSE_DOCS_DEVELOP] into this place.
After that we can create a new documentation step by step.
[MOOSE_DOCS]: https://github.com/FlightControl-Master/MOOSE_DOCS
[MOOSE_DOCS_DEVELOP]: https://github.com/FlightControl-Master/MOOSE_DOCS_DEVELOP
![MOOSE](../images/classes/overview.jpg)
MOOSE is a **M**ission **O**bject **O**riented **S**cripting **E**nvironment, and is meant for mission designers and
mission hosters. It allows to quickly setup complex missions using pre-scripted scenarios using the available classes
within the MOOSE Framework. MOOSE works with the current DCS world and earlier versions.
## Starters guide
You need to write lua code (scripts) to apply the MOOSE framework. But it is not really that hard, if you understand
a couple of principles. Read more in the [Starters Guide](guide-starters.md).
## Mission Designers Guide
This section is meant for those who really want to start using MOOSE and write lua scripts for their missions.
The section provides a comprehensive overview of the different classes that form the complete MOOSE framework.
Here you find a high-level explanation and features, how to:
* Setup AI dispatchers to create complex and coordinated AI behaviour.
* Cargo handling
* Setup task dispatchers for Mission completion
* How to use MOOSE wrapper classes
* The different components of the core MOOSE engine
Read more in the [Mission Designers Guide](guide-designers.md).
Each class will link you further down into the MOOSE Classes guide, for more detailed information on each MOOSE class.
## MOOSE Classes Guide
Here you can find detailed documentation for each MOOSE class.
Click on the hamburger menu on the left upper corner of each page to navigate to other MOOSE classes.
- `master` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS/>
- `develop` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/>
## MOOSE Setup
The delivery of MOOSE follows a structured release process. Over time, new features are added that can be used in your mission.
The latest release of MOOSE can be downloaded [here](https://github.com/FlightControl-Master/MOOSE/releases).
There are 3 different ways how you can use MOOSE, each with a different engagement and complexity level:
### Setup for Mission Designers
This section shows how to setup a development environment for Mission Designers using the MOOSE framework.
- Download and install Java.
- Setup Lua Development Tools IDE (from the Eclipse suite).
- Setup a logging tool.
- Tweak your DCS environment.
Please read the detailed [LDT Setup Guide](guide-setup-ldt.md) for more information.
### Setup for Beta tester guide
Beta testers of MOOSE are requested to install additional software.
As a return or as a reward, testers get:
* Newly developed features planned for the next MOOSE release can be tested and incorporated in your missions early.
* You can evaluate and contribute to the stability of the next release.
* Your mission creation workflow becomes very flexible. New features are dynamically added to you missions.
Please read the detailed [Beta Tester Guide](guide-beta-tester.md) for more information.
### Contribute on the MOOSE development
Those people who have experience in lua development or are excited to contribute to the MOOSE project are welcome.
Please consult the [Contribution Guide](guide-contribution.md) for more information.
### Debug your code interactively using LDT
Have a look at the [Interactive Debugging](guide-debug.html) to setup your system so you can debug your mission code.
## MOOSE Support Channels
MOOSE is broadcasted, documented and supported through various social media channels.
Click here for the [Communities Guide](guide-communities.md) of the MOOSE framework.
## MOOSE framework goal
The goal of MOOSE is to allow mission designers to **enhance the mission designs** by using **mission orchestration objects**,
which can be _instantiated_ from defined classes within the framework.
This will allow to write exciting missions and multi player cooperative operation scenarios.
Of course, the richness of the framework will determine the richness of the misson scenarios.
The MOOSE is a service that is produced while being consumed ... ,
it will evolve further as more classes are developed for the framework, and as more users are using it.
MOOSE is NOT meant to be a one-man show, it is meant to evolve within a growing community around the framework.
Within the community, key users will support, document, explain and even create new classes for the framework.
It is the ambition to grow this framework as a de-facto standard for mission designers to use within the DCS World community.
## MOOSE community on Discord
Join our MOOSE community on Discord.
A place where mission designers and developers come together to discuss the latest features.
There are a lot of people supporting Mission Designers on [Discord](https://discord.gg/gj68fm969S).
Thank you!
The Moose Team

19
docs/beginner/index.md Normal file
View File

@ -0,0 +1,19 @@
---
has_children: true
nav_order: 2
---
# Beginner
In this section we will add all informations needed for your first steps using
MOOSE.
{: .note }
> This documentation is WIP (work in progress) and it will take some time to
> fill it with usefull and up to date informations. Please be patient and check
> back here from time to time to see if there is anything new for you.
If you cannot find the information you are looking for here in the new
documentation, please take a look at the [archive].
[archive]: ../archive/index.md

View File

@ -0,0 +1,29 @@
---
parent: Beginner
nav_order: 99
---
# Tipps and tricks
{: .no_toc }
1. Table of contents
{:toc}
This section we put a lot of usefull informations needed by beginners.
## Find the installation folder of DCS
It depends on the platform and the version you choosed to install:
- [DCS World Steam Edition]{:target="_blank"} from Steam.
- To find the folder right click on the game in Steam.
- Open Properties / Installed Files / Browse
- [DCS World Standalone installer]{:target="_blank"} from Eagle Dynamics website.
- Default installation locations:
- Stable: C:\Program Files\Eagle Dynamics\DCS World
- OpenBeta: C:\Program Files\Eagle Dynamics\DCS World.Openbeta
- If you changed the installation folder of the Standalone version, right
click on the game icon, open Properties and click on `Open File Location`.
[DCS World Steam Edition]: https://store.steampowered.com/app/223750/DCS_World_Steam_Edition/
[DCS World Standalone installer]: https://www.digitalcombatsimulator.com/en/downloads/world/

View File

@ -1,5 +1,6 @@
--- ---
parent: Build system parent: Build system
grand_parent: Developer
nav_order: 2 nav_order: 2
--- ---
@ -56,6 +57,25 @@ Main build steps to create the class documentation are defined in [.github/workf
- Copy build result to `MOOSE_DOCS` folder. - Copy build result to `MOOSE_DOCS` folder.
- Push results to the target repository. - Push results to the target repository.
# Build a preview locally
To generate a preview of the class documentation go into the folder
`docker/build-docks` and run `docker compose up`. It will create a Docker image
and start a Docker container. Within this container all needed software packages
are included to build to class documentation.
- You need a working installation of [Docker].
- In the main repository folder a new folder `build` will be created.
- Subfolders `build/docs` and `build/tools` will be generated.
- Repo `Applevangelist/luadocumentor` will be checked out to `build/tools/luadocumentor`
- `luadocumentor.lua` will be executed and writes the output to `build/docs`.
{: .note }
> If [MOOSE_DOCS] is checked out to `/moose/build/MOOSE_DOCS` by the developer
> manually, then the generated files are also copied into `/moose/build/MOOSE_DOCS/Documentation/`.
> This allows to run `docker compose up` in `/moose/build/MOOSE_DOCS/docker/`,
> so the full result can be checked.
[tree]: https://wiki.ubuntuusers.de/tree/ [tree]: https://wiki.ubuntuusers.de/tree/
[LuaDoc]: https://keplerproject.github.io/luadoc/ [LuaDoc]: https://keplerproject.github.io/luadoc/
[LuaDocumentor]: https://luarocks.org/modules/luarocks/luadocumentor [LuaDocumentor]: https://luarocks.org/modules/luarocks/luadocumentor
@ -71,3 +91,4 @@ Main build steps to create the class documentation are defined in [.github/workf
[Lua]: https://www.lua.org/ [Lua]: https://www.lua.org/
[LuaRocks]: https://luarocks.org/ [LuaRocks]: https://luarocks.org/
[.github/workflows/build-docs.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-docs.yml [.github/workflows/build-docs.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-docs.yml
[Docker]: https://www.docker.com/

View File

@ -1,5 +1,6 @@
--- ---
parent: Build system parent: Build system
grand_parent: Developer
nav_order: 1 nav_order: 1
--- ---
@ -21,8 +22,8 @@ Main build steps to create the include files are defined in [.github/workflows/b
- Run the build steps: - Run the build steps:
- Run `./Moose Setup/Moose_Create.lua` to create `Moose.lua`. - Run `./Moose Setup/Moose_Create.lua` to create `Moose.lua`.
- Run `./Moose Setup/Moose_Create.lua` to create dynamic `Moose.lua` to - Run `./Moose Setup/Moose_Create.lua` to create dynamic `Moose.lua` which
load individual Lua class files used by Moose developers. loads individual Lua class files used by Moose developers.
- Run [LuaSrcDiet] to compress the [Lua] code and create `Moose_.lua` - Run [LuaSrcDiet] to compress the [Lua] code and create `Moose_.lua`
- Run [LuaCheck] to find errors in the code. Warnings are ignored, because - Run [LuaCheck] to find errors in the code. Warnings are ignored, because
there are a lot of warnings, which cannot be resolved by the Moose team. there are a lot of warnings, which cannot be resolved by the Moose team.
@ -34,6 +35,23 @@ Main build steps to create the include files are defined in [.github/workflows/b
- Copy build result to `MOOSE_INCLUDE` folder - Copy build result to `MOOSE_INCLUDE` folder
- Push results to [MOOSE_INCLUDE] repository - Push results to [MOOSE_INCLUDE] repository
# Build a preview locally
To generate a preview of the include files go into the folder
`docker/build-includes` and run `docker compose up`. It will create a Docker
image and start a Docker container.
Within this container all needed software packages are included to build the
include files.
- You need a working installation of [Docker].
- In the main repository folder a new folder `build` will be created.
- The following subfolders will be generated:
- `build/result/Moose_Include_Dynamic` and
- `build/result/Moose_Include_Static`
- `./Moose Setup/Moose_Create.lua` will be executed to generate the target files
- [LuaSrcDiet] will be executed to generate the target file `Moose_.lua`
- [LuaCheck] runs to find errors
[.github/workflows/build-includes.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-includes.yml [.github/workflows/build-includes.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-includes.yml
[tree]: https://wiki.ubuntuusers.de/tree/ [tree]: https://wiki.ubuntuusers.de/tree/
[lua5.3]: https://www.lua.org/manual/5.3/ [lua5.3]: https://www.lua.org/manual/5.3/
@ -43,3 +61,4 @@ Main build steps to create the include files are defined in [.github/workflows/b
[MOOSE_INCLUDE]: https://github.com/FlightControl-Master/MOOSE_INCLUDE [MOOSE_INCLUDE]: https://github.com/FlightControl-Master/MOOSE_INCLUDE
[LuaSrcDiet]: https://github.com/jirutka/luasrcdiet [LuaSrcDiet]: https://github.com/jirutka/luasrcdiet
[Lua]: https://www.lua.org/ [Lua]: https://www.lua.org/
[Docker]: https://www.docker.com/

View File

@ -1,5 +1,6 @@
--- ---
parent: Build system parent: Build system
grand_parent: Developer
nav_order: 3 nav_order: 3
--- ---
@ -37,6 +38,20 @@ This can be displayed as follows:
- Open a browser with the following URL: `http://127.0.0.1:4000/`. - Open a browser with the following URL: `http://127.0.0.1:4000/`.
- After a change of the [Markdown] files, wait some seconds and press F5 in the browser. - After a change of the [Markdown] files, wait some seconds and press F5 in the browser.
{: .warning }
> Some changes are not processed properly with this procedure. It is then
> necessary to stop and restart the container once. On startup everything is
> always regenerated.
# Run linkinator to find brocken links
When changing this documentation it is very useful to run linkinator to find broken links.
This can be done as follows:
- You need a working installation of [Docker].
- Go to the `docker/gh-pages-check` subfolder.
- Run `docker compose up`.
[GitHub Pages]: https://pages.github.com/ [GitHub Pages]: https://pages.github.com/
[MOOSE]: https://github.com/FlightControl-Master/MOOSE [MOOSE]: https://github.com/FlightControl-Master/MOOSE
[Just the Docs]: https://github.com/just-the-docs/just-the-docs [Just the Docs]: https://github.com/just-the-docs/just-the-docs

View File

@ -1,6 +1,9 @@
--- ---
layout: default
title: Build system
parent: Developer
has_children: true has_children: true
nav_order: 3 nav_order: 99
--- ---
# Build system # Build system

View File

@ -1,5 +1,6 @@
--- ---
parent: Build system parent: Build system
grand_parent: Developer
nav_order: 4 nav_order: 4
--- ---

21
docs/developer/index.md Normal file
View File

@ -0,0 +1,21 @@
---
title: Developer
has_children: true
nav_order: 4
---
# Developer
All information in this section is primarily intended for developers who extend
or maintain the Moose program code. Of course, this information may also be of
interest to others who want to learn more about the background of MOOSE.
{: .note }
> This documentation is WIP (work in progress) and it will take some time to
> fill it with usefull and up to date informations. Please be patient and check
> back here from time to time to see if there is anything new for you.
If you cannot find the information you are looking for here in the new
documentation, please take a look at the [archive].
[archive]: ../archive/index.md

View File

@ -4,6 +4,7 @@ services:
jekyll: jekyll:
build: build:
context: ./ context: ./
image: moose/docs
ports: ports:
- 4000:4000 - 4000:4000
volumes: volumes:

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

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