* #CSAR - Add Persistence (#1889)

* Adds a modified version of ops.CTLD's Persistence to ops.CSAR

* Update Marker.lua

---------

Co-authored-by: Jason du Plessis <33880363+TheChosenOn3@users.noreply.github.com>
This commit is contained in:
Thomas 2023-01-27 18:36:38 +01:00 committed by GitHub
parent f4c9bced45
commit 5ec18d45a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 313 additions and 4 deletions

View File

@ -26,11 +26,11 @@
-- --
-- === -- ===
-- --
-- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing) -- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing), The Chosen One (Persistence)
-- @module Ops.CSAR -- @module Ops.CSAR
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
-- Date: November 2022 -- Date: January 2023
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@ -197,6 +197,26 @@
-- --
-- --Create a casualty and CASEVAC request from a "Point" (VEC2) for the blue coalition --shagrat -- --Create a casualty and CASEVAC request from a "Point" (VEC2) for the blue coalition --shagrat
-- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE) -- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE)
--
-- ## 6. Save and load downed pilots - Persistance
--
-- You can save and later load back downed pilots to make your mission persistent.
-- For this to work, you need to de-sanitize **io** and **lfs** in your MissionScripting.lua, which is located in your DCS installtion folder under Scripts.
-- There is a risk involved in doing that; if you do not know what that means, this is possibly not for you.
--
-- Use the following options to manage your saves:
--
-- mycsar.enableLoadSave = true -- allow auto-saving and loading of files
-- mycsar.saveinterval = 600 -- save every 10 minutes
-- mycsar.filename = "missionsave.csv" -- example filename
-- mycsar.filepath = "C:\\Users\\myname\\Saved Games\\DCS\Missions\\MyMission" -- example path
--
-- Then use an initial load at the beginning of your mission:
--
-- mycsar:__Load(10)
--
-- **Caveat:**
-- Dropped troop noMessage and forcedesc parameters aren't saved.
-- --
-- @field #CSAR -- @field #CSAR
CSAR = { CSAR = {
@ -296,6 +316,8 @@ function CSAR:New(Coalition, Template, Alias)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #CSAR local self=BASE:Inherit(self, FSM:New()) -- #CSAR
BASE:T({Coalition, Prefixes, Alias})
--set Coalition --set Coalition
if Coalition and type(Coalition)=="string" then if Coalition and type(Coalition)=="string" then
if Coalition=="blue" then if Coalition=="blue" then
@ -346,6 +368,8 @@ function CSAR:New(Coalition, Template, Alias)
self:AddTransition("*", "Returning", "*") -- CSAR able to return to base. self:AddTransition("*", "Returning", "*") -- CSAR able to return to base.
self:AddTransition("*", "Rescued", "*") -- Pilot at MASH. self:AddTransition("*", "Rescued", "*") -- Pilot at MASH.
self:AddTransition("*", "KIA", "*") -- Pilot killed in action. self:AddTransition("*", "KIA", "*") -- Pilot killed in action.
self:AddTransition("*", "Load", "*") -- CSAR load event.
self:AddTransition("*", "Save", "*") -- CSAR save event.
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
-- tables, mainly for tracking actions -- tables, mainly for tracking actions
@ -442,6 +466,14 @@ function CSAR:New(Coalition, Template, Alias)
self.SRSVolume = 1.0 -- volume 0.0 to 1.0 self.SRSVolume = 1.0 -- volume 0.0 to 1.0
self.SRSGender = "male" -- male or female self.SRSGender = "male" -- male or female
local AliaS = string.gsub(self.alias," ","_")
self.filename = string.format("CSAR_%s_Persist.csv",AliaS)
-- load and save downed pilots
self.enableLoadSave = false
self.filepath = nil
self.saveinterval = 600
------------------------ ------------------------
--- Pseudo Functions --- --- Pseudo Functions ---
------------------------ ------------------------
@ -471,6 +503,24 @@ function CSAR:New(Coalition, Template, Alias)
-- @function [parent=#CSAR] __Status -- @function [parent=#CSAR] __Status
-- @param #CSAR self -- @param #CSAR self
-- @param #number delay Delay in seconds. -- @param #number delay Delay in seconds.
--
-- --- Triggers the FSM event "Load".
-- @function [parent=#CSAR] Load
-- @param #CSAR self
--- Triggers the FSM event "Load" after a delay.
-- @function [parent=#CSAR] __Load
-- @param #CSAR self
-- @param #number delay Delay in seconds.
--- Triggers the FSM event "Save".
-- @function [parent=#CSAR] Load
-- @param #CSAR self
--- Triggers the FSM event "Save" after a delay.
-- @function [parent=#CSAR] __Save
-- @param #CSAR self
-- @param #number delay Delay in seconds.
--- On After "PilotDown" event. Downed Pilot detected. --- On After "PilotDown" event. Downed Pilot detected.
-- @function [parent=#CSAR] OnAfterPilotDown -- @function [parent=#CSAR] OnAfterPilotDown
@ -538,6 +588,24 @@ function CSAR:New(Coalition, Template, Alias)
-- @param #string To To state. -- @param #string To To state.
-- @param #string Pilotname Name of the pilot KIA. -- @param #string Pilotname Name of the pilot KIA.
--- FSM Function OnAfterLoad.
-- @function [parent=#CSAR] OnAfterLoad
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path (Optional) Path where the file is located. Default is the DCS root installation folder or your "Saved Games\\DCS" folder if the lfs module is desanitized.
-- @param #string filename (Optional) File name for loading. Default is "CSAR_<alias>_Persist.csv".
--- FSM Function OnAfterSave.
-- @function [parent=#CSAR] OnAfterSave
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path (Optional) Path where the file is saved. Default is the DCS root installation folder or your "Saved Games\\DCS" folder if the lfs module is desanitized.
-- @param #string filename (Optional) File name for saving. Default is "CSAR_<alias>_Persist.csv".
return self return self
end end
@ -2219,7 +2287,16 @@ function CSAR:onafterStart(From, Event, To)
self.msrs:SetLabel("CSAR") self.msrs:SetLabel("CSAR")
self.SRSQueue = MSRSQUEUE:New("CSAR") self.SRSQueue = MSRSQUEUE:New("CSAR")
end end
self:__Status(-10) self:__Status(-10)
if self.enableLoadSave then
local interval = self.saveinterval
local filename = self.filename
local filepath = self.filepath
self:__Save(interval,filepath,filename)
end
return self return self
end end
@ -2452,6 +2529,240 @@ function CSAR:onbeforeLanded(From, Event, To, HeliName, Airbase)
self:T({From, Event, To, HeliName, Airbase}) self:T({From, Event, To, HeliName, Airbase})
return self return self
end end
--- On before "Save" event. Checks if io and lfs are available.
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path (Optional) Path where the file is saved. Default is the DCS root installation folder or your "Saved Games\\DCS" folder if the lfs module is desanitized.
-- @param #string filename (Optional) File name for saving. Default is "CSAR_<alias>_Persist.csv".
function CSAR:onbeforeSave(From, Event, To, path, filename)
self:T({From, Event, To, path, filename})
if not self.enableLoadSave then
return self
end
-- Thanks to @FunkyFranky
-- Check io module is available.
if not io then
self:E(self.lid.."ERROR: io not desanitized. Can't save current state.")
return false
end
-- Check default path.
if path==nil and not lfs then
self:E(self.lid.."WARNING: lfs not desanitized. State will be saved in DCS installation root directory rather than your \"Saved Games\\DCS\" folder.")
end
return true
end
--- On after "Save" event. Player data is saved to file.
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path Path where the file is saved. If nil, file is saved in the DCS root installtion directory or your "Saved Games" folder if lfs was desanitized.
-- @param #string filename (Optional) File name for saving. Default is Default is "CSAR_<alias>_Persist.csv".
function CSAR:onafterSave(From, Event, To, path, filename)
self:T({From, Event, To, path, filename})
-- Thanks to @FunkyFranky
if not self.enableLoadSave then
return self
end
--- Function that saves data to file
local function _savefile(filename, data)
local f = assert(io.open(filename, "wb"))
f:write(data)
f:close()
end
-- Set path or default.
if lfs then
path=self.filepath or lfs.writedir()
end
-- Set file name.
filename=filename or self.filename
-- Set path.
if path~=nil then
filename=path.."\\"..filename
end
local pilots = self.downedPilots
--local data = "LoadedData = {\n"
local data = "playerName,x,y,z,coalition,country,description,typeName,unitName,freq\n"
local n = 0
for _,_grp in pairs(pilots) do
local DownedPilot = _grp -- Wrapper.Group#GROUP
if DownedPilot and DownedPilot.alive then
-- get downed pilot data for saving
local playerName = DownedPilot.player
local group = DownedPilot.group
local coalition = group:GetCoalition()
local country = group:GetCountry()
local description = DownedPilot.desc
local typeName = DownedPilot.typename
local freq = DownedPilot.frequency
local location = group:GetVec3()
local unitName = DownedPilot.originalUnit
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%s,%s,%d\n",playerName,location.x,location.y,location.z,coalition,country,description,typeName,unitName,freq)
self:I(self.lid.."Saving to CSAR File: " .. txt)
data = data .. txt
end
end
_savefile(filename, data)
-- AutoSave
if self.enableLoadSave then
local interval = self.saveinterval
local filename = self.filename
local filepath = self.filepath
self:__Save(interval,filepath,filename)
end
return self
end
--- On before "Load" event. Checks if io and lfs and the file are available.
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path (Optional) Path where the file is located. Default is the DCS root installation folder or your "Saved Games\\DCS" folder if the lfs module is desanitized.
-- @param #string filename (Optional) File name for loading. Default is "CSAR_<alias>_Persist.csv".
function CSAR:onbeforeLoad(From, Event, To, path, filename)
self:T({From, Event, To, path, filename})
if not self.enableLoadSave then
return self
end
--- Function that check if a file exists.
local function _fileexists(name)
local f=io.open(name,"r")
if f~=nil then
io.close(f)
return true
else
return false
end
end
-- Set file name and path
filename=filename or self.filename
path = path or self.filepath
-- Check io module is available.
if not io then
self:E(self.lid.."WARNING: io not desanitized. Cannot load file.")
return false
end
-- Check default path.
if path==nil and not lfs then
self:E(self.lid.."WARNING: lfs not desanitized. State will be saved in DCS installation root directory rather than your \"Saved Games\\DCS\" folder.")
end
-- Set path or default.
if lfs then
path=path or lfs.writedir()
end
-- Set path.
if path~=nil then
filename=path.."\\"..filename
end
-- Check if file exists.
local exists=_fileexists(filename)
if exists then
return true
else
self:E(self.lid..string.format("WARNING: State file %s might not exist.", filename))
return false
--return self
end
end
--- On after "Load" event. Loads dropped units from file.
-- @param #CSAR self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #string path (Optional) Path where the file is located. Default is the DCS root installation folder or your "Saved Games\\DCS" folder if the lfs module is desanitized.
-- @param #string filename (Optional) File name for loading. Default is "CSAR_<alias>_Persist.csv".
function CSAR:onafterLoad(From, Event, To, path, filename)
self:T({From, Event, To, path, filename})
if not self.enableLoadSave then
return self
end
--- Function that loads data from a file.
local function _loadfile(filename)
local f=assert(io.open(filename, "rb"))
local data=f:read("*all")
f:close()
return data
end
-- Set file name and path
filename=filename or self.filename
path = path or self.filepath
-- Set path or default.
if lfs then
path=path or lfs.writedir()
end
-- Set path.
if path~=nil then
filename=path.."\\"..filename
end
-- Info message.
local text=string.format("Loading CSAR state from file %s", filename)
MESSAGE:New(text,10):ToAllIf(self.Debug)
self:I(self.lid..text)
local file=assert(io.open(filename, "rb"))
local loadeddata = {}
for line in file:lines() do
loadeddata[#loadeddata+1] = line
end
file:close()
-- remove header
table.remove(loadeddata, 1)
for _id,_entry in pairs (loadeddata) do
local dataset = UTILS.Split(_entry,",")
-- 1=playerName,2=x,3=y,4=z,5=coalition,6=country,7=description,8=typeName,9=unitName,10=freq\n
local playerName = dataset[1]
local vec3 = {}
vec3.x = tonumber(dataset[2])
vec3.y = tonumber(dataset[3])
vec3.z = tonumber(dataset[4])
local point = COORDINATE:NewFromVec3(vec3)
local coalition = dataset[5]
local country = dataset[6]
local description = dataset[7]
local typeName = dataset[8]
local unitName = dataset[9]
local freq = dataset[10]
self:_AddCsar(coalition, country, point, typeName, unitName, playerName, freq, nil, description, nil)
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- End Ops.CSAR -- End Ops.CSAR
-------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -175,8 +175,6 @@ function MARKER:New( Coordinate, Text )
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self = BASE:Inherit( self, FSM:New() ) -- #MARKER local self = BASE:Inherit( self, FSM:New() ) -- #MARKER
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
self.coordinate=UTILS.DeepCopy(Coordinate) self.coordinate=UTILS.DeepCopy(Coordinate)
self.text = Text self.text = Text