Version 0.985

Quick Ref
Clone Zones Reference Resolve
Clone Relations Demo
This commit is contained in:
Christian Franz 2022-02-24 16:55:32 +01:00
parent d69ce05d80
commit f1aa9cabf1
22 changed files with 885 additions and 138 deletions

Binary file not shown.

BIN
Doc/DML Quick Reference.pdf Normal file

Binary file not shown.

View File

@ -178,13 +178,8 @@ function FARPZones.createFARPFromZone(aZone)
return theFarp return theFarp
end end
--[[--
function FARPZones.drawFarp(theFarp)
local theZone = theFarp.zone
local theOwner = theFarp.owner
FARPZones.drawZoneInMap(theZone, theOwner)
end
--]]--
function FARPZones.drawFARPCircleInMap(theFarp) function FARPZones.drawFARPCircleInMap(theFarp)
if not theFarp then return end if not theFarp then return end
@ -430,6 +425,7 @@ function FARPZones.readConfig()
FARPZones.spinUpDelay = cfxZones.getNumberFromZoneProperty(theZone, "spinUpDelay", 30) FARPZones.spinUpDelay = cfxZones.getNumberFromZoneProperty(theZone, "spinUpDelay", 30)
if FARPZones.verbose then if FARPZones.verbose then
trigger.action.outText("***frpZ: read config", 30) trigger.action.outText("***frpZ: read config", 30)
end end

View File

@ -1,5 +1,5 @@
cfxArtilleryZones = {} cfxArtilleryZones = {}
cfxArtilleryZones.version = "2.0.1" cfxArtilleryZones.version = "2.0.2"
cfxArtilleryZones.requiredLibs = { cfxArtilleryZones.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
"cfxZones", -- Zones, of course "cfxZones", -- Zones, of course
@ -24,7 +24,8 @@ cfxArtilleryZones.verbose = false
- att transition time to zone info mark - att transition time to zone info mark
- made compatible with linked zones - made compatible with linked zones
- added silent attribute - added silent attribute
- added transition time to arty command chatter - added transition time to arty command chatter
2.0.2 - boom?, arty? synonyms
Artillery Target Zones *** EXTENDS ZONES *** Artillery Target Zones *** EXTENDS ZONES ***
Target Zones for artillery. Can determine which zones are in range and visible and then handle artillery barrage to this zone Target Zones for artillery. Can determine which zones are in range and visible and then handle artillery barrage to this zone
@ -121,13 +122,18 @@ function cfxArtilleryZones.processArtilleryZone(aZone)
aZone.addMark = cfxZones.getBoolFromZoneProperty(aZone, "addMark", true) -- note: defaults to true aZone.addMark = cfxZones.getBoolFromZoneProperty(aZone, "addMark", true) -- note: defaults to true
aZone.shellVariance = cfxZones.getNumberFromZoneProperty(aZone, "shellVariance", 0.2) -- strength of explosion can vary by +/- this amount aZone.shellVariance = cfxZones.getNumberFromZoneProperty(aZone, "shellVariance", 0.2) -- strength of explosion can vary by +/- this amount
if cfxZones.hasProperty(aZone, "f?") then if cfxZones.hasProperty(aZone, "f?") then
aZone.triggerFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "none") aZone.artyTriggerFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "none")
end end
--[[--
if cfxZones.hasProperty(aZone, "triggerFlag") then if cfxZones.hasProperty(aZone, "triggerFlag") then
aZone.triggerFlag = cfxZones.getStringFromZoneProperty(aZone, "triggerFlag", "none") aZone.artyTriggerFlag = cfxZones.getStringFromZoneProperty(aZone, "triggerFlag", "none")
end end
if aZone.triggerFlag then --]]--
aZone.lastTriggerValue = trigger.misc.getUserFlag(aZone.triggerFlag) -- save last value if cfxZones.hasProperty(aZone, "artillery?") then
aZone.artyTriggerFlag = cfxZones.getStringFromZoneProperty(aZone, "artillery?", "none")
end
if aZone.artyTriggerFlag then
aZone.lastTriggerValue = trigger.misc.getUserFlag(aZone.artyTriggerFlag) -- save last value
end end
aZone.cooldown =cfxZones.getNumberFromZoneProperty(aZone, "cooldown", 120) -- seconds aZone.cooldown =cfxZones.getNumberFromZoneProperty(aZone, "cooldown", 120) -- seconds
aZone.baseAccuracy = cfxZones.getNumberFromZoneProperty(aZone, "baseAccuracy", aZone.radius) -- meters from center radius shell impact aZone.baseAccuracy = cfxZones.getNumberFromZoneProperty(aZone, "baseAccuracy", aZone.radius) -- meters from center radius shell impact
@ -380,8 +386,8 @@ function cfxArtilleryZones.update()
-- iterate all zones to see if a trigger has changed -- iterate all zones to see if a trigger has changed
for idx, aZone in pairs(cfxArtilleryZones.artilleryZones) do for idx, aZone in pairs(cfxArtilleryZones.artilleryZones) do
if aZone.triggerFlag then if aZone.artyTriggerFlag then
local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerFlag) local currTriggerVal = trigger.misc.getUserFlag(aZone.artyTriggerFlag)
if currTriggerVal ~= aZone.lastTriggerValue if currTriggerVal ~= aZone.lastTriggerValue
then then
-- a triggered release! -- a triggered release!

View File

