diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index c14558c..755992f 100644 Binary files a/Doc/DML Documentation.pdf and b/Doc/DML Documentation.pdf differ diff --git a/Doc/DML Quick Reference.pdf b/Doc/DML Quick Reference.pdf index c9c4eca..598a566 100644 Binary files a/Doc/DML Quick Reference.pdf and b/Doc/DML Quick Reference.pdf differ diff --git a/modules/RNDFlags.lua b/modules/RNDFlags.lua index 9b9696f..79bbc74 100644 --- a/modules/RNDFlags.lua +++ b/modules/RNDFlags.lua @@ -1,5 +1,5 @@ rndFlags = {} -rndFlags.version = "2.0.0" +rndFlags.version = "2.0.1" rndFlags.verbose = false rndFlags.requiredLibs = { "dcsCommon", -- always @@ -14,7 +14,8 @@ rndFlags.requiredLibs = { Version History 2.0.0 - dmlZones, OOP - + 2.0.1 - a little less verbosity + --]] rndFlags.rndGen = {} @@ -164,7 +165,9 @@ function rndFlags.fire(theZone) for i=1, pollSize do -- check there are still flags left 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 = {} if theZone.reshuffle then rndFlags.reshuffle(theZone) @@ -180,7 +183,7 @@ function rndFlags.fire(theZone) --rndFlags.pollFlag(theFlag, theZone.rndMethod) 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 theZone:pollFlag(theFlag, theZone.rndMethod) diff --git a/modules/cfxZones.lua b/modules/cfxZones.lua index 5c23d6e..992daab 100644 --- a/modules/cfxZones.lua +++ b/modules/cfxZones.lua @@ -1,5 +1,5 @@ cfxZones = {} -cfxZones.version = "4.2.0" +cfxZones.version = "4.3.0" -- cf/x zone management module -- 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.2 - hash property missing warning - 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 function cfxZones.pollFlag(theFlag, method, theZone) + --trigger.action.outText("enter pollflag for flag <" .. theFlag .. "> of zone <" .. theZone.name .. ">", 30) local allFlags = {} if dcsCommon.containsString(theFlag, ",") then if cfxZones.verbose then @@ -2429,6 +2431,11 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal) return theBool 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 -- only go false if exactly no or false or "0" theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off") @@ -2455,6 +2462,11 @@ function dmlZone:getBoolFromZoneProperty(theProperty, defaultVal) return theBool 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 -- only go false if exactly no or false or "0" theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p ~= "off") diff --git a/modules/cloneZone.lua b/modules/cloneZone.lua index 8529da8..0a973d4 100644 --- a/modules/cloneZone.lua +++ b/modules/cloneZone.lua @@ -1,5 +1,5 @@ cloneZones = {} -cloneZones.version = "2.0.1" +cloneZones.version = "2.1.0" cloneZones.verbose = false cloneZones.requiredLibs = { "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.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.despawnPlan = {} -- used with despawnIn cloneZones.respawnOnGroupID = true @@ -40,6 +42,8 @@ cloneZones.respawnOnGroupID = true 2.0.0 - clean-up 2.0.1 - improved empty! logic to account for deferred spawn 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 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 end @@ -1214,6 +1222,20 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone) -- SPAWN NOW!!!! theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData) 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 if not rawData.useAI then @@ -1393,6 +1415,18 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone) local theStatic = coalition.addStaticObject(ctry, rawData) local newStaticID = tonumber(theStatic:getID()) 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 -- statics if newStaticID == rawData.CZTargetID then @@ -1677,7 +1711,7 @@ function cloneZones.update() local willSpawn = false -- init to false. if aZone:testZoneFlag(aZone.spawnFlag, aZone.cloneTriggerMethod, "lastSpawnValue") 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 cloneZones.spawnWithCloner(aZone) willSpawn = true -- in case prewipe, we delay @@ -1702,6 +1736,30 @@ function cloneZones.update() 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 function cloneZones.doOnStart() diff --git a/modules/csarManager2.lua b/modules/csarManager2.lua index 401c9aa..c950f88 100644 --- a/modules/csarManager2.lua +++ b/modules/csarManager2.lua @@ -1,5 +1,5 @@ csarManager = {} -csarManager.version = "3.2.2" +csarManager.version = "3.2.5" csarManager.ups = 1 --[[-- VERSION HISTORY @@ -37,6 +37,9 @@ csarManager.ups = 1 3.2.2 - reset helicopter weight on birth - cleanup 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 @@ -79,6 +82,7 @@ csarManager.csarCompleteCB = {} csarManager.csarCreatedCB = {} csarManager.csarRemoveCB = {} csarManager.csarPickupCB = {} +csarManager.csarSmokeCB = {} -- -- CREATING A CSAR -- @@ -168,6 +172,13 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew, trigger.action.outText("+++csar: 'downed' procced for <" .. name .. ">", 30) 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 newMission.name = name .. " (ID#" .. csarManager.missionID .. ")" -- make it uuid-capable if csarManager.addPrefix then @@ -199,9 +210,9 @@ function csarManager.createCSARMissionData(point, theSide, freq, name, numCrew, return newMission end -function csarManager.addMission(theMission) +function csarManager.addMission(theMission, theZone) table.insert(csarManager.openMissions, theMission) - csarManager.invokeNewMissionCallbacks(theMission) + csarManager.invokeNewMissionCallbacks(theMission, theZone) end 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 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( csarManager.smokeDist, csarMission.zone.point.x, csarMission.zone.point.z) dcsCommon.markPointWithSmoke(smokePoint, csarManager.smokeColor) @@ -1242,7 +1260,7 @@ function csarManager.update() -- every second -- if currVal ~= theZone.lastCSARVal then if theZone:testZoneFlag(theZone.startCSAR, theZone.triggerMethod, "lastCSARVal") then local theMission = csarManager.createCSARMissionFromZone(theZone) - csarManager.addMission(theMission) + csarManager.addMission(theMission, theZone) --theZone.lastCSARVal = currVal if csarManager.verbose or theZone.verbose then 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) end + -- add to list of startable csar + if theZone.startCSAR then + csarManager.addCSARZone(theZone) + end + if (not deferred) then + --[[-- local mPoint = theZone:getPoint() if theZone.rndLoc then mPoint = theZone:createRandomPointInZone() end if theZone.onRoad then @@ -1418,13 +1442,12 @@ function csarManager.readCSARZone(theZone) theZone.csarMapMarker, 0.1, -- theZone.radius, nil) -- parashoo unit - csarManager.addMission(theMission) + csarManager.addMission(theMission, theZone) +--]]-- + local theMission = csarManager.createCSARMissionFromZone(theZone) + csarManager.addMission(theMission, theZone) end - -- add to list of startable csar - if theZone.startCSAR then - csarManager.addCSARZone(theZone) - end if deferred and not theZone.startCSAR then 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 -- of people was rescued. 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) end end -- mission created cb(theMission) -function csarManager.invokeNewMissionCallbacks(theMission) ---trigger.action.outText("enter invoke new mission cb", 30) +function csarManager.invokeNewMissionCallbacks(theMission, theZone) -- invoke anyone who wants to know that a new mission was created for idx, cb in pairs(csarManager.csarCreatedCB) do - cb(theMission) + cb(theMission, theZone) end end @@ -1470,6 +1496,12 @@ function csarManager.invokePickUpCallbacks(theMission) end end +function csarManager.invokeSmokeCallbacks(theMission, uName) + for idx, cb in pairs(csarManager.csarSmokeCB) do + cb(theMission, uName) + end +end + function csarManager.installCallback(theCB) table.insert(csarManager.csarCompleteCB, theCB) end @@ -1482,6 +1514,10 @@ function csarManager.installPickupCallback(theCB) table.insert(csarManager.csarPickupCB, theCB) end +function csarManager.installSmokeCallback(theCB) + table.insert(csarManager.csarSmokeCB, theCB) +end + function csarManager.readConfigZone() csarManager.name = "csarManagerConfig" -- compat with cfxZones local theZone = cfxZones.getZoneByName("csarManagerConfig") @@ -1545,6 +1581,11 @@ function csarManager.readConfigZone() end 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) diff --git a/modules/factoryZone.lua b/modules/factoryZone.lua index 4e3ea75..b3b2c8a 100644 --- a/modules/factoryZone.lua +++ b/modules/factoryZone.lua @@ -1,5 +1,5 @@ factoryZone = {} -factoryZone.version = "3.1.0" +factoryZone.version = "3.1.1" factoryZone.verbose = false factoryZone.name = "factoryZone" diff --git a/modules/groupTrackers.lua b/modules/groupTrackers.lua index 16e1045..58b32c6 100644 --- a/modules/groupTrackers.lua +++ b/modules/groupTrackers.lua @@ -1,5 +1,5 @@ groupTracker = {} -groupTracker.version = "2.0.0" +groupTracker.version = "2.0.1" groupTracker.verbose = false groupTracker.ups = 1 groupTracker.requiredLibs = { @@ -11,6 +11,7 @@ groupTracker.trackers = {} --[[-- Version History 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! local currCount = #theZone.trackedGroups + dcsCommon.getSizeOfTable(theZone.limbo) 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) end theZone.lastGroupCount = currCount @@ -558,7 +562,7 @@ function groupTracker.trackGroupsInZone(theZone) for idy, aGroup in pairs(theGroups) do groupTracker.addGroupToTracker(aGroup, theTracker) 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 diff --git a/modules/playerScore.lua b/modules/playerScore.lua index 77c97fe..97ac4bd 100644 --- a/modules/playerScore.lua +++ b/modules/playerScore.lua @@ -1,5 +1,5 @@ cfxPlayerScore = {} -cfxPlayerScore.version = "3.0.1" +cfxPlayerScore.version = "3.1.0" cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers cfxPlayerScore.badSound = "Death BRASS.wav" cfxPlayerScore.scoreSound = "Quest Snare 3.wav" @@ -13,6 +13,7 @@ cfxPlayerScore.firstSave = true -- to force overwrite - DCS 2.9 safe 3.0.1 - cleanup 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]) end + if theZone:hasProperty("sharedData") then + cfxPlayerScore.sharedData = theZone:getStringFromZoneProperty("sharedData", "cfxNameMissing") + end end -- @@ -1218,15 +1222,15 @@ function cfxPlayerScore.saveData() featZones[theZone.name] = theFeat end theData.featData = featZones - return theData + return theData, cfxPlayerScore.sharedData end function cfxPlayerScore.loadData() if not persistence then return end - local theData = persistence.getSavedDataForModule("cfxPlayerScore") + local theData = persistence.getSavedDataForModule("cfxPlayerScore", cfxPlayerScore.sharedData) if not theData 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 return end diff --git a/modules/sequencer.lua b/modules/sequencer.lua index 418140f..e47516f 100644 --- a/modules/sequencer.lua +++ b/modules/sequencer.lua @@ -1,5 +1,5 @@ sequencer = {} -sequencer.version = "1.0.0" +sequencer.version = "2.0.0" sequencer.verbose = false sequencer.requiredLibs = { "dcsCommon", -- always @@ -8,7 +8,11 @@ sequencer.requiredLibs = { --[[-- 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 = {} @@ -31,12 +35,12 @@ end -- function sequencer.createSequenceWithZone(theZone) - local seqRaw = cfxZones.getStringFromZoneProperty(theZone, "sequence!", "none") + local seqRaw = theZone:getStringFromZoneProperty("sequence!", "none") local theFlags = dcsCommon.flagArrayFromString(seqRaw) theZone.sequence = theFlags - local interRaw = cfxZones.getStringFromZoneProperty(theZone, "intervals", "86400") - if cfxZones.hasProperty(theZone, "interval") then - interRaw = cfxZones.getStringFromZoneProperty(theZone, "interval", "86400") -- = 24 * 3600 = 24 hours default interval + local interRaw = theZone:getStringFromZoneProperty("intervals", "86400") + if theZone:hasProperty("interval") then + interRaw = theZone:getStringFromZoneProperty("interval", "86400") -- = 24 * 3600 = 24 hours default interval end local theIntervals = dcsCommon.rangeArrayFromString(interRaw, false) @@ -45,53 +49,52 @@ function sequencer.createSequenceWithZone(theZone) theZone.seqIndex = 1 -- we start at one theZone.intervalIndex = 1 -- here too - theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) - theZone.zeroSequence = cfxZones.getBoolFromZoneProperty(theZone, "zeroSequence", true) + theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false) + theZone.zeroSequence = theZone:getBoolFromZoneProperty("zeroSequence", true) - theZone.seqLoop = cfxZones.getBoolFromZoneProperty(theZone, "loop", false) + theZone.seqLoop = theZone:getBoolFromZoneProperty("loop", false) theZone.seqRunning = false theZone.seqComplete = false theZone.seqStarted = false theZone.timeLimit = 0 -- will be set to when we expire - if cfxZones.hasProperty(theZone, "done!") then - theZone.seqDone = cfxZones.getStringFromZoneProperty(theZone, "done!", "") - elseif cfxZones.hasProperty(theZone, "seqDone!") then - theZone.seqDone = cfxZones.getStringFromZoneProperty(theZone, "seqDone!", "") + if theZone:hasProperty("done!") then + theZone.seqDone = theZone:getStringFromZoneProperty("done!", "") + elseif theZone:hasProperty("seqDone!") then + theZone.seqDone = theZone:getStringFromZoneProperty("seqDone!", "") end - if cfxZones.hasProperty(theZone, "next?") then - theZone.nextSeq = cfxZones.getStringFromZoneProperty(theZone, "next?", "") - theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) + if theZone:hasProperty("next?") then + theZone.nextSeq = theZone:getStringFromZoneProperty("next?", "") + theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq) end - if cfxZones.hasProperty(theZone, "startSeq?") then - theZone.startSeq = cfxZones.getStringFromZoneProperty(theZone, "startSeq?", "") - theZone.lastStartSeq = cfxZones.getFlagValue(theZone.startSeq, theZone) - --trigger.action.outText("read as " .. theZone.startSeq, 30) + if theZone:hasProperty("startSeq?") then + theZone.startSeq = theZone:getStringFromZoneProperty("startSeq?", "") + theZone.lastStartSeq = theZone:getFlagValue(theZone.startSeq) end - if cfxZones.hasProperty(theZone, "stopSeq?") then - theZone.stopSeq = cfxZones.getStringFromZoneProperty(theZone, "stopSeq?", "") - theZone.lastStopSeq = cfxZones.getFlagValue(theZone.stopSeq, theZone) + if theZone:hasProperty("stopSeq?") then + theZone.stopSeq = theZone:getStringFromZoneProperty("stopSeq?", "") + theZone.lastStopSeq = theZone:getFlagValue(theZone.stopSeq) end - if cfxZones.hasProperty(theZone, "resetSeq?") then - theZone.resetSeq = cfxZones.getStringFromZoneProperty(theZone, "resetSeq?", "") - theZone.lastResetSeq = cfxZones.getFlagValue(theZone.resetSeq, theZone) + if theZone:hasProperty("resetSeq?") then + theZone.resetSeq = theZone:getStringFromZoneProperty("resetSeq?", "") + theZone.lastResetSeq = theZone:getFlagValue(theZone.resetSeq) end -- methods - theZone.seqMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") - if cfxZones.hasProperty(theZone, "seqMethod") then - theZone.seqMethod = cfxZones.getStringFromZoneProperty(theZone, "seqMethod", "inc") + theZone.seqMethod = theZone:getStringFromZoneProperty("method", "inc") + if theZone:hasProperty("seqMethod") then + theZone.seqMethod = theZone:getStringFromZoneProperty("seqMethod", "inc") end - theZone.seqTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change") - if cfxZones.hasProperty(theZone, "seqTriggerMethod") then - theZone.seqTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "seqTriggerMethod", "change") + theZone.seqTriggerMethod = theZone:getStringFromZoneProperty("triggerMethod", "change") + if theZone:hasProperty("seqTriggerMethod") then + theZone.seqTriggerMethod = theZone:getStringFromZoneProperty("seqTriggerMethod", "change") end if (not theZone.onStart) and not (theZone.startSeq) then @@ -103,7 +106,7 @@ function sequencer.fire(theZone) -- time's up. poll flag at index local theFlag = theZone.sequence[theZone.seqIndex] if theFlag then - cfxZones.pollFlag(theFlag, theZone.seqMethod, theZone) + theZone:pollFlag(theFlag, theZone.seqMethod) if theZone.verbose or sequencer.verbose then trigger.action.outText("+++seq: triggering flag <" .. theFlag .. "> for index <" .. theZone.seqIndex .. "> in sequence <" .. theZone.name .. ">", 30) end @@ -160,7 +163,7 @@ function sequencer.continue(theZone) -- reset any lingering 'next' flags so they don't -- trigger a newly started sequence if theZone.nextSeq then - theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) + theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq) end if not theZone.seqStarted then @@ -204,14 +207,13 @@ function sequencer.update() for idx, theZone in pairs(sequencer.sequencers) do -- 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) end - --trigger.action.outText("have as " .. theZone.startSeq, 30) -- first, check if we need to pause or continue 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) if theZone.verbose or sequencer.verbose then 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 -- when it starts if theZone.startSeq then - theZone.lastStartSeq = cfxZones.getFlagValue(theZone.startSeq, theZone) + theZone.lastStartSeq = theZone:getFlagValue(theZone.startSeq) end end 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) if theZone.verbose or sequencer.verbose then trigger.action.outText("+++seq: pausing sequencer <" .. theZone.name .. ">", 30) end else if theZone.stopSeq then - theZone.lastStopSeq = cfxZones.getFlagValue(theZone.stopSeq, theZone) + theZone.lastStopSeq = theZone:getFlagValue(theZone.stopSeq) end end @@ -241,7 +243,7 @@ function sequencer.update() -- check if we have received a 'next' signal local doNext = false 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 trigger.action.outText("+++seq: 'next' command received for sequencer <" .. theZone.name .. "> on <" .. theZone.nextSeq .. ">", 30) end @@ -251,7 +253,7 @@ function sequencer.update() if doNext or (theZone.timeLimit < now) then -- we are timed out or triggered! if theZone.nextSeq then - theZone.lastNextSeq = cfxZones.getFlagValue(theZone.nextSeq, theZone) + theZone.lastNextSeq = theZone:getFlagValue(theZone.nextSeq) end sequencer.fire(theZone) sequencer.advanceInterval(theZone) @@ -260,7 +262,7 @@ function sequencer.update() sequencer.startWaitCycle(theZone) else if theZone.seqDone then - cfxZones.pollFlag(theZone.seqDone, theZone.seqMethod, theZone) + theZone:pollFlag(theZone.seqDone, theZone.seqMethod) if theZone.verbose or sequencer.verbose then trigger.action.outText("+++seq: banging done! flag <" .. theZone.seqDone .. "> for sequence <" .. theZone.name .. ">", 30) end @@ -364,13 +366,10 @@ function sequencer.readConfigZone() -- note: must match exactly!!!! local theZone = cfxZones.getZoneByName("sequencerConfig") if not theZone then - theZone = cfxZones.createSimpleZone("sequencerConfig") - if sequencer.verbose then - trigger.action.outText("***RND: NO config zone!", 30) - end + theZone = cfxZones.createSimpleZone("sequencerConfig") end - sequencer.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) + sequencer.verbose = theZone.verbose if sequencer.verbose then trigger.action.outText("***RND: read config", 30) diff --git a/modules/stopGaps standalone.lua b/modules/stopGaps standalone.lua index 86f009f..84db1e4 100644 --- a/modules/stopGaps standalone.lua +++ b/modules/stopGaps standalone.lua @@ -1,5 +1,5 @@ stopGap = {} -stopGap.version = "1.1.0 STANDALONE" +stopGap.version = "1.1.1 STANDALONE" stopGap.verbose = false stopGap.ssbEnabled = true 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.9 - optimization when turning on stopgap 1.1.0 - kickTheDead option - + 1.1.1 - filter "from runway" clients + --]]-- stopGap.standInGroups ={} @@ -131,6 +132,7 @@ function stopGap.isGroundStart(theGroup) if action == "Fly Over Point" then return false end if action == "Turning Point" 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 -- but is it in water (carrier)? local u1 = theGroup.units[1] diff --git a/modules/stopGaps.lua b/modules/stopGaps.lua index 46984d3..0e169ee 100644 --- a/modules/stopGaps.lua +++ b/modules/stopGaps.lua @@ -1,5 +1,5 @@ stopGap = {} -stopGap.version = "1.1.0" +stopGap.version = "1.1.1" stopGap.verbose = false stopGap.ssbEnabled = true stopGap.ignoreMe = "-sg" @@ -50,6 +50,7 @@ stopGap.requiredLibs = { 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.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 == "Turning Point" 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 -- but is it in water (carrier)? local u1 = theGroup.units[1] diff --git a/modules/valet.lua b/modules/valet.lua index 4099ab3..f4f2fea 100644 --- a/modules/valet.lua +++ b/modules/valet.lua @@ -1,5 +1,5 @@ valet = {} -valet.version = "1.0.3" +valet.version = "1.1.0" valet.verbose = false valet.requiredLibs = { "dcsCommon", -- always @@ -13,7 +13,7 @@ valet.valets = {} 1.0.1 - typos in verbosity corrected 1.0.2 - also scan birth events 1.0.3 - outSoundFile now working correctly - + 1.1.0 - hysteresis is now time-based (10 seconds) --]]-- function valet.addValet(theZone) @@ -236,6 +236,8 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers) p.y = 0 -- sanity first local maxRad = theZone.maxRadius -- set up hysteresis + -- new hysteresis: 10 seconds outside time + local now = timer.getTime() local outside = maxRad * 1.2 for playerName, aPlayerUnit in pairs (allPlayers) do local unitName = aPlayerUnit:getName() @@ -269,6 +271,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers) if not theDesc then theDesc = {} theDesc.currentlyIn = false + theDesc.lastTimeIn = 99999999 theDesc.greets = 0 theDesc.byes = 0 theDesc.unitName = unitName @@ -278,6 +281,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers) else -- ha!!! player changed planes! theDesc.currentlyIn = false + theDesc.lastTimeIn = 99999999 theDesc.greets = 0 theDesc.byes = 0 theDesc.unitName = unitName @@ -289,11 +293,14 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers) valet.greetPlayer(playerName, aPlayerUnit, theZone, theDesc) 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 else -- ha!!! player changed planes! theDesc.currentlyIn = false + theDesc.lastTimeIn = 99999999 theDesc.greets = 0 theDesc.byes = 0 theDesc.unitName = unitName @@ -306,6 +313,7 @@ function valet.checkZoneAgainstPlayers(theZone, allPlayers) else -- was outside before end + theDesc.lastTimeIn = 99999999 else -- we are in the twilight zone (hysteresis). Do nothing. end