Version 0.997

Wiper
This commit is contained in:
Christian Franz 2022-04-07 16:26:48 +02:00
parent 9f54ac1917
commit 2b97597e83
14 changed files with 602 additions and 32 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxGroundTroops = {} cfxGroundTroops = {}
cfxGroundTroops.version = "1.7.4" cfxGroundTroops.version = "1.7.5"
cfxGroundTroops.ups = 1 cfxGroundTroops.ups = 1
cfxGroundTroops.verbose = false cfxGroundTroops.verbose = false
cfxGroundTroops.requiredLibs = { cfxGroundTroops.requiredLibs = {
@ -59,6 +59,7 @@ cfxGroundTroops.deployedTroops = {}
-- - callback when group is being engaged under guard orders -- - callback when group is being engaged under guard orders
-- 1.7.3 - callbacks for lase:tracking and lase:stop -- 1.7.3 - callbacks for lase:tracking and lase:stop
-- 1.7.4 - verbose flag, warnings suppressed -- 1.7.4 - verbose flag, warnings suppressed
-- 1.7.5 - some troop.group hardening with isExist()
@ -199,6 +200,11 @@ end
-- enemies are an attribute of the troop structure -- enemies are an attribute of the troop structure
function cfxGroundTroops.makeTroopsEngageEnemies(troop) function cfxGroundTroops.makeTroopsEngageEnemies(troop)
local group = troop.group local group = troop.group
if not group:isExist() then
trigger.action.outText("+++gndT: troup don't exist, dropping", 30)
return
end
local enemies = troop.enemy local enemies = troop.enemy
local from = dcsCommon.getGroupLocation(group) local from = dcsCommon.getGroupLocation(group)
if not from then return end -- the commandos died if not from then return end -- the commandos died
@ -218,6 +224,11 @@ end
-- attribute -- attribute
function cfxGroundTroops.makeTroopsEngageZone(troop) function cfxGroundTroops.makeTroopsEngageZone(troop)
local group = troop.group local group = troop.group
if not group:isExist() then
trigger.action.outText("+++gndT: make engage zone: troops do not exist, exiting", 30)
return
end
local enemyZone = troop.destination -- must be cfxZone local enemyZone = troop.destination -- must be cfxZone
local from = dcsCommon.getGroupLocation(group) local from = dcsCommon.getGroupLocation(group)
if not from then return end -- the group died if not from then return end -- the group died
@ -250,6 +261,10 @@ function cfxGroundTroops.switchToOffroad(troops)
-- on their route for longer than allowed -- on their route for longer than allowed
-- we now force a direct approach -- we now force a direct approach
local group = troops.group local group = troops.group
if not group.isExist() then
return
end
local enemies = troops.destination local enemies = troops.destination
local from = dcsCommon.getGroupLocation(group) local from = dcsCommon.getGroupLocation(group)
if not from then return end -- the commandos died if not from then return end -- the commandos died
@ -315,6 +330,7 @@ end
function cfxGroundTroops.updateAttackers(troop) function cfxGroundTroops.updateAttackers(troop)
if not troop then return end if not troop then return end
if not troop.destination then return end if not troop.destination then return end
if not troop.group:isExist() then return end
if cfxZones.isGroupPartiallyInZone(troop.group, troop.destination) then if cfxZones.isGroupPartiallyInZone(troop.group, troop.destination) then
-- we have arrived -- we have arrived
@ -335,6 +351,10 @@ end
-- 'engaged' means that the troop.enemy attribute is set -- 'engaged' means that the troop.enemy attribute is set
function cfxGroundTroops.updateGuards(troop) function cfxGroundTroops.updateGuards(troop)
if not troop.group:isExist() then
return
end
local theEnemy = troop.enemy local theEnemy = troop.enemy
if theEnemy then if theEnemy then
-- see if enemy is dead -- see if enemy is dead
@ -807,7 +827,7 @@ function cfxGroundTroops.checkPileUp()
for idx, troop in pairs(cfxGroundTroops.deployedTroops) do for idx, troop in pairs(cfxGroundTroops.deployedTroops) do
-- get each group and count them if they are inside -- get each group and count them if they are inside
-- their destination -- their destination
if troop.insideDestination then if troop.insideDestination and troop.group:isExist() then
local side = troop.group:getCoalition() local side = troop.group:getCoalition()
local thePile = thePiles[troop.destination] local thePile = thePiles[troop.destination]
local theSide = troop.group:getCoalition() local theSide = troop.group:getCoalition()
@ -879,7 +899,7 @@ function cfxGroundTroops.checkSchedules()
-- plan and needs to be scheduled -- plan and needs to be scheduled
if troop.updateID == nil then if troop.updateID == nil then
troop.unscheduleCount = troop.unscheduleCount + 1 troop.unscheduleCount = troop.unscheduleCount + 1
if (troop.unscheduleCount > 1) then if (troop.unscheduleCount > 1) and troop.group:isExist() then
trigger.action.outText("+++ groundT: unscheduled group " .. troop.group:getName() .. " cnt=" .. troop.unscheduleCount , 30) trigger.action.outText("+++ groundT: unscheduled group " .. troop.group:getName() .. " cnt=" .. troop.unscheduleCount , 30)
end end
end end
@ -896,7 +916,7 @@ function cfxGroundTroops.getTroopReport(theSide, ignoreInfantry)
if not ignoreInfantry then ignoreInfantry = false end if not ignoreInfantry then ignoreInfantry = false end
local report = "GROUND FORCES REPORT" local report = "GROUND FORCES REPORT"
for idx, troop in pairs(cfxGroundTroops.deployedTroops) do for idx, troop in pairs(cfxGroundTroops.deployedTroops) do
if troop.side == theSide then if troop.side == theSide and troop.group:isExist() then
local unitNum = troop.group:getSize() local unitNum = troop.group:getSize()
report = report .. "\n" .. troop.name .. " (".. unitNum .."): <" .. troop.orders .. ">" report = report .. "\n" .. troop.name .. " (".. unitNum .."): <" .. troop.orders .. ">"
if troop.orders == "attackOwnedZone" then if troop.orders == "attackOwnedZone" then
@ -975,8 +995,14 @@ function cfxGroundTroops.addGroundTroopsToPool(troops) -- troops MUST be a table
end end
function cfxGroundTroops.removeTroopsFromPool(troops) function cfxGroundTroops.removeTroopsFromPool(troops)
if not troops then return end if not troops then return end
if troops.signature ~= "cfx" then return end if troops.signature ~= "cfx" then return end
if not troops.group:isExist() then
trigger.action.outText("warning: removeFromPool called with inexistant group", 30)
return
end
if cfxGroundTroops.deployedTroops[troops.group:getName()] then if cfxGroundTroops.deployedTroops[troops.group:getName()] then
local troop = cfxGroundTroops.deployedTroops[troops.group:getName()] local troop = cfxGroundTroops.deployedTroops[troops.group:getName()]
@ -1066,7 +1092,9 @@ function cfxGroundTroops.manageQueues()
-- trnasfer items from the front to the managed queue -- trnasfer items from the front to the managed queue
local theTroops = cfxGroundTroops.troopQueue[1] local theTroops = cfxGroundTroops.troopQueue[1]
table.remove(cfxGroundTroops.troopQueue, 1) table.remove(cfxGroundTroops.troopQueue, 1)
cfxGroundTroops.deployedTroops[theTroops.group:getName()] = theTroops if theTroops.group:isExist() then
cfxGroundTroops.deployedTroops[theTroops.group:getName()] = theTroops
end
-- trigger.action.outText("+++gT: dequed and activaed " .. theTroops.group:getName(), 30) -- trigger.action.outText("+++gT: dequed and activaed " .. theTroops.group:getName(), 30)
end end
end end

View File

@ -1,5 +1,5 @@
cfxSmokeZone = {} cfxSmokeZone = {}
cfxSmokeZone.version = "1.0.4" cfxSmokeZone.version = "1.1.0"
cfxSmokeZone.requiredLibs = { cfxSmokeZone.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
"cfxZones", -- Zones, of course "cfxZones", -- Zones, of course
@ -15,6 +15,7 @@ cfxSmokeZone.requiredLibs = {
1.0.4 - startSmoke? synonym 1.0.4 - startSmoke? synonym
- alphanum DML flag upgrade - alphanum DML flag upgrade
- random color support - random color support
1.1.0 - Watchflag upgrade
SMOKE ZONES *** EXTENDS ZONES *** SMOKE ZONES *** EXTENDS ZONES ***
keeps 'eternal' smoke up for any zone that has the keeps 'eternal' smoke up for any zone that has the
@ -49,7 +50,7 @@ function cfxSmokeZone.processSmokeZone(aZone)
-- f? query flags -- f? query flags
if cfxZones.hasProperty(aZone, "f?") then if cfxZones.hasProperty(aZone, "f?") then
aZone.onFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "none") aZone.onFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "*<none>")
end end
if cfxZones.hasProperty(aZone, "startSmoke?") then if cfxZones.hasProperty(aZone, "startSmoke?") then
@ -59,6 +60,15 @@ function cfxSmokeZone.processSmokeZone(aZone)
if aZone.onFlag then if aZone.onFlag then
aZone.onFlagVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- save last value aZone.onFlagVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- save last value
end end
-- watchflags:
-- triggerMethod
aZone.smokeTriggerMethod = cfxZones.getStringFromZoneProperty(aZone, "triggerMethod", "change")
if cfxZones.hasProperty(aZone, "smokeTriggerMethod") then
aZone.delayTriggerMethod = cfxZones.getStringFromZoneProperty(aZone, "smokeTriggerMethod", "change")
end
end end
function cfxSmokeZone.addSmokeZone(aZone) function cfxSmokeZone.addSmokeZone(aZone)
@ -122,7 +132,6 @@ function cfxSmokeZone.update()
for idx, aZone in pairs(cfxSmokeZone.smokeZones) do for idx, aZone in pairs(cfxSmokeZone.smokeZones) do
if not aZone.paused and aZone.smokeColor then if not aZone.paused and aZone.smokeColor then
cfxSmokeZone.startSmoke(aZone) cfxSmokeZone.startSmoke(aZone)
end end
end end
end end
@ -131,14 +140,21 @@ end
function cfxSmokeZone.checkFlags() function cfxSmokeZone.checkFlags()
timer.scheduleFunction(cfxSmokeZone.checkFlags, {}, timer.getTime() + 1) -- every second timer.scheduleFunction(cfxSmokeZone.checkFlags, {}, timer.getTime() + 1) -- every second
for idx, aZone in pairs(cfxSmokeZone.smokeZones) do for idx, aZone in pairs(cfxSmokeZone.smokeZones) do
if aZone.paused and aZone.onFlagVal then if aZone.paused and aZone.onFlagVal then
-- see if this changed -- see if this changed
if cfxZones.testZoneFlag(aZone, aZone.onFlag, aZone.smokeTriggerMethod, "onFlagVal") then
cfxSmokeZone.startSmoke(aZone)
end
--[[--
-- old code
local currTriggerVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- trigger.misc.getUserFlag(aZone.onFlag) local currTriggerVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- trigger.misc.getUserFlag(aZone.onFlag)
if currTriggerVal ~= aZone.onFlagVal then if currTriggerVal ~= aZone.onFlagVal then
-- yupp, trigger start -- yupp, trigger start
cfxSmokeZone.startSmoke(aZone) cfxSmokeZone.startSmoke(aZone)
aZone.onFlagVal = currTriggerVal aZone.onFlagVal = currTriggerVal
end end
--]]--
end end
end end
end end

View File

@ -64,6 +64,7 @@ cfxZones.version = "2.7.0"
- verbose for zone-local accepted (but not acted upon) - verbose for zone-local accepted (but not acted upon)
- hasProperty now offers active information when looking for '*?' and '*!' - hasProperty now offers active information when looking for '*?' and '*!'
- 2.7.0 - doPollFlag - fully support multiple flags per bang! - 2.7.0 - doPollFlag - fully support multiple flags per bang!
- 2.7.1 - setFlagValueMult()
--]]-- --]]--
cfxZones.verbose = false cfxZones.verbose = false
@ -2881,6 +2882,25 @@ function cfxZones.pollFlag(theFlag, method, theZone)
end end
function cfxZones.setFlagValueMult(theFlag, theValue, theZone)
local allFlags = {}
if dcsCommon.containsString(theFlag, ",") then
if cfxZones.verbose then
trigger.action.outText("+++zones: will multi-set flags <" .. theFlag .. "> to " .. theValue, 30)
end
allFlags = dcsCommon.splitString(theFlag, ",")
else
table.insert(allFlags, theFlag)
end
for idx, aFlag in pairs(allFlags) do
aFlag = dcsCommon.trim(aFlag)
-- note: mey require range preprocessing, but that's not
-- a priority
cfxZones.setFlagValue(aFlag, theValue, theZone)
end
end
function cfxZones.setFlagValue(theFlag, theValue, theZone) function cfxZones.setFlagValue(theFlag, theValue, theZone)
local zoneName = "<dummy>" local zoneName = "<dummy>"
if not theZone then if not theZone then
@ -3036,7 +3056,7 @@ function cfxZones.testFlagByMethodForZone(currVal, lastVal, theMethod, theZone)
end end
function cfxZones.testZoneFlag(theZone, theFlagName, theMethod, latchName) function cfxZones.testZoneFlag(theZone, theFlagName, theMethod, latchName)
-- returns true if method contraints are met for flag theFlagName -- returns true if method constraints are met for flag theFlagName
-- as defined by theMethod -- as defined by theMethod
if not theMethod then if not theMethod then
theMethod = "change" theMethod = "change"