@ -1,5 +1,5 @@
cfxCargoReceiver = {} cfxCargoReceiver = {}
cfxCargoReceiver.version = "1.1.0" cfxCargoReceiver.version = "1.2.0"
cfxCargoReceiver.ups = 1 -- once a second cfxCargoReceiver.ups = 1 -- once a second
cfxCargoReceiver.maxDirectionRange = 500 -- in m. distance when cargo manager starts talking to pilots who are carrying that cargo cfxCargoReceiver.maxDirectionRange = 500 -- in m. distance when cargo manager starts talking to pilots who are carrying that cargo
cfxCargoReceiver.requiredLibs = { cfxCargoReceiver.requiredLibs = {
@ -13,7 +13,9 @@ cfxCargoReceiver.requiredLibs = {
- 1.0.0 initial vbersion - 1.0.0 initial vbersion
- 1.1.0 added flag manipulation options - 1.1.0 added flag manipulation options
no negative agl on announcement no negative agl on announcement
silent attribute silent attribute
- 1.2.0 method
f!, cargoReceived!
CargoReceiver is a zone enhancement you use to be automatically CargoReceiver is a zone enhancement you use to be automatically
@ -67,6 +69,17 @@ function cfxCargoReceiver.processReceiverZone(aZone) -- process attribute and ad
if cfxZones.hasProperty(aZone, "f-1") then if cfxZones.hasProperty(aZone, "f-1") then
aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f-1", "999") aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f-1", "999")
end end
-- new method support
aZone.method = cfxZones.getStringFromZoneProperty(aZone, "method", "inc")
if cfxZones.hasProperty(aZone, "f!") then
aZone.outReceiveFlag = cfxZones.getNumberFromZoneProperty(aZone, "f!", -1)
end
if cfxZones.hasProperty(aZone, "cargoReceived!") then
aZone.outReceiveFlag = cfxZones.getNumberFromZoneProperty(aZone, "cargoReceived!", -1)
end
end end
function cfxCargoReceiver.addReceiverZone(aZone) function cfxCargoReceiver.addReceiverZone(aZone)
@ -132,6 +145,9 @@ function cfxCargoReceiver.cargoEvent(event, object, name)
trigger.action.setUserFlag(aZone.decreaseFlag, val) trigger.action.setUserFlag(aZone.decreaseFlag, val)
end end
if aZone.outReceiveFlag then
cfxZones.pollFlag(aZone.outReceiveFlag, aZone.method)
end
--trigger.action.outText("+++rcv: " .. name .. " delivered in zone " .. aZone.name, 30) --trigger.action.outText("+++rcv: " .. name .. " delivered in zone " .. aZone.name, 30)
--trigger.action.outSound("Quest Snare 3.wav") --trigger.action.outSound("Quest Snare 3.wav")

View File

@ -1,5 +1,5 @@
cfxMX = {} cfxMX = {}
cfxMX.version = "1.0.1" cfxMX.version = "1.1.0"
--[[-- --[[--
Mission data decoder. Access to ME-built mission structures Mission data decoder. Access to ME-built mission structures
@ -8,9 +8,17 @@ cfxMX.version = "1.0.1"
Version History Version History
1.0.0 - initial version 1.0.0 - initial version
1.0.1 - getStaticFromDCSbyName() 1.0.1 - getStaticFromDCSbyName()
1.1.0 - getStaticFromDCSbyName also copies groupID when not fetching orig
- on start up collects a cross reference table of all
original group id
- add linkUnit for statics
--]]-- --]]--
cfxMX.groupNamesByID = {}
cfxMX.groupIDbyName = {}
cfxMX.groupDataByName = {}
function cfxMX.getGroupFromDCSbyName(aName, fetchOriginal) function cfxMX.getGroupFromDCSbyName(aName, fetchOriginal)
if not fetchOriginal then fetchOriginal = false end if not fetchOriginal then fetchOriginal = false end
@ -105,6 +113,15 @@ function cfxMX.getStaticFromDCSbyName(aName, fetchOriginal)
local category = obj_type_name local category = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's at least one static in group! if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's at least one static in group!
for group_num, group_data in pairs(obj_type_data.group) do for group_num, group_data in pairs(obj_type_data.group) do
-- get linkUnit info if it exists
local linkUnit = nil
if group_data and group_data.route and group_data.route and group_data.route.points[1] then
linkUnit = group_data.route.points[1].linkUnit
if linkUnit then
--trigger.action.outText("MX: found missing link to " .. linkUnit .. " in " .. group_data.name, 30)
end
end
if group_data and group_data.units and type(group_data.units) == 'table' if group_data and group_data.units and type(group_data.units) == 'table'
then --make sure - again - that this is a valid group then --make sure - again - that this is a valid group
for unit_num, unit_data in pairs(group_data.units) do -- iterate units for unit_num, unit_data in pairs(group_data.units) do -- iterate units
@ -113,6 +130,11 @@ function cfxMX.getStaticFromDCSbyName(aName, fetchOriginal)
local theStatic = unit_data local theStatic = unit_data
if not fetchOriginal then if not fetchOriginal then
theStatic = dcsCommon.clone(unit_data) theStatic = dcsCommon.clone(unit_data)
-- copy group ID from group above
theStatic.groupId = group_data.groupId
-- copy linked unit data
theStatic.linkUnit = linkUnit
end end
return theStatic, category, countryID, groupName return theStatic, category, countryID, groupName
@ -132,6 +154,51 @@ function cfxMX.getStaticFromDCSbyName(aName, fetchOriginal)
return nil, "<none>", "<none>", "<no group name>" return nil, "<none>", "<none>", "<no group name>"
end end
function cfxMX.createCrossReference()
for coa_name_miz, coa_data in pairs(env.mission.coalition) do -- iterate all coalitions
local coa_name = coa_name_miz
if string.lower(coa_name_miz) == 'neutrals' then -- remove 's' at neutralS
coa_name = 'neutral'
end
-- directly convert coalition into number for easier access later
local coaNum = 0
if coa_name == "red" then coaNum = 1 end
if coa_name == "blue" then coaNum = 2 end
if type(coa_data) == 'table' then -- coalition = {bullseye, nav_points, name, county},
-- with county being an array
if coa_data.country then -- make sure there a country table for this coalition
for cntry_id, cntry_data in pairs(coa_data.country) do -- iterate all countries for this
-- per country = {id, name, vehicle, helicopter, plane, ship, static}
local countryName = string.lower(cntry_data.name)
local countryID = cntry_data.id
if type(cntry_data) == 'table' then -- filter strings .id and .name
for obj_type_name, obj_type_data in pairs(cntry_data) do
if obj_type_name == "helicopter" or
obj_type_name == "ship" or
obj_type_name == "plane" or
obj_type_name == "vehicle" or
obj_type_name == "static"
then -- (so it's not id or name)
local category = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's at least one group!
for group_num, group_data in pairs(obj_type_data.group) do
local aName = group_data.name
local aID = group_data.groupId
cfxMX.groupNamesByID[aID] = aName
cfxMX.groupIDbyName[aName] = aID
cfxMX.groupDataByName[aName] = group_data
end
end --if has category data
end --if plane, helo etc... category
end --for all objects in country
end --if has country data
end --for all countries in coalition
end --if coalition has country table
end -- if there is coalition data
end --for all coalitions in mission
end
function cfxMX.catText2ID(inText) function cfxMX.catText2ID(inText)
local outCat = 0 -- airplane local outCat = 0 -- airplane
local c = inText:lower() local c = inText:lower()
@ -144,3 +211,11 @@ function cfxMX.catText2ID(inText)
return outCat return outCat
end end
function cfxMX.start()
cfxMX.createCrossReference()
trigger.action.outText("cfxMX: "..#cfxMX.groupNamesByID .. " groups processed successfully", 30)
end
-- start
cfxMX.start()

View File

@ -1,5 +1,5 @@
cfxObjectDestructDetector = {} cfxObjectDestructDetector = {}
cfxObjectDestructDetector.version = "1.0.1" cfxObjectDestructDetector.version = "1.1.0"
cfxObjectDestructDetector.requiredLibs = { cfxObjectDestructDetector.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
"cfxZones", -- Zones, of course "cfxZones", -- Zones, of course
@ -9,6 +9,8 @@ cfxObjectDestructDetector.verbose = false
VERSION HISTORY VERSION HISTORY
1.0.0 initial version, based on parashoo, arty zones 1.0.0 initial version, based on parashoo, arty zones
1.0.1 fixed bug: trigger.MISC.getUserFlag() 1.0.1 fixed bug: trigger.MISC.getUserFlag()
1.1.0 added support for method, f! and destroyed!
Detect when an object with OBJECT ID as assigned in ME dies Detect when an object with OBJECT ID as assigned in ME dies
*** EXTENDS ZONES *** EXTENDS ZONES
@ -69,6 +71,16 @@ function cfxObjectDestructDetector.processObjectDestructZone(aZone)
if cfxZones.hasProperty(aZone, "f-1") then if cfxZones.hasProperty(aZone, "f-1") then
aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f-1", "999") aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f-1", "999")
end end
-- new method support
aZone.method = cfxZones.getStringFromZoneProperty(aZone, "method", "flip")
if cfxZones.hasProperty(aZone, "f!") then
aZone.outDestroyFlag = cfxZones.getNumberFromZoneProperty(aZone, "f!", -1)
end
if cfxZones.hasProperty(aZone, "destroyed!") then
aZone.outDestroyFlag = cfxZones.getNumberFromZoneProperty(aZone, "destroyed!", -1)
end
end end
-- --
-- MAIN DETECTOR -- MAIN DETECTOR
@ -98,6 +110,11 @@ function cfxObjectDestructDetector:onEvent(event)
trigger.action.setUserFlag(aZone.decreaseFlag, val) trigger.action.setUserFlag(aZone.decreaseFlag, val)
end end
-- support for banging
if aZone.outDestroyFlag then
cfxZones.pollFlag(aZone.outDestroyFlag, aZone.method)
end
-- invoke callbacks -- invoke callbacks
cfxObjectDestructDetector.invokeCallbacksFor(aZone) cfxObjectDestructDetector.invokeCallbacksFor(aZone)
if cfxObjectDestructDetector.verbose then if cfxObjectDestructDetector.verbose then

View File

@ -1,5 +1,5 @@
cfxObjectSpawnZones = {} cfxObjectSpawnZones = {}
cfxObjectSpawnZones.version = "1.1.4" cfxObjectSpawnZones.version = "1.1.5"
cfxObjectSpawnZones.requiredLibs = { cfxObjectSpawnZones.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
@ -23,6 +23,7 @@ cfxObjectSpawnZones.ups = 1
-- - added possibility to autoUnlink -- - added possibility to autoUnlink
-- 1.1.3 - ME-triggered flag via f? and triggerFlag -- 1.1.3 - ME-triggered flag via f? and triggerFlag
-- 1.1.4 - activate?, pause? attributes -- 1.1.4 - activate?, pause? attributes
-- 1.1.5 - spawn?, spawnObjects? synonyms
-- Object spawn zones have the following major uses: -- Object spawn zones have the following major uses:
-- - dynamically spawn cargo -- - dynamically spawn cargo
@ -85,6 +86,16 @@ function cfxObjectSpawnZones.createSpawner(inZone)
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end end
if cfxZones.hasProperty(inZone, "spawn?") then
theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawn?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end
if cfxZones.hasProperty(inZone, "spawnObjects?") then
theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawnObjects?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end
if cfxZones.hasProperty(inZone, "activate?") then if cfxZones.hasProperty(inZone, "activate?") then
theSpawner.activateFlag = cfxZones.getStringFromZoneProperty(inZone, "activate?", "none") theSpawner.activateFlag = cfxZones.getStringFromZoneProperty(inZone, "activate?", "none")
theSpawner.lastActivateValue = trigger.misc.getUserFlag(theSpawner.activateFlag) theSpawner.lastActivateValue = trigger.misc.getUserFlag(theSpawner.activateFlag)

View File

@ -1,5 +1,5 @@
cfxSmokeZone = {} cfxSmokeZone = {}
cfxSmokeZone.version = "1.0.3" cfxSmokeZone.version = "1.0.4"
cfxSmokeZone.requiredLibs = { cfxSmokeZone.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
"cfxZones", -- Zones, of course "cfxZones", -- Zones, of course
@ -12,7 +12,10 @@ cfxSmokeZone.requiredLibs = {
1.0.3 - added paused attribute 1.0.3 - added paused attribute
- added f? attribute --> onFlag - added f? attribute --> onFlag
- broke out startSmoke - broke out startSmoke
1.0.4 - startSmoke? synonym
- alphanum flag upgrade
- random color support
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
'smoke' attribute 'smoke' attribute
@ -34,6 +37,9 @@ function cfxSmokeZone.processSmokeZone(aZone)
if rawVal == "white" or rawVal == "2" then theColor = 2 end if rawVal == "white" or rawVal == "2" then theColor = 2 end
if rawVal == "orange" or rawVal == "3" then theColor = 3 end if rawVal == "orange" or rawVal == "3" then theColor = 3 end
if rawVal == "blue" or rawVal == "4" then theColor = 4 end if rawVal == "blue" or rawVal == "4" then theColor = 4 end
if rawVal == "?" or rawVal == "random" or rawVal == "rnd" then
theColor = dcsCommon.smallRandom(5) - 1
end
aZone.smokeColor = theColor aZone.smokeColor = theColor
aZone.smokeAlt = cfxZones.getNumberFromZoneProperty(aZone, "altitude", 1) aZone.smokeAlt = cfxZones.getNumberFromZoneProperty(aZone, "altitude", 1)
@ -46,8 +52,12 @@ function cfxSmokeZone.processSmokeZone(aZone)
aZone.onFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "none") aZone.onFlag = cfxZones.getStringFromZoneProperty(aZone, "f?", "none")
end end
if cfxZones.hasProperty(aZone, "startSmoke?") then
aZone.onFlag = cfxZones.getStringFromZoneProperty(aZone, "startSmoke?", "none")
end
if aZone.onFlag then if aZone.onFlag then
aZone.onFlagVal = trigger.misc.getUserFlag(aZone.onFlag) -- save last value aZone.onFlagVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- save last value
end end
end end
@ -67,7 +77,7 @@ function cfxSmokeZone.addSmokeZoneWithColor(aZone, aColor, anAltitude, paused, o
if onFlag then if onFlag then
aZone.onFlag = onFlag aZone.onFlag = onFlag
aZone.onFlagVal = trigger.misc.getUserFlag(onFlag) aZone.onFlagVal = cfxZones.getFlagValue(aZone.onFlag, aZone) -- trigger.misc.getUserFlag(onFlag)
end end
cfxSmokeZone.addSmokeZone(aZone) -- add to update loop cfxSmokeZone.addSmokeZone(aZone) -- add to update loop
@ -123,7 +133,7 @@ function cfxSmokeZone.checkFlags()
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
local currTriggerVal = 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)

View File

@ -1,5 +1,5 @@
cfxSpawnZones = {} cfxSpawnZones = {}
cfxSpawnZones.version = "1.5.2" cfxSpawnZones.version = "1.5.3"
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
@ -52,6 +52,7 @@ cfxSpawnZones.verbose = false
-- 1.5.1 - relaxed baseName and default to dcsCommon.uuid() -- 1.5.1 - relaxed baseName and default to dcsCommon.uuid()
-- - verbose -- - verbose
-- 1.5.2 - activate?, pause? flag -- 1.5.2 - activate?, pause? flag
-- 1.5.3 - spawn?, spawnUnits? flags
-- --
-- new version requires cfxGroundTroops, where they are -- new version requires cfxGroundTroops, where they are
-- --
@ -140,6 +141,17 @@ function cfxSpawnZones.createSpawner(inZone)
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end end
-- synonyms spawn? and spawnObject?
if cfxZones.hasProperty(inZone, "spawn?") then
theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawn?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end
if cfxZones.hasProperty(inZone, "spawnUnits?") then
theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawnObject?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end
if cfxZones.hasProperty(inZone, "activate?") then if cfxZones.hasProperty(inZone, "activate?") then
theSpawner.activateFlag = cfxZones.getStringFromZoneProperty(inZone, "activate?", "none") theSpawner.activateFlag = cfxZones.getStringFromZoneProperty(inZone, "activate?", "none")
theSpawner.lastActivateValue = trigger.misc.getUserFlag(theSpawner.activateFlag) theSpawner.lastActivateValue = trigger.misc.getUserFlag(theSpawner.activateFlag)

View File

@ -6,7 +6,7 @@
-- --
cfxZones = {} cfxZones = {}
cfxZones.version = "2.5.5" cfxZones.version = "2.5.6"
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
- 2.2.4 - getCoalitionFromZoneProperty - 2.2.4 - getCoalitionFromZoneProperty
- getStringFromZoneProperty - getStringFromZoneProperty
@ -50,6 +50,10 @@ cfxZones.version = "2.5.5"
- extractPropertyFromDCS trims key and property - extractPropertyFromDCS trims key and property
- 2.5.5 - pollFlag() centralized for banging - 2.5.5 - pollFlag() centralized for banging
- allStaticsInZone - allStaticsInZone
- 2.5.6 - flag accessor setFlagValue(), getFlagValue
- pollFlag supports theZone as final parameter
- randomDelayFromPositiveRange
- isMEFlag
--]]-- --]]--
cfxZones.verbose = false cfxZones.verbose = false
@ -197,6 +201,7 @@ function cfxZones.readFromDCS(clearfirst)
-- add to my table -- add to my table
cfxZones.zones[upperName] = newZone -- WARNING: UPPER ZONE!!! cfxZones.zones[upperName] = newZone -- WARNING: UPPER ZONE!!!
--trigger.action.outText("znd: procced " .. newZone.name .. " with radius " .. newZone.radius, 30)
else else
if cfxZones.verbose then if cfxZones.verbose then
trigger.action.outText("cf/x zones: malformed zone #" .. i .. " dropped", 10) trigger.action.outText("cf/x zones: malformed zone #" .. i .. " dropped", 10)
@ -467,11 +472,13 @@ end;
function cfxZones.isPointInsideZone(thePoint, theZone) function cfxZones.isPointInsideZone(thePoint, theZone)
local p = {x=thePoint.x, y = 0, z = thePoint.z} -- zones have no altitude local p = {x=thePoint.x, y = 0, z = thePoint.z} -- zones have no altitude
if (theZone.isCircle) then if (theZone.isCircle) then
local zp = cfxZones.getPoint(theZone)
local d = dcsCommon.dist(p, theZone.point) local d = dcsCommon.dist(p, theZone.point)
return d < theZone.radius return d < theZone.radius
end end
if (theZone.isPoly) then if (theZone.isPoly) then
--trigger.action.outText("zne: isPointInside: " .. theZone.name .. " is Polyzone!", 30)
return (cfxZones.isPointInsidePoly(p, theZone.poly)) return (cfxZones.isPointInsidePoly(p, theZone.poly))
end end
@ -550,6 +557,7 @@ end
-- --
function cfxZones.allGroupsInZone(theZone, categ) -- categ is optional, must be code function cfxZones.allGroupsInZone(theZone, categ) -- categ is optional, must be code
-- warning: does not check for exiting! -- warning: does not check for exiting!
--trigger.action.outText("Zone " .. theZone.name .. " radius " .. theZone.radius, 30)
local inZones = {} local inZones = {}
local coals = {0, 1, 2} -- all coalitions local coals = {0, 1, 2} -- all coalitions
for idx, coa in pairs(coals) do for idx, coa in pairs(coals) do
@ -601,9 +609,12 @@ function cfxZones.isGroupPartiallyInZone(aGroup, aZone)
for uk, aUnit in pairs (allUnits) do for uk, aUnit in pairs (allUnits) do
if aUnit:isExist() and aUnit:getLife() > 1 then if aUnit:isExist() and aUnit:getLife() > 1 then
local p = aUnit:getPoint() local p = aUnit:getPoint()
if cfxZones.isPointInsideZone(p, aZone) then local inzone, percent, dist = cfxZones.pointInZone(p, aZone)
if inzone then -- cfxZones.isPointInsideZone(p, aZone) then
--trigger.action.outText("zne: YAY <" .. aUnit:getName() .. "> IS IN " .. aZone.name, 30)
return true return true
end end
--trigger.action.outText("zne: <" .. aUnit:getName() .. "> not in " .. aZone.name .. ", dist = " .. dist .. ", rad = ", aZone.radius, 30)
end end
end end
return false return false
@ -1048,7 +1059,7 @@ end
-- --
-- Flag Pulling -- Flag Pulling
-- --
function cfxZones.pollFlag(theFlag, method) function cfxZones.pollFlag(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)
end end
@ -1085,6 +1096,68 @@ function cfxZones.pollFlag(theFlag, method)
end end
end end
function cfxZones.setFlagValue(theFlag, theValue, theZone)
local zoneName = "<dummy>"
if not theZone then
trigger.action.outText("+++Zne: no zone on setFlagValue")
else
zoneName = theZone.name -- for flag wildcards
end
if type(theFlag) == "number" then
-- straight set, ME flag
trigger.action.setUserFlag(theFlag, theValue)
return
end
-- we assume it's a string now
theFlag = dcsCommon.trim(theFlag) -- clear leading/trailing spaces
local nFlag = tonumber(theFlag)
if nFlag then
trigger.action.setUserFlag(theFlag, theValue)
return
end
-- now do wildcard processing. we have alphanumeric
if dcsCommon.stringStartsWith(theFlag, "*") then
theFlag = zoneName .. theFlag
end
trigger.action.setUserFlag(theFlag, theValue)
end
function cfxZones.getFlagValue(theFlag, theZone)
local zoneName = "<dummy>"
if not theZone then
trigger.action.outText("+++Zne: no zone on getFlagValue")
else
zoneName = theZone.name -- for flag wildcards
end
if type(theFlag) == "number" then
-- straight get, ME flag
return trigger.misc.getUserFlag(theFlag)
end
-- we assume it's a string now
theFlag = dcsCommon.trim(theFlag) -- clear leading/trailing spaces
local nFlag = tonumber(theFlag)
if nFlag then
return trigger.misc.getUserFlag(theFlag)
end
-- now do wildcard processing. we have alphanumeric
if dcsCommon.stringStartsWith(theFlag, "*") then
theFlag = zoneName .. theFlag
end
return trigger.misc.getUserFlag(theFlag)
end
function cfxZones.isMEFlag(inFlag)
return true
-- returns true if inFlag is a pure positive number
-- inFlag = dcsCommon.trim(inFlag)
-- return dcsCommon.stringIsPositiveNumber(inFlag)
end
-- --
-- PROPERTY PROCESSING -- PROPERTY PROCESSING
@ -1167,6 +1240,19 @@ function cfxZones.getMinMaxFromZoneProperty(theZone, theProperty)
end end
function cfxZones.randomDelayFromPositiveRange(minVal, maxVal)
if not maxVal then return minVal end
if not minVal then return maxVal end
local delay = maxVal
if minVal > 0 and minVal < delay then
-- we want a randomized from time from minTime .. delay
local varPart = delay - minVal + 1
varPart = dcsCommon.smallRandom(varPart) - 1
delay = minVal + varPart
end
return delay
end
function cfxZones.getPositiveRangeFromZoneProperty(theZone, theProperty, default) function cfxZones.getPositiveRangeFromZoneProperty(theZone, theProperty, default)
-- reads property as string, and interprets as range 'a-b'. -- reads property as string, and interprets as range 'a-b'.
-- if not a range but single number, returns both for upper and lower -- if not a range but single number, returns both for upper and lower

View File

@ -1,5 +1,5 @@
cloneZones = {} cloneZones = {}
cloneZones.version = "1.1.1" cloneZones.version = "1.2.0"
cloneZones.verbose = false cloneZones.verbose = false
cloneZones.requiredLibs = { cloneZones.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -7,7 +7,10 @@ cloneZones.requiredLibs = {
"cfxMX", "cfxMX",
} }
cloneZones.cloners = {} cloneZones.cloners = {}
cloneZones.callbacks = {}
cloneZones.unitXlate = {}
cloneZones.groupXlate = {} -- used to translate original groupID to cloned. only holds last spawned group id
cloneZones.uniqueCounter = 9200000 -- we start group numbering here
--[[-- --[[--
Clones Groups from ME mission data Clones Groups from ME mission data
Copyright (c) 2022 by Christian Franz and cf/x AG Copyright (c) 2022 by Christian Franz and cf/x AG
@ -18,6 +21,16 @@ cloneZones.cloners = {}
1.1.0 - support for static objects 1.1.0 - support for static objects
- despawn? attribute - despawn? attribute
1.1.1 - despawnAll: isExist guard 1.1.1 - despawnAll: isExist guard
- map in? to f?
1.2.0 - Lua API integration: callbacks
- groupXlate struct
- unitXlate struct
- resolveReferences
- getGroupsInZone rewritten for data
- static resolve
- linkUnit resolve
- clone? synonym
- empty! and method attributes
--]]-- --]]--
@ -38,18 +51,82 @@ function cloneZones.getCloneZoneByName(aName)
return nil return nil
end end
--
-- callbacks
--
function cloneZones.addCallback(theCallback)
if not theCallback then return end
table.insert(cloneZones.callbacks, theCallback)
end
-- reasons for callback
-- "will despawn group" - args is the group about to be despawned
-- "did spawn group" -- args is group that was spawned
-- "will despawn static"
-- "did spawn static"
-- "spawned" -- completed spawn cycle. args contains .groups and .statics spawned
-- "empty" -- all spawns have been killed, args is empty
-- "wiped" -- preWipe executed
-- "<none" -- something went wrong
function cloneZones.invokeCallbacks(theZone, reason, args)
if not theZone then return end
if not reason then reason = "<none>" end
if not args then args = {} end
-- invoke anyone who wants to know that a group
-- of people was rescued.
for idx, cb in pairs(cloneZones.callbacks) do
cb(theZone, reason, args)
end
end
-- group translation orig id
-- --
-- reading zones -- reading zones
-- --
function cloneZones.partOfGroupDataInZone(theZone, theUnits)
local zP = cfxZones.getPoint(theZone)
zP.y = 0
for idx, aUnit in pairs(theUnits) do
local uP = {}
uP.x = aUnit.x
uP.y = 0
uP.z = aUnit.y -- !! y-z
local dist = dcsCommon.dist(uP, zP)
if dist <= theZone.radius then return true end
end
return false
end
function cloneZones.allGroupsInZoneByData(theZone)
local theGroupsInZone = {}
local radius = theZone.radius
for groupName, groupData in pairs(cfxMX.groupDataByName) do
if groupData.units then
if cloneZones.partOfGroupDataInZone(theZone, groupData.units) then
theGroup = Group.getByName(groupName)
table.insert(theGroupsInZone, theGroup)
end
end
end
return theGroupsInZone
end
function cloneZones.createClonerWithZone(theZone) -- has "Cloner" function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
local localZones = cfxZones.allGroupsInZone(theZone) if cloneZones.verbose then
trigger.action.outText("+++clnZ: new cloner " .. theZone.name, 30)
end
local localZones = cloneZones.allGroupsInZoneByData(theZone)
local localObjects = cfxZones.allStaticsInZone(theZone) local localObjects = cfxZones.allStaticsInZone(theZone)
theZone.cloner = true -- this is a cloner zoner theZone.cloner = true -- this is a cloner zoner
theZone.mySpawns = {} theZone.mySpawns = {}
theZone.myStatics = {} theZone.myStatics = {}
--theZone.groupVectors = {}
theZone.origin = cfxZones.getPoint(theZone) -- save reference point for all groupVectors theZone.origin = cfxZones.getPoint(theZone) -- save reference point for all groupVectors
-- source tells us which template to use. it can be the following: -- source tells us which template to use. it can be the following:
@ -72,8 +149,15 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
if gName then if gName then
table.insert(theZone.cloneNames, gName) table.insert(theZone.cloneNames, gName)
table.insert(theZone.mySpawns, aGroup) -- collect them for initial despawn table.insert(theZone.mySpawns, aGroup) -- collect them for initial despawn
-- now get group data and save a lookup for
-- resolving internal references
local rawData, cat, ctry = cfxMX.getGroupFromDCSbyName(gName)
local origID = rawData.groupId
-- cloneZones.templateGroups[gName] = origID
-- cloneZones.templateGroupsReverse[origID] = gName
end end
end end
for idx, aStatic in pairs (localObjects) do for idx, aStatic in pairs (localObjects) do
local sName = aStatic:getName() local sName = aStatic:getName()
if sName then if sName then
@ -111,6 +195,12 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value
end end
-- synonyms
if cfxZones.hasProperty(theZone, "clone?") then
theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "clone?", "none")
theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value
end
-- deSpawn? -- deSpawn?
if cfxZones.hasProperty(theZone, "deSpawn?") then if cfxZones.hasProperty(theZone, "deSpawn?") then
theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "deSpawn?", "none") theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "deSpawn?", "none")
@ -127,16 +217,19 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
theZone.emptyFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty+1", "<None>") -- note string on number default theZone.emptyFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty+1", "<None>") -- note string on number default
end end
if cfxZones.hasProperty(theZone, "empty!") then
theZone.emptyBangFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty!", "<None>") -- note string on number default
end
theZone.method = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
if cfxZones.hasProperty(theZone, "masterOwner") then if cfxZones.hasProperty(theZone, "masterOwner") then
theZone.masterOwner = cfxZones.getStringFromZoneProperty(theZone, "masterOwner", "<none>") theZone.masterOwner = cfxZones.getStringFromZoneProperty(theZone, "masterOwner", "<none>")
end end
--cloneZones.spawnWithCloner(theZone)
theZone.turn = cfxZones.getNumberFromZoneProperty(theZone, "turn", 0) theZone.turn = cfxZones.getNumberFromZoneProperty(theZone, "turn", 0)
-- make sure we spawn at least once -- we end with clear plate
-- bad idea, since we may want to simply create a template
-- if not theZone.spawnFlag then theZone.onStart = true end
end end
-- --
@ -148,7 +241,10 @@ function cloneZones.despawnAll(theZone)
trigger.action.outText("wiping <" .. theZone.name .. ">", 30) trigger.action.outText("wiping <" .. theZone.name .. ">", 30)
end end
for idx, aGroup in pairs(theZone.mySpawns) do for idx, aGroup in pairs(theZone.mySpawns) do
--trigger.action.outText("++clnZ: despawn all " .. aGroup.name, 30)
if aGroup:isExist() then if aGroup:isExist() then
cloneZones.invokeCallbacks(theZone, "will despawn group", aGroup)
Group.destroy(aGroup) Group.destroy(aGroup)
end end
end end
@ -156,7 +252,10 @@ function cloneZones.despawnAll(theZone)
-- warning! may be mismatch because we are looking at groups -- warning! may be mismatch because we are looking at groups
-- not objects. let's see -- not objects. let's see
if aStatic:isExist() then if aStatic:isExist() then
trigger.action.outText("Destroying static <" .. aStatic:getName() .. ">", 30) if cloneZones.verbose then
trigger.action.outText("Destroying static <" .. aStatic:getName() .. ">", 30)
end
cloneZones.invokeCallbacks(theZone, "will despawn static", aStatic)
Object.destroy(aStatic) -- we don't aStatio:destroy() to find out what it is Object.destroy(aStatic) -- we don't aStatio:destroy() to find out what it is
end end
end end
@ -165,7 +264,7 @@ function cloneZones.despawnAll(theZone)
end end
function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWaypoints) function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWaypoints)
--trigger.action.outText("Update loc - zone delta: [" .. zoneDelta.x .. "," .. zoneDelta.z .. "]", 30)
-- remember that zoneDelta's [z] modifies theData's y!! -- remember that zoneDelta's [z] modifies theData's y!!
theData.x = theData.x + zoneDelta.x theData.x = theData.x + zoneDelta.x
theData.y = theData.y + zoneDelta.z -- !!! theData.y = theData.y + zoneDelta.z -- !!!
@ -178,8 +277,6 @@ function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWayp
-- first waypoint, but only all others if asked -- first waypoint, but only all others if asked
-- to -- to
local theRoute = theData.route local theRoute = theData.route
-- TODO: vehicles can have 'spans' - may need to program for
-- those as well. we currently only go for points
if theRoute then if theRoute then
local thePoints = theRoute.points local thePoints = theRoute.points
if thePoints and #thePoints > 0 then if thePoints and #thePoints > 0 then
@ -227,8 +324,13 @@ function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWayp
end end
end end
end end
function cloneZones.uniqueID()
local uid = cloneZones.uniqueCounter
cloneZones.uniqueCounter = cloneZones.uniqueCounter + 1
return uid
end
function cloneZones.uniqueNameGroupData(theData) function cloneZones.uniqueNameGroupData(theData)
theData.name = dcsCommon.uuid(theData.name) theData.name = dcsCommon.uuid(theData.name)
local units = theData.units local units = theData.units
for idx, aUnit in pairs(units) do for idx, aUnit in pairs(units) do
@ -236,6 +338,21 @@ function cloneZones.uniqueNameGroupData(theData)
end end
end end
function cloneZones.uniqueIDGroupData(theData)
theData.groupId = cloneZones.uniqueID()
end
function cloneZones.uniqueIDUnitData(theData)
if not theData then return end
if not theData.units then return end
local units = theData.units
for idx, aUnit in pairs(units) do
aUnit.CZorigID = aUnit.unitId
aUnit.unitId = cloneZones.uniqueID()
aUnit.CZTargetID = aUnit.unitId
end
end
function cloneZones.resolveOwnership(spawnZone, ctry) function cloneZones.resolveOwnership(spawnZone, ctry)
if not spawnZone.masterOwner then return ctry end if not spawnZone.masterOwner then return ctry end
@ -254,9 +371,151 @@ function cloneZones.resolveOwnership(spawnZone, ctry)
return ctry return ctry
end end
--
-- resolve external group references
--
function cloneZones.resolveGroupID(gID, rawData, dataTable, reason)
local resolvedID = gID
local myOName = rawData.CZorigName
local groupName = cfxMX.groupNamesByID[gID]
--trigger.action.outText("Resolve for <" .. myOName .. "> the external ID: " .. gID .. " --> " .. groupName .. " for <" .. reason.. "> task", 30)
-- first, check if this an internal reference, i.e. inside the same
-- zone template
for idx, otherData in pairs(dataTable) do
-- look in own data table
if otherData.CZorigName == groupName then
-- using cfxMX for clarity only (name access)
resolvedID = otherData.CZTargetID
--trigger.action.outText("resolved (internally) " .. gID .. " to " .. resolvedID, 30)
return resolvedID
end
end
-- now check if we have spawned this before
local lastClone = cloneZones.groupXlate[gID]
if lastClone then
resolvedID = lastClone
--trigger.action.outText("resolved (EXT) " .. gID .. " to " .. resolvedID, 30)
return resolvedID
end
-- if we get here, reference is not to a cloned item
--trigger.action.outText("resolved " .. gID .. " to " .. resolvedID, 30)
return resolvedID
end
function cloneZones.resolveUnitID(uID, rawData, dataTable, reason)
-- also resolves statics as they share ID with units
local resolvedID = uID
--trigger.action.outText("Resolve reference to unitId <" .. uID .. "> for <" .. reason.. "> task", 30)
-- first, check if this an internal reference, i.e. inside the same
-- zone template
for idx, otherData in pairs(dataTable) do
-- iterate all units
for idy, aUnit in pairs(otherData.units) do
if aUnit.CZorigID == uID then
resolvedID = aUnit.CZTargetID
--trigger.action.outText("resolved (internally) " .. uID .. " to " .. resolvedID, 30)
return resolvedID
end
end
end
-- now check if we have spawned this before
local lastClone = cloneZones.unitXlate[uID]
if lastClone then
resolvedID = lastClone
--trigger.action.outText("resolved (U-EXT) " .. uID .. " to " .. resolvedID, 30)
return resolvedID
end
-- if we get here, reference is not to a cloned item
--trigger.action.outText("resolved G-" .. uID .. " to " .. resolvedID, 30)
return resolvedID
end
function cloneZones.resolveStaticLinkUnit(uID)
local resolvedID = uID
local lastClone = cloneZones.unitXlate[uID]
if lastClone then
resolvedID = lastClone
--trigger.action.outText("resolved (U-EXT) " .. uID .. " to " .. resolvedID, 30)
return resolvedID
end
return resolvedID
end
function cloneZones.resolveWPReferences(rawData, theZone, dataTable)
-- check to see if we really need data table, as we have theZone
-- perform a check of route for group or unit references
if not rawData then return end
local myOName = rawData.CZorigName
if rawData.route and rawData.route.points then
local points = rawData.route.points
for idx, aPoint in pairs(points) do
-- check if there is a link unit here and resolve
if aPoint.linkUnit then
local gID = aPoint.linkUnit
local resolvedID = cloneZones.resolveUnitID(gID, rawData, dataTable, "linkUnit")
aPoint.linkUnit = resolvedID
--trigger.action.outText("resolved link unit to "..resolvedID .. " for " .. rawData.name, 30)
end
-- iterate all tasks assigned to point
local task = aPoint.task
if task and task.params and task.params.tasks then
local tasks = task.params.tasks
for idy, taskData in pairs(tasks) do
-- resolve group references in TASKS
if taskData.id and taskData.params and taskData.params.groupId
then
-- we resolve group reference
local gID = taskData.params.groupId
local resolvedID = cloneZones.resolveGroupID(gID, rawData, dataTable, taskData.id)
taskData.params.groupId = resolvedID
end
-- resolve unit references in TASKS
if taskData.id and taskData.params and taskData.params.unitId
then
-- we don't look for keywords, we simply resolve
local uID = taskData.params.unitId
local resolvedID = cloneZones.resolveUnitID(uID, rawData, dataTable, taskData.id)
taskData.params.unitId = resolvedID
end
-- resolve unit references in ACTIONS
if taskData.params and taskData.params.action and
taskData.params.action.params and taskData.params.action.params.unitId then
local uID = taskData.params.action.params.unitId
local resolvedID = cloneZones.resolveUnitID(uID, rawData, dataTable, "Action")
taskData.params.action.params.unitId = resolvedID
end
end
end
end
end
end
function cloneZones.resolveReferences(theZone, dataTable)
-- when an action refers to another group, we check if
-- the group referred to is also a clone, and update
-- the reference to the newest incardnation
for idx, rawData in pairs(dataTable) do
-- resolve references in waypoints
cloneZones.resolveWPReferences(rawData, theZone, dataTable)
end
end
function cloneZones.spawnWithTemplateForZone(theZone, spawnZone) function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
--trigger.action.outText("ENTER: Spawn with template " .. theZone.name .. " for spawnZone " .. spawnZone.name, 30) -- theZone is the cloner with the template
-- theZone is the zoner with the template
-- spawnZone is the spawner with settings -- spawnZone is the spawner with settings
--if not spawnZone then spawnZone = theZone end --if not spawnZone then spawnZone = theZone end
local newCenter = cfxZones.getPoint(spawnZone) local newCenter = cfxZones.getPoint(spawnZone)
@ -265,17 +524,23 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
local spawnedGroups = {} local spawnedGroups = {}
local spawnedStatics = {} local spawnedStatics = {}
local dataToSpawn = {}
for idx, aGroupName in pairs(theZone.cloneNames) do for idx, aGroupName in pairs(theZone.cloneNames) do
local rawData, cat, ctry = cfxMX.getGroupFromDCSbyName(aGroupName) local rawData, cat, ctry = cfxMX.getGroupFromDCSbyName(aGroupName)
rawData.CZorigName = rawData.name -- save original group name
if rawData.name == aGroupName then local origID = rawData.groupId -- save original group ID
else rawData.CZorigID = origID
cloneZones.uniqueIDGroupData(rawData) -- assign unique ID we know
cloneZones.uniqueIDUnitData(rawData) -- assign unique ID for units -- saves old unitId as CZorigID
rawData.CZTargetID = rawData.groupId -- save
if rawData.name ~= aGroupName then
trigger.action.outText("Clone: FAILED name check", 30) trigger.action.outText("Clone: FAILED name check", 30)
end end
-- now use raw data to spawn and see if it works outabox -- now use raw data to spawn and see if it works outabox
local theCat = cfxMX.catText2ID(cat) local theCat = cfxMX.catText2ID(cat)
rawData.CZtheCat = theCat -- save cat
-- update their position if not spawning to exact same location -- update their position if not spawning to exact same location
cloneZones.updateLocationsInGroupData(rawData, zoneDelta, spawnZone.moveRoute) cloneZones.updateLocationsInGroupData(rawData, zoneDelta, spawnZone.moveRoute)
@ -286,29 +551,76 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
-- make sure unit and group names are unique -- make sure unit and group names are unique
cloneZones.uniqueNameGroupData(rawData) cloneZones.uniqueNameGroupData(rawData)
-- see waht country we spawn for -- see what country we spawn for
ctry = cloneZones.resolveOwnership(spawnZone, ctry) ctry = cloneZones.resolveOwnership(spawnZone, ctry)
rawData.CZctry = ctry -- save ctry
local theGroup = coalition.addGroup(ctry, theCat, rawData) table.insert(dataToSpawn, rawData)
end
-- now resolve references to other cloned units for all raw data
-- we must do this BEFORE we spawn
cloneZones.resolveReferences(theZone, dataToSpawn)
-- now spawn all raw data
for idx, rawData in pairs (dataToSpawn) do
-- now spawn and save to clones
local theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
table.insert(spawnedGroups, theGroup) table.insert(spawnedGroups, theGroup)
--trigger.action.outText("spawned group " .. rawData.name .. "consisting of", 30)
-- update groupXlate table
local newGroupID = theGroup:getID() -- new ID assigned by DCS
local origID = rawData.CZorigID -- before we materialized
cloneZones.groupXlate[origID] = newGroupID
-- now also save all units for references
-- and verify assigned vs target ID
for idx, aUnit in pairs(rawData.units) do
-- access the proposed name
local uName = aUnit.name
local gUnit = Unit.getByName(uName)
if gUnit then
-- unit exists. compare planned and assigned ID
local uID = tonumber(gUnit:getID())
if uID == aUnit.CZTargetID then
--trigger.action.outText("unit " .. uName .. "#"..uID, 30)
-- all good
else
trigger.action.outText("clnZ: post-clone verification failed for unit <" .. uName .. ">: ÎD mismatch: " .. uID .. " -- " .. aUnit.CZTargetID, 30)
end
cloneZones.unitXlate[aUnit.CZorigID] = uID
else
trigger.action.outText("clnZ: post-clone verifiaction failed for unit <" .. uName .. ">: not found", 30)
end
end
-- check if our assigned ID matches the handed out by
-- DCS
if newGroupID == rawData.CZTargetID then
-- we are good
else
trigger.action.outText("clnZ: MISMATCH " .. rawData.name .. " target ID " .. rawData.CZTargetID .. " does not match " .. newGroupID, 30)
end
cloneZones.invokeCallbacks(theZone, "did spawn group", theGroup)
end end
-- static spawns -- static spawns
for idx, aStaticName in pairs(theZone.staticNames) do for idx, aStaticName in pairs(theZone.staticNames) do
local rawData, cat, ctry, parent = cfxMX.getStaticFromDCSbyName(aStaticName) local rawData, cat, ctry, parent = cfxMX.getStaticFromDCSbyName(aStaticName) -- returns a UNIT data block
if not rawData then if not rawData then
trigger.action.outText("Static Clone: no such group <"..aStaticName .. ">", 30) trigger.action.outText("Static Clone: no such group <"..aStaticName .. ">", 30)
elseif rawData.name == aStaticName then elseif rawData.name == aStaticName then
trigger.action.outText("Static Clone: suxess!!! <".. aStaticName ..">", 30) -- all good
else else
trigger.action.outText("Static Clone: FAILED name check for <" .. aStaticName .. ">", 30) trigger.action.outText("Static Clone: FAILED name check for <" .. aStaticName .. ">", 30)
end end
local origID = rawData.unitId -- save original unit ID
rawData.CZorigID = origID
-- now use raw data to spawn and see if it works outabox -- now use raw data to spawn and see if it works outabox
local theCat = cfxMX.catText2ID(cat) -- will be "static" --local theCat = cfxMX.catText2ID(cat) -- will be "static"
-- move origin -- move origin
rawData.x = rawData.x + zoneDelta.x rawData.x = rawData.x + zoneDelta.x
@ -317,20 +629,56 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
-- apply turning -- apply turning
dcsCommon.rotateUnitData(rawData, spawnZone.turn, newCenter.x, newCenter.z) dcsCommon.rotateUnitData(rawData, spawnZone.turn, newCenter.x, newCenter.z)
-- make sure static name is unique -- make sure static name is unique and remember original
-- cloneZones.uniqueNameGroupData(rawData)
rawData.name = dcsCommon.uuid(rawData.name) rawData.name = dcsCommon.uuid(rawData.name)
rawData.unitID = nil -- simply forget, will be newly issued rawData.unitId = cloneZones.uniqueID()
rawData.CZTargetID = rawData.unitId
-- see waht country we spawn for -- see what country we spawn for
ctry = cloneZones.resolveOwnership(spawnZone, ctry) ctry = cloneZones.resolveOwnership(spawnZone, ctry)
-- handle linkUnit if provided
if rawData.linkUnit then
--trigger.action.outText("has link to " .. rawData.linkUnit, 30)
local lU = cloneZones.resolveStaticLinkUnit(rawData.linkUnit)
--trigger.action.outText("resolved to " .. lU, 30)
rawData.linkUnit = lU
if not rawData.offsets then
rawData.offsets = {}
rawData.offsets.angle = 0
rawData.offsets.x = 0
rawData.offsets.y = 0
--trigger.action.outText("clnZ: link required offset for " .. rawData.name, 30)
end
rawData.offsets.y = rawData.offsets.y - zoneDelta.z
rawData.offsets.x = rawData.offsets.x - zoneDelta.x
rawData.offsets.angle = rawData.offsets.angle + spawnZone.turn
rawData.linkOffset = true
-- trigger.action.outText("zone deltas are " .. zoneDelta.x .. ", " .. zoneDelta.y, 30)
end
local theStatic = coalition.addStaticObject(ctry, rawData) local theStatic = coalition.addStaticObject(ctry, rawData)
local newStaticID = tonumber(theStatic:getID())
table.insert(spawnedStatics, theStatic) table.insert(spawnedStatics, theStatic)
-- we don't mix groups with units, so no lookup tables for
-- statics
if newStaticID == rawData.CZTargetID then
-- trigger.action.outText("Static ID OK: " .. newStaticID .. " for " .. rawData.name, 30)
else
trigger.action.outText("Static ID mismatch: " .. newStaticID .. " vs (target) " .. rawData.CZTargetID .. " for " .. rawData.name, 30)
end
cloneZones.unitXlate[origID] = newStaticID -- same as units
cloneZones.invokeCallbacks(theZone, "did spawn static", theStatic)
--]]-- --]]--
trigger.action.outText("Static spawn: spawned " .. aStaticName, 30) if cloneZones.verbose then
trigger.action.outText("Static spawn: spawned " .. aStaticName, 30)
end
end end
local args = {}
args.groups = spawnedGroups
args.statics = spawnedStatics
cloneZones.invokeCallbacks(theZone, "spawned", args)
return spawnedGroups, spawnedStatics return spawnedGroups, spawnedStatics
end end
@ -381,6 +729,7 @@ function cloneZones.spawnWithCloner(theZone)
-- pre-Wipe? -- pre-Wipe?
if theZone.preWipe then if theZone.preWipe then
cloneZones.despawnAll(theZone) cloneZones.despawnAll(theZone)
cloneZones.invokeCallbacks(theZone, "wiped", {})
end end
@ -454,6 +803,7 @@ function cloneZones.hasLiveUnits(theZone)
return false return false
end end
-- old code, deprecated
function cloneZones.pollFlag(flagNum, method) function cloneZones.pollFlag(flagNum, method)
-- we currently ignore method -- we currently ignore method
local num = trigger.misc.getUserFlag(flagNum) local num = trigger.misc.getUserFlag(flagNum)
@ -491,17 +841,24 @@ function cloneZones.update()
end end
end end
-- see if we are empty and should signal -- empty handling
if aZone.emptyFlag and aZone.hasClones then local isEmpty = cloneZones.countLiveUnits(aZone) < 1 and aZone.hasClones
if cloneZones.countLiveUnits(aZone) < 1 then if isEmpty then
-- we are depleted. poll flag once, then remember we have -- see if we need to bang a flag
-- polled if aZone.emptyFlag then
cloneZones.pollFlag(aZone.emptyFlag) cloneZones.pollFlag(aZone.emptyFlag)
aZone.hasClones = false end
if aZone.emptyBangFlag then
cfxZones.pollFlag(aZone.emptyBangFlag, aZone.method)
end end
-- invoke callbacks
cloneZones.invokeCallbacks(aZone, "empty", {})
-- prevent isEmpty next pass
aZone.hasClones = false
end end
end end
end end
@ -571,8 +928,25 @@ function cloneZones.start()
return true return true
end end
-- let's go! -- let's go!
if not cloneZones.start() then if not cloneZones.start() then
trigger.action.outText("cf/x Clone Zones aborted: missing libraries", 30) trigger.action.outText("cf/x Clone Zones aborted: missing libraries", 30)
cloneZones = nil cloneZones = nil
end end
--[[-- callback testing
czcb = {}
function czcb.callback(theZone, reason, args)
trigger.action.outText("clone CB: " .. theZone.name .. " with " .. reason, 30)
end
cloneZones.addCallback(czcb.callback)
--]]--
--[[--
to resolve tasks
- AFAC
- FAC Assign group
- set freq for unit
--]]--

