Version 2.2.0

"maybe" for boolean
inBuiltup for csarManager
This commit is contained in:
Christian Franz 2024-03-20 16:10:14 +01:00
parent 6088c4cfa1
commit eb2bef85b8
13 changed files with 214 additions and 81 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
rndFlags = {} rndFlags = {}
rndFlags.version = "2.0.0" rndFlags.version = "2.0.1"
rndFlags.verbose = false rndFlags.verbose = false
rndFlags.requiredLibs = { rndFlags.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -14,7 +14,8 @@ rndFlags.requiredLibs = {
Version History Version History
2.0.0 - dmlZones, OOP 2.0.0 - dmlZones, OOP
2.0.1 - a little less verbosity
--]] --]]
rndFlags.rndGen = {} rndFlags.rndGen = {}
@ -164,7 +165,9 @@ function rndFlags.fire(theZone)
for i=1, pollSize do for i=1, pollSize do
-- check there are still flags left -- check there are still flags left
if #availableFlags < 1 then if #availableFlags < 1 then
trigger.action.outText("+++RND: no flags left in " .. theZone.name .. " in index " .. i, 30) if rndFlags.verbose or theZone.verbose then
trigger.action.outText("+++RND: no flags left in <" .. theZone.name .. "> in index " .. i, 30)
end
theZone.myFlags = {} theZone.myFlags = {}
if theZone.reshuffle then if theZone.reshuffle then
rndFlags.reshuffle(theZone) rndFlags.reshuffle(theZone)
@ -180,7 +183,7 @@ function rndFlags.fire(theZone)
--rndFlags.pollFlag(theFlag, theZone.rndMethod) --rndFlags.pollFlag(theFlag, theZone.rndMethod)
if rndFlags.verbose or theZone.verbose then if rndFlags.verbose or theZone.verbose then
trigger.action.outText("+++RND: polling " .. theFlag .. " with " .. theZone.rndMethod, 30) trigger.action.outText("+++RND: polling <" .. theFlag .. "> with " .. theZone.rndMethod, 30)
end end
theZone:pollFlag(theFlag, theZone.rndMethod) theZone:pollFlag(theFlag, theZone.rndMethod)

View File

@ -1,5 +1,5 @@
cfxZones = {} cfxZones = {}
cfxZones.version = "4.2.0" cfxZones.version = "4.3.0"
-- cf/x zone management module -- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable -- reads dcs zones and makes them accessible and mutable
@ -45,6 +45,7 @@ cfxZones.version = "4.2.0"
- 4.1.1 - evalRemainder() updates - 4.1.1 - evalRemainder() updates
- 4.1.2 - hash property missing warning - 4.1.2 - hash property missing warning
- 4.2.0 - new createRandomPointInPopulatedZone() - 4.2.0 - new createRandomPointInPopulatedZone()
- 4.3.0 - boolean supports maybe, random, rnd, ?
--]]-- --]]--
@ -1618,6 +1619,7 @@ function cfxZones.doPollFlag(theFlag, method, theZone) -- no OOP equivalent
end end
function cfxZones.pollFlag(theFlag, method, theZone) function cfxZones.pollFlag(theFlag, method, theZone)
--trigger.action.outText("enter pollflag for flag <" .. theFlag .. "> of zone <" .. theZone.name .. ">", 30)
local allFlags = {} local allFlags = {}
if dcsCommon.containsString(theFlag, ",") then if dcsCommon.containsString(theFlag, ",") then
if cfxZones.verbose then if cfxZones.verbose then
@ -2429,6 +2431,11 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal)
return theBool return theBool
end end
-- special: return a random value if p == "rnd" or "?" or "maybe"
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
return (math.random(1000) < 500) -- 50:50
end
local theBool = true local theBool = true
-- only go false if exactly no or false or "0" -- only go false if exactly no or false or "0"
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off") theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off")
@ -2455,6 +2462,11 @@ function dmlZone:getBoolFromZoneProperty(theProperty, defaultVal)
return theBool return theBool
end end
-- special: return a random value if p == "rnd" or "?" or "maybe"
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
return (math.random(1000) < 500) -- 50:50
end
local theBool = true local theBool = true
-- only go false if exactly no or false or "0" -- only go false if exactly no or false or "0"
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p ~= "off") theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p ~= "off")

View File

