mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 1.1.2
More persistence
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
unitPersistence = {}
|
||||
unitPersistence.version = '1.0.1'
|
||||
unitPersistence.version = '1.1.1'
|
||||
unitPersistence.verbose = false
|
||||
unitPersistence.updateTime = 60 -- seconds. Once every minute check statics
|
||||
unitPersistence.requiredLibs = {
|
||||
@@ -15,6 +15,11 @@ unitPersistence.requiredLibs = {
|
||||
- handles linked static objects
|
||||
- does no longer mess with heliports
|
||||
- update statics once a minute, not second
|
||||
1.0.2 - fixes coalition bug for static objects
|
||||
1.1.0 - added air and sea units - for filtering destroyed units
|
||||
1.1.1 - fixed static link (again)
|
||||
- fixed air spawn (fixed wing)
|
||||
|
||||
|
||||
REQUIRES PERSISTENCE AND MX
|
||||
|
||||
@@ -23,6 +28,10 @@ unitPersistence.requiredLibs = {
|
||||
--]]--
|
||||
unitPersistence.groundTroops = {} -- local buffered copy that we
|
||||
-- maintain from save to save
|
||||
unitPersistence.fixedWing = {}
|
||||
unitPersistence.rotorWing = {}
|
||||
unitPersistence.ships = {}
|
||||
|
||||
unitPersistence.statics = {} -- locally unpacked and buffered static objects
|
||||
|
||||
--
|
||||
@@ -49,18 +58,24 @@ function unitPersistence.saveData()
|
||||
local uName = theUnitData.name
|
||||
local gUnit = Unit.getByName(uName)
|
||||
if gUnit and gUnit:isExist() then
|
||||
-- got a live one!
|
||||
gotALiveOne = true
|
||||
-- update x and y and heading
|
||||
theUnitData.heading = dcsCommon.getUnitHeading(gUnit)
|
||||
pos = gUnit:getPoint()
|
||||
theUnitData.x = pos.x
|
||||
theUnitData.y = pos.z -- (!!)
|
||||
-- ground units do not use alt
|
||||
if gUnit:isActive() then
|
||||
theUnitData.isDead = gUnit:getLife() < 1
|
||||
if not theUnitData.isDead then
|
||||
-- got a live one!
|
||||
gotALiveOne = true
|
||||
-- update x, y and heading
|
||||
theUnitData.heading = dcsCommon.getUnitHeading(gUnit)
|
||||
pos = gUnit:getPoint()
|
||||
theUnitData.x = pos.x
|
||||
theUnitData.y = pos.z -- (!!)
|
||||
end
|
||||
else
|
||||
gotALiveOne = true -- not yet activated
|
||||
end
|
||||
else
|
||||
theUnitData.isDead = true
|
||||
end -- is alive and exists?
|
||||
end -- unit not dead
|
||||
end -- unit maybe not dead
|
||||
end -- iterate units in group
|
||||
groupData.isDead = not gotALiveOne
|
||||
end -- if group is not dead
|
||||
@@ -69,6 +84,136 @@ function unitPersistence.saveData()
|
||||
end
|
||||
end
|
||||
|
||||
-- aircraft
|
||||
for groupName, groupData in pairs(unitPersistence.fixedWing) do
|
||||
-- we update this record live and save it to file
|
||||
if not groupData.isDead then
|
||||
local gotALiveOne = false
|
||||
local allUnits = groupData.units
|
||||
for idx, theUnitData in pairs(allUnits) do
|
||||
if not theUnitData.isDead then
|
||||
local uName = theUnitData.name
|
||||
local gUnit = Unit.getByName(uName)
|
||||
if gUnit and gUnit:isExist() then
|
||||
-- update x and y and heading if active and alive
|
||||
if gUnit:isActive() then -- only overwrite if active
|
||||
theUnitData.isDead = gUnit:getLife() < 1
|
||||
if not theUnitData.isDead then
|
||||
gotALiveOne = true -- this group is still alive
|
||||
theUnitData.heading = dcsCommon.getUnitHeading(gUnit)
|
||||
pos = gUnit:getPoint()
|
||||
theUnitData.x = pos.x
|
||||
theUnitData.y = pos.z -- (!!)
|
||||
theUnitData.alt = pos.y
|
||||
theUnitData.alt_type = "BARO"
|
||||
theUnitData.speed = dcsCommon.vMag(gUnit:getVelocity())
|
||||
-- we now could get fancy and do some proccing of the
|
||||
-- waypoints and make the one it's nearest to its
|
||||
-- current waypoint, curtailing all others, but that
|
||||
-- may easily mess with waypoint actions, so we don't
|
||||
end
|
||||
else
|
||||
gotALiveOne = true -- has not yet been activated, live
|
||||
end
|
||||
else
|
||||
theUnitData.isDead = true
|
||||
-- trigger.action.outText("+++unitPersistence - unit <" .. uName .. "> of group <" .. groupName .. "> is dead or non-existant", 30)
|
||||
end -- is alive and exists?
|
||||
end -- unit maybe not dead
|
||||
end -- iterate units in group
|
||||
groupData.isDead = not gotALiveOne
|
||||
end -- if group is not dead
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("unitPersistence: save - processed air group <" .. groupName .. ">.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
-- helos
|
||||
for groupName, groupData in pairs(unitPersistence.rotorWing) do
|
||||
-- we update this record live and save it to file
|
||||
if not groupData.isDead then
|
||||
local gotALiveOne = false
|
||||
local allUnits = groupData.units
|
||||
for idx, theUnitData in pairs(allUnits) do
|
||||
if not theUnitData.isDead then
|
||||
local uName = theUnitData.name
|
||||
local gUnit = Unit.getByName(uName)
|
||||
if gUnit and gUnit:isExist() then
|
||||
-- update x and y and heading if active and alive
|
||||
if gUnit:isActive() then -- only overwrite if active
|
||||
theUnitData.isDead = gUnit:getLife() < 1
|
||||
if not theUnitData.isDead then
|
||||
gotALiveOne = true -- this group is still alive
|
||||
theUnitData.heading = dcsCommon.getUnitHeading(gUnit)
|
||||
pos = gUnit:getPoint()
|
||||
theUnitData.x = pos.x
|
||||
theUnitData.y = pos.z -- (!!)
|
||||
theUnitData.alt = pos.y
|
||||
theUnitData.alt_type = "BARO"
|
||||
theUnitData.speed = dcsCommon.vMag(gUnit:getVelocity())
|
||||
-- we now could get fancy and do some proccing of the
|
||||
-- waypoints and make the one it's nearest to its
|
||||
-- current waypoint, curtailing all others, but that
|
||||
-- may easily mess with waypoint actions, so we don't
|
||||
end
|
||||
else
|
||||
gotALiveOne = true -- has not yet been activated, live
|
||||
end
|
||||
else
|
||||
theUnitData.isDead = true
|
||||
trigger.action.outText("+++unitPersistence - unit <" .. uName .. "> of group <" .. groupName .. "> is dead or non-existant", 30)
|
||||
end -- is alive and exists?
|
||||
end -- unit maybe not dead
|
||||
end -- iterate units in group
|
||||
groupData.isDead = not gotALiveOne
|
||||
end -- if group is not dead
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("unitPersistence: save - processed helo group <" .. groupName .. ">.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
-- ships
|
||||
for groupName, groupData in pairs(unitPersistence.ships) do
|
||||
-- we update this record live and save it to file
|
||||
if not groupData.isDead then
|
||||
local gotALiveOne = false
|
||||
local allUnits = groupData.units
|
||||
for idx, theUnitData in pairs(allUnits) do
|
||||
if not theUnitData.isDead then
|
||||
local uName = theUnitData.name
|
||||
local gUnit = Unit.getByName(uName)
|
||||
if gUnit and gUnit:isExist() then
|
||||
-- update x and y and heading if active and alive
|
||||
if gUnit:isActive() then -- only overwrite if active
|
||||
theUnitData.isDead = gUnit:getLife() < 1
|
||||
if not theUnitData.isDead then
|
||||
gotALiveOne = true -- this group is still alive
|
||||
theUnitData.heading = dcsCommon.getUnitHeading(gUnit)
|
||||
pos = gUnit:getPoint()
|
||||
theUnitData.x = pos.x
|
||||
theUnitData.y = pos.z -- (!!)
|
||||
-- we only filter dead ships and don't mess with others
|
||||
-- during load, so we are doing this solely for possible
|
||||
-- later expansions
|
||||
end
|
||||
else
|
||||
gotALiveOne = true -- has not yet been activated, live
|
||||
end
|
||||
else
|
||||
theUnitData.isDead = true
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence - unit <" .. uName .. "> of group <" .. groupName .. "> is dead or non-existant", 30)
|
||||
end
|
||||
end -- is alive and exists?
|
||||
end -- unit maybe not dead
|
||||
end -- iterate units in group
|
||||
groupData.isDead = not gotALiveOne
|
||||
end -- if group is not dead
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("unitPersistence: save - processed ship group <" .. groupName .. ">.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
-- process all static objects placed with ME
|
||||
for oName, oData in pairs(unitPersistence.statics) do
|
||||
if not oData.isDead or oData.lateActivation then
|
||||
@@ -96,6 +241,10 @@ function unitPersistence.saveData()
|
||||
|
||||
theData.version = unitPersistence.version
|
||||
theData.ground = unitPersistence.groundTroops
|
||||
theData.fixedWing = unitPersistence.fixedWing
|
||||
theData.rotorWing = unitPersistence.rotorWing
|
||||
theData.ships = unitPersistence.ships
|
||||
|
||||
theData.statics = unitPersistence.statics
|
||||
return theData
|
||||
end
|
||||
@@ -103,6 +252,13 @@ end
|
||||
--
|
||||
-- Load Mission Data
|
||||
--
|
||||
function unitPersistence.delayedSpawn(args)
|
||||
local cat = args.cat
|
||||
local cty = args.cty
|
||||
local newGroup = args.newGroup
|
||||
local theGroup = coalition.addGroup(cty, cat, newGroup)
|
||||
end
|
||||
|
||||
function unitPersistence.loadMission()
|
||||
local theData = persistence.getSavedDataForModule("unitPersistence")
|
||||
if not theData then
|
||||
@@ -137,7 +293,6 @@ function unitPersistence.loadMission()
|
||||
-- filter all dead groups
|
||||
if theUnitData.isDead then
|
||||
-- skip it
|
||||
|
||||
else
|
||||
-- add it to new group
|
||||
table.insert(newUnits, theUnitData)
|
||||
@@ -145,29 +300,129 @@ function unitPersistence.loadMission()
|
||||
end
|
||||
-- replace old unit setup with new
|
||||
newGroup.units = newUnits
|
||||
|
||||
local cty = groupData.cty
|
||||
local cat = groupData.cat
|
||||
|
||||
-- destroy the old group
|
||||
--theGroup:destroy() -- will be replaced
|
||||
|
||||
-- spawn new one
|
||||
|
||||
-- spawn new one, replaces old one
|
||||
theGroup = coalition.addGroup(cty, cat, newGroup)
|
||||
if not theGroup then
|
||||
trigger.action.outText("+++ failed to add modified group <" .. groupName .. ">")
|
||||
end
|
||||
if unitPersistence.verbose then
|
||||
-- trigger.action.outText("+++unitPersistence: updated group <" .. groupName .. "> of cat <" .. cat .. "> for cty <" .. cty .. ">", 30)
|
||||
trigger.action.outText("+++ failed to add modified group <" .. groupName .. ">", 30)
|
||||
end
|
||||
end
|
||||
end
|
||||
unitPersistence.groundTroops = theData.ground
|
||||
else
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: no ground unit data.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
if theData.fixedWing then
|
||||
for groupName, groupData in pairs(theData.fixedWing) do
|
||||
--trigger.action.outText("+++ start loading group <" .. groupName .. ">", 30)
|
||||
local theGroup = Group.getByName(groupName)
|
||||
if not theGroup then
|
||||
mismatchWarning = true
|
||||
elseif groupData.isDead then
|
||||
theGroup:destroy()
|
||||
elseif groupData.isPlayer then
|
||||
-- skip it
|
||||
else
|
||||
local newGroup = dcsCommon.clone(groupData)
|
||||
local newUnits = {}
|
||||
for idx, theUnitData in pairs(groupData.units) do
|
||||
-- filter all dead groups
|
||||
if theUnitData.isDead then
|
||||
-- skip it
|
||||
else
|
||||
-- add it to new group
|
||||
table.insert(newUnits, theUnitData)
|
||||
end
|
||||
end
|
||||
-- replace old unit setup with (delayed) new
|
||||
newGroup.units = newUnits
|
||||
local cty = groupData.cty
|
||||
local cat = groupData.cat
|
||||
|
||||
-- spawn new one, replaces old one
|
||||
theGroup:destroy()
|
||||
local args = {}
|
||||
args.cty = cty
|
||||
args.cat = cat
|
||||
args.newGroup = newGroup
|
||||
-- since DCS can't replace a group directly (none will appear), we introduce a brief interval for things to settle
|
||||
timer.scheduleFunction(unitPersistence.delayedSpawn, args, timer.getTime()+0.5)
|
||||
|
||||
end
|
||||
end
|
||||
unitPersistence.fixedWing = theData.fixedWing
|
||||
else
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: no aircraft (fixed wing) unit data.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
if theData.rotorWing then
|
||||
for groupName, groupData in pairs(theData.rotorWing) do
|
||||
local theGroup = Group.getByName(groupName)
|
||||
if not theGroup then
|
||||
mismatchWarning = true
|
||||
elseif groupData.isDead then
|
||||
theGroup:destroy()
|
||||
elseif groupData.isPlayer then
|
||||
-- skip it
|
||||
else
|
||||
local newGroup = dcsCommon.clone(groupData)
|
||||
local newUnits = {}
|
||||
for idx, theUnitData in pairs(groupData.units) do
|
||||
-- filter all dead groups
|
||||
if theUnitData.isDead then
|
||||
-- skip it
|
||||
else
|
||||
-- add it to new group
|
||||
table.insert(newUnits, theUnitData)
|
||||
end
|
||||
end
|
||||
-- replace old unit setup with new
|
||||
newGroup.units = newUnits
|
||||
local cty = groupData.cty
|
||||
local cat = groupData.cat
|
||||
|
||||
-- spawn new one, replaces old one
|
||||
theGroup = coalition.addGroup(cty, cat, newGroup)
|
||||
if not theGroup then
|
||||
trigger.action.outText("+++ failed to add modified group <" .. groupName .. ">", 30)
|
||||
end
|
||||
end
|
||||
end
|
||||
unitPersistence.rotorWing = theData.rotorWing
|
||||
else
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: no rotor wing unit data.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
if theData.ships then
|
||||
for groupName, groupData in pairs(theData.ships) do
|
||||
local theGroup = Group.getByName(groupName)
|
||||
if not theGroup then
|
||||
mismatchWarning = true
|
||||
elseif groupData.isDead then
|
||||
-- when entire group is destroyed, we will also
|
||||
-- destroy group. Else all survive
|
||||
-- we currently don't dick around with carrieres unless they are dead
|
||||
theGroup:destroy()
|
||||
else
|
||||
-- do nothing
|
||||
end
|
||||
end
|
||||
unitPersistence.ships = theData.ships
|
||||
else
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: no rotor wing unit data.", 30)
|
||||
end
|
||||
end
|
||||
|
||||
-- and now the same for static objects
|
||||
if theData.statics then
|
||||
for name, staticData in pairs(theData.statics) do
|
||||
@@ -177,8 +432,6 @@ function unitPersistence.loadMission()
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: static <" .. name .. "> is late activate, no update", 30)
|
||||
end
|
||||
--elseif not theStatic then
|
||||
-- mismatchWarning = true
|
||||
elseif staticData.category == "Heliports" then
|
||||
-- FARPS are static objects that HATE to be
|
||||
-- messed with, so we don't
|
||||
@@ -188,7 +441,7 @@ function unitPersistence.loadMission()
|
||||
else
|
||||
local newStatic = dcsCommon.clone(staticData)
|
||||
-- add link info if it exists
|
||||
newStatic.linkUnit = cfxMX.linkByName[name]
|
||||
newStatic.linkUnit = cfxMX.linkByName[staticData.groupName]
|
||||
if newStatic.linkUnit and unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: linked static <" .. name .. "> to unit <" .. newStatic.linkUnit .. ">", 30)
|
||||
end
|
||||
@@ -197,15 +450,16 @@ function unitPersistence.loadMission()
|
||||
-- spawn new one, replacing same.named old, dead if required
|
||||
gStatic = coalition.addStaticObject(cty, newStatic)
|
||||
if not gStatic then
|
||||
trigger.action.outText("+++ failed to add modified static <" .. name .. ">")
|
||||
trigger.action.outText("+++ failed to add modified static <" .. name .. ">", 30)
|
||||
end
|
||||
if unitPersistence.verbose then
|
||||
local note = ""
|
||||
if newStatic.dead then note = " (dead)" end
|
||||
-- trigger.action.outText("+++unitPersistence: updated static <" .. name .. "> for cty <" .. cty .. ">" .. note, 30)
|
||||
trigger.action.outText("+++unitPersistence: updated static <" .. name .. "> for cty <" .. cty .. ">" .. note, 30)
|
||||
end
|
||||
end
|
||||
end
|
||||
unitPersistence.statics = theData.statics
|
||||
end
|
||||
|
||||
if mismatchWarning then
|
||||
@@ -268,6 +522,7 @@ function unitPersistence.start()
|
||||
-- create a local copy of the entire groundForces data that
|
||||
-- we maintain internally. It's fixed, and we work on our
|
||||
-- own copy for speed
|
||||
unitPersistence.groundTroops = {}
|
||||
for gname, data in pairs(cfxMX.allGroundByName) do
|
||||
local gd = dcsCommon.clone(data) -- copy the record
|
||||
gd.isDead = false -- init new field to alive
|
||||
@@ -275,14 +530,71 @@ function unitPersistence.start()
|
||||
gd.cat = cfxMX.catText2ID("vehicle")
|
||||
local gGroup = Group.getByName(gname)
|
||||
if not gGroup then
|
||||
trigger.action.outText("+++warning: group <" .. gname .. "> does not exist in-game!?", 30)
|
||||
trigger.action.outText("+++warning: ground group <" .. gname .. "> does not exist in-game!?", 30)
|
||||
else
|
||||
local firstUnit = gGroup:getUnit(1)
|
||||
gd.cty = firstUnit:getCountry()
|
||||
gd.cty = cfxMX.countryByName[gname]
|
||||
unitPersistence.groundTroops[gname] = gd
|
||||
end
|
||||
end
|
||||
|
||||
-- now add all aircraft
|
||||
unitPersistence.fixedWing = {}
|
||||
for gname, data in pairs(cfxMX.allFixedByName) do
|
||||
local gd = dcsCommon.clone(data) -- copy the record
|
||||
gd.isDead = false -- init new field to alive
|
||||
gd.isPlayer = (cfxMX.playerGroupByName[gname] ~= nil)
|
||||
-- coalition and country
|
||||
gd.cat = cfxMX.catText2ID("plane") -- 0
|
||||
gd.cty = cfxMX.countryByName[gname]
|
||||
local gGroup = Group.getByName(gname)
|
||||
if gd.isPlayer then
|
||||
-- skip
|
||||
elseif not gGroup then
|
||||
trigger.action.outText("+++warning: fixed-wing group <" .. gname .. "> does not exist in-game!?", 30)
|
||||
else
|
||||
unitPersistence.fixedWing[gname] = gd
|
||||
end
|
||||
end
|
||||
|
||||
-- and helicopters
|
||||
unitPersistence.rotorWing = {}
|
||||
for gname, data in pairs(cfxMX.allHeloByName) do
|
||||
local gd = dcsCommon.clone(data) -- copy the record
|
||||
gd.isDead = false -- init new field to alive
|
||||
gd.isPlayer = (cfxMX.playerGroupByName[gname] ~= nil)
|
||||
-- coalition and country
|
||||
gd.cat = cfxMX.catText2ID("helicopter") -- 1
|
||||
gd.cty = cfxMX.countryByName[gname]
|
||||
local gGroup = Group.getByName(gname)
|
||||
if gd.isPlayer then
|
||||
-- skip
|
||||
elseif not gGroup then
|
||||
trigger.action.outText("+++warning: helo group <" .. gname .. "> does not exist in-game!?", 30)
|
||||
else
|
||||
unitPersistence.rotorWing[gname] = gd
|
||||
end
|
||||
end
|
||||
|
||||
-- finally ships
|
||||
-- we only do ships to remove them when they are dead because
|
||||
-- messing with ships can give problems: aircraft carriers.
|
||||
unitPersistence.ships = {}
|
||||
for gname, data in pairs(cfxMX.allSeaByName) do
|
||||
local gd = dcsCommon.clone(data) -- copy the record
|
||||
gd.isDead = false -- init new field to alive
|
||||
-- coalition and country
|
||||
gd.cat = cfxMX.catText2ID("ship") -- 3
|
||||
gd.cty = cfxMX.countryByName[gname]
|
||||
local gGroup = Group.getByName(gname)
|
||||
if gd.isPlayer then
|
||||
-- skip
|
||||
elseif not gGroup then
|
||||
trigger.action.outText("+++warning: ship group <" .. gname .. "> does not exist in-game!?", 30)
|
||||
else
|
||||
unitPersistence.ships[gname] = gd
|
||||
end
|
||||
end
|
||||
|
||||
-- make local copies of all static MX objects
|
||||
-- that we also maintain internally, and convert them to game
|
||||
-- spawnable objects
|
||||
@@ -294,19 +606,18 @@ function unitPersistence.start()
|
||||
local theStatic = dcsCommon.clone(staticData)
|
||||
theStatic.isDead = false
|
||||
theStatic.groupId = mxData.groupId
|
||||
theStatic.groupName = name -- save top-level name
|
||||
theStatic.cat = cfxMX.catText2ID("static")
|
||||
theStatic.cty = cfxMX.countryByName[name]
|
||||
--trigger.action.outText("Processed MX static group <" .. name .. ">, object <" .. name .. "> with cty <" .. theStatic.cty .. ">",30)
|
||||
local gameOb = StaticObject.getByName(theStatic.name)
|
||||
if not gameOb then
|
||||
if unitPersistence.verbose then
|
||||
trigger.action.outText("+++unitPersistence: static object <" .. theStatic.name .. "> has late activation", 30)
|
||||
end
|
||||
theStatic.lateActivation = true
|
||||
else
|
||||
--theStatic.cty = gameOb:getCountry()
|
||||
--unitPersistence.statics[theStatic.name] = theStatic
|
||||
end
|
||||
unitPersistence.statics[theStatic.name] = theStatic
|
||||
unitPersistence.statics[theStatic.name] = theStatic -- HERE WE CHANGE FROM GROUP NAME TO STATIC NAME!!!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -328,6 +639,11 @@ if not unitPersistence.start() then
|
||||
unitPersistence = nil
|
||||
end
|
||||
--[[--
|
||||
ToDo: linked statics and linked units on restore
|
||||
- waypoint analysis for aircraft so
|
||||
- whan they have take off as Inital WP and they are moving
|
||||
then we change the first WP to 'turning point'
|
||||
- waypoint analysis to match waypoint to position. very difficult if waypoints describe a circle.
|
||||
- group analysis for carriers to be able to process groups that do
|
||||
not contain carriers
|
||||
|
||||
--]]--
|
||||
|
||||
Reference in New Issue
Block a user