148
modules/changer.lua Normal file
View File

@ -0,0 +1,148 @@
changer = {}
changer.version = "0.0.0"
changer.verbose = false
changer.ups = 1
changer.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
changer.changers = {}
--[[--
Version History
1.0.0 - Initial version
--]]--
function changer.addChanger(theZone)
table.insert(changer.changers, theZone)
end
function changer.getChangerByName(aName)
for idx, aZone in pairs(changer.changers) do
if aName == aZone.name then return aZone end
end
if changer.verbose then
trigger.action.outText("+++chgr: no changer with name <" .. aName ..">", 30)
end
return nil
end
--
-- read zone
--
function wiper.createWiperWithZone(theZone)
theZone.triggerWiperFlag = cfxZones.getStringFromZoneProperty(theZone, "wipe?", "*<none>")
-- triggerWiperMethod
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerWiperMethod") then
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerWiperMethod", "change")
end
if theZone.triggerWiperFlag then
theZone.lastTriggerWiperValue = cfxZones.getFlagValue(theZone.triggerWiperFlag, theZone)
end
local theCat = cfxZones.getStringFromZoneProperty(theZone, "category", "static")
if cfxZones.hasProperty(theZone, "wipeCategory") then
theCat = cfxZones.getStringFromZoneProperty(theZone, "wipeCategory", "static")
end
if cfxZones.hasProperty(theZone, "wipeCat") then
theCat = cfxZones.getStringFromZoneProperty(theZone, "wipeCat", "static")
end
theZone.wipeCategory = dcsCommon.string2ObjectCat(theCat)
if cfxZones.hasProperty(theZone, "wipeNamed") then
theZone.wipeNamed = cfxZones.getStringFromZoneProperty(theZone, "wipeNamed", "<no name given>")
if dcsCommon.stringEndsWith(theZone.wipeNamed, "*") then
theZone.wipeNamedBeginsWith = true
theZone.wipeNamed = dcsCommon.removeEnding(theZone.wipeNamed, "*")
end
end
theZone.wipeInventory = cfxZones.getBoolFromZoneProperty(theZone, "wipeInventory", false)
if wiper.verbose or theZone.verbose then
trigger.action.outText("+++wpr: new wiper zone <".. theZone.name ..">", 30)
end
end
--
-- MAIN ACTION
--
function changer.isTriggered(theZone)
end
--
-- Update
--
function changer.update()
-- call me in a second to poll triggers
timer.scheduleFunction(changer.update, {}, timer.getTime() + 1/changer.ups)
for idx, aZone in pairs(changer.changers) do
end
end
--
-- Config & Start
--
function changer.readConfigZone()
local theZone = cfxZones.getZoneByName("changerConfig")
if not theZone then
if changer.verbose then
trigger.action.outText("+++chgr: NO config zone!", 30)
end
theZone = cfxZones.createSimpleZone("changerConfig") -- temp only
end
changer.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
changer.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 1)
if changer.verbose then
trigger.action.outText("+++chgr: read config", 30)
end
end
function wiper.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx Wiper requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx Wiper", wiper.requiredLibs) then
return false
end
-- read config
wiper.readConfigZone()
-- process cloner Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("wipe?")
for k, aZone in pairs(attrZones) do
wiper.createWiperWithZone(aZone) -- process attributes
wiper.addWiper(aZone) -- add to list
end
-- start update
wiper.update()
trigger.action.outText("cfx Wiper v" .. wiper.version .. " started.", 30)
return true
end
-- let's go!
if not wiper.start() then
trigger.action.outText("cfx Wiper aborted: missing libraries", 30)
wiper = nil
end

