Version 1.1.9

new counter
massive upgrades to messenger
small upgrades to GuardianAngel
This commit is contained in:
Christian Franz 2022-11-10 09:03:15 +01:00
parent 5c1afa0c4b
commit 8f225cc30a
15 changed files with 622 additions and 59 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
baseCaptured={} baseCaptured={}
baseCaptured.version = "1.0.1" baseCaptured.version = "1.0.2"
baseCaptured.verbose = false baseCaptured.verbose = false
baseCaptured.ups = 1 baseCaptured.ups = 1
baseCaptured.requiredLibs = { baseCaptured.requiredLibs = {
@ -15,6 +15,8 @@ baseCaptured.handleContested = true --
1.0.0 - Initial version based on cloose's code 1.0.0 - Initial version based on cloose's code
1.0.1 - contested! flag 1.0.1 - contested! flag
- update and handleContested - update and handleContested
1.0.2 - expanded verbosity
- typo in defining redCaptured! corrected
--]]-- --]]--
@ -47,7 +49,7 @@ function baseCaptured.createZone(theZone)
end end
if cfxZones.hasProperty(theZone, "redCaptured!") then if cfxZones.hasProperty(theZone, "redCaptured!") then
theZone.redCap = cfxZones.getStringFromZoneProperty(theZone, "blueCaptured!", "*none") theZone.redCap = cfxZones.getStringFromZoneProperty(theZone, "redCaptured!", "*none")
end end
if cfxZones.hasProperty(theZone, "red!") then if cfxZones.hasProperty(theZone, "red!") then
@ -81,10 +83,16 @@ function baseCaptured.triggerZone(theZone)
if newOwner == 1 then -- red if newOwner == 1 then -- red
if theZone.redCap then if theZone.redCap then
cfxZones.pollFlag(theZone.redCap, theZone.capturedMethod, theZone) cfxZones.pollFlag(theZone.redCap, theZone.capturedMethod, theZone)
if baseCaptured.verbose or theZone.verbose then
trigger.action.outText("+++bCap: banging redCap! with <" .. theZone.redCap .. "> for zone <" .. theZone.name .. ">", 30)
end
end end
elseif newOwner == 2 then elseif newOwner == 2 then
if theZone.blueCap then if theZone.blueCap then
cfxZones.pollFlag(theZone.blueCap, theZone.capturedMethod, theZone) cfxZones.pollFlag(theZone.blueCap, theZone.capturedMethod, theZone)
if baseCaptured.verbose or theZone.verbose then
trigger.action.outText("+++bCap: banging blueCap! with <" .. theZone.blueCap .. "> for zone <" .. theZone.name .. ">", 30)
end
end end
else else
-- contested -- contested

View File

