Version 0.998

xFlags
Radio Trigger
messenger simplification
bang! constants
This commit is contained in:
Christian Franz 2022-04-14 14:37:11 +02:00
parent 2b97597e83
commit 284063b829
18 changed files with 630 additions and 1845 deletions

Binary file not shown.

Binary file not shown.

View File

@ -62,8 +62,6 @@ cfxGroundTroops.deployedTroops = {}
-- 1.7.5 - some troop.group hardening with isExist()
-- an entry into the deployed troop has the following attributes
-- - group - the group
-- - orders: "guard" - will guard the spot and look for enemies in range

View File

@ -1,5 +1,5 @@
cfxSSBClient = {}
cfxSSBClient.version = "2.0.2"
cfxSSBClient.version = "2.0.3"
cfxSSBClient.verbose = false
cfxSSBClient.singleUse = false -- set to true to block crashed planes
-- NOTE: singleUse (true) requires SSB to disable immediate respawn after kick
@ -38,6 +38,8 @@ Version History
2.0.1 - stricter verbosity: moved more comments to verbose only
2.0.2 - health check code (initial)
- added verbosity
2.0.3 - getPlayerName nil-trap on cloned player planes guard
in onEvent
WHAT IT IS
SSB Client is a small script that forms the client-side counterpart to
@ -268,7 +270,12 @@ function cfxSSBClient:onEvent(event)
local theUnit = event.initiator -- we know this exists
local uName = theUnit:getName()
if not uName then return end
-- player entered unit
-- player entered unit?
-- check if this is cloned impostor
if not theUnit.getPlayerName then
trigger.action.outText("+++SSBC: non-player client " .. uName .. " detected, ignoring.", 30)
return
end
local playerName = theUnit:getPlayerName()
if not playerName then
return -- NPC plane

File diff suppressed because it is too large Load Diff

View File