View File

@ -15,6 +15,7 @@ countDown.requiredLibs = {
1.1.0 - Lua interface: callbacks 1.1.0 - Lua interface: callbacks
- corrected verbose (erroneously always suppressed) - corrected verbose (erroneously always suppressed)
- triggerFlag --> triggerCountFlag - triggerFlag --> triggerCountFlag
1.1.1 - corrected bug in invokeCallback
--]]-- --]]--
@ -56,7 +57,7 @@ function countDown.invokeCallbacks(theZone, val, tminus, zero, belowZero, loopin
-- invoke anyone who wants to know that a group -- invoke anyone who wants to know that a group
-- of people was rescued. -- of people was rescued.
for idx, cb in pairs(csarManager.csarCompleteCB) do for idx, cb in pairs(countDown.callbacks) do
cb(theZone, val, tminus, zero, belowZero, looping) cb(theZone, val, tminus, zero, belowZero, looping)
end end
end end
@ -94,7 +95,7 @@ function countDown.createCountDownWithZone(theZone)
end end
if theZone.triggerCountFlag then if theZone.triggerCountFlag then
theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value theZone.lastCountTriggerValue = trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value
end end
-- zero! bang -- zero! bang
@ -184,13 +185,13 @@ function countDown.update()
-- make sure to re-start before reading time limit -- make sure to re-start before reading time limit
if aZone.triggerCountFlag then if aZone.triggerCountFlag then
local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerCountFlag) local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerCountFlag)
if currTriggerVal ~= aZone.lastTriggerValue if currTriggerVal ~= aZone.lastCountTriggerValue
then then
if countDown.verbose then if countDown.verbose then
trigger.action.outText("+++cntD: triggered on in?", 30) trigger.action.outText("+++cntD: triggered on in?", 30)
end end
countDown.isTriggered(aZone) countDown.isTriggered(aZone)
aZone.lastTriggerValue = trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value aZone.lastCountTriggerValue = trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value
end end
end end
end end

