Introduction

By connecting DCS Mission Scripting lua environment and LotAtc Server you enable:

  • Instructor module with DCS

Installation / Configuration

DCS World modification

Mandatory to have weather updates with dedicated server

DCS Server owner need to patch a file in DCS World directory to enable external socket connection to LotAtc Server.

The file to modify is DCS World/Scripts/MissionScripting.lua, you have to add the line:

dofile('Scripts/ScriptingSystem.lua')

-- The following line must be added
dofile(lfs.writedir().."Mods\\services\\LotAtc\\lua utils\\lotatcMissionServer.lua")

Be careful, on each DCS update, this file will be reverted and you have to do the modification again, use OvGME or equivalent is certainly a good idea

Once done, no more modification EVEN if LotAtc Server is updated.

LotAtc Server Configuration

You need to enable Json server in LotAtc Configurator.

image-left

The default port is 8081, if you run several DCS instances, please modify it here. YOU ALSO NEED TO EDIT the lotatcMissionServer.lua file to change the port also !!!

In lotatcMissionServer.lua:

-- Customization (adapt if you need)
lotatcLink.port = 8081 -- LotAtc port

Mission script

Only need to use Advanced Instructor orders with DCS

If you want LotAtc Server interaction with your mission, you have to add the trigger DO SCRIPT FILE and the line:

example.lua

image-left

In this example, I load first Moose.lua, then add some radio item, then load my example.lua file that will use LotAtcLink and Moose.

Once done, no more need to modify Mission file even on LotAtc Upgrade, all is done in background for you

Tutorial

Here you will find some fast steps to test (or integrate) DCS AI interaction.

  1. Add the line in DCS World/Scripts/ScriptingSystem.lua as explained in DCS World Modification above. (only need for DCS Host):
  2. In Mission Editor, add a DO SCRIPT FILE with Moose.lua file you can grab there
  3. Add a DO SCRIPT FILE with example.lua file you find in your DCS Server mods/services/LotAtc/lua utils/example.lua image-left
  4. Add an awacs and some random units
  5. Launch the mission (can be done from mission editor)
  6. Connect with LotAtc Advanced and connect with admin rights
  7. Use Alt+right click on any unit to change its heading, see here

Dev Area

Introduction

LotAtc Link provides a two-way communication with LotAtc Server. It is in early developpement but possibility are huge:

  • Moving IA
  • Create/Destroy any unit
  • Interact with lua mission flag

As LotAtc is always opened to others projects, the choice has been made to open this link to anybody in order for the interface to be implemented by any lua framework (pure DCS lua, Moose, Mist,…).

I hope that a community can be created around LotAtc Link in order to build fantastic mission with it!

Want to help ?

Join LotAtc Discord and join the #mission-lua-scripting channel!

API

When using LotAtcLink you have to connect your code to LotAtcLink callbacks:

See Saved Games\<DCS Instance>\mods\services\LotAtc\lua utils\example.lua as example.

Here is a complete example to make IA turning with LotAtc Advanced!

    --[[
Here is a simple example to use with lotatcMissionServer
]]--

env.info("initializing My LotAtc Link example...")
local LCallbacks = {}
--------------------------------------------------------------
-- LotAtc Link mission script example file
-- Copyright RBorn Software
-- Author: DArt - LotAtc
-- You can modify and adapt it
--------------------------------------------------------------
LCallbacks.command_status = function(env, msg)
    env.info("LotAtcLink: have version ".. msg.version)
    local _s = string.format("trigger.action.outText('LotAtcLink is connected with LotAtc %s', 10 )", msg.version)
    local f, error_msg = loadstring(_s, "LotAtcLink")
    if f then
        setfenv(f, lotatcLink.mission_env)
        local success, result = pcall(f)
        if success then 
            env.info("LotAtcLink: success")
        else
            env.info("LotAtcLink: failed")
            env.info( error_msg )
            env.info( result )
        end
    end
end
--------------------------------------------------------------
LCallbacks.command_order = function(env, msg)
    if msg.orders then
        env.info("LotAtcLink: receive order")
        for i, order in pairs(msg.orders) do
            env.info("------ Treat order")
            env.info("   o " .. order.order_name )
            local _group = nil
            if order.group_name then
                env.info("   o " .. order.group_name )
                env.info("   o " .. order.unit_name )
                _group = GROUP:FindByName( order.group_name )
            end
            if _group and (_group:GetPlayerCount() == 0 ) then
                --env.info( "Found!" )
                if order.order_name == "object" then
                    loe_order(env,order, _group )
                elseif order.order_name == "delete" then
                    env.info("   o delete")
                    _group:Destroy(true)
                elseif order.order_name == "command" then
                    loe_command(env,order, _group )
                end
            end
        end
    end
end

--------------------------------------------------------------
loe_order = function(env, order, _group)
    env.info("   o " .. order.property )
    
    if order.property == "headingDeg" then
        loe_order_headingDeg(env, order, _group)
    elseif order.property == "altitude" then
        loe_order_altitude(env, order, _group)
    elseif order.property == "position" then
        loe_order_position(env, order, _group)
    else
        env.info("-- Not yet supported --")
    end