@ -11,6 +11,15 @@ changer.changers = {}
Version History
1.0.0 - Initial version
Transmogrify an incoming signal to an output signal
- not
- bool
- value
- rnd
- count (? multiple signals, better done with xFlags)
- min, max minmax 2,3, cap,
--]]--
function changer.addChanger(theZone)
@ -31,50 +40,70 @@ end
--
-- read zone
--
function wiper.createWiperWithZone(theZone)
theZone.triggerWiperFlag = cfxZones.getStringFromZoneProperty(theZone, "wipe?", "*<none>")
function changer.createChangerWithZone(theZone)
theZone.triggerChangerFlag = cfxZones.getStringFromZoneProperty(theZone, "change?", "*<none>")
-- if theZone.triggerChangerFlag then
theZone.lastTriggerChangeValue = cfxZones.getFlagValue(theZone.triggerChangerFlag, theZone)
-- end
-- triggerWiperMethod
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerWiperMethod") then
theZone.triggerWiperMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerWiperMethod", "change")
-- triggerChangerMethod
theZone.triggerChangerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerChangerMethod") then
theZone.triggerChangerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerChangerMethod", "change")
end
if theZone.triggerWiperFlag then
theZone.lastTriggerWiperValue = cfxZones.getFlagValue(theZone.triggerWiperFlag, theZone)
end
theZone.inEval = cfxZones.getBoolFromZoneProperty(theZone, "inEval", true) -- yes/no to pre-process, default is yes
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")
theZone.changeTo = cfxZones.getStringFromZoneProperty(theZone, "to", "val") -- val, not, bool
theZone.changeTo = string.lower(theZone.changeTo)
theZone.changeTo = dcsCommon.trim(theZone.changeTo)
theZone.changeOut = cfxZones.getStringFromZoneProperty(theZone, "out!", "*none")
if cfxZones.hasProperty(theZone, "changeOut!") then
theZone.changeOut = cfxZones.getStringFromZoneProperty(theZone, "changeOut!", "*none")
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)
if changer.verbose or theZone.verbose then
trigger.action.outText("+++chgr: new changer zone <".. theZone.name ..">", 30)
end
end
--
-- MAIN ACTION
--
function changer.isTriggered(theZone)
function changer.process(theZone)
-- read the line
local inVal = cfxZones.getFlagValue(theZone.triggerChangerFlag, theZone)
currVal = inVal
if theZone.inEval then
currVal = cfxZones.evalFlagMethodImmediate(currVal, theZone.triggerChangerMethod, theZone)
end
if type(currVal) == "boolean" then
if currVal then currVal = 1 else currVal = 0 end
end
local res = currVal
local op = theZone.changeTo
-- process and write outflag
if op == "bool" then
if currVal == 0 then res = 0 else res = 1 end
elseif
op == "not" then
if currVal == 0 then res = 1 else res = 0 end
end
-- all others drop through
-- write out
cfxZones.setFlagValueMult(theZone.changeOut, res, theZone)
if changer.verbose or theZone.verbose then
trigger.action.outText("+++chgr: changed <" .. inVal .. "> via op=(" .. op .. ") to <" .. res .. "> for <" .. theZone.name .. ">", 10)
end
-- remember last value in case we need it
theZone.lastTriggerChangeValue = currVal -- we should never need to use this, but leave it in for now. note we save currVal, not res...
end
@ -87,8 +116,7 @@ function changer.update()
timer.scheduleFunction(changer.update, {}, timer.getTime() + 1/changer.ups)
for idx, aZone in pairs(changer.changers) do
changer.process(aZone)
end
end
@ -114,35 +142,35 @@ function changer.readConfigZone()
end
end
function wiper.start()
function changer.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx Wiper requires dcsCommon", 30)
trigger.action.outText("cfx changer requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx Wiper", wiper.requiredLibs) then
if not dcsCommon.libCheck("cfx changer", changer.requiredLibs) then
return false
end
-- read config
wiper.readConfigZone()
changer.readConfigZone()
-- process cloner Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("wipe?")
local attrZones = cfxZones.getZonesWithAttributeNamed("change?")
for k, aZone in pairs(attrZones) do
wiper.createWiperWithZone(aZone) -- process attributes
wiper.addWiper(aZone) -- add to list
changer.createChangerWithZone(aZone) -- process attributes
changer.addChanger(aZone) -- add to list
end
-- start update
wiper.update()
changer.update()
trigger.action.outText("cfx Wiper v" .. wiper.version .. " started.", 30)
trigger.action.outText("cfx Changer v" .. changer.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
if not changer.start() then
trigger.action.outText("cfx changer aborted: missing libraries", 30)
changer = nil
end

View File

@ -69,6 +69,7 @@ dcsCommon.version = "2.5.9"
2.5.7 - point2text(p)
2.5.8 - string2GroupCat()
2.5.9 - string2ObjectCat()
2.6.0 - unified uuid, removed uuIdent
--]]--
@ -78,7 +79,8 @@ dcsCommon.version = "2.5.9"
dcsCommon.verbose = false -- set to true to see debug messages. Lots of them
dcsCommon.uuidStr = "uuid-"
dcsCommon.simpleUUID = 76543 -- a number to start. as good as any
-- globals
dcsCommon.cbID = 0 -- callback id for simple callback scheduling
dcsCommon.troopCarriers = {"Mi-8MT", "UH-1H", "Mi-24P"} -- Ka-50 and Gazelle can't carry troops
@ -1896,16 +1898,16 @@ dcsCommon.version = "2.5.9"
end
dcsCommon.simpleUUID = 76543 -- a number to start. as good as any
function dcsCommon.numberUUID()
dcsCommon.simpleUUID = dcsCommon.simpleUUID + 1
return dcsCommon.simpleUUID
end
function dcsCommon.uuid(prefix)
dcsCommon.uuIdent = dcsCommon.uuIdent + 1
--dcsCommon.uuIdent = dcsCommon.uuIdent + 1
if not prefix then prefix = dcsCommon.uuidStr end
return prefix .. "-" .. dcsCommon.uuIdent
return prefix .. "-" .. dcsCommon.numberUUID() -- dcsCommon.uuIdent
end
function dcsCommon.event2text(id)
@ -2194,7 +2196,7 @@ end
-- init any variables the lib requires internally
function dcsCommon.init()
cbID = 0
dcsCommon.uuIdent = 0
--dcsCommon.uuIdent = 0
if (dcsCommon.verbose) or true then
trigger.action.outText("dcsCommon v" .. dcsCommon.version .. " loaded", 10)
end

View File