View File

@ -1,5 +1,5 @@
dcsCommon = {} dcsCommon = {}
dcsCommon.version = "2.5.4" dcsCommon.version = "2.5.5"
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB 2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB - clockPositionOfARelativeToB
@ -62,6 +62,9 @@ dcsCommon.version = "2.5.4"
- removed forced error in failed pickRandom - removed forced error in failed pickRandom
2.5.4 - rotateUnitData() 2.5.4 - rotateUnitData()
- randomBetween() - randomBetween()
2.5.5 - stringStartsWithDigit()
- stringStartsWithLetter()
- stringIsPositiveNumber()
--]]-- --]]--
@ -1700,7 +1703,31 @@ dcsCommon.version = "2.5.4"
return trimmedArray return trimmedArray
end end
-- same as cfxZones, this is the commonly used, may need to remove from zones function dcsCommon.stringIsPositiveNumber(theString)
-- only full integer positive numbers supported
if not theString then return false end
-- if theString == "" then return false end
for i = 1, #theString do
local c = theString:sub(i,i)
if c < "0" or c > "9" then return false end
end
return true
end
function dcsCommon.stringStartsWithDigit(theString)
if #theString < 1 then return false end
local c = string.sub(theString, 1, 1)
return c >= "0" and c <= "9"
end
function dcsCommon.stringStartsWithLetter(theString)
if #theString < 1 then return false end
local c = string.sub(theString, 1, 1)
if c >= "a" and c <= "z" then return true end
if c >= "A" and c <= "Z" then return true end
return false
end
function dcsCommon.stringStartsWith(theString, thePrefix) function dcsCommon.stringStartsWith(theString, thePrefix)
return theString:find(thePrefix) == 1 return theString:find(thePrefix) == 1
end end
@ -2109,8 +2136,8 @@ end
function dcsCommon.init() function dcsCommon.init()
cbID = 0 cbID = 0
dcsCommon.uuIdent = 0 dcsCommon.uuIdent = 0
if (dcsCommon.verbose) then if (dcsCommon.verbose) or true then
trigger.action.outText("dcsCommon v" .. dcsCommon.version .. " loaded successfully", 10) trigger.action.outText("dcsCommon v" .. dcsCommon.version .. " loaded", 10)
end end
end end