@ -1,5 +1,5 @@
cloneZones = {} cloneZones = {}
cloneZones.version = "2.0.1" cloneZones.version = "2.1.0"
cloneZones.verbose = false cloneZones.verbose = false
cloneZones.requiredLibs = { cloneZones.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -20,8 +20,10 @@ cloneZones.uniqueCounter = 9200000 -- we start group numbering here
cloneZones.lclUniqueCounter = 1 -- zone-local init value, can be config'dHeading cloneZones.lclUniqueCounter = 1 -- zone-local init value, can be config'dHeading
cloneZones.globalCounter = 1 -- module-global count cloneZones.globalCounter = 1 -- module-global count
cloneZones.allClones = {} -- all clones spawned, regularly GC'd cloneZones.allClones = {} -- all clones spawned, regularly GC'd
-- contains DATA blocks!
cloneZones.allCObjects = {} -- all clones objects cloneZones.allCObjects = {} -- all clones objects
cloneZones.despawnPlan = {} -- used with despawnIn
cloneZones.respawnOnGroupID = true cloneZones.respawnOnGroupID = true
@ -40,6 +42,8 @@ cloneZones.respawnOnGroupID = true
2.0.0 - clean-up 2.0.0 - clean-up
2.0.1 - improved empty! logic to account for deferred spawn 2.0.1 - improved empty! logic to account for deferred spawn
when pre-wipe is active when pre-wipe is active
2.1.0 - despawnIn option
- inBuiltup option for rndLoc
--]]-- --]]--
-- --
@ -332,6 +336,10 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
end end
theZone.useAI = theZone:getBoolFromZoneProperty("useAI", true) theZone.useAI = theZone:getBoolFromZoneProperty("useAI", true)
if theZone:hasProperty("despawnIn") then
theZone.despawnInMin, theZone.despawnInMax = theZone:getPositiveRangeFromZoneProperty("despawnIn", 2,2)
end
-- we end with clear plate -- we end with clear plate
end end
@ -1214,6 +1222,20 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
-- SPAWN NOW!!!! -- SPAWN NOW!!!!
theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData) theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
table.insert(spawnedGroups, theGroup) table.insert(spawnedGroups, theGroup)
-- see if this is an auto-despawner
if spawnZone.despawnInMin then
local now = timer.getTime()
local timeLimit = dcsCommon.randomBetween(spawnZone.despawnInMin, spawnZone.despawnInMax)
local info = {}
info.theGroup = theGroup
info.name = theData.name
info.isObject = false
info.timeLimit = now + timeLimit
info.cloneZone = spawnZone
table.insert(cloneZones.despawnPlan, info)
-- trigger.action.outText("+++clne: scheduled auto-despawn for <" .. info.name .. "> in <" .. timeLimit .. "> secs", 30)
end
-- turn off AI if disabled -- turn off AI if disabled
if not rawData.useAI then if not rawData.useAI then
@ -1393,6 +1415,18 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
local theStatic = coalition.addStaticObject(ctry, rawData) local theStatic = coalition.addStaticObject(ctry, rawData)
local newStaticID = tonumber(theStatic:getID()) local newStaticID = tonumber(theStatic:getID())
table.insert(spawnedStatics, theStatic) table.insert(spawnedStatics, theStatic)
if spawnZone.despawnInMin then
local now = timer.getTime()
local timeLimit = dcsCommon.randomBetween(spawnZone.despawnInMin, spawnZone.despawnInMax)
local info = {}
info.theGroup = theStatic
info.name = theData.name
info.isObject = true
info.timeLimit = now + timeLimit
info.cloneZone = spawnZone
table.insert(cloneZones.despawnPlan, info)
-- trigger.action.outText("+++clne: scheduled auto-despawn for OBJECT <" .. info.name .. "> in <" .. timeLimit .. "> secs", 30)
end
-- we don't mix groups with units, so no lookup tables for -- we don't mix groups with units, so no lookup tables for
-- statics -- statics
if newStaticID == rawData.CZTargetID then if newStaticID == rawData.CZTargetID then
@ -1677,7 +1711,7 @@ function cloneZones.update()
local willSpawn = false -- init to false. local willSpawn = false -- init to false.
if aZone:testZoneFlag(aZone.spawnFlag, aZone.cloneTriggerMethod, "lastSpawnValue") then if aZone:testZoneFlag(aZone.spawnFlag, aZone.cloneTriggerMethod, "lastSpawnValue") then
if cloneZones.verbose or aZone.verbose then if cloneZones.verbose or aZone.verbose then
trigger.action.outText("+++clnZ: spawn triggered for <" .. aZone.name .. ">", 30) trigger.action.outText("+++clnZ: spawn triggered for <" .. aZone.name .. "> on flag <" .. aZone.spawnFlag .. ">", 30)
end end
cloneZones.spawnWithCloner(aZone) cloneZones.spawnWithCloner(aZone)
willSpawn = true -- in case prewipe, we delay willSpawn = true -- in case prewipe, we delay
@ -1702,6 +1736,30 @@ function cloneZones.update()
end end
end end
-- now remove all scheduled despawns
local now = timer.getTime()
local filtered = {}
for idx, theInfo in pairs(cloneZones.despawnPlan) do
if theInfo.timeLimit < now then
-- trigger.action.outText("+++clne: auto-despawning <" .. theInfo.name .. ">", 30)
if theInfo.isObject then
-- dealloc static object
local theObject = theInfo.theGroup
if theObject and StaticObject.isExist(theObject) then
StaticObject.destroy(theObject)
end
else
local theGroup = theInfo.theGroup
if theGroup and Group.isExist(theGroup) then
Group.destroy(theGroup)
end
end
else
table.insert(filtered, theInfo)
end
end
cloneZones.despawnPlan = filtered
end end
function cloneZones.doOnStart() function cloneZones.doOnStart()

View File