@ -1,5 +1,5 @@
cfxSpawnZones = {} cfxSpawnZones = {}
cfxSpawnZones.version = "1.7.0" cfxSpawnZones.version = "1.7.1"
cfxSpawnZones.requiredLibs = { cfxSpawnZones.requiredLibs = {
"dcsCommon", -- common is of course needed for everything "dcsCommon", -- common is of course needed for everything
-- pretty stupid to check for this since we -- pretty stupid to check for this since we
@ -61,6 +61,8 @@ cfxSpawnZones.spawnedGroups = {}
-- 1.5.3 - spawn?, spawnUnits? flags -- 1.5.3 - spawn?, spawnUnits? flags
-- 1.6.0 - trackwith interface for group tracker -- 1.6.0 - trackwith interface for group tracker
-- 1.7.0 - persistence support -- 1.7.0 - persistence support
-- 1.7.1 - improved verbosity
-- - spelling check
-- --
-- new version requires cfxGroundTroops, where they are -- new version requires cfxGroundTroops, where they are
-- --
@ -230,6 +232,10 @@ function cfxSpawnZones.createSpawner(inZone)
theSpawner.target = nil theSpawner.target = nil
end end
if cfxSpawnZones.verbose or inZone.verbose then
trigger.action.outText("+++spwn: created spawner for <" .. inZone.name .. ">", 30)
end
return theSpawner return theSpawner
end end
@ -326,6 +332,10 @@ function cfxSpawnZones.spawnWithSpawner(aSpawner)
if not aSpawner then return end if not aSpawner then return end
local theZone = aSpawner.zone -- retrieve the zone that defined me local theZone = aSpawner.zone -- retrieve the zone that defined me
if cfxSpawnZones.verbose or theZone.verbose then
trigger.action.outText("+++spwn: started spawn with spawner for <" .. theZone.name .. ">", 30)
end
-- will NOT check if conditions are met. This forces a spawn -- will NOT check if conditions are met. This forces a spawn
local unitTypes = {} -- build type names local unitTypes = {} -- build type names
--local p = aSpawner.zone.point --local p = aSpawner.zone.point

View File

@ -1,5 +1,5 @@
cfxZones = {} cfxZones = {}
cfxZones.version = "2.9.0" cfxZones.version = "2.9.1"
-- cf/x zone management module -- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable -- reads dcs zones and makes them accessible and mutable
@ -106,6 +106,9 @@ cfxZones.version = "2.9.0"
- linkUnit works for late-activating units - linkUnit works for late-activating units
- linkUnit now also works for player / clients, dynamic (re-)linking - linkUnit now also works for player / clients, dynamic (re-)linking
- linkUnit uses zone's origin for all calculations - linkUnit uses zone's origin for all calculations
- 2.9.1 - new evalRemainder()
- pollFlag supports +/- for immediate numbers, flags, number flags in parantheses
- stronger guards in hasProperty
--]]-- --]]--
cfxZones.verbose = false cfxZones.verbose = false
@ -1186,6 +1189,35 @@ function cfxZones.unPulseFlag(args)
cfxZones.setFlagValue(theFlag, newVal, theZone) cfxZones.setFlagValue(theFlag, newVal, theZone)
end end
function cfxZones.evalRemainder(remainder)
local rNum = tonumber(remainder)
if not rNum then
-- 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
return rNum
end
function cfxZones.doPollFlag(theFlag, method, theZone) function cfxZones.doPollFlag(theFlag, method, theZone)
if cfxZones.verbose then if cfxZones.verbose then
trigger.action.outText("+++zones: polling flag " .. theFlag .. " with " .. method, 30) trigger.action.outText("+++zones: polling flag " .. theFlag .. " with " .. method, 30)
@ -1198,14 +1230,19 @@ function cfxZones.doPollFlag(theFlag, method, theZone)
method = method:lower() method = method:lower()
method = dcsCommon.trim(method) method = dcsCommon.trim(method)
val = tonumber(method) val = tonumber(method)
if val then if dcsCommon.stringStartsWith(method, "+") or dcsCommon.stringStartsWith(method, "-")
cfxZones.setFlagValue(theFlag, val, theZone) then
if cfxZones.verbose or theZone.verbose then -- skip this processing, a legal Lua val can start with "+" or "-"
trigger.action.outText("+++zones: flag <" .. theFlag .. "> changed to #" .. val, 30) -- but we interpret it as a method
else
if val then
cfxZones.setFlagValue(theFlag, val, theZone)
if cfxZones.verbose or theZone.verbose then
trigger.action.outText("+++zones: flag <" .. theFlag .. "> changed to #" .. val, 30)
end
return
end end
return
end end
--trigger.action.outText("+++zones: polling " .. theZone.name .. " method " .. method .. " flag " .. theFlag, 30) --trigger.action.outText("+++zones: polling " .. theZone.name .. " method " .. method .. " flag " .. theFlag, 30)
local currVal = cfxZones.getFlagValue(theFlag, theZone) local currVal = cfxZones.getFlagValue(theFlag, theZone)
if method == "inc" or method == "f+1" then if method == "inc" or method == "f+1" then
@ -1233,6 +1270,21 @@ function cfxZones.doPollFlag(theFlag, method, theZone)
elseif dcsCommon.stringStartsWith(method, "pulse") then elseif dcsCommon.stringStartsWith(method, "pulse") then
cfxZones.pulseFlag(theFlag, method, theZone) cfxZones.pulseFlag(theFlag, method, theZone)
elseif dcsCommon.stringStartsWith(method, "+") then
-- we add whatever is to the right
local remainder = dcsCommon.removePrefix(method, "+")
local adder = cfxZones.evalRemainder(remainder)
cfxZones.setFlagValue(theFlag, currVal+adder, theZone)
if theZone.verbose then
trigger.action.outText("+++zones: (poll) updating with '+' flag <" .. theFlag .. "> in <" .. theZone.name .. "> by <" .. adder .. "> to <" .. adder + currVal .. ">", 30)
end
elseif dcsCommon.stringStartsWith(method, "-") then
-- we subtract whatever is to the right
local remainder = dcsCommon.removePrefix(method, "-")
local adder = cfxZones.evalRemainder(remainder)
cfxZones.setFlagValue(theFlag, currVal-adder, theZone)
else else
if method ~= "on" and method ~= "f=1" then if method ~= "on" and method ~= "f=1" then
trigger.action.outText("+++zones: unknown method <" .. method .. "> - using 'on'", 30) trigger.action.outText("+++zones: unknown method <" .. method .. "> - using 'on'", 30)
@ -1894,6 +1946,10 @@ function cfxZones.getPositiveRangeFromZoneProperty(theZone, theProperty, default
end end
function cfxZones.hasProperty(theZone, theProperty) function cfxZones.hasProperty(theZone, theProperty)
if not theProperty then
trigger.action.outText("+++zne: WARNING - hasProperty called with nil theProperty for zone <" .. theZone.name .. ">", 30)
return false
end
local foundIt = cfxZones.getZoneProperty(theZone, theProperty) local foundIt = cfxZones.getZoneProperty(theZone, theProperty)
if not foundIt then if not foundIt then
-- check for possible forgotten or exchanged IO flags -- check for possible forgotten or exchanged IO flags

View File

@ -1,9 +1,11 @@
cfxmon = {} cfxmon = {}
cfxmon.version = "1.0.0" cfxmon.version = "1.0.1"
cfxmon.delay = 30 -- seconds for display cfxmon.delay = 30 -- seconds for display
--[[-- --[[--
Version History Version History
1.0.0 - initial version 1.0.0 - initial version
1.0.1 - better guard for even.initiator to check if unit exists
- and handle static objcects and other non-grouped objects
cfxmon is a monitor for all cfx events and callbacks cfxmon is a monitor for all cfx events and callbacks
use monConfig to tell cfxmon which events and callbacks use monConfig to tell cfxmon which events and callbacks
@ -36,17 +38,22 @@ function cfxmon.rejected(event)
trigger.action.outText("***mon - dcsReject: " .. event.id .. " (" .. dcsCommon.event2text(event.id) .. ")", cfxmon.delay) trigger.action.outText("***mon - dcsReject: " .. event.id .. " (" .. dcsCommon.event2text(event.id) .. ")", cfxmon.delay)
end end
function cfxmon.dcsCB(event) function cfxmon.dcsCB(event) -- callback
local initiatorStat = "" local initiatorStat = ""
if event.initiator then if event.initiator and Unit.isExist(event.initiator) then
local theUnit = event.initiator local theUnit = event.initiator
local theGroup = theUnit:getGroup() -- we assume it is unit, but it can be a static object,
-- and may not have getGroup implemented!
if theUnit.getGroup then
local theGroup = theUnit:getGroup()
local theGroupName = "<none>" local theGroupName = "<none>"
if theGroup then theGroupName = theGroup:getName() end if theGroup then theGroupName = theGroup:getName() end
initiatorStat = ", for " .. theUnit:getName()
initiatorStat = ", for " .. theUnit:getName() initiatorStat = initiatorStat .. " of " .. theGroupName
initiatorStat = initiatorStat .. " of " .. theGroupName else
initiatorStat = ", non-unit (static?) " .. theUnit:getName()
end
else else
initiatorStat = ", NO Initiator" initiatorStat = ", NO Initiator"
end end

View File

@ -1,5 +1,5 @@
changer = {} changer = {}
changer.version = "1.0.3" changer.version = "1.0.4"
changer.verbose = false changer.verbose = false
changer.ups = 1 changer.ups = 1
changer.requiredLibs = { changer.requiredLibs = {
@ -13,6 +13,7 @@ changer.changers = {}
1.0.1 - Better guards in config to avoid <none> Zone getter warning 1.0.1 - Better guards in config to avoid <none> Zone getter warning
1.0.2 - on/off: verbosity 1.0.2 - on/off: verbosity
1.0.3 - NOT on/off 1.0.3 - NOT on/off
1.0.4 - a little bit more conversation
Transmogrify an incoming signal to an output signal Transmogrify an incoming signal to an output signal
- not - not
@ -224,7 +225,7 @@ function changer.update()
changer.process(aZone) changer.process(aZone)
else else
if changer.verbose or aZone.verbose then if changer.verbose or aZone.verbose then
trigger.action.outText("+++chgr: " .. aZone.name .. " gate closed.", 30) trigger.action.outText("+++chgr: " .. aZone.name .. " gate closed [flag <" .. aZone.changerOnOff .. "> is 0].", 30)
end end
end end
elseif aZone.changerOnOffINV then elseif aZone.changerOnOffINV then
@ -232,12 +233,16 @@ function changer.update()
changer.process(aZone) changer.process(aZone)
else else
if changer.verbose or aZone.verbose then if changer.verbose or aZone.verbose then
trigger.action.outText("+++chgr: " .. aZone.name .. " gate closed.", 30) trigger.action.outText("+++chgr: " .. aZone.name .. " gate closed [INVflag <" .. aZone.changerOnOffINV .. "> is 1].", 30)
end end
end end
else else
changer.process(aZone) changer.process(aZone)
end end
else
if aZone.verbose then
trigger.action.outText("+++chgr: <" .. aZone.name .. "> is paused.")
end
end end
end end
end end

121
modules/counter.lua Normal file
View File

@ -0,0 +1,121 @@
counter = {}
counter.version = "1.0.0"
counter.verbose = false
counter.ups = 1
counter.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
counter.counters = {}
--[[--
Version History
1.0.0 - Initial version
--]]--
function counter.addCounter(theZone)
table.insert(counter.counters, theZone)
end
function counter.getCounterByName(aName)
for idx, aZone in pairs(counter.counters) do
if aName == aZone.name then return aZone end
end
if counter.verbose then
trigger.action.outText("+++ctr: no counter with name <" .. aName ..">", 30)
end
return nil
end
function counter.createCounterWithZone(theZone)
theZone.counterInputFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "*<none>")
theZone.lastCounterInputFlag = cfxZones.getFlagValue(theZone.counterInputFlag, theZone)
-- triggerCounterMethod
theZone.triggerCounterMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerCountMethod") then
theZone.triggerCounterMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerChangeMethod", "change")
end
theZone.countMethod = cfxZones.getStringFromZoneProperty(theZone, "countMethod", "+1")
if cfxZones.hasProperty(theZone, "method") then
theZone.countMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "+1")
end
theZone.countOut = cfxZones.getStringFromZoneProperty(theZone, "out!", "<none>")
if cfxZones.hasProperty(theZone, "countOut!") then
theZone.countOut = cfxZones.getStringFromZoneProperty(theZone, "countOut!", "<none>")
end
end
--
-- Update
--
function counter.update()
-- call me in a second to poll triggers
timer.scheduleFunction(counter.update, {}, timer.getTime() + 1/counter.ups)
for idx, aZone in pairs(counter.counters) do
if cfxZones.testZoneFlag(aZone, aZone.counterInputFlag, aZone.triggerCounterMethod, "lastCounterInputFlag") then
cfxZones.pollFlag(aZone.countOut, aZone.countMethod, aZone)
end
end
end
--
-- Config & Start
--
function counter.readConfigZone()
local theZone = cfxZones.getZoneByName("counterConfig")
if not theZone then
if counter.verbose then
trigger.action.outText("+++ctr: NO config zone!", 30)
end
theZone = cfxZones.createSimpleZone("counterConfig") -- temp only
end
counter.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
counter.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 1)
if counter.verbose then
trigger.action.outText("+++ctr: read config", 30)
end
end
function counter.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx counter requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx counter", counter.requiredLibs) then
return false
end
-- read config
counter.readConfigZone()
-- process counter Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("count?")
for k, aZone in pairs(attrZones) do
counter.createCounterWithZone(aZone) -- process attributes
counter.addCounter(aZone) -- add to list
end
-- start update
counter.update()
trigger.action.outText("cfx counter v" .. counter.version .. " started.", 30)
return true
end
-- let's go!
if not counter.start() then
trigger.action.outText("cfx counter aborted: missing libraries", 30)
counter = nil
end

View File

@ -1,5 +1,5 @@
dcsCommon = {} dcsCommon = {}
dcsCommon.version = "2.7.7" dcsCommon.version = "2.7.9"
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB 2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB - clockPositionOfARelativeToB
@ -109,6 +109,15 @@ dcsCommon.version = "2.7.7"
- dumpVar2Str detects meta tables - dumpVar2Str detects meta tables
- rotateGroupData kills unit's psi value if it existed since it messes with heading - rotateGroupData kills unit's psi value if it existed since it messes with heading
- rotateGroupData - changes psi to -heading if it exists rather than nilling - rotateGroupData - changes psi to -heading if it exists rather than nilling
2.7.8 - new getGeneralDirection()
- new getNauticalDirection()
- more robust guards for getUnitSpeed
2.7.9 - new bool2Num(theBool)
- new aspectByDirection()
- createGroundGroupWithUnits corrected spelling of minDist, crashed scattered formation
- randomPointInCircle fixed erroneous local for x, z
- "scattered" formation repaired
--]]-- --]]--
-- dcsCommon is a library of common lua functions -- dcsCommon is a library of common lua functions
@ -663,7 +672,9 @@ dcsCommon.version = "2.7.7"
while direction < 0 do while direction < 0 do
direction = direction + 360 direction = direction + 360
end end
while direction >= 360 do
direction = direction - 360
end
if direction < 15 then -- special case 12 o'clock past 12 o'clock if direction < 15 then -- special case 12 o'clock past 12 o'clock
return 12 return 12
end end
@ -673,6 +684,54 @@ dcsCommon.version = "2.7.7"
end end
function dcsCommon.getGeneralDirection(direction) -- inspired by cws, improvements my own
if not direction then return "unkown" end
direction = math.fmod (direction, 360)
while direction < 0 do
direction = direction + 360
end
while direction >= 360 do
direction = direction - 360
end
if direction < 45 then return "ahead" end
if direction < 135 then return "right" end
if direction < 225 then return "behind" end
if direction < 315 then return "left" end
return "ahead"
end
function dcsCommon.getNauticalDirection(direction) -- inspired by cws, improvements my own
if not direction then return "unkown" end
direction = math.fmod (direction, 360)
while direction < 0 do
direction = direction + 360
end
while direction >= 360 do
direction = direction - 360
end
if direction < 45 then return "ahead" end
if direction < 135 then return "starboard" end
if direction < 225 then return "aft" end
if direction < 315 then return "port" end
return "ahead"
end
function dcsCommon.aspectByDirection(direction) -- inspired by cws, improvements my own
if not direction then return "unkown" end
direction = math.fmod (direction, 360)
while direction < 0 do
direction = direction + 360
end
while direction >= 360 do
direction = direction - 360
end
if direction < 45 then return "hot" end
if direction < 135 then return "beam" end
if direction < 225 then return "drag" end
if direction < 315 then return "beam" end
return "hot"
end
function dcsCommon.randomDegrees() function dcsCommon.randomDegrees()
local degrees = math.random(360) * 3.14152 / 180 local degrees = math.random(360) * 3.14152 / 180
@ -690,6 +749,8 @@ dcsCommon.version = "2.7.7"
function dcsCommon.randomPointInCircle(sourceRadius, innerRadius, x, z) function dcsCommon.randomPointInCircle(sourceRadius, innerRadius, x, z)
if not x then x = 0 end if not x then x = 0 end
if not z then z = 0 end
--local y = 0 --local y = 0
if not innerRadius then innerRadius = 0 end if not innerRadius then innerRadius = 0 end
if innerRadius < 0 then innerRadius = 0 end if innerRadius < 0 then innerRadius = 0 end
@ -698,8 +759,8 @@ dcsCommon.version = "2.7.7"
-- now lets get a random degree -- now lets get a random degree
local degrees = dcsCommon.randomDegrees() -- math.random(360) * 3.14152 / 180 -- ok, it's actually radiants. local degrees = dcsCommon.randomDegrees() -- math.random(360) * 3.14152 / 180 -- ok, it's actually radiants.
local r = (sourceRadius-innerRadius) * percent local r = (sourceRadius-innerRadius) * percent
local x = x + (innerRadius + r) * math.cos(degrees) x = x + (innerRadius + r) * math.cos(degrees)
local z = z + (innerRadius + r) * math.sin(degrees) z = z + (innerRadius + r) * math.sin(degrees)
local thePoint = {} local thePoint = {}
thePoint.x = x thePoint.x = x
@ -1351,12 +1412,15 @@ dcsCommon.version = "2.7.7"
local lowDist = 10000 local lowDist = 10000
local uPoint = {} local uPoint = {}
local thePoint = {} local thePoint = {}
repeat -- get random point intil mindistance to all is kept or emergencybreak repeat -- get random point until mindistance to all is kept or emergencybreak
thePoint = dcsCommon.randomPointInCircle(radius, innerRadius) -- returns x, 0, z
-- check if too close to others
for idx, rUnit in pairs(processedUnits) do -- get min dist to all positioned units for idx, rUnit in pairs(processedUnits) do -- get min dist to all positioned units
thePoint = dcsCommon.randomPointInCircle(radius, innerRadius) -- returns x, 0, z --trigger.action.outText("rPnt: thePoint = " .. dcsCommon.point2text(thePoint), 30)
uPoint.x = rUnit.x uPoint.x = rUnit.x
uPoint.y = 0 uPoint.y = 0
uPoint.z = rUnit.y uPoint.z = rUnit.y
--trigger.action.outText("rPnt: uPoint = " .. dcsCommon.point2text(uPoint), 30)
local dist = dcsCommon.dist(thePoint, uPoint) -- measure distance to unit local dist = dcsCommon.dist(thePoint, uPoint) -- measure distance to unit
if (dist < lowDist) then lowDist = dist end if (dist < lowDist) then lowDist = dist end
end end
@ -1509,7 +1573,7 @@ dcsCommon.version = "2.7.7"
function dcsCommon.createGroundGroupWithUnits(name, theUnitTypes, radius, minDist, formation, innerRadius) function dcsCommon.createGroundGroupWithUnits(name, theUnitTypes, radius, minDist, formation, innerRadius)
if not minDist then mindist = 4 end -- meters if not minDist then minDist = 4 end -- meters
if not formation then formation = "line" end if not formation then formation = "line" end
if not radius then radius = 30 end -- meters if not radius then radius = 30 end -- meters
if not innerRadius then innerRadius = 0 end if not innerRadius then innerRadius = 0 end
@ -1982,6 +2046,12 @@ end
return "no" return "no"
end end
function dcsCommon.bool2Num(theBool)
if not theBool then theBool = false end
if theBool then return 1 end
return 0
end
function dcsCommon.point2text(p) function dcsCommon.point2text(p)
if not p then return "<!NIL!>" end if not p then return "<!NIL!>" end
local t = "[x=" local t = "[x="
@ -2417,7 +2487,7 @@ end
function dcsCommon.getUnitSpeed(theUnit) function dcsCommon.getUnitSpeed(theUnit)
if not theUnit then return 0 end if not theUnit then return 0 end
if not theUnit:isExist() then return 0 end if not Unit.isExist(theUnit) then return 0 end
local v = theUnit:getVelocity() local v = theUnit:getVelocity()
return dcsCommon.mag(v.x, v.y, v.z) return dcsCommon.mag(v.x, v.y, v.z)
end end