View File

@ -1,5 +1,5 @@
delayFlag = {} delayFlag = {}
delayFlag.version = "1.0.2" delayFlag.version = "1.0.4"
delayFlag.verbose = false delayFlag.verbose = false
delayFlag.requiredLibs = { delayFlag.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -20,7 +20,9 @@ delayFlag.flags = {}
- using cfxZones for polling - using cfxZones for polling
- removed pollFlag - removed pollFlag
1.0.3 - bug fix for config zone name 1.0.3 - bug fix for config zone name
- removed message attribute, moved to own module - removed message attribute, moved to own module
- triggerFlag --> triggerDelayFlag
1.0.4 - startDelay
--]]-- --]]--
@ -55,15 +57,19 @@ function delayFlag.createTimerWithZone(theZone)
-- trigger flag -- trigger flag
if cfxZones.hasProperty(theZone, "f?") then if cfxZones.hasProperty(theZone, "f?") then
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none") theZone.triggerDelayFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
end end
if cfxZones.hasProperty(theZone, "in?") then if cfxZones.hasProperty(theZone, "in?") then
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") theZone.triggerDelayFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none")
end end
if theZone.triggerFlag then if cfxZones.hasProperty(theZone, "startDelay?") then
theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value theZone.triggerDelayFlag = cfxZones.getStringFromZoneProperty(theZone, "startDelay?", "none")
end
if theZone.triggerDelayFlag then
theZone.lastDelayTriggerValue = trigger.misc.getUserFlag(theZone.triggerDelayFlag) -- save last value
end end
@ -79,10 +85,6 @@ function delayFlag.createTimerWithZone(theZone)
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
end end
-- message
if cfxZones.hasProperty(theZone, "message") then
theZone.myMessage = cfxZones.getStringZoneProperty(theZone, "message", "<none>")
end
-- init -- init
theZone.running = false theZone.running = false
@ -128,9 +130,9 @@ function delayFlag.update()
for idx, aZone in pairs(delayFlag.flags) do for idx, aZone in pairs(delayFlag.flags) do
-- make sure to re-start before reading time limit -- make sure to re-start before reading time limit
if aZone.triggerFlag then if aZone.triggerDelayFlag then
local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerFlag) local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerDelayFlag)
if currTriggerVal ~= aZone.lastTriggerValue if currTriggerVal ~= aZone.lastDelayTriggerValue
then then
if delayFlag.verbose then if delayFlag.verbose then
if aZone.running then if aZone.running then
@ -140,7 +142,7 @@ function delayFlag.update()
end end
end end
delayFlag.startDelay(aZone) -- we restart even if running delayFlag.startDelay(aZone) -- we restart even if running
aZone.lastTriggerValue = currTriggerVal aZone.lastDelayTriggerValue = currTriggerVal
end end
end end
@ -152,9 +154,9 @@ function delayFlag.update()
-- poll flag -- poll flag
cfxZones.pollFlag(aZone.outFlag, aZone.method) cfxZones.pollFlag(aZone.outFlag, aZone.method)
-- say message -- say message
if aZone.myMessage then --if aZone.myMessage then
trigger.action.outText(aZone.myMessage, 30) -- trigger.action.outText(aZone.myMessage, 30)
end --end
end end
end end