@ -1,5 +1,5 @@
csarManager = {} csarManager = {}
csarManager.version = "3.2.2" csarManager.version = "3.2.5"
csarManager.ups = 1 csarManager.ups = 1
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
@ -37,6 +37,9 @@ csarManager.ups = 1
3.2.2 - reset helicopter weight on birth 3.2.2 - reset helicopter weight on birth
- cleanup - cleanup
3.2.3 - hardening against *accidental* multi-unit player groups. 3.2.3 - hardening against *accidental* multi-unit player groups.
3.2.4 - pass theZone with missionCreateCB when created from zone
3.2.5 - smoke callbacks
- useRanks option
INTEGRATES AUTOMATICALLY WITH playerScore INTEGRATES AUTOMATICALLY WITH playerScore
@ -79,6 +82,7 @@ csarManager.csarCompleteCB = {}
csarManager.csarCreatedCB = {} csarManager.csarCreatedCB = {}
csarManager.csarRemoveCB = {} csarManager.csarRemoveCB = {}
csarManager.csarPickupCB = {} csarManager.csarPickupCB = {}
csarManager.csarSmokeCB = {}
-- --
-- CREATING A CSAR -- CREATING A CSAR
-- --
@ -168,6 +172,13 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew,
trigger.action.outText("+++csar: 'downed' procced for <" .. name .. ">", 30) trigger.action.outText("+++csar: 'downed' procced for <" .. name .. ">", 30)
end end
end end
if csarManager.useRanks then
-- local ranks = csarManager.ranks -- {"Lt", "Lt", "Lt", "Col", "Cpt", "WO", "WO"}
local myRank = dcsCommon.pickRandom(csarManager.ranks)
name = myRank .. " " .. name
end
if not inRadius then inRadius = csarManager.rescueRadius end if not inRadius then inRadius = csarManager.rescueRadius end
newMission.name = name .. " (ID#" .. csarManager.missionID .. ")" -- make it uuid-capable newMission.name = name .. " (ID#" .. csarManager.missionID .. ")" -- make it uuid-capable
if csarManager.addPrefix then if csarManager.addPrefix then
@ -199,9 +210,9 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew,
return newMission return newMission
end end
function csarManager.addMission(theMission) function csarManager.addMission(theMission, theZone)
table.insert(csarManager.openMissions, theMission) table.insert(csarManager.openMissions, theMission)
csarManager.invokeNewMissionCallbacks(theMission) csarManager.invokeNewMissionCallbacks(theMission, theZone)
end end
function csarManager.removeMission(theMission, pickup) function csarManager.removeMission(theMission, pickup)
@ -1134,6 +1145,13 @@ function csarManager.update() -- every second
-- also pop smoke if not popped already, or more than 5 minutes ago -- also pop smoke if not popped already, or more than 5 minutes ago
if csarManager.useSmoke and (timer.getTime() - csarMission.lastSmokeTime) >= 5 * 60 then if csarManager.useSmoke and (timer.getTime() - csarMission.lastSmokeTime) >= 5 * 60 then
if csarMission.lastSmokeTime < 0 then
-- this is the first time that this mission pops smoke
-- trigger.action.outText("***will invoke smoke cb", 30)
csarManager.invokeSmokeCallbacks(csarMission, uName)
else
--trigger.action.outText("nope smoke's a dope", 30)
end
local smokePoint = dcsCommon.randomPointOnPerimeter( local smokePoint = dcsCommon.randomPointOnPerimeter(
csarManager.smokeDist, csarMission.zone.point.x, csarMission.zone.point.z) csarManager.smokeDist, csarMission.zone.point.x, csarMission.zone.point.z)
dcsCommon.markPointWithSmoke(smokePoint, csarManager.smokeColor) dcsCommon.markPointWithSmoke(smokePoint, csarManager.smokeColor)
@ -1242,7 +1260,7 @@ function csarManager.update() -- every second
-- if currVal ~= theZone.lastCSARVal then -- if currVal ~= theZone.lastCSARVal then
if theZone:testZoneFlag(theZone.startCSAR, theZone.triggerMethod, "lastCSARVal") then if theZone:testZoneFlag(theZone.startCSAR, theZone.triggerMethod, "lastCSARVal") then
local theMission = csarManager.createCSARMissionFromZone(theZone) local theMission = csarManager.createCSARMissionFromZone(theZone)
csarManager.addMission(theMission) csarManager.addMission(theMission, theZone)
--theZone.lastCSARVal = currVal --theZone.lastCSARVal = currVal
if csarManager.verbose or theZone.verbose then if csarManager.verbose or theZone.verbose then
trigger.action.outText("+++csar: started CSAR mission for <" .. theZone.csarName .. ">", 30) trigger.action.outText("+++csar: started CSAR mission for <" .. theZone.csarName .. ">", 30)
@ -1399,7 +1417,13 @@ function csarManager.readCSARZone(theZone)
trigger.action.outText("warning: competing 'onRoad' and 'inPopulated' attributes in zone <" .. theZone.name .. ">. Using 'onRoad'.", 30) trigger.action.outText("warning: competing 'onRoad' and 'inPopulated' attributes in zone <" .. theZone.name .. ">. Using 'onRoad'.", 30)
end end
-- add to list of startable csar
if theZone.startCSAR then
csarManager.addCSARZone(theZone)
end
if (not deferred) then if (not deferred) then
--[[--
local mPoint = theZone:getPoint() local mPoint = theZone:getPoint()
if theZone.rndLoc then mPoint = theZone:createRandomPointInZone() end if theZone.rndLoc then mPoint = theZone:createRandomPointInZone() end
if theZone.onRoad then if theZone.onRoad then
@ -1418,13 +1442,12 @@ function csarManager.readCSARZone(theZone)
theZone.csarMapMarker, theZone.csarMapMarker,
0.1, -- theZone.radius, 0.1, -- theZone.radius,
nil) -- parashoo unit nil) -- parashoo unit
csarManager.addMission(theMission) csarManager.addMission(theMission, theZone)
--]]--
local theMission = csarManager.createCSARMissionFromZone(theZone)
csarManager.addMission(theMission, theZone)
end end
-- add to list of startable csar
if theZone.startCSAR then
csarManager.addCSARZone(theZone)
end
if deferred and not theZone.startCSAR then if deferred and not theZone.startCSAR then
trigger.action.outText("+++csar: warning - CSAR Mission in Zone <" .. theZone.name .. "> can't be started", 30) trigger.action.outText("+++csar: warning - CSAR Mission in Zone <" .. theZone.name .. "> can't be started", 30)
@ -1449,16 +1472,19 @@ function csarManager.invokeCallbacks(theCoalition, success, numRescued, notes, t
-- invoke anyone who wants to know that a group -- invoke anyone who wants to know that a group
-- of people was rescued. -- of people was rescued.
for idx, cb in pairs(csarManager.csarCompleteCB) do for idx, cb in pairs(csarManager.csarCompleteCB) do
-- notes =
-- "KIA" when evacuee is killed (success = false)
-- "success" when mission done (success = true)
-- "lost" when evacuee timed out (success = false)
cb(theCoalition, success, numRescued, notes, theMission) cb(theCoalition, success, numRescued, notes, theMission)
end end
end end
-- mission created cb(theMission) -- mission created cb(theMission)
function csarManager.invokeNewMissionCallbacks(theMission) function csarManager.invokeNewMissionCallbacks(theMission, theZone)
--trigger.action.outText("enter invoke new mission cb", 30)
-- invoke anyone who wants to know that a new mission was created -- invoke anyone who wants to know that a new mission was created
for idx, cb in pairs(csarManager.csarCreatedCB) do for idx, cb in pairs(csarManager.csarCreatedCB) do
cb(theMission) cb(theMission, theZone)
end end
end end
@ -1470,6 +1496,12 @@ function csarManager.invokePickUpCallbacks(theMission)
end end
end end
function csarManager.invokeSmokeCallbacks(theMission, uName)
for idx, cb in pairs(csarManager.csarSmokeCB) do
cb(theMission, uName)
end
end
function csarManager.installCallback(theCB) function csarManager.installCallback(theCB)
table.insert(csarManager.csarCompleteCB, theCB) table.insert(csarManager.csarCompleteCB, theCB)
end end
@ -1482,6 +1514,10 @@ function csarManager.installPickupCallback(theCB)
table.insert(csarManager.csarPickupCB, theCB) table.insert(csarManager.csarPickupCB, theCB)
end end
function csarManager.installSmokeCallback(theCB)
table.insert(csarManager.csarSmokeCB, theCB)
end
function csarManager.readConfigZone() function csarManager.readConfigZone()
csarManager.name = "csarManagerConfig" -- compat with cfxZones csarManager.name = "csarManagerConfig" -- compat with cfxZones
local theZone = cfxZones.getZoneByName("csarManagerConfig") local theZone = cfxZones.getZoneByName("csarManagerConfig")
@ -1545,6 +1581,11 @@ function csarManager.readConfigZone()
end end
csarManager.addPrefix = theZone:getBoolFromZoneProperty("addPrefix", true) csarManager.addPrefix = theZone:getBoolFromZoneProperty("addPrefix", true)
csarManager.useRanks = theZone:getBoolFromZoneProperty("useRanks", false)
local lRanks= theZone:getStringFromZoneProperty("ranks", "Lt, Lt, Lt, Col, Cpt, WO, WO")
local typeArray = dcsCommon.splitString(lRanks, ",")
typeArray = dcsCommon.trimArray(typeArray)
csarManager.ranks = typeArray
csarManager.maxMissions = theZone:getNumberFromZoneProperty("maxMissions", 15) csarManager.maxMissions = theZone:getNumberFromZoneProperty("maxMissions", 15)

View File

@ -1,5 +1,5 @@
factoryZone = {} factoryZone = {}
factoryZone.version = "3.1.0" factoryZone.version = "3.1.1"
factoryZone.verbose = false factoryZone.verbose = false
factoryZone.name = "factoryZone" factoryZone.name = "factoryZone"

View File

@ -1,5 +1,5 @@
groupTracker = {} groupTracker = {}
groupTracker.version = "2.0.0" groupTracker.version = "2.0.1"
groupTracker.verbose = false groupTracker.verbose = false
groupTracker.ups = 1 groupTracker.ups = 1
groupTracker.requiredLibs = { groupTracker.requiredLibs = {
@ -11,6 +11,7 @@ groupTracker.trackers = {}
--[[-- --[[--
Version History Version History
2.0.0 - dmlZones, OOP, clean-up, legacy support 2.0.0 - dmlZones, OOP, clean-up, legacy support
2.0.1 - fix to verbosity, better verbosity
--]]-- --]]--
@ -473,6 +474,9 @@ function groupTracker.update()
-- see if we need to bang on empty! -- see if we need to bang on empty!
local currCount = #theZone.trackedGroups + dcsCommon.getSizeOfTable(theZone.limbo) local currCount = #theZone.trackedGroups + dcsCommon.getSizeOfTable(theZone.limbo)
if theZone.allGoneFlag and currCount == 0 and currCount ~= theZone.lastGroupCount then if theZone.allGoneFlag and currCount == 0 and currCount ~= theZone.lastGroupCount then
if theZone.verbose or groupTracker.verbose then
trigger.action.outText("+++gTrk: all groups for tracker <" .. theZone.name .. "> gone, polling <" .. theZone.allGoneFlag .. ">", 30)
end
cfxZones.pollFlag(theZone.allGoneFlag, theZone.trackerMethod, theZone) cfxZones.pollFlag(theZone.allGoneFlag, theZone.trackerMethod, theZone)
end end
theZone.lastGroupCount = currCount theZone.lastGroupCount = currCount
@ -558,7 +562,7 @@ function groupTracker.trackGroupsInZone(theZone)
for idy, aGroup in pairs(theGroups) do for idy, aGroup in pairs(theGroups) do
groupTracker.addGroupToTracker(aGroup, theTracker) groupTracker.addGroupToTracker(aGroup, theTracker)
if groupTracker.verbose or theZone.verbose then if groupTracker.verbose or theZone.verbose then
trigger.action.outText("+++gTrk-TW: added " .. theGroup:getName() .. " to tracker " .. theName, 30) trigger.action.outText("+++gTrk-TW: added " .. aGroup:getName() .. " to tracker " .. theName, 30)
end end
end end
end end

View File

@ -1,5 +1,5 @@
cfxPlayerScore = {} cfxPlayerScore = {}
cfxPlayerScore.version = "3.0.1" cfxPlayerScore.version = "3.1.0"
cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers
cfxPlayerScore.badSound = "Death BRASS.wav" cfxPlayerScore.badSound = "Death BRASS.wav"
cfxPlayerScore.scoreSound = "Quest Snare 3.wav" cfxPlayerScore.scoreSound = "Quest Snare 3.wav"
@ -13,6 +13,7 @@ cfxPlayerScore.firstSave = true -- to force overwrite
- DCS 2.9 safe - DCS 2.9 safe
3.0.1 - cleanup 3.0.1 - cleanup
3.0.2 - interface with ObjectDestructDetector for scoring scenery objects 3.0.2 - interface with ObjectDestructDetector for scoring scenery objects
3.1.0 - shared data for persistence
--]]-- --]]--
@ -1198,6 +1199,9 @@ function cfxPlayerScore.readConfigZone(theZone)
theZone:setFlagValue(cfxPlayerScore.blueScoreOut, cfxPlayerScore.coalitionScore[2]) theZone:setFlagValue(cfxPlayerScore.blueScoreOut, cfxPlayerScore.coalitionScore[2])
end end
if theZone:hasProperty("sharedData") then
cfxPlayerScore.sharedData = theZone:getStringFromZoneProperty("sharedData", "cfxNameMissing")
end
end end
-- --
@ -1218,15 +1222,15 @@ function cfxPlayerScore.saveData()
featZones[theZone.name] = theFeat featZones[theZone.name] = theFeat
end end
theData.featData = featZones theData.featData = featZones
return theData return theData, cfxPlayerScore.sharedData
end end
function cfxPlayerScore.loadData() function cfxPlayerScore.loadData()
if not persistence then return end if not persistence then return end
local theData = persistence.getSavedDataForModule("cfxPlayerScore") local theData = persistence.getSavedDataForModule("cfxPlayerScore", cfxPlayerScore.sharedData)
if not theData then if not theData then
if cfxPlayerScore.verbose then if cfxPlayerScore.verbose then
trigger.action.outText("+++playerscore: no save date received, skipping.", 30) trigger.action.outText("+++playerscore: no save data received, skipping.", 30)
end end
return return
end end

