Version 1.4.4

stopGap refresh
interpreted wildcards
unitZone "*" match all
This commit is contained in:
Christian Franz 2023-09-21 15:48:56 +02:00
parent 0f1e814d22
commit d1d4af63a0
8 changed files with 360 additions and 143 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxZones = {} cfxZones = {}
cfxZones.version = "4.0.3" cfxZones.version = "4.0.5"
-- cf/x zone management module -- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable -- reads dcs zones and makes them accessible and mutable
@ -153,6 +153,10 @@ cfxZones.version = "4.0.3"
- 4.0.2 - removed verbosity from declutterZone (both versions) - 4.0.2 - removed verbosity from declutterZone (both versions)
- 4.0.3 - new processDynamicVZU() - 4.0.3 - new processDynamicVZU()
- wildcard uses processDynamicVZU - wildcard uses processDynamicVZU
- 4.0.4 - setFlagValue now supports multiple flags (OOP and classic)
- doSetFlagValue optimizations
- 4.0.5 - dynamicAB wildcard
- processDynamicValueVU
--]]-- --]]--
@ -1781,6 +1785,14 @@ function cfxZones.expandFlagName(theFlag, theZone)
return theFlag return theFlag
end end
function dmlZone:setFlagValue(theFlag, theValue)
cfxZones.setFlagValueMult(theFlag, theValue, self)
end
function cfxZones.setFlagValue(theFlag, theValue, theZone)
cfxZones.setFlagValueMult(theFlag, theValue, theZone)
end
function cfxZones.setFlagValueMult(theFlag, theValue, theZone) function cfxZones.setFlagValueMult(theFlag, theValue, theZone)
local allFlags = {} local allFlags = {}
if dcsCommon.containsString(theFlag, ",") then if dcsCommon.containsString(theFlag, ",") then
@ -1796,11 +1808,11 @@ function cfxZones.setFlagValueMult(theFlag, theValue, theZone)
aFlag = dcsCommon.trim(aFlag) aFlag = dcsCommon.trim(aFlag)
-- note: mey require range preprocessing, but that's not -- note: mey require range preprocessing, but that's not
-- a priority -- a priority
cfxZones.setFlagValue(aFlag, theValue, theZone) cfxZones.doSetFlagValue(aFlag, theValue, theZone)
end end
end end
function cfxZones.setFlagValue(theFlag, theValue, theZone) function cfxZones.doSetFlagValue(theFlag, theValue, theZone)
local zoneName = "<dummy>" local zoneName = "<dummy>"
if not theZone then if not theZone then
trigger.action.outText("+++Zne: no zone on setFlagValue", 30) -- mod me for detector trigger.action.outText("+++Zne: no zone on setFlagValue", 30) -- mod me for detector
@ -1809,19 +1821,13 @@ function cfxZones.setFlagValue(theFlag, theValue, theZone)
end end
if type(theFlag) == "number" then if type(theFlag) == "number" then
-- straight set, ME flag -- straight set, oldschool ME flag
trigger.action.setUserFlag(theFlag, theValue) trigger.action.setUserFlag(theFlag, theValue)
return return
end end
-- we assume it's a string now -- we assume it's a string now
theFlag = dcsCommon.trim(theFlag) -- clear leading/trailing spaces theFlag = dcsCommon.trim(theFlag) -- clear leading/trailing spaces
local nFlag = tonumber(theFlag)
if nFlag then
trigger.action.setUserFlag(theFlag, theValue)
return
end
-- some QoL: detect "<none>" -- some QoL: detect "<none>"
if dcsCommon.containsString(theFlag, "<none>") then if dcsCommon.containsString(theFlag, "<none>") then
trigger.action.outText("+++Zone: warning - setFlag has '<none>' flag name in zone <" .. zoneName .. ">", 30) -- if error, intended break trigger.action.outText("+++Zone: warning - setFlag has '<none>' flag name in zone <" .. zoneName .. ">", 30) -- if error, intended break
@ -1834,9 +1840,6 @@ function cfxZones.setFlagValue(theFlag, theValue, theZone)
trigger.action.setUserFlag(theFlag, theValue) trigger.action.setUserFlag(theFlag, theValue)
end end
function dmlZone:setFlagValue(theFlag, theValue)
cfxZones.setFlagValue(theFlag, theValue, self)
end
function cfxZones.getFlagValue(theFlag, theZone) function cfxZones.getFlagValue(theFlag, theZone)
@ -3110,16 +3113,16 @@ local locales = {"coa",}
local outMsg = inMsg local outMsg = inMsg
local uHead = 0 local uHead = 0
for idx, aLocale in pairs(locales) do for idx, aLocale in pairs(locales) do
local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>" local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>" -- e.g. "<coa: flag Name>
repeat -- iterate all patterns one by one repeat -- iterate all patterns one by one
local startLoc, endLoc = string.find(outMsg, pattern) local startLoc, endLoc = string.find(outMsg, pattern)
if startLoc then if startLoc then
local theValParam = string.sub(outMsg, startLoc, endLoc) local theValParam = string.sub(outMsg, startLoc, endLoc)
-- strip lead and trailer -- strip lead and trailer
local param = string.gsub(theValParam, "<" .. aLocale .. ":%s*", "") local param = string.gsub(theValParam, "<" .. aLocale .. ":%s*", "") -- remove "<coa:"
param = string.gsub(param, ">","") param = string.gsub(param, ">","") -- remove trailing ">"
-- find zone or unit -- find zone or unit
param = dcsCommon.trim(param) param = dcsCommon.trim(param) -- param = "flag Name"
local tZone = cfxZones.getZoneByName(param) local tZone = cfxZones.getZoneByName(param)
local tUnit = Unit.getByName(param) local tUnit = Unit.getByName(param)
@ -3127,7 +3130,7 @@ local locales = {"coa",}
if aLocale == "coa" then if aLocale == "coa" then
coa = trigger.misc.getUserFlag(param) coa = trigger.misc.getUserFlag(param)
if tZone then coa = tZone.owner end if tZone then coa = tZone.owner end
if zUnit then coa = tUnit:getCoalition() end if tUnit and Unit:isExist(tUnit) then coa = tUnit:getCoalition() end
locString = dcsCommon.coalition2Text(coa) locString = dcsCommon.coalition2Text(coa)
end end
@ -3138,6 +3141,83 @@ local locales = {"coa",}
return outMsg return outMsg
end end
-- process two-value vars that can be flag or unit and return interpreted value
-- i.e. <alive: Aerial-1-1>
function cfxZones.processDynamicValueVU(inMsg)
local locales = {"yes", "true", "alive", "in"}
local outMsg = inMsg
local uHead = 0
for idx, aLocale in pairs(locales) do
local pattern = "<" .. aLocale .. ":%s*[%s%w%*%d%.%-_]+>" -- e.g. "<yes: flagOrUnitName>
repeat -- iterate all patterns one by one
local startLoc, endLoc = string.find(outMsg, pattern)
if startLoc then
local theValParam = string.sub(outMsg, startLoc, endLoc)
-- strip lead and trailer
local param = string.gsub(theValParam, "<" .. aLocale .. ":%s*", "") -- remove "<alive:"
param = string.gsub(param, ">","") -- remove trailing ">"
-- find zone or unit
param = dcsCommon.trim(param) -- param = "flagOrUnitName"
local tUnit = Unit.getByName(param)
local yesNo = trigger.misc.getUserFlag(param) ~= 0
if tUnit then yesNo = Unit.isExist(tUnit) end
local locString = "err"
if aLocale == "yes" then
if yesNo then locString = "yes" else locString = "no" end
elseif aLocale == "true" then
if yesNo then locString = "true" else locString = "false" end
elseif aLocale == "alive" then
if yesNo then locString = "alive" else locString = "dead" end
elseif aLocale == "in" then
if yesNo then locString = "in" else locString = "out" end
end
outMsg = string.gsub(outMsg, pattern, locString, 1) -- only one sub!
end -- if startloc
until not startLoc
end -- for all locales
return outMsg
end
function cfxZones.processDynamicAB(inMsg, locale)
local outMsg = inMsg
if not locale then locale = "A/B" end
-- <A/B: flagOrUnitName [val A | val B]>
local replacerValPattern = "<".. locale .. ":%s*[%s%w%*%d%.%-_]+" .. "%[[%s%w]+|[%s%w]+%]"..">"
repeat
local startLoc, endLoc = string.find(outMsg, replacerValPattern)
if startLoc then
local rp = string.sub(outMsg, startLoc, endLoc)
-- get val/unit name
local valA, valB = string.find(rp, ":%s*[%s%w%*%d%.%-_]+%[")
local val = string.sub(rp, valA+1, valB-1)
val = dcsCommon.trim(val)
-- get left and right
local leftA, leftB = string.find(rp, "%[[%s%w]+|" ) -- from "[" to "|"
local rightA, rightB = string.find(rp, "|[%s%w]+%]") -- from "|" to "]"
left = string.sub(rp, leftA+1, leftB-1)
left = dcsCommon.trim(left)
right = string.sub(rp, rightA+1, rightB-1)
right = dcsCommon.trim(right)
-- trigger.action.outText("+++replacer pattern <" .. rp .. "> found, val = <" .. val .. ">, A = <" .. left .. ">, B = <" .. right .. ">", 30)
local yesno = false
-- see if unit exists
local theUnit = Unit.getByName(val)
if theUnit then
yesno = Unit:isExist(theUnit)
else
yesno = trigger.misc.getUserFlag(val) ~= 0
end
local locString = left
if yesno then locString = right end
outMsg = string.gsub(outMsg, replacerValPattern, locString, 1)
end
until not startLoc
return outMsg
end
function cfxZones.rspMapper360(directionInDegrees, numResponses) function cfxZones.rspMapper360(directionInDegrees, numResponses)
-- maps responses around a clock. Clock has 12 'responses' (12, 1, .., 11), -- maps responses around a clock. Clock has 12 'responses' (12, 1, .., 11),
-- with the first (12) also mapping to the last half arc -- with the first (12) also mapping to the last half arc
@ -3187,6 +3267,8 @@ function cfxZones.processStringWildcards(inMsg, theZone, timeFormat, imperialUni
theMsg = cfxZones.processDynamicLoc(theMsg, imperialUnits, responses) theMsg = cfxZones.processDynamicLoc(theMsg, imperialUnits, responses)
-- process values that can be derived from flag (default), zone or unit -- process values that can be derived from flag (default), zone or unit
theMsg = cfxZones.processDynamicVZU(theMsg) theMsg = cfxZones.processDynamicVZU(theMsg)
theMsg = cfxZones.processDynamicAB(theMsg)
theMsg = cfxZones.processDynamicValueVU(theMsg)
return theMsg return theMsg
end end

View File

@ -1,5 +1,5 @@
duel = {} duel = {}
duel.version = "1.0.2" duel.version = "1.1.0"
duel.verbose = false duel.verbose = false
duel.requiredLibs = { duel.requiredLibs = {
"dcsCommon", "dcsCommon",
@ -11,7 +11,9 @@ duel.requiredLibs = {
1.0.0 - Initial Version 1.0.0 - Initial Version
1.0.1 - verbosity bug with SSB removed 1.0.1 - verbosity bug with SSB removed
1.0.2 - units are reserved for player when they disappear 1.0.2 - units are reserved for player when they disappear
1.1.0 - maxRed and maxBlue per zone to be able to create
1v1, 2v2, XvY duel zones
--]]-- --]]--
--[[-- --[[--
@ -25,8 +27,6 @@ duel.requiredLibs = {
duel.duelZones = {} duel.duelZones = {}
duel.activePlayers = {} -- by player name duel.activePlayers = {} -- by player name
--duel.activeUnits = {} -- as above, by unit name
--duel.missingPlayers = {}
duel.allDuelists = {} -- all potential dualists as collected from zones duel.allDuelists = {} -- all potential dualists as collected from zones
-- --
-- reading attributes -- reading attributes
@ -49,8 +49,8 @@ function duel.createDuelZone(theZone)
local groupData = cfxMX.playerUnit2Group[unitName] local groupData = cfxMX.playerUnit2Group[unitName]
duelist.groupName = groupData.name duelist.groupName = groupData.name
duelist.coa = cfxMX.groupCoalitionByName[duelist.groupName] duelist.coa = cfxMX.groupCoalitionByName[duelist.groupName]
if duel.verbose then if duel.verbose or theZone.verbose then
-- trigger.action.outText("Detected player unit <" .. duelist.name .. ">, type <" .. duelist.type .. "> of group <" .. duelist.groupName .. "> of coa <" .. duelist.coa .. "> in zone <" .. theZone.name .. "> as duelist", 30) trigger.action.outText("Detected player unit <" .. duelist.name .. ">, type <" .. duelist.type .. "> of group <" .. duelist.groupName .. "> of coa <" .. duelist.coa .. "> in zone <" .. theZone.name .. "> as duelist", 30)
end end
duelist.active = false duelist.active = false
@ -60,14 +60,13 @@ function duel.createDuelZone(theZone)
-- enter into global table -- enter into global table
-- player can only be in at maximum one duelist zones -- player can only be in at maximum one duelist zones
if duel.allDuelists[unitName] then if duel.allDuelists[unitName] then
trigger.action.outText("+++WARNING: overlapping duelists! Overwriting previous data", 30) trigger.action.outText("+++WARNING: overlapping duelists for zone <" .. theZone.name .. ">! Overwriting previous data", 30)
end end
duel.allDuelists[unitName] = duelist duel.allDuelists[unitName] = duelist
theZone.duelists[unitName] = duelist theZone.duelists[unitName] = duelist
end end
end end
theZone.state = "waiting" -- FSM, init to waiting state
theZone.duelTriggerMethod = theZone:getStringFromZoneProperty("duelTriggerMethod", "change") theZone.duelTriggerMethod = theZone:getStringFromZoneProperty("duelTriggerMethod", "change")
if theZone:hasProperty("on?") then if theZone:hasProperty("on?") then
theZone.duelOnFlag = theZone:getStringFromZoneProperty("on?", "*none") theZone.duelOnFlag = theZone:getStringFromZoneProperty("on?", "*none")
@ -83,6 +82,8 @@ function duel.createDuelZone(theZone)
theZone.active = false theZone.active = false
end end
theZone.maxRed = theZone:getNumberFromZoneProperty("maxRed", 1)
theZone.maxBlue = theZone:getNumberFromZoneProperty("maxBlue", 1)
end end
-- --
@ -102,12 +103,48 @@ function duel.closeSlotsForZoneAndCoaExceptGroupNamed(theZone, coa, groupName)
end end
end end
function duel.closeSlotsForZoneAndCoaExceptActive(theZone, coa)
-- iterate this zone's duelist groups and tell SSB to close them now
local allDuelists = theZone.duelists
for unitName, theDuelist in pairs(allDuelists) do
local theUnit = Unit.getByName(unitName)
if theUnit and Unit.isExist(theUnit) then
-- is unit exists already, do not close down
if theZone.verbose or duel.verbose then
trigger.action.outText("+++duel: leaving unit <" .. unitName .. "> in game", 30)
end
else
-- this unit is not live, close group down
local dgName = theDuelist.groupName
if (theDuelist.coa == coa) and (dgName ~= groupName) then
if duel.verbose or theZone.verbose then
trigger.action.outText("+++duel: closing SSB slot for group <" .. dgName .. ">, coa <" .. theDuelist.coa .. ">", 30)
end
trigger.action.setUserFlag(dgName,100) -- anything but 0 means closed
end
end
end
end
function duel.countActiveUnitsForCoaInZone(theZone, coa)
local allDuelists = theZone.duelists
local activeCount = 0
for unitName, theDuelist in pairs(allDuelists) do
if theDuelist.coa == coa then
local theUnit = Unit.getByName(unitName)
if theUnit and Unit.isExist(theUnit) then
activeCount = activeCount + 1
end
end
end
return activeCount
end
function duel.openSlotsForZoneAndCoa(theZone, coa) function duel.openSlotsForZoneAndCoa(theZone, coa)
local allDuelists = theZone.duelists local allDuelists = theZone.duelists
for unitName, theDuelist in pairs(allDuelists) do for unitName, theDuelist in pairs(allDuelists) do
if (theDuelist.coa == coa) then if (theDuelist.coa == coa) then
if duel.verbose then if duel.verbose or theZone.verbose then
trigger.action.outText("+++duel: opening SSB slot for group <" .. theDuelist.groupName .. ">, coa <" .. theDuelist.coa .. ">", 30) trigger.action.outText("+++duel: opening SSB slot for group <" .. theDuelist.groupName .. ">, coa <" .. theDuelist.coa .. ">", 30)
end end
trigger.action.setUserFlag(theDuelist.groupName, 0) -- 0 means OPEN trigger.action.setUserFlag(theDuelist.groupName, 0) -- 0 means OPEN
@ -117,28 +154,30 @@ end
function duel.checkReopenSlotsForZoneAndCoa(theZone, coa) function duel.checkReopenSlotsForZoneAndCoa(theZone, coa)
-- test if one side can reopen all slots to enter the duel -- test if one side can reopen all slots to enter the duel
-- if so, will reset FSM for zone --
local maxForCoa = theZone.maxRed
if coa == 2 then maxForCoa = theZone.maxBlue end
local allDuelists = theZone.duelists local allDuelists = theZone.duelists
local allUnengaged = true local canReopen = true
local engageCount = 0
for unitName, theDuelist in pairs(allDuelists) do for unitName, theDuelist in pairs(allDuelists) do
if (theDuelist.coa == coa) then if (theDuelist.coa == coa) then
local theUnit = Unit.getByName(unitName) local theUnit = Unit.getByName(unitName)
if theUnit and Unit.isExist(theUnit) then if theUnit and Unit.isExist(theUnit) then
-- unit is still alive on this side, can't reopen -- unit is still alive on this side
allUnengaged = false engageCount = engageCount + 1
end end
end end
end end
if engageCount < maxForCoa then canReopen = true end
if allUnengaged then if canReopen then
if duel.verbose then if duel.verbose then
trigger.action.outText("+++duel: will open all slots for <" .. theZone:getName() .. ">, coa <" .. coa .. ">", 30) trigger.action.outText("+++duel: will open all slots for <" .. theZone:getName() .. ">, coa <" .. coa .. ">", 30)
end end
duel.openSlotsForZoneAndCoa(theZone, coa) duel.openSlotsForZoneAndCoa(theZone, coa)
theZone.state = "waiting"
else else
if duel.verbose then if duel.verbose then
trigger.action.outText("+++duel: unable to reopenslots for <" .. theZone:getName() .. ">, coa <" .. coa .. ">, still engaged", 30) trigger.action.outText("+++duel: unable to reopenslots for <" .. theZone:getName() .. ">, coa <" .. coa .. ">, " .. engageCount .. " units are still engaged", 30)
end end
end end
end end
@ -149,6 +188,10 @@ function duel.duelistEnteredArena(theUnit, theDuelist)
theDuelist.active = true theDuelist.active = true
local player = theUnit:getPlayerName() local player = theUnit:getPlayerName()
if not player then
trigger.action.outText("+++Duel: WARNING: no player name for unit <" .. theUnit:getName() .. "> upon enter arena", 30)
return
end
local unitName = theUnit:getName() local unitName = theUnit:getName()
local groupName = theDuelist.groupName local groupName = theDuelist.groupName
local theZone = theDuelist.zone --duel.duelZones[theDuelist.arena] local theZone = theDuelist.zone --duel.duelZones[theDuelist.arena]
@ -187,11 +230,22 @@ function duel.duelistEnteredArena(theUnit, theDuelist)
duel.activePlayers[player] = playerData duel.activePlayers[player] = playerData
-- close all slots for this zone and coalition if it is active -- close all slots for this zone and coalition if it is active
if theZone.active then -- and we have reched the maximum of players for that coalition
if theZone.verbose or duel.verbose then local maxForCoa = theZone.maxRed
trigger.action.outText("+++duel: zone <" .. theZone:getName() .. ">, closing coa <" .. coa .. "> slots except for player's <" .. player .. "> group <" .. groupName .. ">", 30) if coa == 2 then maxForCoa = theZone.maxBlue end
local activeInZone = duel.countActiveUnitsForCoaInZone(theZone, coa)
if theZone.active then
if(activeInZone >= maxForCoa) then
if theZone.verbose or duel.verbose then
trigger.action.outText("+++duel: zone <" .. theZone:getName() .. ">, closing coa <" .. coa .. "> slots except for player's <" .. player .. "> group <" .. groupName .. ">", 30)
end
--duel.closeSlotsForZoneAndCoaExceptGroupNamed(theZone, coa, groupName)
duel.closeSlotsForZoneAndCoaExceptActive(theZone, coa)
else
if duel.verbose or theZone.verbose then
trigger.action.outText("Zone <" .. theZone.name .. "> Coa <" .. coa .. "> remains open, have <" .. activeInZone .. "> participants, max is <" .. maxForCoa .. ">", 30)
end
end end
duel.closeSlotsForZoneAndCoaExceptGroupNamed(theZone, coa, groupName)
else else
if theZone.verbose or duel.verbose then if theZone.verbose or duel.verbose then
trigger.action.outText("+++duel: zone <" .. theZone:getName() .. "> currently not active, not closing slots", 30) trigger.action.outText("+++duel: zone <" .. theZone:getName() .. "> currently not active, not closing slots", 30)
@ -234,30 +288,7 @@ function duel.update()
-- call me in a second to poll triggers -- call me in a second to poll triggers
timer.scheduleFunction(duel.update, {}, timer.getTime() + 1/duel.ups) timer.scheduleFunction(duel.update, {}, timer.getTime() + 1/duel.ups)
-- find units that have disappeared, and react accordingly -- check active players and their units
--[[--
for unitName, theDuelist in pairs (duel.allDuelists) do
local theZone = theDuelist.zone
if theDuelist.active then
-- trigger.action.outText("+++duel: unit <" .. unitName .. "> is active in zone <" .. theZone:getName() .. ">, controlled by <" .. theDuelist.playerName .. ">", 30)
local theUnit = Unit.getByName(unitName)
if theUnit and Unit.isExist(theUnit) then
-- all is well
else
if duel.verbose then
trigger.action.outText("+++duel: unit <" .. unitName .. "> controlled by <" .. theDuelist.playerName .. "> has disappeared, starting cleanup", 30)
end
theDuelist.playerName = nil
theDuelist.active = false
duel.checkReopenSlotsForZoneAndCoa(theZone, theDuelist.coa)
end
end
end
--]]--
-- now check the active players and their units
local now = timer.getTime() local now = timer.getTime()
local filtered = {} local filtered = {}
for playerName, playerData in pairs(duel.activePlayers) do for playerName, playerData in pairs(duel.activePlayers) do

View File

@ -1,10 +1,12 @@
stopGap = {} stopGap = {}
stopGap.version = "1.0.6 STANDALONE" stopGap.version = "1.0.9 STANDALONE"
stopGap.verbose = false stopGap.verbose = false
stopGap.ssbEnabled = true stopGap.ssbEnabled = true
stopGap.ignoreMe = "-sg" stopGap.ignoreMe = "-sg"
stopGap.spIgnore = "-sp" -- only single-player ignored stopGap.spIgnore = "-sp" -- only single-player ignored
stopGap.isMP = false stopGap.isMP = false
stopGap.running = true
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
--[[-- --[[--
Written and (c) 2023 by Christian Franz Written and (c) 2023 by Christian Franz
@ -29,6 +31,9 @@ stopGap.isMP = false
1.0.5 - (DML-only additions) 1.0.5 - (DML-only additions)
1.0.6 - can detect stopGapGUI active on server 1.0.6 - can detect stopGapGUI active on server
- supports "-sp" for single-player only suppress - supports "-sp" for single-player only suppress
1.0.7 - (DML-only internal cool stuff)
1.0.8 - added refreshInterval option as requested
1.0.9 - optimization when turning on stopgap
--]]-- --]]--
stopGap.standInGroups ={} stopGap.standInGroups ={}
@ -175,7 +180,7 @@ end
function stopGap.initGaps() function stopGap.initGaps()
-- when we enter, all slots are emptry -- when we enter, all slots are emptry
-- and we populate all slots -- and we populate all empty slots
-- with their static representations -- with their static representations
for name, group in pairs (cfxMX.playerGroupByName) do for name, group in pairs (cfxMX.playerGroupByName) do
-- check to see if this group is on the ground at parking -- check to see if this group is on the ground at parking
@ -194,13 +199,11 @@ function stopGap.initGaps()
end end
else else
-- replace all groups entirely with static objects -- replace all groups entirely with static objects
---local allUnits = group.units
local theStaticGroup = stopGap.createStandInsForMXGroup(group) local theStaticGroup = stopGap.createStandInsForMXGroup(group)
-- remember this static group by its real name -- remember this static group by its real name
stopGap.standInGroups[group.name] = theStaticGroup stopGap.standInGroups[group.name] = theStaticGroup
end end
end -- if groundtstart end -- if groundtstart
end end
end end
@ -212,13 +215,29 @@ function stopGap.turnOff()
end end
end end
stopGap.standInGroups = {} stopGap.standInGroups = {}
stopGap.running = false
end end
function stopGap.turnOn() function stopGap.turnOn()
-- populate all empty (non-taken) slots with stand-ins -- populate all empty (un-occupied) slots with stand-ins
stopGap.initGaps() stopGap.initGaps()
stopGap.running = true
end end
function stopGap.refreshAll() -- restore all statics
if stopGap.refreshInterval > 0 then
-- re-schedule invocation
timer.scheduleFunction(stopGap.refreshAll, {}, timer.getTime() + stopGap.refreshInterval)
if stopGap.running then
stopGap.turnOff() -- kill all statics
-- turn back on in half a second
timer.scheduleFunction(stopGap.turnOn, {}, timer.getTime() + 0.5)
end
if stopGap.verbose then
trigger.action.outText("+++stopG: refreshing all static", 30)
end
end
end
-- --
-- event handling -- event handling
-- --
@ -271,6 +290,7 @@ function stopGap.update()
stopGap.turnOff() stopGap.turnOff()
stopGap.isMP = true stopGap.isMP = true
stopGap.turnOn() stopGap.turnOn()
return
end end
end end
@ -349,9 +369,14 @@ function stopGap.start()
-- connect event handler -- connect event handler
world.addEventHandler(stopGap) world.addEventHandler(stopGap)
-- start update in 10 seconds -- start update in 1 second
timer.scheduleFunction(stopGap.update, {}, timer.getTime() + 1) timer.scheduleFunction(stopGap.update, {}, timer.getTime() + 1)
-- start refresh cycle if refresh (>0)
if stopGap.refreshInterval > 0 then
timer.scheduleFunction(stopGap.refreshAll, {}, timer.getTime() + stopGap.refreshInterval)
end
-- say hi! -- say hi!
local mp = " (SP - <" .. sgDetect .. ">)" local mp = " (SP - <" .. sgDetect .. ">)"
if sgDetect > 0 then mp = " -- MP GUI Detected (" .. sgDetect .. ")!" end if sgDetect > 0 then mp = " -- MP GUI Detected (" .. sgDetect .. ")!" end

View File

@ -1,10 +1,13 @@
stopGap = {} stopGap = {}
stopGap.version = "1.0.7" stopGap.version = "1.0.8"
stopGap.verbose = false stopGap.verbose = false
stopGap.ssbEnabled = true stopGap.ssbEnabled = true
stopGap.ignoreMe = "-sg" stopGap.ignoreMe = "-sg"
stopGap.spIgnore = "-sp" -- only single-player ignored stopGap.spIgnore = "-sp" -- only single-player ignored
stopGap.isMP = false stopGap.isMP = false
stopGap.running = true
stopGap.refreshInterval = -1 -- seconds to refresh all statics. -1 = never, 3600 = once every hour
stopGap.requiredLibs = { stopGap.requiredLibs = {
"dcsCommon", "dcsCommon",
@ -42,6 +45,10 @@ stopGap.requiredLibs = {
1.0.6 - spIgnore '-sp' 1.0.6 - spIgnore '-sp'
1.0.7 - migrated to OOP zones 1.0.7 - migrated to OOP zones
- corrected ssbEnabled config from sbb to ssb - corrected ssbEnabled config from sbb to ssb
1.0.8 - added refreshInterval option as requested
- refresh attribute config zone
1.0.9 - in line with standalone (optimization not required for DML)
--]]-- --]]--
stopGap.standInGroups = {} stopGap.standInGroups = {}
@ -187,11 +194,28 @@ function stopGap.turnOff()
end end
end end
stopGap.standInGroups = {} stopGap.standInGroups = {}
stopGap.running = false
end end
function stopGap.turnOn() function stopGap.turnOn()
-- populate all empty (non-taken) slots with stand-ins -- populate all empty (non-taken) slots with stand-ins
stopGap.initGaps() stopGap.initGaps()
stopGap.running = true
end
function stopGap.refreshAll() -- restore all statics
if stopGap.refreshInterval > 0 then
-- re-schedule invocation
timer.scheduleFunction(stopGap.refreshAll, {}, timer.getTime() + stopGap.refreshInterval)
if stopGap.running then
stopGap.turnOff() -- kill all statics
-- turn back on in half a second
timer.scheduleFunction(stopGap.turnOn, {}, timer.getTime() + 0.5)
end
if stopGap.verbose then
trigger.action.outText("+++stopG: refreshing all static", 30)
end
end
end end
-- --
-- event handling -- event handling
@ -366,6 +390,8 @@ function stopGap.readConfigZone(theZone)
trigger.action.outText("+++StopG: turned off", 30) trigger.action.outText("+++StopG: turned off", 30)
end end
end end
stopGap.refreshInterval = theZone:getNumberFromZoneProperty("refresh", -1) -- default: no refresh
end end
-- --
@ -407,9 +433,14 @@ function stopGap.start()
-- connect event handler -- connect event handler
world.addEventHandler(stopGap) world.addEventHandler(stopGap)
-- start update in 10 seconds -- start update in 1 second
timer.scheduleFunction(stopGap.update, {}, timer.getTime() + 1) timer.scheduleFunction(stopGap.update, {}, timer.getTime() + 1)
-- start refresh cycle if refresh (>0)
if stopGap.refreshInterval > 0 then
timer.scheduleFunction(stopGap.refreshAll, {}, timer.getTime() + stopGap.refreshInterval)
end
-- say hi! -- say hi!
local mp = " (SP - <" .. sgDetect .. ">)" local mp = " (SP - <" .. sgDetect .. ">)"
if sgDetect > 0 then mp = " -- MP GUI Detected (" .. sgDetect .. ")!" end if sgDetect > 0 then mp = " -- MP GUI Detected (" .. sgDetect .. ")!" end

View File

@ -1,5 +1,5 @@
unitZone={} unitZone={}
unitZone.version = "1.2.5" unitZone.version = "2.0.0"
unitZone.verbose = false unitZone.verbose = false
unitZone.ups = 1 unitZone.ups = 1
unitZone.requiredLibs = { unitZone.requiredLibs = {
@ -18,7 +18,15 @@ unitZone.requiredLibs = {
- better guards for uzOn? and uzOff? - better guards for uzOn? and uzOff?
1.2.4 - more verbosity on uzDirect 1.2.4 - more verbosity on uzDirect
1.2.5 - reading config improvement 1.2.5 - reading config improvement
2.0.0 - matchAll option (internal, automatic look for "*" in names)
- lookFor defaults to "*"
- OOP dmlZones
- uzDirect correctly initialized at start
- synonyms uzDirect#, uzDirectInv#
- uzDirectInv better support
- unitZone now used to define the coalition, coalition DEPRECATED
- filter synonym
- direct#, directInv# synonyms
--]]-- --]]--
unitZone.unitZones = {} unitZone.unitZones = {}
@ -63,81 +71,117 @@ end
function unitZone.createUnitZone(theZone) function unitZone.createUnitZone(theZone)
-- start val - a range -- start val - a range
theZone.lookFor = cfxZones.getStringFromZoneProperty(theZone, "lookFor", "cfx no unit supplied") theZone.lookFor = theZone:getStringFromZoneProperty("lookFor", "*") -- default to match all
if dcsCommon.stringEndsWith(theZone.lookFor, "*") then if theZone.lookFor == "*" then
theZone.lookForBeginsWith = true theZone.matchAll = true
if theZone.verbose or unitZone.verbose then
trigger.action.outText("+++uZne: zone <" .. theZone.name .. "> set up to matche all names", 30)
end
elseif dcsCommon.stringEndsWith(theZone.lookFor, "*") then
theZone.lookForBeginsWith = true
theZone.matchAll = false
theZone.lookFor = dcsCommon.removeEnding(theZone.lookFor, "*") theZone.lookFor = dcsCommon.removeEnding(theZone.lookFor, "*")
end end
theZone.matching = cfxZones.getStringFromZoneProperty(theZone, "matching", "group") -- group, player [, name, type] theZone.matching = theZone:getStringFromZoneProperty("matching", "group") -- group, player [, name, type]
theZone.matching = dcsCommon.trim(theZone.matching:lower()) theZone.matching = dcsCommon.trim(theZone.matching:lower())
if theZone.matching == "groups" then theZone.matching = "group" end -- some simplification if theZone.matching == "groups" then theZone.matching = "group" end -- some simplification
if theZone.matching == "players" then theZone.matching = "player" end -- some simplification if theZone.matching == "players" then theZone.matching = "player" end -- some simplification
-- coalition -- coalition
theZone.uzCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0) -- 0 = all theZone.uzCoalition = theZone:getCoalitionFromZoneProperty("unitZone", 0) -- now with main attribute
if cfxZones.hasProperty(theZone, "uzCoalition") then -- DEPRECATED 2023 SEPT: provided for legacy compatibility
theZone.uzCoalition = cfxZones.getCoalitionFromZoneProperty(theZone, "uzCoalition", 0) if theZone:hasProperty("coalition") then
theZone.uzCoalition = theZone:getCoalitionFromZoneProperty("coalition", 0) -- 0 = all
elseif theZone:hasProperty("uzCoalition") then
theZone.uzCoalition = theZone:getCoalitionFromZoneProperty("uzCoalition", 0)
end end
if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: set coa " .. theZone.uzCoalition .. " for <" .. theZone.name .. ">", 30)
end
-- DML Method -- DML Method
theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") theZone.uzMethod = theZone:getStringFromZoneProperty("method", "inc")
if cfxZones.hasProperty(theZone, "uzMethod") then if theZone:hasProperty("uzMethod") then
theZone.uzMethod = cfxZones.getStringFromZoneProperty(theZone, "uzMethod", "inc") theZone.uzMethod = theZone:getStringFromZoneProperty("uzMethod", "inc")
end end
if cfxZones.hasProperty(theZone, "enterZone!") then if theZone:hasProperty("enterZone!") then
theZone.enterZone = cfxZones.getStringFromZoneProperty(theZone, "enterZone!", "*<none>") theZone.enterZone = theZone:getStringFromZoneProperty("enterZone!", "*<none>")
end end
if cfxZones.hasProperty(theZone, "exitZone!") then if theZone:hasProperty("exitZone!") then
theZone.exitZone = cfxZones.getStringFromZoneProperty(theZone, "exitZone!", "*<none>") theZone.exitZone = theZone:getStringFromZoneProperty("exitZone!", "*<none>")
end end
if cfxZones.hasProperty(theZone, "changeZone!") then if theZone:hasProperty("changeZone!") then
theZone.changeZone = cfxZones.getStringFromZoneProperty(theZone, "changeZone!", "*<none>") theZone.changeZone = theZone:getStringFromZoneProperty("changeZone!", "*<none>")
end end
if cfxZones.hasProperty(theZone, "filterFor") then if theZone:hasProperty("filterFor") then
local filterString = cfxZones.getStringFromZoneProperty(theZone, "filterFor", "1") -- ground local filterString = theZone:getStringFromZoneProperty( "filterFor", "1") -- ground
theZone.filterFor = unitZone.string2cat(filterString) theZone.filterFor = unitZone.string2cat(filterString)
if unitZone.verbose or theZone.verbose then if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: filtering " .. theZone.filterFor .. " in " .. theZone.name, 30) trigger.action.outText("+++uZne: filtering " .. theZone.filterFor .. " in " .. theZone.name, 30)
end end
elseif theZone:hasProperty("filter") then
local filterString = theZone:getStringFromZoneProperty( "filter", "1") -- ground
theZone.filterFor = unitZone.string2cat(filterString)
if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: filtering " .. theZone.filterFor .. " in " .. theZone.name, 30)
end
end end
-- uzDirect -- uzDirect
if cfxZones.hasProperty(theZone, "uzDirect") then if theZone:hasProperty("uzDirect") then
theZone.uzDirect = cfxZones.getStringFromZoneProperty(theZone, "uzDirect", "*<none>") theZone.uzDirect = theZone:getStringFromZoneProperty("uzDirect", "*<none>")
elseif
theZone:hasProperty("uzDirect#") then
theZone.uzDirect = theZone:getStringFromZoneProperty("uzDirect#", "*<none>")
elseif
theZone:hasProperty("direct#") then
theZone.uzDirect = theZone:getStringFromZoneProperty("direct#", "*<none>")
end end
if cfxZones.hasProperty(theZone, "uzDirectInv") then if theZone:hasProperty("uzDirectInv") then
theZone.uzDirectInv = cfxZones.getStringFromZoneProperty(theZone, "uzDirectInv", "*<none>") theZone.uzDirectInv = theZone:getStringFromZoneProperty("uzDirectInv", "*<none>")
elseif theZone:hasProperty("uzDirectInv#") then
theZone.uzDirectInv = theZone:getStringFromZoneProperty("uzDirectInv#", "*<none>")
elseif theZone:hasProperty("directInv#") then
theZone.uzDirectInv = theZone:getStringFromZoneProperty("directInv#", "*<none>")
end end
-- on/off flags -- on/off flags
theZone.uzPaused = false -- we are turned on theZone.uzPaused = false -- we are turned on
if cfxZones.hasProperty(theZone, "uzOn?") then if theZone:hasProperty("uzOn?") then
theZone.triggerOnFlag = cfxZones.getStringFromZoneProperty(theZone, "uzOn?", "*<none1>") theZone.triggerOnFlag = theZone:getStringFromZoneProperty("uzOn?", "*<none1>")
theZone.lastTriggerOnValue = cfxZones.getFlagValue(theZone.triggerOnFlag, theZone) theZone.lastTriggerOnValue = theZone:getFlagValue(theZone.triggerOnFlag)
end end
if cfxZones.hasProperty(theZone, "uzOff?") then if theZone:hasProperty("uzOff?") then
theZone.triggerOffFlag = cfxZones.getStringFromZoneProperty(theZone, "uzOff?", "*<none2>") theZone.triggerOffFlag = theZone:getStringFromZoneProperty("uzOff?", "*<none2>")
theZone.lastTriggerOffValue = cfxZones.getFlagValue(theZone.triggerOffFlag, theZone) theZone.lastTriggerOffValue = theZone:getFlagValue(theZone.triggerOffFlag)
end end
theZone.uzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change") theZone.uzTriggerMethod = theZone:getStringFromZoneProperty("triggerMethod", "change")
if cfxZones.hasProperty(theZone, "uzTriggerMethod") then if theZone:hasProperty("uzTriggerMethod") then
theZone.uzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "uzTriggerMethod", "change") theZone.uzTriggerMethod = theZone:getStringFromZoneProperty("uzTriggerMethod", "change")
end end
-- now get initial zone status ? -- now get initial zone status ?
theZone.lastStatus = unitZone.checkZoneStatus(theZone) theZone.lastStatus = unitZone.checkZoneStatus(theZone)
if theZone.uzDirect then
if newState then
theZone:setFlagValue(theZone.uzDirect, 1)
else
theZone:setFlagValue(theZone.uzDirect, 0)
end
end
if theZone.uzDirectInv then
if newState then
theZone:setFlagValue(theZone.uzDirectInv, 0)
else
theZone:setFlagValue(theZone.uzDirectInv, 1)
end
end
if unitZone.verbose or theZone.verbose then if unitZone.verbose or theZone.verbose then
trigger.action.outText("+++uZne: processsed unit zone " .. theZone.name, 30) trigger.action.outText("+++uZne: processsed unit zone <" .. theZone.name .. "> with status = (" .. dcsCommon.bool2Text(theZone.lastStatus) .. ")", 30)
end end
end end
@ -148,7 +192,7 @@ end
-- --
function unitZone.collectGroups(theZone) function unitZone.collectGroups(theZone)
local collector = {} local collector = {} -- players: units, groups: groups
if theZone.matching == "player" then if theZone.matching == "player" then
-- collect all players matching coalition -- collect all players matching coalition
if theZone.uzCoalition == 1 or theZone.uzCoalition == 0 then if theZone.uzCoalition == 1 or theZone.uzCoalition == 0 then
@ -166,16 +210,14 @@ function unitZone.collectGroups(theZone)
elseif theZone.matching == "group" then elseif theZone.matching == "group" then
if theZone.uzCoalition == 1 or theZone.uzCoalition == 0 then if theZone.uzCoalition == 1 or theZone.uzCoalition == 0 then
local allGroups = coalition.getGroups(1, theZone.filterFor) local allGroups = coalition.getGroups(1, theZone.filterFor)
for idx, aGroup in pairs(allGroups) do
for idx, pUnit in pairs(allGroups) do table.insert(collector, aGroup)
table.insert(collector, pUnit)
end end
end end
if theZone.uzCoalition == 2 or theZone.uzCoalition == 0 then if theZone.uzCoalition == 2 or theZone.uzCoalition == 0 then
local allGroups = coalition.getGroups(2, theZone.filterFor) local allGroups = coalition.getGroups(2, theZone.filterFor)
for idx, aGroup in pairs(allGroups) do
for idx, pUnit in pairs(allGroups) do table.insert(collector, aGroup)
table.insert(collector, pUnit)
end end
end end
else else
@ -197,15 +239,17 @@ function unitZone.checkZoneStatus(theZone)
local playerCheck = theZone.matching == "player" local playerCheck = theZone.matching == "player"
if playerCheck then if playerCheck then
-- we check the names for players only -- we check the names for players only
-- collector holds units, not groups -- collector holds units for players, not groups
for idx, pUnit in pairs(theGroups) do for idx, pUnit in pairs(theGroups) do
local puName = pUnit:getName() local puName = pUnit:getName()
local hasMatch = false local hasMatch = theZone.matchAll
if theZone.lookForBeginsWith then if not hasMatch then
hasMatch = dcsCommon.stringStartsWith(puName, lookFor) if theZone.lookForBeginsWith then
else hasMatch = dcsCommon.stringStartsWith(puName, lookFor)
hasMatch = puName == lookFor else
end hasMatch = puName == lookFor
end
end
if hasMatch then if hasMatch then
if cfxZones.unitInZone(pUnit, theZone) then if cfxZones.unitInZone(pUnit, theZone) then
return true return true
@ -214,20 +258,21 @@ function unitZone.checkZoneStatus(theZone)
end end
else else
-- we perform group check -- we perform group check.
for idx, aGroup in pairs(theGroups) do for idx, aGroup in pairs(theGroups) do
local gName=aGroup:getName() local gName=aGroup:getName()
local hasMatch = false local hasMatch = theZone.matchAll
if theZone.lookForBeginsWith then if not hasMatch then
hasMatch = dcsCommon.stringStartsWith(gName, lookFor) if theZone.lookForBeginsWith then
else hasMatch = dcsCommon.stringStartsWith(gName, lookFor)
hasMatch = gName == lookFor else
end hasMatch = gName == lookFor
end
end
if hasMatch and aGroup:isExist() then if hasMatch and aGroup:isExist() then
-- check all living units in zone -- check all living units in zone
local gUnits = aGroup:getUnits() local gUnits = aGroup:getUnits()
for idy, aUnit in pairs (gUnits) do for idy, aUnit in pairs (gUnits) do
--trigger.action.outText("trying " .. gName,10)
if cfxZones.unitInZone(aUnit, theZone) then if cfxZones.unitInZone(aUnit, theZone) then
return true return true
end end
@ -244,18 +289,18 @@ end
function unitZone.bangState(theZone, newState) function unitZone.bangState(theZone, newState)
if theZone.changeZone then if theZone.changeZone then
cfxZones.pollFlag(theZone.changeZone, theZone.uzMethod, theZone) theZone:pollFlag(theZone.changeZone, theZone.uzMethod)
end end
if newState then if newState then
if theZone.enterZone then if theZone.enterZone then
cfxZones.pollFlag(theZone.enterZone, theZone.uzMethod, theZone) theZone:pollFlag(theZone.enterZone, theZone.uzMethod)
if unitZone.verbose then if unitZone.verbose then
trigger.action.outText("+++uZone: banging enter! with <" .. theZone.uzMethod .. "> on <" .. theZone.enterZone .. "> for " .. theZone.name, 30) trigger.action.outText("+++uZone: banging enter! with <" .. theZone.uzMethod .. "> on <" .. theZone.enterZone .. "> for " .. theZone.name, 30)
end end
end end
else else
if theZone.exitZone then if theZone.exitZone then
cfxZones.pollFlag(theZone.exitZone, theZone.uzMethod, theZone) theZone:pollFlag(theZone.exitZone, theZone.uzMethod)
if unitZone.verbose then if unitZone.verbose then
trigger.action.outText("+++uZone: banging exit! with <" .. theZone.uzMethod .. "> on <" .. theZone.exitZone .. "> for " .. theZone.name, 30) trigger.action.outText("+++uZone: banging exit! with <" .. theZone.uzMethod .. "> on <" .. theZone.exitZone .. "> for " .. theZone.name, 30)
end end
@ -269,14 +314,16 @@ function unitZone.update()
for idx, aZone in pairs(unitZone.unitZones) do for idx, aZone in pairs(unitZone.unitZones) do
-- check if we need to pause/unpause -- check if we need to pause/unpause
if aZone.triggerOnFlag and cfxZones.testZoneFlag(aZone, aZone.triggerOnFlag, aZone.uzTriggerMethod, "lastTriggerOnValue") then if aZone.triggerOnFlag and
aZone:testZoneFlag( aZone.triggerOnFlag, aZone.uzTriggerMethod, "lastTriggerOnValue") then
if unitZone.verbose or aZone.verbose then if unitZone.verbose or aZone.verbose then
trigger.action.outText("+++uZone: turning " .. aZone.name .. " on", 30) trigger.action.outText("+++uZone: turning " .. aZone.name .. " on", 30)
end end
aZone.uzPaused = false aZone.uzPaused = false
end end
if aZone.triggerOffFlag and cfxZones.testZoneFlag(aZone, aZone.triggerOffFlag, aZone.uzTriggerMethod, "lastTriggerOffValue") then if aZone.triggerOffFlag and
aZone:testZoneFlag(aZone.triggerOffFlag, aZone.uzTriggerMethod, "lastTriggerOffValue") then
if unitZone.verbose or aZone.verbose then if unitZone.verbose or aZone.verbose then
trigger.action.outText("+++uZone: turning " .. aZone.name .. " OFF", 30) trigger.action.outText("+++uZone: turning " .. aZone.name .. " OFF", 30)
end end
@ -299,9 +346,9 @@ function unitZone.update()
trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting uzDirect <" .. aZone.uzDirect .. "> to ".. dcsCommon.bool2Num(newState), 30) trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting uzDirect <" .. aZone.uzDirect .. "> to ".. dcsCommon.bool2Num(newState), 30)
end end
if newState then if newState then
cfxZones.setFlagValueMult(aZone.uzDirect, 1, aZone) aZone:setFlagValue(aZone.uzDirect, 1)
else else
cfxZones.setFlagValueMult(aZone.uzDirect, 0, aZone) aZone:setFlagValue(aZone.uzDirect, 0)
end end
end end
if aZone.uzDirectInv then if aZone.uzDirectInv then
@ -310,9 +357,9 @@ function unitZone.update()
trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting INVuzDirect <" .. aZone.uzDirectInv .. "> to ".. dcsCommon.bool2Num(invState), 30) trigger.action.outText("+++uZone: <" .. aZone.name .. "> setting INVuzDirect <" .. aZone.uzDirectInv .. "> to ".. dcsCommon.bool2Num(invState), 30)
end end
if newState then if newState then
cfxZones.setFlagValueMult(aZone.uzDirectInv, 0, aZone) aZone:setFlagValue(aZone.uzDirectInv, 0)
else else
cfxZones.setFlagValueMult(aZone.uzDirectInv, 1, aZone) aZone:setFlagValue(aZone.uzDirectInv, 1)
end end
end end
end end
@ -323,6 +370,7 @@ end
-- Config & Start -- Config & Start
-- --
function unitZone.readConfigZone() function unitZone.readConfigZone()
unitZone.name = "unitZoneConfig"
local theZone = cfxZones.getZoneByName("unitZoneConfig") local theZone = cfxZones.getZoneByName("unitZoneConfig")
if not theZone then if not theZone then
theZone = cfxZones.createSimpleZone("unitZoneConfig") theZone = cfxZones.createSimpleZone("unitZoneConfig")
@ -370,6 +418,6 @@ if not unitZone.start() then
unitZone = nil unitZone = nil
end end
--ToDo: matching: name, name wildcard, type
--ToDo: add 'neutral' support and add 'both' option --ToDo: add 'neutral' support and add 'both' option
--ToDo: add API --ToDo: add API

Binary file not shown.