View File

@ -1,5 +1,5 @@
messenger = {} messenger = {}
messenger.version = "1.0.0" messenger.version = "1.0.1"
messenger.verbose = false messenger.verbose = false
messenger.requiredLibs = { messenger.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -9,6 +9,8 @@ messenger.messengers = {}
--[[-- --[[--
Version History Version History
1.0.0 - initial version 1.0.0 - initial version
1.0.1 - messageOut? synonym
- spelling types in about
--]]-- --]]--
@ -53,6 +55,10 @@ function messenger.createMessengerDownWithZone(theZone)
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none")
end end
if cfxZones.hasProperty(theZone, "messageOut?") then
theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "messageOut?", "none")
end
if theZone.triggerMessagerFlag then if theZone.triggerMessagerFlag then
theZone.lastMessageTriggerValue = trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value theZone.lastMessageTriggerValue = trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value
end end
@ -125,10 +131,10 @@ end
function messenger.start() function messenger.start()
-- lib check -- lib check
if not dcsCommon.libCheck then if not dcsCommon.libCheck then
trigger.action.outText("cfx Count Down requires dcsCommon", 30) trigger.action.outText("cfx Messenger requires dcsCommon", 30)
return false return false
end end
if not dcsCommon.libCheck("cfx Count Down", messenger.requiredLibs) then if not dcsCommon.libCheck("cfx Messenger", messenger.requiredLibs) then
return false return false
end end