View File

@ -1,5 +1,5 @@
sequencer = {} sequencer = {}
sequencer.version = "1.0.0" sequencer.version = "2.0.0"
sequencer.verbose = false sequencer.verbose = false
sequencer.requiredLibs = { sequencer.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -8,7 +8,11 @@ sequencer.requiredLibs = {
--[[-- --[[--
Sequencer: pull flags in a sequence with oodles of features Sequencer: pull flags in a sequence with oodles of features
Copyright (c) 2022 by Christian Franz Copyright (c) 2022-24 by Christian Franz
Version History
1.0.0 - initial version
2.0.0 - dmlZones
--]]-- --]]--
sequencer.sequencers = {} sequencer.sequencers = {}
@ -31,12 +35,12 @@ end
-- --
function sequencer.createSequenceWithZone(theZone) function sequencer.createSequenceWithZone(theZone)
local seqRaw = cfxZones.getStringFromZoneProperty(theZone, "sequence!", "none") local seqRaw = theZone:getStringFromZoneProperty("sequence!", "none")
local theFlags = dcsCommon.flagArrayFromString(seqRaw) local theFlags = dcsCommon.flagArrayFromString(seqRaw)
theZone.sequence = theFlags theZone.sequence = theFlags
local interRaw = cfxZones.getStringFromZoneProperty(theZone, "intervals", "86400") local interRaw = theZone:getStringFromZoneProperty("intervals", "86400")
if cfxZones.hasProperty(theZone, "interval") then if theZone:hasProperty("interval") then
interRaw = cfxZones.getStringFromZoneProperty(theZone, "interval", "86400") -- = 24 * 3600 = 24 hours default interval interRaw = theZone:getStringFromZoneProperty("interval", "86400") -- = 24 * 3600 = 24 hours default interval
end end
local theIntervals = dcsCommon.rangeArrayFromString(interRaw, false) local theIntervals = dcsCommon.rangeArrayFromString(interRaw, false)
@ -45,53 +49,52 @@ function sequencer.createSequenceWithZone(theZone)
theZone.seqIndex = 1 -- we start at one theZone.seqIndex = 1 -- we start at one
theZone.intervalIndex = 1 -- here too theZone.intervalIndex = 1 -- here too
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false)
theZone.zeroSequence = cfxZones.getBoolFromZoneProperty(theZone, "zeroSequence", true) theZone.zeroSequence = theZone:getBoolFromZoneProperty("zeroSequence", true)
theZone.seqLoop = cfxZones.getBoolFromZoneProperty(theZone, "loop", false) theZone.seqLoop = theZone:getBoolFromZoneProperty("loop", false)
theZone.seqRunning = false theZone.seqRunning = false
theZone.seqComplete = false theZone.seqComplete = false
theZone.seqStarted = false theZone.seqStarted = false
theZone.timeLimit = 0 -- will be set to when we expire theZone.timeLimit = 0 -- will be set to when we expire
if cfxZones.hasProperty(theZone, "done!") then if theZone:hasProperty("done!") then
theZone.seqDone = cfxZones.getStringFromZoneProperty(theZone, "done!", "<none>") theZone.seqDone = theZone:getStringFromZoneProperty("done!", "<none>")
elseif cfxZones.hasProperty(theZone, "seqDone!") then elseif theZone:hasProperty("seqDone!") then
theZone.seqDone = cfxZones.getStringFromZoneProperty(theZone, "seqDone!", "<none>") theZone.seqDone = theZone:getStringFromZoneProperty("seqDone!", "<none>")
end end
if cfxZones.hasProperty(theZone, "next?") then if theZone:hasProperty("next?") then
theZone.nextSeq = cfxZones.getStringFromZoneProperty(theZone, "next?", "<none>") theZone.nextSeq = theZone:getStringFromZoneProperty("next?", "<none>")
theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq)
end end
if cfxZones.hasProperty(theZone, "startSeq?") then if theZone:hasProperty("startSeq?") then
theZone.startSeq = cfxZones.getStringFromZoneProperty(theZone, "startSeq?", "<none>") theZone.startSeq = theZone:getStringFromZoneProperty("startSeq?", "<none>")
theZone.lastStartSeq = cfxZones.getFlagValue(theZone.startSeq, theZone) theZone.lastStartSeq = theZone:getFlagValue(theZone.startSeq)
--trigger.action.outText("read as " .. theZone.startSeq, 30)
end end
if cfxZones.hasProperty(theZone, "stopSeq?") then if theZone:hasProperty("stopSeq?") then
theZone.stopSeq = cfxZones.getStringFromZoneProperty(theZone, "stopSeq?", "<none>") theZone.stopSeq = theZone:getStringFromZoneProperty("stopSeq?", "<none>")
theZone.lastStopSeq = cfxZones.getFlagValue(theZone.stopSeq, theZone) theZone.lastStopSeq = theZone:getFlagValue(theZone.stopSeq)
end end
if cfxZones.hasProperty(theZone, "resetSeq?") then if theZone:hasProperty("resetSeq?") then
theZone.resetSeq = cfxZones.getStringFromZoneProperty(theZone, "resetSeq?", "<none>") theZone.resetSeq = theZone:getStringFromZoneProperty("resetSeq?", "<none>")
theZone.lastResetSeq = cfxZones.getFlagValue(theZone.resetSeq, theZone) theZone.lastResetSeq = theZone:getFlagValue(theZone.resetSeq)
end end
-- methods -- methods
theZone.seqMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") theZone.seqMethod = theZone:getStringFromZoneProperty("method", "inc")
if cfxZones.hasProperty(theZone, "seqMethod") then if theZone:hasProperty("seqMethod") then
theZone.seqMethod = cfxZones.getStringFromZoneProperty(theZone, "seqMethod", "inc") theZone.seqMethod = theZone:getStringFromZoneProperty("seqMethod", "inc")
end end
theZone.seqTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change") theZone.seqTriggerMethod = theZone:getStringFromZoneProperty("triggerMethod", "change")
if cfxZones.hasProperty(theZone, "seqTriggerMethod") then if theZone:hasProperty("seqTriggerMethod") then
theZone.seqTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "seqTriggerMethod", "change") theZone.seqTriggerMethod = theZone:getStringFromZoneProperty("seqTriggerMethod", "change")
end end
if (not theZone.onStart) and not (theZone.startSeq) then if (not theZone.onStart) and not (theZone.startSeq) then
@ -103,7 +106,7 @@ function sequencer.fire(theZone)
-- time's up. poll flag at index -- time's up. poll flag at index
local theFlag = theZone.sequence[theZone.seqIndex] local theFlag = theZone.sequence[theZone.seqIndex]
if theFlag then if theFlag then
cfxZones.pollFlag(theFlag, theZone.seqMethod, theZone) theZone:pollFlag(theFlag, theZone.seqMethod)
if theZone.verbose or sequencer.verbose then if theZone.verbose or sequencer.verbose then
trigger.action.outText("+++seq: triggering flag <" .. theFlag .. "> for index <" .. theZone.seqIndex .. "> in sequence <" .. theZone.name .. ">", 30) trigger.action.outText("+++seq: triggering flag <" .. theFlag .. "> for index <" .. theZone.seqIndex .. "> in sequence <" .. theZone.name .. ">", 30)
end end
@ -160,7 +163,7 @@ function sequencer.continue(theZone)
-- reset any lingering 'next' flags so they don't -- reset any lingering 'next' flags so they don't
-- trigger a newly started sequence -- trigger a newly started sequence
if theZone.nextSeq then if theZone.nextSeq then
theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq)
end end
if not theZone.seqStarted then if not theZone.seqStarted then
@ -204,14 +207,13 @@ function sequencer.update()
for idx, theZone in pairs(sequencer.sequencers) do for idx, theZone in pairs(sequencer.sequencers) do
-- see if reset was pulled -- see if reset was pulled
if theZone.resetSeq and cfxZones.testZoneFlag(theZone, theZone.resetSeq, theZone.seqTriggerMethod, "lastResetSeq") then if theZone.resetSeq and theZone:testZoneFlag(theZone.resetSeq, theZone.seqTriggerMethod, "lastResetSeq") then
sequencer.reset(theZone) sequencer.reset(theZone)
end end
--trigger.action.outText("have as " .. theZone.startSeq, 30)
-- first, check if we need to pause or continue -- first, check if we need to pause or continue
if (not theZone.seqRunning) and theZone.startSeq and if (not theZone.seqRunning) and theZone.startSeq and
cfxZones.testZoneFlag(theZone, theZone.startSeq, theZone.seqTriggerMethod, "lastStartSeq") then theZone:testZoneFlag(theZone.startSeq, theZone.seqTriggerMethod, "lastStartSeq") then
sequencer.continue(theZone) sequencer.continue(theZone)
if theZone.verbose or sequencer.verbose then if theZone.verbose or sequencer.verbose then
trigger.action.outText("+++seq: continuing sequencer <" .. theZone.name .. ">", 30) trigger.action.outText("+++seq: continuing sequencer <" .. theZone.name .. ">", 30)
@ -220,19 +222,19 @@ function sequencer.update()
-- synch the start flag so we don't immediately trigger -- synch the start flag so we don't immediately trigger
-- when it starts -- when it starts
if theZone.startSeq then if theZone.startSeq then
theZone.lastStartSeq = cfxZones.getFlagValue(theZone.startSeq, theZone) theZone.lastStartSeq = theZone:getFlagValue(theZone.startSeq)
end end
end end
if theZone.seqRunning and theZone.stopSeq and if theZone.seqRunning and theZone.stopSeq and
cfxZones.testZoneFlag(theZone, theZone.stopSeq, theZone.seqTriggerMethod, "lastStopSeq") then theZone:testZoneFlag(theZone.stopSeq, theZone.seqTriggerMethod, "lastStopSeq") then
sequencer.pause(theZone) sequencer.pause(theZone)
if theZone.verbose or sequencer.verbose then if theZone.verbose or sequencer.verbose then
trigger.action.outText("+++seq: pausing sequencer <" .. theZone.name .. ">", 30) trigger.action.outText("+++seq: pausing sequencer <" .. theZone.name .. ">", 30)
end end
else else
if theZone.stopSeq then if theZone.stopSeq then
theZone.lastStopSeq = cfxZones.getFlagValue(theZone.stopSeq, theZone) theZone.lastStopSeq = theZone:getFlagValue(theZone.stopSeq)
end end
end end
@ -241,7 +243,7 @@ function sequencer.update()
-- check if we have received a 'next' signal -- check if we have received a 'next' signal
local doNext = false local doNext = false
if theZone.nextSeq then if theZone.nextSeq then
doNext = cfxZones.testZoneFlag(theZone, theZone.nextSeq, theZone.seqTriggerMethod, "lastNextSeq") doNext = theZone:testZoneFlag(theZone.nextSeq, theZone.seqTriggerMethod, "lastNextSeq")
if doNext and (sequencer.verbose or theZone.verbose) then if doNext and (sequencer.verbose or theZone.verbose) then
trigger.action.outText("+++seq: 'next' command received for sequencer <" .. theZone.name .. "> on <" .. theZone.nextSeq .. ">", 30) trigger.action.outText("+++seq: 'next' command received for sequencer <" .. theZone.name .. "> on <" .. theZone.nextSeq .. ">", 30)
end end
@ -251,7 +253,7 @@ function sequencer.update()
if doNext or (theZone.timeLimit < now) then if doNext or (theZone.timeLimit < now) then
-- we are timed out or triggered! -- we are timed out or triggered!
if theZone.nextSeq then if theZone.nextSeq then
theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq)
end end
sequencer.fire(theZone) sequencer.fire(theZone)
sequencer.advanceInterval(theZone) sequencer.advanceInterval(theZone)
@ -260,7 +262,7 @@ function sequencer.update()
sequencer.startWaitCycle(theZone) sequencer.startWaitCycle(theZone)
else else
if theZone.seqDone then if theZone.seqDone then
cfxZones.pollFlag(theZone.seqDone, theZone.seqMethod, theZone) theZone:pollFlag(theZone.seqDone, theZone.seqMethod)
if theZone.verbose or sequencer.verbose then if theZone.verbose or sequencer.verbose then
trigger.action.outText("+++seq: banging done! flag <" .. theZone.seqDone .. "> for sequence <" .. theZone.name .. ">", 30) trigger.action.outText("+++seq: banging done! flag <" .. theZone.seqDone .. "> for sequence <" .. theZone.name .. ">", 30)
end end
@ -364,13 +366,10 @@ function sequencer.readConfigZone()
-- note: must match exactly!!!! -- note: must match exactly!!!!
local theZone = cfxZones.getZoneByName("sequencerConfig") local theZone = cfxZones.getZoneByName("sequencerConfig")
if not theZone then if not theZone then
theZone = cfxZones.createSimpleZone("sequencerConfig") theZone = cfxZones.createSimpleZone("sequencerConfig")
if sequencer.verbose then
trigger.action.outText("***RND: NO config zone!", 30)
end
end end
sequencer.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) sequencer.verbose = theZone.verbose
if sequencer.verbose then if sequencer.verbose then
trigger.action.outText("***RND: read config", 30) trigger.action.outText("***RND: read config", 30)