end

--------------------------------------------------------------
loe_order_headingDeg = function( env, order, _group )
    env.info( "change heading to " .. order.value )
    FromCoord = _group:GetCoordinate()
    ToCoord = FromCoord:Translate( 1000000, tonumber(order.value) )
    RoutePoints = {}
    RoutePoints[#RoutePoints+1] = FromCoord:WaypointAirFlyOverPoint( "BARO", _group:GetVelocityKMH())
    RoutePoints[#RoutePoints+1] = ToCoord:WaypointAirFlyOverPoint( "BARO", _group:GetVelocityKMH())
    RouteTask = _group:TaskRoute( RoutePoints )
    _group:SetTask(RouteTask, 1 )
end

--------------------------------------------------------------
loe_order_altitude = function( env, order, _group )
    env.info( "change altitude to " .. order.value )
    Route = _group:CopyRoute()
    for i, w in pairs(Route) do
        w.alt = tonumber(order.value)
    end
    _group:Route(Route)
end

--------------------------------------------------------------
loe_order_position = function( env, order, _group )
    env.info( "   --> change position " .. order.value.latitude .. " " .. order.value.longitude )
    FromCoord = _group:GetCoordinate()
    env.info( FromCoord )
    _pos = COORDINATE:NewFromLLDD(order.value.latitude, order.value.longitude)--, FromCoord:GetPointVec2():GetAlt())
    _name = _group.GroupName
    _group:Destroy(true)
    _newgroup = SPAWN:New(_name):SpawnFromVec3(_pos:GetVec3())
end
--------------------------------------------------------------
loe_command = function(env, order, _group)
    env.info("   o " .. order.property )
    
    if order.property == "rtb" then
        loe_command_rtb(env, order, _group)
    elseif order.property == "cap" then
        loe_command_cap(env, order, _group)
    else
        env.info("-- Not yet supported --")
    end
end

--------------------------------------------------------------
loe_command_rtb = function( env, order, _group )
    env.info( "RTB on" .. order.value )
    local _airbase = AIRBASE:FindByName(order.value)
    if _airbase then
        FromCoord = _group:GetCoordinate()
        
        local AirbasePointVec2 = _airbase:GetPointVec2()
        local AirbaseAirPoint = AirbasePointVec2:WaypointAir(
          POINT_VEC3.RoutePointAltType.BARO,
          "Land",
          "Landing", 
          _group:GetUnit(1):GetDesc().speedMax
        )
        
        AirbaseAirPoint["airdromeId"] = _airbase:GetID()
        AirbaseAirPoint["speed_locked"] = true

        RoutePoints = {}
        RoutePoints[#RoutePoints+1] = FromCoord:WaypointAirFlyOverPoint( "BARO", _group:GetVelocityKMH())
        RoutePoints[#RoutePoints+1] = AirbaseAirPoint
        RouteTask = _group:TaskRoute( RoutePoints )
        _group:SetTask(RouteTask, 1 )
    end
end

--------------------------------------------------------------
loe_command_cap = function( env, order, _group )
    env.info( "CAP on")
    ZoneA = ZONE_RADIUS:New( "Zone A".. _group.GroupName, _group:GetVec2(), 30000 )
    AICapZone = AI_CAP_ZONE:New( ZoneA, 500, 1000, 500, 600 )
    AICapZone:SetControllable( _group )
    AICapZone:SetEngageZone( ZoneA ) -- Set the Engage Zone. The AI will only engage when the bogeys are within the CapEngageZone.

    AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone.
end
--------------------------------------------------------------
lotatcLink.registerCallbacks( LCallbacks )
env.info("My LotAtc Link initialized")
Callback Description Parameters
command_status First call when LotAtcLink is initialized data.version contains LotAtc Version used
command_order Call on each LotAtc Instructor command data.orders contains one or more orders to execute (see orders below)

Orders

A lua order object have:

order.object

Member Description
order_name “order”
group_name DCS Group name
unit_name DCS Unit name
property Property name that changes
value New value

Property can be:

Name Description
headingDeg new heading in degrees
altitude new altitude in meters
groundSpeed new ground speed in km/h

Flags

You export a DCS flag to LotAtc Advanced. It can be read and write directly from there.

Mission script must be initialized as described above then, you have to add the trigger DO SCRIPT and the line:

lotatcLink.registerFlag('1', 'reload', 'Reloading Scritpting')

Parameters are:

Parameter Description
id of the flag  
short name use for button text in LotAtc
description use for description text in LotAtc

image-left

Once registered, flag is displayed in LotAtc and reflect current status. If user click on the flag button in LotAtc, mission script will be updated.

A command order is also generated in LotAtcLink that you can used if you need it:

order

Member Description
order_name “flag”
number DCS flag id
value New value

Updated: