Version 0.9985

CivAir
QoL
fixes in ssbClient, cloneZone
This commit is contained in:
Christian Franz 2022-04-21 14:25:33 +02:00
parent 284063b829
commit ab1fb76c6f
14 changed files with 290 additions and 307 deletions

Binary file not shown.

Binary file not shown.

View File

@ -273,7 +273,7 @@ function cfxSSBClient:onEvent(event)
-- player entered unit?
-- check if this is cloned impostor
if not theUnit.getPlayerName then
trigger.action.outText("+++SSBC: non-player client " .. uName .. " detected, ignoring.", 30)
trigger.action.outText("+++SSBC: non-player 'client' " .. uName .. " detected, ignoring.", 30)
return
end
local playerName = theUnit:getPlayerName()

View File

@ -6,7 +6,7 @@
--
cfxZones = {}
cfxZones.version = "2.7.4"
cfxZones.version = "2.7.5"
--[[-- VERSION HISTORY
- 2.2.4 - getCoalitionFromZoneProperty
- getStringFromZoneProperty
@ -69,6 +69,7 @@ cfxZones.version = "2.7.4"
- 2.7.3 - testZoneFlag returns mathodResult, lastVal
- evalFlagMethodImmediate()
- 2.7.4 - doPollFlag supports immediate number setting
- 2.7.5 - more QoL checks when mixing up ? and ! for attributes
--]]--
cfxZones.verbose = false
@ -1655,11 +1656,16 @@ end
function cfxZones.hasProperty(theZone, theProperty)
local foundIt = cfxZones.getZoneProperty(theZone, theProperty)
if not foundIt then
-- check for possible forgotten or exchanged IO flags
if string.sub(theProperty, -1) == "?" then
local lessOp = theProperty:sub(1,-2)
if cfxZones.getZoneProperty(theZone, lessOp) ~= nil then
trigger.action.outText("*** NOTE: " .. theZone.name .. "'s property <" .. lessOp .. "> may be missing a Query ('?') symbol", 30)
end
local lessPlus = lessOp .. "!"
if cfxZones.getZoneProperty(theZone, lessPlus) ~= nil then
trigger.action.outText("*** NOTE: " .. theZone.name .. "'s property <" .. lessOp .. "> may be using '!' instead of '?' for input", 30)
end
return false
end
@ -1668,6 +1674,10 @@ function cfxZones.hasProperty(theZone, theProperty)
if cfxZones.getZoneProperty(theZone, lessOp) ~= nil then
trigger.action.outText("*** NOTE: " .. theZone.name .. "'s property <" .. lessOp .. "> may be missing a Bang! ('!') symbol", 30)
end
local lessPlus = lessOp .. "?"
if cfxZones.getZoneProperty(theZone, lessPlus) ~= nil then
trigger.action.outText("*** NOTE: " .. theZone.name .. "'s property <" .. lessOp .. "> may be using '!' instead of '?' for input", 30)
end
return false
end

View File