@ -1,5 +1,5 @@
groupTracker = {}
groupTracker.version = "1.1.0"
groupTracker.version = "1.1.1"
groupTracker.verbose = false
groupTracker.ups = 1
groupTracker.requiredLibs = {
@ -14,6 +14,7 @@ groupTracker.trackers = {}
1.1.0 - filtering added
- array support for trackers
- array support for trackers
1.1.1 - corrected clone zone reference bug
--]]--
@ -199,7 +200,7 @@ function groupTracker.trackGroupsInZone(theZone)
else
for idy, aGroup in pairs(theGroups) do
groupTracker.addGroupToTracker(aGroup, theTracker)
if cloneZones.verbose or theZone.verbose then
if groupTracker.verbose or theZone.verbose then
trigger.action.outText("+++gTrk-TW: added " .. theGroup:getName() .. " to tracker " .. theName, 30)
end
end

View File

@ -1,5 +1,5 @@
messenger = {}
messenger.version = "1.2.1"
messenger.version = "1.3.0"
messenger.verbose = false
messenger.requiredLibs = {
"dcsCommon", -- always
@ -19,7 +19,8 @@ messenger.messengers = {}
- messageOn?
- messageOff?
1.2.0 - msgTriggerMethod (original Watchflag integration)
1.2.1 - qoL: <n> = newline, <z> = zone name, <v> = value
1.2.1 - qoL: <n> = newline, <z> = zone name, <v> = value
1.3.0 - messenger? saves messageOut? attribute
--]]--
function messenger.addMessenger(theZone)
@ -56,6 +57,7 @@ end
function messenger.createMessengerWithZone(theZone)
-- start val - a range
local aMessage = cfxZones.getStringFromZoneProperty(theZone, "message", "")
theZone.message = messenger.preProcMessage(aMessage, theZone)
@ -76,10 +78,13 @@ function messenger.createMessengerWithZone(theZone)
theZone.msgTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "msgTriggerMethod", "change")
end
-- trigger flag f? in? messageOut?
-- trigger flag f? in? messageOut?, add messenger?
if cfxZones.hasProperty(theZone, "f?") then
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
end
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
-- may want to add deprecated note later
end
-- can also use in? for counting. we always use triggerMessagerFlag
if cfxZones.hasProperty(theZone, "in?") then
@ -90,9 +95,17 @@ function messenger.createMessengerWithZone(theZone)
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "messageOut?", "none")
end
if theZone.triggerMessagerFlag then
theZone.lastMessageTriggerValue = cfxZones.getFlagValue(theZone.triggerMessagerFlag, theZone)-- trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value
end
-- try default only if no other is set
if not theZone.triggerMessagerFlag then
if not cfxZones.hasProperty(theZone, "messenger?") then
trigger.action.outText("*** Note: messenger in <" .. theZone.name .. "> can't be triggered", 30)
end
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "messenger?", "none")
end
-- if theZone.triggerMessagerFlag then
theZone.lastMessageTriggerValue = cfxZones.getFlagValue(theZone.triggerMessagerFlag, theZone)-- save last value
-- end
theZone.messageOff = false
if cfxZones.hasProperty(theZone, "messageOff?") then
@ -238,13 +251,21 @@ function messenger.start()
-- read config
messenger.readConfigZone()
-- process cloner Zones
-- process messenger Zones
-- old style
local attrZones = cfxZones.getZonesWithAttributeNamed("messenger")
for k, aZone in pairs(attrZones) do
messenger.createMessengerWithZone(aZone) -- process attributes
messenger.addMessenger(aZone) -- add to list
end
-- new style that saves messageOut? flag by reading flags
attrZones = cfxZones.getZonesWithAttributeNamed("messenger?")
for k, aZone in pairs(attrZones) do
messenger.createMessengerWithZone(aZone) -- process attributes
messenger.addMessenger(aZone) -- add to list
end
-- start update
messenger.update()

127
modules/module template.lua Normal file
View File

