mirror of
https://github.com/DaKerboul/perun.git
synced 2026-08-09 19:55:40 +02:00
Added Cyrillic alphabet (russian). Some characters are disabled due to potential conflict with English alphabet. Enable if only Cyrillic is used
1022 lines
37 KiB
Lua
1022 lines
37 KiB
Lua
-- Perun for DCS World https://github.com/szporwolik/perun -> DCS Hook component
|
||
|
||
-- Initial init
|
||
local Perun = {}
|
||
package.path = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua"
|
||
package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
|
||
|
||
-- ###################### SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION #############################
|
||
|
||
Perun.RefreshStatus = 15 -- (int) [default: 60] Base refresh rate in seconds to send status update
|
||
Perun.RefreshMission = 60 -- (int) [default: 120] Refresh rate in seconds to send mission information
|
||
Perun.TCPTargetPort = 48621 -- (int) [default: 48621] TCP port to send data to
|
||
Perun.TCPPerunHost = "localhost" -- (string) [default: "localhost"] IP adress of the Perun instance or "localhost"
|
||
Perun.Instance = 1 -- (int) [default: 1] Id number of instance (if multiple DCS instances are to run at the same PC)
|
||
Perun.JsonStatusLocation = "Scripts\\Json\\" -- (string) [default: "Scripts\\Json\\"] Folder relative do user's SaveGames DCS folder -> status file updated each RefreshMission
|
||
Perun.MissionStartNoDeathWindow = 300 -- (int) [default: 300] Number of secounds after mission start when death of the pilot will not go to statistics, shall avoid death penalty during spawning DCS bugs
|
||
Perun.DebugMode = 2 -- (int) [0 (default),1,2] Value greater than 0 will display Perun information in DCS log file, values: 1 - minimal verbose, 2 - all log information will be logged
|
||
Perun.LogServerMessages = 1 -- (int) [0,1 (default)] Set to 1 if you want to log also the chat messages send by server
|
||
Perun.MOTD_L1 = "Witamy na serwerze Gildia.org !" -- (string) Message send to players connecting the server - Line 1
|
||
Perun.MOTD_L2 = "Wymagamy obecnosci DCS SRS oraz TeamSpeak - szczegoly na forum" -- (string) Message send to players connecting the server - Line 2
|
||
|
||
-- ###################### END OF SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION ######################
|
||
|
||
-- Variable init
|
||
Perun.Version = "v0.11.1"
|
||
Perun.StatusData = {}
|
||
Perun.SlotsData = {}
|
||
Perun.MissionData = {}
|
||
Perun.ServerData = {}
|
||
Perun.StatData = {}
|
||
Perun.StatDataLastType = {}
|
||
Perun.PlayersTableCache = {}
|
||
Perun.MissionHash=""
|
||
Perun.ReconnectTimeout = 30
|
||
Perun.lastSentStatus = 0
|
||
Perun.lastSentMission = 0
|
||
Perun.lastSentKeepAlive = 0
|
||
Perun.lastConnectionError = 0
|
||
Perun.lastTimer = 0
|
||
Perun.lastReconnect = (-1) * Perun.ReconnectTimeout
|
||
Perun.SendRetries = 2
|
||
Perun.RefreshKeepAlive = 3
|
||
Perun.JsonStatusLocation = lfs.writedir() .. Perun.JsonStatusLocation
|
||
Perun.socket = require("socket")
|
||
Perun.IsServer = DCS.isServer( )
|
||
Perun.ConnectionError = "[Perun] ERROR: Connection broken - contact server admin!"
|
||
|
||
-- ################################ Helper function definitions ################################
|
||
function stripChars(str)
|
||
-- Hellper functions removes accents characters from string
|
||
-- via https://stackoverflow.com/questions/50459102/replace-accented-characters-in-string-to-standard-with-lua
|
||
local _tableAccents = {}
|
||
_tableAccents["à"] = "a"
|
||
_tableAccents["á"] = "a"
|
||
_tableAccents["â"] = "a"
|
||
_tableAccents["ã"] = "a"
|
||
_tableAccents["ä"] = "a"
|
||
_tableAccents["ç"] = "c"
|
||
_tableAccents["è"] = "e"
|
||
_tableAccents["é"] = "e"
|
||
_tableAccents["ê"] = "e"
|
||
_tableAccents["ë"] = "e"
|
||
_tableAccents["ì"] = "i"
|
||
_tableAccents["í"] = "i"
|
||
_tableAccents["î"] = "i"
|
||
_tableAccents["ï"] = "i"
|
||
_tableAccents["ñ"] = "n"
|
||
_tableAccents["ò"] = "o"
|
||
_tableAccents["ó"] = "o"
|
||
_tableAccents["ô"] = "o"
|
||
_tableAccents["õ"] = "o"
|
||
_tableAccents["ö"] = "o"
|
||
_tableAccents["ù"] = "u"
|
||
_tableAccents["ú"] = "u"
|
||
_tableAccents["û"] = "u"
|
||
_tableAccents["ü"] = "u"
|
||
_tableAccents["ý"] = "y"
|
||
_tableAccents["ÿ"] = "y"
|
||
_tableAccents["À"] = "A"
|
||
_tableAccents["Á"] = "A"
|
||
_tableAccents["Â"] = "A"
|
||
_tableAccents["Ã"] = "A"
|
||
_tableAccents["Ä"] = "A"
|
||
_tableAccents["Ç"] = "C"
|
||
_tableAccents["È"] = "E"
|
||
_tableAccents["É"] = "E"
|
||
_tableAccents["Ê"] = "E"
|
||
_tableAccents["Ë"] = "E"
|
||
_tableAccents["Ì"] = "I"
|
||
_tableAccents["Í"] = "I"
|
||
_tableAccents["Î"] = "I"
|
||
_tableAccents["Ï"] = "I"
|
||
_tableAccents["Ñ"] = "N"
|
||
_tableAccents["Ò"] = "O"
|
||
_tableAccents["Ó"] = "O"
|
||
_tableAccents["Ô"] = "O"
|
||
_tableAccents["Õ"] = "O"
|
||
_tableAccents["Ö"] = "O"
|
||
_tableAccents["Ù"] = "U"
|
||
_tableAccents["Ú"] = "U"
|
||
_tableAccents["Û"] = "U"
|
||
_tableAccents["Ü"] = "U"
|
||
_tableAccents["Ý"] = "Y"
|
||
|
||
-- Polish accents
|
||
_tableAccents["ę"] = "e"
|
||
_tableAccents["Ę"] = "Ę"
|
||
_tableAccents["ó"] = "o"
|
||
_tableAccents["Ó"] = "O"
|
||
_tableAccents["ą"] = "a"
|
||
_tableAccents["Ą"] = "A"
|
||
_tableAccents["ś"] = "s"
|
||
_tableAccents["Ś"] = "S"
|
||
_tableAccents["ć"] = "c"
|
||
_tableAccents["Ć"] = "C"
|
||
_tableAccents["ż"] = "z"
|
||
_tableAccents["Ż"] = "Z"
|
||
_tableAccents["ź"] = "z"
|
||
_tableAccents["Ź"] = "Z"
|
||
_tableAccents["ł"] = "l"
|
||
_tableAccents["Ł"] = "L"
|
||
|
||
-- Cyrillic script (Russian)
|
||
_tableAccents["а"] = "a"
|
||
_tableAccents["А"] = "A"
|
||
_tableAccents["б"] = "b"
|
||
_tableAccents["Б"] = "B"
|
||
_tableAccents["в"] = "v"
|
||
_tableAccents["В"] = "V"
|
||
_tableAccents["г"] = "g"
|
||
_tableAccents["Г"] = "G"
|
||
_tableAccents["д"] = "d"
|
||
_tableAccents["Д"] = "D"
|
||
_tableAccents["е"] = "ye"
|
||
_tableAccents["Е"] = "YE"
|
||
_tableAccents["ё"] = "yo"
|
||
_tableAccents["Ё"] = "YO"
|
||
_tableAccents["ж"] = "zh"
|
||
_tableAccents["Ж"] = "Zh"
|
||
_tableAccents["з"] = "z"
|
||
_tableAccents["З"] = "Z"
|
||
_tableAccents["и"] = "ee"
|
||
_tableAccents["И"] = "EE"
|
||
_tableAccents["й"] = "i"
|
||
_tableAccents["Й"] = "I"
|
||
_tableAccents["к"] = "k"
|
||
_tableAccents["К"] = "K"
|
||
_tableAccents["л"] = "l"
|
||
_tableAccents["Л"] = "L"
|
||
_tableAccents["м"] = "m"
|
||
_tableAccents["М"] = "M"
|
||
-- _tableAccents["Н"] = "M" - disabled due to conflict with english
|
||
_tableAccents["п"] = "p"
|
||
_tableAccents["П"] = "P"
|
||
-- _tableAccents["р"] = "r" - disabled due to conflict with english
|
||
-- _tableAccents["Р"] = "R" - disabled due to conflict with english
|
||
-- _tableAccents["с"] = "s" - disabled due to conflict with english
|
||
-- _tableAccents["С"] = "S" - disabled due to conflict with english
|
||
_tableAccents["т"] = "t"
|
||
_tableAccents["Т"] = "T"
|
||
_tableAccents["у"] = "u"
|
||
_tableAccents["У"] = "U"
|
||
_tableAccents["ф"] = "f"
|
||
_tableAccents["Ф"] = "F"
|
||
-- _tableAccents["х"] = "h" - disabled due to conflict with english
|
||
-- _tableAccents["Х"] = "H" - disabled due to conflict with english
|
||
_tableAccents["ц"] = "ts"
|
||
_tableAccents["Ц"] = "TS"
|
||
_tableAccents["ч"] = "ch"
|
||
_tableAccents["Ч"] = "CH"
|
||
_tableAccents["ш"] = "sh"
|
||
_tableAccents["Ш"] = "SH"
|
||
_tableAccents["щ"] = "sh"
|
||
_tableAccents["Щ"] = "SH"
|
||
_tableAccents["ъ"] = ""
|
||
_tableAccents["Ъ"] = ""
|
||
_tableAccents["ы"] = "i"
|
||
_tableAccents["Ы"] = "I"
|
||
_tableAccents["ь"] = ""
|
||
_tableAccents["Ь"] = ""
|
||
_tableAccents["э"] = "e"
|
||
_tableAccents["Э"] = "E"
|
||
_tableAccents["ю"] = "yu"
|
||
_tableAccents["Ю"] = "YU"
|
||
_tableAccents["я"] = "ya"
|
||
_tableAccents["Я"] = "YA"
|
||
|
||
-- TBD additonal characters for other languages
|
||
|
||
-- Check string and replace special chars via replacement table
|
||
local _normalizedString = ''
|
||
for _strChar in string.gmatch(str, "([%z\1-\127\194-\244][\128-\191]*)") do
|
||
if _tableAccents[_strChar] ~= nil then
|
||
-- Replace char
|
||
_normalizedString = _normalizedString.._tableAccents[_strChar]
|
||
else
|
||
-- No need to replace
|
||
_normalizedString = _normalizedString.._strChar
|
||
end
|
||
end
|
||
return _normalizedString
|
||
end
|
||
|
||
Perun.GetCategory = function(id)
|
||
-- Helper function returns object category basing on https://pastebin.com/GUAXrd2U
|
||
local _killed_target_category = "Other"
|
||
|
||
-- Sometimes we get empty object id (seems like DCS API bug)
|
||
if id ~= nil and id ~= "" then
|
||
_killed_target_category = DCS.getUnitTypeAttribute(id, "category")
|
||
|
||
-- Below, simple hack to get the propper category when DCS API is not returning correct value
|
||
if _killed_target_category == nil then
|
||
local _killed_target_cat_check_ship = DCS.getUnitTypeAttribute(id, "DeckLevel")
|
||
local _killed_target_cat_check_plane = DCS.getUnitTypeAttribute(id, "WingSpan")
|
||
if _killed_target_cat_check_ship ~= nil and _killed_target_cat_check_plane == nil then
|
||
_killed_target_category = "Ships"
|
||
elseif _killed_target_cat_check_ship == nil and _killed_target_cat_check_plane ~= nil then
|
||
_killed_target_category = "Planes"
|
||
else
|
||
_killed_target_category = "Helicopters"
|
||
end
|
||
end
|
||
end
|
||
|
||
return _killed_target_category
|
||
end
|
||
|
||
Perun.SideID2Name = function(id)
|
||
-- Helper function returns side name per side (coalition) id
|
||
local _sides = {
|
||
[0] = 'SPECTATOR',
|
||
[1] = 'RED',
|
||
[2] = 'BLUE',
|
||
[3] = 'NEUTRAL', -- TBD check once this is released in DCS
|
||
}
|
||
if id > 0 then
|
||
return _sides[id]
|
||
else
|
||
return "?"
|
||
end
|
||
end
|
||
|
||
Perun.AddLog = function(text,LogLevel)
|
||
-- Adds logs to DCS.log file
|
||
LogLevel = LogLevel or 1
|
||
if Perun.DebugMode >= LogLevel then
|
||
net.log("[Perun] ".. text)
|
||
end
|
||
end
|
||
|
||
Perun.GenerateMissionHash = function()
|
||
-- Generates unique simulation mission hash
|
||
return DCS.getMissionName( ).."@".. Perun.Instance .. "@" .. Perun.Version .. "@".. os.date('%Y%m%d_%H%M%S')
|
||
end
|
||
|
||
Perun.GetMulticrewAllParameters = function (PlayerId)
|
||
-- Gets all multicrew parameters
|
||
local _result = ""
|
||
local _master_type= "?"
|
||
local _master_slot = nil
|
||
local _sub_slot = nil
|
||
|
||
local _player_slot = net.get_player_info(PlayerId, 'slot')
|
||
if not _player_slot then
|
||
_player_slot=Perun.PlayersTableCache["p"..PlayerId].slot
|
||
end
|
||
|
||
if _player_slot and _player_slot ~= '' and not (string.find(_player_slot, 'red') or string.find(_player_slot, 'blue')) then
|
||
-- Player took model
|
||
_master_slot = _player_slot
|
||
_sub_slot =0
|
||
|
||
if (not tonumber(_player_slot)) then
|
||
-- If this is multiseat slot parse master slot and look for seat number
|
||
_t_start, _t_end = string.find(_player_slot, '_%d+')
|
||
|
||
if _t_start then
|
||
-- This is co-player
|
||
_master_slot = string.sub(_player_slot, 0 , _t_start -1 )
|
||
_sub_slot = string.sub(_player_slot, _t_start + 1, _t_end )
|
||
end
|
||
end
|
||
_master_type = DCS.getUnitType(_master_slot)
|
||
|
||
elseif string.find(_player_slot, 'red') or string.find(_player_slot, 'blue') then
|
||
-- Deal with the special slots addded by Combined Arms and Spectators
|
||
if string.find(_player_slot, 'artillery_commander') then
|
||
_master_type = "artillery_commander"
|
||
elseif string.find(_player_slot, 'instructor') then
|
||
_master_type = "instructor"
|
||
elseif string.find(_player_slot, 'forward_observer') then
|
||
_master_type = "forward_observer"
|
||
elseif string.find(_player_slot, 'observer') then
|
||
_master_type = "observer"
|
||
end
|
||
_master_slot = -1
|
||
_sub_slot = 0
|
||
else
|
||
_master_slot = -1
|
||
_sub_slot = -1
|
||
end
|
||
return _master_type,_master_slot,_sub_slot
|
||
end
|
||
|
||
Perun.GetMulticrewParameter = function (PlayerId,Parameter)
|
||
-- Get specific multicrew Parameter
|
||
_master_type,_master_slot,_sub_slot = Perun.GetMulticrewAllParameters(PlayerId)
|
||
|
||
if Parameter == "mastertype" then
|
||
return _master_type
|
||
elseif Parameter == "masterslot" then
|
||
return _master_slot
|
||
elseif Parameter == "subslot" then
|
||
return _sub_slot
|
||
elseif Parameter == "subtype" then
|
||
if _sub_slot == 0 then
|
||
return _master_type
|
||
else
|
||
return _master_type .. "_" .. _sub_slot
|
||
end
|
||
else
|
||
return nil
|
||
end
|
||
end
|
||
|
||
Perun.GetMulticrewCrew = function (owner_playerID)
|
||
-- Get all multicrew crew
|
||
_master_type,_master_slot,_sub_slot = Perun.GetMulticrewAllParameters(owner_playerID)
|
||
|
||
local _crew = {}
|
||
table.insert(_crew, owner_playerID)
|
||
if _master_type == "F-14B" or _master_type == "Yak-52" or _master_type == "L-39C" or _master_type == "SA342M" or _master_type =="SA342Minigun" or _master_type == "SA342Mistral" or _master_type == "SA342L" then -- TBD add additional multicrew model types
|
||
local _owner_side=net.get_player_info(owner_playerID, 'side')
|
||
|
||
if _master_slot and _master_slot ~= "" then
|
||
-- Search for all players from crew
|
||
local _all_players = net.get_player_list()
|
||
for PlayerIDIndex, _playerID in ipairs(_all_players) do
|
||
local _playerDetails = net.get_player_info( _playerID )
|
||
|
||
if _playerDetails.side == _owner_side and (_playerDetails.slot == _master_slot or _playerDetails.slot == _master_slot .. "_1" or _playerDetails.slot == _master_slot .. "_2" or _playerDetails.slot == _master_slot .. "_3" or _playerDetails.slot == _master_slot .. "_4") and _playerID ~= owner_playerID then
|
||
-- Add to crew list
|
||
table.insert(_crew, _playerID)
|
||
else
|
||
-- Do nothing
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
Perun.AddLog("Multicrew check completed: " .. net.lua2json(_crew),2)
|
||
return _crew
|
||
end
|
||
|
||
Perun.GetMulticrewCrewNames = function (owner_playerID)
|
||
-- Get all crew names and return as string (needed for logging purposes)
|
||
local _pilots_accounted = Perun.GetMulticrewCrew(owner_playerID)
|
||
local _result_text = ""
|
||
for _, pilotID in ipairs(_pilots_accounted) do
|
||
_result_text= _result_text .. net.get_player_info(pilotID, "name") .. ", "
|
||
end
|
||
return _result_text
|
||
end
|
||
|
||
Perun.GetTakeOffLandingEvent = function (takeoff,location)
|
||
-- Get correct event type for statistics basing on objecy which served as runway/farp
|
||
local _operation = ""
|
||
if takeoff == true then
|
||
_operation="tookoff_"
|
||
else
|
||
_operation="landing_"
|
||
end
|
||
|
||
local _temp_type = ""
|
||
if string.find(location, "FARP",1,true) then
|
||
_temp_type = "FARP"
|
||
elseif string.find(location, "CVN-74 John C. Stennis",1,true) or string.find(location, "LHA-1 Tarawa",1,true) or string.find(location, "SHIP",1,true) then
|
||
_temp_type = "SHIP"
|
||
elseif location ~= "" then
|
||
_temp_type = "AIRFIELD"
|
||
else
|
||
_temp_type = "OTHER"
|
||
end
|
||
|
||
return _operation .. _temp_type
|
||
end
|
||
|
||
-- ################################ TCP Connection ################################
|
||
|
||
Perun.ConnectToPerun = function ()
|
||
-- Connects to Perun server
|
||
Perun.AddLog("Connecting to TCP server",2)
|
||
Perun.TCP = assert(Perun.socket.tcp())
|
||
Perun.TCP:settimeout(5000)
|
||
|
||
_, _err = Perun.TCP:connect(Perun.TCPPerunHost, Perun.TCPTargetPort)
|
||
if _err then
|
||
-- Could not connect
|
||
Perun.AddLog("ERROR - TCP connection error : " .. _err , 1)
|
||
else
|
||
-- Connected
|
||
Perun.AddLog("Success - connected to TCP server",2)
|
||
end
|
||
local _now = DCS.getRealTime()
|
||
Perun.lastReconnect = _now
|
||
end
|
||
|
||
Perun.SendToPerun = function(data_id, data_package)
|
||
-- Prepares and sends data package
|
||
local _TempData={}
|
||
_TempData["type"]=data_id
|
||
_TempData["payload"]=data_package
|
||
_TempData["timestamp"]=os.date('%Y-%m-%d %H:%M:%S')
|
||
_TempData["instance"]=Perun.Instance
|
||
|
||
-- Build TCP frame
|
||
local _TCPFrame="<SOT>" .. stripChars(net.lua2json(_TempData)) .. "<EOT>"
|
||
|
||
-- TCP Part - sending
|
||
local _intStatus = nil
|
||
local _intTries =0
|
||
local _err=nil
|
||
local _dropped = true
|
||
|
||
-- Try to send a few times (defind in settings section)
|
||
local _now = DCS.getRealTime()
|
||
while _intStatus == nil and _intTries < Perun.SendRetries do
|
||
_intStatus, _err = Perun.TCP:send(_TCPFrame)
|
||
if _err then
|
||
-- Failure, packet was not send
|
||
Perun.AddLog("Packed not send : " .. data_id .. " , error: " .. _err .. ", tries: " .. _intTries,2)
|
||
if _now > Perun.lastReconnect + Perun.ReconnectTimeout then
|
||
Perun.ConnectToPerun()
|
||
end
|
||
else
|
||
-- Succes, packet was send
|
||
Perun.AddLog("Packet send : " .. data_id .. " , tries:" .. _intTries,2)
|
||
_dropped = false
|
||
end
|
||
_intTries=_intTries+1
|
||
end
|
||
|
||
if _dropped == true then
|
||
-- Add information to log file and send chat message to all that Perun connection is broken
|
||
Perun.AddLog("ERROR - packed dropped : " .. data_id,1)
|
||
if _now > Perun.lastConnectionError + Perun.ReconnectTimeout then
|
||
-- Informs all players that there is Peron error; below hack for DCS net.send_chat not working
|
||
local _all_players = net.get_player_list()
|
||
for PlayerIDIndex, _playerID in ipairs(_all_players) do
|
||
net.send_chat_to(Perun.ConnectionError , _playerID)
|
||
end
|
||
-- Reset last error send counter
|
||
Perun.lastConnectionError = _now
|
||
end
|
||
end
|
||
end
|
||
|
||
-- ################################ Log functions ################################
|
||
|
||
Perun.LogChat = function(playerID,msg,all)
|
||
-- Logs chat messages
|
||
local _TempData={}
|
||
_TempData['player']= net.get_player_info(playerID, "name")
|
||
_TempData['msg']=stripChars(msg)
|
||
_TempData['all']=all
|
||
_TempData['ucid']=net.get_player_info(playerID, 'ucid')
|
||
_TempData['datetime']=os.date('%Y-%m-%d %H:%M:%S')
|
||
_TempData['missionhash']=Perun.MissionHash
|
||
|
||
Perun.AddLog("Sending chat message",2)
|
||
Perun.SendToPerun(50,_TempData)
|
||
end
|
||
|
||
Perun.LogEvent = function(log_type,log_content,log_arg_1,log_arg_2)
|
||
-- Logs events messages
|
||
local _TempData={}
|
||
_TempData['log_type']= log_type
|
||
_TempData['log_arg_1']= log_arg_1
|
||
_TempData['log_arg_2']= log_arg_2
|
||
_TempData['log_content']=log_content
|
||
_TempData['log_datetime']=os.date('%Y-%m-%d %H:%M:%S')
|
||
_TempData['log_missionhash']=Perun.MissionHash
|
||
|
||
if log_arg_1 == nil then
|
||
log_arg_1 = "null"
|
||
end
|
||
if log_arg_2 == nil then
|
||
log_arg_2 = "null"
|
||
end
|
||
|
||
Perun.AddLog("Sending event data, event: " .. log_type .. ", arg1:" .. log_arg_1 .. ", arg2:" .. log_arg_2 .. ", content: " .. log_content,2)
|
||
Perun.SendToPerun(51,_TempData)
|
||
end
|
||
|
||
Perun.LogStats = function(playerID)
|
||
-- Log player status
|
||
local _PlayerStatsTable=Perun.LogStatsGet(playerID)
|
||
local _TempData={}
|
||
_TempData['stat_data_perun']=_PlayerStatsTable
|
||
_TempData['stat_data_type']= _PlayerStatsTable['ps_type'];
|
||
_TempData['stat_data_masterslot'] = _PlayerStatsTable['ps_masterslot'];
|
||
_TempData['stat_data_subslot'] = _PlayerStatsTable['ps_subslot'];
|
||
_TempData['stat_ucid']=_PlayerStatsTable['ps_ucid'];
|
||
_TempData['stat_name']=_PlayerStatsTable['ps_name'];
|
||
_TempData['stat_datetime']=os.date('%Y-%m-%d %H:%M:%S')
|
||
_TempData['stat_missionhash']=Perun.MissionHash
|
||
|
||
Perun.AddLog("Sending stats data",2)
|
||
Perun.SendToPerun(52,_TempData)
|
||
end
|
||
|
||
Perun.LogAllStats = function()
|
||
-- Log all players data
|
||
local _all_players = net.get_player_list()
|
||
for PlayerIDIndex, _playerID in ipairs(_all_players) do
|
||
if _playerID ~= 1 then
|
||
Perun.LogStats(_playerID)
|
||
end
|
||
end
|
||
end
|
||
|
||
Perun.LogLogin = function(playerID)
|
||
-- Player logged in
|
||
local _TempData={}
|
||
_TempData['login_ucid']=net.get_player_info(playerID, 'ucid')
|
||
_TempData['login_ipaddr']=net.get_player_info(playerID, 'ipaddr')
|
||
_TempData['login_name']=net.get_player_info(playerID, 'name')
|
||
_TempData['login_datetime']=os.date('%Y-%m-%d %H:%M:%S')
|
||
|
||
Perun.AddLog("Sending login event",2)
|
||
Perun.SendToPerun(53,_TempData)
|
||
end
|
||
|
||
--- ################################ Calculate stats ################################
|
||
|
||
Perun.LogStatsCount = function(argPlayerID,argAction,argTimer)
|
||
-- Creates or updates Perun statistics array
|
||
local _player_hash=net.get_player_info(argPlayerID, 'ucid')..Perun.GetMulticrewParameter(argPlayerID,"subtype")
|
||
|
||
-- By default we will be sending stats
|
||
argTimer = argTimer or false
|
||
|
||
if Perun.StatData[_player_hash] == nil then
|
||
-- Create empty element
|
||
local _TempData={}
|
||
_TempData['ps_ucid'] = net.get_player_info(argPlayerID, 'ucid')
|
||
_TempData['ps_name'] = net.get_player_info(argPlayerID, 'name')
|
||
_TempData['ps_type'] = Perun.GetMulticrewParameter(argPlayerID,"subtype")
|
||
_TempData['ps_masterslot'] = Perun.GetMulticrewParameter(argPlayerID,"masterslot")
|
||
_TempData['ps_subslot'] = Perun.GetMulticrewParameter(argPlayerID,"subslot")
|
||
_TempData['ps_pvp'] = 0
|
||
_TempData['ps_deaths'] = 0
|
||
_TempData['ps_ejections'] = 0
|
||
_TempData['ps_crashes'] = 0
|
||
_TempData['ps_teamkills'] = 0
|
||
_TempData['ps_time'] = 0
|
||
_TempData['ps_kills_planes'] = 0
|
||
_TempData['ps_kills_helicopters'] = 0
|
||
_TempData['ps_kills_air_defense'] = 0
|
||
_TempData['ps_kills_armor'] = 0
|
||
_TempData['ps_kills_unarmed'] = 0
|
||
_TempData['ps_kills_infantry'] = 0
|
||
_TempData['ps_kills_ships'] = 0
|
||
_TempData['ps_kills_fortification'] = 0
|
||
_TempData['ps_kills_artillery'] = 0
|
||
_TempData['ps_kills_other'] = 0
|
||
_TempData['ps_airfield_takeoffs'] = 0
|
||
_TempData['ps_airfield_landings'] = 0
|
||
_TempData['ps_ship_takeoffs'] = 0
|
||
_TempData['ps_ship_landings'] = 0
|
||
_TempData['ps_farp_takeoffs'] = 0
|
||
_TempData['ps_farp_landings'] = 0
|
||
_TempData['ps_other_takeoffs'] = 0
|
||
_TempData['ps_other_landings'] = 0
|
||
|
||
Perun.StatData[_player_hash]=_TempData
|
||
end
|
||
|
||
if Perun.GetMulticrewParameter(argPlayerID,"subtype") ~= nil then
|
||
Perun.StatDataLastType[net.get_player_info(argPlayerID, 'ucid')]=_player_hash
|
||
else
|
||
-- Do nothing
|
||
end
|
||
|
||
if argAction == "eject" then
|
||
Perun.StatData[_player_hash]['ps_ejections']=Perun.StatData[_player_hash]['ps_ejections']+1
|
||
elseif argAction == "pilot_death" then
|
||
if DCS.getModelTime() > Perun.MissionStartNoDeathWindow then
|
||
-- we do not track deaths during mission startup due to spawning issues
|
||
Perun.StatData[_player_hash]['ps_deaths']=Perun.StatData[_player_hash]['ps_deaths']+1
|
||
end
|
||
elseif argAction == "friendly_fire" then
|
||
Perun.StatData[_player_hash]['ps_teamkills']=Perun.StatData[_player_hash]['ps_teamkills']+1
|
||
elseif argAction == "crash" then
|
||
Perun.StatData[_player_hash]['ps_crashes']=Perun.StatData[_player_hash]['ps_crashes']+1
|
||
elseif argAction == "landing_FARP" then
|
||
Perun.StatData[_player_hash]['ps_farp_landings']=Perun.StatData[_player_hash]['ps_farp_landings']+1
|
||
elseif argAction == "landing_SHIP" then
|
||
Perun.StatData[_player_hash]['ps_ship_landings']=Perun.StatData[_player_hash]['ps_ship_landings']+1
|
||
elseif argAction == "landing_AIRFIELD" then
|
||
Perun.StatData[_player_hash]['ps_airfield_landings']=Perun.StatData[_player_hash]['ps_airfield_landings']+1
|
||
elseif argAction == "tookoff_FARP" then
|
||
Perun.StatData[_player_hash]['ps_farp_takeoffs']=Perun.StatData[_player_hash]['ps_farp_takeoffs']+1
|
||
elseif argAction == "tookoff_SHIP" then
|
||
Perun.StatData[_player_hash]['ps_ship_takeoffs']=Perun.StatData[_player_hash]['ps_ship_takeoffs']+1
|
||
elseif argAction == "tookoff_AIRFIELD" then
|
||
Perun.StatData[_player_hash]['ps_airfield_takeoffs']=Perun.StatData[_player_hash]['ps_airfield_takeoffs']+1
|
||
elseif argAction == "kill_Planes" then
|
||
Perun.StatData[_player_hash]['ps_kills_planes']=Perun.StatData[_player_hash]['ps_kills_planes']+1
|
||
elseif argAction == "kill_Helicopters" then
|
||
Perun.StatData[_player_hash]['ps_kills_helicopters']=Perun.StatData[_player_hash]['ps_kills_helicopters']+1
|
||
elseif argAction == "kill_Ships" then
|
||
Perun.StatData[_player_hash]['ps_kills_ships']=Perun.StatData[_player_hash]['ps_kills_ships']+1
|
||
elseif argAction == "kill_Air_Defence" then
|
||
Perun.StatData[_player_hash]['ps_kills_air_defense']=Perun.StatData[_player_hash]['ps_kills_air_defense']+1
|
||
elseif argAction == "kill_Unarmed" then
|
||
Perun.StatData[_player_hash]['ps_kills_unarmed']=Perun.StatData[_player_hash]['ps_kills_unarmed']+1
|
||
elseif argAction == "kill_Armor" then
|
||
Perun.StatData[_player_hash]['ps_kills_armor']=Perun.StatData[_player_hash]['ps_kills_armor']+1
|
||
elseif argAction == "kill_Infantry" then
|
||
Perun.StatData[_player_hash]['ps_kills_infantry']=Perun.StatData[_player_hash]['ps_kills_infantry']+1
|
||
elseif argAction == "kill_Fortification" then
|
||
Perun.StatData[_player_hash]['ps_kills_fortification']=Perun.StatData[_player_hash]['ps_kills_fortification']+1
|
||
elseif argAction == "kill_Artillery" then
|
||
Perun.StatData[_player_hash]['ps_kills_artillery']=Perun.StatData[_player_hash]['ps_kills_artillery']+1
|
||
elseif argAction == "kill_Other" then
|
||
Perun.StatData[_player_hash]['ps_kills_other']=Perun.StatData[_player_hash]['ps_kills_other']+1
|
||
elseif argAction == "kill_PvP" then
|
||
Perun.StatData[_player_hash]['ps_pvp']=Perun.StatData[_player_hash]['ps_pvp']+1
|
||
elseif argAction == "landing_OTHER" then
|
||
Perun.StatData[_player_hash]['ps_other_landings']=Perun.StatData[_player_hash]['ps_other_landings']+1
|
||
elseif argAction == "tookoff_OTHER" then
|
||
Perun.StatData[_player_hash]['ps_other_takeoffs']=Perun.StatData[_player_hash]['ps_other_takeoffs']+1
|
||
elseif argAction == "timer" then
|
||
Perun.StatData[_player_hash]['ps_time']=Perun.StatData[_player_hash]['ps_time']+1
|
||
end
|
||
|
||
-- Always update slots
|
||
Perun.StatData[_player_hash]['ps_masterslot'] = Perun.GetMulticrewParameter(argPlayerID,"masterslot")
|
||
Perun.StatData[_player_hash]['ps_subslot'] = Perun.GetMulticrewParameter(argPlayerID,"subslot")
|
||
|
||
Perun.AddLog("Stats data prepared",2)
|
||
|
||
-- If this is timer request do not send data to database
|
||
if argTimer ~= true then
|
||
Perun.LogStats(argPlayerID);
|
||
end
|
||
end
|
||
|
||
Perun.LogStatsCountCrew = function (MasterPilotID,ActionType)
|
||
-- Change stats for the whole crew
|
||
local _pilots_accounted = Perun.GetMulticrewCrew(MasterPilotID)
|
||
for _, pilotID in ipairs(_pilots_accounted) do
|
||
Perun.LogStatsCount(pilotID,ActionType)
|
||
end
|
||
end
|
||
-- ################################ Data preparation ################################
|
||
|
||
Perun.LogStatsGet = function(playerID)
|
||
-- Gets Perun statistics array per player
|
||
local next = next -- Make next function local - this improves performance
|
||
local _player_hash = nil
|
||
|
||
local _ucid = net.get_player_info(playerID, 'ucid')
|
||
if not _ucid then
|
||
_ucid=Perun.PlayersTableCache["p"..playerID].ucid
|
||
end
|
||
|
||
if next(Perun.StatDataLastType) == nil then
|
||
-- Array is empty
|
||
_player_hash=_ucid..Perun.GetMulticrewParameter(playerID,"subtype")
|
||
elseif Perun.StatDataLastType[net.get_player_info(playerID, 'ucid')]== nil then
|
||
-- Last type entry is empty
|
||
_player_hash=_ucid..Perun.GetMulticrewParameter(playerID,"subtype")
|
||
else
|
||
-- Return last type entry
|
||
_player_hash=Perun.StatDataLastType[_ucid]
|
||
end
|
||
|
||
local next = next -- Make next function local - this improves performance
|
||
if next(Perun.StatData) == nil then
|
||
-- Array is empty
|
||
Perun.LogStatsCount(playerID,'init') -- Init statistics
|
||
end
|
||
if Perun.StatData[_player_hash]== nil then
|
||
-- Stats for player are empty
|
||
Perun.LogStatsCount(playerID,'init') -- Init statistics
|
||
end
|
||
|
||
Perun.AddLog("Getting stats data",2)
|
||
return Perun.StatData[_player_hash];
|
||
end
|
||
|
||
Perun.UpdateStatus = function()
|
||
-- Main function for status updates
|
||
|
||
-- Diagnostic data
|
||
-- Update version data
|
||
Perun.ServerData['v_dcs_hook']=Perun.Version
|
||
|
||
-- Update clients data - count connected players
|
||
_playerlist=net.get_player_list()
|
||
_count = 0
|
||
for _ in pairs(_playerlist) do _count = _count + 1 end
|
||
Perun.ServerData['c_players']=_count
|
||
|
||
-- Send
|
||
Perun.AddLog("Sending server data",2)
|
||
Perun.SendToPerun(1,Perun.ServerData)
|
||
|
||
-- Status data - update all subsections
|
||
-- 1 - Mission data
|
||
local _TempData={}
|
||
_TempData['name']=DCS.getMissionName()
|
||
_TempData['modeltime']=DCS.getModelTime()
|
||
_TempData['realtime']=DCS.getRealTime()
|
||
_TempData['pause']=DCS.getPause()
|
||
_TempData['multiplayer']=DCS.isMultiplayer()
|
||
_TempData['theatre'] = Perun.MissionData['mission']['theatre']
|
||
_TempData['weather'] = Perun.MissionData['mission']['weather']
|
||
Perun.StatusData["mission"] = _TempData
|
||
|
||
-- 2 - Players data
|
||
_PlayersTable={}
|
||
for _k, _i in ipairs(_playerlist) do
|
||
_PlayersTable[_k]=net.get_player_info(_i)
|
||
end
|
||
Perun.StatusData["players"] = _PlayersTable
|
||
|
||
-- Send
|
||
Perun.AddLog("Sending status data",2)
|
||
Perun.SendToPerun(2,Perun.StatusData)
|
||
|
||
-- Update slots data
|
||
Perun.SlotsData['coalitions']=DCS.getAvailableCoalitions()
|
||
Perun.SlotsData['slots']={}
|
||
|
||
-- Build up slot table
|
||
for _j, _i in pairs(Perun.SlotsData['coalitions']) do
|
||
Perun.SlotsData['slots'][_j]=DCS.getAvailableSlots(_j)
|
||
|
||
for _sj, _si in pairs(Perun.SlotsData['slots'][_j]) do
|
||
Perun.SlotsData['slots'][_j][_sj]['countryName']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['onboard_num']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['groupSize']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['groupName']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['callsign']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['task']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['airdromeId']= nil
|
||
Perun.SlotsData['slots'][_j][_sj]['helipadName']= nil
|
||
end
|
||
end
|
||
|
||
-- Send
|
||
Perun.AddLog("Sending slots data",2)
|
||
Perun.SendToPerun(3,Perun.SlotsData)
|
||
end
|
||
|
||
Perun.UpdateMission = function()
|
||
-- Main function for mission information updates
|
||
Perun.AddLog("Updating mission data",2)
|
||
Perun.MissionData=DCS.getCurrentMission()
|
||
-- Perun.SendToPerun(4,Perun.MissionData) -- TBD can cause data transmission troubles
|
||
Perun.AddLog("Mission data updated",2)
|
||
end
|
||
|
||
--- ################################ Event callbacks ################################
|
||
|
||
Perun.onSimulationStart = function()
|
||
-- Simulation was started
|
||
Perun.MissionHash=Perun.GenerateMissionHash()
|
||
Perun.LogEvent("SimStart","Mission " .. Perun.MissionHash .. " started",nil,nil);
|
||
Perun.StatData = {}
|
||
Perun.StatDataLastType = {}
|
||
Perun.PlayersTableCache = {}
|
||
end
|
||
|
||
Perun.onSimulationStop = function()
|
||
-- Simulation was stopped
|
||
Perun.LogEvent("SimStop","Mission " .. Perun.MissionHash .. " finished",nil,nil);
|
||
Perun.MissionHash=Perun.GenerateMissionHash();
|
||
Perun.StatData = {}
|
||
Perun.StatDataLastType = {}
|
||
Perun.LogAllStats()
|
||
Perun.PlayersTableCache = {}
|
||
end
|
||
|
||
Perun.onPlayerDisconnect = function(id, err_code)
|
||
-- Player disconnected
|
||
Perun.LogEvent("disconnect", "Player " .. id .. " disconnected.(?)",nil,nil);
|
||
|
||
return
|
||
end
|
||
|
||
Perun.onPlayerStop = function (id)
|
||
-- Player left the simulation (happens right before a disconnect, if player exited by desire)
|
||
Perun.LogEvent("quit", "Player " .. id .. " quit the server.",nil,nil);
|
||
return
|
||
end
|
||
|
||
Perun.onSimulationFrame = function()
|
||
-- Repeat for each simulator frame
|
||
local _now = DCS.getRealTime()
|
||
|
||
-- First run
|
||
if Perun.lastSentMission ==0 and Perun.lastSentStatus ==0 then
|
||
Perun.UpdateMission()
|
||
end
|
||
|
||
-- Send mission update and update JSON
|
||
if _now > Perun.lastSentMission + Perun.RefreshMission then
|
||
Perun.lastSentMission = _now
|
||
|
||
Perun.UpdateMission()
|
||
end
|
||
|
||
-- Send status update
|
||
if _now > Perun.lastSentStatus + Perun.RefreshStatus then
|
||
Perun.lastSentStatus = _now
|
||
|
||
Perun.UpdateStatus()
|
||
end
|
||
|
||
-- Send keepalive
|
||
if _now > Perun.lastSentKeepAlive + Perun.SendRetries then
|
||
Perun.lastSentKeepAlive = _now
|
||
Perun.SendToPerun(0,nil)
|
||
end
|
||
|
||
-- Calucalate time on slot per each of players
|
||
if _now > Perun.lastTimer + 60 then
|
||
Perun.lastTimer = _now;
|
||
local _all_players = net.get_player_list()
|
||
for PlayerIDIndex, _playerID in ipairs(_all_players) do
|
||
if _playerID ~= 1 then
|
||
Perun.LogStatsCount(_playerID,"timer",true)
|
||
end
|
||
end
|
||
end
|
||
|
||
|
||
end
|
||
|
||
Perun.onPlayerStart = function (id)
|
||
-- Player entered cocpit
|
||
net.send_chat_to(Perun.MOTD_L1, id);
|
||
net.send_chat_to(Perun.MOTD_L2, id);
|
||
end
|
||
|
||
Perun.onPlayerTrySendChat = function (playerID, msg, all)
|
||
-- Somebody tries to send chat message
|
||
if msg~=Perun.MOTD_L1 and msg~=Perun.MOTD_L2 and msg~=Perun.ConnectionError then
|
||
Perun.LogChat(playerID,msg,all)
|
||
end
|
||
|
||
return msg
|
||
end
|
||
|
||
Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
|
||
-- Game event has occured
|
||
Perun.AddLog("Event handler for ".. eventName .. " started",2)
|
||
|
||
if eventName == "friendly_fire" then
|
||
--"friendly_fire", playerID, weaponName, victimPlayerID
|
||
if arg2 == "" then
|
||
arg2 = "Cannon"
|
||
end
|
||
|
||
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .." killed friendly " .. Perun.GetMulticrewCrewNames(arg3) .. " using " .. arg2,nil,nil);
|
||
|
||
elseif eventName == "mission_end" then
|
||
--"mission_end", winner, msg
|
||
Perun.LogEvent(eventName,"Mission finished, winner " .. arg1 .. " message: " .. arg2,nil,nil);
|
||
|
||
elseif eventName == "kill" then
|
||
--"kill", killerPlayerID, killerUnitType, killerSide, victimPlayerID, victimUnitType, victimSide, weaponName
|
||
local _temp_victims=""
|
||
if net.get_player_info(arg4, "name") ~= nil then
|
||
_temp_victims = " player(s) ".. Perun.GetMulticrewCrewNames(arg4) .. " ";
|
||
|
||
Perun.LogStats(arg4);
|
||
else
|
||
_temp_victims = " AI ";
|
||
end
|
||
|
||
if net.get_player_info(arg1, "name") ~= nil then
|
||
_temp_killers = " player(s) ".. Perun.GetMulticrewCrewNames(arg1) .." ";
|
||
|
||
_temp_event_type=""
|
||
if arg3 ~= arg6 then
|
||
_temp_category=Perun.GetCategory(arg5)
|
||
|
||
if _temp_category == "Planes" then
|
||
_temp_event_type="kill_Planes"
|
||
elseif _temp_category == "Helicopters" then
|
||
_temp_event_type="kill_Helicopters"
|
||
elseif _temp_category == "Ships" then
|
||
_temp_event_type="kill_Ships"
|
||
elseif _temp_category == "Air Defence" then
|
||
_temp_event_type="kill_Air_Defence"
|
||
elseif _temp_category == "Unarmed" then
|
||
_temp_event_type="kill_Unarmed"
|
||
elseif _temp_category == "Armor" then
|
||
_temp_event_type="kill_Armor"
|
||
elseif _temp_category == "Infantry" then
|
||
_temp_event_type="kill_Infantry"
|
||
elseif _temp_category == "Fortification" then
|
||
_temp_event_type="kill_Fortification"
|
||
elseif _temp_category == "Artillery" or _temp_category == "MissilesSS" then
|
||
_temp_event_type="kill_Artillery"
|
||
else
|
||
_temp_event_type="kill_Other"
|
||
end
|
||
if net.get_player_info(arg4, "name") ~= nil and arg3 ~= arg6 then
|
||
Perun.LogStatsCountCrew (arg1,"kill_PvP")
|
||
end
|
||
else
|
||
_temp_event_type="friendly_fire"
|
||
end
|
||
|
||
Perun.LogStatsCountCrew (arg1,_temp_event_type)
|
||
|
||
else
|
||
_temp_killers = " AI ";
|
||
end
|
||
|
||
if arg7 == "" then
|
||
arg7 = "Cannon"
|
||
end
|
||
|
||
local victim_vehicle = arg5
|
||
if victim_vehicle == "" then
|
||
victim_vehicle = "?"
|
||
end
|
||
|
||
Perun.LogEvent(eventName,Perun.SideID2Name(arg3) .. _temp_killers .. " in " .. arg2 .. " killed " .. Perun.SideID2Name(arg6) .. _temp_victims .. " in " .. victim_vehicle .. " using " .. arg7 .. " [".. Perun.GetCategory(arg5).."]",arg7,Perun.GetCategory(arg5));
|
||
|
||
elseif eventName == "self_kill" then
|
||
--"self_kill", playerID
|
||
Perun.LogStats(arg1);
|
||
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " killed himself",nil,nil);
|
||
|
||
elseif eventName == "change_slot" then
|
||
--"change_slot", playerID, slotID, prevSide
|
||
|
||
_master_type,_master_slot,_sub_slot = Perun.GetMulticrewAllParameters(arg1)
|
||
if _sub_slot == nil then
|
||
_sub_slot =""
|
||
else
|
||
_sub_slot =" (" .. _sub_slot .. ") "
|
||
end
|
||
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " changed slot to " .. _master_type .. " " .. _sub_slot,nil,nil);
|
||
|
||
Perun.LogStats(arg1);
|
||
Perun.LogStatsCount(arg1,"init")
|
||
Perun.PlayersTableCache["p"..arg1]=net.get_player_info(arg1);
|
||
|
||
elseif eventName == "connect" then
|
||
--"connect", playerID, name
|
||
Perun.LogLogin(arg1);
|
||
Perun.LogEvent(eventName,"Player "..net.get_player_info(arg1, "name") .. " connected",nil,nil);
|
||
Perun.PlayersTableCache["p"..arg1]=net.get_player_info(arg1);
|
||
|
||
elseif eventName == "disconnect" then
|
||
--"disconnect", playerID, name, playerSide, reason_code
|
||
Perun.LogEvent(eventName,"Player " .. arg2 .. " disconnected (".. arg4 .. ")." ,arg4,nil);
|
||
Perun.LogStats(arg1);
|
||
|
||
elseif eventName == "crash" then
|
||
--"crash", playerID, unit_missionID
|
||
Perun.LogStatsCountCrew (arg1,"crash")
|
||
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .. " crashed in " .. DCS.getUnitType(arg2),nil,nil);
|
||
|
||
elseif eventName == "eject" then
|
||
--"eject", playerID, unit_missionID
|
||
Perun.LogStatsCountCrew (arg1,"eject") -- TBD crew or initiator only?
|
||
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .. " ejected " .. DCS.getUnitType(arg2),nil,nil);
|
||
|
||
elseif eventName == "takeoff" then
|
||
--"takeoff", playerID, unit_missionID, airdromeName
|
||
if arg3 ~= "" then
|
||
_temp_airfield = " from " .. arg3;
|
||
else
|
||
_temp_airfield = "";
|
||
end
|
||
|
||
Perun.LogStatsCountCrew (arg1,Perun.GetTakeOffLandingEvent(true,arg3))
|
||
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .. " took off in ".. DCS.getUnitType(arg2) .. _temp_airfield,arg3,nil);
|
||
|
||
elseif eventName == "landing" then
|
||
--"landing", playerID, unit_missionID, airdromeName
|
||
if arg3 ~= "" then
|
||
_temp_airfield = " at " .. arg3;
|
||
else
|
||
_temp_airfield ="";
|
||
end
|
||
|
||
Perun.LogStatsCountCrew (arg1,Perun.GetTakeOffLandingEvent(false,arg3))
|
||
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .. " landed in " .. DCS.getUnitType(arg2).. _temp_airfield,arg3,nil);
|
||
|
||
elseif eventName == "pilot_death" then
|
||
--"pilot_death", playerID, unit_missionID
|
||
Perun.LogStatsCountCrew (arg1,"pilot_death") -- TBD crew or initiator only?
|
||
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player(s) " .. Perun.GetMulticrewCrewNames(arg1) .. " in " .. DCS.getUnitType(arg2) .. " died",nil,nil);
|
||
|
||
else
|
||
Perun.LogEvent(eventName,"Unknown event type",nil,nil);
|
||
|
||
end
|
||
Perun.AddLog("Event handler for " .. eventName .. " finished",2)
|
||
end
|
||
|
||
-- ########### Finalize and set callbacks ###########
|
||
if Perun.IsServer then
|
||
-- If this game instance is hosting multiplayer game, start Perun
|
||
Perun.MissionHash=Perun.GenerateMissionHash() -- Generate initial missionhash
|
||
DCS.setUserCallbacks(Perun) -- Set user callbacs, map DCS event handlers with functions defined above
|
||
net.log("Perun by VladMordock was loaded: " .. Perun.Version ) -- Display perun information in log
|
||
Perun.ConnectToPerun() -- Connect to Perun server
|
||
end
|