View File

@ -1,6 +1,6 @@
countDown = {} countDown = {}
countDown.version = "1.3.0" countDown.version = "1.3.0"
countDown.verbose = true countDown.verbose = false
countDown.ups = 1 countDown.ups = 1
countDown.requiredLibs = { countDown.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always

View File

@ -1,5 +1,5 @@
dcsCommon = {} dcsCommon = {}
dcsCommon.version = "2.5.8" dcsCommon.version = "2.5.9"
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB 2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB - clockPositionOfARelativeToB
@ -68,6 +68,7 @@ dcsCommon.version = "2.5.8"
2.5.6 - corrected stringEndsWith() bug with str 2.5.6 - corrected stringEndsWith() bug with str
2.5.7 - point2text(p) 2.5.7 - point2text(p)
2.5.8 - string2GroupCat() 2.5.8 - string2GroupCat()
2.5.9 - string2ObjectCat()
--]]-- --]]--
@ -1806,6 +1807,28 @@ dcsCommon.version = "2.5.8"
return catNum return catNum
end end
function dcsCommon.string2ObjectCat(inString)
if not inString then return 3 end -- default static
inString = inString:lower()
inString = dcsCommon.trim(inString)
local catNum = tonumber(inString)
if catNum then
if catNum < 0 then catNum = 0 end
if catNum > 6 then catNum = 6 end
return catNum
end
catNum = 3 -- static default
if dcsCommon.stringStartsWith(inString, "uni") then catNum = 1 end
if dcsCommon.stringStartsWith(inString, "wea") then catNum = 2 end
if dcsCommon.stringStartsWith(inString, "bas") then catNum = 4 end
if dcsCommon.stringStartsWith(inString, "sce") then catNum = 5 end
if dcsCommon.stringStartsWith(inString, "car") then catNum = 6 end
return catNum
end
-- recursively show the contents of a variable -- recursively show the contents of a variable
function dcsCommon.dumpVar(key, value, prefix, inrecursion) function dcsCommon.dumpVar(key, value, prefix, inrecursion)