@ -1,5 +1,5 @@
changer = {}
changer.version = "0.0.0"
changer.version = "1.0.0"
changer.verbose = false
changer.ups = 1
changer.requiredLibs = {
@ -15,10 +15,6 @@ changer.changers = {}
- not
- bool
- value
- rnd
- count (? multiple signals, better done with xFlags)
- min, max minmax 2,3, cap,
--]]--
@ -48,14 +44,17 @@ function changer.createChangerWithZone(theZone)
-- triggerChangerMethod
theZone.triggerChangerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerChangerMethod") then
theZone.triggerChangerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerChangerMethod", "change")
if cfxZones.hasProperty(theZone, "triggerChangeMethod") then
theZone.triggerChangerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerChangeMethod", "change")
end
theZone.inEval = cfxZones.getBoolFromZoneProperty(theZone, "inEval", true) -- yes/no to pre-process, default is yes
theZone.changeTo = cfxZones.getStringFromZoneProperty(theZone, "to", "val") -- val, not, bool
if cfxZones.hasProperty(theZone, "changeTo") then
theZone.changerTo = cfxZones.getStringFromZoneProperty(theZone, "changeTo", "val")
end
theZone.changeTo = string.lower(theZone.changeTo)
theZone.changeTo = dcsCommon.trim(theZone.changeTo)
@ -64,6 +63,28 @@ function changer.createChangerWithZone(theZone)
theZone.changeOut = cfxZones.getStringFromZoneProperty(theZone, "changeOut!", "*none")
end
-- pause / on / off commands
theZone.changerPaused = cfxZones.getBoolFromZoneProperty(theZone, "paused", false) -- we default to unpaused
if cfxZones.hasProperty(theZone, "changePaused") then
theZone.changerPaused = cfxZones.getBoolFromZoneProperty(theZone, "changePaused", false)
end
if theZone.changerPaused and (changer.verbose or theZone.verbose) then
trigger.action.outText("+++chgr: <" .. theZone.name .. "> starts paused", 30)
end
theZone.changerOn = cfxZones.getStringFromZoneProperty(theZone, "on?", "*<none>")
if cfxZones.hasProperty(theZone, "changeOn?") then
theZone.changerOn = cfxZones.getStringFromZoneProperty(theZone, "changeOn?", "*<none>")
end
theZone.lastChangerOnValue = cfxZones.getFlagValue(theZone.changerOn, theZone)
theZone.changerOff = cfxZones.getStringFromZoneProperty(theZone, "off?", "*<none>")
if cfxZones.hasProperty(theZone, "changeOff?") then
theZone.changerOff = cfxZones.getStringFromZoneProperty(theZone, "changeOff?", "*<none>")
end
theZone.lastChangerOffValue = cfxZones.getFlagValue(theZone.changerOff, theZone)
if changer.verbose or theZone.verbose then
trigger.action.outText("+++chgr: new changer zone <".. theZone.name ..">", 30)
end
@ -90,11 +111,14 @@ function changer.process(theZone)
-- process and write outflag
if op == "bool" then
if currVal == 0 then res = 0 else res = 1 end
elseif
op == "not" then
elseif op == "not" then
if currVal == 0 then res = 1 else res = 0 end
elseif op == "val" or op == "direct" then
-- do nothing
else
trigger.action.outText("+++chgr: unsupported changeTo operation <" .. .. "> in zone <" .. .. ">, using 'val'", 30)
end
-- all others drop through
-- illegal ops drop through after warning, functioning as 'val'
-- write out
cfxZones.setFlagValueMult(theZone.changeOut, res, theZone)
@ -116,7 +140,27 @@ function changer.update()
timer.scheduleFunction(changer.update, {}, timer.getTime() + 1/changer.ups)
for idx, aZone in pairs(changer.changers) do
changer.process(aZone)
-- process the pause/unpause flags
-- see if we should suspend
if cfxZones.testZoneFlag(theZone, theZone.changerOn, "change", "lastChangerOnValue") then
if changer.verbose or theZone.verbose then
trigger.action.outText("+++chgr: enabling " .. theZone.name, 30)
end
theZone.changerPaused = false
end
if cfxZones.testZoneFlag(theZone, theZone.changerOff, "change", "lastChangerOffValue") then
if changer.verbose or theZone.verbose then
trigger.action.outText("+++chgr: DISabling " .. theZone.name, 30)
end
theZone.changerPaused = true
end
-- do processing if not paused
if not aZone.changerPaused then
changer.process(aZone)
end
end
end
@ -174,3 +218,10 @@ if not changer.start() then
trigger.action.outText("cfx changer aborted: missing libraries", 30)
changer = nil
end
--[[--
Possible expansions
- rnd
- min, max minmax 2,3, cap to left right values,
--]]--

View File