View File

@ -1,5 +1,5 @@
guardianAngel = {} guardianAngel = {}
guardianAngel.version = "3.0.2" guardianAngel.version = "3.0.4"
guardianAngel.ups = 10 guardianAngel.ups = 10
guardianAngel.name = "Guardian Angel" -- just in case someone accesses .name guardianAngel.name = "Guardian Angel" -- just in case someone accesses .name
guardianAngel.launchWarning = true -- detect launches and warn pilot guardianAngel.launchWarning = true -- detect launches and warn pilot
@ -59,6 +59,8 @@ guardianAngel.requiredLibs = {
- removed legacy code - removed legacy code
3.0.2 - added guardianAngel.name for those who use local flags on activate 3.0.2 - added guardianAngel.name for those who use local flags on activate
3.0.3 - monitorItem() guards against loss of target (nil) 3.0.3 - monitorItem() guards against loss of target (nil)
3.0.4 - launchSound attribute
- interventionSound attribute
This script detects missiles launched against protected aircraft an This script detects missiles launched against protected aircraft an
@ -276,11 +278,20 @@ function guardianAngel.monitorItem(theItem)
local desc = "Missile, missile, missile - now heading for " .. ctName .. "!" local desc = "Missile, missile, missile - now heading for " .. ctName .. "!"
if guardianAngel.private then if guardianAngel.private then
trigger.action.outTextForGroup(ID, desc, 30) trigger.action.outTextForGroup(ID, desc, 30)
if guardianAngel.launchSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.launchSound
trigger.action.outSoundForGroup(ID, fileName)
end
else else
trigger.action.outText(desc, 30) trigger.action.outText(desc, 30)
if guardianAngel.launchSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.launchSound
trigger.action.outSound(fileName)
end
end end
end end
end end
guardianAngel.retargetItem(theItem, currentTarget, isThreat) guardianAngel.retargetItem(theItem, currentTarget, isThreat)
t = currentTarget t = currentTarget
else else
@ -326,14 +337,20 @@ function guardianAngel.monitorItem(theItem)
d <= lethalRange + 10 d <= lethalRange + 10
then then
desc = desc .. " ANGEL INTERVENTION" desc = desc .. " ANGEL INTERVENTION"
--if theItem.lostTrack then desc = desc .. " (little sneak!)" end
--if theItem.missed then desc = desc .. " (missed you!)" end
if guardianAngel.announcer then if guardianAngel.announcer then
if guardianAngel.private then if guardianAngel.private then
trigger.action.outTextForGroup(ID, desc, 30) trigger.action.outTextForGroup(ID, desc, 30)
if guardianAngel.interventionSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.interventionSound
trigger.action.outSoundForGroup(ID, fileName)
end
else else
trigger.action.outText(desc, 30) trigger.action.outText(desc, 30)
if guardianAngel.interventionSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.interventionSound
trigger.action.outSound(fileName)
end
end end
end end
guardianAngel.invokeCallbacks("intervention", theItem.targetName, theItem.weaponName) guardianAngel.invokeCallbacks("intervention", theItem.targetName, theItem.weaponName)
@ -608,8 +625,16 @@ function guardianAngel.somethingHappened(event)
-- can be moved to update() -- can be moved to update()
if guardianAngel.private then if guardianAngel.private then
trigger.action.outTextForGroup(grpID, "Missile, missile, missile, " .. oclock .. " o clock" .. vbInfo, 30) trigger.action.outTextForGroup(grpID, "Missile, missile, missile, " .. oclock .. " o clock" .. vbInfo, 30)
if guardianAngel.launchSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.launchSound
trigger.action.outSoundForGroup(grpID, fileName)
end
else else
trigger.action.outText("Missile, missile, missile, " .. oclock .. " o clock" .. vbInfo, 30) trigger.action.outText("Missile, missile, missile, " .. oclock .. " o clock" .. vbInfo, 30)
if guardianAngel.launchSound then
local fileName = "l10n/DEFAULT/" .. guardianAngel.launchSound
trigger.action.outSound(fileName)
end
end end
theQItem.detected = true -- remember: we detected and warned already theQItem.detected = true -- remember: we detected and warned already
@ -850,6 +875,14 @@ function guardianAngel.readConfigZone()
guardianAngel.lastDeActivate = cfxZones.getFlagValue(guardianAngel.deactivate, theZone) guardianAngel.lastDeActivate = cfxZones.getFlagValue(guardianAngel.deactivate, theZone)
end end
if cfxZones.hasProperty(theZone, "launchSound") then
guardianAngel.launchSound = cfxZones.getStringFromZoneProperty(theZone, "launchSound", "nosound")
end
if cfxZones.hasProperty(theZone, "interventionSound") then
guardianAngel.interventionSound = cfxZones.getStringFromZoneProperty(theZone, "interventionSound", "nosound")
end
guardianAngel.configZone = theZone guardianAngel.configZone = theZone
if guardianAngel.verbose then if guardianAngel.verbose then
trigger.action.outText("+++gA: processed config zone", 30) trigger.action.outText("+++gA: processed config zone", 30)

View File

@ -1,5 +1,5 @@
messenger = {} messenger = {}
messenger.version = "2.0.1" messenger.version = "2.1.0"
messenger.verbose = false messenger.verbose = false
messenger.requiredLibs = { messenger.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -43,6 +43,24 @@ messenger.messengers = {}
- unit - unit
- group - group
2.0.1 - config optimization 2.0.1 - config optimization
2.1.0 - unit only: dynamicUnitProcessing for
- <bae: u/z> bearing to unit/zone
- <rbae u/z> response mapped by unit's heading
- <clk: u/z> bearing in clock position to unit/zone
- <rng: u/z> range to unit/zone
- <hnd: u/z> bearing in left/right/ahead/behind
- <sde: u/z> bearing in starboard/port/ahead/aft
- added dynamicGroupProcessing to select unit 1
- responses attribute
- <rsp: flag>
- <rrnd> response randomized
- <rhdg: u/z> respons mapped by unit's heading
- <cls unit> closing speed
- <vel unit> velocity (speed)
- <asp unit> aspect
- fix to messageMute
- <type: unit>
--]]-- --]]--
@ -137,6 +155,38 @@ function messenger.processDynamicValues(inMsg, theZone)
outMsg = string.gsub(outMsg, pattern, val, 1) -- only one sub! outMsg = string.gsub(outMsg, pattern, val, 1) -- only one sub!
end end
until not startLoc until not startLoc
-- now process rsp
pattern = "<rsp:%s*[%s%w%*%d%.%-_]+>" -- no list allowed but blanks and * and . and - and _ --> we fail on the other specials to keep this simple
if theZone.msgResponses and (#theZone.msgResponses > 0) then -- only if this zone has an array
--trigger.action.outText("enter response proccing", 30)
repeat -- iterate all patterns one by one
local startLoc, endLoc = string.find(outMsg, pattern)
if startLoc then
--trigger.action.outText("response: found an occurence", 30)
local theValParam = string.sub(outMsg, startLoc, endLoc)
-- strip lead and trailer
local param = string.gsub(theValParam, "<rsp:%s*", "")
param = string.gsub(param, ">","")
-- access flag
local val = cfxZones.getFlagValue(param, theZone)
if not val or (val < 1) then val = 1 end
if val > #theZone.msgResponses then val = #theZone.msgResponses end
val = theZone.msgResponses[val]
val = dcsCommon.trim(val)
-- replace pattern in original with new val
outMsg = string.gsub(outMsg, pattern, val, 1) -- only one sub!
end
until not startLoc
-- rnd response
local rndRsp = dcsCommon.pickRandom(theZone.msgResponses)
outMsg = outMsg:gsub ("<rrnd>", rndRsp)
end
return outMsg return outMsg
end end
@ -167,8 +217,13 @@ end
function messenger.processDynamicLoc(inMsg, theZone) function messenger.processDynamicLoc(inMsg, theZone)
-- replace all occurences of <lat/lon/ele/mgrs: flagName> with their values -- replace all occurences of <lat/lon/ele/mgrs: flagName> with their values
local locales = {"lat", "lon", "ele", "mgrs", "lle", "latlon"} -- agl = angels
-- vel = velocity (speed)
-- hdg = heading
-- rhdg = heading, response-mapped
local locales = {"lat", "lon", "ele", "mgrs", "lle", "latlon", "alt", "vel", "hdg", "rhdg", "type"}
local outMsg = inMsg local outMsg = inMsg
local uHead = 0
for idx, aLocale in pairs(locales) do for idx, aLocale in pairs(locales) do
local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>" local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>"
repeat -- iterate all patterns one by one repeat -- iterate all patterns one by one
@ -183,14 +238,32 @@ function messenger.processDynamicLoc(inMsg, theZone)
local thePoint = nil local thePoint = nil
local tZone = cfxZones.getZoneByName(param) local tZone = cfxZones.getZoneByName(param)
local tUnit = Unit.getByName(param) local tUnit = Unit.getByName(param)
local spd = 0
local angels = 0
local theType = "<errType>"
if tZone then if tZone then
theType = "Zone"
thePoint = cfxZones.getPoint(tZone) thePoint = cfxZones.getPoint(tZone)
-- since zones always have elevation of 0, if tZone.linkedUnit and Unit.isExist(tZone.linkedUnit) then
-- now get the elevation from the map local lU = tZone.linkedUnit
thePoint.y = land.getHeight({x = thePoint.x, y = thePoint.z}) local masterPoint = lU:getPoint()
thePoint.y = masterPoint.y
spd = dcsCommon.getUnitSpeed(lU)
spd = math.floor(spd * 3.6)
uHead = math.floor(dcsCommon.getUnitHeading(tUnit) * 57.2958) -- to degrees.
else
-- since zones always have elevation of 0,
-- now get the elevation from the map
thePoint.y = land.getHeight({x = thePoint.x, y = thePoint.z})
end
elseif tUnit then elseif tUnit then
if Unit.isExist(tUnit) then if Unit.isExist(tUnit) then
theType = tUnit:getTypeName()
thePoint = tUnit:getPoint() thePoint = tUnit:getPoint()
spd = dcsCommon.getUnitSpeed(tUnit)
-- convert m/s to km/h
spd = math.floor(spd * 3.6)
uHead = math.floor(dcsCommon.getUnitHeading(tUnit) * 57.2958) -- to degrees.
end end
else else
-- nothing to do, remove me. -- nothing to do, remove me.
@ -202,16 +275,31 @@ function messenger.processDynamicLoc(inMsg, theZone)
-- processing. return result in locString -- processing. return result in locString
local lat, lon, alt = coord.LOtoLL(thePoint) local lat, lon, alt = coord.LOtoLL(thePoint)
lat, lon = dcsCommon.latLon2Text(lat, lon) lat, lon = dcsCommon.latLon2Text(lat, lon)
angels = math.floor(thePoint.y)
if theZone.imperialUnits then if theZone.imperialUnits then
alt = math.floor(alt * 3.28084) -- feet alt = math.floor(alt * 3.28084) -- feet
spd = math.floor(spd * 0.539957) -- km/h to knots
angels = math.floor(angels * 3.28084)
else else
alt = math.floor(alt) -- meters alt = math.floor(alt) -- meters
end end
if angels > 1000 then
angels = math.floor(angels / 100) * 100
end
if aLocale == "lat" then locString = lat if aLocale == "lat" then locString = lat
elseif aLocale == "lon" then locString = lon elseif aLocale == "lon" then locString = lon
elseif aLocale == "ele" then locString = tostring(alt) elseif aLocale == "ele" then locString = tostring(alt)
elseif aLocale == "lle" then locString = lat .. " " .. lon .. " ele " .. tostring(alt) elseif aLocale == "lle" then locString = lat .. " " .. lon .. " ele " .. tostring(alt)
elseif aLocale == "latlon" then locString = lat .. " " .. lon elseif aLocale == "latlon" then locString = lat .. " " .. lon
elseif aLocale == "alt" then locString = tostring(angels) -- don't confuse alt and angels, bad var naming here
elseif aLocale == "vel" then locString = tostring(spd)
elseif aLocale == "hdg" then locString = tostring(uHead)
elseif aLocale == "type" then locString = theType
elseif aLocale == "rhdg" and (theZone.msgResponses) then
local offset = messenger.rspMapper360(uHead, #theZone.msgResponses)
locString = dcsCommon.trim(theZone.msgResponses[offset])
else else
-- we have mgrs -- we have mgrs
local grid = coord.LLtoMGRS(coord.LOtoLL(thePoint)) local grid = coord.LLtoMGRS(coord.LOtoLL(thePoint))
@ -226,6 +314,161 @@ function messenger.processDynamicLoc(inMsg, theZone)
return outMsg return outMsg
end end
function messenger.rspMapper360(directionInDegrees, numResponses)
-- maps responses like clock. Clock has 12 'responses' (12, 1, .., 11),
-- with the first (12) also mapping to the last half arc
-- this method dynamically 'winds' the responses around
-- a clock and returns the index of the message to display
if numResponses < 1 then numResponses = 1 end
directionInDegrees = math.floor(directionInDegrees)
while directionInDegrees < 0 do directionInDegrees = directionInDegrees + 360 end
while directionInDegrees >= 360 do directionInDegrees = directionInDegrees - 360 end
-- now we have 0..360
-- calculate arc per item
local arcPerItem = 360 / numResponses
local halfArc = arcPerItem / 2
-- we now map 0..360 to (0-halfArc..360-halfArc) by shifting
-- direction by half-arc and clipping back 0..360
-- and now we can directly derive the index of the response
directionInDegrees = directionInDegrees + halfArc
if directionInDegrees >= 360 then directionInDegrees = directionInDegrees - 360 end
local index = math.floor(directionInDegrees / arcPerItem) + 1 -- 1 .. numResponses
return index
end
function messenger.dynamicGroupProcessing(msg, theZone, theGroup)
if not theGroup then return msg end
-- access first unit
local theUnit = theGroup:getUnit(1)
if not theUnit then return msg end
if not Unit.isExist(theUnit) then return msg end
-- we always use unit 1 as reference
return messenger.dynamicUnitProcessing(msg, theZone, theUnit)
end
function messenger.dynamicUnitProcessing(inMsg, theZone, theUnit)
-- replace all occurences of <bae/rng/asp/cls/clk: unit/zone> with their values
-- bae = bearingInDegreesFromAtoB
-- rng = range
-- asp = aspect (not yet implemented)
-- cls = closing velocity (not yet implemented)
-- clk = o'clock
-- hnd = handedness (left/right/ahead/behind
-- sde = side (starboard / port / ahead / aft)
-- rbea = responses mapped to bearing. maps all responses like clock, with "12" being the first response. requires msgResponses set
local here = theUnit:getPoint()
local uHead = dcsCommon.getUnitHeading(theUnit) * 57.2958 -- to degrees.
local locales = {"bea", "rng", "clk", "hnd", "sde", "rbea", "cls", "pcls", "asp"}
local outMsg = inMsg
for idx, aLocale in pairs(locales) do
local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>"
repeat -- iterate all patterns one by one
local startLoc, endLoc = string.find(outMsg, pattern)
if startLoc then
local theValParam = string.sub(outMsg, startLoc, endLoc)
-- strip lead and trailer
local param = string.gsub(theValParam, "<" .. aLocale .. ":%s*", "")
param = string.gsub(param, ">","")
-- find zone or unit
param = dcsCommon.trim(param)
local thePoint = nil
local cls = 0
local aspct = 0
local tZone = cfxZones.getZoneByName(param)
local tUnit = Unit.getByName(param)
local aspect = 0
local tHead = 0
if tZone then
thePoint = cfxZones.getPoint(tZone)
-- if this zone follows a unit, get the master units elevaltion
if tZone.linkedUnit and Unit.isExist(tZone.linkedUnit) then
local lU = tZone.linkedUnit
local masterPoint = lU:getPoint()
thePoint.y = masterPoint.y
cls = -dcsCommon.getClosingVelocity(theUnit, lU)
tHead = dcsCommon.getUnitHeading(lU) * 57.2958
else
-- since zones always have elevation of 0,
-- now get the elevation from the map
thePoint.y = land.getHeight({x = thePoint.x, y = thePoint.z})
end
elseif tUnit then
if Unit.isExist(tUnit) then
thePoint = tUnit:getPoint()
cls = -dcsCommon.getClosingVelocity(theUnit, tUnit)
tHead = dcsCommon.getUnitHeading(tUnit) * 57.2958
end
else
-- nothing to do, remove me.
end
local locString = theZone.errString
if thePoint then
-- now that we have a point, we can do locale-specific
-- processing. return result in locString
local pcls = cls
local r = dcsCommon.dist(here, thePoint)
--local alt = thePoint.y
local uSize = "m"
if theZone.imperialUnits then
r = math.floor(r * 3.28084) -- feet
uSize = "ft"
if r > 1000 then
-- convert to nautical mile
r = math.floor(r * 10 / 6076.12) / 10
uSize = "nm"
end
cls = math.floor(cls * 1.9438452) -- m/s to knots
pcls = math.floor(pcls * 32.8084) / 10 -- ft/s
else
r = math.floor(r) -- meters
if r > 1000 then
r = math.floor (r / 100) / 10
uSize = "km"
end
cls = math.floor(cls * 3.6) -- m/s to km/h
pcls = math.floor(pcls * 10) / 10 -- m/s
end
local bea = dcsCommon.bearingInDegreesFromAtoB(here, thePoint)
local beaInv = 360 - bea -- from tUnit to player
local direction = bea - uHead -- tUnit as seen from player heading uHead
if direction < 0 then direction = direction + 360 end
aspect = beaInv - tHead
-- set up locale exchange string
if aLocale == "bea" then locString = tostring(bea)
elseif aLocale == "asp" then locString = dcsCommon.aspectByDirection(aspect)
elseif aLocale == "clk" then
locString = tostring(dcsCommon.getClockDirection(direction))
elseif aLocale == "rng" then locString = tostring(r)..uSize
elseif aLocale == "cls" then locString = tostring(cls)
elseif aLocale == "pcls" then locString = tostring(pcls)
elseif aLocale == "hnd" then locString = dcsCommon.getGeneralDirection(direction)
elseif aLocale == "sde" then locString = dcsCommon.getNauticalDirection(direction)
elseif aLocale == "rbea" and (theZone.msgResponses) then
local offset = messenger.rspMapper360(direction, #theZone.msgResponses)
locString = dcsCommon.trim(theZone.msgResponses[offset])
else locString = "<locale " .. aLocale .. " err: undefined params>"
end
end
-- replace pattern in original with new val
outMsg = string.gsub(outMsg, pattern, locString, 1) -- only one sub!
end -- if startloc
until not startLoc
end -- for all locales
return outMsg
end
function messenger.dynamicFlagProcessing(inMsg, theZone) function messenger.dynamicFlagProcessing(inMsg, theZone)
if not inMsg then return "No in message" end if not inMsg then return "No in message" end
if not theZone then return "Nil zone" end if not theZone then return "Nil zone" end
@ -296,10 +539,12 @@ function messenger.createMessengerWithZone(theZone)
-- end -- end
theZone.messageOff = cfxZones.getBoolFromZoneProperty(theZone, "mute", false) --false theZone.messageOff = cfxZones.getBoolFromZoneProperty(theZone, "mute", false) --false
if cfxZones.hasProperty(theZone, "messageOff?") then if cfxZones.hasProperty(theZone, "messageMute") then
theZone.messageOff = cfxZones.getBoolFromZoneProperty(theZone, "messageMute", false) theZone.messageOff = cfxZones.getBoolFromZoneProperty(theZone, "messageMute", false)
end end
-- advisory: messageOff, messageOffFlag and lastMessageOff are all distinct
if cfxZones.hasProperty(theZone, "messageOff?") then if cfxZones.hasProperty(theZone, "messageOff?") then
theZone.messageOffFlag = cfxZones.getStringFromZoneProperty(theZone, "messageOff?", "*none") theZone.messageOffFlag = cfxZones.getStringFromZoneProperty(theZone, "messageOff?", "*none")
theZone.lastMessageOff = cfxZones.getFlagValue(theZone.messageOffFlag, theZone) theZone.lastMessageOff = cfxZones.getFlagValue(theZone.messageOffFlag, theZone)
@ -313,23 +558,19 @@ function messenger.createMessengerWithZone(theZone)
-- reveiver: coalition, group, unit -- reveiver: coalition, group, unit
if cfxZones.hasProperty(theZone, "coalition") then if cfxZones.hasProperty(theZone, "coalition") then
theZone.msgCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0) theZone.msgCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0)
end elseif cfxZones.hasProperty(theZone, "msgCoalition") then
if cfxZones.hasProperty(theZone, "msgCoalition") then
theZone.msgCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "msgCoalition", 0) theZone.msgCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "msgCoalition", 0)
end end
if cfxZones.hasProperty(theZone, "group") then if cfxZones.hasProperty(theZone, "group") then
theZone.msgGroup = cfxZones.getStringFromZoneProperty(theZone, "group", "<none>") theZone.msgGroup = cfxZones.getStringFromZoneProperty(theZone, "group", "<none>")
end elseif cfxZones.hasProperty(theZone, "msgGroup") then
if cfxZones.hasProperty(theZone, "msgGroup") then
theZone.msgGroup = cfxZones.getStringFromZoneProperty(theZone, "msgGroup", "<none>") theZone.msgGroup = cfxZones.getStringFromZoneProperty(theZone, "msgGroup", "<none>")
end end
if cfxZones.hasProperty(theZone, "unit") then if cfxZones.hasProperty(theZone, "unit") then
theZone.msgUnit = cfxZones.getStringFromZoneProperty(theZone, "unit", "<none>") theZone.msgUnit = cfxZones.getStringFromZoneProperty(theZone, "unit", "<none>")
end elseif cfxZones.hasProperty(theZone, "msgUnit") then
if cfxZones.hasProperty(theZone, "msgUnit") then
theZone.msgUnit = cfxZones.getStringFromZoneProperty(theZone, "msgUnit", "<none>") theZone.msgUnit = cfxZones.getStringFromZoneProperty(theZone, "msgUnit", "<none>")
end end
@ -358,6 +599,12 @@ function messenger.createMessengerWithZone(theZone)
theZone.errString = cfxZones.getStringFromZoneProperty(theZone, "messageError", "") theZone.errString = cfxZones.getStringFromZoneProperty(theZone, "messageError", "")
end end
-- possible responses for mapping
if cfxZones.hasProperty(theZone, "responses") then
local resp = cfxZones.getStringFromZoneProperty(theZone, "responses", "none")
theZone.msgResponses = dcsCommon.string2Array(resp, ",")
end
if messenger.verbose or theZone.verbose then if messenger.verbose or theZone.verbose then
trigger.action.outText("+++Msg: new zone <".. theZone.name .."> will say <".. theZone.message .. ">", 30) trigger.action.outText("+++Msg: new zone <".. theZone.name .."> will say <".. theZone.message .. ">", 30)
end end
@ -424,6 +671,7 @@ function messenger.isTriggered(theZone)
local theGroup = Group.getByName(theZone.msgGroup) local theGroup = Group.getByName(theZone.msgGroup)
if theGroup and Group.isExist(theGroup) then if theGroup and Group.isExist(theGroup) then
local ID = theGroup:getID() local ID = theGroup:getID()
msg = messenger.dynamicGroupProcessing(msg, theZone, theGroup)
trigger.action.outTextForGroup(ID, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForGroup(ID, msg, theZone.duration, theZone.clearScreen)
trigger.action.outSoundForGroup(ID, fileName) trigger.action.outSoundForGroup(ID, fileName)
end end
@ -431,6 +679,7 @@ function messenger.isTriggered(theZone)
local theUnit = Unit.getByName(theZone.msgUnit) local theUnit = Unit.getByName(theZone.msgUnit)
if theUnit and Unit.isExist(theUnit) then if theUnit and Unit.isExist(theUnit) then
local ID = theUnit:getID() local ID = theUnit:getID()
msg = messenger.dynamicUnitProcessing(msg, theZone, theUnit)
trigger.action.outTextForUnit(ID, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForUnit(ID, msg, theZone.duration, theZone.clearScreen)
trigger.action.outSoundForUnit(ID, fileName) trigger.action.outSoundForUnit(ID, fileName)
end end
@ -533,11 +782,6 @@ if not messenger.start() then
end end
--[[-- --[[--
Wildcard extension:
- general flag access <v flag name>
- <t: flag name>
- <lat: unit/zone name>
- <mrgs: unit/zone name>
--]]-- --]]--

View File

@ -1,5 +1,5 @@
unitZone={} unitZone={}
unitZone.version = "1.2.3" unitZone.version = "1.2.4"
unitZone.verbose = false unitZone.verbose = false
unitZone.ups = 1 unitZone.ups = 1
unitZone.requiredLibs = { unitZone.requiredLibs = {
@ -16,6 +16,7 @@ unitZone.requiredLibs = {
1.2.2 - uzDirectInv 1.2.2 - uzDirectInv
1.2.3 - better guards for enterZone!, exitZone!, changeZone! 1.2.3 - better guards for enterZone!, exitZone!, changeZone!
- better guards for uzOn? and uzOff? - better guards for uzOn? and uzOff?
1.2.4 - more verbosity on uzDirect
--]]-- --]]--
@ -282,7 +283,7 @@ function unitZone.update()
-- scan all zones -- scan all zones
if not aZone.uzPaused then if not aZone.uzPaused then
local newState = unitZone.checkZoneStatus(aZone) local newState = unitZone.checkZoneStatus(aZone) -- returns true if at least one unit in zone
if newState ~= aZone.lastStatus then if newState ~= aZone.lastStatus then
-- bang on change! -- bang on change!
@ -292,6 +293,9 @@ function unitZone.update()
-- output direct state suite -- output direct state suite
if aZone.uzDirect then if aZone.uzDirect then
if aZone.verbose or unitZone.verbose then
trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting uzDirect <" .. aZone.uzDirect .. "> to ".. dcsCommon.bool2Num(newState), 30)
end
if newState then if newState then
cfxZones.setFlagValueMult(aZone.uzDirect, 1, aZone) cfxZones.setFlagValueMult(aZone.uzDirect, 1, aZone)
else else
@ -299,6 +303,10 @@ function unitZone.update()
end end
end end
if aZone.uzDirectInv then if aZone.uzDirectInv then
local invState = not newState
if aZone.verbose or unitZone.verbose then
trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting INVuzDirect <" .. aZone.uzDirectInv .. "> to ".. dcsCommon.bool2Num(invState), 30)
end
if newState then if newState then
cfxZones.setFlagValueMult(aZone.uzDirectInv, 0, aZone) cfxZones.setFlagValueMult(aZone.uzDirectInv, 0, aZone)
else else
@ -363,5 +371,6 @@ if not unitZone.start() then
unitZone = nil unitZone = nil
end end
--ToDo: matching: name, name wildcard, type
--ToDo: add 'neutral' support and add 'both' option --ToDo: add 'neutral' support and add 'both' option
--ToDo: add API --ToDo: add API