diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index a735dae..2bc4caa 100644 Binary files a/Doc/DML Documentation.pdf and b/Doc/DML Documentation.pdf differ diff --git a/Doc/DML Quick Reference.pdf b/Doc/DML Quick Reference.pdf index 7a3e0f1..110c5e6 100644 Binary files a/Doc/DML Quick Reference.pdf and b/Doc/DML Quick Reference.pdf differ diff --git a/modules/LZ.lua b/modules/LZ.lua new file mode 100644 index 0000000..5561f73 --- /dev/null +++ b/modules/LZ.lua @@ -0,0 +1,145 @@ +LZ = {} +LZ.version = "0.0.0" +LZ.verbose = false +LZ.ups = 1 +LZ.requiredLibs = { + "dcsCommon", -- always + "cfxZones", -- Zones, of course +} +LZ.LZs = {} + +--[[-- + Version History + 1.0.0 - initial version + + +--]]-- + +function LZ.addLZ(theZone) + table.insert(LZ.LZs, theZone) +end + +function LZ.getLZByName(aName) + for idx, aZone in pairs(LZ.LZs) do + if aName == aZone.name then return aZone end + end + if LZ.verbose then + trigger.action.outText("+++LZ: no LZ with name <" .. aName ..">", 30) + end + + return nil +end + +-- +-- read zone +-- +function LZ.createLZWithZone(theZone) + -- read main trigger + theZone.triggerLZFlag = cfxZones.getStringFromZoneProperty(theZone, "lz!", "*") + + -- TriggerMethod: common and specific synonym + theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") + + if cfxZones.hasProperty(theZone, "lzTriggerMethod") then + theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "lzMethod", "change") + end + + if LZ.verbose or theZone.verbose then + trigger.action.outText("+++LZ: new LZ <".. theZone.name ..">", 30) + end + +end + +-- +-- MAIN ACTION +-- +function LZ.processUpdate(theZone) + +end + +-- +-- Event Handling +-- +function LZ:onEvent(event) + -- only interested in S_EVENT_BASE_CAPTURED events + if event.id ~= world.event.S_EVENT_BASE_CAPTURED then + return + end + + for idx, aZone in pairs(LZ.LZs) do + -- check if landed inside and of correct type, colition, name whatever + + end +end + +-- +-- Update +-- + +function LZ.update() + -- call me in a second to poll triggers + timer.scheduleFunction(LZ.update, {}, timer.getTime() + 1/LZ.ups) + + for idx, aZone in pairs(LZ.LZs) do + -- see if we are triggered + if cfxZones.testZoneFlag(aZone, aZone.triggerLZFlag, aZone.LZTriggerMethod, "lastTriggerLZValue") then + if LZ.verbose or theZone.verbose then + trigger.action.outText("+++LZ: triggered on main? for <".. aZone.name ..">", 30) + end + LZ.processUpdate(aZone) + end + end +end + +-- +-- Config & Start +-- +function LZ.readConfigZone() + local theZone = cfxZones.getZoneByName("LZConfig") + if not theZone then + if LZ.verbose then + trigger.action.outText("+++LZ: NO config zone!", 30) + end + return + end + + LZ.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) + + if LZ.verbose then + trigger.action.outText("+++LZ: read config", 30) + end +end + +function LZ.start() + -- lib check + if not dcsCommon.libCheck then + trigger.action.outText("cfx LZ requires dcsCommon", 30) + return false + end + if not dcsCommon.libCheck("cfx LZ", LZ.requiredLibs) then + return false + end + + -- read config + LZ.readConfigZone() + + -- process LZ Zones + -- old style + local attrZones = cfxZones.getZonesWithAttributeNamed("lz!") + for k, aZone in pairs(attrZones) do + LZ.createLZWithZone(aZone) -- process attributes + LZ.addLZ(aZone) -- add to list + end + + -- start update + LZ.update() + + trigger.action.outText("cfx LZ v" .. LZ.version .. " started.", 30) + return true +end + +-- let's go! +if not LZ.start() then + trigger.action.outText("cfx LZ aborted: missing libraries", 30) + LZ = nil +end \ No newline at end of file diff --git a/modules/baseCaptured.lua b/modules/baseCaptured.lua index 88d33a5..0562aba 100644 --- a/modules/baseCaptured.lua +++ b/modules/baseCaptured.lua @@ -1,89 +1,100 @@ baseCaptured={} -baseCaptured.version = "1.0.1" +baseCaptured.version = "1.0.0" baseCaptured.verbose = false baseCaptured.requiredLibs = { "dcsCommon", -- always "cfxZones", -- Zones, of course } + --[[-- - baseCaptured - Detects when the assigned base has been captured - - Properties - - baseCaptured Marks this as baseCaptured zone. The value is ignored. - The closest base (airdrome or helipad) is automatically assigned to this zone. - (MANDATORY) - - coalition The coalition that needs to capture the base. Accepts 0/all, 1/red, 2/blue. - captureCoalition Defaults to 0 (all) - - method DML Flag method for output. Use only one synonym per zone. - capturedMethod Defaults to "flip". - - f! The flag to bang! after the base matching above filter criteria has been captured. - captured! Use only one synonym per zone. - - Configuration - - verbose Show debugging information. Default is false. + baseCaptured - Detects when the assigned base has been captured, idea and first implementation by cloose Version History - 1.0.0 - Initial version - 1.0.1 - Automatic Closest Base Assignment + 1.0.0 - Initial version based on cloose's code + --]]-- baseCaptured.zones = {} -function baseCaptured.assignClosestBase(theZone) - local base = dcsCommon.getClosestAirbaseTo(theZone.point) - if base then - theZone.baseName = base:getName() - if baseCaptured.verbose or theZone.verbose then - trigger.action.outText("***basedCaptured: assigned <" .. theZone.name .. "> to base <" .. theZone.baseName .. ">", 30) - end - else - trigger.action.outText("***basedCaptured: unable to resolve base for <" .. theZone.name .. ">", 30) - end -end function baseCaptured.createZone(theZone) - -- assign closest base - baseCaptured.assignClosestBase(theZone) - - -- coalition (1=red,2=blue,0=neutral/all) - theZone.captureCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0) - if cfxZones.hasProperty(theZone, "captureCoalition") then - theZone.captureCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "captureCoalition", 0) - end - - if baseCaptured.verbose or theZone.verbose then - trigger.action.outText("***basedCaptured: set coalition " .. theZone.captureCoalition .. " for <" .. theZone.name .. ">", 30) - end - + -- find closest base + theZone.theBase = dcsCommon.getClosestAirbaseTo(theZone.point) + theZone.baseName = theZone.theBase:getName() + theZone.currentOwner = theZone.theBase:getCoalition() + + -- baseCaptured is the method + theZone.capturedFlag = cfxZones.getStringFromZoneProperty(theZone, "baseCaptured!", "*none") + + -- get flag output method - theZone.capturedMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "flip") + theZone.capturedMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") if cfxZones.hasProperty(theZone, "capturedMethod") then - theZone.capturedMethod = cfxZones.getStringFromZoneProperty(theZone, "capturedMethod", "flip") + theZone.capturedMethod = cfxZones.getStringFromZoneProperty(theZone, "capturedMethod", "inc") end - -- get captured flag - if cfxZones.hasProperty(theZone, "f!") then - theZone.capturedFlag = cfxZones.getStringFromZoneProperty(theZone, "f!", "*none") + -- other outputs + if cfxZones.hasProperty(theZone, "blueCaptured!") then + theZone.blueCap = cfxZones.getStringFromZoneProperty(theZone, "blueCaptured!", "*none") end - if cfxZones.hasProperty(theZone, "captured!") then - theZone.capturedFlag = cfxZones.getStringFromZoneProperty(theZone, "captured!", "*none") + + if cfxZones.hasProperty(theZone, "blue!") then + theZone.blueCap = cfxZones.getStringFromZoneProperty(theZone, "blue!", "*none") + end + + if cfxZones.hasProperty(theZone, "redCaptured!") then + theZone.redCap = cfxZones.getStringFromZoneProperty(theZone, "blueCaptured!", "*none") + end + + if cfxZones.hasProperty(theZone, "red!") then + theZone.redCap = cfxZones.getStringFromZoneProperty(theZone, "red!", "*none") + end + + if cfxZones.hasProperty(theZone, "baseOwner") then + theZone.baseOwner = cfxZones.getStringFromZoneProperty(theZone, "baseOwner", "*none") + cfxZones.setFlagValueMult(theZone.baseOwner, theZone.currentOwner, theZone) + if baseCaptured.verbose or theZone.verbose then + trigger.action.outText("+++bCap: setting owner for <" .. theZone.name .. "> to " .. theZone.currentOwner, 30) + end + end + + if baseCaptured.verbose or theZone.verbose then + trigger.action.outText("+++bCap: tracking base <" .. theZone.baseName .. "> with <" .. theZone.name .. ">", 30) end end -function baseCaptured.addZone(theZone) - if not theZone.capturedFlag or theZone.capturedFlag == "*none" then - trigger.action.outText("***baseCaptured NOTE: " .. theZone.name .. " is missing a valid or property", 30) - return - end - +function baseCaptured.addBaseCaptureZone(theZone) table.insert(baseCaptured.zones, theZone) end function baseCaptured.triggerZone(theZone) + local newOwner = theZone.theBase:getCoalition() cfxZones.pollFlag(theZone.capturedFlag, theZone.capturedMethod, theZone) - if baseCaptured.verbose then - trigger.action.outText("***baseCaptured: banging captured! with <" .. theZone.capturedMethod .. "> on <" .. theZone.capturedFlag .. "> for " .. theZone.baseName, 30) + if newOwner == 1 then -- red + if theZone.redCap then + cfxZones.pollFlag(theZone.redCap, theZone.capturedMethod, theZone) + end + elseif newOwner == 2 then + if theZone.blueCap then + cfxZones.pollFlag(theZone.blueCap, theZone.capturedMethod, theZone) + end + else + -- possibly a new side? Neutral doesn't cap + end + + if baseCaptured.verbose or theZone.verbose then + trigger.action.outText("+++bCap: <" .. theZone.baseName .. "> changed hands from <" .. theZone.currentOwner .. "> to <" .. newOwner .. ">", 30) + trigger.action.outText("+++bCap: banging captured! with <" .. theZone.capturedMethod .. "> on <" .. theZone.capturedFlag .. "> for " .. theZone.baseName, 30) end + + -- change the ownership + theZone.currentOwner = newOwner + if theZone.baseOwner then + cfxZones.setFlagValueMult(theZone.baseOwner, newOwner, theZone) + if baseCaptured.verbose or theZone.verbose then + trigger.action.outText("+++bCap: owner is " .. newOwner, 30) + end + end end -- world event callback @@ -92,14 +103,16 @@ function baseCaptured:onEvent(event) if event.id ~= world.event.S_EVENT_BASE_CAPTURED then return end + if not event.place then + trigger.action.outText("+++bCap: capture event without place, aborting.", 30) + return + end local baseName = event.place:getName() local newCoalition = event.place:getCoalition() - for idx, aZone in pairs(baseCaptured.zones) do - local hasName = aZone.baseName == baseName - local hasCoalition = aZone.captureCoalition == 0 or aZone.captureCoalition == newCoalition - if hasName and hasCoalition then + for idx, aZone in pairs(baseCaptured.zones) do + if aZone.baseName == baseName then baseCaptured.triggerZone(aZone) end end @@ -115,7 +128,7 @@ function baseCaptured.readConfigZone() baseCaptured.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) if baseCaptured.verbose then - trigger.action.outText("***baseCaptured: read configuration from zone", 30) + trigger.action.outText("+++bCap: read configuration from zone", 30) end end @@ -133,10 +146,10 @@ function baseCaptured.start() baseCaptured.readConfigZone() -- process all baseCaptured zones - local zones = cfxZones.getZonesWithAttributeNamed("baseCaptured") + local zones = cfxZones.getZonesWithAttributeNamed("baseCaptured!") for k, aZone in pairs(zones) do baseCaptured.createZone(aZone) -- process zone attributes - baseCaptured.addZone(aZone) -- add to list + baseCaptured.addBaseCaptureZone(aZone) -- add to list end -- listen for events diff --git a/modules/cfxZones.lua b/modules/cfxZones.lua index 0f7e50c..3e4fdbc 100644 --- a/modules/cfxZones.lua +++ b/modules/cfxZones.lua @@ -6,7 +6,7 @@ -- cfxZones = {} -cfxZones.version = "2.7.5" +cfxZones.version = "2.7.6" --[[-- VERSION HISTORY - 2.2.4 - getCoalitionFromZoneProperty - getStringFromZoneProperty @@ -70,6 +70,7 @@ cfxZones.version = "2.7.5" - evalFlagMethodImmediate() - 2.7.4 - doPollFlag supports immediate number setting - 2.7.5 - more QoL checks when mixing up ? and ! for attributes + - 2.7.6 - trim for getBoolFromZoneProperty and getStringFromZoneProperty --]]-- cfxZones.verbose = false @@ -1417,7 +1418,7 @@ end function cfxZones.testZoneFlag(theZone, theFlagName, theMethod, latchName) -- returns two values: true/false method result, and curr value - -- returns true if method contraints are met for flag theFlagName + -- returns true if method constraints are met for flag theFlagName -- as defined by theMethod if not theMethod then theMethod = "change" @@ -1587,6 +1588,7 @@ function cfxZones.getStringFromZoneProperty(theZone, theProperty, default) local p = cfxZones.getZoneProperty(theZone, theProperty) if not p then return default end if type(p) == "string" then + p = dcsCommon.trim(p) if p == "" then p = default end return p end @@ -1714,6 +1716,7 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal) -- make sure we compare so default always works when -- answer isn't exactly the opposite p = p:lower() + p = dcsCommon.trim(p) if defaultVal == false then -- only go true if exact match to yes or true theBool = false diff --git a/modules/civAir.lua b/modules/civAir.lua index 2c36df9..99384ce 100644 --- a/modules/civAir.lua +++ b/modules/civAir.lua @@ -1,5 +1,5 @@ civAir = {} -civAir.version = "1.5.0" +civAir.version = "1.5.1" --[[-- 1.0.0 initial version 1.1.0 exclude list for airfields @@ -21,6 +21,7 @@ civAir.version = "1.5.0" reading type array from config corrected massive simplifications: always between zoned airfieds exclude list and include list + 1.5.1 added depart only and arrive only options for airfields --]]-- @@ -41,8 +42,7 @@ civAir.maxTraffic = 10 -- number of flights at the same time civAir.maxIdle = 8 * 60 -- seconds of ide time before it is removed after landing -civAir.trafficCenters = { - } +civAir.trafficCenters = {} -- place zones on the map and add a "civAir" attribute. -- If the attribute's value is anything -- but "exclude", the closest airfield to the zone @@ -52,8 +52,7 @@ civAir.trafficCenters = { -- by zones, the list is automatically populated with all -- airfields in the map -civAir.excludeAirfields = { - } +civAir.excludeAirfields = {} -- list all airfields that must NOT be included in -- civilian activities. Will be used for neither landing -- nor departure. overrides any airfield that was included @@ -62,6 +61,9 @@ civAir.excludeAirfields = { -- can be populated by zone on the map that have the -- 'civAir' attribute with value "exclude" +civAir.departOnly = {} -- use only to start from +civAir.landingOnly = {} -- use only to land at + civAir.requiredLibs = { "dcsCommon", -- common is of course needed for everything "cfxZones", -- zones management foc CSAR and CSAR Mission zones @@ -113,8 +115,13 @@ function civAir.processZone(theZone) local af = dcsCommon.getClosestAirbaseTo(theZone.point, 0) -- 0 = only airfields, not farp or ships if af then local afName = af:getName() - if value:lower() == "exclude" then + value = value:lower() + if value == "exclude" then table.insert(civAir.excludeAirfields, afName) + elseif dcsCommon.stringStartsWith(value, "depart") or dcsCommon.stringStartsWith(value, "start") then + table.insert(civAir.departOnly, afName) + elseif dcsCommon.stringStartsWith(value, "land") or dcsCommon.stringStartsWith(value, "arriv") then + table.insert(civAir.landingOnly, afName) else table.insert(civAir.trafficCenters, afName) -- note that adding the same twice makes it more likely to be picked end @@ -169,31 +176,40 @@ function civAir.getTwoAirbases() local fAB -- first airbase to depart local sAB -- second airbase to fly to - -- remove all currently excluded air bases from available - local filteredAB = civAir.filterAirfields(civAir.trafficCenters, civAir.excludeAirfields) + local departAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.departOnly) + -- remove all currently excluded air bases from departure + local filteredAB = civAir.filterAirfields(departAB, civAir.excludeAirfields) -- if none left, error if #filteredAB < 1 then - trigger.action.outText("+++civA: too few airfields") + trigger.action.outText("+++civA: too few departure airfields") return nil, nil end + -- now pick the departure airfield + fAB = dcsCommon.pickRandom(filteredAB) + + -- now generate list of landing airfields + local arriveAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.landingOnly) + -- remove all currently excluded air bases from arrival + filteredAB = civAir.filterAirfields(arriveAB, civAir.excludeAirfields) + -- if one left use it twice, boring flight. - if #filteredAB < 2 then - local fabName = filteredAB[1] - fAB = dcsCommon.getAirbasesWhoseNameContains(fabName, 0) - return fAB, fAB -- same twice + if #filteredAB < 1 then + trigger.action.outText("+++civA: too few arrival airfields") + return nil, nil end - -- pick any two that are not the same - fAB = dcsCommon.pickRandom(filteredAB) + -- pick any second that are not the same + local tries = 0 repeat - sAB = dcsCommon.pickRandom(filteredAB) - until fAB ~= sAB + sAB = dcsCommon.pickRandom(filteredAB) + tries = tries + 1 -- only try 10 times + until fAB ~= sAB or tries > 10 + fAB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0) sAB = dcsCommon.getFirstAirbaseWhoseNameContains(sAB, 0) - return fAB, sAB - + return fAB, sAB end function civAir.parkingIsFree(fromWP) @@ -433,6 +449,20 @@ function civAir.listTrafficCenters() for idx, aName in pairs(civAir.trafficCenters) do trigger.action.outText(aName, 30) end + + if #civAir.departOnly > 0 then + trigger.action.outText("Departure-Only:", 30) + for idx, aName in pairs(civAir.departOnly) do + trigger.action.outText(aName, 30) + end + end + + if #civAir.landingOnly > 0 then + trigger.action.outText("Arrival/Landing-Only:", 30) + for idx, aName in pairs(civAir.landingOnly) do + trigger.action.outText(aName, 30) + end + end end -- start @@ -449,7 +479,9 @@ function civAir.start() civAir.collectHubs() -- make sure there is something in trafficCenters - if #civAir.trafficCenters < 1 then + if (#civAir.trafficCenters + #civAir.departOnly < 1) or + (#civAir.trafficCenters + #civAir.landingOnly < 1) + then trigger.action.outText("+++civA: auto-populating", 30) -- simply add airfields on the map local allBases = dcsCommon.getAirbasesWhoseNameContains("*", 0) diff --git a/modules/cloneZone.lua b/modules/cloneZone.lua index d192642..651dfcf 100644 --- a/modules/cloneZone.lua +++ b/modules/cloneZone.lua @@ -1,5 +1,5 @@ cloneZones = {} -cloneZones.version = "1.4.2" +cloneZones.version = "1.4.4" cloneZones.verbose = false cloneZones.requiredLibs = { "dcsCommon", -- always @@ -40,6 +40,9 @@ cloneZones.uniqueCounter = 9200000 -- we start group numbering here 1.4.1 - trackWith: accepts list of trackers 1.4.2 - onstart delays for 0.1 s to prevent static stacking - turn bug for statics (bug in dcsCommon, resolved) + 1.4.3 - embark/disembark now works with cloners + 1.4.4 - removed some debugging verbosity + --]]-- @@ -406,6 +409,8 @@ end -- function cloneZones.resolveGroupID(gID, rawData, dataTable, reason) + if not reason then reason = "" end + local resolvedID = gID local myOName = rawData.CZorigName local groupName = cfxMX.groupNamesByID[gID] @@ -511,7 +516,55 @@ function cloneZones.resolveWPReferences(rawData, theZone, dataTable) end - -- resolve unit references in TASKS + -- resolve EMBARK/DISEMBARK groupd references + if taskData.id and taskData.params and taskData.params.groupsForEmbarking + then + -- build new groupsForEmbarking + local embarkers = taskData.params.groupsForEmbarking + local newEmbarkers = {} + for grpIdx, gID in pairs(embarkers) do + local resolvedID = cloneZones.resolveGroupID(gID, rawData, dataTable, "embark") + table.insert(newEmbarkers, resolvedID) + trigger.action.outText("+++clnZ: resolved embark group id <" .. gID .. "> to <" .. resolvedID .. ">", 30) + end + -- replace old with new table + taskData.params.groupsForEmbarking = newEmbarkers + end + + -- resolve DISTRIBUTION (embark) unit/group refs + if taskData.id and taskData.params and taskData.params.distribution then + local newDist = {} -- will replace old + for aUnit, aList in pairs(taskData.params.distribution) do + -- first, translate this unit's number + local newUnit = cloneZones.resolveUnitID(aUnit, rawData, dataTable, "transportID") + local embarkers = aList + local newEmbarkers = {} + for grpIdx, gID in pairs(embarkers) do + -- translate old to new + local resolvedID = cloneZones.resolveGroupID(gID, rawData, dataTable, "embark") + table.insert(newEmbarkers, resolvedID) + trigger.action.outText("+++clnZ: resolved distribute unit/group id <" .. aUnit .. "/" .. gID .. "> to <".. newUnit .. "/" .. resolvedID .. ">", 30) + end + -- store this as new group for + -- translated transportID + newDist[newUnit] = newEmbarkers + end + -- replace old distribution with new + taskData.params.distribution = newDist + trigger.action.outText("+++clnZ: rebuilt distribution", 30) + end + + -- resolve selectedTransport unit reference + if taskData.id and taskData.params and taskData.params.selectedTransportt then + local tID = taskData.params.selectedTransport + local newTID = cloneZones.resolveUnitID(tID, rawData, dataTable, "transportID") + taskData.params.selectedTransport = newTID + rigger.action.outText("+++clnZ: resolved selected transport <" .. tID .. "> to <" .. newTID .. ">", 30) + end + + -- note: we may need to process x and y as well + + -- 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 @@ -690,7 +743,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone) -- now use raw data to spawn and see if it works outabox --local theCat = cfxMX.catText2ID(cat) -- will be "static" - trigger.action.outText("static object proccing", 30) + -- trigger.action.outText("static object proccing", 30) rawData.x = rawData.x + zoneDelta.x rawData.y = rawData.y + zoneDelta.z -- !!! diff --git a/modules/dcsCommon.lua b/modules/dcsCommon.lua index 5218f08..d18d432 100644 --- a/modules/dcsCommon.lua +++ b/modules/dcsCommon.lua @@ -1,5 +1,5 @@ dcsCommon = {} -dcsCommon.version = "2.6.1" +dcsCommon.version = "2.6.2" --[[-- VERSION HISTORY 2.2.6 - compassPositionOfARelativeToB - clockPositionOfARelativeToB @@ -71,6 +71,7 @@ dcsCommon.version = "2.6.1" 2.5.9 - string2ObjectCat() 2.6.0 - unified uuid, removed uuIdent 2.6.1 - removed bug in rotateUnitData: cy --> cz param passing + 2.6.2 - new combineTables() --]]-- @@ -199,6 +200,17 @@ dcsCommon.version = "2.6.1" return array end + -- combine table. creates new + function dcsCommon.combineTables(inOne, inTwo) + local outTable = {} + for idx, element in pairs(inOne) do + table.insert(outTable, element) + end + for idx, element in pairs(inTwo) do + table.insert(outTable, element) + end + return outTable + end -- -- A I R F I E L D S A N D F A R P S -- diff --git a/modules/xFlags.lua b/modules/xFlags.lua index 29508b7..6342d38 100644 --- a/modules/xFlags.lua +++ b/modules/xFlags.lua @@ -1,5 +1,5 @@ xFlags = {} -xFlags.version = "1.2.1" +xFlags.version = "1.3.0" xFlags.verbose = false xFlags.hiVerbose = false xFlags.ups = 1 -- overwritten in get config when configZone is present @@ -26,6 +26,8 @@ xFlags.requiredLibs = { 1.2.2 - on/off/suspend commands - hiVerbose option - corrected bug in reset checksum + 1.3.0 - xCount! flag + - "never" operator --]]-- xFlags.xFlagZones = {} @@ -94,7 +96,9 @@ function xFlags.createXFlagsWithZone(theZone) theZone.xChange = cfxZones.getStringFromZoneProperty(theZone, "xChange!", "*") end - theZone.xDirect = cfxZones.getStringFromZoneProperty(theZone, "xDirect!", "*") + theZone.xDirect = cfxZones.getStringFromZoneProperty(theZone, "xDirect", "*") + + theZone.xCount = cfxZones.getStringFromZoneProperty(theZone, "xCount", "*") theZone.inspect = cfxZones.getStringFromZoneProperty(theZone, "require", "or") -- same as any -- supported any/or, all/and, moreThan, atLeast, exactly @@ -297,6 +301,7 @@ function xFlags.evaluateZone(theZone) local hits, checkSum = xFlags.evaluateFlags(theZone) -- depending on inspect see what the outcome is -- supported any/or, all/and, moreThan, atLeast, exactly + -- if require = "never", we never trigger local op = theZone.inspect local evalResult = false if (op == "or" or op == "any" or op == "some") then @@ -327,6 +332,9 @@ function xFlags.evaluateZone(theZone) -- warning: 'half' means really 'at least half" evalResult = true end + + elseif op == "never" then + evalResult = false -- not required, just to be explicit else trigger.action.outText("+++xFlg: WARNING: <" .. theZone.name .. "> has unknown requirement: <" .. op .. ">", 30) end @@ -353,7 +361,7 @@ function xFlags.evaluateZone(theZone) end -- now directly set the value of evalResult (0 = false, 1 = true) - -- to "xDirect!". Always sets output to current result of evaluation + -- to "xDirect". Always sets output to current result of evaluation -- true (1)/false(0), no matter if changed or not if evalResult then @@ -362,6 +370,9 @@ function xFlags.evaluateZone(theZone) cfxZones.setFlagValueMult(theZone.xDirect, 0, theZone) end + -- directly set the xCount flag + cfxZones.setFlagValueMult(theZone.xCount, hits, theZone) + -- now see if we bang the output according to method if evalResult then if xFlags.verbose or theZone.verbose then diff --git a/tutorial & demo missions/demo - Count Bases Blue.miz b/tutorial & demo missions/demo - Count Bases Blue.miz new file mode 100644 index 0000000..49d05ea Binary files /dev/null and b/tutorial & demo missions/demo - Count Bases Blue.miz differ diff --git a/tutorial & demo missions/demo - base captured.miz b/tutorial & demo missions/demo - base captured.miz index a32f48a..9b16d17 100644 Binary files a/tutorial & demo missions/demo - base captured.miz and b/tutorial & demo missions/demo - base captured.miz differ diff --git a/tutorial & demo missions/demo - one-way air.miz b/tutorial & demo missions/demo - one-way air.miz new file mode 100644 index 0000000..5f28a3d Binary files /dev/null and b/tutorial & demo missions/demo - one-way air.miz differ diff --git a/tutorial & demo missions/microskel.lua b/tutorial & demo missions/microskel.lua new file mode 100644 index 0000000..9b9147f --- /dev/null +++ b/tutorial & demo missions/microskel.lua @@ -0,0 +1,13 @@ +skel = {} +function skel:onEvent(event) -- event handler +end + +function skel.update() + -- schedule next update invocation + timer.scheduleFunction(skel.update, {}, timer.getTime() + 1) + -- your own stuff and checks here + trigger.action.outText("DCS, this is Lua. Hello. Lua.", 30) +end + +world.addEventHandler(skel) -- connect event hander +skel.update() -- start update cycle