View File

@ -1,5 +1,5 @@
stopGap = {} stopGap = {}
stopGap.version = "1.1.0 STANDALONE" stopGap.version = "1.1.1 STANDALONE"
stopGap.verbose = false stopGap.verbose = false
stopGap.ssbEnabled = true stopGap.ssbEnabled = true
stopGap.ignoreMe = "-sg" stopGap.ignoreMe = "-sg"
@ -36,7 +36,8 @@ stopGap.kickTheDead = true -- kick players to spectators on death to prevent re-
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 1.1.0 - kickTheDead option
1.1.1 - filter "from runway" clients
--]]-- --]]--
stopGap.standInGroups ={} stopGap.standInGroups ={}
@ -131,6 +132,7 @@ function stopGap.isGroundStart(theGroup)
if action == "Fly Over Point" then return false end if action == "Fly Over Point" then return false end
if action == "Turning Point" then return false end if action == "Turning Point" then return false end
if action == "Landing" then return false end if action == "Landing" then return false end
if action == "From Runway" then return false end
-- looks like aircraft is on the ground -- looks like aircraft is on the ground
-- but is it in water (carrier)? -- but is it in water (carrier)?
local u1 = theGroup.units[1] local u1 = theGroup.units[1]

View File

@ -1,5 +1,5 @@
stopGap = {} stopGap = {}
stopGap.version = "1.1.0" stopGap.version = "1.1.1"
stopGap.verbose = false stopGap.verbose = false
stopGap.ssbEnabled = true stopGap.ssbEnabled = true
stopGap.ignoreMe = "-sg" stopGap.ignoreMe = "-sg"
@ -50,6 +50,7 @@ stopGap.requiredLibs = {
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 1.1.0 - kickTheDead option
1.1.1 - filter "from runway" clients
--]]-- --]]--
@ -90,6 +91,7 @@ function stopGap.isGroundStart(theGroup)
if action == "Fly Over Point" then return false end if action == "Fly Over Point" then return false end
if action == "Turning Point" then return false end if action == "Turning Point" then return false end
if action == "Landing" then return false end if action == "Landing" then return false end
if action == "From Runway" then return false end
-- looks like aircraft is on the ground -- looks like aircraft is on the ground
-- but is it in water (carrier)? -- but is it in water (carrier)?
local u1 = theGroup.units[1] local u1 = theGroup.units[1]

