mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 2.1.0
Shared Persistence, Stop Gap
This commit is contained in:
parent
a44f145218
commit
6088c4cfa1
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
bombRange = {}
|
bombRange = {}
|
||||||
bombRange.version = "1.1.0"
|
bombRange.version = "1.1.1"
|
||||||
bombRange.dh = 1 -- meters above ground level burst
|
bombRange.dh = 1 -- meters above ground level burst
|
||||||
|
|
||||||
bombRange.requiredLibs = {
|
bombRange.requiredLibs = {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cargoSuper = {}
|
cargoSuper = {}
|
||||||
cargoSuper.version = "1.1.1"
|
cargoSuper.version = "1.1.2"
|
||||||
--[[--
|
--[[--
|
||||||
version history
|
version history
|
||||||
1.0.0 - initial version
|
1.0.0 - initial version
|
||||||
@ -14,6 +14,8 @@ version history
|
|||||||
- getManifestForCategory alias for getManifestFor
|
- getManifestForCategory alias for getManifestFor
|
||||||
- removeAllMassFor()
|
- removeAllMassFor()
|
||||||
1.1.1 - deleteMassObject corrected index bug
|
1.1.1 - deleteMassObject corrected index bug
|
||||||
|
1.1.2 - removed a typo that did not reset mass correctly
|
||||||
|
in removeAllMassForCargo
|
||||||
|
|
||||||
CargoSuper manages weigth for a logical named unit. Weight can be added
|
CargoSuper manages weigth for a logical named unit. Weight can be added
|
||||||
to arbitrary categories like 'passengers', 'cargo' or "whatever". In order
|
to arbitrary categories like 'passengers', 'cargo' or "whatever". In order
|
||||||
@ -102,14 +104,14 @@ function cargoSuper.removeMassObjectFrom(name, category, theMassObject, forget)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- DO NOT PUBLISH. Provided only for backwards compatibility
|
-- DO NOT PUBLISH. Provided only for backwards compatibility
|
||||||
function cargoSuper.removeAllMassForCargo(name, catergory)
|
function cargoSuper.removeAllMassForCargo(name, category)
|
||||||
if not category then category = "cSup!DefCat" end
|
if not category then category = "cSup!DefCat" end
|
||||||
nameStats.reset(name, category, cargoSuper.cargos)
|
nameStats.reset(name, category, cargoSuper.cargos)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- alias for removeAllMassForCargo
|
-- alias for removeAllMassForCargo
|
||||||
function cargoSuper.removeAllMassForCategory(name, catergory)
|
function cargoSuper.removeAllMassForCategory(name, category)
|
||||||
cargoSuper.removeAllMassForCargo(name, catergory)
|
cargoSuper.removeAllMassForCargo(name, category)
|
||||||
end
|
end
|
||||||
|
|
||||||
function cargoSuper.removeAllMassFor(name)
|
function cargoSuper.removeAllMassFor(name)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
csarManager = {}
|
csarManager = {}
|
||||||
csarManager.version = "3.2.0"
|
csarManager.version = "3.2.2"
|
||||||
csarManager.ups = 1
|
csarManager.ups = 1
|
||||||
|
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
@ -32,6 +32,12 @@ csarManager.ups = 1
|
|||||||
- 3.2.0 - inPopulated csar option
|
- 3.2.0 - inPopulated csar option
|
||||||
- clearance csar attribute
|
- clearance csar attribute
|
||||||
- maxTries csar attribute
|
- maxTries csar attribute
|
||||||
|
- 3.2.1 - comsRange attribute when mission times out
|
||||||
|
- rescueTypes option in config
|
||||||
|
3.2.2 - reset helicopter weight on birth
|
||||||
|
- cleanup
|
||||||
|
3.2.3 - hardening against *accidental* multi-unit player groups.
|
||||||
|
|
||||||
|
|
||||||
INTEGRATES AUTOMATICALLY WITH playerScore
|
INTEGRATES AUTOMATICALLY WITH playerScore
|
||||||
INTEGRATES WITH LIMITED AIRFRAMES
|
INTEGRATES WITH LIMITED AIRFRAMES
|
||||||
@ -102,8 +108,11 @@ function csarManager.createDownedPilot(theMission, existingUnit)
|
|||||||
aHeading = math.random(360)/360 * 2 * 3.1415
|
aHeading = math.random(360)/360 * 2 * 3.1415
|
||||||
end
|
end
|
||||||
theMission.locations = {}
|
theMission.locations = {}
|
||||||
|
-- get a typeName for the unit to create from my list of
|
||||||
|
-- types
|
||||||
|
local rType = dcsCommon.pickRandom(csarManager.rescueTypes)
|
||||||
local theBoyGroup = dcsCommon.createSingleUnitGroup(theMission.name,
|
local theBoyGroup = dcsCommon.createSingleUnitGroup(theMission.name,
|
||||||
"Soldier M4 GRG", -- "Soldier M4 GRG",
|
rType, -- "Soldier M4 GRG",
|
||||||
aLocation.x,
|
aLocation.x,
|
||||||
aLocation.z,
|
aLocation.z,
|
||||||
-aHeading + 1.5) -- + 1.5 to turn inwards
|
-aHeading + 1.5) -- + 1.5 to turn inwards
|
||||||
@ -181,7 +190,6 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew,
|
|||||||
-- set timeLimit if enabled
|
-- set timeLimit if enabled
|
||||||
if timeLimit then
|
if timeLimit then
|
||||||
local theLimit = cfxZones.randomDelayFromPositiveRange(timeLimit[1], timeLimit[2]) * 60
|
local theLimit = cfxZones.randomDelayFromPositiveRange(timeLimit[1], timeLimit[2]) * 60
|
||||||
-- trigger.action.outText("set time limit for mission to "..theLimit, 30)
|
|
||||||
newMission.expires = timer.getTime() + theLimit
|
newMission.expires = timer.getTime() + theLimit
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -192,7 +200,6 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew,
|
|||||||
end
|
end
|
||||||
|
|
||||||
function csarManager.addMission(theMission)
|
function csarManager.addMission(theMission)
|
||||||
-- trigger.action.outText("enter addMission", 30)
|
|
||||||
table.insert(csarManager.openMissions, theMission)
|
table.insert(csarManager.openMissions, theMission)
|
||||||
csarManager.invokeNewMissionCallbacks(theMission)
|
csarManager.invokeNewMissionCallbacks(theMission)
|
||||||
end
|
end
|
||||||
@ -318,9 +325,16 @@ function csarManager:onEvent(event)
|
|||||||
-- we also need to make sure that there are no
|
-- we also need to make sure that there are no
|
||||||
-- more troopsOnBoard
|
-- more troopsOnBoard
|
||||||
|
|
||||||
|
local myName = theUnit:getName()
|
||||||
local conf = csarManager.getUnitConfig(theUnit)
|
local conf = csarManager.getUnitConfig(theUnit)
|
||||||
conf.unit = theUnit
|
conf.unit = theUnit
|
||||||
conf.troopsOnBoard = {}
|
conf.troopsOnBoard = {}
|
||||||
|
local totalMass = cargoSuper.calculateTotalMassFor(myName)
|
||||||
|
|
||||||
|
-- now also set cargo weight for the unit
|
||||||
|
cargoSuper.removeAllMassForCargo(myName, "Evacuees") -- will allocate new empty table
|
||||||
|
totalMass = cargoSuper.calculateTotalMassFor(myName)
|
||||||
|
trigger.action.setUnitInternalCargo(myName, totalMass) -- super recalcs
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -448,11 +462,12 @@ function csarManager.heloLanded(theUnit)
|
|||||||
"Evacuees",
|
"Evacuees",
|
||||||
theMassObject)
|
theMassObject)
|
||||||
msn = theMassObject.ref
|
msn = theMassObject.ref
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset weight
|
-- reset weight
|
||||||
local totalMass = cargoSuper.calculateTotalMassFor(myName)
|
local totalMass = cargoSuper.calculateTotalMassFor(myName)
|
||||||
trigger.action.setUnitInternalCargo(myName, totalMass) -- super recalcs
|
trigger.action.setUnitInternalCargo(myName, totalMass) -- super recalcs
|
||||||
|
|
||||||
conf.troopsOnBoard = {} -- empty out troops on board
|
conf.troopsOnBoard = {} -- empty out troops on board
|
||||||
-- we do *not* return so we can pick up troops on
|
-- we do *not* return so we can pick up troops on
|
||||||
-- a CSARBASE if they were dropped there
|
-- a CSARBASE if they were dropped there
|
||||||
@ -524,6 +539,7 @@ function csarManager.heloLanded(theUnit)
|
|||||||
local totalMass = cargoSuper.calculateTotalMassFor(myName)
|
local totalMass = cargoSuper.calculateTotalMassFor(myName)
|
||||||
trigger.action.setUnitInternalCargo(myName, totalMass) -- 10 kg as empty + per-unit time people
|
trigger.action.setUnitInternalCargo(myName, totalMass) -- 10 kg as empty + per-unit time people
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function csarManager.asynchSuccess(args)
|
function csarManager.asynchSuccess(args)
|
||||||
@ -733,6 +749,8 @@ function csarManager.doListCSARRequests(args)
|
|||||||
local conf = args[1]
|
local conf = args[1]
|
||||||
local param = args[2]
|
local param = args[2]
|
||||||
local theUnit = conf.unit
|
local theUnit = conf.unit
|
||||||
|
if not theUnit then return end -- ??
|
||||||
|
if not Unit.isExist(theUnit) then return end
|
||||||
local point = theUnit:getPoint()
|
local point = theUnit:getPoint()
|
||||||
local theSide = theUnit:getCoalition()
|
local theSide = theUnit:getCoalition()
|
||||||
|
|
||||||
@ -794,6 +812,8 @@ function csarManager.doStatusCarrying(args)
|
|||||||
local conf = args[1]
|
local conf = args[1]
|
||||||
local param = args[2]
|
local param = args[2]
|
||||||
local theUnit = conf.unit
|
local theUnit = conf.unit
|
||||||
|
if not theUnit then return end -- ??
|
||||||
|
if not Unit.isExist(theUnit) then return end
|
||||||
local now = timer.getTime()
|
local now = timer.getTime()
|
||||||
|
|
||||||
-- build status report
|
-- build status report
|
||||||
@ -837,6 +857,9 @@ function csarManager.unloadOne(args)
|
|||||||
local conf = args[1]
|
local conf = args[1]
|
||||||
local param = args[2]
|
local param = args[2]
|
||||||
local theUnit = conf.unit
|
local theUnit = conf.unit
|
||||||
|
if not theUnit then return end -- ??
|
||||||
|
if not Unit.isExist(theUnit) then return end
|
||||||
|
|
||||||
local myName = theUnit:getName()
|
local myName = theUnit:getName()
|
||||||
|
|
||||||
local report = "NYI: unload one"
|
local report = "NYI: unload one"
|
||||||
@ -869,7 +892,9 @@ function csarManager.unloadOne(args)
|
|||||||
trigger.action.outSoundForCoalition(theSide, csarManager.actionSound) -- "Quest Snare 3.wav")
|
trigger.action.outSoundForCoalition(theSide, csarManager.actionSound) -- "Quest Snare 3.wav")
|
||||||
|
|
||||||
-- recalc weight
|
-- recalc weight
|
||||||
trigger.action.setUnitInternalCargo(myName, 10 + #conf.troopsOnBoard * csarManager.pilotWeight) -- 10 kg as empty + per-unit time people
|
local totalMass = 10 + #conf.troopsOnBoard * csarManager.pilotWeight
|
||||||
|
trigger.action.setUnitInternalCargo(myName, totalMass) -- 10 kg as empty + per-unit time people
|
||||||
|
--trigger.action.outText("unit <" .. myName .. ">, internal cargo now <" .. totalMass .. ">kg", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -882,6 +907,8 @@ function csarManager.directions(args)
|
|||||||
local conf = args[1]
|
local conf = args[1]
|
||||||
local param = args[2]
|
local param = args[2]
|
||||||
local theUnit = conf.unit
|
local theUnit = conf.unit
|
||||||
|
if not theUnit then return end -- ??
|
||||||
|
if not Unit.isExist(theUnit) then return end
|
||||||
local myName = theUnit:getName()
|
local myName = theUnit:getName()
|
||||||
local theSide = theUnit:getCoalition()
|
local theSide = theUnit:getCoalition()
|
||||||
local report = "Nothing to report."
|
local report = "Nothing to report."
|
||||||
@ -997,12 +1024,23 @@ function csarManager.updateCSARMissions()
|
|||||||
if stillRunning and stillAlive then
|
if stillRunning and stillAlive then
|
||||||
table.insert(newMissions, aMission)
|
table.insert(newMissions, aMission)
|
||||||
elseif stillAlive then
|
elseif stillAlive then
|
||||||
|
-- expired.
|
||||||
|
local p = aMission.zone:getPoint() -- all missions have a zone
|
||||||
|
p.y = 0
|
||||||
|
local thePlayers = coalition.getPlayers(aMission.side)
|
||||||
local msg = aMission.name .. " is no longer responding. Abort rescue."
|
local msg = aMission.name .. " is no longer responding. Abort rescue."
|
||||||
trigger.action.outTextForCoalition(aMission.side, msg, 30)
|
for idx, theUnit in pairs (thePlayers) do
|
||||||
trigger.action.outSoundForCoalition(aMission.side, csarManager.lostSound)
|
local up = theUnit:getPoint()
|
||||||
|
up.y = 0
|
||||||
|
local dist = math.floor (dcsCommon.dist(up, p))
|
||||||
|
if dist < csarManager.comsRange then
|
||||||
|
local ID = theUnit:getID()
|
||||||
|
trigger.action.outTextForUnit(ID, msg, 30)
|
||||||
|
trigger.action.outSoundForUnit(ID, csarManager.lostSound)
|
||||||
|
end
|
||||||
|
end
|
||||||
csarManager.invokeCallbacks(aMission.side, false, 1, "lost", aMission)
|
csarManager.invokeCallbacks(aMission.side, false, 1, "lost", aMission)
|
||||||
if aMission.group and Group.isExist(aMission.group) then
|
if aMission.group and Group.isExist(aMission.group) then
|
||||||
-- trigger.action.outText("removing group", 30)
|
|
||||||
Group.destroy(aMission.group)
|
Group.destroy(aMission.group)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@ -1156,12 +1194,11 @@ function csarManager.update() -- every second
|
|||||||
trigger.action.outText("+++csar: <" .. uName .. "> now has <" .. #allEvacuees .. "> groups of evacuees on board, totalling " .. totalMass .. "kg", 30)
|
trigger.action.outText("+++csar: <" .. uName .. "> now has <" .. #allEvacuees .. "> groups of evacuees on board, totalling " .. totalMass .. "kg", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
--trigger.action.outTextForGroup(uID, hoverMsg, 30, true)
|
|
||||||
trigger.action.outSoundForGroup(uID, csarManager.pickupSound)
|
trigger.action.outSoundForGroup(uID, csarManager.pickupSound)
|
||||||
|
|
||||||
--return -- we only ever rescue one
|
--return -- we only ever rescue one
|
||||||
end -- hovered long enough
|
end -- hovered long enough
|
||||||
--trigger.action.outTextForGroup(uID, hoverMsg, 30, true)
|
|
||||||
-- return -- only ever one winch op
|
-- return -- only ever one winch op
|
||||||
else -- too high for hover
|
else -- too high for hover
|
||||||
hoverMsg = "Evacuee " .. d * 1 .. "m on your " .. oclock .. " o'clock; land or descend to between 10 and 90 AGL for winching"
|
hoverMsg = "Evacuee " .. d * 1 .. "m on your " .. oclock .. " o'clock; land or descend to between 10 and 90 AGL for winching"
|
||||||
@ -1328,13 +1365,11 @@ function csarManager.readCSARZone(theZone)
|
|||||||
theZone.csarMapMarker = nil
|
theZone.csarMapMarker = nil
|
||||||
if theZone:hasProperty("timeLimit") then
|
if theZone:hasProperty("timeLimit") then
|
||||||
local tmin, tmax = theZone:getPositiveRangeFromZoneProperty("timeLimit", 1)
|
local tmin, tmax = theZone:getPositiveRangeFromZoneProperty("timeLimit", 1)
|
||||||
-- trigger.action.outText("Read time limit for <" .. theZone.name .. ">: <" .. tmin .. ">, <" .. tmax .. ">", 30)
|
|
||||||
theZone.timeLimit = {tmin, tmax}
|
theZone.timeLimit = {tmin, tmax}
|
||||||
else
|
else
|
||||||
theZone.timeLimit = nil
|
theZone.timeLimit = nil
|
||||||
end
|
end
|
||||||
-- theZone.timeLimit = theZone:getNumberFromZoneProperty("timeLimit", 0)
|
|
||||||
-- if theZone.timeLimit == 0 then theZone.timeLimit = nil else theZone.timeLimit = timeLimit * 60 end
|
|
||||||
|
|
||||||
local deferred = theZone:getBoolFromZoneProperty("deferred", false)
|
local deferred = theZone:getBoolFromZoneProperty("deferred", false)
|
||||||
|
|
||||||
@ -1389,7 +1424,6 @@ function csarManager.readCSARZone(theZone)
|
|||||||
-- add to list of startable csar
|
-- add to list of startable csar
|
||||||
if theZone.startCSAR then
|
if theZone.startCSAR then
|
||||||
csarManager.addCSARZone(theZone)
|
csarManager.addCSARZone(theZone)
|
||||||
-- trigger.action.outText("csar: added <".. theZone.name .."> to deferred csar missions", 30)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if deferred and not theZone.startCSAR then
|
if deferred and not theZone.startCSAR then
|
||||||
@ -1495,6 +1529,7 @@ function csarManager.readConfigZone()
|
|||||||
csarManager.pickupSound = theZone:getStringFromZoneProperty("pickupSound", csarManager.actionSound)
|
csarManager.pickupSound = theZone:getStringFromZoneProperty("pickupSound", csarManager.actionSound)
|
||||||
csarManager.vectoring = theZone:getBoolFromZoneProperty("vectoring", true)
|
csarManager.vectoring = theZone:getBoolFromZoneProperty("vectoring", true)
|
||||||
csarManager.lostSound = theZone:getStringFromZoneProperty("lostSound", csarManager.actionSound)
|
csarManager.lostSound = theZone:getStringFromZoneProperty("lostSound", csarManager.actionSound)
|
||||||
|
csarManager.comsRange = theZone:getNumberFromZoneProperty("comsRange", 40000)
|
||||||
|
|
||||||
-- add own troop carriers
|
-- add own troop carriers
|
||||||
if theZone:hasProperty("troopCarriers") then
|
if theZone:hasProperty("troopCarriers") then
|
||||||
@ -1512,6 +1547,13 @@ function csarManager.readConfigZone()
|
|||||||
csarManager.addPrefix = theZone:getBoolFromZoneProperty("addPrefix", true)
|
csarManager.addPrefix = theZone:getBoolFromZoneProperty("addPrefix", true)
|
||||||
|
|
||||||
csarManager.maxMissions = theZone:getNumberFromZoneProperty("maxMissions", 15)
|
csarManager.maxMissions = theZone:getNumberFromZoneProperty("maxMissions", 15)
|
||||||
|
|
||||||
|
-- add types to use for the rescuee
|
||||||
|
local hTypes = theZone:getStringFromZoneProperty("rescueTypes", "Soldier M4 GRG")
|
||||||
|
local typeArray = dcsCommon.splitString(hTypes, ",")
|
||||||
|
typeArray = dcsCommon.trimArray(typeArray)
|
||||||
|
csarManager.rescueTypes = typeArray
|
||||||
|
|
||||||
if csarManager.verbose then
|
if csarManager.verbose then
|
||||||
trigger.action.outText("+++csar: read config", 30)
|
trigger.action.outText("+++csar: read config", 30)
|
||||||
end
|
end
|
||||||
@ -1535,8 +1577,6 @@ function csarManager.start()
|
|||||||
-- and populate the available mission.
|
-- and populate the available mission.
|
||||||
csarManager.processCSARZones()
|
csarManager.processCSARZones()
|
||||||
|
|
||||||
-- install callbacks for helo-relevant events
|
|
||||||
--dcsCommon.addEventHandler(csarManager.somethingHappened, csarManager.preProcessor, csarManager.postProcessor)
|
|
||||||
world.addEventHandler(csarManager)
|
world.addEventHandler(csarManager)
|
||||||
|
|
||||||
-- now iterate through all player groups and install the CSAR Menu
|
-- now iterate through all player groups and install the CSAR Menu
|
||||||
|
|||||||
@ -17,6 +17,7 @@ factoryZone.name = "factoryZone"
|
|||||||
- productionTime config synonyme
|
- productionTime config synonyme
|
||||||
- defendMe? attribute
|
- defendMe? attribute
|
||||||
- triggered 'shocked' mode via defendMe
|
- triggered 'shocked' mode via defendMe
|
||||||
|
3.1.1 - fixed a big with persistence
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
factoryZone.requiredLibs = {
|
factoryZone.requiredLibs = {
|
||||||
@ -734,7 +735,7 @@ function factoryZone.loadData()
|
|||||||
local allZoneData = theData.zoneData
|
local allZoneData = theData.zoneData
|
||||||
for zName, zData in pairs(allZoneData) do
|
for zName, zData in pairs(allZoneData) do
|
||||||
-- access zone
|
-- access zone
|
||||||
local theZone = factoryZone.getOwnedZoneByName(zName)
|
local theZone = factoryZone.getFactoryZoneByName(zName)-- was: factoryZone.getOwnedZoneByName(zName)
|
||||||
if theZone then
|
if theZone then
|
||||||
if zData.defenderData then
|
if zData.defenderData then
|
||||||
if theZone.defenders and theZone.defenders:isExist() then
|
if theZone.defenders and theZone.defenders:isExist() then
|
||||||
|
|||||||
@ -93,16 +93,13 @@ function nameStats.addString(name, aString, path, rootNode)
|
|||||||
if not name then return nil end
|
if not name then return nil end
|
||||||
if not aString then return nil end
|
if not aString then return nil end
|
||||||
local theLeaf = nameStats.getLeaf(name, path, rootNode)
|
local theLeaf = nameStats.getLeaf(name, path, rootNode)
|
||||||
--table.insert(theLeaf.strings, aString)
|
|
||||||
theLeaf.strings = theLeaf.strings .. aString
|
theLeaf.strings = theLeaf.strings .. aString
|
||||||
-- return aString
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- reset the log
|
-- reset the log
|
||||||
function nameStats.removeAllString(name, path, rootNode)
|
function nameStats.removeAllString(name, path, rootNode)
|
||||||
if not name then return nil end
|
if not name then return nil end
|
||||||
local theLeaf = nameStats.getLeaf(name, path, rootNode)
|
local theLeaf = nameStats.getLeaf(name, path, rootNode)
|
||||||
-- theLeaf.strings = {}
|
|
||||||
theLeaf.strings = ""
|
theLeaf.strings = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -166,7 +163,7 @@ function nameStats.reset(name, path, rootNode)
|
|||||||
-- create new leaf and replace existing
|
-- create new leaf and replace existing
|
||||||
theLeaf = nameStats.createLeaf()
|
theLeaf = nameStats.createLeaf()
|
||||||
theEntry.data[path] = theLeaf
|
theEntry.data[path] = theLeaf
|
||||||
|
rootNode[name] = theEntry
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxObjectSpawnZones = {}
|
cfxObjectSpawnZones = {}
|
||||||
cfxObjectSpawnZones.version = "2.0.0"
|
cfxObjectSpawnZones.version = "2.1.0"
|
||||||
cfxObjectSpawnZones.requiredLibs = {
|
cfxObjectSpawnZones.requiredLibs = {
|
||||||
"dcsCommon", -- common is of course needed for everything
|
"dcsCommon", -- common is of course needed for everything
|
||||||
-- pretty stupid to check for this since we
|
-- pretty stupid to check for this since we
|
||||||
@ -14,6 +14,7 @@ cfxObjectSpawnZones.verbose = false
|
|||||||
|
|
||||||
version history
|
version history
|
||||||
2.0.0 - dmlZones
|
2.0.0 - dmlZones
|
||||||
|
2.1.0 - autoTurn attribute
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -87,6 +88,8 @@ function cfxObjectSpawnZones.createSpawner(inZone)
|
|||||||
theSpawner.autoLink = inZone:getBoolFromZoneProperty("autoLink", true)
|
theSpawner.autoLink = inZone:getBoolFromZoneProperty("autoLink", true)
|
||||||
|
|
||||||
theSpawner.heading = inZone:getNumberFromZoneProperty("heading", 0)
|
theSpawner.heading = inZone:getNumberFromZoneProperty("heading", 0)
|
||||||
|
-- note: currently expects rads. maybe change to degrees?
|
||||||
|
theSpawner.autoTurn = inZone:getBoolFromZoneProperty("autoTurn", false)
|
||||||
theSpawner.weight = inZone:getNumberFromZoneProperty("weight", 0)
|
theSpawner.weight = inZone:getNumberFromZoneProperty("weight", 0)
|
||||||
if theSpawner.weight < 0 then theSpawner.weight = 0 end
|
if theSpawner.weight < 0 then theSpawner.weight = 0 end
|
||||||
|
|
||||||
@ -265,8 +268,8 @@ function cfxObjectSpawnZones.spawnObjectNTimes(aSpawner, theType, n, container)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local numObjects = n
|
local numObjects = n
|
||||||
local degrees = 3.14157 / 180
|
local degrees = 3.14157 / 180 -- rads!
|
||||||
local degreeIncrement = (360 / numObjects) * degrees
|
local degreeIncrement = (360 / numObjects) * degrees -- rads!
|
||||||
local currDegree = 0
|
local currDegree = 0
|
||||||
local missionObjects = {}
|
local missionObjects = {}
|
||||||
for i=1, numObjects do
|
for i=1, numObjects do
|
||||||
@ -274,11 +277,14 @@ function cfxObjectSpawnZones.spawnObjectNTimes(aSpawner, theType, n, container)
|
|||||||
local ry = math.sin(currDegree) * aZone.radius
|
local ry = math.sin(currDegree) * aZone.radius
|
||||||
local ox = center.x + rx
|
local ox = center.x + rx
|
||||||
local oy = center.z + ry -- note: z!
|
local oy = center.z + ry -- note: z!
|
||||||
|
local hdg = aSpawner.heading -- heading is in rads!
|
||||||
|
if aSpawner.autoTurn then
|
||||||
|
hdg = hdg + currDegree -- currDegree is in rads!
|
||||||
|
end
|
||||||
local theStaticData = dcsCommon.createStaticObjectData(
|
local theStaticData = dcsCommon.createStaticObjectData(
|
||||||
aSpawner.baseName .. "-" .. aSpawner.count,
|
aSpawner.baseName .. "-" .. aSpawner.count,
|
||||||
theType,
|
theType,
|
||||||
aSpawner.heading,
|
hdg ,--aSpawner.heading,
|
||||||
false, -- dead?
|
false, -- dead?
|
||||||
aSpawner.isCargo,
|
aSpawner.isCargo,
|
||||||
aSpawner.weight)
|
aSpawner.weight)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxOwnedZones = {}
|
cfxOwnedZones = {}
|
||||||
cfxOwnedZones.version = "2.1.0"
|
cfxOwnedZones.version = "2.2.0"
|
||||||
cfxOwnedZones.verbose = false
|
cfxOwnedZones.verbose = false
|
||||||
cfxOwnedZones.announcer = true
|
cfxOwnedZones.announcer = true
|
||||||
cfxOwnedZones.name = "cfxOwnedZones"
|
cfxOwnedZones.name = "cfxOwnedZones"
|
||||||
@ -29,6 +29,7 @@ cfxOwnedZones.name = "cfxOwnedZones"
|
|||||||
- method support for individual owned zones
|
- method support for individual owned zones
|
||||||
- method support for global (config) output
|
- method support for global (config) output
|
||||||
- moved drawZone to cfxZones
|
- moved drawZone to cfxZones
|
||||||
|
2.2.0 - excludedTypes option in config
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
cfxOwnedZones.requiredLibs = {
|
cfxOwnedZones.requiredLibs = {
|
||||||
@ -317,13 +318,43 @@ function cfxOwnedZones.update()
|
|||||||
-- we only check first unit that is alive
|
-- we only check first unit that is alive
|
||||||
local theUnit = dcsCommon.getGroupUnit(aGroup)
|
local theUnit = dcsCommon.getGroupUnit(aGroup)
|
||||||
if theUnit and (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
if theUnit and (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
||||||
theZone.numRed = theZone.numRed + aGroup:getSize()
|
if cfxOwnedZones.excludedTypes then
|
||||||
|
-- special carve-out for exclduding some
|
||||||
|
-- unit types to prevent them from capping
|
||||||
|
local uType = theUnit:getTypeName()
|
||||||
|
local forbidden = false
|
||||||
|
for idx, aType in pairs(cfxOwnedZones.excludedTypes) do
|
||||||
|
if uType == aType then
|
||||||
|
forbidden = true
|
||||||
|
else
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not forbidden then
|
||||||
|
theZone.numRed = theZone.numRed + aGroup:getSize()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
theZone.numRed = theZone.numRed + aGroup:getSize()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else -- full eval
|
||||||
local allUnits = aGroup:getUnits()
|
local allUnits = aGroup:getUnits()
|
||||||
for idy, theUnit in pairs(allUnits) do
|
for idy, theUnit in pairs(allUnits) do
|
||||||
if (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
if (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
||||||
theZone.numRed = theZone.numRed + 1
|
-- theZone.numRed = theZone.numRed + 1
|
||||||
|
if cfxOwnedZones.excludedTypes then
|
||||||
|
-- special carve-out for exclduding some
|
||||||
|
-- unit types to prevent them from capping
|
||||||
|
local uType = theUnit:getTypeName()
|
||||||
|
local forbidden = false
|
||||||
|
for idx, aType in pairs(cfxOwnedZones.excludedTypes) do
|
||||||
|
if uType == aType then forbidden = true end
|
||||||
|
end
|
||||||
|
if not forbidden then
|
||||||
|
theZone.numRed = theZone.numRed + aGroup:getSize()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
theZone.numRed = theZone.numRed + aGroup:getSize()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -337,13 +368,43 @@ function cfxOwnedZones.update()
|
|||||||
-- we only check first unit that is alive
|
-- we only check first unit that is alive
|
||||||
local theUnit = dcsCommon.getGroupUnit(aGroup)
|
local theUnit = dcsCommon.getGroupUnit(aGroup)
|
||||||
if theUnit and (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
if theUnit and (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
||||||
theZone.numBlue = theZone.numBlue + aGroup:getSize()
|
if cfxOwnedZones.excludedTypes then
|
||||||
|
-- special carve-out for exclduding some
|
||||||
|
-- unit types to prevent them from capping
|
||||||
|
local uType = theUnit:getTypeName()
|
||||||
|
local forbidden = false
|
||||||
|
for idx, aType in pairs(cfxOwnedZones.excludedTypes) do
|
||||||
|
if uType == aType then
|
||||||
|
forbidden = true
|
||||||
|
else
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not forbidden then
|
||||||
|
theZone.numBlue = theZone.numBlue + aGroup:getSize()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
theZone.numBlue = theZone.numBlue + aGroup:getSize()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local allUnits = aGroup:getUnits()
|
local allUnits = aGroup:getUnits()
|
||||||
for idy, theUnit in pairs(allUnits) do
|
for idy, theUnit in pairs(allUnits) do
|
||||||
if (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
if (not theUnit:inAir()) and theZone:unitInZone(theUnit) then
|
||||||
theZone.numBlue = theZone.numBlue + 1
|
-- theZone.numBlue = theZone.numBlue + 1
|
||||||
|
if cfxOwnedZones.excludedTypes then
|
||||||
|
-- special carve-out for exclduding some
|
||||||
|
-- unit types to prevent them from capping
|
||||||
|
local uType = theUnit:getTypeName()
|
||||||
|
local forbidden = false
|
||||||
|
for idx, aType in pairs(cfxOwnedZones.excludedTypes) do
|
||||||
|
if uType == aType then forbidden = true end
|
||||||
|
end
|
||||||
|
if not forbidden then
|
||||||
|
theZone.numBlue = theZone.numBlue + aGroup:getSize()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
theZone.numBlue = theZone.numBlue + aGroup:getSize()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -799,6 +860,13 @@ function cfxOwnedZones.readConfigZone(theZone)
|
|||||||
cfxOwnedZones.neutralLine = theZone:getRGBAVectorFromZoneProperty("neutralLine", {0.8, 0.8, 0.8, 1.0})
|
cfxOwnedZones.neutralLine = theZone:getRGBAVectorFromZoneProperty("neutralLine", {0.8, 0.8, 0.8, 1.0})
|
||||||
cfxOwnedZones.neutralFill = theZone:getRGBAVectorFromZoneProperty("neutralFill", {0.8, 0.8, 0.8, 0.2})
|
cfxOwnedZones.neutralFill = theZone:getRGBAVectorFromZoneProperty("neutralFill", {0.8, 0.8, 0.8, 0.2})
|
||||||
|
|
||||||
|
if theZone:hasProperty("excludedTypes") then
|
||||||
|
local theTypes = theZone:getStringFromZoneProperty("excludedTypes", "none")
|
||||||
|
local typeArray = dcsCommon.splitString(theTypes, ",")
|
||||||
|
typeArray = dcsCommon.trimArray(typeArray)
|
||||||
|
cfxOwnedZones.excludedTypes = typeArray
|
||||||
|
end
|
||||||
|
|
||||||
cfxOwnedZones.method = theZone:getStringFromZoneProperty("method", "inc")
|
cfxOwnedZones.method = theZone:getStringFromZoneProperty("method", "inc")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
persistence = {}
|
persistence = {}
|
||||||
persistence.version = "2.0.0"
|
persistence.version = "3.0.0"
|
||||||
persistence.ups = 1 -- once every 1 seconds
|
persistence.ups = 1 -- once every 1 seconds
|
||||||
persistence.verbose = false
|
persistence.verbose = false
|
||||||
persistence.active = false
|
persistence.active = false
|
||||||
@ -17,6 +17,7 @@ persistence.requiredLibs = {
|
|||||||
Version History
|
Version History
|
||||||
2.0.0 - dml zones, OOP
|
2.0.0 - dml zones, OOP
|
||||||
cleanup
|
cleanup
|
||||||
|
3.0.0 - shared data
|
||||||
|
|
||||||
PROVIDES LOAD/SAVE ABILITY TO MODULES
|
PROVIDES LOAD/SAVE ABILITY TO MODULES
|
||||||
PROVIDES STANDALONE/HOSTED SERVER COMPATIBILITY
|
PROVIDES STANDALONE/HOSTED SERVER COMPATIBILITY
|
||||||
@ -67,11 +68,34 @@ end
|
|||||||
--
|
--
|
||||||
-- registered modules call this to get their data
|
-- registered modules call this to get their data
|
||||||
--
|
--
|
||||||
function persistence.getSavedDataForModule(name)
|
function persistence.getSavedDataForModule(name, sharedDataName)
|
||||||
if not persistence.active then return nil end
|
if not persistence.active then return nil end
|
||||||
if not persistence.hasData then return nil end
|
if not persistence.hasData then return nil end
|
||||||
if not persistence.missionData then return end
|
if not persistence.missionData then return end
|
||||||
|
if not sharedDataName then sharedDataName = nil end
|
||||||
|
|
||||||
|
if sharedDataName then
|
||||||
|
-- we read from shared data and only revert to
|
||||||
|
-- common if we find nothing
|
||||||
|
local shFile = persistence.sharedDir .. sharedDataName .. ".txt"
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("persistence: will try to load shared data from <" .. shFile .. ">", 30)
|
||||||
|
end
|
||||||
|
local theData = persistence.loadTable(shFile, true)
|
||||||
|
if theData then
|
||||||
|
if theData[name] then
|
||||||
|
return theData[name]
|
||||||
|
end
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("persistence: shared data file <" .. sharedDataName .. "> exists but currently holds no data for <" .. name .. ">, reverting to main", 30)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("persistence: shared data file <" .. sharedDataName
|
||||||
|
.. "> does not yet exist, reverting to main", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
return persistence.missionData[name] -- simply get the modules data block
|
return persistence.missionData[name] -- simply get the modules data block
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -162,9 +186,8 @@ function persistence.saveTable(theTable, fileName, shared, append)
|
|||||||
|
|
||||||
local path = persistence.missionDir .. fileName
|
local path = persistence.missionDir .. fileName
|
||||||
if shared then
|
if shared then
|
||||||
-- we would now change the path
|
-- we change the path to shared
|
||||||
trigger.action.outText("+++persistence: NYI: shared", 30)
|
path = persistence.sharedDir .. fileName .. ".txt"
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local theFile = nil
|
local theFile = nil
|
||||||
@ -186,11 +209,21 @@ function persistence.saveTable(theTable, fileName, shared, append)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function persistence.loadText(fileName) -- load file as text
|
function persistence.loadText(fileName, hasPath) -- load file as text
|
||||||
if not persistence.active then return nil end
|
if not persistence.active then return nil end
|
||||||
if not fileName then return nil end
|
if not fileName then return nil end
|
||||||
|
|
||||||
local path = persistence.missionDir .. fileName
|
local path
|
||||||
|
if hasPath then
|
||||||
|
path = fileName
|
||||||
|
else
|
||||||
|
path = persistence.missionDir .. fileName
|
||||||
|
end
|
||||||
|
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("persistence: will load text file <" .. path .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
local theFile = io.open(path, "r")
|
local theFile = io.open(path, "r")
|
||||||
if not theFile then return nil end
|
if not theFile then return nil end
|
||||||
|
|
||||||
@ -201,11 +234,12 @@ function persistence.loadText(fileName) -- load file as text
|
|||||||
return t
|
return t
|
||||||
end
|
end
|
||||||
|
|
||||||
function persistence.loadTable(fileName) -- load file as table
|
function persistence.loadTable(fileName, hasPath) -- load file as table
|
||||||
if not persistence.active then return nil end
|
if not persistence.active then return nil end
|
||||||
if not fileName then return nil end
|
if not fileName then return nil end
|
||||||
|
if not hasPath then hasPath = false end
|
||||||
|
|
||||||
local t = persistence.loadText(fileName)
|
local t = persistence.loadText(fileName, hasPath)
|
||||||
|
|
||||||
if not t then return nil end
|
if not t then return nil end
|
||||||
|
|
||||||
@ -241,6 +275,12 @@ function persistence.initFlagsFromData(theFlags)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function persistence.freshStart()
|
||||||
|
persistence.missionData = {}
|
||||||
|
persistence.hasData = true
|
||||||
|
trigger.action.setUserFlag("cfxPersistenceHasData", 1)
|
||||||
|
end
|
||||||
|
|
||||||
function persistence.missionStartDataLoad()
|
function persistence.missionStartDataLoad()
|
||||||
-- check one: see if we have mission data
|
-- check one: see if we have mission data
|
||||||
local theData = persistence.loadTable(persistence.saveFileName)
|
local theData = persistence.loadTable(persistence.saveFileName)
|
||||||
@ -249,6 +289,7 @@ function persistence.missionStartDataLoad()
|
|||||||
if persistence.verbose then
|
if persistence.verbose then
|
||||||
trigger.action.outText("+++persistence: no saved data, fresh start.", 30)
|
trigger.action.outText("+++persistence: no saved data, fresh start.", 30)
|
||||||
end
|
end
|
||||||
|
persistence.freshStart()
|
||||||
return
|
return
|
||||||
end -- there was no data to load
|
end -- there was no data to load
|
||||||
|
|
||||||
@ -256,6 +297,7 @@ function persistence.missionStartDataLoad()
|
|||||||
if persistence.verbose then
|
if persistence.verbose then
|
||||||
trigger.action.outText("+++persistence: detected fresh start.", 30)
|
trigger.action.outText("+++persistence: detected fresh start.", 30)
|
||||||
end
|
end
|
||||||
|
persistence.freshStart()
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -308,8 +350,13 @@ function persistence.collectFlagData()
|
|||||||
return flagData
|
return flagData
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function persistence.saveSharedData()
|
||||||
|
trigger.action.outText("WARNING: Persistence's saveSharedData invoked!", 30)
|
||||||
|
end
|
||||||
|
|
||||||
function persistence.saveMissionData()
|
function persistence.saveMissionData()
|
||||||
local myData = {}
|
local myData = {}
|
||||||
|
local allSharedData = {} -- organized by 'shared' name returned
|
||||||
|
|
||||||
-- first, handle versionID and freshMaker
|
-- first, handle versionID and freshMaker
|
||||||
if persistence.freshMaker then
|
if persistence.freshMaker then
|
||||||
@ -325,8 +372,15 @@ function persistence.saveMissionData()
|
|||||||
|
|
||||||
-- now handle all other modules
|
-- now handle all other modules
|
||||||
for moduleName, callbacks in pairs(persistence.callbacks) do
|
for moduleName, callbacks in pairs(persistence.callbacks) do
|
||||||
local moduleData = callbacks.persistData()
|
local moduleData, sharedName = callbacks.persistData()
|
||||||
if moduleData then
|
if moduleData then
|
||||||
|
if sharedName then -- save into shared bucket
|
||||||
|
-- allshared[specificShared[moduleName]]
|
||||||
|
local specificShared = allSharedData[sharedName]
|
||||||
|
if not specificShared then specificShared = {} end
|
||||||
|
specificShared[moduleName] = moduleData
|
||||||
|
allSharedData[sharedName] = specificShared -- write back
|
||||||
|
end
|
||||||
myData[moduleName] = moduleData
|
myData[moduleName] = moduleData
|
||||||
if persistence.verbose then
|
if persistence.verbose then
|
||||||
trigger.action.outText("+++persistence: gathered data from <" .. moduleName .. ">", 30)
|
trigger.action.outText("+++persistence: gathered data from <" .. moduleName .. ">", 30)
|
||||||
@ -340,6 +394,23 @@ function persistence.saveMissionData()
|
|||||||
|
|
||||||
-- now save data to file
|
-- now save data to file
|
||||||
persistence.saveTable(myData, persistence.saveFileName)
|
persistence.saveTable(myData, persistence.saveFileName)
|
||||||
|
|
||||||
|
-- now save all shared name data as separate files
|
||||||
|
for shareName, data in pairs (allSharedData) do
|
||||||
|
-- save into shared folder, by name that was returned from callback
|
||||||
|
-- read what was saved, and replace changed key/values from data
|
||||||
|
local shFile = persistence.sharedDir .. shareName .. ".txt"
|
||||||
|
local theData = persistence.loadTable(shFile, true) -- hasPath
|
||||||
|
if theData then
|
||||||
|
for k, v in pairs(data) do
|
||||||
|
theData[k] = v
|
||||||
|
end
|
||||||
|
else
|
||||||
|
theData = data
|
||||||
|
end
|
||||||
|
|
||||||
|
persistence.saveTable(theData, shareName, true) -- true --> shared
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -433,6 +504,7 @@ function persistence.readConfigZone()
|
|||||||
end
|
end
|
||||||
|
|
||||||
persistence.serverDir = theZone:getStringFromZoneProperty("serverDir", "Missions\\")
|
persistence.serverDir = theZone:getStringFromZoneProperty("serverDir", "Missions\\")
|
||||||
|
persistence.sharedDir = "DML-Shared-Data\\" -- hard-wired!
|
||||||
|
|
||||||
if hasConfig then
|
if hasConfig then
|
||||||
if theZone:hasProperty("saveDir") then
|
if theZone:hasProperty("saveDir") then
|
||||||
@ -513,10 +585,12 @@ function persistence.start()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
local mainDir = persistence.root .. persistence.serverDir
|
local mainDir = persistence.root .. persistence.serverDir -- usually DCS/Missions
|
||||||
if not dcsCommon.stringEndsWith(mainDir, "\\") then
|
if not dcsCommon.stringEndsWith(mainDir, "\\") then
|
||||||
mainDir = mainDir .. "\\"
|
mainDir = mainDir .. "\\"
|
||||||
end
|
end
|
||||||
|
local sharedDir = mainDir .. persistence.sharedDir -- ends on \\, hardwired
|
||||||
|
persistence.sharedDir = sharedDir
|
||||||
|
|
||||||
-- lets see if we can access the server's mission directory and
|
-- lets see if we can access the server's mission directory and
|
||||||
-- save directory
|
-- save directory
|
||||||
@ -531,12 +605,12 @@ function persistence.start()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
persistence.mainDir = mainDir
|
persistence.mainDir = mainDir
|
||||||
|
|
||||||
local missionDir = mainDir .. persistence.saveDir
|
local missionDir = mainDir .. persistence.saveDir
|
||||||
if not dcsCommon.stringEndsWith(missionDir, "\\") then
|
if not dcsCommon.stringEndsWith(missionDir, "\\") then
|
||||||
missionDir = missionDir .. "\\"
|
missionDir = missionDir .. "\\"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- check if mission dir exists already
|
-- check if mission dir exists already
|
||||||
local success, mode = persistence.hasFile(missionDir)
|
local success, mode = persistence.hasFile(missionDir)
|
||||||
if success and mode == "directory" then
|
if success and mode == "directory" then
|
||||||
@ -566,6 +640,35 @@ function persistence.start()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- make sure that SHARED dir exists, create if not
|
||||||
|
local success, mode = persistence.hasFile(sharedDir)
|
||||||
|
if success and mode == "directory" then
|
||||||
|
-- has been allocated, and is dir
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("+++persistence: saving SHARED data to <" .. sharedDir .. ">", 30)
|
||||||
|
end
|
||||||
|
elseif success then
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("+++persistence: <" .. sharedDir .. "> is not a directory", 30)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
-- does not exist, try to allocate it
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("+++persistence: will now create <" .. sharedDir .. ">", 30)
|
||||||
|
end
|
||||||
|
local ok, mkErr = lfs.mkdir(sharedDir)
|
||||||
|
if not ok then
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("+++persistence: unable to create <" .. sharedDir .. ">: <" .. mkErr .. ">", 30)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if persistence.verbose then
|
||||||
|
trigger.action.outText("+++persistence: created <" .. sharedDir .. "> successfully, will save SHARED data here", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- missionDir is root + serverDir + saveDir
|
-- missionDir is root + serverDir + saveDir
|
||||||
persistence.missionDir = missionDir
|
persistence.missionDir = missionDir
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
scribe = {}
|
scribe = {}
|
||||||
scribe.version = "1.0.1"
|
scribe.version = "1.1.0"
|
||||||
scribe.requiredLibs = {
|
scribe.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
"cfxZones", -- Zones, of course
|
"cfxZones", -- Zones, of course
|
||||||
@ -11,6 +11,7 @@ Player statistics package
|
|||||||
VERSION HISTORY
|
VERSION HISTORY
|
||||||
1.0.0 Initial Version
|
1.0.0 Initial Version
|
||||||
1.0.1 postponed land, postponed takeoff, unit_lost
|
1.0.1 postponed land, postponed takeoff, unit_lost
|
||||||
|
1.1.0 supports persistence's SHARED ability to share data across missions
|
||||||
--]]--
|
--]]--
|
||||||
scribe.verbose = true
|
scribe.verbose = true
|
||||||
scribe.db = {} -- indexed by player name
|
scribe.db = {} -- indexed by player name
|
||||||
@ -538,6 +539,11 @@ function scribe.readConfigZone()
|
|||||||
scribe.lTime = theZone:getStringFromZoneProperty("lTime", "time:")
|
scribe.lTime = theZone:getStringFromZoneProperty("lTime", "time:")
|
||||||
scribe.landingCD = theZone:getNumberFromZoneProperty("landingCD", 60) -- seconds between stake-off, landings, or either
|
scribe.landingCD = theZone:getNumberFromZoneProperty("landingCD", 60) -- seconds between stake-off, landings, or either
|
||||||
|
|
||||||
|
-- shared data persistence interface
|
||||||
|
if theZone:hasProperty("sharedData") then
|
||||||
|
scribe.sharedData = theZone:getStringFromZoneProperty("sharedData", "cfxNameMissing")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -555,12 +561,13 @@ function scribe.saveData()
|
|||||||
local theLog = dcsCommon.clone(scribe.db)
|
local theLog = dcsCommon.clone(scribe.db)
|
||||||
theData.theLog = theLog
|
theData.theLog = theLog
|
||||||
|
|
||||||
return theData
|
return theData, scribe.sharedData -- second val only if shared
|
||||||
end
|
end
|
||||||
|
|
||||||
function scribe.loadData()
|
function scribe.loadData()
|
||||||
if not persistence then return end
|
if not persistence then return end
|
||||||
local theData = persistence.getSavedDataForModule("scribe")
|
local theData = persistence.getSavedDataForModule("scribe", scribe.sharedData)
|
||||||
|
|
||||||
if not theData then
|
if not theData then
|
||||||
if scribe.verbose then
|
if scribe.verbose then
|
||||||
trigger.action.outText("+++scb: no save date received, skipping.", 30)
|
trigger.action.outText("+++scb: no save date received, skipping.", 30)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
stopGap = {}
|
stopGap = {}
|
||||||
stopGap.version = "1.0.9 STANDALONE"
|
stopGap.version = "1.1.0 STANDALONE"
|
||||||
stopGap.verbose = false
|
stopGap.verbose = false
|
||||||
stopGap.ssbEnabled = true
|
stopGap.ssbEnabled = true
|
||||||
stopGap.ignoreMe = "-sg"
|
stopGap.ignoreMe = "-sg"
|
||||||
@ -7,6 +7,7 @@ stopGap.spIgnore = "-sp" -- only single-player ignored
|
|||||||
stopGap.isMP = false
|
stopGap.isMP = false
|
||||||
stopGap.running = true
|
stopGap.running = true
|
||||||
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
|
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
|
||||||
|
stopGap.kickTheDead = true -- kick players to spectators on death to prevent re-entry issues
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
Written and (c) 2023 by Christian Franz
|
Written and (c) 2023 by Christian Franz
|
||||||
@ -34,6 +35,8 @@ stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600
|
|||||||
1.0.7 - (DML-only internal cool stuff)
|
1.0.7 - (DML-only internal cool stuff)
|
||||||
1.0.8 - added refreshInterval option as requested
|
1.0.8 - added refreshInterval option as requested
|
||||||
1.0.9 - optimization when turning on stopgap
|
1.0.9 - optimization when turning on stopgap
|
||||||
|
1.1.0 - kickTheDead option
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
stopGap.standInGroups ={}
|
stopGap.standInGroups ={}
|
||||||
@ -253,11 +256,11 @@ function stopGap:onEvent(event)
|
|||||||
if not event.id then return end
|
if not event.id then return end
|
||||||
if not event.initiator then return end
|
if not event.initiator then return end
|
||||||
local theUnit = event.initiator
|
local theUnit = event.initiator
|
||||||
|
if (not theUnit.getPlayerName) or (not theUnit:getPlayerName()) then
|
||||||
if event.id == 15 then
|
return
|
||||||
if (not theUnit.getPlayerName) or (not theUnit:getPlayerName()) then
|
end -- no player unit.
|
||||||
return
|
local id = event.id
|
||||||
end -- no player unit.
|
if id == 15 then
|
||||||
local uName = theUnit:getName()
|
local uName = theUnit:getName()
|
||||||
local theGroup = theUnit:getGroup()
|
local theGroup = theUnit:getGroup()
|
||||||
local gName = theGroup:getName()
|
local gName = theGroup:getName()
|
||||||
@ -269,13 +272,31 @@ function stopGap:onEvent(event)
|
|||||||
stopGap.removeStaticGapGroupNamed(gName)
|
stopGap.removeStaticGapGroupNamed(gName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- erase stopGapGUI flag, no longer required, unit
|
-- erase stopGapGUI flag, no longer required, unit
|
||||||
-- is now slotted into
|
-- is now slotted into
|
||||||
trigger.action.setUserFlag("SG"..gName, 0)
|
trigger.action.setUserFlag("SG"..gName, 0)
|
||||||
end
|
end
|
||||||
|
if (id == 9) or (id == 30) or (id == 5) then -- dead, lost, crash
|
||||||
|
local pName = theUnit:getPlayerName()
|
||||||
|
timer.scheduleFunction(stopGap.kickplayer, pName, timer.getTime() + 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
stopGap.kicks = {}
|
||||||
|
function stopGap.kickplayer(args)
|
||||||
|
if not stopGap.kickTheDead then return end
|
||||||
|
local pName = args
|
||||||
|
for i,slot in pairs(net.get_player_list()) do
|
||||||
|
local nn = net.get_name(slot)
|
||||||
|
if nn == pName then
|
||||||
|
if stopGap.kicks[nn] then
|
||||||
|
if timer.getTime() < stopGap.kicks[nn] then return end
|
||||||
|
end
|
||||||
|
net.force_player_slot(slot, 0, '')
|
||||||
|
stopGap.kicks[nn] = timer.getTime() + 5 -- avoid too many kicks in 5 seconds
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
--
|
--
|
||||||
-- update
|
-- update
|
||||||
--
|
--
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
stopGap = {}
|
stopGap = {}
|
||||||
stopGap.version = "1.0.10"
|
stopGap.version = "1.1.0"
|
||||||
stopGap.verbose = false
|
stopGap.verbose = false
|
||||||
stopGap.ssbEnabled = true
|
stopGap.ssbEnabled = true
|
||||||
stopGap.ignoreMe = "-sg"
|
stopGap.ignoreMe = "-sg"
|
||||||
@ -7,7 +7,7 @@ stopGap.spIgnore = "-sp" -- only single-player ignored
|
|||||||
stopGap.isMP = false
|
stopGap.isMP = false
|
||||||
stopGap.running = true
|
stopGap.running = true
|
||||||
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
|
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
|
||||||
|
stopGap.kickTheDead = true -- kick players to spectators on death to prevent re-entry issues
|
||||||
|
|
||||||
stopGap.requiredLibs = {
|
stopGap.requiredLibs = {
|
||||||
"dcsCommon",
|
"dcsCommon",
|
||||||
@ -49,6 +49,7 @@ stopGap.requiredLibs = {
|
|||||||
- refresh attribute config zone
|
- refresh attribute config zone
|
||||||
1.0.9 - in line with standalone (optimization not required for DML)
|
1.0.9 - in line with standalone (optimization not required for DML)
|
||||||
1.0.10 - some more verbosity for spIgnore and sgIgnore zones (DML only)
|
1.0.10 - some more verbosity for spIgnore and sgIgnore zones (DML only)
|
||||||
|
1.1.0 - kickTheDead option
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -233,11 +234,11 @@ function stopGap:onEvent(event)
|
|||||||
if not event.id then return end
|
if not event.id then return end
|
||||||
if not event.initiator then return end
|
if not event.initiator then return end
|
||||||
local theUnit = event.initiator
|
local theUnit = event.initiator
|
||||||
|
if (not theUnit.getPlayerName) or (not theUnit:getPlayerName()) then
|
||||||
if event.id == 15 then
|
return
|
||||||
if (not theUnit.getPlayerName) or (not theUnit:getPlayerName()) then
|
end -- no player unit.
|
||||||
return
|
local id = event.id
|
||||||
end -- no player unit.
|
if id == 15 then
|
||||||
local uName = theUnit:getName()
|
local uName = theUnit:getName()
|
||||||
local theGroup = theUnit:getGroup()
|
local theGroup = theUnit:getGroup()
|
||||||
local gName = theGroup:getName()
|
local gName = theGroup:getName()
|
||||||
@ -249,11 +250,31 @@ function stopGap:onEvent(event)
|
|||||||
stopGap.removeStaticGapGroupNamed(gName)
|
stopGap.removeStaticGapGroupNamed(gName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- erase stopGapGUI flag, no longer required, unit
|
-- erase stopGapGUI flag, no longer required, unit
|
||||||
-- is now slotted into
|
-- is now slotted into
|
||||||
trigger.action.setUserFlag("SG"..gName, 0)
|
trigger.action.setUserFlag("SG"..gName, 0)
|
||||||
end
|
end
|
||||||
|
if (id == 9) or (id == 30) or (id == 5) then -- dead, lost, crash
|
||||||
|
local pName = theUnit:getPlayerName()
|
||||||
|
timer.scheduleFunction(stopGap.kickplayer, pName, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
stopGap.kicks = {}
|
||||||
|
function stopGap.kickplayer(args)
|
||||||
|
if not stopGap.kickTheDead then return end
|
||||||
|
local pName = args
|
||||||
|
for i,slot in pairs(net.get_player_list()) do
|
||||||
|
local nn = net.get_name(slot)
|
||||||
|
if nn == pName then
|
||||||
|
if stopGap.kicks[nn] then
|
||||||
|
if timer.getTime() < stopGap.kicks[nn] then return end
|
||||||
|
end
|
||||||
|
net.force_player_slot(slot, 0, '')
|
||||||
|
stopGap.kicks[nn] = timer.getTime() + 5 -- avoid too many kicks in 5 seconds
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -403,6 +424,7 @@ function stopGap.readConfigZone(theZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
stopGap.refreshInterval = theZone:getNumberFromZoneProperty("refresh", -1) -- default: no refresh
|
stopGap.refreshInterval = theZone:getNumberFromZoneProperty("refresh", -1) -- default: no refresh
|
||||||
|
stopGap.kickTheDead = theZone:getBoolFromZoneProperty("kickDead", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
BIN
tutorial & demo missions/demo - rvb BLUE.miz
Normal file
BIN
tutorial & demo missions/demo - rvb BLUE.miz
Normal file
Binary file not shown.
BIN
tutorial & demo missions/demo - rvb RED.miz
Normal file
BIN
tutorial & demo missions/demo - rvb RED.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user