@ -1,5 +1,5 @@
civAir = {}
civAir.version = "1.4.0"
civAir.version = "1.5.0"
--[[--
1.0.0 initial version
1.1.0 exclude list for airfields
@ -16,6 +16,11 @@ civAir.version = "1.4.0"
all configs it finds
module check
removed obsolete civAirConfig module
1.5.0 process zones as in all other modules
verbose is part of config zone
reading type array from config corrected
massive simplifications: always between zoned airfieds
exclude list and include list
--]]--
@ -34,52 +39,28 @@ civAir.aircraftTypes = {"Yak-40", "Yak-40", "C-130", "C-17A", "IL-76MD", "An-30
-- concurrently under way
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.trafficAirbases = {
randomized = 0, -- between any on map
localHubs = 1, -- between any two airfields inside the same random hub listed in trafficCenters
betweenHubs = 2 -- between any in random hub 1 to any in random hub 2
}
civAir.trafficRange = 100 -- 120000 -- defines hub size, in meters. Make it 100 to make it only that airfield
-- ABPickmethod determines how airfields are picked
-- for air traffic
civAir.ABPickMethod = civAir.trafficAirbases.betweenHubs
civAir.trafficCenters = {
--"batu",
--"kobul",
--"senaki",
--"kutai",
} -- trafficCenters is used with hubs. Each entry defines a hub
-- where we collect airdromes etc based on range
-- simply add a string to identify the hub center
-- e.g. "senak" to define "Senaki Kolkhi"
-- to have planes only fly between airfields in 100 km range
-- around senaki kolkhi, enter only senaki as traffic center, set
-- trafficRange to 100000 and ABPickMethod to localHubs
-- to have traffic only between any airfields listed
-- in trafficCenters, set trafficRange to a small value
-- like 100 meters and set ABPickMethod to betweenHubs
-- to have flights that always cross the map with multiple
-- airfields, choose two or three hubs that are 300 km apart,
-- then set trafficRange to 150000 and ABPickMethod to betweenHubs
-- you can also place zones on the map and add a
-- civAir attribute. If the attribute value is anything
-- but "exclude", the closest airfield to the zone
-- is added to trafficCenters
-- if you leave this list empty, and do not add airfields
-- by zones, the list is automatically populated by all
-- airfields in the map
}
-- 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
-- is added to trafficCenters
-- if you leave this list empty, and do not add airfields
-- by zones, the list is automatically populated with all
-- airfields in the map
civAir.excludeAirfields = {
--"senaki",
}
-- 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
-- in trafficCenters. Here, Senaki is off limits for
-- civilian air traffic
-- can be populated by zone on the map that have the
-- 'civAir' attribute with value "exclude"
-- 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
-- in trafficCenters. Here, Senaki is off limits for
-- civilian air traffic
-- can be populated by zone on the map that have the
-- 'civAir' attribute with value "exclude"
civAir.requiredLibs = {
"dcsCommon", -- common is of course needed for everything
@ -91,7 +72,7 @@ civAir.idlePlanes = {}
function civAir.readConfigZone()
-- note: must match exactly!!!!
local theZone = cfxZones.getZoneByName("CivAirConfig")
local theZone = cfxZones.getZoneByName("civAirConfig")
if not theZone then
trigger.action.outText("***civA: NO config zone!", 30)
return
@ -101,7 +82,10 @@ function civAir.readConfigZone()
-- ok, for each property, load it if it exists
if cfxZones.hasProperty(theZone, "aircraftTypes") then
civAir.aircraftTypes = cfxZones.getStringFromZoneProperty(theZone, "aircraftTypes", "Yak-40")
local theTypes = cfxZones.getStringFromZoneProperty(theZone, "aircraftTypes", "Yak-40")
local typeArray = dcsCommon.splitString(theTypes, ",")
typeArray = dcsCommon.trimArray(typeArray)
civAir.aircraftTypes = typeArray
end
if cfxZones.hasProperty(theZone, "ups") then
@ -117,18 +101,27 @@ function civAir.readConfigZone()
civAir.maxIdle = cfxZones.getNumberFromZoneProperty(theZone, "maxIdle", 8 * 60)
end
if cfxZones.hasProperty(theZone, "trafficRange") then
civAir.trafficRange = cfxZones.getNumberFromZoneProperty(theZone, "trafficRange", 120000) -- 120 km
end
if cfxZones.hasProperty(theZone, "ABPickMethod") then
civAir.ABPickMethod = cfxZones.getNumberFromZoneProperty(theZone, "ABPickMethod", 0) -- randomized any
end
if cfxZones.hasProperty(theZone, "initialAirSpawns") then
civAir.initialAirSpawns = cfxZones.getBoolFromZoneProperty(theZone, "initialAirSpawns", true)
end
civAir.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
end
function civAir.processZone(theZone)
local value = cfxZones.getStringFromZoneProperty(theZone, "civAir", "")
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
table.insert(civAir.excludeAirfields, afName)
else
table.insert(civAir.trafficCenters, afName) -- note that adding the same twice makes it more likely to be picked
end
else
trigger.action.outText("+++civA: unable to resolve airfield for <" .. theZone.name .. ">", 30)
end
end
function civAir.addPlane(thePlaneUnit) -- warning: is actually a group
@ -158,122 +151,49 @@ function civAir.getPlane(aName) -- warning: returns GROUP!
return civAir.activePlanes[aName]
end
-- get an air base, may exclude an airbase from choice
-- method is dependent on
function civAir.getAnAirbase(excludeThisOne)
-- different methods to select a base
-- purely random from current list
local theAB;
if civAir.ABPickMethod == civAir.trafficAirbases.randomized then
repeat
local allAB = dcsCommon.getAirbasesWhoseNameContains("*", 0) -- all airfields, no Ships nor FABS
theAB = dcsCommon.pickRandom(allAB)
until theAB ~= excludeThisOne
return theAB
end
if civAir.ABPickMethod == civAir.trafficAirbases.localHubs then
-- first, pick a hub name
end
trigger.action.outText("civA: warning - unknown method <" .. civAir.ABPickMethod .. ">", 30)
return nil
end
function civAir.excludeAirbases(inList, excludeList)
if not inList then return {} end
if not excludeList then return inList end
if #excludeList < 1 then return inList end
local theDict = {}
-- build dict
for idx, aBase in pairs(inList) do
theDict[aBase:getName()] = aBase
end
-- now iterate through all excludes and remove them from dics
for idx, aName in pairs (excludeList) do
local allOfflimitAB = dcsCommon.getAirbasesWhoseNameContains(aName, 0)
for idx2, illegalBase in pairs (allOfflimitAB) do
theDict[illegalBase:getName()] = nil
function civAir.filterAirfields(inAll, inFilter)
local outList = {}
for idx, anItem in pairs(inAll) do
if dcsCommon.arrayContainsString(inFilter, anItem) then
-- filtered, do nothing.
else
-- not filtered
table.insert(outList, anItem)
end
end
-- now linearise (make array) from dict
local theArray = dcsCommon.enumerateTable(theDict)
return theArray
return outList
end
function civAir.getTwoAirbases()
local fAB
local sAB
-- get any two airbases on the map
if civAir.ABPickMethod == civAir.trafficAirbases.randomized then
local allAB = dcsCommon.getAirbasesWhoseNameContains("*", 0) -- all airfields, no Ships nor FABS, all coalitions
-- remove illegal source/dest airfields
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
local fAB -- first airbase to depart
local sAB -- second airbase to fly to
fAB = dcsCommon.pickRandom(allAB)
repeat
sAB = dcsCommon.pickRandom(allAB)
until fAB ~= sAB or (#allAB < 2)
return fAB, sAB
-- remove all currently excluded air bases from available
local filteredAB = civAir.filterAirfields(civAir.trafficCenters, civAir.excludeAirfields)
-- if none left, error
if #filteredAB < 1 then
trigger.action.outText("+++civA: too few airfields")
return nil, nil
end
-- pick a hub, and then selct any two different airbases in the hub
if civAir.ABPickMethod == civAir.trafficAirbases.localHubs then
local hubName = dcsCommon.pickRandom(civAir.trafficCenters)
-- get the airfield that is identified by this
local theHub = dcsCommon.getFirstAirbaseWhoseNameContains(hubName, 0) -- only airfields, all coalitions
-- get all airbases that surround in range
local allAB = dcsCommon.getAirbasesInRangeOfAirbase(
theHub, -- centered on this base
true, -- include hub itself
civAir.trafficRange, -- hub size in meters
0 -- only airfields
)
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
fAB = dcsCommon.pickRandom(allAB)
repeat
sAB = dcsCommon.pickRandom(allAB)
until fAB ~= sAB or (#allAB < 2)
return fAB, sAB
-- 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
end
-- pick two hubs: one for source, one for destination airfields,
-- then pick an airfield from each hub
if civAir.ABPickMethod == civAir.trafficAirbases.betweenHubs then
--trigger.action.outText("between", 30)
local sourceHubName = dcsCommon.pickRandom(civAir.trafficCenters)
--trigger.action.outText("picked " .. sourceHubName, 30)
local sourceHub = dcsCommon.getFirstAirbaseWhoseNameContains(sourceHubName, 0)
--trigger.action.outText("sourceHub " .. sourceHub:getName(), 30)
-- pick any two that are not the same
fAB = dcsCommon.pickRandom(filteredAB)
repeat
sAB = dcsCommon.pickRandom(filteredAB)
until fAB ~= sAB
fAB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
sAB = dcsCommon.getFirstAirbaseWhoseNameContains(sAB, 0)
local destHub
repeat destHubName = dcsCommon.pickRandom(civAir.trafficCenters)
until destHubName ~= sourceHubName or #civAir.trafficCenters < 2
destHub = dcsCommon.getFirstAirbaseWhoseNameContains(destHubName, 0)
--trigger.action.outText("destHub " .. destHub:getName(), 30)
local allAB = dcsCommon.getAirbasesInRangeOfAirbase(
sourceHub, -- centered on this base
true, -- include hub itself
civAir.trafficRange, -- hub size in meters
0 -- only airfields
)
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
fAB = dcsCommon.pickRandom(allAB)
allAB = dcsCommon.getAirbasesInRangeOfAirbase(
destHub, -- centered on this base
true, -- include hub itself
civAir.trafficRange, -- hub size in meters
0 -- only airfields
)
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
sAB = dcsCommon.pickRandom(allAB)
return fAB, sAB
end
return fAB, sAB
trigger.action.outText("civA: warning - unknown method <" .. civAir.ABPickMethod .. "> in getTwoAirbases()", 30)
end
function civAir.parkingIsFree(fromWP)
@ -370,6 +290,10 @@ function civAir.createNewFlight(inAirStart)
civAir.flightCount = civAir.flightCount + 1
local fAB, sAB = civAir.getTwoAirbases() -- from AB
if not fAB or not sAB then
trigger.action.outText("+++civA: cannot create flight, no source or destination", 30)
return
end
local name = fAB:getName() .. "-" .. sAB:getName().. "/" .. civAir.flightCount
local TypeString = dcsCommon.pickRandom(civAir.aircraftTypes)
@ -500,17 +424,7 @@ function civAir.collectHubs()
local pZones = cfxZones.zonesWithProperty("civAir")
for k, aZone in pairs(pZones) do
local value = cfxZones.getStringFromZoneProperty(aZone, "civAir", "")
local af = dcsCommon.getClosestAirbaseTo(aZone.point, 0) -- 0 = only airfields, not farp or ships
if af then
local afName = af:getName()
if value:lower() == "exclude" then
table.insert(civAir.excludeAirfields, afName)
else
table.insert(civAir.trafficCenters, afName)
end
end
civAir.processZone(aZone)
end
end
@ -536,17 +450,19 @@ function civAir.start()
-- make sure there is something in trafficCenters
if #civAir.trafficCenters < 1 then
trigger.action.outText("+++civTraffic: auto-populating", 30)
trigger.action.outText("+++civA: auto-populating", 30)
-- simply add airfields on the map
local allBases = dcsCommon.getAirbasesWhoseNameContains("*", 0)
for idx, aBase in pairs(allBases) do
local afName = aBase:getName()
--trigger.action.outText("+++civTraffic: adding " .. afName, 30)
table.insert(civAir.trafficCenters, afName)
end
end
civAir.listTrafficCenters()
if civAir.verbose then
civAir.listTrafficCenters()
end
-- air-start half population if allowed
if civAir.initialAirSpawns then
@ -557,7 +473,7 @@ function civAir.start()
civAir.update()
-- say hi!
trigger.action.outText("cf/x civTraffic v" .. civAir.version .. " started.", 30)
trigger.action.outText("cf/x civAir v" .. civAir.version .. " started.", 30)
return true
end
@ -568,5 +484,11 @@ end
--[[--
Additional ideas
source to target method
- border zones: ac can airstart in there and disappear in there
- callbacks for civ spawn / despawn
- add civkill callback / redCivKill blueCivKill flag bangers
- Helicopter support
- departure only, destination only
- add slot checking to see if other planes block it even though DCS claims the slot is free
--]]--

View File

@ -1,5 +1,5 @@
cloneZones = {}
cloneZones.version = "1.4.1"
cloneZones.version = "1.4.2"
cloneZones.verbose = false
cloneZones.requiredLibs = {
"dcsCommon", -- always
@ -38,6 +38,8 @@ cloneZones.uniqueCounter = 9200000 -- we start group numbering here
- trackWith: attribute
1.4.0 - Watchflags
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)
--]]--
@ -688,7 +690,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"
-- move origin
trigger.action.outText("static object proccing", 30)
rawData.x = rawData.x + zoneDelta.x
rawData.y = rawData.y + zoneDelta.z -- !!!
@ -704,7 +706,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
-- handle linkUnit if provided
if rawData.linkUnit then
if false and 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)
@ -869,14 +871,6 @@ function cloneZones.hasLiveUnits(theZone)
return false
end
-- old code, deprecated
--[[--
function cloneZones.pollFlag(flagNum, method)
-- we currently ignore method
local num = trigger.misc.getUserFlag(flagNum)
trigger.action.setUserFlag(flagNum, num+1)
end
--]]--
--
-- UPDATE
--
@ -903,20 +897,6 @@ function cloneZones.update()
end
cloneZones.spawnWithCloner(aZone)
end
-- old code
--[[--
if aZone.spawnFlag then
local currTriggerVal = cfxZones.getFlagValue(aZone.spawnFlag, aZone) -- trigger.misc.getUserFlag(aZone.spawnFlag)
if currTriggerVal ~= aZone.lastSpawnValue
then
if cloneZones.verbose then
trigger.action.outText("+++clnZ: spawn triggered for <" .. aZone.name .. ">", 30)
end
cloneZones.spawnWithCloner(aZone)
aZone.lastSpawnValue = currTriggerVal
end
end
--]]--
-- empty handling
local isEmpty = cloneZones.countLiveUnits(aZone) < 1 and aZone.hasClones
@ -999,8 +979,12 @@ function cloneZones.start()
cloneZones.addCloneZone(aZone) -- remember it so we can smoke it
end
-- run through onStart
cloneZones.onStart()
-- run through onStart, but leave at least a few
-- cycles to go through object removal so statics
-- can spawn on ground. onStart is being deprecated, the
-- raiseFlag module covers this since the first time
-- raiseFlag is run is t0 + 0.5s
timer.scheduleFunction(cloneZones.onStart, {}, timer.getTime() + 0.1)
-- start update
cloneZones.update()
@ -1016,13 +1000,6 @@ if not cloneZones.start() then
cloneZones = nil
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
@ -1030,4 +1007,5 @@ cloneZones.addCallback(czcb.callback)
- AFAC
- FAC Assign group
- set freq for unit
- embark / disembark
--]]--