View File

@ -1,5 +1,5 @@
unitZone={} unitZone={}
unitZone.version = "1.1.0" unitZone.version = "1.2.0"
unitZone.verbose = false unitZone.verbose = false
unitZone.ups = 1 unitZone.ups = 1
unitZone.requiredLibs = { unitZone.requiredLibs = {
@ -11,6 +11,7 @@ unitZone.requiredLibs = {
1.0.0 - Initial Version 1.0.0 - Initial Version
1.1.0 - DML flag integration 1.1.0 - DML flag integration
- method/uzMethod - method/uzMethod
1.2.0 - uzOn?, uzOff?, triggerMethod
--]]-- --]]--
@ -73,11 +74,11 @@ function unitZone.createUnitZone(theZone)
theZone.uzCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "uzCoalition", 0) theZone.uzCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "uzCoalition", 0)
end end
if unitZone.verbose then if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: set coa " .. theZone.uzCoalition .. " for <" .. theZone.name .. ">", 30) trigger.action.outText("+++uZne: set coa " .. theZone.uzCoalition .. " for <" .. theZone.name .. ">", 30)
end end
-- DML M;ethod -- DML Method
theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
if cfxZones.hasProperty(theZone, "uzMethod") then if cfxZones.hasProperty(theZone, "uzMethod") then
theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "uzMethod", "inc") theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "uzMethod", "inc")
@ -90,16 +91,30 @@ function unitZone.createUnitZone(theZone)
if cfxZones.hasProperty(theZone, "filterFor") then if cfxZones.hasProperty(theZone, "filterFor") then
local filterString = cfxZones.getStringFromZoneProperty(theZone, "filterFor", "1") -- ground local filterString = cfxZones.getStringFromZoneProperty(theZone, "filterFor", "1") -- ground
theZone.filterFor = unitZone.string2cat(filterString) theZone.filterFor = unitZone.string2cat(filterString)
if unitZone.verbose then if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: filtering " .. theZone.filterFor .. " in " .. theZone.name, 30) trigger.action.outText("+++uZne: filtering " .. theZone.filterFor .. " in " .. theZone.name, 30)
end end
end end
-- on/off flags
theZone.uzPaused = false -- we are turned on
theZone.triggerOnFlag = cfxZones.getStringFromZoneProperty(theZone, "uzOn?", "*<none1>")
theZone.lastTriggerOnValue = cfxZones.getFlagValue(theZone.triggerOnFlag, theZone)
theZone.triggerOffFlag = cfxZones.getStringFromZoneProperty(theZone, "uzOff?", "*<none2>")
theZone.lastTriggerOffValue = cfxZones.getFlagValue(theZone.triggerOffFlag, theZone)
theZone.uzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "uzTriggerMethod") then
theZone.uzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "uzTriggerMethod", "change")
end
-- now get initial zone status ? -- now get initial zone status ?
theZone.lastStatus = unitZone.checkZoneStatus(theZone) theZone.lastStatus = unitZone.checkZoneStatus(theZone)
if unitZone.verbose then if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: processsed unit zone " .. theZone.name, 30) trigger.action.outText("+++uZne: processsed unit zone " .. theZone.name, 30)
end end
end end
@ -221,14 +236,31 @@ function unitZone.update()
timer.scheduleFunction(unitZone.update, {}, timer.getTime() + 1/unitZone.ups) timer.scheduleFunction(unitZone.update, {}, timer.getTime() + 1/unitZone.ups)
for idx, aZone in pairs(unitZone.unitZones) do for idx, aZone in pairs(unitZone.unitZones) do
-- scan all zones -- check if we need to pause/unpause
local newState = unitZone.checkZoneStatus(aZone) if cfxZones.testZoneFlag(aZone, aZone.triggerOnFlag, aZone.uzTriggerMethod, "lastTriggerOnValue") then
if unitZone.verbose or aZone.verbose then
if newState ~= aZone.lastStatus then trigger.action.outText("+++uZone: turning " .. aZone.name .. " on", 30)
-- bang on change! end
unitZone.bangState(aZone, newState) aZone.uzPaused = false
aZone.lastStatus = newState
end end
if cfxZones.testZoneFlag(aZone, aZone.triggerOffFlag, aZone.uzTriggerMethod, "lastTriggerOffValue") then
if unitZone.verbose or aZone.verbose then
trigger.action.outText("+++uZone: turning " .. aZone.name .. " OFF", 30)
end
aZone.uzPaused = true
end
-- scan all zones
if not aZone.uzPaused then
local newState = unitZone.checkZoneStatus(aZone)
if newState ~= aZone.lastStatus then
-- bang on change!
unitZone.bangState(aZone, newState)
aZone.lastStatus = newState
end
end
end end
end end