View File

@ -1,5 +1,5 @@
pulseFlags = {} pulseFlags = {}
pulseFlags.version = "1.0.2" pulseFlags.version = "1.0.3"
pulseFlags.verbose = false pulseFlags.verbose = false
pulseFlags.requiredLibs = { pulseFlags.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -14,6 +14,10 @@ pulseFlags.requiredLibs = {
- 1.0.0 Initial version - 1.0.0 Initial version
- 1.0.1 pause behavior debugged - 1.0.1 pause behavior debugged
- 1.0.2 zero pulse optional initial pulse suppress - 1.0.2 zero pulse optional initial pulse suppress
- 1.0.3 pollFlag switched to cfxZones
uses randomDelayFromPositiveRange
flag! now is string
WARNING: still needs full alphaNum flag upgrade
--]]-- --]]--
@ -28,7 +32,7 @@ end
-- --
function pulseFlags.createPulseWithZone(theZone) function pulseFlags.createPulseWithZone(theZone)
theZone.flag = cfxZones.getNumberFromZoneProperty(theZone, "flag!", -1) -- the flag to pulse theZone.flag = cfxZones.getStringFromZoneProperty(theZone, "flag!", -1) -- the flag to pulse
-- time can be number, or number-number range -- time can be number, or number-number range
theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "time", 1) theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "time", 1)
@ -68,42 +72,6 @@ end
-- --
-- update -- update
-- --
function pulseFlags.pollFlag(theFlag, method)
if pulseFlags.verbose then
trigger.action.outText("+++PulF: polling flag " .. theFlag .. " with " .. method, 30)
end
method = method:lower()
local currVal = trigger.misc.getUserFlag(theFlag)
if method == "inc" or method == "f+1" then
trigger.action.setUserFlag(theFlag, currVal + 1)
elseif method == "dec" or method == "f-1" then
trigger.action.setUserFlag(theFlag, currVal - 1)
elseif method == "off" or method == "f=0" then
trigger.action.setUserFlag(theFlag, 0)
elseif method == "flip" or method == "xor" then
if currVal ~= 0 then
trigger.action.setUserFlag(theFlag, 0)
else
trigger.action.setUserFlag(theFlag, 1)
end
else
if method ~= "on" and method ~= "f=1" then
trigger.action.outText("+++PulF: unknown method <" .. method .. "> - using 'on'", 30)
end
-- default: on.
trigger.action.setUserFlag(theFlag, 1)
end
local newVal = trigger.misc.getUserFlag(theFlag)
if pulseFlags.verbose then
trigger.action.outText("+++PulF: flag <" .. theFlag .. "> changed from " .. currVal .. " to " .. newVal, 30)
end
end
function pulseFlags.doPulse(args) function pulseFlags.doPulse(args)
@ -118,7 +86,7 @@ function pulseFlags.doPulse(args)
-- do a poll on flags -- do a poll on flags
-- first, we only do an initial pulse if zeroPulse is set -- first, we only do an initial pulse if zeroPulse is set
if theZone.hasPulsed or theZone.zeroPulse then if theZone.hasPulsed or theZone.zeroPulse then
pulseFlags.pollFlag(theZone.flag, theZone.method) cfxZones.pollFlag(theZone.flag, theZone.method, theZone)
-- decrease count -- decrease count
if theZone.pulses > 0 then if theZone.pulses > 0 then
@ -149,6 +117,7 @@ function pulseFlags.doPulse(args)
theZone.hasPulsed = true -- we are past initial pulse theZone.hasPulsed = true -- we are past initial pulse
-- if we get here, schedule next pulse -- if we get here, schedule next pulse
--[[--
local delay = theZone.time local delay = theZone.time
if theZone.minTime > 0 and theZone.minTime < delay then if theZone.minTime > 0 and theZone.minTime < delay then
-- we want a randomized from time from minTime .. delay -- we want a randomized from time from minTime .. delay
@ -156,6 +125,8 @@ function pulseFlags.doPulse(args)
varPart = dcsCommon.smallRandom(varPart) - 1 varPart = dcsCommon.smallRandom(varPart) - 1
delay = theZone.minTime + varPart delay = theZone.minTime + varPart
end end
--]]--
local delay = cfxZones.randomDelayFromPositiveRange(theZone.minTime, theZone.time)
--trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> scheduled in ".. delay .."!", 30) --trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> scheduled in ".. delay .."!", 30)