View File

@ -1,5 +1,5 @@
dcsCommon = {}
dcsCommon.version = "2.5.9"
dcsCommon.version = "2.6.1"
--[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB
@ -70,6 +70,7 @@ dcsCommon.version = "2.5.9"
2.5.8 - string2GroupCat()
2.5.9 - string2ObjectCat()
2.6.0 - unified uuid, removed uuIdent
2.6.1 - removed bug in rotateUnitData: cy --> cz param passing
--]]--
@ -1483,7 +1484,7 @@ dcsCommon.version = "2.5.9"
return px, py
end
function dcsCommon.rotateUnitData(theUnit, degrees, cx, cy)
function dcsCommon.rotateUnitData(theUnit, degrees, cx, cz)
if not cx then cx = 0 end
if not cz then cz = 0 end
local cy = cz

View File

@ -1,5 +1,5 @@
delayFlag = {}
delayFlag.version = "1.2.1"
delayFlag.version = "1.2.2"
delayFlag.verbose = false
delayFlag.requiredLibs = {
"dcsCommon", -- always
@ -31,6 +31,9 @@ delayFlag.flags = {}
1.2.0 - Watchflags
1.2.1 - method goes to dlyMethod
- delay done is correctly inited
1.2.2 - delayMethod defaults to inc
- zone-local verbosity
- code clean-up
--]]--
@ -58,7 +61,7 @@ end
function delayFlag.createTimerWithZone(theZone)
-- delay
theZone.delayMin, theZone.delayMax = cfxZones.getPositiveRangeFromZoneProperty(theZone, "timeDelay", 1) -- same as zone signature
if delayFlag.verbose then
if delayFlag.verbose or theZone.verbose then
trigger.action.outText("+++dlyF: time delay is <" .. theZone.delayMin .. ", " .. theZone.delayMax .. "> seconds", 30)
end
@ -88,10 +91,10 @@ function delayFlag.createTimerWithZone(theZone)
end
theZone.delayMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "flip")
theZone.delayMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
if cfxZones.hasProperty(theZone, "delayMethod") then
theZone.delayMethod = cfxZones.getStringFromZoneProperty(theZone, "delayMethod", "flip")
theZone.delayMethod = cfxZones.getStringFromZoneProperty(theZone, "delayMethod", "inc")
end
-- out flag
@ -108,9 +111,6 @@ function delayFlag.createTimerWithZone(theZone)
theZone.lastTriggerStopValue = cfxZones.getFlagValue(theZone.triggerStopDelay, theZone)
end
-- init
theZone.delayRunning = false
theZone.timeLimit = -1
@ -139,7 +139,7 @@ function delayFlag.startDelay(theZone)
if delay > theZone.delayMax then delay = theZone.delayMax end
if delay < 1 then delay = 1 end
if delayFlag.verbose then
if delayFlag.verbose or theZone.verbose then
trigger.action.outText("+++dlyF: delay " .. theZone.name .. " range " .. delayMin .. "-" .. delayMax .. ": selected " .. delay, 30)
end
end
@ -157,25 +157,14 @@ function delayFlag.update()
-- see if we need to stop
if cfxZones.testZoneFlag(aZone, aZone.triggerStopDelay, aZone.delayTriggerMethod, "lastTriggerStopValue") then
aZone.delayRunning = false -- simply stop.
if delayFlag.verbose then
if delayFlag.verbose or aZone.verbose then
trigger.action.outText("+++dlyF: stopped delay " .. aZone.name, 30)
end
end
-- old code
--[[--
if aZone.triggerStopDelay then
local currTriggerVal = cfxZones.getFlagValue(aZone.triggerStopDelay, aZone)
if currTriggerVal ~= lastTriggerStopValue then
aZone.delayRunning = false -- simply stop.
if delayFlag.verbose then
trigger.action.outText("+++dlyF: stopped delay " .. aZone.name, 30)
end
end
end
--]]--
if cfxZones.testZoneFlag(aZone, aZone.triggerDelayFlag, aZone.delayTriggerMethod, "lastDelayTriggerValue") then
if delayFlag.verbose then
if delayFlag.verbose or aZone.verbose then
if aZone.delayRunning then
trigger.action.outText("+++dlyF: re-starting timer " .. aZone.name, 30)
else
@ -184,25 +173,7 @@ function delayFlag.update()
end
delayFlag.startDelay(aZone) -- we restart even if running
end
-- old code
--[[--
-- make sure to re-start before reading time limit
if aZone.triggerDelayFlag then
local currTriggerVal = cfxZones.getFlagValue(aZone.triggerDelayFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerDelayFlag)
if currTriggerVal ~= aZone.lastDelayTriggerValue
then
if delayFlag.verbose then
if aZone.delayRunning then
trigger.action.outText("+++dlyF: re-starting timer " .. aZone.name, 30)
else
trigger.action.outText("+++dlyF: init timer for " .. aZone.name, 30)
end
end
delayFlag.startDelay(aZone) -- we restart even if running
aZone.lastDelayTriggerValue = currTriggerVal
end
end
--]]--
if aZone.delayRunning then
-- check expiry
@ -240,18 +211,7 @@ function delayFlag.readConfigZone()
end
end
--[[--
function delayFlag.onStart()
for idx, theZone in pairs(delayFlag.flags) do
if theZone.onStart then
if delayFlag.verbose then
trigger.action.outText("+++dlyF: onStart for <"..theZone.name .. ">", 30)
end
delayFlag.startDelay(theZone)
end
end
end
--]]--
function delayFlag.start()
-- lib check

