Pikey Posted February 23, 2020 Author Share Posted February 23, 2020 how to restart mission as normal ? I dont understand. Press LeftShift-R to restart a mission.? ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
AYcoo Posted February 23, 2020 Share Posted February 23, 2020 I dont understand. Press LeftShift-R to restart a mission.? i use it in my server to capture airports red units die and blue units come over when all airports are captured how could i reset this to start again (sorry my weak English) Link to comment Share on other sites More sharing options...
Pikey Posted February 23, 2020 Author Share Posted February 23, 2020 Ah! Makes more sense. Delete the Save file in your DCS directory, the mission is back to the start.i use it in my server to capture airports red units die and blue units come over when all airports are captured how could i reset this to start again (sorry my weak English) ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
AYcoo Posted February 23, 2020 Share Posted February 23, 2020 (edited) Ah! Makes more sense. Delete the Save file in your DCS directory, the mission is back to the start. thanks Pikey although it would be better if there is automatic way to delete it or reset for example when all airports cuptured trigger do script newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) Edited February 23, 2020 by AYcoo Link to comment Share on other sites More sharing options...
Pikey Posted February 23, 2020 Author Share Posted February 23, 2020 thanks Pikey although it would be better if there is automatic way to delete it or reset for example when all airports cuptured trigger do script newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) Just do that then. People dont all use it the same. For Moose Have a SET_AIRBASE:New():FilterCoalitions("red"):FilterStart() Count it's members. in a SCHEDULER. If it reaches 0 then os.remove() the SaveUnits.lua file restart the mission. You still need a way to restart the mission though, that's only avialable in the triggers of ME itself. Some people wouldnt like an immediate restart, just saying. MOOSE is easy, come learn Lua on Discord. :) ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
AYcoo Posted February 23, 2020 Share Posted February 23, 2020 [quote=newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) tried to put trigger do script but didn't work i have moose in my mission but i don't know how :( Link to comment Share on other sites More sharing options...
AYcoo Posted February 24, 2020 Share Posted February 24, 2020 up Link to comment Share on other sites More sharing options...
Pikey Posted February 25, 2020 Author Share Posted February 25, 2020 Sorry teaching you Lua is beyond the scope of forum work. You have to delete the save file as I said. its in your DCS folder. I've provided you with what you need to know, but I'm not customising the script for you! :) ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
AYcoo Posted February 25, 2020 Share Posted February 25, 2020 just want to know if there is alternative ok got that ty Link to comment Share on other sites More sharing options...
Pikey Posted March 26, 2020 Author Share Posted March 26, 2020 SimpleStatic Saving has been reworked as per 2nd post. I've fixed unit headings in SGS also. I wanted to scribble my mad findings about statics as it's taken me the best part of the entire day to workaround the seemingly endless issues DCS has. But I learned something worth sharing. 1. Farps. Jeez-Ohh. Farps (and rigs), as statics refuse to obey normal DCS static conventions in some of the methods you can use on them. In this way, I found it better to treat them as Airbases, since they reliably work in that manner. I've now excluded them fairly easily from attempting to be manipulated by checking if the name of the static is also an airbase. Mad scientist workaround, but its perfect. Farps and Rigs will not be touched. I've never destroyed one either, but just know that the script will not persist farps, or try to do anything with them. This means they stay in all of your missions through restarts. Which is what you want. 2. Other statics like "Effects". Effects like Bigsmoke are fairly new to DCS and do not observe all of the characteristics of other statics. They are always dead, getDesc() and other requests for type, heading do not work, but they end up included as a Static by moose. I've filtered these with nil checks also. 3. Ships For some reason ships always return that they are alive when asked. This absolutely puts the kaibosh on this script and there is nothing you can do about it either. I'd recommend only using ships as static units when you are decorating and couldnt give a rat's arse about their persistence. Statics will always work as cheap alternatives and visual fillers very nicely so are important because scaling multiplayer missions is vital. However ships are one to avoid for statics. 4. Cargo was fine and I tested the "Barrage Balloon" in the assets pack too. You have to remember that not all statics have a destroyed model. So you can bomb the DCS airshow crowd all you want and they will carry on cheering. The other issue to touch on is the error that occurs when a static object is spawned. I use the core scripting method rather than SPAWNSTATIC because it's the only way I can spawn a dead object. I have a feeling FlightControl hated statics with a pasison and they litter moose with SET issues, filtering issues and bugs, just by the nature of them having had bugs and quirks. The error is caused when the event handler for the birth of a dead static object is attempted to be added to the MOOSE DATABASE. It's a lot of error lines in the log, but it's entirely of no effect to either the game, Moose or the progressing of the script. Moose just can't deal with it because there is a missing index on the birth event, probably caused by the static itself being missing something from the event data. I'm choosing to ignore it for now as fixing it has no benefit to anyone once they know what it is. However, I've written code comemnts so you can choose to comment out the part of the script that replaces live statics with dead models of itself after a restart. If someone knows what they are doing, then they might have a care to do that and can. Someone that doesn't understand the error message, has no reason to ask how to remove it, since they should have read this or the known issues part and would also have desanitised their mission environment modules and are likely a danger to themselves and others with the copy/paste shortcut.;) ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
AYcoo Posted April 3, 2020 Share Posted April 3, 2020 (edited) hey again Pikey one question if i install SLmod would your script sgs still work ?or does SLmod does the job ? if not is there awat to make it work ? Edited April 3, 2020 by AYcoo Link to comment Share on other sites More sharing options...
Voodooflies Posted April 25, 2020 Share Posted April 25, 2020 Hey Pikey, Awesome scripts. I'm trying to use it on my multiplayer dynamic campaign called OP Iranian Freedom on PG, Open Beta. My mission uses MOOSE CAP/GCI with borders. The saving process itself works well (for both statics & groups) but for some reasons, after a restart, my CAP & GCI groups handled by MOOSE are not getting spawned. Have you got any idea ? That's the only issue I got so far. Here are the scripts I'm using.GCICAP_Iranian_Freedom.luaSGS_Iranian_Freedom.luaSSS_Iranian_Freedom.lua [sIGPIC][/sIGPIC] Link to comment Share on other sites More sharing options...
Pikey Posted April 26, 2020 Author Share Posted April 26, 2020 If you have a problem with GCI then troubleshoot that, with logs, in the appropriate thread or Discord. Isuspect you'll quickly find the issue with your GCI once you begin to read your dcs log. ___________________________________________________________________________ SIMPLE SCENERY SAVING * SIMPLE GROUP SAVING * SIMPLE STATIC SAVING * Link to comment Share on other sites More sharing options...
OzDeaDMeaT Posted September 2, 2020 Share Posted September 2, 2020 Hey Pikey, Firstly great script. I am attempting to load the externally from the .miz file. It all loads and creates the file ok. I am doing the same for Moose first also. Rather than starting the Moose script on Mission Start (it crashes my server for some reason) I am running the external include.lua that is running Moose etc. I got an external include script that is injected into the mission itself. local missionScriptsDir = [[C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\]] dofile(missionScriptsDir ..[[include.lua]]) The include looks like this: local mooseDir = [[C:\DCS_SCRIPTS\MOOSE\]] dofile(mooseDir ..[[Moose.lua]]) ---------------------------------------------------------------------------MOOSE local missionScriptsDir = [[C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\]] dofile(missionScriptsDir ..[[sGS.lua]]) The file is generated correctly, its on reload that I am getting an error saying the file exists. 2020-09-02 16:24:44.424 INFO SCRIPTING: *** MOOSE INCLUDE END *** 2020-09-02 16:24:44.424 INFO SCRIPTING: Loaded Simple Group Saving, by Pikey, 2018, version 1.0 2020-09-02 16:24:44.424 ERROR SCRIPTING: Mission script error: [string "C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\SGS.lua"]:90: attempt to index global 'lfs' (a nil value) stack traceback: [C]: ? [string "C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\SGS.lua"]:90: in function 'file_exists' [string "C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\SGS.lua"]:105: in main chunk [C]: in function 'dofile' [string "C:\DCS_SCRIPTS\OzDM_Syria_Persistence_Test\include.lua"]:5: in main chunk [C]: in function 'dofile' [string "C:\Users\C0RNER~1\AppData\Local\Temp\DCS.openbeta_server\/~mis00006B1D.lua"]:2: in main chunk I have changed two lines in your script. Firstly I have it so the units list is saved every 10 minutes. SaveScheduleUnits=600 --how many seconds between each check of all the statics. Secondly I changed it so the File it saves out to is of a similar name to the mission file itself. writemission(newMissionStr, "OzDM_Syria_Persistence_Test.lua")--write the file from the above to SaveUnits.lua The server is running SLMOD and i keep commenting out the likes but each time the server starts it uncomments these two lines. sanitizeModule('io') sanitizeModule('lfs') I believe this is the problem but ****ed if i know how to stop DCS from modifying the lines at server start. CPU: i9-12900K @ 4.9Ghz M/B: MSI MEG z690 Ace RAM: 128GB Video Card: MSI RTX 4090 Suprim Liquid X VR: Varjo Aero Link to comment Share on other sites More sharing options...
OzDeaDMeaT Posted September 2, 2020 Share Posted September 2, 2020 OK, it turns out SLMOD was ****ing me up. I have since removed SLMOD while i try and work out how this thing is supposed to work. I can't seem to get the vehicles to load correctly on startup. it seems to generate a new file and overwrite then old one with a full list of units again. CPU: i9-12900K @ 4.9Ghz M/B: MSI MEG z690 Ace RAM: 128GB Video Card: MSI RTX 4090 Suprim Liquid X VR: Varjo Aero Link to comment Share on other sites More sharing options...
OzDeaDMeaT Posted September 22, 2020 Share Posted September 22, 2020 OK, I have racked my brain, asked Moose folk and generally given up on such a simple addition to make this script a little more useful (at least for me) Issue: I want to have the script ignore ALL ground vehicle groups with the word 'IGNORE' or 'ignore' or 'Ignore' or any variance of the word ignore in the group name, but save all the other ground units. The script is currently only writing the line below now. SaveUnits = {} Any help would be appreciated as I am completely stuck. Here is the code I have attempted to put in but had no success with. It was originally saving the ignore groups and on reload the ignore groups had no waypoints. Now after i modified line 181 it only saves the following line. -- Simple Group Saving by Pikey May 2019 -- Usage of this script should credit the following contributors: --Pikey, --Speed & Grimes for their work on Serialising tables, included below, --FlightControl for MOOSE (Required) -- Modified by OzDeaDMeaT to add the IGNORE --INTENDED USAGE --DCS Server Admins looking to do long term multi session play that will need a server reboot in between and they wish to keep the Ground --Unit positions true from one reload to the next. --USAGE --Ensure LFS and IO are not santitised in missionScripting.lua. This enables writing of files. If you don't know what this does, don't attempt to use this script. --Requires versions of MOOSE.lua supporting "SET:ForEachGroupAlive()". Should be good for 6 months or more from date of writing. --MIST not required, but should work OK with it regardless. --Edit 'SaveScheduleUnits' below, (line 34) to the number of seconds between saves. Low impact. 10 seconds is a fast schedule. --Place Ground Groups wherever you want on the map as normal. --Run this script at Mission start --The script will create a small file with the list of Groups and Units. --At Mission Start it will check for a save file, if not there, create it fresh --If the table is there, it loads it and Spawns everything that was saved. --The table is updated throughout mission play --The next time the mission is loaded it goes through all the Groups again and loads them from the save file. --LIMITATIONS --Only Ground Groups and Units are specified, play with the SET Filter at your own peril. Could be adjusted for just one Coalition or a FilterByName(). --See line 107 and 168 for the SET. --See https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Set.html##(SET_GROUP) --Naval Groups not Saved. If Included, there may be issues with spawned objects and Client slots where Ships have slots for aircraft/helo. Possible if not a factor --Statics are not included. See 'Simple Static Saving' for a solution --Routes are not saved. Uncomment lines 148-153 if you wish to keep them, but they won't activate them on restart. It is impossible to query a group for it's current --route, only for the original route it recieved from the Mission Editor. Therefore a DCS limitation. ----------------------------------- --Configurable for user: SaveScheduleUnits=30 --how many seconds between each check of all the statics. ----------------------------------- --Do not edit below here ----------------------------------- local version = "1.0" function IntegratedbasicSerialize(s) if s == nil then return "\"\"" else if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then return tostring(s) elseif type(s) == 'string' then return string.format('%q', s) end end end -- imported slmod.serializeWithCycles (Speed) function IntegratedserializeWithCycles(name, value, saved) local basicSerialize = function (o) if type(o) == "number" then return tostring(o) elseif type(o) == "boolean" then return tostring(o) else -- assume it is a string return IntegratedbasicSerialize(o) end end local t_str = {} saved = saved or {} -- initial value if ((type(value) == 'string') or (type(value) == 'number') or (type(value) == 'table') or (type(value) == 'boolean')) then table.insert(t_str, name .. " = ") if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then table.insert(t_str, basicSerialize(value) .. "\n") else if saved[value] then -- value already saved? table.insert(t_str, saved[value] .. "\n") else saved[value] = name -- save name for next time table.insert(t_str, "{}\n") for k,v in pairs(value) do -- save its fields local fieldname = string.format("%s[%s]", name, basicSerialize(k)) table.insert(t_str, IntegratedserializeWithCycles(fieldname, v, saved)) end end end return table.concat(t_str) else return "" end end function file_exists(name) --check if the file already exists for writing if lfs.attributes(name) then return true else return false end end function writemission(data, file)--Function for saving to file (commonly found) File = io.open(file, "w") File:write(data) File:close() end --SCRIPT START env.info("Loaded Simple Group Saving, by Pikey, 2018, version " .. version) if file_exists("TestUnits.lua") then --Script has been run before, so we need to load the save env.info("Existing database, loading from File.") AllGroups = SET_GROUP:New() --Create Moose Group Variable local TempSET = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterOnce() --Creates a Moose Group Variable with all ground units TempSET:ForEachGroup(function (MooseGroup) local GroupsName = MooseGroup:GetName() if string.find(GroupsName, "IGNORE*") == nil then env.info("Group Loaded - " .. GroupsName) AllGroups:Add(MooseGroup) end end) --AllGroups = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterStart() AllGroups:ForEachGroup(function (grp) grp:Destroy() end) dofile("TestUnits.lua") tempTable={} Spawn={} --RUN THROUGH THE KEYS IN THE TABLE (GROUPS) for k,v in pairs (SaveUnits) do units={} --RUN THROUGH THE UNITS IN EACH GROUP for i= 1, #(SaveUnits[k]["units"]) do tempTable = { ["type"]=SaveUnits[k]["units"][i]["type"], ["transportable"]= {["randomTransportable"] = false,}, --["unitId"]=9000,used to generate ID's here but no longer doing that since DCS seems to handle it ["skill"]=SaveUnits[k]["units"][i]["skill"], ["y"]=SaveUnits[k]["units"][i]["y"] , ["x"]=SaveUnits[k]["units"][i]["x"] , ["name"]=SaveUnits[k]["units"][i]["name"], ["heading"]=SaveUnits[k]["units"][i]["heading"], ["playerCanDrive"]=true, --hardcoded but easily changed. } table.insert(units,tempTable) end --end unit for loop groupData = { ["visible"] = true, --["lateActivation"] = false, ["tasks"] = {}, -- end of ["tasks"] ["uncontrollable"] = false, ["task"] = "Ground Nothing", --["taskSelected"] = true, --["route"] = --{ --["spans"] = {}, --["points"]= {} -- },-- end of ["spans"] --["groupId"] = 9000 + _count, ["hidden"] = false, ["units"] = units, ["y"] = SaveUnits[k]["y"], ["x"] = SaveUnits[k]["x"], ["name"] = SaveUnits[k]["name"], --["start_time"] = 0, } coalition.addGroup(SaveUnits[k]["CountryID"], SaveUnits[k]["CategoryID"], groupData) groupData = {} end --end Group for loop else --Save File does not exist we start a fresh table, no spawns needed -- Added by OzDM SaveUnits={} AllGroups = SET_GROUP:New() --Create Moose Group Variable local TempSET = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterOnce() --Creates a Moose Group Variable with all ground units TempSET:ForEachGroup(function (SpecificGroup) local GrpName = SpecificGroup:GetName() if string.find(GrpName, "IGNORE*") == nil then env.info("Group Saved - " .. GrpName) AllGroups:Add(SpecificGroup) end end) -- ORIGINAL -- SaveUnits={} -- AllGroups = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterStart() end --THE SAVING SCHEDULE SCHEDULER:New( nil, function() AllGroups:ForEachGroupAlive(function (grp) local DCSgroup = Group.getByName(grp:GetName() ) local size = DCSgroup:getSize() _unittable={} for i = 1, size do local tmpTable = { ["type"]=grp:GetUnit(i):GetTypeName(), ["transportable"]=true, ["unitID"]=grp:GetUnit(i):GetID(), ["skill"]="Average", ["y"]=grp:GetUnit(i):GetVec2().y, ["x"]=grp:GetUnit(i):GetVec2().x, ["name"]=grp:GetUnit(i):GetName(), ["playerCanDrive"]=true, ["heading"]=grp:GetUnit(i):GetHeading(), } table.insert(_unittable,tmpTable) --add units to a temporary table end SaveUnits[grp:GetName()] = { ["CountryID"]=grp:GetCountry(), ["SpawnCoalitionID"]=grp:GetCountry(), ["tasks"]={}, --grp:GetTaskMission(), --wrong gives the whole thing ["CategoryID"]=grp:GetCategory(), ["task"]="Ground Nothing", ["route"]={}, -- grp:GetTaskRoute(), ["groupId"]=grp:GetID(), --["SpawnCategoryID"]=grp:GetCategory(), ["units"]= _unittable, ["y"]=grp:GetVec2().y, ["x"]=grp:GetVec2().x, ["name"]=grp:GetName(), ["start_time"]=0, ["CoalitionID"]=grp:GetCoalition(), ["SpawnCountryID"]=grp:GetCoalition(), } end) newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, "TestUnits.lua")--write the file from the above to SaveUnits.lua --writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) (FYI I am not a LUA person, just trying to get this most basic of basic feature additions added to this script) CPU: i9-12900K @ 4.9Ghz M/B: MSI MEG z690 Ace RAM: 128GB Video Card: MSI RTX 4090 Suprim Liquid X VR: Varjo Aero Link to comment Share on other sites More sharing options...
fargo007 Posted September 23, 2020 Share Posted September 23, 2020 Here's how I handled it - at restore time, not save time. You cannot fix the route/waypoints issue. Restored groups simply won't have them, or they won't work. Since the route issue in DCS affects this script, I chose to have it ignore any moving vehicles, which I name "convoy..," and are all scheduled spawns anyway (patrolling vehicles, etc). I also added in the functionality for it to recreate any CSAR pickups that are on the map, which are also easily identified by their group name. I also load my script at 25 seconds, not at mission start, so that CSAR exists already. Happy to contribute back if anyone else finds this useful. /[bSD]FargoSGS-Fargo.lua Have fun. Don't suck. Kill bad guys. https://discord.gg/blacksharkden/ Link to comment Share on other sites More sharing options...
OzDeaDMeaT Posted September 24, 2020 Share Posted September 24, 2020 Here's how I handled it - at restore time, not save time. You cannot fix the route/waypoints issue. Restored groups simply won't have them, or they won't work. Since the route issue in DCS affects this script, I chose to have it ignore any moving vehicles, which I name "convoy..," and are all scheduled spawns anyway (patrolling vehicles, etc). I also added in the functionality for it to recreate any CSAR pickups that are on the map, which are also easily identified by their group name. I also load my script at 25 seconds, not at mission start, so that CSAR exists already. Happy to contribute back if anyone else finds this useful. /[bSD]Fargo Thanks for the Script Fargo. With a little help from the from AEF Zyfr and Wingthor from Moose I managed to get it working. I also added a section some variables at the start of the script to help people tweak it for various missions (i.e. the save file name && IgnoreString for groups) -- Simple Group Saving by Pikey May 2019 -- Usage of this script should credit the following contributors: --Pikey, --Speed & Grimes for their work on Serialising tables, included below, --FlightControl for MOOSE (Required) -- Modified by OzDeaDMeaT to add the ability to ignore specific groups defined by the mission maker. --INTENDED USAGE --DCS Server Admins looking to do long term multi session play that will need a server reboot in between and they wish to keep the Ground --Unit positions true from one reload to the next. --USAGE --Ensure LFS and IO are not santitised in missionScripting.lua. This enables writing of files. If you don't know what this does, don't attempt to use this script. --Requires versions of MOOSE.lua supporting "SET:ForEachGroupAlive()". Should be good for 6 months or more from date of writing. --MIST not required, but should work OK with it regardless. --Edit 'SaveScheduleUnits' below, (line 34) to the number of seconds between saves. Low impact. 10 seconds is a fast schedule. --Place Ground Groups wherever you want on the map as normal. --Run this script at Mission start --The script will create a small file with the list of Groups and Units. --At Mission Start it will check for a save file, if not there, create it fresh --If the table is there, it loads it and Spawns everything that was saved. --The table is updated throughout mission play --The next time the mission is loaded it goes through all the Groups again and loads them from the save file. --LIMITATIONS --Only Ground Groups and Units are specified, play with the SET Filter at your own peril. Could be adjusted for just one Coalition or a FilterByName(). --See line 107 and 168 for the SET. --See https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Set.html##(SET_GROUP) --Naval Groups not Saved. If Included, there may be issues with spawned objects and Client slots where Ships have slots for aircraft/helo. Possible if not a factor --Statics are not included. See 'Simple Static Saving' for a solution --Routes are not saved. Uncomment lines 148-153 if you wish to keep them, but they won't activate them on restart. It is impossible to query a group for it's current --route, only for the original route it recieved from the Mission Editor. Therefore a DCS limitation. ----------------------------------- --Configurable for user: SaveScheduleUnits=30 --how many seconds between each check of all the statics. ----------------------------------- --Do not edit below here ----------------------------------- local version = "1.1a" SaveFileName = "TestUnits.lua" --The File you want this script to use when writing out. SrchString = "IGNORE" --This string will be forced lower case when searched as the GroupName searched is also forced to lowercase function IntegratedbasicSerialize(s) if s == nil then return "\"\"" else if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then return tostring(s) elseif type(s) == 'string' then return string.format('%q', s) end end end function IntegratedserializeWithCycles(name, value, saved) -- imported slmod.serializeWithCycles (Speed) local basicSerialize = function (o) if type(o) == "number" then return tostring(o) elseif type(o) == "boolean" then return tostring(o) else -- assume it is a string return IntegratedbasicSerialize(o) end end local t_str = {} saved = saved or {} -- initial value if ((type(value) == 'string') or (type(value) == 'number') or (type(value) == 'table') or (type(value) == 'boolean')) then table.insert(t_str, name .. " = ") if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then table.insert(t_str, basicSerialize(value) .. "\n") else if saved[value] then -- value already saved? table.insert(t_str, saved[value] .. "\n") else saved[value] = name -- save name for next time table.insert(t_str, "{}\n") for k,v in pairs(value) do -- save its fields local fieldname = string.format("%s[%s]", name, basicSerialize(k)) table.insert(t_str, IntegratedserializeWithCycles(fieldname, v, saved)) end end end return table.concat(t_str) else return "" end end function file_exists(name) --check if the file already exists for writing if lfs.attributes(name) then return true else return false end end function writemission(data, file)--Function for saving to file (commonly found) File = io.open(file, "w") File:write(data) File:close() end --SCRIPT START env.info("Loaded Simple Group Saving, by Pikey, 2018, version " .. version) if file_exists(SaveFileName) then --Script has been run before, so we need to load the save env.info("Existing database, loading from File.") AllGroups = SET_GROUP:New() --Create Moose Group Variable local TempSET = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterOnce() --Creates a Moose Group Variable with all ground units TempSET:ForEachGroup(function (MooseGroup) local GroupsName = MooseGroup:GetName() env.info("Checking Group - " .. GroupsName) if string.find(string.lower(GroupsName), string.lower(SrchString)) == nil then env.info("Group Loaded - " .. GroupsName) AllGroups:AddGroup(MooseGroup) end end) --AllGroups = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterStart() AllGroups:ForEachGroup(function (grp) grp:Destroy() end) dofile(SaveFileName) tempTable={} Spawn={} --RUN THROUGH THE KEYS IN THE TABLE (GROUPS) for k,v in pairs (SaveUnits) do units={} --RUN THROUGH THE UNITS IN EACH GROUP for i= 1, #(SaveUnits[k]["units"]) do tempTable = { ["type"]=SaveUnits[k]["units"][i]["type"], ["transportable"]= {["randomTransportable"] = false,}, --["unitId"]=9000,used to generate ID's here but no longer doing that since DCS seems to handle it ["skill"]=SaveUnits[k]["units"][i]["skill"], ["y"]=SaveUnits[k]["units"][i]["y"] , ["x"]=SaveUnits[k]["units"][i]["x"] , ["name"]=SaveUnits[k]["units"][i]["name"], ["heading"]=SaveUnits[k]["units"][i]["heading"], ["playerCanDrive"]=true, --hardcoded but easily changed. } table.insert(units,tempTable) end --end unit for loop groupData = { ["visible"] = true, --["lateActivation"] = false, ["tasks"] = {}, -- end of ["tasks"] ["uncontrollable"] = false, ["task"] = "Ground Nothing", --["taskSelected"] = true, --["route"] = --{ --["spans"] = {}, --["points"]= {} -- },-- end of ["spans"] --["groupId"] = 9000 + _count, ["hidden"] = false, ["units"] = units, ["y"] = SaveUnits[k]["y"], ["x"] = SaveUnits[k]["x"], ["name"] = SaveUnits[k]["name"], --["start_time"] = 0, } coalition.addGroup(SaveUnits[k]["CountryID"], SaveUnits[k]["CategoryID"], groupData) groupData = {} end --end Group for loop else --Save File does not exist we start a fresh table, no spawns needed -- Added by OzDM SaveUnits={} AllGroups = SET_GROUP:New() --Create Moose Group Variable local TempSET = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterOnce() --Creates a Moose Group Variable with all ground units TempSET:ForEachGroup(function (SpecificGroup) local GrpName = SpecificGroup:GetName() if string.find(string.lower(GrpName), string.lower(SrchString)) == nil then env.info("Group Saved - " .. GrpName) AllGroups:AddGroup(SpecificGroup) end end) -- ORIGINAL -- SaveUnits={} -- AllGroups = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterStart() end --THE SAVING SCHEDULE SCHEDULER:New( nil, function() AllGroups:ForEachGroupAlive(function (grp) local DCSgroup = Group.getByName(grp:GetName() ) local size = DCSgroup:getSize() _unittable={} for i = 1, size do local tmpTable = { ["type"]=grp:GetUnit(i):GetTypeName(), ["transportable"]=true, ["unitID"]=grp:GetUnit(i):GetID(), ["skill"]="Average", ["y"]=grp:GetUnit(i):GetVec2().y, ["x"]=grp:GetUnit(i):GetVec2().x, ["name"]=grp:GetUnit(i):GetName(), ["playerCanDrive"]=true, ["heading"]=grp:GetUnit(i):GetHeading(), } table.insert(_unittable,tmpTable) --add units to a temporary table end SaveUnits[grp:GetName()] = { ["CountryID"]=grp:GetCountry(), ["SpawnCoalitionID"]=grp:GetCountry(), ["tasks"]={}, --grp:GetTaskMission(), --wrong gives the whole thing ["CategoryID"]=grp:GetCategory(), ["task"]="Ground Nothing", ["route"]={}, -- grp:GetTaskRoute(), ["groupId"]=grp:GetID(), --["SpawnCategoryID"]=grp:GetCategory(), ["units"]= _unittable, ["y"]=grp:GetVec2().y, ["x"]=grp:GetVec2().x, ["name"]=grp:GetName(), ["start_time"]=0, ["CoalitionID"]=grp:GetCoalition(), ["SpawnCountryID"]=grp:GetCoalition(), } end) newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, SaveFileName)--write the file from the above to SaveUnits.lua --writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) CPU: i9-12900K @ 4.9Ghz M/B: MSI MEG z690 Ace RAM: 128GB Video Card: MSI RTX 4090 Suprim Liquid X VR: Varjo Aero Link to comment Share on other sites More sharing options...
OzDeaDMeaT Posted September 25, 2020 Share Posted September 25, 2020 Thnx to Shadowze and Wingthor from the Moose Discord for the help while I learn LUA. - Added an array of strings to blacklist against the save function - Added Debug to show / hide messages while testing (can be turned off and on) - Added Unit and Group count when saving file - Added Support for scripted units to be saved as well (can be turned off and on) - Bug - Cant delete file when no groups are being saved (thus resetting the persistence). Not sure if this is an issue with DCS or Moose at this point. --[[simple Group Saving by Pikey May 2019 (Updated by OzDeaDMeaT September 2020) Usage of this script should credit the following contributors: Pikey, Speed & Grimes for their work on Serialising tables, included below, FlightControl for MOOSE (Required) -------------------------------------------------------------------------------------- INTENDED USAGE DCS Server Admins looking to do long term multi session play that will need a server reboot in between and they wish to keep the Ground Unit positions true from one reload to the next. -------------------------------------------------------------------------------------- USAGE Ensure LFS and IO are not santitised in missionScripting.lua. This enables writing of files. If you don't know what this does, don't attempt to use this script. Requires versions of MOOSE.lua supporting "SET:ForEachGroupAlive()". Should be good for 6 months or more from date of writing. MIST not required, but should work OK with it regardless. Edit 'SaveScheduleUnits' below, (line 34) to the number of seconds between saves. Low impact. 10 seconds is a fast schedule. Place Ground Groups wherever you want on the map as normal. Run this script at Mission start The script will create a small file with the list of Groups and Units. At Mission Start it will check for a save file, if not there, create it fresh If the table is there, it loads it and Spawns everything that was saved. The table is updated throughout mission play The next time the mission is loaded it goes through all the Groups again and loads them from the save file. -------------------------------------------------------------------------------------- LIMITATIONS Only Ground Groups and Units are specified, play with the SET Filter at your own peril. Could be adjusted for just one Coalition or a FilterByName(). See line 107 and 168 for the SET. See https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Core.Set.html##(SET_GROUP) Naval Groups not Saved. If Included, there may be issues with spawned objects and Client slots where Ships have slots for aircraft/helo. Possible if not a factor Statics are not included. See 'Simple Static Saving' for a solution Routes are not saved. Uncomment lines 148-153 if you wish to keep them, but they won't activate them on restart. It is impossible to query a group for it's current route, only for the original route it recieved from the Mission Editor. Therefore a DCS limitation. ]] ----------------------------------- --Configurable for user: SaveScheduleUnits=30 --how many seconds between each check of all the statics. local version = "1.2c" local SGS_DEBUG = false --Enable if you want verbose debug messages in your log (great for troubleshooting) local ALLOW_DROPIN_GROUPS = false --Enables drop in groups, i.e. groups that are loaded into the game from external scripts rather than Mission Editor added groups. local DELETE_FILE_ON_NO_GROUPS = false --This switch will delete the save file once there is no ground units to safe anymore allowing for automated persistent data reset. SaveFileName = "TestUnits.lua" --The File you want this script to use when writing out. t_SrchStringTable = {"IGNORE","sidemission", "AnotherString"} --This string will be forced lower case when searched as the GroupName searched is also forced to lowercase ----------------------------------- --Do not edit below here ----------------------------------- function IntegratedbasicSerialize(s) if s == nil then return "\"\"" else if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then return tostring(s) elseif type(s) == 'string' then return string.format('%q', s) end end end if SGS_DEBUG == true then env.info("Function: IntegratedbasicSerialize LOADED OK")end function IntegratedserializeWithCycles(name, value, saved) -- imported slmod.serializeWithCycles (Speed) local basicSerialize = function (o) if type(o) == "number" then return tostring(o) elseif type(o) == "boolean" then return tostring(o) else -- assume it is a string return IntegratedbasicSerialize(o) end end local t_str = {} saved = saved or {} -- initial value if ((type(value) == 'string') or (type(value) == 'number') or (type(value) == 'table') or (type(value) == 'boolean')) then table.insert(t_str, name .. " = ") if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then table.insert(t_str, basicSerialize(value) .. "\n") else if saved[value] then -- value already saved? table.insert(t_str, saved[value] .. "\n") else saved[value] = name -- save name for next time table.insert(t_str, "{}\n") for k,v in pairs(value) do -- save its fields local fieldname = string.format("%s[%s]", name, basicSerialize(k)) table.insert(t_str, IntegratedserializeWithCycles(fieldname, v, saved)) end end end return table.concat(t_str) else return "" end end if SGS_DEBUG == true then env.info("Function: IntegratedserializeWithCycles LOADED OK")end function file_exists(name) --check if the file already exists for writing if lfs.attributes(name) then return true else return false end end if SGS_DEBUG == true then env.info("Function: file_exists LOADED OK")end function writemission(data, file)--Function for saving to file (commonly found) File = io.open(file, "w") File:write(data) File:close() end if SGS_DEBUG == true then env.info("Function: writemission LOADED OK")end function GroupStringSearch(t_SrchTbl, GroupName) --returns true if found BASE:F({t_SrchTbl,GroupName}) if type(t_SrchTbl) ~= "table" then env.info("Error: t_SrchTbl is not a table") return nil end if type(GroupName)~="string" then env.info("Error: GroupName is not a string") return nil end for index, str2check in ipairs(t_SrchTbl) do if type(str2check) == "string" then if string.find(string.lower(GroupName), string.lower(str2check)) ~= nil then return true end end end return false end if SGS_DEBUG == true then env.info("Function: GroupStringSearch LOADED OK")end function Generate_GroupSet() --Generates a set of Groups that have been filtered for Blacklisted group names local TempSET = SET_GROUP:New():FilterCategories("ground"):FilterActive(true):FilterOnce() --Creates a Moose Group Variable with all ground units local rtnSET = SET_GROUP:New() TempSET:ForEachGroup(function (MooseGroup) local GroupsName = MooseGroup:GetName() if SGS_DEBUG == true then env.info("Checking Group - " .. GroupsName)end if GroupStringSearch(t_SrchStringTable, GroupsName) == false then if SGS_DEBUG == true then env.info("Group Loaded - " .. GroupsName)end rtnSET:AddGroup(MooseGroup) end end) return rtnSET end if SGS_DEBUG == true then env.info("Function: Generate_GroupSet LOADED OK")end --SCRIPT START env.info("Loaded Simple Group Saving, by Pikey (2018), updated by OzDeaDMeaT (2020), version " .. version) if file_exists(SaveFileName) then --Script has been run before, so we need to load the save if SGS_DEBUG == true then env.info(SaveFileName .. " save file found. Loading now....")end AllGroups = Generate_GroupSet() AllGroups:ForEachGroup(function (grp) grp:Destroy() end) dofile(SaveFileName) tempTable={} Spawn={} --RUN THROUGH THE KEYS IN THE TABLE (GROUPS) for k,v in pairs (SaveUnits) do units={} --RUN THROUGH THE UNITS IN EACH GROUP for i= 1, #(SaveUnits[k]["units"]) do tempTable = { ["type"]=SaveUnits[k]["units"][i]["type"], ["transportable"]= {["randomTransportable"] = false,}, --["unitId"]=9000,used to generate ID's here but no longer doing that since DCS seems to handle it ["skill"]=SaveUnits[k]["units"][i]["skill"], ["y"]=SaveUnits[k]["units"][i]["y"] , ["x"]=SaveUnits[k]["units"][i]["x"] , ["name"]=SaveUnits[k]["units"][i]["name"], ["heading"]=SaveUnits[k]["units"][i]["heading"], ["playerCanDrive"]=true, --hardcoded but easily changed. } table.insert(units,tempTable) end --end unit for loop groupData = { ["visible"] = true, --["lateActivation"] = false, ["tasks"] = {}, -- end of ["tasks"] ["uncontrollable"] = false, ["task"] = "Ground Nothing", --["taskSelected"] = true, --["route"] = --{ --["spans"] = {}, --["points"]= {} -- },-- end of ["spans"] --["groupId"] = 9000 + _count, ["hidden"] = false, ["units"] = units, ["y"] = SaveUnits[k]["y"], ["x"] = SaveUnits[k]["x"], ["name"] = SaveUnits[k]["name"], --["start_time"] = 0, } coalition.addGroup(SaveUnits[k]["CountryID"], SaveUnits[k]["CategoryID"], groupData) groupData = {} end --end Group for loop else --Save File does not exist we start a fresh table, no spawns needed env.info("No File Found, Generating New file with name " .. SaveFileName) -- Added by OzDM SaveUnits={} AllGroups = Generate_GroupSet() end --THE SAVING SCHEDULE SCHEDULER:New( nil, function() env.info("SAVING - Ground Forces...") if ALLOW_DROPIN_GROUPS == true then AllGroups = Generate_GroupSet() end SavedUnitCount = 0 SavedGroupCount = 0 AllGroups:ForEachGroupAlive(function (grp) local DCSgroup = Group.getByName(grp:GetName() ) SavedGroupCount = SavedGroupCount + 1 local size = DCSgroup:getSize() SavedUnitCount = SavedUnitCount + size _unittable={} for i = 1, size do local tmpTable = { ["type"]=grp:GetUnit(i):GetTypeName(), ["transportable"]=true, ["unitID"]=grp:GetUnit(i):GetID(), ["skill"]="Average", ["y"]=grp:GetUnit(i):GetVec2().y, ["x"]=grp:GetUnit(i):GetVec2().x, ["name"]=grp:GetUnit(i):GetName(), ["playerCanDrive"]=true, ["heading"]=grp:GetUnit(i):GetHeading(), } table.insert(_unittable,tmpTable) --add units to a temporary table end SaveUnits[grp:GetName()] = { ["CountryID"]=grp:GetCountry(), ["SpawnCoalitionID"]=grp:GetCountry(), ["tasks"]={}, --grp:GetTaskMission(), --wrong gives the whole thing ["CategoryID"]=grp:GetCategory(), ["task"]="Ground Nothing", ["route"]={}, -- grp:GetTaskRoute(), ["groupId"]=grp:GetID(), --["SpawnCategoryID"]=grp:GetCategory(), ["units"]= _unittable, ["y"]=grp:GetVec2().y, ["x"]=grp:GetVec2().x, ["name"]=grp:GetName(), ["start_time"]=0, ["CoalitionID"]=grp:GetCoalition(), ["SpawnCountryID"]=grp:GetCoalition(), } end) if (SavedGroupCount > 0) then newMissionStr = IntegratedserializeWithCycles("SaveUnits",SaveUnits) --save the Table as a serialised type with key SaveUnits writemission(newMissionStr, SaveFileName)--write the file from the above to SaveUnits.lua env.info("SAVED - " .. SavedUnitCount .. " units in " .. SavedGroupCount .." groups have been successfully saved to ".. SaveFileName) else if (file_exists(SaveFileName) and DELETE_FILE_ON_NO_GROUPS == true) then env.info("DELETING - " .. SaveFileName) --io.remove (SaveFileName) seems to not work, not sure why. else env.info("SAVE EMPTY - " .. SaveFileName) end end --writemission(newMissionStr, "SaveUnits.lua")--write the file from the above to SaveUnits.lua SaveUnits={}--clear the table for a new write. --env.info("Data saved.") end, {}, 1, SaveScheduleUnits) CPU: i9-12900K @ 4.9Ghz M/B: MSI MEG z690 Ace RAM: 128GB Video Card: MSI RTX 4090 Suprim Liquid X VR: Varjo Aero Link to comment Share on other sites More sharing options...
Chandawg Posted October 13, 2020 Share Posted October 13, 2020 (edited) CTLD Has anyone been able to write the units back into CTLD to make it compatible? Edited October 13, 2020 by Chandawg 1 | CyperPower PC | AMD Ryzen 7 3700X @ 4.4 GHz | 64Gb DDR4 3200 MHz | Radeon RX 5700 8Gb | 32" Samsung Curve| Oculus Rift S | Thrustmaster T160000 HOTAS + Rudder Pedals | Windows 10-64 | Link to comment Share on other sites More sharing options...
Falcon_S Posted October 24, 2020 Share Posted October 24, 2020 @Pikey Hello, thanks for this script. I have question: How it will work with two missions that using saving script? Different units, diff locations, diff qty of units etc... So, first mission have SavedUnits.lua but what will happens if we stop current and load second mission? Will second mission script load units from first mission or will create new SavedUnits.lua (old will be deleted?). How to deal with that? Can SavedUnits.lua be renamed and be loaded only for specific mission or what...? Thanks. Quote Немој ништа силом, узми већи чекић! MSI Tomahawk MAX | Ryzen 7 3700x | 32GB DDR4 3200MHz | RX 5700 XT OC Red Dragon 8GB | VPC Throttle CM3 + VPC Constellation ALPHA on VPC WarBRD Base | HP Reverb G2 Youtube | Follow Me on TWITCH! Link to comment Share on other sites More sharing options...
Falcon_S Posted October 25, 2020 Share Posted October 25, 2020 Anyone? Quote Немој ништа силом, узми већи чекић! MSI Tomahawk MAX | Ryzen 7 3700x | 32GB DDR4 3200MHz | RX 5700 XT OC Red Dragon 8GB | VPC Throttle CM3 + VPC Constellation ALPHA on VPC WarBRD Base | HP Reverb G2 Youtube | Follow Me on TWITCH! Link to comment Share on other sites More sharing options...
Guile Posted November 4, 2020 Share Posted November 4, 2020 @Pikey Hello, thanks for this script. I have question: How it will work with two missions that using saving script? Different units, diff locations, diff qty of units etc... So, first mission have SavedUnits.lua but what will happens if we stop current and load second mission? Will second mission script load units from first mission or will create new SavedUnits.lua (old will be deleted?). How to deal with that? Can SavedUnits.lua be renamed and be loaded only for specific mission or what...? Thanks. Open the SGS.lua and edit lines 106,113 and 220 where it says "SaveUnits.lua" change it to "SaveUnitsMission1.lua". Then rename this SGS.lua file to SGSMission1.lua, save it, reload it in the mission editor and that should work. Do that for every different mission you want to run. 1 ▀▄▀▄▀▄ DCS: Air Assault Operations ▄▀▄▀▄▀ Join the fight! YouTube Channel Link to comment Share on other sites More sharing options...
Falcon_S Posted November 4, 2020 Share Posted November 4, 2020 Thanks @Guile ! Quote Немој ништа силом, узми већи чекић! MSI Tomahawk MAX | Ryzen 7 3700x | 32GB DDR4 3200MHz | RX 5700 XT OC Red Dragon 8GB | VPC Throttle CM3 + VPC Constellation ALPHA on VPC WarBRD Base | HP Reverb G2 Youtube | Follow Me on TWITCH! Link to comment Share on other sites More sharing options...
Hellfire Posted March 5, 2022 Share Posted March 5, 2022 Is it possible to save the SaveUnits.lua to Save Game folder instead of main DCS folder? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now