@ -0,0 +1,127 @@
tmpl = {}
tmpl.version = "0.0.0"
tmpl.verbose = false
tmpl.ups = 1
tmpl.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
tmpl.tmpls = {}
--[[--
Version History
--]]--
function tmpl.addTmpl(theZone)
table.insert(tmpl.tmpls, theZone)
end
function tmpl.getTmplByName(aName)
for idx, aZone in pairs(tmpl.tmpls) do
if aName == aZone.name then return aZone end
end
if tmpl.verbose then
trigger.action.outText("+++tmpl: no tmpl with name <" .. aName ..">", 30)
end
return nil
end
--
-- read zone
--
function tmpl.createTmplWithZone(theZone)
-- read main trigger
theZone.triggerTmplFlag = cfxZones.getStringFromZoneProperty(theZone, "tmpl?", "*<none>")
theZone.lastTriggerTmplValue = cfxZones.getFlagValue(theZone.triggerTmplFlag, theZone)
-- TriggerMethod: common and specific synonym
theZone.tmplTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "tmplTriggerMethod") then
theZone.tmplTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "tmplTriggerMethod", "change")
end
if tmpl.verbose or theZone.verbose then
trigger.action.outText("+++tmpl: new tmpl zone <".. theZone.name ..">", 30)
end
end
--
-- MAIN ACTION
--
function tmpl.process(theZone)
end
--
-- Update
--
function tmpl.update()
-- call me in a second to poll triggers
timer.scheduleFunction(tmpl.update, {}, timer.getTime() + 1/tmpl.ups)
for idx, aZone in pairs(tmpl.tmpls) do
-- see if we are triggered
if cfxZones.testZoneFlag(aZone, aZone.triggerTmplFlag, aZone.tmplTriggerMethod, "lastTriggerTmplValue") then
if tmpl.verbose or theZone.verbose then
trigger.action.outText("+++tmpl: triggered on main? for <".. aZone.name ..">", 30)
end
tmpl.process(aZone)
end
end
end
--
-- Config & Start
--
function tmpl.readConfigZone()
local theZone = cfxZones.getZoneByName("tmplConfig")
if not theZone then
if tmpl.verbose then
trigger.action.outText("+++tmpl: NO config zone!", 30)
end
return
end
tmpl.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
if tmpl.verbose then
trigger.action.outText("+++tmpl: read config", 30)
end
end
function tmpl.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx tmpl requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx tmpl", tmpl.requiredLibs) then
return false
end
-- read config
tmpl.readConfigZone()
-- process tmpl Zones
-- old style
local attrZones = cfxZones.getZonesWithAttributeNamed("tmpl")
for k, aZone in pairs(attrZones) do
tmpl.createTmplWithZone(aZone) -- process attributes
tmpl.addTmpl(aZone) -- add to list
end
-- start update
tmpl.update()
trigger.action.outText("cfx tmpl v" .. tmpl.version .. " started.", 30)
return true
end
-- let's go!
if not tmpl.start() then
trigger.action.outText("cfx tmpl aborted: missing libraries", 30)
tmpl = nil
end

147
modules/radioTrigger.lua Normal file
View File

