-- the state.json file will be updated according to this schedule, and also on each destruction or capture event local WRITESTATE_SCHEDULE_IN_SECONDS = 60 logger = mist.Logger:new("DCSRetribution", "info") logger:info("Check that json.lua is loaded : json = "..tostring(json)) crash_events = {} -- killed aircraft will be added via S_EVENT_CRASH event dead_events = {} -- killed units will be added via S_EVENT_DEAD event unit_lost_events = {} -- killed units will be added via S_EVENT_UNIT_LOST kill_events = {} -- killed units will be added via S_EVENT_KILL base_capture_events = {} destroyed_objects_positions = {} -- will be added via S_EVENT_DEAD event mission_ended = false local function ends_with(str, ending) return ending == "" or str:sub(-#ending) == ending end local function messageAll(message) local msg = {} msg.text = message msg.displayTime = 25 msg.msgFor = {coa = {'all'}} mist.message.add(msg) end function write_state() local _debriefing_file_location = debriefing_file_location if not debriefing_file_location then _debriefing_file_location = "[nil]" end local fp = io.open(_debriefing_file_location, 'w') local game_state = { ["crash_events"] = crash_events, ["dead_events"] = dead_events, ["base_capture_events"] = base_capture_events, ["unit_lost_events"] = unit_lost_events, ["kill_events"] = kill_events, ["mission_ended"] = mission_ended, ["destroyed_objects_positions"] = destroyed_objects_positions, } if not json then local message = string.format("Unable to save DCS Retribution state to %s, JSON library is not loaded !", _debriefing_file_location) logger:error(message) messageAll(message) end fp:write(json:encode(game_state)) fp:close() end local function canWrite(name) local f = io.open(name, "w") if f then f:close() return true end return false end local function testDebriefingFilePath(folderPath, folderName, useCurrentStamping) if folderPath then local filePath = nil if not ends_with(folderPath, "\\") then folderPath = folderPath .. "\\" end if useCurrentStamping then filePath = string.format("%sstate-%s.json",folderPath, tostring(os.time())) else filePath = string.format("%sstate.json",folderPath) end local isOk = canWrite(filePath) if isOk then logger:info(string.format("The state.json file will be created in %s : (%s)",folderName, filePath)) return filePath end end return nil end local function discoverDebriefingFilePath() -- establish a search pattern into the following modes -- 1. Environment variable RETRIBUTION_EXPORT_DIR, to support dedicated server hosting -- 2. Embedded DCS Retribution dcsRetribution.installPath (set by the app to its install path), to support locally hosted single player -- 3. System temporary folder, as set in the TEMP environment variable -- 4. Working directory. local useCurrentStamping = nil if os then useCurrentStamping = os.getenv("RETRIBUTION_EXPORT_STAMPED_STATE") end local installPath = nil if dcsRetribution then installPath = dcsRetribution.installPath end if os then local result = nil -- try using the RETRIBUTION_EXPORT_DIR environment variable result = testDebriefingFilePath(os.getenv("RETRIBUTION_EXPORT_DIR"), "RETRIBUTION_EXPORT_DIR", useCurrentStamping) if result then return result end -- no joy ? maybe there is a valid path in the mission ? result = testDebriefingFilePath(installPath, "the DCS Retribution install folder", useCurrentStamping) if result then return result end -- there's always the possibility of using the system temporary folder result = testDebriefingFilePath(os.getenv("TEMP"), "TEMP", useCurrentStamping) if result then return result end end -- nothing worked, let's try the last resort folder : current directory. if lfs then return testDebriefingFilePath(lfs.writedir().."Missions\\", "the working directory", useCurrentStamping) end return nil end debriefing_file_location = discoverDebriefingFilePath() write_state_error_handling = function() local _debriefing_file_location = debriefing_file_location if not debriefing_file_location then _debriefing_file_location = "[nil]" logger:error("Unable to find where to write DCS Retribution state") end if pcall(write_state) then else messageAll("Unable to write DCS Retribution state to ".._debriefing_file_location.. "\nYou can abort the mission in DCS Retribution.\n".. "\n\nPlease fix your setup in DCS Retribution, make sure you are pointing to the right installation directory from the File/Preferences menu. Then after fixing the path restart DCS Retribution, and then restart DCS.".. "\n\nYou can also try to fix the issue manually by replacing the file /Scripts/MissionScripting.lua by the one provided there : /resources/scripts/MissionScripting.lua. And then restart DCS. (This will also have to be done again after each DCS update)".. "\n\nIt's not worth playing, the state of the mission will not be recorded.") end -- reschedule mist.scheduleFunction(write_state_error_handling, {}, timer.getTime() + WRITESTATE_SCHEDULE_IN_SECONDS) end activeWeapons = {} local function onEvent(event) if event.id == world.event.S_EVENT_CRASH and event.initiator then crash_events[#crash_events + 1] = event.initiator.getName(event.initiator) write_state() end if event.id == world.event.S_EVENT_UNIT_LOST and event.initiator then unit_lost_events[#unit_lost_events + 1] = event.initiator.getName(event.initiator) write_state() end if event.id == world.event.S_EVENT_KILL and event.target then kill_events[#kill_events + 1] = event.target.getName(event.target) write_state() end if event.id == world.event.S_EVENT_DEAD and event.initiator then dead_events[#dead_events + 1] = event.initiator.getName(event.initiator) local position = event.initiator.getPosition(event.initiator) local destruction = {} destruction.x = position.p.x destruction.y = position.p.y destruction.z = position.p.z destruction.type = event.initiator:getTypeName() destruction.orientation = mist.getHeading(event.initiator) * 57.3 destroyed_objects_positions[#destroyed_objects_positions + 1] = destruction write_state() end if event.id == world.event.S_EVENT_MISSION_END then mission_ended = true write_state() end end mist.addEventHandler(onEvent) -- create the state.json file and start the scheduling write_state_error_handling()