View File

@ -13,6 +13,7 @@ radioTrigger.radioTriggers = {}
1.0.0 - initial version
--]]--
function radioTrigger.addRadioTrigger(theZone)
table.insert(radioTrigger.radioTriggers, theZone)
end

View File

@ -1,5 +1,5 @@
unitZone={}
unitZone.version = "1.2.0"
unitZone.version = "1.2.1"
unitZone.verbose = false
unitZone.ups = 1
unitZone.requiredLibs = {
@ -12,6 +12,7 @@ unitZone.requiredLibs = {
1.1.0 - DML flag integration
- method/uzMethod
1.2.0 - uzOn?, uzOff?, triggerMethod
1.2.1 - uzDirect
--]]--
@ -96,6 +97,11 @@ function unitZone.createUnitZone(theZone)
end
end
-- uzDirect
if cfxZones.hasProperty(theZone, "uzDirect") then
theZone.uzDirect = cfxZones.getStringFromZoneProperty(theZone, "uzDirect", "*<none>")
end
-- on/off flags
theZone.uzPaused = false -- we are turned on
theZone.triggerOnFlag = cfxZones.getStringFromZoneProperty(theZone, "uzOn?", "*<none1>")
@ -260,6 +266,15 @@ function unitZone.update()
unitZone.bangState(aZone, newState)
aZone.lastStatus = newState
end
-- output direct state
if aZone.uzDirect then
if newState then
cfxZones.setFlagValueMult(aZone.uzDirect, 1, aZone)
else
cfxZones.setFlagValueMult(aZone.uzDirect, 0, aZone)
end
end
end
end
end