@ -0,0 +1,147 @@
radioTrigger = {}
radioTrigger.version = "1.0.0"
radioTrigger.verbose = false
radioTrigger.ups = 1
radioTrigger.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
radioTrigger.radioTriggers = {}
--[[--
Version History
1.0.0 - initial version
--]]--
function radioTrigger.addRadioTrigger(theZone)
table.insert(radioTrigger.radioTriggers, theZone)
end
function radioTrigger.getRadioTriggerByName(aName)
for idx, aZone in pairs(radioTrigger.radioTriggers) do
if aName == aZone.name then return aZone end
end
if radioTrigger.verbose then
trigger.action.outText("+++radioTrigger: no radioTrigger with name <" .. aName ..">", 30)
end
return nil
end
--
-- read zone
--
function radioTrigger.createRadioTriggerWithZone(theZone)
-- read main trigger
theZone.triggerRadioFlag = cfxZones.getStringFromZoneProperty(theZone, "radio?", "*<none>")
theZone.lastRadioTriggerValue = cfxZones.getFlagValue(theZone.triggerRadioFlag, theZone)
-- TriggerMethod: common and specific synonym
theZone.radioTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "radioTriggerMethod") then
theZone.radioTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "radioTriggerMethod", "change")
end
-- out method
theZone.rtMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
if cfxZones.hasProperty(theZone, "rtMethod") then
theZone.rtMethod = cfxZones.getStringFromZoneProperty(theZone, "rtMethod", "inc")
end
-- out flag
theZone.rtOutFlag = cfxZones.getStringFromZoneProperty(theZone, "out!", "*<none>")
if cfxZones.hasProperty(theZone, "rtOut!") then
theZone.rtOutFlag = cfxZones.getStringFromZoneProperty(theZone, "rtOut!", "*<none>")
end
if radioTrigger.verbose or theZone.verbose then
trigger.action.outText("+++rTrg: new radioTrigger zone <".. theZone.name ..">", 30)
end
end
--
-- MAIN ACTION
--
function radioTrigger.process(theZone)
-- we are triggered, simply poll the out flag
cfxZones.pollFlag(theZone.rtOutFlag, theZone.rtMethod, theZone)
end
--
-- Update
--
function radioTrigger.update()
-- call me in a second to poll triggers
timer.scheduleFunction(radioTrigger.update, {}, timer.getTime() + 1/radioTrigger.ups)
for idx, aZone in pairs(radioTrigger.radioTriggers) do
-- see if we are triggered
local origSave = aZone.lastRadioTriggerValue
if cfxZones.testZoneFlag(aZone, aZone.triggerRadioFlag, aZone.radioTriggerMethod, "lastRadioTriggerValue") then
if radioTrigger.verbose or aZone.verbose then
trigger.action.outText("+++rTrg: triggered on radio? for <".. aZone.name ..">", 30)
end
radioTrigger.process(aZone)
-- now RESET both trigger and last trigger
-- so radio can be used again
cfxZones.setFlagValue(aZone.triggerRadioFlag, origSave, aZone)
aZone.lastRadioTriggerValue = origSave
end
end
end
--
-- Config & Start
--
function radioTrigger.readConfigZone()
local theZone = cfxZones.getZoneByName("radioTriggerConfig")
if not theZone then
if radioTrigger.verbose then
trigger.action.outText("+++radioTrigger: NO config zone!", 30)
end
return
end
radioTrigger.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
if radioTrigger.verbose then
trigger.action.outText("+++radioTrigger: read config", 30)
end
end
function radioTrigger.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx radioTrigger requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx radioTrigger", radioTrigger.requiredLibs) then
return false
end
-- read config
radioTrigger.readConfigZone()
-- process radioTrigger Zones
-- old style
local attrZones = cfxZones.getZonesWithAttributeNamed("radio?")
for k, aZone in pairs(attrZones) do
radioTrigger.createRadioTriggerWithZone(aZone) -- process attributes
radioTrigger.addRadioTrigger(aZone) -- add to list
end
-- start update
radioTrigger.update()
trigger.action.outText("cfx radioTrigger v" .. radioTrigger.version .. " started.", 30)
return true
end
-- let's go!
if not radioTrigger.start() then
trigger.action.outText("cfx radioTrigger aborted: missing libraries", 30)
radioTrigger = nil
end

View File