137
modules/raiseFlag.lua Normal file
View File

@ -0,0 +1,137 @@
raiseFlag = {}
raiseFlag.version = "1.0.0"
raiseFlag.verbose = false
raiseFlag.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
}
raiseFlag.flags = {}
--[[--
Raise A Flag module -- (c) 2022 by Christian Franz and cf/x AG
Version History
1.0.0 - initial release
--]]--
function raiseFlag.addRaiseFlag(theZone)
table.insert(raiseFlag.flags, theZone)
end
function raiseFlag.getRaiseFlagByName(aName)
for idx, aZone in pairs(raiseFlag.flags) do
if aName == aZone.name then return aZone end
end
if raiseFlag.verbose then
trigger.action.outText("+++rFlg: no raiseFlag with name <" .. aName ..">", 30)
end
return nil
end
--
-- read attributes
--
function raiseFlag.createRaiseFlagWithZone(theZone)
-- get flag from faiseFlag itself
theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag", "<none>") -- the flag to raise
theZone.flagValue = cfxZones.getNumberFromZoneProperty(theZone, "value", 1) -- value to set to
theZone.minAfterTime, theZone.maxAfterTime = cfxZones.getPositiveRangeFromZoneProperty(theZone, "afterTime", -1)
if cfxZones.hasProperty(theZone, "stopFlag?") then
theZone.triggerStopFlag = cfxZones.getStringFromZoneProperty(theZone, "stopFlag?", "none")
theZone.lastTriggerStopValue = cfxZones.getFlagValue(theZone.triggerStopFlag, theZone) -- save last value
end
theZone.scheduleID = nil
theZone.raiseStopped = false
-- now simply schedule for invocation
local args = {}
args.theZone = theZone
if theZone.minAfterTime < 1 then
timer.scheduleFunction(raiseFlag.triggered, args, timer.getTime() + 0.5)
else
local delay = cfxZones.randomDelayFromPositiveRange(theZone.minAfterTime, theZone.maxAfterTime)
timer.scheduleFunction(raiseFlag.triggered, args, timer.getTime() + delay)
end
end
function raiseFlag.triggered(args)
local theZone = args.theZone
if theZone.raiseStopped then return end
-- if we get here, we aren't stopped and do the flag pull
cfxZones.setFlagValue(theZone.raiseFlag, theZone.flagValue, theZone)
end
--
-- update
--
function raiseFlag.update()
-- call me in a second to poll triggers
timer.scheduleFunction(raiseFlag.update, {}, timer.getTime() + 1)
for idx, aZone in pairs(raiseFlag.flags) do
-- make sure to re-start before reading time limit
if aZone.triggerStopFlag then
local currTriggerVal = cfxZones.getFlagValue(aZone.triggerStopFlag, theZone)
if currTriggerVal ~= aZone.lastTriggerStopValue
then
theZone.raiseStopped = true -- we are done, no flag!
end
end
end
end
--
-- config & go!
--
function raiseFlag.readConfigZone()
local theZone = cfxZones.getZoneByName("raiseFlagConfig")
if not theZone then
if raiseFlag.verbose then
trigger.action.outText("+++rFlg: NO config zone!", 30)
end
return
end
raiseFlag.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
if raiseFlag.verbose then
trigger.action.outText("+++rFlg: read config", 30)
end
end
function raiseFlag.start()
-- lib check
if not dcsCommon.libCheck then
trigger.action.outText("cfx raise flag requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx Count Down", raiseFlag.requiredLibs) then
return false
end
-- read config
raiseFlag.readConfigZone()
-- process cloner Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("raiseFlag")
for k, aZone in pairs(attrZones) do
raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes
raiseFlag.addRaiseFlag(aZone) -- add to list
end
-- start update
raiseFlag.update()
trigger.action.outText("cfx raiseFlag v" .. raiseFlag.version .. " started.", 30)
return true
end
-- let's go!
if not raiseFlag.start() then
trigger.action.outText("cfx Raise Flag aborted: missing libraries", 30)
raiseFlag = nil
end

Binary file not shown.

Binary file not shown.