View File

@ -1,6 +1,7 @@
xFlags = {}
xFlags.version = "1.2.1"
xFlags.verbose = false
xFlags.hiVerbose = false
xFlags.ups = 1 -- overwritten in get config when configZone is present
xFlags.requiredLibs = {
"dcsCommon", -- always
@ -22,6 +23,9 @@ xFlags.requiredLibs = {
- xSuccess optimizations
- inc, dec, quoted flags
- matchNum can carry flag
1.2.2 - on/off/suspend commands
- hiVerbose option
- corrected bug in reset checksum
--]]--
xFlags.xFlagZones = {}
@ -33,6 +37,7 @@ end
-- create xFlag
--
function xFlags.reset(theZone)
theZone.flagChecksum = "" -- reset checksum
for i = 1, #theZone.flagNames do
-- since the checksum is order dependent,
-- we must preserve the order of the array
@ -116,6 +121,18 @@ function xFlags.createXFlagsWithZone(theZone)
theZone.xOneShot = cfxZones.getBoolFromZoneProperty(theZone, "oneShot", true)
-- on / off commands
-- on/off flags
theZone.xSuspended = cfxZones.getBoolFromZoneProperty(theZone, "xSuspended", false) -- we are turned on
if theZone.xSuspended and (xFlags.verbose or theZone.verbose) then
trigger.action.outText("+++xFlg: <" .. theZone.name .. "> starts suspended", 30)
end
theZone.xtriggerOnFlag = cfxZones.getStringFromZoneProperty(theZone, "xOn?", "*<none1>")
theZone.xlastTriggerOnValue = cfxZones.getFlagValue(theZone.xtriggerOnFlag, theZone)
theZone.xtriggerOffFlag = cfxZones.getStringFromZoneProperty(theZone, "xOff?", "*<none2>")
theZone.xlastTriggerOffValue = cfxZones.getFlagValue(theZone.xtriggerOffFlag, theZone)
end
function xFlags.evaluateNumOrFlag(theAttribute, theZone)
@ -282,30 +299,41 @@ function xFlags.evaluateZone(theZone)
-- supported any/or, all/and, moreThan, atLeast, exactly
local op = theZone.inspect
local evalResult = false
if (op == "or" or op == "any" or op == "some") and hits > 0 then
evalResult = true
elseif (op == "and" or op == "all") and hits == #theZone.flagNames then
evalResult = true
elseif (op == "morethan" or op == "more than") and hits > matchNum then
evalResult = true
elseif (op == "atleast" or op == "at least") and hits >= matchNum then
evalResult = true
elseif op == "exactly" and hits == matchNum then
evalResult = true
elseif (op == "none" or op == "nor") and hits == 0 then
evalResult = true
elseif (op == "not all" or op == "notall" or op == "nand") and hits < #theZone.flagNames then
evalResult = true
elseif (op == "most") and hits > (#theZone.flagNames / 2) then
evalResult = true
elseif (op == "half" or op == "at least half" or op == "half or more") and hits >= (#theZone.flagNames / 2) then
-- warning: 'half' means really 'at least half"
evalResult = true
if (op == "or" or op == "any" or op == "some") then
if hits > 0 then evalResult = true end
elseif (op == "and" or op == "all") then
if hits == #theZone.flagNames then evalResult = true end
elseif (op == "morethan" or op == "more than") then
if hits > matchNum then evalResult = true end
elseif (op == "atleast" or op == "at least") then
if hits >= matchNum then evalResult = true end
elseif op == "exactly" then
if hits == matchNum then evalResult = true end
elseif (op == "none" or op == "nor") then
if hits == 0 then evalResult = true end
elseif (op == "not all" or op == "notall" or op == "nand") then
if hits < #theZone.flagNames then evalResult = true end
elseif (op == "most") then
if hits > (#theZone.flagNames / 2) then evalResult = true end
elseif (op == "half" or op == "at least half" or op == "half or more") then
if hits >= (#theZone.flagNames / 2) then
-- warning: 'half' means really 'at least half"
evalResult = true
end
else
trigger.action.outText("+++xFlg: WARNING: <" .. theZone.name .. "> has unknown requirement: <" .. op .. ">", 30)
end
-- add "most" to more than 50% of flagnum
-- add "most" to more than 50% of flagnum
-- now check if changed and if result true
-- now check if changed and if result true
if checkSum ~= theZone.flagChecksum then
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: change detected for " .. theZone.name .. ": " .. theZone.flagChecksum .. "-->" ..checkSum, 30)
@ -319,7 +347,7 @@ function xFlags.evaluateZone(theZone)
end
theZone.flagChecksum = checkSum
else
if xFlags.verbose or theZone.verbose then
if xFlags.hiVerbose and (xFlags.verbose or theZone.verbose) then
trigger.action.outText("+++xFlag: no change, checksum is |" .. checkSum .. "| for <" .. theZone.name .. ">", 10)
end
end
@ -337,7 +365,7 @@ function xFlags.evaluateZone(theZone)
-- now see if we bang the output according to method
if evalResult then
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlag: success bang! on <" .. theZone.xSuccess .. "> for <" .. theZone.name .. ">", 30)
trigger.action.outText("+++xFlag: success bang! on <" .. theZone.xSuccess .. "> for <" .. theZone.name .. "> with method <" .. theZone.xMethod .. ">", 30)
end
cfxZones.pollFlag(theZone.xSuccess, theZone.xMethod, theZone)
theZone.xHasFired = true
@ -351,8 +379,25 @@ function xFlags.update()
timer.scheduleFunction(xFlags.update, {}, timer.getTime() + 1/xFlags.ups)
for idx, theZone in pairs (xFlags.xFlagZones) do
-- see if we should suspend
if cfxZones.testZoneFlag(theZone, theZone.xtriggerOnFlag, "change", "xlastTriggerOnValue") then
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlg: enabling " .. theZone.name, 30)
end
theZone.xSuspended = false
end
if cfxZones.testZoneFlag(theZone, theZone.xtriggerOffFlag, "change", "xlastTriggerOffValue") then
if xFlags.verbose or theZone.verbose then
trigger.action.outText("+++xFlg: DISabling " .. theZone.name, 30)
end
theZone.xSuspended = true
end
-- see if they should fire
xFlags.evaluateZone(theZone)
if not theZone.xSuspended then
xFlags.evaluateZone(theZone)
end
-- see if they should reset
if theZone.xReset then

Binary file not shown.

Binary file not shown.