View File

@ -1,5 +1,5 @@
valet = {} valet = {}
valet.version = "1.0.3" valet.version = "1.1.0"
valet.verbose = false valet.verbose = false
valet.requiredLibs = { valet.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -13,7 +13,7 @@ valet.valets = {}
1.0.1 - typos in verbosity corrected 1.0.1 - typos in verbosity corrected
1.0.2 - also scan birth events 1.0.2 - also scan birth events
1.0.3 - outSoundFile now working correctly 1.0.3 - outSoundFile now working correctly
1.1.0 - hysteresis is now time-based (10 seconds)
--]]-- --]]--
function valet.addValet(theZone) function valet.addValet(theZone)
@ -236,6 +236,8 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers)
p.y = 0 -- sanity first p.y = 0 -- sanity first
local maxRad = theZone.maxRadius local maxRad = theZone.maxRadius
-- set up hysteresis -- set up hysteresis
-- new hysteresis: 10 seconds outside time
local now = timer.getTime()
local outside = maxRad * 1.2 local outside = maxRad * 1.2
for playerName, aPlayerUnit in pairs (allPlayers) do for playerName, aPlayerUnit in pairs (allPlayers) do
local unitName = aPlayerUnit:getName() local unitName = aPlayerUnit:getName()
@ -269,6 +271,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers)
if not theDesc then if not theDesc then
theDesc = {} theDesc = {}
theDesc.currentlyIn = false theDesc.currentlyIn = false
theDesc.lastTimeIn = 99999999
theDesc.greets = 0 theDesc.greets = 0
theDesc.byes = 0 theDesc.byes = 0
theDesc.unitName = unitName theDesc.unitName = unitName
@ -278,6 +281,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers)
else else
-- ha!!! player changed planes! -- ha!!! player changed planes!
theDesc.currentlyIn = false theDesc.currentlyIn = false
theDesc.lastTimeIn = 99999999
theDesc.greets = 0 theDesc.greets = 0
theDesc.byes = 0 theDesc.byes = 0
theDesc.unitName = unitName theDesc.unitName = unitName
@ -289,11 +293,14 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers)
valet.greetPlayer(playerName, aPlayerUnit, theZone, theDesc) valet.greetPlayer(playerName, aPlayerUnit, theZone, theDesc)
end end
elseif (dist > outside) and theDesc then theDesc.lastTimeIn = now
elseif theDesc and now > theDesc.lastTimeIn + 10 then --(dist > outside) and theDesc then
if theDesc.unitName == unitName then if theDesc.unitName == unitName then
else else
-- ha!!! player changed planes! -- ha!!! player changed planes!
theDesc.currentlyIn = false theDesc.currentlyIn = false
theDesc.lastTimeIn = 99999999
theDesc.greets = 0 theDesc.greets = 0
theDesc.byes = 0 theDesc.byes = 0
theDesc.unitName = unitName theDesc.unitName = unitName
@ -306,6 +313,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers)
else else
-- was outside before -- was outside before
end end
theDesc.lastTimeIn = 99999999
else else
-- we are in the twilight zone (hysteresis). Do nothing. -- we are in the twilight zone (hysteresis). Do nothing.
end end