diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index 033ee5b..f170779 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 8070df9..4c76ffc 100644 Binary files a/Doc/DML Quick Reference.pdf and b/Doc/DML Quick Reference.pdf differ diff --git a/modules/cfxNDB.lua b/modules/cfxNDB.lua index 62c585b..e76661a 100644 --- a/modules/cfxNDB.lua +++ b/modules/cfxNDB.lua @@ -1,5 +1,5 @@ cfxNDB = {} -cfxNDB.version = "1.2.0" +cfxNDB.version = "1.2.1" --[[-- cfxNDB: @@ -22,6 +22,10 @@ cfxNDB.version = "1.2.0" - startNDB() can accept string - stopNDB() can accept string 1.2.0 - DML full integration + 1.2.1 - height correction for NDB on creation + - update only when moving and delta > maxDelta + - zone-local verbosity support + - better config defaulting --]]-- @@ -47,7 +51,7 @@ function cfxNDB.startNDB(theNDB) if not theNDB.freq then -- this zone is not an NDB. Exit - if cfxNDB.verbose then + if cfxNDB.verbose or theNDB.verbose then trigger.action.outText("+++ndb: start() -- " .. theNDB.name .. " is not a cfxNDB.", 30) end return @@ -60,10 +64,12 @@ function cfxNDB.startNDB(theNDB) local modulation = 0 if theNDB.fm then modulation = 1 end - local loc = cfxZones.getPoint(theNDB) + local loc = cfxZones.getPoint(theNDB) -- y === 0 + loc.y = land.getHeight({x = loc.x, y = loc.z}) -- get y from land trigger.action.radioTransmission(fileName, loc, modulation, true, theNDB.freq, theNDB.power, theNDB.ndbID) + theNDB.lastLoc = loc -- save for delta comparison - if cfxNDB.verbose then + if cfxNDB.verbose or theNDB.verbose then local dsc = "" if theNDB.linkedUnit then dsc = " (linked to ".. theNDB.linkedUnit:getName() .. "!, r=" .. theNDB.ndbRefresh .. ") " @@ -72,7 +78,7 @@ function cfxNDB.startNDB(theNDB) end theNDB.paused = false - if cfxNDB.verbose then + if cfxNDB.verbose or theNDB.verbose then trigger.action.outText("+++ndb: " .. theNDB.name .. " started", 30) end end @@ -84,7 +90,7 @@ function cfxNDB.stopNDB(theNDB) if not theNDB.freq then -- this zone is not an NDB. Exit - if cfxNDB.verbose then + if cfxNDB.verbose or theNDB.verbose then trigger.action.outText("+++ndb: stop() -- " .. theNDB.name .. " is not a cfxNDB.", 30) end return @@ -92,7 +98,7 @@ function cfxNDB.stopNDB(theNDB) trigger.action.stopRadioTransmission(theNDB.ndbID) theNDB.paused = true - if cfxNDB.verbose then + if cfxNDB.verbose or theNDB.verbose then trigger.action.outText("+++ndb: " .. theNDB.name .. " stopped", 30) end end @@ -159,8 +165,19 @@ function cfxNDB.update() -- yupp, need to update if (not theNDB.paused) and (now > theNDB.ndbRefreshTime) then - cfxNDB.stopNDB(theNDB) -- also pauses - cfxNDB.startNDB(theNDB) -- turns off pause + -- optimization: check that it moved far enough + -- to merit update. + if not theNDB.lastLoc then + cfxNDB.startNDB(theNDB) -- never was started + else + local loc = cfxZones.getPoint(theNDB) -- y === 0 + loc.y = land.getHeight({x = loc.x, y = loc.z}) -- get y from land + local delta = dcsCommon.dist(loc, theNDB.lastLoc) + if delta > cfxNDB.maxDist then + cfxNDB.stopNDB(theNDB) + cfxNDB.startNDB(theNDB) + end + end end end @@ -185,15 +202,14 @@ end function cfxNDB.readConfig() local theZone = cfxZones.getZoneByName("ndbConfig") if not theZone then - if cfxNDB.verbose then - trigger.action.outText("***ndb: NO config zone!", 30) - end - return + theZone = cfxZones.createSimpleZone("ndbConfig") end cfxNDB.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) cfxNDB.ndbRefresh = cfxZones.getNumberFromZoneProperty(theZone, "ndbRefresh", 10) + cfxNDB.maxDist = cfxZones.getNumberFromZoneProperty(theZone, "maxDist", 50) -- max 50m error for movement + if cfxNDB.verbose then trigger.action.outText("***ndb: read config", 30) end @@ -218,6 +234,7 @@ function cfxNDB.start() -- start update cfxNDB.update() + trigger.action.outText("cf/x NDB version " .. cfxNDB.version .. " started", 30) return true end diff --git a/modules/cfxOwnedZones.lua b/modules/cfxOwnedZones.lua index d532a54..792bdd8 100644 --- a/modules/cfxOwnedZones.lua +++ b/modules/cfxOwnedZones.lua @@ -1,5 +1,5 @@ cfxOwnedZones = {} -cfxOwnedZones.version = "1.2.4" +cfxOwnedZones.version = "1.3.0" cfxOwnedZones.verbose = false cfxOwnedZones.announcer = true cfxOwnedZones.name = "cfxOwnedZones" @@ -49,8 +49,19 @@ cfxOwnedZones.name = "cfxOwnedZones" 1.2.2 - redCap! and blueCap! 1.2.3 - fix for persistence bug when not using conquered flag 1.2.4 - pause? and activate? inputs +1.3.0 - new update method + - new fastEval option in config + - new numCap option in config + - new numKeep option in config + - new easyContest option in config + - new logic to keep and lose zones. controlled with numKeep and numCap. + - winSound + - loseSound + - redLost! zone output + - blueLost! zone output + - ownedBy direct zone output + - neutral! zone output - --]]-- cfxOwnedZones.requiredLibs = { "dcsCommon", -- common is of course needed for everything @@ -91,7 +102,7 @@ cfxOwnedZones.conqueredCallbacks = {} -- zone attributes when owned -- owner: coalition that owns the zone -- status: FSM for spawning --- defendersRED/BLUE - coma separated type string for the group to spawm on defense cycle completion +-- defendersRED/BLUE - coma separated type string for the group to spawn on defense cycle completion -- attackersRED/BLUE - as above for attack cycle. -- timeStamp - time when zone switched into current state -- spawnRadius - overrides zone's radius when placing defenders. can be use to place defenders inside or outside zone itself @@ -232,10 +243,26 @@ function cfxOwnedZones.addOwnedZone(aZone) aZone.redCap = cfxZones.getStringFromZoneProperty(aZone, "redCap!", "none") end + if cfxZones.hasProperty(aZone, "redLost!") then + aZone.redLost = cfxZones.getStringFromZoneProperty(aZone, "redLost!", "none") + end + if cfxZones.hasProperty(aZone, "blueCap!") then aZone.blueCap = cfxZones.getStringFromZoneProperty(aZone, "blueCap!", "none") end + if cfxZones.hasProperty(aZone, "blueLost!") then + aZone.blueLost = cfxZones.getStringFromZoneProperty(aZone, "blueLost!", "none") + end + + if cfxZones.hasProperty(aZone, "neutral!") then + aZone.neutralCap = cfxZones.getStringFromZoneProperty(aZone, "neutral!", "none") + end + + if cfxZones.hasProperty(aZone, "ownedBy") then + aZone.ownedBy = cfxZones.getStringFromZoneProperty(aZone, "ownedBy", "none") + end + -- pause? and activate? if cfxZones.hasProperty(aZone, "pause?") then aZone.pauseFlag = cfxZones.getStringFromZoneProperty(aZone, "pause?", "none") @@ -534,17 +561,25 @@ end function cfxOwnedZones.zoneConquered(aZone, theSide, formerOwner) -- 0 = neutral 1 = RED 2 = BLUE local who = "REDFORCE" - if theSide == 2 then who = "BLUEFORCE" end + if theSide == 2 then who = "BLUEFORCE" + elseif theSide == 0 then who = "NEUTRAL" end + if cfxOwnedZones.announcer then - trigger.action.outText(who .. " have secured zone " .. aZone.name, 30) - aZone.owner = theSide + if theSide == 0 then + trigger.action.outText(aZone.name .. " has become NEUTRAL", 30) + else + trigger.action.outText(who .. " have secured zone " .. aZone.name, 30) + end + aZone.owner = theSide -- just to be sure -- play different sounds depending on who's won if theSide == 1 then - trigger.action.outSoundForCoalition(1, "Quest Snare 3.wav") - trigger.action.outSoundForCoalition(2, "Death BRASS.wav") + trigger.action.outSoundForCoalition(1, cfxOwnedZones.winSound) + trigger.action.outSoundForCoalition(2, cfxOwnedZones.loseSound) + elseif theSide == 2 then + trigger.action.outSoundForCoalition(2, cfxOwnedZones.winSound) + trigger.action.outSoundForCoalition(1, cfxOwnedZones.loseSound) else - trigger.action.outSoundForCoalition(2, "Quest Snare 3.wav") - trigger.action.outSoundForCoalition(1, "Death BRASS.wav") + -- no sound played, new owner is neutral end end @@ -556,10 +591,22 @@ function cfxOwnedZones.zoneConquered(aZone, theSide, formerOwner) -- 0 = neutral cfxZones.pollFlag(aZone.redCap, "inc", aZone) end + if formerOwner == 1 and aZone.redLost then + cfxZones.pollFlag(aZone.redLost, "inc", aZone) + end + if theSide == 2 and aZone.blueCap then cfxZones.pollFlag(aZone.blueCap, "inc", aZone) end + if formerOwner == 2 and aZone.blueLost then + cfxZones.pollFlag(aZone.blueLost, "inc", aZone) + end + + if theSide == 0 and aZone.neutralCap then + cfxZones.pollFlag(aZone.neutralCap, "inc", aZone) + end + -- invoke callbacks now cfxOwnedZones.invokeConqueredCallbacks(aZone, theSide, formerOwner) @@ -852,7 +899,150 @@ function cfxOwnedZones.GC() end function cfxOwnedZones.update() + -- to speed this up we might only want to check the first unit + -- in group, and if inside, count the entire group as inside + -- new. unit counting update cfxOwnedZones.updateSchedule = timer.scheduleFunction(cfxOwnedZones.update, {}, timer.getTime() + 1/cfxOwnedZones.ups) + -- iterate all groups and their units to count how many + -- units are in each zone + for idz, theZone in pairs(cfxOwnedZones.zones) do + theZone.numRed = 0 + theZone.numBlue = 0 + -- count red units + local allRed = coalition.getGroups(1, Group.Category.GROUND) + for idx, aGroup in pairs(allRed) do + if Group.isExist(aGroup) then + if cfxOwnedZones.fastEval then + -- we only check first unit that is alive + local theUnit = dcsCommon.getGroupUnit(aGroup) + if theUnit and cfxZones.unitInZone(theUnit, theZone) then + theZone.numRed = theZone.numRed + aGroup:getSize() + end + else + local allUnits = aGroup:getUnits() + for idy, theUnit in pairs(allUnits) do + if cfxZones.unitInZone(theUnit, theZone) then + theZone.numRed = theZone.numRed + 1 + end + end + end + end + end + -- count blue units + local allBlue = coalition.getGroups(2, Group.Category.GROUND) + for idx, aGroup in pairs(allBlue) do + if Group.isExist(aGroup) then + if cfxOwnedZones.fastEval then + -- we only check first unit that is alive + local theUnit = dcsCommon.getGroupUnit(aGroup) + if theUnit and cfxZones.unitInZone(theUnit, theZone) then + theZone.numBlue = theZone.numBlue + aGroup:getSize() + end + else + local allUnits = aGroup:getUnits() + for idy, theUnit in pairs(allUnits) do + if cfxZones.unitInZone(theUnit, theZone) then + theZone.numBlue = theZone.numBlue + 1 + end + end + end + end + end + -- trigger.action.outText(theZone.name .. " blue: " .. theZone.numBlue .. " red " .. theZone.numRed, 30) + local lastOwner = theZone.owner + local newOwner = 0 -- neutral is default + -- determine new owner + -- step one: no troops here. Become neutral? + if theZone.numRed < 1 and theZone.numBlue < 1 then + if cfxOwnedZones.numKeep < 1 then + newOwner = lastOwner -- keep it, else turns neutral + else + -- noone here, zone becomes neutral + newOwner = 0 -- not strictly required. to be explicit + end + elseif theZone.numRed < 1 then + -- only blue here. enough to keep? + if theZone.numBlue >= cfxOwnedZones.numCap then + newOwner = 2 -- blue owns it + elseif lastOwner == 2 and theZone.numBlue >= cfxOwnedZones.numKeep then + -- enough to keep if owned before + newOwner = 2 + else + newOwner = 0 -- just to make it explicit + end + elseif theZone.numBlue < 1 then + -- only red here. enough to keep? + if theZone.numRed >= cfxOwnedZones.numCap then + newOwner = 1 + elseif lastOwner == 1 and theZone.numRed >= cfxOwnedZones.numKeep then + newOwner = 1 + else + newOwner = 0 + end + else + -- blue and red units here. + -- owner keeps hanging on only they have enough + -- units left + if cfxOwnedZones.easyContest then + -- this zone is immediately contested + newOwner = 0 -- just to be explicit + elseif cfxOwnedZones.numKeep < 1 then + -- old owner keeps it until none left + newOwner = lastOwner + else + if lastOwner == 1 then + -- red can keep it as long as enough units here + if theZone.numRed >= cfxOwnedZones.numKeep then + newOwner = 1 + end -- else 0 + elseif lastOwner == 2 then + -- blue can keep it if enough units here + if theZone.numBlue >= cfxOwnedZones.numKeep then + newOwner = 2 + end -- else 0 + else -- stay 0 + end + end + end + + -- now see if owner changed, and react accordingly + if newOwner == lastOwner then + -- nothing happened, do nothing + else + trigger.action.outText(theZone.name .. " change hands from " .. lastOwner .. " to " .. newOwner, 30) + if newOwner == 0 then -- zone turned neutral + cfxOwnedZones.zoneConquered(theZone, newOwner, lastOwner) + else + cfxOwnedZones.zoneConquered(theZone, newOwner, lastOwner) + end + end + theZone.owner = newOwner + + -- production & flags + -- see if pause/unpause was issued + -- note that capping a zone will not change pause status + if theZone.pauseFlag and cfxZones.testZoneFlag(theZone, theZone.pauseFlag, theZone.ownedTriggerMethod, "lastPauseValue") then + theZone.paused = true + end + + if theZone.activateFlag and cfxZones.testZoneFlag(theZone, theZone.activateFlag, theZone.ownedTriggerMethod, "lastActivateValue") then + theZone.paused = false + end + + -- update ownership flag if exists + if theZone.ownedBy then + cfxZones.setFlagValue(theZone.ownedBy, theZone.owner, theZone) + end + + -- now, perhaps with their new owner call updateZone() + -- to calcualte production for this zone + cfxOwnedZones.updateZone(theZone) + end -- iterating all zones +end + + +function cfxOwnedZones.updateOLD() + cfxOwnedZones.updateSchedule = timer.scheduleFunction(cfxOwnedZones.updateOLD, {}, timer.getTime() + 1/cfxOwnedZones.ups) -- iterate all zones, and determine their current ownership status for key, aZone in pairs(cfxOwnedZones.zones) do @@ -1065,6 +1255,14 @@ function cfxOwnedZones.readConfigZone(theZone) cfxOwnedZones.attackingTime = cfxZones.getNumberFromZoneProperty(theZone, "attackingTime", 300) cfxOwnedZones.shockTime = cfxZones.getNumberFromZoneProperty(theZone, "shockTime", 200) cfxOwnedZones.repairTime = cfxZones.getNumberFromZoneProperty(theZone, "repairTime", 200) + -- numKeep, numCap, fastEval, easyContest + cfxOwnedZones.numCap = cfxZones.getNumberFromZoneProperty(theZone, "numCap", 1) -- minimal number of units required to cap zone + cfxOwnedZones.numKeep = cfxZones.getNumberFromZoneProperty(theZone, "numKeep", 0) -- number required to keep zone + cfxOwnedZones.fastEval = cfxZones.getBoolFromZoneProperty(theZone, "fastEval", true) + cfxOwnedZones.easyContest = cfxZones.getBoolFromZoneProperty(theZone, "easyContest", false) + -- winSound, loseSound + cfxOwnedZones.winSound = cfxZones.getStringFromZoneProperty(theZone, "winSound", "Quest Snare 3.wav" ) + cfxOwnedZones.loseSound = cfxZones.getStringFromZoneProperty(theZone, "loseSound", "Death BRASS.wav") end function cfxOwnedZones.init() diff --git a/modules/cfxPlayerScore.lua b/modules/cfxPlayerScore.lua index 8537813..31dfb45 100644 --- a/modules/cfxPlayerScore.lua +++ b/modules/cfxPlayerScore.lua @@ -39,7 +39,7 @@ cfxPlayerScore.requiredLibs = { "cfxZones", -- zones for config } cfxPlayerScore.playerScore = {} -- init to empty - +cfxPlayerScore.deferred = false -- on deferred, we only award after landing, and erase on any form of re-slot -- typeScore: dictionary sorted by typeString for score -- extend to add more types. It is used by unitType2score to -- determine the base unit score @@ -153,8 +153,10 @@ function cfxPlayerScore.getPlayerScore(playerName) thePlayerScore.name = playerName thePlayerScore.score = 0 -- score thePlayerScore.killTypes = {} -- the type strings killed, dict + thePlayerScore.killQueue = {} -- when using deferred thePlayerScore.totalKills = 0 -- number of kills total thePlayerScore.featTypes = {} -- dict of other things player did + thePlayerScore.featQueue = {} -- when using deferred thePlayerScore.totalFeats = 0 end return thePlayerScore diff --git a/modules/cfxZones.lua b/modules/cfxZones.lua index e305b39..25602d0 100644 --- a/modules/cfxZones.lua +++ b/modules/cfxZones.lua @@ -124,7 +124,7 @@ cfxZones.version = "3.0.6" - 3.0.5 - getPositiveRangeFromZoneProperty() now also supports upper bound (optional) - 3.0.6 - new createSimplePolyZone() - new createSimpleQuadZone() - +- 3.0.7 - getPoint() can also get land y when passing true as second param --]]-- cfxZones.verbose = false cfxZones.caseSensitiveProperties = false -- set to true to make property names case sensitive @@ -2540,7 +2540,9 @@ function cfxZones.getLinkedUnit(theZone) return theZone.linkedUnit end -function cfxZones.getPoint(aZone) -- always works, even linked, returned point can be reused +function cfxZones.getPoint(aZone, getHeight) -- always works, even linked, returned point can be reused +-- returned y (when using getHeight) is that of the land, else 0 + if not getHeight then getHeight = false end if aZone.linkedUnit then local theUnit = aZone.linkedUnit -- has a link. is link existing? @@ -2557,9 +2559,13 @@ function cfxZones.getPoint(aZone) -- always works, even linked, returned point c end local thePos = {} thePos.x = aZone.point.x - thePos.y = 0 -- aZone.y thePos.z = aZone.point.z - + if not getHeight then + thePos.y = 0 -- aZone.y + else + thePos.y = land.getHeight({x = thePos.x, y = thePos.z}) + end + return thePos end diff --git a/modules/countDown.lua b/modules/countDown.lua index 5138cf2..39f3da5 100644 --- a/modules/countDown.lua +++ b/modules/countDown.lua @@ -1,5 +1,5 @@ countDown = {} -countDown.version = "1.3.0" +countDown.version = "1.3.1" countDown.verbose = false countDown.ups = 1 countDown.requiredLibs = { @@ -9,7 +9,7 @@ countDown.requiredLibs = { --[[-- count down on flags to generate new signal on out - Copyright (c) 2022 by Christian Franz and cf/x AG + Copyright (c) 2022, 2023 by Christian Franz and cf/x AG Version History 1.0.0 - initial version @@ -23,8 +23,11 @@ countDown.requiredLibs = { 1.2.1 - disableCounter? 1.3.0 - DML & Watchflags upgrade - method --> ctdwnMethod - - + 1.3.1 - clock? synonym + - new reset? input + - improved verbosity + - zone-local verbosity + --]]-- countDown.counters = {} @@ -48,7 +51,6 @@ function countDown.getCountDownZoneByName(aName) return nil end - -- -- callbacks -- @@ -81,7 +83,6 @@ function countDown.createCountDownWithZone(theZone) trigger.action.outText("+++cntD: initing count down <" .. theZone.name .. "> with " .. theZone.currVal, 30) end - -- loop theZone.loop = cfxZones.getBoolFromZoneProperty(theZone, "loop", false) @@ -94,7 +95,7 @@ function countDown.createCountDownWithZone(theZone) theZone.ctdwnMethod = cfxZones.getStringFromZoneProperty(theZone, "ctdwnMethod", "flip") end - -- triggerMethod + -- triggerMethod for inputs theZone.ctdwnTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change") if cfxZones.hasProperty(theZone, "ctdwnTriggerMethod") then @@ -104,16 +105,21 @@ function countDown.createCountDownWithZone(theZone) -- trigger flag "count" / "start?" if cfxZones.hasProperty(theZone, "count?") then theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "") - end - - + elseif cfxZones.hasProperty(theZone, "clock?") then + theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "clock?", "") -- can also use in? for counting. we always use triggerCountFlag - if cfxZones.hasProperty(theZone, "in?") then + elseif cfxZones.hasProperty(theZone, "in?") then theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "") end if theZone.triggerCountFlag then - theZone.lastCountTriggerValue = cfxZones.getFlagValue(theZone.triggerCountFlag, theZone) -- trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value + theZone.lastCountTriggerValue = cfxZones.getFlagValue(theZone.triggerCountFlag, theZone) + end + + -- reset + if cfxZones.hasProperty(theZone, "reset?") then + theZone.resetFlag = cfxZones.getStringFromZoneProperty(theZone, "reset?", "") + theZone.resetFlagValue = cfxZones.getFlagValue(theZone.resetFlag, theZone) end -- zero! bang @@ -146,10 +152,25 @@ end -- -- Update -- +function countDown.reset(theZone) + local val = dcsCommon.randomBetween(theZone.startMinVal, theZone.startMaxVal) + if countDown.verbose or theZone.verbose then + trigger.action.outText("+++cntD: resetting <" .. theZone.name .. "> to (" .. val .. ")", 30) + end + + theZone.currVal = val + if theZone.counterOut then + cfxZones.setFlagValue(theZone.counterOut, val, theZone) + end + -- read and ignore any pulling of the clock flag + local ignore = cfxZones.testZoneFlag(theZone, theZone.triggerCountFlag, theZone.ctdwnTriggerMethod, "lastCountTriggerValue") + -- simply updates lastTriggerValue to current clock value +end + function countDown.isTriggered(theZone) -- this module has triggered local val = theZone.currVal - 1 -- decrease counter - if countDown.verbose then + if countDown.verbose or theZone.verbose then trigger.action.outText("+++cntD: enter triggered: val now: " .. val, 30) end local tMinus = false @@ -165,8 +186,8 @@ function countDown.isTriggered(theZone) tMinus = true -- see if we need to bang Tminus if theZone.tMinusFlag then - if countDown.verbose then - trigger.action.outText("+++cntD: TMINUTS", 30) + if countDown.verbose or theZone.verbose then + trigger.action.outText("+++cntD: <" .. theZone.name .. "> TMINUTS on flag <" .. theZone.tMinusFlag .. ">", 30) end cfxZones.pollFlag(theZone.tMinusFlag, theZone.ctdwnMethod, theZone) end @@ -175,8 +196,8 @@ function countDown.isTriggered(theZone) -- reached zero zero = true if theZone.zeroFlag then - if countDown.verbose then - trigger.action.outText("+++cntD: ZERO", 30) + if countDown.verbose or theZone.verbose then + trigger.action.outText("+++cntD: ZERO <" .. theZone.name .. "> on flag <" .. theZone.zeroFlag .. ">", 30) end cfxZones.pollFlag(theZone.zeroFlag, theZone.ctdwnMethod, theZone) end @@ -184,17 +205,17 @@ function countDown.isTriggered(theZone) if theZone.loop then -- restart time looping = true - if countDown.verbose then - trigger.action.outText("+++cntD: Looping", 30) - end val = dcsCommon.randomBetween(theZone.startMinVal, theZone.startMaxVal) + if countDown.verbose or theZone.verbose then + trigger.action.outText("+++cntD: Looping <" .. theZone.name .. ">, start val is (" .. val .. ")", 30) + end end else -- below zero belowZero = true if theZone.belowZero and theZone.zeroFlag then - if countDown.verbose then + if countDown.verbose or theZone.verbose then trigger.action.outText("+++cntD: Below Zero", 30) end cfxZones.pollFlag(theZone.zeroFlag, theZone.ctdwnMethod, theZone) @@ -207,7 +228,6 @@ function countDown.isTriggered(theZone) -- update & return theZone.currVal = val - end function countDown.update() @@ -215,8 +235,17 @@ function countDown.update() timer.scheduleFunction(countDown.update, {}, timer.getTime() + 1/countDown.ups) for idx, aZone in pairs(countDown.counters) do + if aZone.resetFlag then + if cfxZones.testZoneFlag(aZone, aZone.resetFlag, aZone.ctdwnTriggerMethod, "resetFlagValue") then + -- reset pulled, reset the timer to start condition + countDown.reset(aZone) + end + end + -- make sure to re-start before reading time limit - if (not aZone.counterDisabled) and cfxZones.testZoneFlag(aZone, aZone.triggerCountFlag, aZone.ctdwnTriggerMethod, "lastCountTriggerValue") + -- if reset, lastTriggerValue is updated and will not trigger + if (not aZone.counterDisabled) and + cfxZones.testZoneFlag(aZone, aZone.triggerCountFlag, aZone.ctdwnTriggerMethod, "lastCountTriggerValue") then if countDown.verbose then trigger.action.outText("+++cntD: triggered on in?", 30) @@ -224,20 +253,6 @@ function countDown.update() countDown.isTriggered(aZone) end - -- old colde - --[[-- - if aZone.triggerCountFlag and not aZone.counterDisabled then - local currTriggerVal = cfxZones.getFlagValue(aZone.triggerCountFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerCountFlag) - if currTriggerVal ~= aZone.lastCountTriggerValue - then - if countDown.verbose then - trigger.action.outText("+++cntD: triggered on in?", 30) - end - countDown.isTriggered(aZone) - aZone.lastCountTriggerValue = cfxZones.getFlagValue(aZone.triggerCountFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value - end - end - --]]-- if cfxZones.testZoneFlag(aZone, aZone.disableCounterFlag, aZone.ctdwnTriggerMethod, "disableCounterFlagVal") then if countDown.verbose then trigger.action.outText("+++cntD: disabling counter " .. aZone.name, 30) @@ -245,18 +260,6 @@ function countDown.update() aZone.counterDisabled = true end - -- old code - --[[-- - if aZone.disableCounterFlag then - local currVal = cfxZones.getFlagValue(aZone.disableCounterFlag, aZone) - if currVal ~= aZone.disableCounterFlagVal then - if countDown.verbose then - trigger.action.outText("+++cntD: disabling counter " .. aZone.name, 30) - end - aZone.counterDisabled = true - end - end - --]]-- end end @@ -273,8 +276,6 @@ function countDown.readConfigZone() end countDown.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 1) - -- slowest is once avery 1000 seconds = 17 minutes, doesn't make much sense slower than 1/second anyway - if countDown.ups < 0.001 then countDown.ups = 0.001 end countDown.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) @@ -304,7 +305,6 @@ function countDown.start() countDown.addCountDown(aZone) -- add to list end - -- start update countDown.update() diff --git a/modules/csarManager2.lua b/modules/csarManager2.lua index 2b4f331..abfbc48 100644 --- a/modules/csarManager2.lua +++ b/modules/csarManager2.lua @@ -1,5 +1,5 @@ csarManager = {} -csarManager.version = "2.2.4" +csarManager.version = "2.2.5" csarManager.verbose = false csarManager.ups = 1 @@ -62,6 +62,7 @@ csarManager.ups = 1 - deprecated coalition attribute - 2.2.4 - CSAR attribute value defaults name - start? attribute for CSAR as startCSAR? synonym + - 2.2.5 - manual freq for CSAR was off by a factor of 10 - Corrected INTEGRATES AUTOMATICALLY WITH playerScore IF INSTALLED @@ -758,10 +759,10 @@ function csarManager.doListCSARRequests(args) local b = dcsCommon.bearingInDegreesFromAtoB(point, mission.zone.point) local status = "alive" if csarManager.vectoring then - report = report .. "\n".. mission.name .. ", bearing " .. b .. ", " ..d .."nm, " .. " ADF " .. mission.freq .. "0 kHz - " .. status + report = report .. "\n".. mission.name .. ", bearing " .. b .. ", " ..d .."nm, " .. " ADF " .. mission.freq * 10 .. " kHz - " .. status else -- leave out vectoring - report = report .. "\n".. mission.name .. " ADF " .. mission.freq .. "0 kHz - " .. status + report = report .. "\n".. mission.name .. " ADF " .. mission.freq * 10 .. " kHz - " .. status end end end @@ -1291,7 +1292,10 @@ function csarManager.readCSARZone(theZone) end theZone.csarFreq = cfxZones.getNumberFromZoneProperty(theZone, "freq", 0) - if theZone.csarFreq == 0 then theZone.csarFreq = nil end + -- since freqs are set in 10kHz multiplier by DML + -- we have to divide the feq given here by 10 + theZone.csarFreq = theZone.csarFreq / 10 + if theZone.csarFreq < 0.01 then theZone.csarFreq = nil end theZone.numCrew = 1 theZone.csarMapMarker = nil theZone.timeLimit = cfxZones.getNumberFromZoneProperty(theZone, "timeLimit", 0) diff --git a/modules/dcsCommon.lua b/modules/dcsCommon.lua index 17e0751..5f411fc 100644 --- a/modules/dcsCommon.lua +++ b/modules/dcsCommon.lua @@ -1,5 +1,5 @@ dcsCommon = {} -dcsCommon.version = "2.8.4" +dcsCommon.version = "2.8.5" --[[-- VERSION HISTORY 2.2.6 - compassPositionOfARelativeToB - clockPositionOfARelativeToB @@ -144,6 +144,7 @@ dcsCommon.version = "2.8.4" - new rotatePointAroundPointDeg() - new rotatePointAroundPointRad() - getClosestAirbaseTo() now supports passing list of air bases + 2.8.5 - better guard in getGroupUnit() --]]-- @@ -999,7 +1000,7 @@ dcsCommon.version = "2.8.4" -- iterate through all members of group until one is alive and exists for index, theUnit in pairs(allUnits) do - if (theUnit:isExist() and theUnit:getLife() > 0) then + if Unit.isExist(theUnit) and theUnit:getLife() > 0 then return theUnit end; end diff --git a/modules/pulseFlags.lua b/modules/pulseFlags.lua index aa5d830..6b8b7ec 100644 --- a/modules/pulseFlags.lua +++ b/modules/pulseFlags.lua @@ -1,5 +1,5 @@ pulseFlags = {} -pulseFlags.version = "1.3.2" +pulseFlags.version = "1.3.3" pulseFlags.verbose = false pulseFlags.requiredLibs = { "dcsCommon", -- always @@ -38,6 +38,7 @@ pulseFlags.requiredLibs = { - 1.3.0 persistence - 1.3.1 typos corrected - 1.3.2 removed last pulse's timeID upon entry in doPulse + - 1.3.3 removed 'pulsing' when pausing, so we can restart --]]-- @@ -275,6 +276,7 @@ function pulseFlags.update() trigger.action.outText("+++pulF: pausing <" .. aZone.name .. ">", 30) end aZone.pulsePaused = true -- prevents new start + aZone.pulsing = false -- we are stopped if aZone.timerID then timer.removeFunction(aZone.timerID) aZone.timerID = nil diff --git a/tutorial & demo missions/demo - ADF and NDB fun.miz b/tutorial & demo missions/demo - ADF and NDB fun.miz index 33ab8be..f139bce 100644 Binary files a/tutorial & demo missions/demo - ADF and NDB fun.miz and b/tutorial & demo missions/demo - ADF and NDB fun.miz differ diff --git a/tutorial & demo missions/demo - CSAR of Georgia.miz b/tutorial & demo missions/demo - CSAR of Georgia.miz index 610984b..ec9cc5a 100644 Binary files a/tutorial & demo missions/demo - CSAR of Georgia.miz and b/tutorial & demo missions/demo - CSAR of Georgia.miz differ diff --git a/tutorial & demo missions/demo - The Zonal Countdown.miz b/tutorial & demo missions/demo - The Zonal Countdown.miz index 57d23d9..e95fd75 100644 Binary files a/tutorial & demo missions/demo - The Zonal Countdown.miz and b/tutorial & demo missions/demo - The Zonal Countdown.miz differ