@ -1,5 +1,5 @@
xFlags = {}
xFlags.version = "1.2.0"
xFlags.version = "1.2.1"
xFlags.verbose = false
xFlags.ups = 1 -- overwritten in get config when configZone is present
xFlags.requiredLibs = {
@ -15,6 +15,13 @@ xFlags.requiredLibs = {
1.1.0 - Watchflags harmonization
1.2.0 - xDirect flag,
- direct array support
1.2.1 - verbosity changes
- "most" operator
- "half or more" operator
- fixed reset
- xSuccess optimizations
- inc, dec, quoted flags
- matchNum can carry flag
--]]--
xFlags.xFlagZones = {}
@ -25,7 +32,7 @@ end
--
-- create xFlag
--
function xFlags.reset()
function xFlags.reset(theZone)
for i = 1, #theZone.flagNames do
-- since the checksum is order dependent,
-- we must preserve the order of the array
@ -33,7 +40,9 @@ function xFlags.reset()
theZone.startFlagValues[i] = cfxZones.getFlagValue(flagName, theZone)
theZone.flagResults[i] = false
theZone.flagChecksum = theZone.flagChecksum .. "0"
trigger.action.outText("+++xF: flag " .. flagName, 30)
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xF: zone <" .. theZone.name .. "> flag " .. flagName, 30)
end
end
theZone.xHasFired = false
end
@ -59,16 +68,23 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.startFlagValues[i] = cfxZones.getFlagValue(flagName, theZone)
theZone.flagResults[i] = false
theZone.flagChecksum = theZone.flagChecksum .. "0"
trigger.action.outText("+++xF: flag " .. flagName, 30)
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: <" .. theZone.name .. "> monitors flag " .. flagName, 30)
end
end
theZone.xHasFired = false
theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "xSuccess!", "<none>")
if cfxZones.hasProperty(theZone, "xSuccess!") then
theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "xSuccess!", "<none>")
end
if cfxZones.hasProperty(theZone, "out!") then
theZone.xSuccess = cfxZones.getStringFromZoneProperty(theZone, "out!", "*<none>")
end
if not theZone.xSuccess then
theZone.xSuccess = "*<none>"
end
if cfxZones.hasProperty(theZone, "xChange!") then
theZone.xChange = cfxZones.getStringFromZoneProperty(theZone, "xChange!", "*<none>")
end
@ -80,12 +96,10 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.inspect = string.lower(theZone.inspect)
theZone.inspect = dcsCommon.trim(theZone.inspect)
theZone.matchNum = cfxZones.getNumberFromZoneProperty(theZone, "#hits", 0)
theZone.matchNum = cfxZones.getStringFromZoneProperty(theZone, "#hits", "1")
theZone.xTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "xFlagMethod", "change") -- (<>=[number or reference flag], off, on, yes, no, true, false, change
theZone.xTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "xTriggerMethod", "change") -- (<>=[number or reference flag], off, on, yes, no, true, false, change
if cfxZones.hasProperty(theZone, "xTrigger") then
theZone.xTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "xTrigger", "change")
end
theZone.xTriggerMethod = string.lower(theZone.xTriggerMethod)
theZone.xTriggerMethod = dcsCommon.trim(theZone.xTriggerMethod)
@ -102,8 +116,31 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.xOneShot = cfxZones.getBoolFromZoneProperty(theZone, "oneShot", true)
end
function xFlags.evaluateNumOrFlag(theAttribute, theZone)
-- on entry, theAttribute contains a string
-- if it's a number, we return that, if it's a
-- string, we see if it's a quoted flag or
-- direct flag. in any way, we fetch and return
-- that flag's value
local aNum = tonumber(theAttribute)
if aNum then return aNum end
local remainder = dcsCommon.trim(theAttribute)
local esc = string.sub(remainder, 1, 1)
local last = string.sub(remainder, -1)
if esc == "(" and last == ")" and string.len(remainder) > 2 then
remainder = string.sub(remainder, 2, -2)
remainder = dcsCommon.trim(remainder)
end
if esc == "\"" and last == "\"" and string.len(remainder) > 2 then
remainder = string.sub(remainder, 2, -2)
remainder = dcsCommon.trim(remainder)
end
rNum = cfxZones.getFlagValue(remainder, theZone)
end
function xFlags.evaluateFlags(theZone)
@ -122,10 +159,34 @@ function xFlags.evaluateFlags(theZone)
local checkSum = ""
local firstChar = string.sub(op, 1, 1)
local remainder = string.sub(op, 2)
remainder = dcsCommon.trim(remainder) -- remove all leading and trailing spaces
local rNum = tonumber(remainder)
if not rNum then
-- interpret remainder as flag name
-- so we can say >*killMax
-- so we can say >*killMax or "22" with 22 a flag name
-- we use remainder as name for flag
-- PROCESS ESCAPE SEQUENCES
local esc = string.sub(remainder, 1, 1)
local last = string.sub(remainder, -1)
if esc == "@" then
remainder = string.sub(remainder, 2)
remainder = dcsCommon.trim(remainder)
end
if esc == "(" and last == ")" and string.len(remainder) > 2 then
-- note: iisues with startswith("(") ???
remainder = string.sub(remainder, 2, -2)
remainder = dcsCommon.trim(remainder)
end
if esc == "\"" and last == "\"" and string.len(remainder) > 2 then
remainder = string.sub(remainder, 2, -2)
remainder = dcsCommon.trim(remainder)
end
if cfxZones.verbose then
trigger.action.outText("+++zne: accessing flag <" .. remainder .. ">", 30)
end
rNum = cfxZones.getFlagValue(remainder, theZone)
end
@ -142,14 +203,14 @@ function xFlags.evaluateFlags(theZone)
else
checkSum = checkSum .. "0"
end
elseif op == "on" or op == "yes" or op == "true" then
elseif op == "on" or op == "yes" or op == "true" or op == "1" then
if currVals[i] ~= 0 then
hits = hits + 1
checkSum = checkSum .. "X"
else
checkSum = checkSum .. "0"
end
elseif op == "off" or op == "no" or op == "false"
elseif op == "off" or op == "no" or op == "false" or op == "0"
then
if currVals[i] == 0 then
hits = hits + 1
@ -158,6 +219,22 @@ function xFlags.evaluateFlags(theZone)
checkSum = checkSum .. "0"
end
elseif op == "inc" or op == "+1" then
if currVals[i] == theZone.startFlagValues[i] + 1 then
hits = hits + 1
checkSum = checkSum .. "X"
else
checkSum = checkSum .. "0"
end
elseif op == "dec" or op == "-1" then
if currVals[i] == theZone.startFlagValues[i] - 1 then
hits = hits + 1
checkSum = checkSum .. "X"
else
checkSum = checkSum .. "0"
end
elseif firstChar == "<" and rNum then
if currVals[i] < rNum then
hits = hits + 1
@ -183,7 +260,7 @@ function xFlags.evaluateFlags(theZone)
end
else
trigger.action.outText("+++xF: unknown xTriggerMethod: <" .. op .. ">", 30)
trigger.action.outText("+++xF: unknown xFlagMethod: <" .. op .. ">", 30)
return 0, ""
end
if xFlags.verbose and lastHits ~= hits then
@ -197,7 +274,9 @@ function xFlags.evaluateZone(theZone)
-- short circuit if we are done
if theZone.xHasFired and theZone.xOneShot then return end
-- calculate matchNum
local matchNum = xFlags.evaluateNumOrFlag(theZone.matchNum, theZone) -- convert or fetch
local hits, checkSum = xFlags.evaluateFlags(theZone)
-- depending on inspect see what the outcome is
-- supported any/or, all/and, moreThan, atLeast, exactly
@ -207,21 +286,28 @@ function xFlags.evaluateZone(theZone)
evalResult = true
elseif (op == "and" or op == "all") and hits == #theZone.flagNames then
evalResult = true
elseif (op == "morethan" or op == "more than") and hits > theZone.matchNum then
elseif (op == "morethan" or op == "more than") and hits > matchNum then
evalResult = true
elseif (op == "atleast" or op == "at least") and hits >= theZone.matchNum then
elseif (op == "atleast" or op == "at least") and hits >= matchNum then
evalResult = true
elseif op == "exactly" and hits == theZone.matchNum then
elseif op == "exactly" and hits == matchNum then
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
elseif (op == "most") and hits > (#theZone.flagNames / 2) then
evalResult = true
elseif (op == "half" or op == "at least half" or op == "half or more") and hits >= (#theZone.flagNames / 2) then
-- warning: 'half' means really 'at least half"
evalResult = true
end
-- add "most" to more than 50% of flagnum
-- now check if changed and if result true
if checkSum ~= theZone.flagChecksum then
if xFlags.verbose then
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: change detected for " .. theZone.name .. ": " .. theZone.flagChecksum .. "-->" ..checkSum, 30)
end
@ -232,6 +318,10 @@ function xFlags.evaluateZone(theZone)
end
end
theZone.flagChecksum = checkSum
else
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: no change, checksum is |" .. checkSum .. "| for <" .. theZone.name .. ">", 10)
end
end
-- now directly set the value of evalResult (0 = false, 1 = true)
@ -246,8 +336,8 @@ function xFlags.evaluateZone(theZone)
-- now see if we bang the output according to method
if evalResult then
if xFlags.verbose then
trigger.action.outText("+++xFlag: success bang! on " .. theZone.xSuccess .. " for " .. theZone.name, 30)
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: success bang! on <" .. theZone.xSuccess .. "> for <" .. theZone.name .. ">", 30)
end
cfxZones.pollFlag(theZone.xSuccess, theZone.xMethod, theZone)
theZone.xHasFired = true
@ -269,8 +359,8 @@ function xFlags.update()
local currVal = cfxZones.getFlagValue(theZone.xReset, theZone)
if currVal ~= theZone.xLastReset then
theZone.xLastReset = currVal
if xFlags.verbose then
trigger.action.outText("+++xF: reset command for " .. theZone.name, 30)
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: reset command for " .. theZone.name, 30)
end
xFlags.reset(theZone)
end
@ -285,7 +375,7 @@ function xFlags.readConfigZone()
local theZone = cfxZones.getZoneByName("xFlagsConfig")
if not theZone then
if xFlags.verbose then
trigger.action.outText("***xFlg: NO config zone!", 30)
trigger.action.outText("***xFlag: NO config zone!", 30)
end
return
end
@ -342,4 +432,9 @@ end
if not xFlags.start() then
trigger.action.outText("cf/x xFlags aborted: missing libraries", 30)
xFlags = nil
end
end
--[[--
Additional features:
- make #hits compatible to flags and numbers
--]]--

Binary file not shown.

Binary file not shown.