Jump to content

Igneous01

Members
  • Posts

    130
  • Joined

  • Last visited

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Looks great! I like the concept of reading all the triggers and scanning their attributes automagically, feels very meta-programming to me. How does this contrast with MOOSE?
  2. I notice you can define a list of key/value pairs on a trigger zone. Is there a way to read these values as well as update them during the mission?
  3. Looks like this is a thing. https://www.janes.com/defence-news/news-detail/update-images-show-plagf-mi-171-helo-equipped-with-possible-ecm-pods
  4. I believe http is not supported in the socket package with the version of lua supplies by the dcs scripting environment. You can either create TCP sockets or UDP sockets, and you must handle the send/receive manually. I've done some of this work myself in an older MissionScripting.lua as an example. This code has been battle tested quite a bit and the socket connections were pretty reliable. You send messages via json strings, which are just lua objects encoded into a json string and sent over the wire. Anything listening on the other end can use a json parser library to read back the receive and parse the message. It's not as simple as using a rest api or http, but it does the job. Scripts\\ServerGameGUI.lua package.path = package.path..";.\\LuaSocket\\?.lua;" package.cpath = package.cpath..";.\\LuaSocket\\?.dll;" local JSONPath = lfs.writedir() .. "Scripts\\JSON.lua" local _errormsg = "" net.log("JSON File Path: " .. JSONPath) KI = {} -- UDP Port Numbers to communicate with the server side mod KI.Config.GAMEGUI_RECEIVE_PORT = 6005 -- the port to listen on for server side messages KI.Config.GAMEGUI_SEND_TO_PORT = 6006 -- the port to send messages to server side KI.Config.SERVER_SESSION_RECEIVE_PORT = 6007 -- the port to listen for server side session/server info -- Initialize Sockets KI.UDPSendSocket = socket.udp() KI.UDPReceiveSocket = socket.udp() KI.UDPReceiveSocket:setsockname("*", KIServer.Config.GAMEGUI_RECEIVE_PORT) KI.UDPReceiveSocket:settimeout(.0001) --receive timer --=============================================================================-- -- TCPSocket INIT KI.TCPSocket = { Object = nil, IsConnected = false } function KI.TCPSocket.Connect() net.log("KI.TCPSocket.Connect called") -- if the socket handle is not nil, invoke close on it just in case it was still left open if KI.TCPSocket.Object ~= nil then KI.TCPSocket.Object:close() end -- start connection KI.TCPSocket.Object = socket.tcp() KI.TCPSocket.Object:settimeout(5) KI.TCPSocket.Object:setoption("tcp-nodelay", true) KI.TCPSocket.IsConnected = false local _r, _err = KI.TCPSocket.Object:connect(KI.Config.TCP_SERVER_IP, KI.Config.TCP_SERVER_PORT) KI.TCPSocket.Object:settimeout(.0001) if _r ~= 1 or _err then net.log("KI.TCPSocket.Connect - ERROR - Failed to connect to TCP Server (Reason: " .. _err .. ")") KI.TCPSocket.IsConnected = false return false else KI.TCPSocket.IsConnected = true return true end end function KI.TCPSocket.Disconnect() net.log("KI.TCPSocket.Disconnect called") KI.TCPSocket.Object:close() KI.TCPSocket.IsConnected = false end -- Creates the message in the correct format the server expects -- Encodes into JSON, and appends size of message in first 6 characters of string function KI.TCPSocket.CreateMessage(action_name, dest, is_bulk_query, data) net.log("KI.TCPSocket.CreateMessage called") local _msg = { Action = action_name, Destination = dest, BulkQuery = is_bulk_query, Data = data, } local _jsonmsg = KI.JSON:encode(_msg) -- sending 6 char header that is size of msg string local _m = string.format("%06d", string.len(_jsonmsg)) .. _jsonmsg net.log("KI.TCPSocket.CreateMessage - dumping message") net.log(_m) return _m end -- Decodes message from JSON string into LUA Table Object function KI.TCPSocket.DecodeMessage(msg) net.log("KI.TCPSocket.DecodeMessage called") local _err = "" local _result, _luaObject = xpcall(function() return KI.JSON:decode(msg) end, function(err) _err = err end) if _result and _luaObject ~= nil then net.log("KI.TCPSocket.DecodeMessage - Message Decoded") return _luaObject elseif _err ~= "" then net.log("KI.TCPSocket.DecodeMessage ERROR - " .. _err) return nil else net.log("KI.TCPSocket.DecodeMessage ERROR - UNKNOWN ERROR") return nil end end function KIServer.TCPSocket.SendUntilComplete(msg, timeout) net.log("KIServer.TCPSocket.SendUntilComplete called") if not KIServer.TCPSocket.IsConnected then net.log("KIServer.TCPSocket.SendUntilComplete - ERROR - Socket is not connected to DB server") return false end if timeout then KIServer.TCPSocket.Object:settimeout(timeout) -- set the timeout (used to handle particularly large messages) else KIServer.TCPSocket.Object:settimeout(.0001) end local bytes_sent = 0 local msg_size = string.len(msg) -- copy the original msg parameter as we want to manipulate the copy without changing the original (but if strings are not by ref - why bother?) local _msgCopy = msg while bytes_sent ~= msg_size do local _indexSent, _error, _lastIndexSent = KIServer.TCPSocket.Object:send(_msgCopy) -- successful send if _indexSent then bytes_sent = bytes_sent + _indexSent else -- error encountered - check third parameter to see if at least some data was sent and retry if _lastIndexSent ~= 0 then net.log("KIServer.TCPSocket.SendUntilComplete - partial send occurred (reason: " .. _error .. ") - Continuing") bytes_sent = bytes_sent + _lastIndexSent else -- complete failure - log net.log("KIServer.TCPSocket.SendUntilComplete - ERROR in sending data (reason: " .. _error .. ")") KIServer.TCPSocket.Disconnect() return false end end -- net.log("KIServer.TCPSocket.SendUntilComplete - bytes sent: "..tostring(bytes_sent)) -- net.log("KIServer.TCPSocket.SendUntilComplete - sent string: '" .. _msgCopy:sub(1, bytes_sent).."'") _msgCopy = _msgCopy:sub(bytes_sent + 1) -- shrink the msg down to what has not been sent -- net.log("KIServer.TCPSocket.SendUntilComplete - Remaining buffer length: " .. tostring(string.len(_msgCopy)) .. " data : '" .. _msgCopy .. "'") end return true end function KIServer.TCPSocket.ReceiveUntilComplete(timeout) net.log("KIServer.TCPSocket.ReceiveUntilComplete called") if timeout then KIServer.TCPSocket.Object:settimeout(timeout) else KIServer.TCPSocket.Object:settimeout(.0001) end local header, _error = KIServer.TCPSocket.Object:receive(6) if header and header:len() == 6 then local msg_size = tonumber(header) local msg, _error = KIServer.TCPSocket.Object:receive(msg_size) if msg and msg:len() == msg_size then net.log("KIServer.TCPSocket.ReceiveUntilComplete - received data transmission") return msg elseif msg and msg:len() < msg_size then net.log("KIServer.TCPSocket.ReceiveUntilComplete - partial data received (Reason: " .. _error .. ")") net.log("KIServer.TCPSocket.ReceiveUntilComplete - trying again") local partmsg, _error = KIServer.TCPSocket.Object:receive(msg_size - msg:len()) -- check if the partial message came through and is the size we are expecting it to be if partmsg and partmsg:len() == (msg_size - msg:len()) then msg = msg .. partmsg return msg else net.log("KIServer.TCPSocket.ReceiveUntilComplete - second try failed to receive (Reason: " .. _error .. ")") KIServer.TCPSocket.Disconnect() return nil end else net.log("KIServer.TCPSocket.ReceiveUntilComplete - ERROR in receiving body data (Reason: " .. _error .. ")") KIServer.TCPSocket.Disconnect() return nil end else net.log("KIServer.TCPSocket.ReceiveUntilComplete - WARNING - did not receive header data (reason: " .. _error .. ")") if _error == "closed" then KIServer.TCPSocket.Disconnect() -- disconnect the socket if the server closed the connection end return nil end end -- end Server TCP Socket -- ========================================================================================================== --
  5. I'm wondering how realistic this could be. If you take the existing Ka-50 platform in game, could you somehow be able to retrofit an ECM pod that could be turned on through the cockpit? I'm imagining a scenario where a squadron of music jamming Ka-50s secretly fly behind enemy lines towards a SAM site, and on a command signal, all would fly above the terrain with music on, from different locations, to overwhelm and confuse the enemy SAM system. Then a SEAD strike package would be flown in to destroy the radar systems. The theory here being that a strong local radar transmission will trick the radar computer systems into prioritizing the ka-50s as the highest priority threat. This would in theory give the strike package some breathing room as the enemy will be too distracted to search/track/engage the strike package from maximum range. Would it be possible to script this in DCS? I've never heard of the ability to fit weapons from a different airframe onto the ka-50 without mods, which I want to avoid.
  6. There's different approaches to do what you're trying to do. 1. You can hook into the dcs game events via lua script and write code to track the data you want to capture. -- catch all forms of shooting events from a player GameEventHandler = {} function GameEventHandler:onEvent(event) if (event.id == world.event.S_EVENT_SHOT or event.id == world.event.S_EVENT_SHOOTING_START or event.id == world.event.S_EVENT_SHOOTING_END) and playerName then env.info("SHOT / SHOOTING START / SHOOTING END") -- catch all hit events that were initiated by a player elseif event.id == world.event.S_EVENT_HIT and playerName then env.info("PLAYER HIT SOMEONE") end end world.addEventHandler(GameEventHandler) ^ Some limitations with the above is that kill events are not tracked here. You would need to create a lua server mod and have an event handler track kills there. You can see a sample of that here: https://github.com/KaukausInsurgency/ki-dcs-mod/blob/master/DCSMod/Hooks/KI_ServerGameGUI.lua (line 1544) 2. You can parse the debriefing.log file you save with something like python and then do whatever you want with it from there. Here is a repo of small python code that parses the debriefing log into a python dictionary. https://github.com/Igneous01/dcs_miz_parser/blob/master/dcs_miz_parser.py Specifically lines 49, 53 - using this library for python to parse lua: https://github.com/SirAnthony/slpp
  7. I've been on hiatus from DCS for a few months (last seen on 1.5) and decided to run up some existing test cases I've built last year to check if any of the scripting engine bugs have been fixed since last year. Looks like it's still the same set of issues as before - so I'm raising awareness on these again: 1) Unit:getCategory() still broken (always returning "HELICOPTER") All but 1 test fails -- test that Unit:getCategory() works UT.TestCompare(function() return Unit.getByName("DCSPlane"):getCategory() == Unit.Category.AIRPLANE end) -- fails UT.TestCompare(function() return Unit.getByName("DCSGroundUnit"):getCategory() == Unit.Category.GROUND_UNIT end) -- fails UT.TestCompare(function() return Unit.getByName("DCSHelo"):getCategory() == Unit.Category.HELICOPTER end) -- pass UT.TestCompare(function() return Unit.getByName("DCSStructure"):getCategory() == Unit.Category.STRUCTURE end) -- fails 2) Group:getByName doesn't return client slots that are not occupied. It's not possible to manipulate or get a group that is a client slot in mp. -- Client slots should be visible in Group.getByName UT.TestCompare(function() return Group.getByName("DCSClientSlot") ~= nil end) -- fails 3) coalition.getGroups() doesn't return client slots at all. It's really not possible to get the client slots defined in a mission at all. if true then local found = false for i, gp in pairs(coalition.getGroups(2, 0)) do if gp:getName() == "DCSClientSlot" then found = true break end end UT.TestCompare(function() return found end) -- fails end 4) calling :destroy on cargo object doesn't work in same scope as rest of code. This breaks a lot of behavior in my crate scripts, and allows people to 'unpack' the same dead crate multiple times. -- test that spawning, then calling :destroy() on a cargo object actually kills it if true then local pos = StaticObject.getByName("DCSCargo"):getPoint() local obj = coalition.addStaticObject(country.id.RUSSIA, { country = "Russia", category = "Cargos", x = pos.x, y = pos.z, type = "ammo_cargo", name = "DCSSpawnedCargo", mass = 1400, canCargo = true }) UT.TestCompare(function() return obj:isExist() end) -- pass obj:destroy() UT.TestCompare(function() return not obj:isExist() end) -- fails UT.TestCompare(function() return obj:getLife() < 1 end) -- fails end 5) [NEW] calling net.get_player_info(1) returns nil in single player. This used to work in 1.5, returning the local player. Now it returns nil, and only works in MP.
  8. Yes - we are working on a new website and live map. The original site is going to be replaced with a newer and prettier version. A sneak peak of the new website is here: http://beta.kaukasusinsurgency.com/ So for the time being the mission scripting side has been on hold while we work on getting the new website up. There's still a few bug fixes that are being done on the scripting side of things, but most of the focus is on the new website. There is a group that is running a private version of this and so far things have been relatively stable. We'll release more info when the site is closer to a v1 launch.
  9. I had a problem with this back in 1.5 but the issue was that the name of my script did not include GameGUI in the filename. Can't recall if that check was dropped in later versions.
  10. Update on progress as I've been inactive on this thread - we have a 3 servers running this on 2.5 - there have been some stability issues with the latest mp crashes that have affected blue flag and dynamic caucasus, but it looks like the cause is known and I have implemented similar workarounds to avoid the crashing. The development of this project is open source and I am adopting an agile like method for features and bugs. For those that are not aware, agile method of development breaks down work items into small tasks and chunks called 'sprints' - sprints typically have a duration of a few weeks to a month or 2, but in my case the sprints are kept to 2 weeks so that releases are packaged faster (and this is not some crazy enterprise software :P). Usually sprints are planned by some governing body like a product owner or manager, but in this case I'm trying something unique in having the user base vote for the items they want to see added. That means your vote counts and the items with the most votes are put into the sprints to be worked on. If you would like to participate please feel free to provide your thoughts and reactions in https://github.com/Igneous01/KI/issues The latest sprint is 0.78, which will be closing soon (followed by a refactoring sprint). https://github.com/Igneous01/KI/projects/9 I will be opening up a project for 0.80 sprint which will be open for users to vote on features and bugs they would like to see added / fixed.
  11. I will be addressing this in KI spawn code as well today. If we are confident it's related to the AI's disperse behavior it should be possible to reproduce on a dev machine and identify the issue.
  12. Grimes - for the function findPathOnroads, does it return the road positions in order (from start to dest) or is the order returned random? Just curious if I can do something like roads[#roads / 2] to get the midway point between the two positions.
  13. I think it's a good idea to add things like DCS Version, Map Name, and Mods as part of server description or something. I will look into that, I think that would be useful for server owners.
  14. Thanks Pikey and Grimes, I was looking at how the Moose CLIENT class got it's information about client slots and see it was using very similar code to iterate through the env.mission table for units with skill 'client' (those are some big nested loops ;) ) Is there a shorter way of iterating through the table so that I only need to iterate maybe [countries][groups] ? If there isn't it's fine, i was just curious if I could reduce my code to maybe 2 to 3 loop iterations instead of the 4 that are there.
  15. Just keeping everyone updated - I am working with a virtual wing in testing and feedback on this early build of KI. So far some good ideas and gaps have been identified so I'll be spending some time addressing the immediate ones. Initial live runs on the server showed a lot of promise - good fps, good latency, and some fun as well. ESAc_matador - let me know when you would like to give it a go, we've got a working version on both my machine and the vwing i'm working with. It would be nice to get another server admin / vwing to try it out and provide feedback.
×
×
  • Create New...