278
modules/wiper.lua Normal file
View File

@ -0,0 +1,278 @@
wiper = {}
wiper.version = "1.0.0"
wiper.verbose = false
wiper.ups = 1
wiper.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
wiper.wipers = {}
--[[--
Version History
1.0.0 - Initial Version
--]]--
function wiper.addWiper(theZone)
table.insert(wiper.wipers, theZone)
end
function wiper.getWiperByName(aName)
for idx, aZone in pairs(wiper.wipers) do
if aName == aZone.name then return aZone end
end
if wiper.verbose then
trigger.action.outText("+++wpr: no wiper with name <" .. aName ..">", 30)
end
return nil
end
--
-- read zone
--
function wiper.createWiperWithZone(theZone)
theZone.triggerWiperFlag = cfxZones.getStringFromZoneProperty(theZone, "wipe?", "*<none>")
-- triggerWiperMethod
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerWiperMethod") then
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerWiperMethod", "change")
end
if theZone.triggerWiperFlag then
theZone.lastTriggerWiperValue = cfxZones.getFlagValue(theZone.triggerWiperFlag, theZone)
end
local theCat = cfxZones.getStringFromZoneProperty(theZone, "category", "static")
if cfxZones.hasProperty(theZone, "wipeCategory") then
theCat = cfxZones.getStringFromZoneProperty(theZone, "wipeCategory", "static")
end
if cfxZones.hasProperty(theZone, "wipeCat") then
theCat = cfxZones.getStringFromZoneProperty(theZone, "wipeCat", "static")
end
theZone.wipeCategory = dcsCommon.string2ObjectCat(theCat)
if cfxZones.hasProperty(theZone, "wipeNamed") then
theZone.wipeNamed = cfxZones.getStringFromZoneProperty(theZone, "wipeNamed", "<no name given>")
theZone.oWipeNamed = theZone.wipeNamed -- save original
-- assemble list of all names to wipe, including wildcard
local allNames = {}
if dcsCommon.containsString(theZone.wipeNamed, ",") then
allNames = dcsCommon.splitString(theZone.wipeNamed, ",")
allNames = dcsCommon.trimArray(allNames)
else
allNames = {dcsCommon.trim(theZone.wipeNamed)}
end
-- assemble dict of all wipeNamed and endswith
local theDict = {}
for idx, aName in pairs(allNames) do
local shortName = aName
local ew = dcsCommon.stringEndsWith(aName, "*")
if ew then
shortName = dcsCommon.removeEnding(aName, "*")
end
theDict[shortName] = ew
if wiper.verbose or theZone.verbose then
trigger.action.outText("+++wpr: dict [".. shortName .."] = " .. dcsCommon.bool2Text(ew),30)
end
end
theZone.wipeNamed = theDict
end
theZone.wipeInventory = cfxZones.getBoolFromZoneProperty(theZone, "wipeInventory", false)
if wiper.verbose or theZone.verbose then
trigger.action.outText("+++wpr: new wiper zone <".. theZone.name ..">", 30)
end
end
--
-- Wiper main action
--
function wiper.objectHandler(theObject, theCollector)
table.insert(theCollector, theObject)
return true
end
wiper.inventory = ""
function wiper.seeZoneInventory(theZone)
-- run a diag which objects are in the zone, and which cat they are
-- set up args
local allCats = {1, 2, 3, 4, 5, 6}
wiper.inventory = ""
for idx, aCat in pairs(allCats) do
local p = cfxZones.getPoint(theZone)
local lp = {x = p.x, y = p.z}
p.y = land.getHeight(lp)
local collector = {}
-- now build the search argument
local args = {
id = world.VolumeType.SPHERE,
params = {
point = p,
radius = theZone.radius
}
}
-- now call search
world.searchObjects(aCat, args, wiper.objectHandler, collector)
wiper.inventory = wiper.inventory .. "Cat = " .. aCat .. ":"
for idy, anObject in pairs(collector) do
wiper.inventory = wiper.inventory .. anObject:getName() .. " "
end
wiper.inventory = wiper.inventory .. "\n"
end
end
function wiper.isTriggered(theZone)
-- see if we need a diagnostic run
wiper.inventory = ""
if theZone.wipeInventory then
wiper.seeZoneInventory(theZone)
-- inventory data
if theZone.wipeInventory then
trigger.action.outText(wiper.inventory, 30)
end
end
-- get current location in case theZone is moving
local p = cfxZones.getPoint(theZone)
local lp = {x = p.x, y = p.z}
p.y = land.getHeight(lp)
local collector = {}
-- now build the search argument
local args = {
id = world.VolumeType.SPHERE,
params = {
point = p,
radius = theZone.radius
}
}
-- set up remaining arguments
local cat = theZone.wipeCategory -- Object.Category.STATIC
-- now call search
world.searchObjects(cat, args, wiper.objectHandler, collector)
if #collector < 1 and (wiper.verbose or theZone.verbose) then
trigger.action.outText("+++wpr: world search returned zero elements for <" .. theZone.name .. "> (cat=" .. theZone.wipeCategory .. ")",30)
end
-- wipe'em!
for idx, anObject in pairs(collector) do
local doWipe = true
-- see if we filter to only named objects
if theZone.wipeNamed then
doWipe = false
local oName = tostring(anObject:getName()) -- prevent number mismatch
for wipeName, beginsWith in pairs(theZone.wipeNamed) do
if beginsWith then
doWipe = doWipe or dcsCommon.stringStartsWith(oName, wipeName)
else
doWipe = doWipe or oName == wipeName
end
end
if wiper.verbose or theZone.verbose then
if not doWipe then
trigger.action.outText("+++wpr: <"..oName.."> not removed, name restriction <" .. theZone.oWipeNamed .. "> not met.",30)
end
end
end
if doWipe then
if wiper.verbose or theZone.verbose then
trigger.action.outText("+++wpr: wiping " .. anObject:getName(), 30)
end
anObject:destroy()
else
if wiper.verbose or theZone.verbose then
trigger.action.outText("+++wpr: spared object <" .. anObject:getName() .. ">",30)
end
end
end
end
--
-- Update
--
function wiper.update()
-- call me in a second to poll triggers
timer.scheduleFunction(wiper.update, {}, timer.getTime() + 1/wiper.ups)
for idx, aZone in pairs(wiper.wipers) do
if cfxZones.testZoneFlag(aZone, aZone.triggerWiperFlag, aZone.triggerWiperMethod, "lastTriggerWiperValue") then
if wiper.verbose or aZone.verbose then
trigger.action.outText("+++wpr: triggered on ".. aZone.triggerWiperFlag .. " for <".. aZone.name ..">", 30)
end
wiper.isTriggered(aZone)
end
end
end
--
-- Config & Start
--
function wiper.readConfigZone()
local theZone = cfxZones.getZoneByName("wiperConfig")
if not theZone then
if wiper.verbose then
trigger.action.outText("+++wpr: NO config zone!", 30)
end
theZone = cfxZones.createSimpleZone("wiperConfig") -- temp only
end
wiper.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
wiper.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 1)
if wiper.verbose then
trigger.action.outText("+++wpr: read config", 30)
end
end
function wiper.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx Wiper requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx Wiper", wiper.requiredLibs) then
return false
end
-- read config
wiper.readConfigZone()
-- process cloner Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("wipe?")
for k, aZone in pairs(attrZones) do
wiper.createWiperWithZone(aZone) -- process attributes
wiper.addWiper(aZone) -- add to list
end
-- start update
wiper.update()
trigger.action.outText("cfx Wiper v" .. wiper.version .. " started.", 30)
return true
end
-- let's go!
if not wiper.start() then
trigger.action.outText("cfx Wiper aborted: missing libraries", 30)
wiper = nil
end

View File

@ -1,5 +1,5 @@
xFlags = {} xFlags = {}
xFlags.version = "1.0.1" xFlags.version = "1.2.0"
xFlags.verbose = false xFlags.verbose = false
xFlags.ups = 1 -- overwritten in get config when configZone is present xFlags.ups = 1 -- overwritten in get config when configZone is present
xFlags.requiredLibs = { xFlags.requiredLibs = {
@ -13,6 +13,8 @@ xFlags.requiredLibs = {
1.0.0 - Initial version 1.0.0 - Initial version
1.0.1 - allow flags names for ops as well 1.0.1 - allow flags names for ops as well
1.1.0 - Watchflags harmonization 1.1.0 - Watchflags harmonization
1.2.0 - xDirect flag,
- direct array support
--]]-- --]]--
xFlags.xFlagZones = {} xFlags.xFlagZones = {}
@ -62,13 +64,17 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.xHasFired = false theZone.xHasFired = false
theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "xSuccess!", "<none>") theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "xSuccess!", "<none>")
if cfxZones.hasProperty(theZone, "out!") then if cfxZones.hasProperty(theZone, "out!") then
theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "out!", "<none>") theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "out!", "*<none>")
end end
if cfxZones.hasProperty(theZone, "xChange!") then if cfxZones.hasProperty(theZone, "xChange!") then
theZone.xChange = cfxZones.getStringFromZoneProperty(theZone, "xChange!", "<none>") theZone.xChange = cfxZones.getStringFromZoneProperty(theZone, "xChange!", "*<none>")
end end
theZone.xDirect = cfxZones.getStringFromZoneProperty(theZone, "xDirect!", "*<none>")
theZone.inspect = cfxZones.getStringFromZoneProperty(theZone, "require", "or") -- same as any theZone.inspect = cfxZones.getStringFromZoneProperty(theZone, "require", "or") -- same as any
-- supported any/or, all/and, moreThan, atLeast, exactly -- supported any/or, all/and, moreThan, atLeast, exactly
theZone.inspect = string.lower(theZone.inspect) theZone.inspect = string.lower(theZone.inspect)
@ -89,13 +95,15 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.xLastReset = cfxZones.getFlagValue(theZone.xReset, theZone) theZone.xLastReset = cfxZones.getFlagValue(theZone.xReset, theZone)
end end
theZone.xMethod = cfxZones.getStringFromZoneProperty(theZone, "xMethod", "flip") theZone.xMethod = cfxZones.getStringFromZoneProperty(theZone, "xMethod", "inc")
if cfxZones.hasProperty(theZone, "method") then if cfxZones.hasProperty(theZone, "method") then
theZone.xMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "flip") theZone.xMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
end end
theZone.xOneShot = cfxZones.getBoolFromZoneProperty(theZone, "oneShot", true) theZone.xOneShot = cfxZones.getBoolFromZoneProperty(theZone, "oneShot", true)
end end
function xFlags.evaluateFlags(theZone) function xFlags.evaluateFlags(theZone)
@ -187,21 +195,28 @@ end
function xFlags.evaluateZone(theZone) function xFlags.evaluateZone(theZone)
-- short circuit if we are done
if theZone.xHasFired and theZone.xOneShot then return end
local hits, checkSum = xFlags.evaluateFlags(theZone) local hits, checkSum = xFlags.evaluateFlags(theZone)
-- depending on inspect see what the outcome is -- depending on inspect see what the outcome is
-- supported any/or, all/and, moreThan, atLeast, exactly -- supported any/or, all/and, moreThan, atLeast, exactly
local op = theZone.inspect local op = theZone.inspect
local evalResult = false local evalResult = false
if (op == "or" or op == "any") and hits > 0 then if (op == "or" or op == "any" or op == "some") and hits > 0 then
evalResult = true evalResult = true
elseif (op == "and" or op == "all") and hits == #theZone.flagNames then elseif (op == "and" or op == "all") and hits == #theZone.flagNames then
evalResult = true evalResult = true
elseif (op == "morethan" or op == "more than") and hits > theZone.matchNum then elseif (op == "morethan" or op == "more than") and hits > theZone.matchNum then
evalResult = true evalResult = true
elseif (op == "atleast" or op == "at lest") and hits >= theZone.matchNum then elseif (op == "atleast" or op == "at least") and hits >= theZone.matchNum then
evalResult = true evalResult = true
elseif op == "exactly" and hits == theZone.matchNum then elseif op == "exactly" and hits == theZone.matchNum then
evalResult = true evalResult = true
elseif (op == "none" or op == "nor") and hits == 0 then
evalResult = true
elseif (op == "not all" or op == "notall" or op == "nand") and hits < #theZone.flagNames then
evalResult = true
end end
-- now check if changed and if result true -- now check if changed and if result true
@ -219,7 +234,17 @@ function xFlags.evaluateZone(theZone)
theZone.flagChecksum = checkSum theZone.flagChecksum = checkSum
end end
if theZone.xHasFired and theZone.xOneShot then return end -- now directly set the value of evalResult (0 = false, 1 = true)
-- to "xDirect!". Always sets output to current result of evaluation
-- true (1)/false(0), no matter if changed or not
if evalResult then
cfxZones.setFlagValueMult(theZone.xDirect, 1, theZone)
else
cfxZones.setFlagValueMult(theZone.xDirect, 0, theZone)
end
-- now see if we bang the output according to method
if evalResult then if evalResult then
if xFlags.verbose then if xFlags.verbose then
trigger.action.outText("+++xFlag: success bang! on " .. theZone.xSuccess .. " for " .. theZone.name, 30) trigger.action.outText("+++xFlag: success bang! on " .. theZone.xSuccess .. " for " .. theZone.name, 30)