mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 1.5.0
- groundExplosion - Liveries for CivAir - too many others to list
This commit is contained in:
parent
c3ba1e7c05
commit
a3cffa58d1
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
rndFlags = {}
|
rndFlags = {}
|
||||||
rndFlags.version = "1.4.1"
|
rndFlags.version = "2.0.0"
|
||||||
rndFlags.verbose = false
|
rndFlags.verbose = false
|
||||||
rndFlags.requiredLibs = {
|
rndFlags.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -33,6 +33,7 @@ rndFlags.requiredLibs = {
|
|||||||
- minor clean-up
|
- minor clean-up
|
||||||
1.4.0 - persistence
|
1.4.0 - persistence
|
||||||
1.4.1 - a little less verbosity
|
1.4.1 - a little less verbosity
|
||||||
|
2.0.0 - dmlZones, OOP
|
||||||
|
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
@ -59,14 +60,14 @@ end
|
|||||||
--
|
--
|
||||||
function rndFlags.createRNDWithZone(theZone)
|
function rndFlags.createRNDWithZone(theZone)
|
||||||
local flags = ""
|
local flags = ""
|
||||||
if cfxZones.hasProperty(theZone, "RND!") then
|
if theZone:hasProperty("RND!") then
|
||||||
flags = cfxZones.getStringFromZoneProperty(theZone, "RND!", "")
|
flags = theZone:getStringFromZoneProperty("RND!", "")
|
||||||
elseif cfxZones.hasProperty(theZone, "flags!") then
|
elseif theZone:hasProperty("flags!") then
|
||||||
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: deprecated 'flags!' usage, use 'RND!' instead.", 30)
|
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: deprecated 'flags!' usage, use 'RND!' instead.", 30)
|
||||||
flags = cfxZones.getStringFromZoneProperty(theZone, "flags!", "")
|
flags = theZone:getStringFromZoneProperty("flags!", "")
|
||||||
elseif cfxZones.hasProperty(theZone, "flags") then
|
elseif theZone:hasProperty("flags") then
|
||||||
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: deprecated 'flags' (no bang) usage, use 'RND!' instead.", 30)
|
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: deprecated 'flags' (no bang) usage, use 'RND!' instead.", 30)
|
||||||
flags = cfxZones.getStringFromZoneProperty(theZone, "flags", "")
|
flags = theZone:getStringFromZoneProperty("flags", "")
|
||||||
else
|
else
|
||||||
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: no flags defined!", 30)
|
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: no flags defined!", 30)
|
||||||
end
|
end
|
||||||
@ -78,73 +79,65 @@ function rndFlags.createRNDWithZone(theZone)
|
|||||||
trigger.action.outText("+++RND: output set for <" .. theZone.name .. "> is <" .. flags .. ">",30)
|
trigger.action.outText("+++RND: output set for <" .. theZone.name .. "> is <" .. flags .. ">",30)
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.pollSizeMin, theZone.pollSize = cfxZones.getPositiveRangeFromZoneProperty(theZone, "pollSize", 1)
|
theZone.pollSizeMin, theZone.pollSize = theZone:getPositiveRangeFromZoneProperty("pollSize", 1)
|
||||||
if rndFlags.verbose or theZone.verbose then
|
if rndFlags.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++RND: pollSize is <" .. theZone.pollSizeMin .. ", " .. theZone.pollSize .. ">", 30)
|
trigger.action.outText("+++RND: pollSize is <" .. theZone.pollSizeMin .. ", " .. theZone.pollSize .. ">", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
theZone.remove = theZone:getBoolFromZoneProperty("remove", false)
|
||||||
theZone.remove = cfxZones.getBoolFromZoneProperty(theZone, "remove", false)
|
theZone.rndTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||||
|
|
||||||
-- watchflag:
|
if theZone:hasProperty("rndTriggerMethod") then
|
||||||
-- triggerMethod
|
theZone.rndTriggerMethod = theZone:getStringFromZoneProperty("rndTriggerMethod", "change")
|
||||||
theZone.rndTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "rndTriggerMethod") then
|
|
||||||
theZone.rndTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "rndTriggerMethod", "change")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- trigger flag
|
-- trigger flag
|
||||||
if cfxZones.hasProperty(theZone, "f?") then
|
if theZone:hasProperty("f?") then
|
||||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
|
theZone.triggerFlag = theZone:getStringFromZoneProperty("f?", "none")
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "in?") then
|
if theZone:hasProperty("in?") then
|
||||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none")
|
theZone.triggerFlag = theZone:getStringFromZoneProperty("in?", "none")
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "rndPoll?") then
|
if theZone:hasProperty("rndPoll?") then
|
||||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "rndPoll?", "none")
|
theZone.triggerFlag = theZone:getStringFromZoneProperty("rndPoll?", "none")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if theZone.triggerFlag then
|
if theZone.triggerFlag then
|
||||||
theZone.lastTriggerValue = cfxZones.getFlagValue(theZone.triggerFlag, theZone)
|
theZone.lastTriggerValue = theZone:getFlagValue(theZone.triggerFlag)
|
||||||
if rndFlags.verbose or theZone.verbose then
|
if rndFlags.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++RND: randomizer in <" .. theZone:getName() .. "> triggers on flag <" .. theZone.triggerFlag .. ">", 30)
|
trigger.action.outText("+++RND: randomizer in <" .. theZone:getName() .. "> triggers on flag <" .. theZone.triggerFlag .. ">", 30)
|
||||||
end
|
end
|
||||||
--trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value
|
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false)
|
||||||
|
|
||||||
if not theZone.onStart and not theZone.triggerFlag then
|
if not theZone.onStart and not theZone.triggerFlag then
|
||||||
-- theZone.onStart = true
|
trigger.action.outText("+++RND - WARNING: no triggers and no onStart, RND in <" .. theZone.name .. "> can't be triggered.", 30)
|
||||||
if true or theZone.verbose or rndFlags.verbose then
|
|
||||||
trigger.action.outText("+++RND - WARNING: no triggers and no onStart, RND in <" .. theZone.name .. "> can't be triggered.", 30)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
|
theZone.rndMethod = theZone:getStringFromZoneProperty("method", "inc")
|
||||||
if cfxZones.hasProperty(theZone, "rndMethod") then
|
if theZone:hasProperty("rndMethod") then
|
||||||
theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "rndMethod", "inc")
|
theZone.rndMethod = theZone:getStringFromZoneProperty("rndMethod", "inc")
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.reshuffle = cfxZones.getBoolFromZoneProperty(theZone, "reshuffle", false)
|
theZone.reshuffle = theZone:getBoolFromZoneProperty("reshuffle", false)
|
||||||
if theZone.reshuffle then
|
if theZone.reshuffle then
|
||||||
-- create a backup copy we can reshuffle from
|
-- create a backup copy we can reshuffle from
|
||||||
theZone.flagStore = dcsCommon.copyArray(theFlags)
|
theZone.flagStore = dcsCommon.copyArray(theFlags)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- done flag OLD, to be deprecated
|
-- done flag OLD, to be deprecated
|
||||||
if cfxZones.hasProperty(theZone, "done+1") then
|
if theZone:hasProperty("done+1") then
|
||||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "<none>")
|
theZone.doneFlag = theZone:getStringFromZoneProperty("done+1", "<none>")
|
||||||
|
trigger.action.outText("Warning: RND zone <" .. theZone.name .. "> uses depreceated 'done+1'.", 30)
|
||||||
|
|
||||||
-- now NEW replacements
|
-- now NEW replacements
|
||||||
elseif cfxZones.hasProperty(theZone, "done!") then
|
elseif theZone:hasProperty("done!") then
|
||||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done!", "<none>")
|
theZone.doneFlag = theZone:getStringFromZoneProperty("done!", "<none>")
|
||||||
elseif cfxZones.hasProperty(theZone, "rndDone!") then
|
elseif theZone:hasProperty("rndDone!") then
|
||||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "rndDone!", "<none>")
|
theZone.doneFlag = theZone.getStringFromZoneProperty("rndDone!", "<none>")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -210,7 +203,7 @@ function rndFlags.fire(theZone)
|
|||||||
trigger.action.outText("+++RND: polling " .. theFlag .. " with " .. theZone.rndMethod, 30)
|
trigger.action.outText("+++RND: polling " .. theFlag .. " with " .. theZone.rndMethod, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
cfxZones.pollFlag(theFlag, theZone.rndMethod, theZone)
|
theZone:pollFlag(theFlag, theZone.rndMethod)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- remove if requested
|
-- remove if requested
|
||||||
@ -317,9 +310,7 @@ function rndFlags.readConfigZone()
|
|||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
rndFlags.verbose = theZone.verbose
|
||||||
rndFlags.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
|
||||||
|
|
||||||
if rndFlags.verbose then
|
if rndFlags.verbose then
|
||||||
trigger.action.outText("***RND: read config", 30)
|
trigger.action.outText("***RND: read config", 30)
|
||||||
end
|
end
|
||||||
@ -349,17 +340,15 @@ function rndFlags.start()
|
|||||||
-- now create an rnd gen for each one and add them
|
-- now create an rnd gen for each one and add them
|
||||||
-- to our watchlist
|
-- to our watchlist
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
rndFlags.createRNDWithZone(aZone) -- process attribute and add to zone
|
rndFlags.createRNDWithZone(aZone)
|
||||||
rndFlags.addRNDZone(aZone) -- remember it so we can smoke it
|
rndFlags.addRNDZone(aZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- obsolete here
|
-- obsolete here
|
||||||
attrZones = cfxZones.getZonesWithAttributeNamed("RND")
|
attrZones = cfxZones.getZonesWithAttributeNamed("RND")
|
||||||
-- now create an rnd gen for each one and add them
|
|
||||||
-- to our watchlist
|
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
rndFlags.createRNDWithZone(aZone) -- process attribute and add to zone
|
rndFlags.createRNDWithZone(aZone)
|
||||||
rndFlags.addRNDZone(aZone) -- remember it so we can smoke it
|
rndFlags.addRNDZone(aZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- persistence
|
-- persistence
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
tdz = {}
|
tdz = {}
|
||||||
tdz.version = "0.9.0dev"
|
tdz.version = "1.0.0"
|
||||||
tdz.requiredLibs = {
|
tdz.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
"cfxZones", -- Zones, of course
|
"cfxZones", -- Zones, of course
|
||||||
}
|
}
|
||||||
|
--[[--
|
||||||
|
VERSION HISTORY
|
||||||
|
1.0.0 - Initial version
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
tdz.allTdz = {}
|
tdz.allTdz = {}
|
||||||
tdz.watchlist = {}
|
tdz.watchlist = {}
|
||||||
tdz.watching = false
|
tdz.watching = false
|
||||||
@ -52,31 +58,7 @@ function tdz.translatePoly(thePoly, v) -- straight rot, translate to 0 first
|
|||||||
if aPoint.z then aPoint.z = aPoint.z + v.z end
|
if aPoint.z then aPoint.z = aPoint.z + v.z end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--[[--
|
|
||||||
function tdz.frameRwy(center, length, width, rads, a, b) -- bearing in rads
|
|
||||||
if not a then a = 0 end
|
|
||||||
if not b then b = 1 end
|
|
||||||
|
|
||||||
-- create a 0-rotated centered poly
|
|
||||||
local poly = {}
|
|
||||||
local half = length / 2
|
|
||||||
local leftEdge = -half
|
|
||||||
poly[4] = { x = leftEdge + a * length, z = width / 2, y = 0}
|
|
||||||
poly[3] = { x = leftEdge + b * length, z = width / 2, y = 0}
|
|
||||||
poly[2] = { x = leftEdge + b * length, z = -width / 2, y = 0}
|
|
||||||
poly[1] = { x = leftEdge + a * length, z = -width / 2, y = 0}
|
|
||||||
-- move it to center in map
|
|
||||||
tdz.translatePoly(poly, center)
|
|
||||||
|
|
||||||
-- rotate it
|
|
||||||
tdz.rotateXZPolyAroundCenterInRads(poly, center, rads)
|
|
||||||
|
|
||||||
-- frame it
|
|
||||||
local mId = dcsCommon.numberUUID()
|
|
||||||
trigger.action.quadToAll(-1, mId, poly[1], poly[2], poly[3], poly[4], {1, 0, 0, 1}, {1, 0, 0, .5}, 3) -- dotted line, red
|
|
||||||
|
|
||||||
end
|
|
||||||
--]]--
|
|
||||||
function tdz.calcTDZone(name, center, length, width, rads, a, b)
|
function tdz.calcTDZone(name, center, length, width, rads, a, b)
|
||||||
if not a then a = 0 end
|
if not a then a = 0 end
|
||||||
if not b then b = 1 end
|
if not b then b = 1 end
|
||||||
@ -94,7 +76,7 @@ function tdz.calcTDZone(name, center, length, width, rads, a, b)
|
|||||||
tdz.rotateXZPolyAroundCenterInRads(poly, center, rads)
|
tdz.rotateXZPolyAroundCenterInRads(poly, center, rads)
|
||||||
-- make it a dml zone
|
-- make it a dml zone
|
||||||
local theNewZone = cfxZones.createSimplePolyZone(name, center, poly)
|
local theNewZone = cfxZones.createSimplePolyZone(name, center, poly)
|
||||||
return theNewZone--, left, right
|
return theNewZone
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -181,7 +163,6 @@ function tdz.playerLanded(theUnit, playerName)
|
|||||||
-- make sure unit names match?
|
-- make sure unit names match?
|
||||||
local entry = tdz.watchlist[playerName]
|
local entry = tdz.watchlist[playerName]
|
||||||
entry.hops = entry.hops + 1 -- uh oh.
|
entry.hops = entry.hops + 1 -- uh oh.
|
||||||
-- trigger.action.outText("Bump!")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- we may want to filter helicopters
|
-- we may want to filter helicopters
|
||||||
@ -226,7 +207,6 @@ function tdz.playerLanded(theUnit, playerName)
|
|||||||
if dOpHdg < dHdg then
|
if dOpHdg < dHdg then
|
||||||
opposite = true
|
opposite = true
|
||||||
dHdg = dOpHdg
|
dHdg = dOpHdg
|
||||||
trigger.action.outText("opposite rwy detected", 30)
|
|
||||||
end
|
end
|
||||||
if dHdg > math.pi * 1.5 then -- > 270+
|
if dHdg > math.pi * 1.5 then -- > 270+
|
||||||
dHdg = dHdg - math.pi * 1.5
|
dHdg = dHdg - math.pi * 1.5
|
||||||
|
|||||||
@ -1,18 +1,34 @@
|
|||||||
bombRange = {}
|
bombRange = {}
|
||||||
bombRange.version = "1.0.0"
|
bombRange.version = "1.1.0"
|
||||||
bombRange.dh = 1 -- meters above ground level burst
|
bombRange.dh = 1 -- meters above ground level burst
|
||||||
|
|
||||||
bombRange.requiredLibs = {
|
bombRange.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
"cfxZones", -- Zones, of course
|
"cfxZones", -- Zones, of course
|
||||||
}
|
}
|
||||||
|
--[[--
|
||||||
|
VERSION HISTORY
|
||||||
|
1.0.0 - Initial version
|
||||||
|
1.1.0 - collector logic for collating hits
|
||||||
|
*after* impact on high-resolution scans (30fps)
|
||||||
|
set resolution to 30 ups by default
|
||||||
|
order of events: check kills against dropping projectiles
|
||||||
|
collecd dead, and compare against missing erdnance while they are fresh
|
||||||
|
GC
|
||||||
|
interpolate hits on dead when looking at kills and projectile does
|
||||||
|
not exist
|
||||||
|
also sampling kill events
|
||||||
|
|
||||||
|
--]]--
|
||||||
bombRange.bombs = {} -- live tracking
|
bombRange.bombs = {} -- live tracking
|
||||||
|
bombRange.collector = {} -- post-impact collections for 0.5 secs
|
||||||
bombRange.ranges = {} -- all bomb ranges
|
bombRange.ranges = {} -- all bomb ranges
|
||||||
bombRange.playerData = {} -- player accumulated data
|
bombRange.playerData = {} -- player accumulated data
|
||||||
bombRange.unitComms = {} -- command interface per unit
|
bombRange.unitComms = {} -- command interface per unit
|
||||||
bombRange.tracking = false -- if true, we are tracking projectiles
|
bombRange.tracking = false -- if true, we are tracking projectiles
|
||||||
bombRange.myStatics = {} -- indexed by id
|
bombRange.myStatics = {} -- indexed by id
|
||||||
|
bombRange.killDist = 20 -- meters, if caught within that of kill event, this weapon was the culprit
|
||||||
|
bombRange.freshKills = {} -- at max 1 second old?
|
||||||
|
|
||||||
function bombRange.addBomb(theBomb)
|
function bombRange.addBomb(theBomb)
|
||||||
table.insert(bombRange.bombs, theBomb)
|
table.insert(bombRange.bombs, theBomb)
|
||||||
@ -44,7 +60,7 @@ function bombRange.createRange(theZone) -- has bombRange attribte to mark it
|
|||||||
end
|
end
|
||||||
theZone.details = theZone:getBoolFromZoneProperty("details", false)
|
theZone.details = theZone:getBoolFromZoneProperty("details", false)
|
||||||
theZone.reporter = theZone:getBoolFromZoneProperty("reporter", true)
|
theZone.reporter = theZone:getBoolFromZoneProperty("reporter", true)
|
||||||
theZone.reportName = theZone:getBoolFromZoneProperty("reportName", true)
|
theZone.reportName = theZone:getBoolFromZoneProperty("reportName", false)
|
||||||
theZone.smokeHits = theZone:getBoolFromZoneProperty("smokeHits", false)
|
theZone.smokeHits = theZone:getBoolFromZoneProperty("smokeHits", false)
|
||||||
theZone.smokeColor = theZone:getSmokeColorStringFromZoneProperty("smokeColor", "blue")
|
theZone.smokeColor = theZone:getSmokeColorStringFromZoneProperty("smokeColor", "blue")
|
||||||
theZone.flagHits = theZone:getBoolFromZoneProperty("flagHits", false)
|
theZone.flagHits = theZone:getBoolFromZoneProperty("flagHits", false)
|
||||||
@ -237,26 +253,51 @@ end
|
|||||||
-- Event Proccing
|
-- Event Proccing
|
||||||
--
|
--
|
||||||
function bombRange.suspectedHit(weapon, target)
|
function bombRange.suspectedHit(weapon, target)
|
||||||
if not bombRange.tracking then
|
local wType = weapon:getTypeName()
|
||||||
return
|
|
||||||
end
|
|
||||||
if not target then return end
|
if not target then return end
|
||||||
local theType = target:getTypeName()
|
if target:getCategory() == 5 then -- scenery
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local theDesc = target:getDesc()
|
||||||
|
local theType = theDesc.typeName -- getTypeName gets display name
|
||||||
|
-- filter statics that we want to ignore
|
||||||
for idx, aType in pairs(bombRange.filterTypes) do
|
for idx, aType in pairs(bombRange.filterTypes) do
|
||||||
if theType == aType then return end
|
if theType == aType then
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- try and match target to my known statics, exit if match
|
-- try and match target to my known statics, exit if match
|
||||||
if not target.getID then return end -- units have no getID!
|
if target.getID then -- units have no getID, so skip for those
|
||||||
local theID = tonumber(target:getID())
|
local theID = tonumber(target:getID())
|
||||||
if bombRange.myStatics[theID] then
|
if bombRange.myStatics[theID] then
|
||||||
return
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- look through the tracked weapons for a match
|
-- look through the collector (recent impacted) first
|
||||||
local filtered = {}
|
|
||||||
local hasfound = false
|
local hasfound = false
|
||||||
|
local theID
|
||||||
|
for idx, b in pairs(bombRange.collector) do
|
||||||
|
if b.weapon == weapon then
|
||||||
|
b.pos = target:getPoint()
|
||||||
|
bombRange.impacted(b, target) -- use this for impact
|
||||||
|
theID = b.ID
|
||||||
|
hasfound = true
|
||||||
|
-- trigger.action.outText("susHit: filtering COLLECTED b <" .. b.name .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if hasfound then
|
||||||
|
bombRange.collector[theID] = nil -- remove from collector
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- look through the tracked weapons for a match next
|
||||||
|
if not bombRange.tracking then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local filtered = {}
|
||||||
for idx, b in pairs (bombRange.bombs) do
|
for idx, b in pairs (bombRange.bombs) do
|
||||||
if b.weapon == weapon then
|
if b.weapon == weapon then
|
||||||
hasfound = true
|
hasfound = true
|
||||||
@ -264,6 +305,8 @@ function bombRange.suspectedHit(weapon, target)
|
|||||||
b.pos = weapon:getPoint()
|
b.pos = weapon:getPoint()
|
||||||
b.v = weapon:getVelocity()
|
b.v = weapon:getVelocity()
|
||||||
bombRange.impacted(b, target)
|
bombRange.impacted(b, target)
|
||||||
|
|
||||||
|
-- trigger.action.outText("susHit: filtering live b <" .. b.name .. ">", 30)
|
||||||
else
|
else
|
||||||
table.insert(filtered, b)
|
table.insert(filtered, b)
|
||||||
end
|
end
|
||||||
@ -273,16 +316,106 @@ function bombRange.suspectedHit(weapon, target)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function bombRange.suspectedKill(target)
|
||||||
|
-- some unit got killed, let's see if our munitions in the collector
|
||||||
|
-- phase are close by, i.e. they have disappeared
|
||||||
|
if not target then return end
|
||||||
|
|
||||||
|
local theDesc = target:getDesc()
|
||||||
|
local theType = theDesc.typeName -- getTypeName gets display name
|
||||||
|
-- filter statics that we want to ignore
|
||||||
|
for idx, aType in pairs(bombRange.filterTypes) do
|
||||||
|
if theType == aType then return end
|
||||||
|
end
|
||||||
|
|
||||||
|
local hasfound = nil
|
||||||
|
local theID
|
||||||
|
local pk = target:getPoint()
|
||||||
|
local now = timer.getTime()
|
||||||
|
|
||||||
|
-- first, search all currently running projectiles, and check for proximity
|
||||||
|
local filtered = {}
|
||||||
|
for idx, b in pairs(bombRange.bombs) do
|
||||||
|
local wp
|
||||||
|
if Weapon.isExist(b.weapon) then
|
||||||
|
wp = b.weapon:getPoint()
|
||||||
|
else
|
||||||
|
local td = now - b.t -- time delta
|
||||||
|
-- calculate current loc from last velocity and
|
||||||
|
-- time
|
||||||
|
local moveV = dcsCommon.vMultScalar(b.v, td)
|
||||||
|
wp = dcsCommon.vAdd(b.pos, moveV)
|
||||||
|
end
|
||||||
|
local delta = dcsCommon.dist(wp, pk)
|
||||||
|
-- now use the line wp-wp+v and calculate distance
|
||||||
|
-- of pk to that line.
|
||||||
|
local wp2 = dcsCommon.vAdd(b.pos, b.v)
|
||||||
|
local delta2 = dcsCommon.distanceOfPointPToLineXZ(pk, b.pos, wp2)
|
||||||
|
|
||||||
|
if delta < bombRange.killDist or delta2 < bombRange.killDist then
|
||||||
|
b.pos = pk
|
||||||
|
bombRange.impacted(b, target)
|
||||||
|
hasfound = true
|
||||||
|
-- trigger.action.outText("filtering b: <" .. b.name .. ">", 30)
|
||||||
|
else
|
||||||
|
table.insert(filtered, b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
bombRange.bombs = filtered
|
||||||
|
if hasfound then
|
||||||
|
-- trigger.action.outText("protocol: removed LIVING weapon from roster after impacted() invocation for non-nil target in suspectedKill", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- now check the projectiles that have already impacted
|
||||||
|
for idx, b in pairs(bombRange.collector) do
|
||||||
|
local dist = dcsCommon.dist(b.pos, pk)
|
||||||
|
local wp2 = dcsCommon.vAdd(b.pos, b.v)
|
||||||
|
local delta2 = dcsCommon.distanceOfPointPToLineXZ(pk, b.pos, wp2)
|
||||||
|
|
||||||
|
if dist < bombRange.killDist or delta2 < bombRange.killDist then
|
||||||
|
-- yeah, *you* killed them!
|
||||||
|
b.pos = pk
|
||||||
|
bombRange.impacted(b, target) -- use this for impact
|
||||||
|
theID = b.ID
|
||||||
|
hasfound = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if hasfound then -- remove from collector, hit attributed
|
||||||
|
bombRange.collector[theID] = nil -- remove from collector
|
||||||
|
-- trigger.action.outText("protocol: removed COLL weapon from roster after impacted() invocation for non-nil target in suspectedKill", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function bombRange:onEvent(event)
|
function bombRange:onEvent(event)
|
||||||
if not event.initiator then return end
|
if not event.initiator then return end
|
||||||
local theUnit = event.initiator
|
local theUnit = event.initiator
|
||||||
|
|
||||||
if event.id == 2 then -- hit
|
if event.id == 2 then -- hit: weapon still exists
|
||||||
if not event.weapon then return end
|
if not event.weapon then return end
|
||||||
bombRange.suspectedHit(event.weapon, event.target)
|
bombRange.suspectedHit(event.weapon, event.target)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if event.id == 28 then -- kill: similar to hit, but due to new mechanics not reliable
|
||||||
|
if not event.weapon then return end
|
||||||
|
bombRange.suspectedHit(event.weapon, event.target)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
if event.id == 8 then -- dead
|
||||||
|
-- these events can come *before* weapon disappears
|
||||||
|
local killDat = {}
|
||||||
|
killDat.victim = event.initiator
|
||||||
|
killDat.p = event.initiator:getPoint()
|
||||||
|
killDat.when = timer.getTime()
|
||||||
|
killDat.name = dcsCommon.uuid("vic")
|
||||||
|
bombRange.freshKills[killDat.name] = killDat
|
||||||
|
bombRange.suspectedKill(event.initiator)
|
||||||
|
end
|
||||||
|
|
||||||
local uName = nil
|
local uName = nil
|
||||||
local pName = nil
|
local pName = nil
|
||||||
if theUnit.getPlayerName and theUnit:getPlayerName() ~= nil then
|
if theUnit.getPlayerName and theUnit:getPlayerName() ~= nil then
|
||||||
@ -314,6 +447,7 @@ function bombRange:onEvent(event)
|
|||||||
b.weapon = w
|
b.weapon = w
|
||||||
b.released = timer.getTime()
|
b.released = timer.getTime()
|
||||||
b.relPos = b.pos
|
b.relPos = b.pos
|
||||||
|
b.ID = dcsCommon.uuid("bomb")
|
||||||
table.insert(bombRange.bombs, b)
|
table.insert(bombRange.bombs, b)
|
||||||
if not bombRange.tracking then
|
if not bombRange.tracking then
|
||||||
timer.scheduleFunction(bombRange.updateBombs, {}, timer.getTime() + 1/bombRange.ups)
|
timer.scheduleFunction(bombRange.updateBombs, {}, timer.getTime() + 1/bombRange.ups)
|
||||||
@ -336,14 +470,25 @@ end
|
|||||||
--
|
--
|
||||||
-- Update
|
-- Update
|
||||||
--
|
--
|
||||||
function bombRange.impacted(weapon, target)
|
function bombRange.impacted(weapon, target, finalPass)
|
||||||
local targetName = nil
|
local targetName = nil
|
||||||
local ipos = weapon.pos -- default to weapon location
|
if target then
|
||||||
if target then
|
|
||||||
ipos = target:getPoint()
|
|
||||||
targetName = target:getDesc()
|
targetName = target:getDesc()
|
||||||
if targetName then targetName = targetName.displayName end
|
if targetName then targetName = targetName.displayName end
|
||||||
if not targetName then targetName = target:getTypeName() end
|
if not targetName then targetName = target:getTypeName() end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- local s = "Entering impacted() with weapon = <" .. weapon.name .. ">"
|
||||||
|
-- if target then
|
||||||
|
-- s = s .. " AND target = <" .. targetName .. ">"
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- when we enter, weapon has ipacted target - if target is non-nil
|
||||||
|
-- what we need to determine is if that target is inside a zone
|
||||||
|
|
||||||
|
local ipos = weapon.pos -- default to weapon location
|
||||||
|
if target then
|
||||||
|
ipos = target:getPoint() -- we make the target loc the impact point
|
||||||
else
|
else
|
||||||
-- not an object hit, interpolate the impact point on ground:
|
-- not an object hit, interpolate the impact point on ground:
|
||||||
-- calculate impact point. we use the linear equation
|
-- calculate impact point. we use the linear equation
|
||||||
@ -375,6 +520,7 @@ function bombRange.impacted(weapon, target)
|
|||||||
trigger.action.outText("+++bRng: nil <theRange> on eval. skipping.", 30)
|
trigger.action.outText("+++bRng: nil <theRange> on eval. skipping.", 30)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if minDist > theRange.clipDist then
|
if minDist > theRange.clipDist then
|
||||||
-- no taget zone inside clip dist. disregard this one, too far off
|
-- no taget zone inside clip dist. disregard this one, too far off
|
||||||
if bombRange.reportLongMisses then
|
if bombRange.reportLongMisses then
|
||||||
@ -383,11 +529,11 @@ function bombRange.impacted(weapon, target)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if theRange.smokeHits then
|
if (not target) and theRange.smokeHits then
|
||||||
trigger.action.smoke(ipos, theRange.smokeColor)
|
trigger.action.smoke(ipos, theRange.smokeColor)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (not target) and theRange.flagHits then -- only ground imparts are flagged
|
if (not target) and theRange.flagHits then -- only ground impacts are flagged
|
||||||
local cty = dcsCommon.getACountryForCoalition(0) -- some neutral county
|
local cty = dcsCommon.getACountryForCoalition(0) -- some neutral county
|
||||||
local p = {x=ipos.x, y=ipos.z}
|
local p = {x=ipos.x, y=ipos.z}
|
||||||
local theStaticData = dcsCommon.createStaticObjectData(dcsCommon.uuid(weapon.type .. " impact"), theRange.flagType)
|
local theStaticData = dcsCommon.createStaticObjectData(dcsCommon.uuid(weapon.type .. " impact"), theRange.flagType)
|
||||||
@ -395,8 +541,37 @@ function bombRange.impacted(weapon, target)
|
|||||||
local theObject = coalition.addStaticObject(cty, theStaticData)
|
local theObject = coalition.addStaticObject(cty, theStaticData)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local impactInside = theRange:pointInZone(ipos)
|
||||||
|
--[[--
|
||||||
|
if target and (not impactInside) then
|
||||||
|
trigger.action.outText("Hit on target <" .. targetName .. "> outside of zone <" .. theRange.name .. ">. should exit unless final impact", 30)
|
||||||
|
-- find closest range to object that was hit
|
||||||
|
local closest = nil
|
||||||
|
local shortest = math.huge
|
||||||
|
local tp = target:getPoint()
|
||||||
|
for idx, aRange in pairs(bombRange.ranges) do
|
||||||
|
local zp = aRange:getPoint()
|
||||||
|
local zDist = dcsCommon.distFlat(zp, tp)
|
||||||
|
if zDist < shortest then
|
||||||
|
shortest = zDist
|
||||||
|
closest = aRange
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
trigger.action.outText("re-check: closest range to target now is <" .. closest.name ..">", 30)
|
||||||
|
if closest:pointInZone(tp) then
|
||||||
|
trigger.action.outText("target <" .. targetName .. "> is INSIDE this range, d = <" .. math.floor(shortest) .. ">", 30)
|
||||||
|
else
|
||||||
|
trigger.action.outText("targed indeed outside, d = <" .. math.floor(shortest) .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
if finalPass then trigger.action.outText("IS final pass.", 30) end
|
||||||
|
end
|
||||||
|
--]]--
|
||||||
if theRange.reporter and theRange.details then
|
if theRange.reporter and theRange.details then
|
||||||
local t = math.floor((timer.getTime() - weapon.released) * 10) / 10
|
local ipc = weapon.impacted
|
||||||
|
if not ipc then ipc = timer.getTime() end
|
||||||
|
local t = math.floor((ipc - weapon.released) * 10) / 10
|
||||||
local v = math.floor(dcsCommon.vMag(weapon.v))
|
local v = math.floor(dcsCommon.vMag(weapon.v))
|
||||||
local tDist = dcsCommon.dist(ipos, weapon.relPos)/1000
|
local tDist = dcsCommon.dist(ipos, weapon.relPos)/1000
|
||||||
tDist = math.floor(tDist*100) /100
|
tDist = math.floor(tDist*100) /100
|
||||||
@ -404,7 +579,7 @@ function bombRange.impacted(weapon, target)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local msg = ""
|
local msg = ""
|
||||||
if theRange:pointInZone(ipos) then
|
if impactInside then
|
||||||
local percentage = 0
|
local percentage = 0
|
||||||
if theRange.isPoly then
|
if theRange.isPoly then
|
||||||
percentage = 100
|
percentage = 100
|
||||||
@ -430,29 +605,45 @@ function bombRange.impacted(weapon, target)
|
|||||||
bombRange.addImpactForWeapon(weapon, true, percentage)
|
bombRange.addImpactForWeapon(weapon, true, percentage)
|
||||||
else
|
else
|
||||||
msg = "Outside target area"
|
msg = "Outside target area"
|
||||||
|
-- if target then msg = msg .. " (EVEN THOUGH TGT = " .. target:getName() .. ")" end
|
||||||
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
if theRange.reportName then msg = msg .. " " .. theRange.name end
|
||||||
if theRange.details then msg = msg .. "(off-center by " .. math.floor(minDist *10)/10 .. " m)" end
|
if theRange.details then msg = msg .. " (off-center by " .. math.floor(minDist *10)/10 .. " m)" end
|
||||||
msg = msg .. ", no hit."
|
msg = msg .. ", no hit."
|
||||||
bombRange.addImpactForWeapon(weapon, false, 0)
|
bombRange.addImpactForWeapon(weapon, false, 0)
|
||||||
end
|
end
|
||||||
if theRange.reporter then
|
if theRange.reporter then
|
||||||
trigger.action.outTextForGroup(weapon.gID,msg , 30)
|
trigger.action.outTextForGroup(weapon.gID,msg , 30)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bombRange.uncollect(theID)
|
||||||
|
-- if this is still here, no hit was registered against the weapon
|
||||||
|
-- and we simply use the impact
|
||||||
|
local b = bombRange.collector[theID]
|
||||||
|
if b then
|
||||||
|
bombRange.collector[theID] = nil
|
||||||
|
bombRange.impacted(b, nil, true) -- final pass
|
||||||
|
-- trigger.action.outText("(final impact)", 30)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function bombRange.updateBombs()
|
function bombRange.updateBombs()
|
||||||
|
local now = timer.getTime()
|
||||||
local filtered = {}
|
local filtered = {}
|
||||||
for idx, theWeapon in pairs(bombRange.bombs) do
|
for idx, theWeapon in pairs(bombRange.bombs) do
|
||||||
if Weapon.isExist(theWeapon.weapon) then
|
if Weapon.isExist(theWeapon.weapon) then
|
||||||
-- update pos and vel
|
-- update pos and vel
|
||||||
theWeapon.pos = theWeapon.weapon:getPoint()
|
theWeapon.pos = theWeapon.weapon:getPoint()
|
||||||
theWeapon.v = theWeapon.weapon:getVelocity()
|
theWeapon.v = theWeapon.weapon:getVelocity()
|
||||||
|
theWeapon.t = now
|
||||||
table.insert(filtered, theWeapon)
|
table.insert(filtered, theWeapon)
|
||||||
else
|
else
|
||||||
-- interpolate the impact position from last position
|
-- put on collector to time out in 1 seconds to allow
|
||||||
bombRange.impacted(theWeapon)
|
-- asynch hits to still register for this weapon in MP
|
||||||
|
-- bombRange.impacted(theWeapon)
|
||||||
|
theWeapon.impacted = timer.getTime()
|
||||||
|
bombRange.collector[theWeapon.ID] = theWeapon --
|
||||||
|
timer.scheduleFunction(bombRange.uncollect, theWeapon.ID, timer.getTime() + 1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -468,6 +659,19 @@ function bombRange.updateBombs()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function bombRange.GC()
|
||||||
|
local cutOff = timer.getTime()
|
||||||
|
local filtered = {}
|
||||||
|
for name, killDat in pairs(bombRange.freshKills) do
|
||||||
|
if killDat.when + 2 < cutOff then
|
||||||
|
-- keep in set for two seconds after kill.when
|
||||||
|
filtered[name] = killDat
|
||||||
|
end
|
||||||
|
end
|
||||||
|
bombRange.freshKills = filtered
|
||||||
|
timer.scheduleFunction(bombRange.GC, {}, timer.getTime() + 10)
|
||||||
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- load & save data
|
-- load & save data
|
||||||
--
|
--
|
||||||
@ -508,7 +712,7 @@ function bombRange.readConfigZone()
|
|||||||
bombRange.filterTypes = dcsCommon.trimArray(theSet)
|
bombRange.filterTypes = dcsCommon.trimArray(theSet)
|
||||||
bombRange.reportLongMisses = theZone:getBoolFromZoneProperty("reportLongMisses", false)
|
bombRange.reportLongMisses = theZone:getBoolFromZoneProperty("reportLongMisses", false)
|
||||||
bombRange.mustCheckIn = theZone:getBoolFromZoneProperty("mustCheckIn", false)
|
bombRange.mustCheckIn = theZone:getBoolFromZoneProperty("mustCheckIn", false)
|
||||||
bombRange.ups = theZone:getNumberFromZoneProperty("ups", 20)
|
bombRange.ups = theZone:getNumberFromZoneProperty("ups", 30)
|
||||||
bombRange.menuTitle = theZone:getStringFromZoneProperty("menuTitle","Contact BOMB RANGE")
|
bombRange.menuTitle = theZone:getStringFromZoneProperty("menuTitle","Contact BOMB RANGE")
|
||||||
if theZone:hasProperty("signIn!") then
|
if theZone:hasProperty("signIn!") then
|
||||||
bombRange.signIn = theZone:getStringFromZoneProperty("signIn!", 30)
|
bombRange.signIn = theZone:getStringFromZoneProperty("signIn!", 30)
|
||||||
@ -551,6 +755,9 @@ function bombRange.start()
|
|||||||
-- add event handler
|
-- add event handler
|
||||||
world.addEventHandler(bombRange)
|
world.addEventHandler(bombRange)
|
||||||
|
|
||||||
|
-- start GC
|
||||||
|
bombRange.GC()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxObjectDestructDetector = {}
|
cfxObjectDestructDetector = {}
|
||||||
cfxObjectDestructDetector.version = "1.3.0"
|
cfxObjectDestructDetector.version = "2.0.0"
|
||||||
cfxObjectDestructDetector.verbose = false
|
cfxObjectDestructDetector.verbose = false
|
||||||
cfxObjectDestructDetector.requiredLibs = {
|
cfxObjectDestructDetector.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -12,11 +12,11 @@ cfxObjectDestructDetector.requiredLibs = {
|
|||||||
1.1.0 added support for method, f! and destroyed!
|
1.1.0 added support for method, f! and destroyed!
|
||||||
1.2.0 DML / Watchflag support
|
1.2.0 DML / Watchflag support
|
||||||
1.3.0 Persistence support
|
1.3.0 Persistence support
|
||||||
|
2.0.0 dmlZone OOP support
|
||||||
|
clean-up
|
||||||
Detect when an object with OBJECT ID as assigned in ME dies
|
re-wrote object determination to not be affected by
|
||||||
*** EXTENDS ZONES
|
ID changes (happens with map updates)
|
||||||
|
fail addZone when name property is missing
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
cfxObjectDestructDetector.objectZones = {}
|
cfxObjectDestructDetector.objectZones = {}
|
||||||
@ -31,7 +31,7 @@ end
|
|||||||
|
|
||||||
function cfxObjectDestructDetector.invokeCallbacksFor(zone)
|
function cfxObjectDestructDetector.invokeCallbacksFor(zone)
|
||||||
for idx, theCB in pairs (cfxObjectDestructDetector.callbacks) do
|
for idx, theCB in pairs (cfxObjectDestructDetector.callbacks) do
|
||||||
theCB(zone, zone.ID, zone.name)
|
theCB(zone, zone.ID, zone.name, zone.objName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -55,104 +55,55 @@ end
|
|||||||
-- processing of zones
|
-- processing of zones
|
||||||
--
|
--
|
||||||
function cfxObjectDestructDetector.processObjectDestructZone(aZone)
|
function cfxObjectDestructDetector.processObjectDestructZone(aZone)
|
||||||
aZone.name = cfxZones.getStringFromZoneProperty(aZone, "NAME", aZone.name)
|
if aZone:hasProperty("name") then
|
||||||
-- aZone.coalition = cfxZones.getCoalitionFromZoneProperty(aZone, "coalition", 0)
|
aZone.objName = string.upper(aZone:getStringFromZoneProperty("NAME", "default"))
|
||||||
aZone.ID = cfxZones.getNumberFromZoneProperty(aZone, "OBJECT ID", 1) -- THIS!
|
else
|
||||||
|
trigger.action.outText("+++OOD: Zone <" .. aZone.name .. "> lacks name attribute, ignored for destruct detection.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-- persistence interface
|
-- persistence interface
|
||||||
aZone.isDestroyed = false
|
aZone.isDestroyed = false
|
||||||
|
|
||||||
--[[-- old code, to be decom'd --]]--
|
aZone.oddMethod = aZone:getStringFromZoneProperty("method", "inc")
|
||||||
if cfxZones.hasProperty(aZone, "setFlag") then
|
if aZone:hasProperty("oddMethod") then
|
||||||
aZone.setFlag = cfxZones.getStringFromZoneProperty(aZone, "setFlag", "999")
|
aZone.oddMethod = aZone:getStringFromZoneProperty("oddMethod", "inc")
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "f=1") then
|
|
||||||
aZone.setFlag = cfxZones.getStringFromZoneProperty(aZone, "f=1", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "clearFlag") then
|
|
||||||
aZone.clearFlag = cfxZones.getStringFromZoneProperty(aZone, "clearFlag", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "f=0") then
|
|
||||||
aZone.clearFlag = cfxZones.getStringFromZoneProperty(aZone, "f=0", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "increaseFlag") then
|
|
||||||
aZone.increaseFlag = cfxZones.getStringFromZoneProperty(aZone, "increaseFlag", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "f+1") then
|
|
||||||
aZone.increaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f+1", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "decreaseFlag") then
|
|
||||||
aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "decreaseFlag", "999")
|
|
||||||
end
|
|
||||||
if cfxZones.hasProperty(aZone, "f-1") then
|
|
||||||
aZone.decreaseFlag = cfxZones.getStringFromZoneProperty(aZone, "f-1", "999")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- DML method support
|
if aZone:hasProperty("f!") then
|
||||||
aZone.oddMethod = cfxZones.getStringFromZoneProperty(aZone, "method", "inc")
|
aZone.outDestroyFlag = aZone:getStringFromZoneProperty("f!", "*none")
|
||||||
if cfxZones.hasProperty(aZone, "oddMethod") then
|
elseif aZone:hasProperty("destroyed!") then
|
||||||
aZone.oddMethod = cfxZones.getStringFromZoneProperty(aZone, "oddMethod", "inc")
|
aZone.outDestroyFlag = aZone:getStringFromZoneProperty("destroyed!", "*none")
|
||||||
end
|
elseif aZone:hasProperty("objectDestroyed!") then
|
||||||
|
aZone.outDestroyFlag = aZone:getStringFromZoneProperty( "objectDestroyed!", "*none")
|
||||||
|
|
||||||
-- we now always have that property
|
|
||||||
aZone.outDestroyFlag = cfxZones.getStringFromZoneProperty(aZone, "f!", "*none")
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(aZone, "destroyed!") then
|
|
||||||
aZone.outDestroyFlag = cfxZones.getStringFromZoneProperty(aZone, "destroyed!", "*none")
|
|
||||||
end
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(aZone, "objectDestroyed!") then
|
|
||||||
aZone.outDestroyFlag = cfxZones.getStringFromZoneProperty(aZone, "objectDestroyed!", "*none")
|
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
--
|
--
|
||||||
-- MAIN DETECTOR
|
-- ON EVENT
|
||||||
--
|
--
|
||||||
-- invoke callbacks when an object was destroyed
|
|
||||||
function cfxObjectDestructDetector:onEvent(event)
|
function cfxObjectDestructDetector:onEvent(event)
|
||||||
if event.id == world.event.S_EVENT_DEAD then
|
if event.id == world.event.S_EVENT_DEAD then
|
||||||
if not event.initiator then return end
|
if not event.initiator then return end
|
||||||
local id = event.initiator:getName()
|
local theObject = event.initiator
|
||||||
if not id then return end
|
local desc = theObject:getDesc()
|
||||||
|
if not desc then return end
|
||||||
|
local matchMe = desc.typeName -- we home in on object's typeName
|
||||||
|
if not matchMe then return end
|
||||||
|
matchMe = string.upper(matchMe)
|
||||||
|
|
||||||
for idx, aZone in pairs(cfxObjectDestructDetector.objectZones) do
|
for idx, aZone in pairs(cfxObjectDestructDetector.objectZones) do
|
||||||
if (not aZone.isDestroyed) and aZone.ID == id then
|
if (not aZone.isDestroyed) and aZone.objName == matchMe then
|
||||||
-- flag manipulation
|
|
||||||
-- OLD FLAG SUPPORT, SOON TO BE REMOVED
|
|
||||||
if aZone.setFlag then
|
|
||||||
trigger.action.setUserFlag(aZone.setFlag, 1)
|
|
||||||
end
|
|
||||||
if aZone.clearFlag then
|
|
||||||
trigger.action.setUserFlag(aZone.clearFlag, 0)
|
|
||||||
end
|
|
||||||
if aZone.increaseFlag then
|
|
||||||
local val = trigger.misc.getUserFlag(aZone.increaseFlag) + 1
|
|
||||||
trigger.action.setUserFlag(aZone.increaseFlag, val)
|
|
||||||
end
|
|
||||||
if aZone.decreaseFlag then
|
|
||||||
local val = trigger.misc.getUserFlag(aZone.decreaseFlag) - 1
|
|
||||||
trigger.action.setUserFlag(aZone.decreaseFlag, val)
|
|
||||||
end
|
|
||||||
-- END OF OLD CODE, TO BE REMOVED
|
|
||||||
|
|
||||||
-- support for banging
|
|
||||||
if aZone.outDestroyFlag then
|
if aZone.outDestroyFlag then
|
||||||
cfxZones.pollFlag(aZone.outDestroyFlag, aZone.oddMethod, aZone)
|
aZone:pollFlag(aZone.outDestroyFlag, aZone.oddMethod)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- invoke callbacks
|
-- invoke callbacks
|
||||||
cfxObjectDestructDetector.invokeCallbacksFor(aZone)
|
cfxObjectDestructDetector.invokeCallbacksFor(aZone)
|
||||||
if aZone.verbose or cfxObjectDestructDetector.verbose then
|
if aZone.verbose or cfxObjectDestructDetector.verbose then
|
||||||
trigger.action.outText("OBJECT KILL: " .. id, 30)
|
trigger.action.outText("OBJECT KILL: " .. id, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- we could now remove the object from the list
|
|
||||||
-- for better performance since it cant
|
|
||||||
-- die twice
|
|
||||||
|
|
||||||
-- save state for persistence
|
-- save state for persistence
|
||||||
aZone.isDestroyed = true
|
aZone.isDestroyed = true
|
||||||
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -172,7 +123,7 @@ function cfxObjectDestructDetector.saveData() -- invoked by persistence
|
|||||||
-- the isDestroyed and flag info info
|
-- the isDestroyed and flag info info
|
||||||
info = {}
|
info = {}
|
||||||
info.isDestroyed = aZone.isDestroyed
|
info.isDestroyed = aZone.isDestroyed
|
||||||
info.outDestroyVal = cfxZones.getFlagValue(aZone.outDestroyFlag, aZone)
|
info.outDestroyVal = aZone:getFlagValue(aZone.outDestroyFlag)
|
||||||
zoneInfo[aZone.name] = info
|
zoneInfo[aZone.name] = info
|
||||||
end
|
end
|
||||||
-- expasion proof: assign as own field
|
-- expasion proof: assign as own field
|
||||||
@ -202,7 +153,7 @@ function cfxObjectDestructDetector.loadMission()
|
|||||||
local theZone = cfxObjectDestructDetector.getObjectDetectZoneByName(zName)
|
local theZone = cfxObjectDestructDetector.getObjectDetectZoneByName(zName)
|
||||||
if theZone then
|
if theZone then
|
||||||
theZone.isDestroyed = info.isDestroyed
|
theZone.isDestroyed = info.isDestroyed
|
||||||
cfxZones.setFlagValue(theZone.outDestroyFlag, info.outDestroyVal, theZone)
|
theZone:setFlagValue(theZone.outDestroyFlag, info.outDestroyVal)
|
||||||
if cfxObjectDestructDetector.verbose or theZone.verbose then
|
if cfxObjectDestructDetector.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++oDDet: persistence setting flag <" .. theZone.outDestroyFlag .. "> to <" .. info.outDestroyVal .. ">",30)
|
trigger.action.outText("+++oDDet: persistence setting flag <" .. theZone.outDestroyFlag .. "> to <" .. info.outDestroyVal .. ">",30)
|
||||||
end
|
end
|
||||||
@ -246,14 +197,14 @@ function cfxObjectDestructDetector.start()
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- collect all zones with 'OBJECT id' attribute
|
-- collect all zones with 'OBJECT ID' attribute
|
||||||
-- collect all spawn zones
|
|
||||||
local attrZones = cfxZones.getZonesWithAttributeNamed("OBJECT ID")
|
local attrZones = cfxZones.getZonesWithAttributeNamed("OBJECT ID")
|
||||||
|
|
||||||
|
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
cfxObjectDestructDetector.processObjectDestructZone(aZone) -- process attribute and add to zone properties (extend zone)
|
if cfxObjectDestructDetector.processObjectDestructZone(aZone) then
|
||||||
cfxObjectDestructDetector.addObjectDetectZone(aZone)
|
cfxObjectDestructDetector.addObjectDetectZone(aZone)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- add myself as event handler
|
-- add myself as event handler
|
||||||
@ -276,8 +227,6 @@ function cfxObjectDestructDetector.start()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- say hi
|
-- say hi
|
||||||
trigger.action.outText("cfx Object Destruct Zones v" .. cfxObjectDestructDetector.version .. " started.", 30)
|
trigger.action.outText("cfx Object Destruct Zones v" .. cfxObjectDestructDetector.version .. " started.", 30)
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
civAir = {}
|
civAir = {}
|
||||||
civAir.version = "2.0.0"
|
civAir.version = "3.0.0"
|
||||||
--[[--
|
--[[--
|
||||||
1.0.0 initial version
|
1.0.0 initial version
|
||||||
1.1.0 exclude list for airfields
|
1.1.0 exclude list for airfields
|
||||||
@ -32,43 +32,61 @@ civAir.version = "2.0.0"
|
|||||||
strenghtened guard on testing against free slots for other units
|
strenghtened guard on testing against free slots for other units
|
||||||
flights are now of random neutral countries
|
flights are now of random neutral countries
|
||||||
maxFlights synonym for maxTraffic
|
maxFlights synonym for maxTraffic
|
||||||
|
3.0.0 liveries support
|
||||||
|
default liveries for Yak-50 (main test case)
|
||||||
|
default liveries for C-130, c-17A, IL-76MD, An-30M, An-26B
|
||||||
|
default aircraft types dcs
|
||||||
|
support for CAM
|
||||||
|
default liveries for all CAM types
|
||||||
|
new DCS attribute
|
||||||
|
new CAM attribute
|
||||||
|
deafault to one Yak-40 if neither
|
||||||
|
support for 'civil_liveries' zone
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
civAir.ups = 0.05 -- updates per second. 0.05 = once every 20 seconds
|
civAir.ups = 0.05 -- updates per second. 0.05 = once every 20 seconds
|
||||||
civAir.initialAirSpawns = true -- when true has population spawn in-air at start
|
civAir.initialAirSpawns = true -- when true has population spawn in-air at start
|
||||||
civAir.verbose = false
|
civAir.verbose = false
|
||||||
|
|
||||||
-- aircraftTypes contains the type names for the neutral air traffic
|
civAir.aircraftTypes = {}
|
||||||
-- each entry has the same chance to be chose, so to make an
|
civAir.dcsBuiltinTypes = {"Yak-40", "C-130", "C-17A", "IL-76MD", "An-30M", "An-26B"}
|
||||||
-- aircraft more probably to appear, add its type multiple times
|
civAir.CAMTypes = { "A_320", "A_330", "A_380", "B_727", "B_737", "B_747", "B_757", "Cessna_210N", "DC_10",}
|
||||||
-- like here with the Yak-40
|
|
||||||
civAir.aircraftTypes = {"Yak-40", "Yak-40", "C-130", "C-17A", "IL-76MD", "An-30M", "An-26B"} -- civilian planes type strings as described here https://github.com/mrSkortch/DCS-miscScripts/tree/master/ObjectDB
|
|
||||||
|
|
||||||
-- maxTraffic is the number of neutral flights that are
|
civAir.liveries = {
|
||||||
-- concurrently under way
|
|
||||||
|
-- definitions for plain vanilla DCS
|
||||||
|
["Yak-40"] = {"Aeroflot", "Algeria GLAM", "Olympic Airways", "Ukranian", "Georgian Airlines", }, --"Georgian Airlines",
|
||||||
|
["C-130"] = {"Air Algerie L-382 White", "Algerian AF Green", "Algerian AF H30 White", "Belgian Air Force", "Canada's Air Force", "French Air Force", "HAF gray", "IRIAF 5-8503", "IRIAF 5-8518", "Israel Defence Force", "Royal Air Force", "Royal Danish Air Force", "Royal Netherlands Air Force", "Royal Norwegian Air Force", "Spanish Air Force", "Turkish Air Force", "US Air Force", },
|
||||||
|
["C-17A"] = {"usaf standard", },
|
||||||
|
["IL-76MD"] = {"Algerian AF IL-76MD", "China Air Force New", "China Air Force Old", "FSB aeroflot", "MVD aeroflot", "RF Air Force", "Ukrainian AF", "Ukrainian AF aeroflot", },
|
||||||
|
["An-30M"] = {"15th Transport AB", "China CAAC", "RF Air Force"},
|
||||||
|
["An-26B"] = {"Abkhazian AF", "Aeroflot", "China PLAAF", "Georgian AF", "RF Air Force", "RF Navy", "Ukraine AF", },
|
||||||
|
|
||||||
|
-- definitions for CAM mod
|
||||||
|
["A_320"] = {"Aeroflot", "Aeroflot 1", "Air Asia", "Air Berlin", "Air Berlin FFO", "Air Berlin OLT", "Air Berlin retro", "Air France", "Air Moldova", "Airbus Neo", "Al Maha", "Alitalia", "American Airlines", "British Airways", "Cebu Pacific", "Clean", "Condor", "Delta Airlines", "Easy Jet", "Easy Jet Berlin", "Easy Jet w", "Edelweiss", "Emirates", "Etihad", "Eurowings", "Eurowings BVB09", "Eurowings Europa Park", "Fly Georgia", "Fly Niki", "Frontier", "German Wings", "Gulf Air", "Iberia", "Iran Air", "Jet Blue NY", "JetBlue", "jetBlue FDNY", "Kish Air", "Kuwait Airways", "Lufthansa", "Lufthansa New", "MEA", "MRTT Canada", "MRTT Luftwaffe", "Qatar", "RAF MPA", "RAF VIP", "S7", "SAS", "Saudi Gulf", "Saudia", "Small Planet", "Star Alliance", "SWISS", "Thomas Cook", "Tunis Air", "Turkish Airlines", "United", "Ural Airlines", "US Airways", "Vietnam Airlines", "Virgin", "WiZZ", "WiZZ Budapest", "WOW", },
|
||||||
|
|
||||||
|
["A_330"] = {"Aer Lingus", "Aeroflot", "Air Canada", "Air China", "Air Tahiti Nui", "AirAsia", "Airbus", "BOURKHAN", "Brussels Airline", "Cathay Pacific", "CEBU Pacific", "China Eastern", "Clean", "DELTA", "DragonAir", "Edelweiss", "Egypt Air", "Emirates", "ETIHAD", "EVA", "FIJI", "FinnAir", "FrenchBlue", "Garude Indunesia", "GulfAir", "Hainan Airlines", "Iberia", "IRoI", "KLM", "LAN Airways", "Lion Air PK-LEG", "LTU", "Lufthansa", "NWA", "nwaold", "Olympic", "OmanAir", "Orbit", "Philipines", "Qantas", "Qatar", "RAF Voyager", "Singapore", "Skyteam", "Srilankan", "Star Aliance", "Swiss", "Thomas Cook", "Turkish Airlines", "US Airways", "Virgin Atlantic", "WorldTrave", },
|
||||||
|
|
||||||
|
["A_380"] = {"Air France", "BA", "China Southern", "Clean", "Emirates", "KA", "LH", "LHF", "Qantas Airways", "QTR", "SA", "TA", },
|
||||||
|
|
||||||
|
["B_727"] = {"AEROFLOT", "Air France", "Alaska", "Alitalia", "American Airlines", "Clean", "Delta Airlines", "Delta Airlines OLD", "FedEx", "Hapag Lloyd", "Lufthansa", "Lufthansa Oberhausen Old", "Northwest", "Pan Am", "Singapore Airlines", "Southwest", "UNITED", "UNITED Old", "ZERO G", },
|
||||||
|
|
||||||
|
["B_737"] = {"Air Algerie", "Air Berlin", "Air France", "airBaltic", "Airzena", "AM", "American_Airlines", "British Airways", "C40s", "Clean", "Disney", "EA", "easyJet", "FINNAIR", "HARIBO", "JA", "Jet2", "kulula", "LH", "Lufthansa BA", "Lufthansa KR", "OLD_BA", "OMAN AIR", "P8 RAF", "P8 USN", "PAN AM", "Polskie Linie Lotnicze LOT", "QANTAS", "RYANAIR", "SouthWest Lone Star", "ThomsonFly", "TNT", "Ukraine Airlines", "UPS", },
|
||||||
|
|
||||||
|
["B_747"] = {"AF", "AF-One", "AI", "CP", "IM", "KLM", "LH", "NW", "PA", "QA", "TA", },
|
||||||
|
|
||||||
|
["B_757"] = {"AA", "BA", "C-32", "Delta", "DHL", "easyJet", "Swiss", "Thomson", },
|
||||||
|
|
||||||
|
["Cessna_210N"] = {"Blank", "D-EKVW", "HellenicAF", "Muster", "N9572H", "SEagle blue", "SEagle red", "USAF-Academy", "V5-BUG", "VH-JGA", },
|
||||||
|
|
||||||
|
["DC_10"] = {"SWISSAIR HB-IHL", "SWISSAIR HB-IMC", "SWISSAIR HB-IPF", }
|
||||||
|
}
|
||||||
civAir.maxTraffic = 10 -- number of flights at the same time
|
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.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
|
|
||||||
-- 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
|
|
||||||
-- if name starts with "***" then it is not an airfield, but zone
|
|
||||||
|
|
||||||
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
|
|
||||||
-- in trafficCenters.
|
|
||||||
-- can be populated by zone on the map that have the
|
|
||||||
-- 'civAir' attribute with value "exclude"
|
|
||||||
|
|
||||||
civAir.departOnly = {} -- use only to start from
|
civAir.departOnly = {} -- use only to start from
|
||||||
civAir.landingOnly = {} -- use only to land at
|
civAir.landingOnly = {} -- use only to land at
|
||||||
civAir.inoutZones = {} -- off-map connector zones
|
civAir.inoutZones = {} -- off-map connector zones
|
||||||
@ -86,40 +104,106 @@ function civAir.readConfigZone()
|
|||||||
-- note: must match exactly!!!!
|
-- note: must match exactly!!!!
|
||||||
local theZone = cfxZones.getZoneByName("civAirConfig")
|
local theZone = cfxZones.getZoneByName("civAirConfig")
|
||||||
if not theZone then
|
if not theZone then
|
||||||
trigger.action.outText("***civA: NO config zone!", 30)
|
|
||||||
theZone = cfxZones.createSimpleZone("civAirConfig")
|
theZone = cfxZones.createSimpleZone("civAirConfig")
|
||||||
end
|
end
|
||||||
|
civAir.verbose = theZone.verbose
|
||||||
-- ok, for each property, load it if it exists
|
civAir.ups = theZone:getNumberFromZoneProperty("ups", 0.05)
|
||||||
if theZone:hasProperty("aircraftTypes") then
|
if civAir.ups < .0001 then civAir.ups = 0.05 end
|
||||||
local theTypes = theZone:getStringFromZoneProperty( "aircraftTypes", civAir.aircraftTypes) -- "Yak-40")
|
|
||||||
local typeArray = dcsCommon.splitString(theTypes, ",")
|
|
||||||
typeArray = dcsCommon.trimArray(typeArray)
|
|
||||||
civAir.aircraftTypes = typeArray
|
|
||||||
end
|
|
||||||
|
|
||||||
-- if theZone:hasProperty("ups") then
|
|
||||||
civAir.ups = theZone:getNumberFromZoneProperty("ups", 0.05)
|
|
||||||
if civAir.ups < .0001 then civAir.ups = 0.05 end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
if theZone:hasProperty("maxTraffic") then
|
if theZone:hasProperty("maxTraffic") then
|
||||||
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxTraffic", 10)
|
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxTraffic", 10)
|
||||||
elseif theZone:hasProperty("maxFlights") then
|
else --if theZone:hasProperty("maxFlights") then
|
||||||
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxFlights", 10)
|
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxFlights", 10)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if theZone:hasProperty("maxIdle") then
|
civAir.maxIdle = theZone:getNumberFromZoneProperty("maxIdle", 8 * 60)
|
||||||
civAir.maxIdle = theZone:getNumberFromZoneProperty("maxIdle", 8 * 60)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- if theZone:hasProperty("initialAirSpawns") then
|
civAir.initialAirSpawns = theZone:getBoolFromZoneProperty( "initialAirSpawns", true)
|
||||||
civAir.initialAirSpawns = theZone:getBoolFromZoneProperty( "initialAirSpawns", true)
|
|
||||||
-- end
|
civAir.owner = theZone:getNumberFromZoneProperty("owner", 82) -- default to UN peacekeepers
|
||||||
|
-- build my aircraft types list
|
||||||
|
local hasDCS = theZone:getBoolFromZoneProperty("dcs", true)
|
||||||
|
if hasDCS then
|
||||||
|
if civAir.verbose then trigger.action.outText("+++civA: adding DCS standard types", 30) end
|
||||||
|
for idx, aType in pairs(civAir.dcsBuiltinTypes) do
|
||||||
|
table.insert(civAir.aircraftTypes, aType)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local hasCAM = theZone:getBoolFromZoneProperty("cam", false)
|
||||||
|
if hasCAM then
|
||||||
|
if civAir.verbose then trigger.action.outText("+++civA: adding CAM add-on types", 30) end
|
||||||
|
for idx, aType in pairs(civAir.CAMTypes) do
|
||||||
|
table.insert(civAir.aircraftTypes, aType)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- now get types and liveries from 'civil_liveries' if present
|
||||||
|
local livZone = cfxZones.getZoneByName("civil_liveries")
|
||||||
|
if livZone then
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("civA: found and processing 'civil_liveries' zone data.", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- read all into my types registry, replacing whatever is there
|
||||||
|
local rawLiver = cfxZones.getAllZoneProperties(livZone)
|
||||||
|
local newTypes, newLiveries = civAir.addTypesAndLiveries(rawLiver)
|
||||||
|
-- now types to existing types if not already there
|
||||||
|
for idx, aType in pairs(newTypes) do
|
||||||
|
dcsCommon.addToTableIfNew(civAir.aircraftTypes, aType)
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("+++civA: processed and added aircraft <" .. aType .. "> to civAir", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- now replace liveries or add if not already there
|
||||||
|
for aType, liveries in pairs(newLiveries) do
|
||||||
|
civAir.liveries[aType] = liveries
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("+++civA: replaced/added liveries for aircraft <" .. aType .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #civAir.aircraftTypes < 1 then
|
||||||
|
table.insert(civAir.aircraftTypes, "Yak-40")
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("+++civA: adding singular Yak-40", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- selective types, overwrites existing types when present
|
||||||
|
-- also provides legacy support
|
||||||
|
if theZone:hasProperty("aircraftTypes") then
|
||||||
|
local theTypes = theZone:getStringFromZoneProperty( "aircraftTypes", civAir.aircraftTypes)
|
||||||
|
local typeArray = dcsCommon.splitString(theTypes, ",")
|
||||||
|
typeArray = dcsCommon.trimArray(typeArray)
|
||||||
|
civAir.aircraftTypes = typeArray
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("+++civA: setting aircraft types to <" .. theTypes .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
civAir.verbose = theZone.verbose
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function civAir.addTypesAndLiveries(rawIn)
|
||||||
|
local newTypes = {}
|
||||||
|
local newLiveries = {}
|
||||||
|
-- now iterate the input table, and generate new types and
|
||||||
|
-- liveries from it
|
||||||
|
for theType, liveries in pairs (rawIn) do
|
||||||
|
if civAir.verbose then
|
||||||
|
trigger.action.outText("+++civA: processing type <" .. theType .. ">:<" .. liveries .. ">", 30)
|
||||||
|
end
|
||||||
|
local livA = dcsCommon.splitString(liveries, ',')
|
||||||
|
livA = dcsCommon.trimArray(livA)
|
||||||
|
table.insert(newTypes, theType)
|
||||||
|
newLiveries[theType] = livA
|
||||||
|
end
|
||||||
|
|
||||||
|
return newTypes, newLiveries
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function civAir.processZone(theZone)
|
function civAir.processZone(theZone)
|
||||||
local value = theZone:getStringFromZoneProperty("civAir", "")
|
local value = theZone:getStringFromZoneProperty("civAir", "")
|
||||||
local af = dcsCommon.getClosestAirbaseTo(theZone.point, 0) -- 0 = only airfields, not farp or ships
|
local af = dcsCommon.getClosestAirbaseTo(theZone.point, 0) -- 0 = only airfields, not farp or ships
|
||||||
@ -137,16 +221,12 @@ function civAir.processZone(theZone)
|
|||||||
elseif dcsCommon.stringStartsWith(value, "inb") then
|
elseif dcsCommon.stringStartsWith(value, "inb") then
|
||||||
table.insert(civAir.departOnly, inoutName) -- start in inbound zone
|
table.insert(civAir.departOnly, inoutName) -- start in inbound zone
|
||||||
civAir.inoutZones[inoutName] = theZone
|
civAir.inoutZones[inoutName] = theZone
|
||||||
-- theZone.inbound = true
|
|
||||||
elseif dcsCommon.stringStartsWith(value, "outb") then
|
elseif dcsCommon.stringStartsWith(value, "outb") then
|
||||||
table.insert(civAir.landingOnly, inoutName)
|
table.insert(civAir.landingOnly, inoutName)
|
||||||
civAir.inoutZones[inoutName] = theZone
|
civAir.inoutZones[inoutName] = theZone
|
||||||
-- theZone.outbound = true
|
|
||||||
elseif dcsCommon.stringStartsWith(value, "in/out") then
|
elseif dcsCommon.stringStartsWith(value, "in/out") then
|
||||||
table.insert(civAir.trafficCenters, inoutName)
|
table.insert(civAir.trafficCenters, inoutName)
|
||||||
civAir.inoutZones[inoutName] = theZone
|
civAir.inoutZones[inoutName] = theZone
|
||||||
-- theZone.inbound = true
|
|
||||||
-- theZone.outbound = true
|
|
||||||
else
|
else
|
||||||
table.insert(civAir.trafficCenters, afName) -- note that adding the same twice makes it more likely to be picked
|
table.insert(civAir.trafficCenters, afName) -- note that adding the same twice makes it more likely to be picked
|
||||||
end
|
end
|
||||||
@ -231,8 +311,7 @@ function civAir.getTwoAirbases()
|
|||||||
sAB = dcsCommon.pickRandom(filteredAB)
|
sAB = dcsCommon.pickRandom(filteredAB)
|
||||||
tries = tries + 1 -- only try 10 times
|
tries = tries + 1 -- only try 10 times
|
||||||
until fAB ~= sAB or tries > 10
|
until fAB ~= sAB or tries > 10
|
||||||
|
|
||||||
|
|
||||||
local civA = {}
|
local civA = {}
|
||||||
if not (dcsCommon.stringStartsWith(fAB, '***')) then
|
if not (dcsCommon.stringStartsWith(fAB, '***')) then
|
||||||
civA.AB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
|
civA.AB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
|
||||||
@ -295,9 +374,15 @@ function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAi
|
|||||||
|
|
||||||
local theGroup = dcsCommon.createEmptyAircraftGroupData (name)
|
local theGroup = dcsCommon.createEmptyAircraftGroupData (name)
|
||||||
local theAUnit = dcsCommon.createAircraftUnitData(name .. "-GA", theTypeString, false)
|
local theAUnit = dcsCommon.createAircraftUnitData(name .. "-GA", theTypeString, false)
|
||||||
|
-- add livery capability for this aircraft
|
||||||
|
civAir.processLiveriesFor(theAUnit, theTypeString)
|
||||||
|
|
||||||
|
-- enforce civ attribute
|
||||||
|
theAUnit.civil_plane = true
|
||||||
|
|
||||||
theAUnit.payload.fuel = 100000
|
theAUnit.payload.fuel = 100000
|
||||||
dcsCommon.addUnitToGroupData(theAUnit, theGroup)
|
dcsCommon.addUnitToGroupData(theAUnit, theGroup)
|
||||||
|
|
||||||
local fromWP
|
local fromWP
|
||||||
if fromAirfield.AB then
|
if fromAirfield.AB then
|
||||||
fromWP = dcsCommon.createTakeOffFromParkingRoutePointData(fromAirfield.AB)
|
fromWP = dcsCommon.createTakeOffFromParkingRoutePointData(fromAirfield.AB)
|
||||||
@ -384,13 +469,7 @@ function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAi
|
|||||||
dcsCommon.addRoutePointForGroupData(theGroup, toWP)
|
dcsCommon.addRoutePointForGroupData(theGroup, toWP)
|
||||||
|
|
||||||
-- spawn
|
-- spawn
|
||||||
local groupCat = Group.Category.AIRPLANE
|
local theSpawnedGroup = coalition.addGroup(civAir.owner, groupCat, theGroup) -- 82 is UN peacekeepers
|
||||||
local allNeutral = dcsCommon.getCountriesForCoalition(0)
|
|
||||||
local aRandomNeutral = dcsCommon.pickRandom(allNeutral)
|
|
||||||
if not aRandomNeutral then
|
|
||||||
trigger.action.outText("+++civA: WARNING: no neutral countries exist, flight is not neutral.", 30)
|
|
||||||
end
|
|
||||||
local theSpawnedGroup = coalition.addGroup(aRandomNeutral, groupCat, theGroup) -- 82 is UN peacekeepers
|
|
||||||
if zoneApproach then
|
if zoneApproach then
|
||||||
-- track this flight to target zone
|
-- track this flight to target zone
|
||||||
civAir.outboundFlights[name] = zoneApproach
|
civAir.outboundFlights[name] = zoneApproach
|
||||||
@ -436,6 +515,20 @@ function civAir.airStartPopulation()
|
|||||||
civAir.airStartSeparation = civAir.airStartSeparation + 200
|
civAir.airStartSeparation = civAir.airStartSeparation + 200
|
||||||
civAir.createNewFlight(true)
|
civAir.createNewFlight(true)
|
||||||
end
|
end
|
||||||
|
-- start update in 15 seconds
|
||||||
|
timer.scheduleFunction(civAir.update, {}, timer.getTime() + 15)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Livery handling
|
||||||
|
--
|
||||||
|
|
||||||
|
function civAir.processLiveriesFor(theData, theType)
|
||||||
|
if civAir.liveries[theType] then
|
||||||
|
local available = civAir.liveries[theType]
|
||||||
|
local chosen = dcsCommon.pickRandom(available)
|
||||||
|
theData.livery_id = chosen
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -609,7 +702,7 @@ function civAir.start()
|
|||||||
|
|
||||||
-- see if there is a config zone and load it
|
-- see if there is a config zone and load it
|
||||||
civAir.readConfigZone()
|
civAir.readConfigZone()
|
||||||
|
|
||||||
-- look for zones to add to air fields list
|
-- look for zones to add to air fields list
|
||||||
civAir.collectHubs()
|
civAir.collectHubs()
|
||||||
|
|
||||||
@ -632,12 +725,15 @@ function civAir.start()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- air-start half population if allowed
|
-- air-start half population if allowed
|
||||||
|
-- allow mission 15 seconds to settle before we start populating to
|
||||||
|
-- allow better access to liveries
|
||||||
if civAir.initialAirSpawns then
|
if civAir.initialAirSpawns then
|
||||||
civAir.airStartPopulation()
|
timer.scheduleFunction(civAir.airStartPopulation, {}, timer.getTime() + 5)
|
||||||
|
else
|
||||||
|
-- start update in 15 seconds
|
||||||
|
timer.scheduleFunction(civAir.update, {}, timer.getTime() + 15)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- start the update loop
|
|
||||||
civAir.update()
|
|
||||||
-- start outbound tracking
|
-- start outbound tracking
|
||||||
civAir.trackOutbound()
|
civAir.trackOutbound()
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cloneZones = {}
|
cloneZones = {}
|
||||||
cloneZones.version = "1.9.0"
|
cloneZones.version = "1.9.1"
|
||||||
cloneZones.verbose = false
|
cloneZones.verbose = false
|
||||||
cloneZones.requiredLibs = {
|
cloneZones.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -106,6 +106,7 @@ cloneZones.respawnOnGroupID = true
|
|||||||
- cooldown attribute
|
- cooldown attribute
|
||||||
- cloner collects all types used
|
- cloner collects all types used
|
||||||
- groupScheme attribute
|
- groupScheme attribute
|
||||||
|
1.9.1 - useAI attribute
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -404,6 +405,8 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
|||||||
theZone.nameScheme = nil
|
theZone.nameScheme = nil
|
||||||
theZone.groupScheme = nil
|
theZone.groupScheme = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
theZone.useAI = theZone:getBoolFromZoneProperty("useAI", true)
|
||||||
-- we end with clear plate
|
-- we end with clear plate
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1256,6 +1259,8 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
-- see what country we spawn for
|
-- see what country we spawn for
|
||||||
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
||||||
rawData.CZctry = ctry -- save ctry
|
rawData.CZctry = ctry -- save ctry
|
||||||
|
-- set AI on or off
|
||||||
|
rawData.useAI = spawnZone.useAI
|
||||||
table.insert(dataToSpawn, rawData)
|
table.insert(dataToSpawn, rawData)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1295,6 +1300,11 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
||||||
table.insert(spawnedGroups, theGroup)
|
table.insert(spawnedGroups, theGroup)
|
||||||
|
|
||||||
|
-- turn off AI if disabled
|
||||||
|
if not rawData.useAI then
|
||||||
|
cloneZones.turnOffAI({theGroup})
|
||||||
|
end
|
||||||
|
|
||||||
-- update groupXlate table from spawned group
|
-- update groupXlate table from spawned group
|
||||||
-- so we can later reference them with other clones
|
-- so we can later reference them with other clones
|
||||||
local newGroupID = theGroup:getID() -- new ID assigned by DCS
|
local newGroupID = theGroup:getID() -- new ID assigned by DCS
|
||||||
@ -1515,6 +1525,13 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
return spawnedGroups, spawnedStatics
|
return spawnedGroups, spawnedStatics
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cloneZones.turnOffAI(args)
|
||||||
|
local theGroup = args[1]
|
||||||
|
local theController = theGroup:getController()
|
||||||
|
theController:setOnOff(false)
|
||||||
|
-- trigger.action.outText("turned off AI for group <" .. theGroup:getName() .. "> ", 30)
|
||||||
|
end
|
||||||
|
|
||||||
-- retro-fit for helo troops and others to provide 'requestable' support
|
-- retro-fit for helo troops and others to provide 'requestable' support
|
||||||
function cloneZones.spawnWithSpawner(theZone)
|
function cloneZones.spawnWithSpawner(theZone)
|
||||||
-- analog to cfxSpawnZones.spawnWithSpawner(theSpawner)
|
-- analog to cfxSpawnZones.spawnWithSpawner(theSpawner)
|
||||||
@ -1950,6 +1967,10 @@ function cloneZones.loadData()
|
|||||||
local gdClone = dcsCommon.clone(gData)
|
local gdClone = dcsCommon.clone(gData)
|
||||||
cloneZones.allClones[gName] = gdClone
|
cloneZones.allClones[gName] = gdClone
|
||||||
local theGroup = coalition.addGroup(cty, cat, gData)
|
local theGroup = coalition.addGroup(cty, cat, gData)
|
||||||
|
-- turn off AI if disabled
|
||||||
|
if not gData.useAI then
|
||||||
|
cloneZones.turnOffAI({theGroup})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- spawn all static objects
|
-- spawn all static objects
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
dcsCommon = {}
|
dcsCommon = {}
|
||||||
dcsCommon.version = "2.9.5"
|
dcsCommon.version = "2.9.6"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
2.2.6 - compassPositionOfARelativeToB
|
2.2.6 - compassPositionOfARelativeToB
|
||||||
- clockPositionOfARelativeToB
|
- clockPositionOfARelativeToB
|
||||||
@ -175,6 +175,7 @@ dcsCommon.version = "2.9.5"
|
|||||||
2.9.3 - getAirbasesWhoseNameContains now supports category tables for filtering
|
2.9.3 - getAirbasesWhoseNameContains now supports category tables for filtering
|
||||||
2.9.4 - new bearing2degrees()
|
2.9.4 - new bearing2degrees()
|
||||||
2.9.5 - distanceOfPointPToLineXZ(p, p1, p2)
|
2.9.5 - distanceOfPointPToLineXZ(p, p1, p2)
|
||||||
|
2.9.6 - new addToTableIfNew()
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -402,6 +403,13 @@ dcsCommon.version = "2.9.5"
|
|||||||
end
|
end
|
||||||
return outTable
|
return outTable
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function dcsCommon.addToTableIfNew(theTable, theElement)
|
||||||
|
for idx, anElement in pairs(theTable) do
|
||||||
|
if anElement == theElement then return end
|
||||||
|
end
|
||||||
|
table.insert(theTable, theElement)
|
||||||
|
end
|
||||||
--
|
--
|
||||||
-- A I R F I E L D S A N D F A R P S
|
-- A I R F I E L D S A N D F A R P S
|
||||||
--
|
--
|
||||||
@ -2404,38 +2412,9 @@ end
|
|||||||
theString = string.upper(theString)
|
theString = string.upper(theString)
|
||||||
thePrefix = string.upper(theString)
|
thePrefix = string.upper(theString)
|
||||||
end
|
end
|
||||||
-- new code because old 'string.find' had some really
|
-- superseded: string.find (s, pattern [, init [, plain]]) solves the problem
|
||||||
-- strange results with aircraft types. Prefix "A-10" did not
|
|
||||||
-- match string "A-10A" etc.
|
|
||||||
|
|
||||||
-- superseded: string.find (s, pattern [, init [, plain]]) solves the problem
|
|
||||||
|
|
||||||
--[[
|
|
||||||
local pl = string.len(thePrefix)
|
|
||||||
if pl > string.len(theString) then return false end
|
|
||||||
if pl < 1 then return false end
|
|
||||||
for i=1, pl do
|
|
||||||
local left = string.sub(theString, i, i)
|
|
||||||
local right = string.sub(thePrefix, i, i)
|
|
||||||
if left ~= right then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
--]]-- trigger.action.outText("---- OK???", 30)
|
|
||||||
-- strange stuff happening with some strings, let's investigate
|
|
||||||
|
|
||||||
local i, j = string.find(theString, thePrefix, 1, true)
|
local i, j = string.find(theString, thePrefix, 1, true)
|
||||||
return (i == 1)
|
return (i == 1)
|
||||||
--[[--
|
|
||||||
if res then
|
|
||||||
trigger.action.outText("startswith: <" .. theString .. "> pre <" .. thePrefix .. "> --> YES", 30)
|
|
||||||
else
|
|
||||||
trigger.action.outText("startswith: <" .. theString .. "> nojoy pre <" .. thePrefix .. ">", 30)
|
|
||||||
end
|
|
||||||
return res
|
|
||||||
--]]--
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function dcsCommon.removePrefix(theString, thePrefix)
|
function dcsCommon.removePrefix(theString, thePrefix)
|
||||||
|
|||||||
@ -13,7 +13,9 @@ fireFX.fx = {}
|
|||||||
1.0.0 - Initial version
|
1.0.0 - Initial version
|
||||||
1.1.0 - persistence
|
1.1.0 - persistence
|
||||||
1.1.1 - agl attribute
|
1.1.1 - agl attribute
|
||||||
|
2.0.0 - dmlZones OOP
|
||||||
|
- rndLoc
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
function fireFX.addFX(theZone)
|
function fireFX.addFX(theZone)
|
||||||
@ -35,7 +37,7 @@ end
|
|||||||
--
|
--
|
||||||
function fireFX.createFXWithZone(theZone)
|
function fireFX.createFXWithZone(theZone)
|
||||||
-- decode size and fire
|
-- decode size and fire
|
||||||
local theSize = cfxZones.getStringFromZoneProperty(theZone, "fireFX", "none")
|
local theSize = theZone:getStringFromZoneProperty("fireFX", "none")
|
||||||
theSize = dcsCommon.trim(theSize)
|
theSize = dcsCommon.trim(theSize)
|
||||||
theSize = string.upper(theSize)
|
theSize = string.upper(theSize)
|
||||||
local fxCode = 1
|
local fxCode = 1
|
||||||
@ -59,22 +61,22 @@ function fireFX.createFXWithZone(theZone)
|
|||||||
trigger.action.outText("+++ffx: new FX with code = <" .. fxCode .. ">", 30)
|
trigger.action.outText("+++ffx: new FX with code = <" .. fxCode .. ">", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.density = cfxZones.getNumberFromZoneProperty(theZone, "density", 0.5)
|
theZone.density = theZone:getNumberFromZoneProperty("density", 0.5)
|
||||||
|
|
||||||
theZone.agl = cfxZones.getNumberFromZoneProperty(theZone, "AGL", 0)
|
theZone.agl = theZone:getNumberFromZoneProperty("AGL", 0)
|
||||||
|
theZone.min, theZone.max = theZone:getPositiveRangeFromZoneProperty("num", 1, 1)
|
||||||
|
|
||||||
|
if theZone:hasProperty("start?") then
|
||||||
if cfxZones.hasProperty(theZone, "start?") then
|
theZone.fxStart = theZone:getStringFromZoneProperty("start?", "*<none>")
|
||||||
theZone.fxStart = cfxZones.getStringFromZoneProperty(theZone, "start?", "*<none>")
|
theZone.fxLastStart = theZone:getFlagValue(theZone.fxStart)
|
||||||
theZone.fxLastStart = cfxZones.getFlagValue(theZone.fxStart, theZone)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "stop?") then
|
if theZone:hasProperty("stop?") then
|
||||||
theZone.fxStop = cfxZones.getStringFromZoneProperty(theZone, "stop?", "*<none>")
|
theZone.fxStop = theZone:getStringFromZoneProperty("stop?", "*<none>")
|
||||||
theZone.fxLastStop = cfxZones.getFlagValue(theZone.fxStop, theZone)
|
theZone.fxLastStop = theZone:getFlagValue(theZone.fxStop)
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.fxOnStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
theZone.fxOnStart = theZone:getBoolFromZoneProperty("onStart", false)
|
||||||
theZone.burning = false
|
theZone.burning = false
|
||||||
|
|
||||||
if not theZone.fxOnStart and not theZone.fxStart then
|
if not theZone.fxOnStart and not theZone.fxStart then
|
||||||
@ -84,14 +86,23 @@ function fireFX.createFXWithZone(theZone)
|
|||||||
-- output method (not needed)
|
-- output method (not needed)
|
||||||
|
|
||||||
-- trigger method
|
-- trigger method
|
||||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "fxTriggerMethod", "change")
|
theZone.fxTriggerMethod = theZone:getStringFromZoneProperty( "fxTriggerMethod", "change")
|
||||||
if cfxZones.hasProperty(theZone, "triggerMethod") then
|
if theZone:hasProperty("triggerMethod") then
|
||||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
theZone.fxTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
theZone.rndLoc = theZone:getBoolFromZoneProperty("rndLoc", false)
|
||||||
|
if theZone.max + 1 and (not theZone.rndLoc) then
|
||||||
|
if theZone.verbose or fireFX.verbose then
|
||||||
|
trigger.action.outText("+++ffx: more than 1 fires, will set to random loc")
|
||||||
|
end
|
||||||
|
theZone.rndLoc = true
|
||||||
|
end
|
||||||
|
|
||||||
if fireFX.verbose or theZone.verbose then
|
if fireFX.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++ffx: new FX <".. theZone.name ..">", 30)
|
trigger.action.outText("+++ffx: new FX <".. theZone.name ..">", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -99,18 +110,29 @@ end
|
|||||||
--
|
--
|
||||||
function fireFX.startTheFire(theZone)
|
function fireFX.startTheFire(theZone)
|
||||||
if not theZone.burning then
|
if not theZone.burning then
|
||||||
local p = cfxZones.getPoint(theZone)
|
theZone.fireNames = {}
|
||||||
p.y = land.getHeight({x = p.x, y = p.z}) + theZone.agl
|
local num = cfxZones.randomInRange(theZone.min, theZone.max)
|
||||||
local preset = theZone.fxCode
|
for i = 1, num do
|
||||||
local density = theZone.density
|
local p = cfxZones.getPoint(theZone)
|
||||||
trigger.action.effectSmokeBig(p, preset, density, theZone.name)
|
if theZone.rndLoc then
|
||||||
|
p = theZone:randomPointInZone()
|
||||||
|
end
|
||||||
|
p.y = land.getHeight({x = p.x, y = p.z}) + theZone.agl
|
||||||
|
local preset = theZone.fxCode
|
||||||
|
local density = theZone.density
|
||||||
|
local fireName = dcsCommon.uuid(theZone.name)
|
||||||
|
trigger.action.effectSmokeBig(p, preset, density, fireName)
|
||||||
|
theZone.fireNames[i] = fireName
|
||||||
|
end
|
||||||
theZone.burning = true
|
theZone.burning = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function fireFX.extinguishFire(theZone)
|
function fireFX.extinguishFire(theZone)
|
||||||
if theZone.burning then
|
if theZone.burning then
|
||||||
trigger.action.effectSmokeStop(theZone.name)
|
for idx, aFireName in pairs(theZone.fireNames) do
|
||||||
|
trigger.action.effectSmokeStop(aFireName)
|
||||||
|
end
|
||||||
theZone.burning = false
|
theZone.burning = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
105
modules/groundExplosion.lua
Normal file
105
modules/groundExplosion.lua
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
groundExplosion = {}
|
||||||
|
groundExplosion.version = "1.0.0"
|
||||||
|
groundExplosion.requiredLibs = {
|
||||||
|
"dcsCommon",
|
||||||
|
"cfxZones",
|
||||||
|
}
|
||||||
|
groundExplosion.zones = {}
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Version History
|
||||||
|
1.0.0 - Initial version
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
|
||||||
|
function groundExplosion.addExplosion(theZone)
|
||||||
|
theZone.powerMin, theZone.powerMax = theZone:getPositiveRangeFromZoneProperty("explosion", 1, 1)
|
||||||
|
theZone.triggerMethod = theZone:getStringFromZoneProperty("tiggerMethod", "change")
|
||||||
|
if theZone:hasProperty("boom?") then
|
||||||
|
theZone.boom = theZone:getStringFromZoneProperty("boom?", "none")
|
||||||
|
theZone.lastBoom = theZone:getFlagValue(theZone.boom)
|
||||||
|
end
|
||||||
|
theZone.numMin, theZone.numMax = theZone:getPositiveRangeFromZoneProperty("num", 1, 1)
|
||||||
|
theZone.rndLoc = theZone:getBoolFromZoneProperty("rndLoc", false)
|
||||||
|
if (theZone.numMax > 1) then
|
||||||
|
theZone.rndLoc = true
|
||||||
|
theZone.multi = true
|
||||||
|
end
|
||||||
|
theZone.duration = theZone:getNumberFromZoneProperty("duration", 0)
|
||||||
|
theZone.aglMin, theZone.aglMax = theZone:getPositiveRangeFromZoneProperty("AGL", 1,1)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- go boom
|
||||||
|
--
|
||||||
|
function groundExplosion.doBoom(args)
|
||||||
|
local loc = args[1]
|
||||||
|
local power = args[2]
|
||||||
|
local theZone = args[3]
|
||||||
|
trigger.action.explosion(loc, power)
|
||||||
|
end
|
||||||
|
|
||||||
|
function groundExplosion.startBoom(theZone)
|
||||||
|
local now = timer.getTime()
|
||||||
|
local num = cfxZones.randomInRange(theZone.numMin, theZone.numMax)
|
||||||
|
local i = 1
|
||||||
|
while i <= num do
|
||||||
|
local loc
|
||||||
|
if theZone.rndLoc then
|
||||||
|
loc = theZone:randomPointInZone()
|
||||||
|
else
|
||||||
|
loc = theZone:getPoint()
|
||||||
|
end
|
||||||
|
local h = land.getHeight({x = loc.x, y = loc.z})
|
||||||
|
local agl = cfxZones.randomInRange(theZone.aglMin, theZone.aglMax)
|
||||||
|
loc.y = h + agl
|
||||||
|
local power = cfxZones.randomInRange(theZone.powerMin, theZone.powerMax)
|
||||||
|
if theZone.duration > 0 then -- deferred
|
||||||
|
local tplus = (i-1) * theZone.duration / num
|
||||||
|
timer.scheduleFunction(groundExplosion.doBoom, {loc, power, theZone}, now + tplus + 0.1)
|
||||||
|
else -- immediate
|
||||||
|
trigger.action.explosion(loc, power)
|
||||||
|
end
|
||||||
|
i = i + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Update
|
||||||
|
--
|
||||||
|
function groundExplosion.update()
|
||||||
|
for idx, theZone in pairs(groundExplosion.zones) do
|
||||||
|
|
||||||
|
if theZone.boom then
|
||||||
|
if theZone:testZoneFlag(theZone.boom, theZone.triggerMethod, "lastBoom") then
|
||||||
|
groundExplosion.startBoom(theZone)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
timer.scheduleFunction(groundExplosion.update, {}, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function groundExplosion.start()
|
||||||
|
if not dcsCommon.libCheck("cfx groundExplosion",
|
||||||
|
cfxObjectDestructDetector.requiredLibs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- collect all zones with 'OBJECT ID' attribute
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("explosion")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
groundExplosion.addExplosion(aZone)
|
||||||
|
table.insert(groundExplosion.zones, aZone)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- start update
|
||||||
|
timer.scheduleFunction(groundExplosion.update, {}, timer.getTime() + 1)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- let's go
|
||||||
|
if not groundExplosion.start() then
|
||||||
|
trigger.action.outText("cf/x groundExplosion aborted: missing libraries", 30)
|
||||||
|
groundExplosion = nil
|
||||||
|
end
|
||||||
@ -1,5 +1,5 @@
|
|||||||
pulseFlags = {}
|
pulseFlags = {}
|
||||||
pulseFlags.version = "1.3.3"
|
pulseFlags.version = "2.0.0"
|
||||||
pulseFlags.verbose = false
|
pulseFlags.verbose = false
|
||||||
pulseFlags.requiredLibs = {
|
pulseFlags.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -39,6 +39,9 @@ pulseFlags.requiredLibs = {
|
|||||||
- 1.3.1 typos corrected
|
- 1.3.1 typos corrected
|
||||||
- 1.3.2 removed last pulse's timeID upon entry in doPulse
|
- 1.3.2 removed last pulse's timeID upon entry in doPulse
|
||||||
- 1.3.3 removed 'pulsing' when pausing, so we can restart
|
- 1.3.3 removed 'pulsing' when pausing, so we can restart
|
||||||
|
- 2.0.0 dmlZones / OOP
|
||||||
|
using method on all outputs
|
||||||
|
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -59,106 +62,86 @@ end
|
|||||||
--
|
--
|
||||||
|
|
||||||
function pulseFlags.createPulseWithZone(theZone)
|
function pulseFlags.createPulseWithZone(theZone)
|
||||||
if cfxZones.hasProperty(theZone, "pulse") then
|
if theZone:hasProperty("pulse") then
|
||||||
theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse", "*none") -- the flag to pulse
|
theZone.pulseFlag = theZone:getStringFromZoneProperty("pulse", "*none") -- the flag to pulse
|
||||||
end
|
trigger.action.outText("Warning: pulser in zone <" .. theZone.name .. "> uses deprecated attribuet 'pulse'.", 30)
|
||||||
|
elseif theZone:hasProperty("pulse!") then
|
||||||
if cfxZones.hasProperty(theZone, "pulse!") then
|
theZone.pulseFlag = theZone:getStringFromZoneProperty("pulse!", "*none") -- the flag to pulse
|
||||||
theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse!", "*none") -- the flag to pulse
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- time can be number, or number-number range
|
-- time can be number, or number-number range
|
||||||
theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "time", 1)
|
theZone.minTime = 1
|
||||||
if cfxZones.hasProperty(theZone, "pulseInterval") then
|
theZone.time = 1
|
||||||
theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "pulseInterval", 1)
|
if theZone:hasProperty("time") then
|
||||||
|
theZone.minTime, theZone.time = theZone:getPositiveRangeFromZoneProperty("time", 1)
|
||||||
|
elseif theZone:hasProperty("pulseInterval") then
|
||||||
|
theZone.minTime, theZone.time = theZone:getPositiveRangeFromZoneProperty("pulseInterval", 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
if pulseFlags.verbose or theZone.verbose then
|
if pulseFlags.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> time is <".. theZone.minTime ..", " .. theZone.time .. "!", 30)
|
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> time is <".. theZone.minTime ..", " .. theZone.time .. "!", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
theZone.pulses = -1 -- set to infinite
|
theZone.pulses = -1 -- set to infinite
|
||||||
if cfxZones.hasProperty(theZone, "pulses") then
|
if theZone:hasProperty("pulses") then
|
||||||
local minP
|
local minP, maxP = theZone:getPositiveRangeFromZoneProperty("pulses", 1)
|
||||||
local maxP
|
|
||||||
minP, maxP = cfxZones.getPositiveRangeFromZoneProperty(theZone, "pulses", 1)
|
|
||||||
if minP == maxP then theZone.pulses = minP
|
if minP == maxP then theZone.pulses = minP
|
||||||
else
|
else
|
||||||
theZone.pulses = cfxZones.randomInRange(minP, maxP)
|
theZone.pulses = cfxZones.randomInRange(minP, maxP)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if pulseFlags.verbose or theZone.verbose then
|
if pulseFlags.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> set to <" .. theZone.pulses .. "> pulses", 30)
|
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> set to <" .. theZone.pulses .. "> pulses", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.pulsesLeft = 0 -- will start new cycle
|
theZone.pulsesLeft = 0 -- will start new cycle
|
||||||
|
|
||||||
-- watchflag:
|
theZone.pulseTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||||
-- triggerMethod
|
|
||||||
theZone.pulseTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "pulseTriggerMethod") then
|
if theZone:hasProperty("pulseTriggerMethod") then
|
||||||
theZone.pulseTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "pulseTriggerMethod", "change")
|
theZone.pulseTriggerMethod = theZone:getStringFromZoneProperty("pulseTriggerMethod", "change")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- trigger flags
|
-- trigger flags
|
||||||
if cfxZones.hasProperty(theZone, "activate?") then
|
if theZone:hasProperty("activate?") then
|
||||||
theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "activate?", "none")
|
theZone.activatePulseFlag = theZone:getStringFromZoneProperty("activate?", "none")
|
||||||
theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value
|
theZone.lastActivateValue = theZone:getFlagValue(theZone.activatePulseFlag)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "startPulse?") then
|
if theZone:hasProperty("startPulse?") then
|
||||||
theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "startPulse?", "none")
|
theZone.activatePulseFlag = theZone:getStringFromZoneProperty("startPulse?", "none")
|
||||||
theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value
|
theZone.lastActivateValue = theZone:getFlagValue(theZone.activatePulseFlag)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "pause?") then
|
if theZone:hasProperty("pause?") then
|
||||||
theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pause?", "*none")
|
theZone.pausePulseFlag = theZone:getStringFromZoneProperty("pause?", "*none")
|
||||||
theZone.lastPauseValue = cfxZones.getFlagValue(theZone.pausePulseFlag, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value
|
theZone.lastPauseValue = theZone:getFlagValue(theZone.pausePulseFlag)
|
||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "pausePulse?") then
|
if theZone:hasProperty("pausePulse?") then
|
||||||
theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pausePulse?", "*none")
|
theZone.pausePulseFlag = theZone:getStringFromZoneProperty( "pausePulse?", "*none")
|
||||||
theZone.lastPauseValue = cfxZones.getFlagValue(theZone.pausePulseFlag, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value
|
theZone.lastPauseValue = theZone:getFlagValue(theZone.pausePulseFlag)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- harmonizing on onStart, and converting to old pulsePaused
|
-- harmonizing on onStart, and converting to old pulsePaused
|
||||||
local onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", true)
|
local onStart = theZone:getBoolFromZoneProperty("onStart", true)
|
||||||
theZone.pulsePaused = not (onStart)
|
theZone.pulsePaused = not (onStart)
|
||||||
-- old code, to be deprecated
|
|
||||||
if cfxZones.hasProperty(theZone, "paused") then
|
|
||||||
theZone.pulsePaused = cfxZones.getBoolFromZoneProperty(theZone, "paused", false)
|
|
||||||
|
|
||||||
elseif cfxZones.hasProperty(theZone, "pulseStopped") then
|
theZone.pulseMethod = theZone:getStringFromZoneProperty("method", "inc")
|
||||||
theZone.pulsePaused = cfxZones.getBoolFromZoneProperty(theZone, "pulseStopped", false)
|
|
||||||
end
|
if theZone:hasProperty("outputMethod") then
|
||||||
--]]--
|
theZone.pulseMethod = theZone:getStringFromZoneProperty( "outputMethod", "inc")
|
||||||
|
|
||||||
theZone.pulseMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "flip")
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "pulseMethod") then
|
|
||||||
theZone.pulseMethod = cfxZones.getStringFromZoneProperty(theZone, "pulseMethod", "flip")
|
|
||||||
end
|
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "outputMethod") then
|
|
||||||
theZone.pulseMethod = cfxZones.getStringFromZoneProperty(theZone, "outputMethod", "flip")
|
|
||||||
end
|
end
|
||||||
-- done flag
|
-- done flag
|
||||||
if cfxZones.hasProperty(theZone, "done+1") then
|
if theZone:hasProperty("pulsesDone!") then
|
||||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "*none")
|
theZone.pulseDoneFlag = theZone:getStringFromZoneProperty("pulsesDone!", "*none")
|
||||||
end
|
end
|
||||||
if cfxZones.hasProperty(theZone, "pulsesDone!") then
|
if theZone:hasProperty("done!") then
|
||||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "pulsesDone!", "*none")
|
theZone.pulseDoneFlag = theZone:getStringFromZoneProperty("done!", "*none")
|
||||||
end
|
end
|
||||||
if cfxZones.hasProperty(theZone, "done!") then
|
|
||||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done!", "*none")
|
|
||||||
end
|
|
||||||
|
|
||||||
theZone.pulsing = false -- not running
|
theZone.pulsing = false -- not running
|
||||||
theZone.hasPulsed = false
|
theZone.hasPulsed = false
|
||||||
theZone.zeroPulse = cfxZones.getBoolFromZoneProperty(theZone, "zeroPulse", true)
|
theZone.zeroPulse = theZone:getBoolFromZoneProperty("zeroPulse", true)
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -185,8 +168,7 @@ function pulseFlags.doPulse(args)
|
|||||||
trigger.action.outText("+++pulF: will bang " .. theZone.pulseFlag, 30);
|
trigger.action.outText("+++pulF: will bang " .. theZone.pulseFlag, 30);
|
||||||
end
|
end
|
||||||
|
|
||||||
cfxZones.pollFlag(theZone.pulseFlag, theZone.pulseMethod, theZone)
|
theZone:pollFlag(theZone.pulseFlag, theZone.pulseMethod)
|
||||||
|
|
||||||
-- decrease count
|
-- decrease count
|
||||||
if theZone.pulses > 0 then
|
if theZone.pulses > 0 then
|
||||||
-- only do this if ending
|
-- only do this if ending
|
||||||
@ -196,11 +178,10 @@ function pulseFlags.doPulse(args)
|
|||||||
if theZone.pulsesLeft < 1 then
|
if theZone.pulsesLeft < 1 then
|
||||||
-- increment done flag if set
|
-- increment done flag if set
|
||||||
if theZone.pulseDoneFlag then
|
if theZone.pulseDoneFlag then
|
||||||
--local currVal = cfxZones.getFlagValue(theZone.pulseDoneFlag, theZone)-- trigger.misc.getUserFlag(theZone.pulseDoneFlag)
|
theZone:pollFlag(theZone.pulseDoneFlag, theZone.pulseMethod)
|
||||||
cfxZones.pollFlag(theZone.pulseDoneFlag, "inc", theZone) -- trigger.action.setUserFlag(theZone.pulseDoneFlag, currVal + 1)
|
|
||||||
end
|
end
|
||||||
if pulseFlags.verbose or theZone.verbose then
|
if pulseFlags.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++pulF: pulse <" .. theZone.name .. "> ended!", 30)
|
trigger.action.outText("+++pulF: pulse <" .. theZone.name .. "> ended.", 30)
|
||||||
end
|
end
|
||||||
theZone.pulsing = false
|
theZone.pulsing = false
|
||||||
theZone.pulsePaused = true
|
theZone.pulsePaused = true
|
||||||
@ -218,7 +199,6 @@ function pulseFlags.doPulse(args)
|
|||||||
-- if we get here, schedule next pulse
|
-- if we get here, schedule next pulse
|
||||||
local delay = cfxZones.randomDelayFromPositiveRange(theZone.minTime, theZone.time)
|
local delay = cfxZones.randomDelayFromPositiveRange(theZone.minTime, theZone.time)
|
||||||
|
|
||||||
|
|
||||||
-- schedule in delay time
|
-- schedule in delay time
|
||||||
theZone.scheduledTime = timer.getTime() + delay
|
theZone.scheduledTime = timer.getTime() + delay
|
||||||
theZone.timerID = timer.scheduleFunction(pulseFlags.doPulse, args, theZone.scheduledTime)
|
theZone.timerID = timer.scheduleFunction(pulseFlags.doPulse, args, theZone.scheduledTime)
|
||||||
@ -228,7 +208,6 @@ function pulseFlags.doPulse(args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- start new pulse, will reset
|
-- start new pulse, will reset
|
||||||
function pulseFlags.startNewPulse(theZone)
|
function pulseFlags.startNewPulse(theZone)
|
||||||
theZone.pulsesLeft = theZone.pulses
|
theZone.pulsesLeft = theZone.pulses
|
||||||
@ -241,7 +220,6 @@ function pulseFlags.startNewPulse(theZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function pulseFlags.update()
|
function pulseFlags.update()
|
||||||
-- call me in a second to poll triggers
|
|
||||||
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
||||||
|
|
||||||
for idx, aZone in pairs(pulseFlags.pulses) do
|
for idx, aZone in pairs(pulseFlags.pulses) do
|
||||||
@ -249,10 +227,7 @@ function pulseFlags.update()
|
|||||||
if aZone.pulsing then
|
if aZone.pulsing then
|
||||||
-- this zone has a pulse and has scheduled
|
-- this zone has a pulse and has scheduled
|
||||||
-- a new pulse, nothing to do
|
-- a new pulse, nothing to do
|
||||||
|
|
||||||
else
|
else
|
||||||
-- this zone has not scheduled a new pulse
|
|
||||||
-- let's see why
|
|
||||||
if aZone.pulsePaused then
|
if aZone.pulsePaused then
|
||||||
-- ok, zone is paused. all clear
|
-- ok, zone is paused. all clear
|
||||||
else
|
else
|
||||||
@ -263,7 +238,7 @@ function pulseFlags.update()
|
|||||||
|
|
||||||
-- see if we got a pause or activate command
|
-- see if we got a pause or activate command
|
||||||
-- activatePulseFlag
|
-- activatePulseFlag
|
||||||
if cfxZones.testZoneFlag(aZone, aZone.activatePulseFlag, aZone.pulseTriggerMethod, "lastActivateValue") then
|
if aZone:testZoneFlag(activatePulseFlag, aZone.pulseTriggerMethod, "lastActivateValue") then
|
||||||
if pulseFlags.verbose or aZone.verbose then
|
if pulseFlags.verbose or aZone.verbose then
|
||||||
trigger.action.outText("+++pulF: activating <" .. aZone.name .. ">", 30)
|
trigger.action.outText("+++pulF: activating <" .. aZone.name .. ">", 30)
|
||||||
end
|
end
|
||||||
@ -271,7 +246,7 @@ function pulseFlags.update()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- pausePulseFlag
|
-- pausePulseFlag
|
||||||
if cfxZones.testZoneFlag(aZone, aZone.pausePulseFlag, aZone.pulseTriggerMethod, "lastPauseValue") then
|
if aZone:testZoneFlag(aZone.pausePulseFlag, aZone.pulseTriggerMethod, "lastPauseValue") then
|
||||||
if pulseFlags.verbose or aZone.verbose then
|
if pulseFlags.verbose or aZone.verbose then
|
||||||
trigger.action.outText("+++pulF: pausing <" .. aZone.name .. ">", 30)
|
trigger.action.outText("+++pulF: pausing <" .. aZone.name .. ">", 30)
|
||||||
end
|
end
|
||||||
@ -296,11 +271,9 @@ function pulseFlags.readConfigZone()
|
|||||||
if pulseFlags.verbose then
|
if pulseFlags.verbose then
|
||||||
trigger.action.outText("+++pulF: NO config zone!", 30)
|
trigger.action.outText("+++pulF: NO config zone!", 30)
|
||||||
end
|
end
|
||||||
return
|
theZone = cfxZones.createSimpleZone("pulseFlagsConfig")
|
||||||
end
|
end
|
||||||
|
pulseFlags.verbose = theZone.verbose
|
||||||
pulseFlags.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
|
||||||
|
|
||||||
if pulseFlags.verbose then
|
if pulseFlags.verbose then
|
||||||
trigger.action.outText("+++pulF: read config", 30)
|
trigger.action.outText("+++pulF: read config", 30)
|
||||||
end
|
end
|
||||||
@ -385,25 +358,19 @@ function pulseFlags.start()
|
|||||||
-- read config
|
-- read config
|
||||||
pulseFlags.readConfigZone()
|
pulseFlags.readConfigZone()
|
||||||
|
|
||||||
-- process RND Zones
|
-- process "pulse" Zones - deprecated!!
|
||||||
local attrZones = cfxZones.getZonesWithAttributeNamed("pulse")
|
local attrZones = cfxZones.getZonesWithAttributeNamed("pulse")
|
||||||
-- local a = dcsCommon.getSizeOfTable(attrZones)
|
|
||||||
-- trigger.action.outText("pulse zones: " .. a, 30)
|
|
||||||
-- now create a pulse gen for each one and add them
|
|
||||||
-- to our watchlist
|
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
pulseFlags.createPulseWithZone(aZone) -- process attribute and add to zone
|
pulseFlags.createPulseWithZone(aZone)
|
||||||
pulseFlags.addPulse(aZone) -- remember it so we can pulse it
|
pulseFlags.addPulse(aZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
attrZones = cfxZones.getZonesWithAttributeNamed("pulse!")
|
attrZones = cfxZones.getZonesWithAttributeNamed("pulse!")
|
||||||
a = dcsCommon.getSizeOfTable(attrZones)
|
a = dcsCommon.getSizeOfTable(attrZones)
|
||||||
trigger.action.outText("pulse! zones: " .. a, 30)
|
trigger.action.outText("pulse! zones: " .. a, 30)
|
||||||
-- now create a pulse gen for each one and add them
|
|
||||||
-- to our watchlist
|
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
pulseFlags.createPulseWithZone(aZone) -- process attribute and add to zone
|
pulseFlags.createPulseWithZone(aZone)
|
||||||
pulseFlags.addPulse(aZone) -- remember it so we can pulse it
|
pulseFlags.addPulse(aZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- load any saved data
|
-- load any saved data
|
||||||
@ -417,7 +384,6 @@ function pulseFlags.start()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- start update in 1 second
|
-- start update in 1 second
|
||||||
--pulseFlags.update()
|
|
||||||
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
||||||
|
|
||||||
trigger.action.outText("cfx Pulse Flags v" .. pulseFlags.version .. " started.", 30)
|
trigger.action.outText("cfx Pulse Flags v" .. pulseFlags.version .. " started.", 30)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
raiseFlag = {}
|
raiseFlag = {}
|
||||||
raiseFlag.version = "1.2.1"
|
raiseFlag.version = "2.0.0"
|
||||||
raiseFlag.verbose = false
|
raiseFlag.verbose = false
|
||||||
raiseFlag.requiredLibs = {
|
raiseFlag.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -7,19 +7,18 @@ raiseFlag.requiredLibs = {
|
|||||||
}
|
}
|
||||||
raiseFlag.flags = {}
|
raiseFlag.flags = {}
|
||||||
--[[--
|
--[[--
|
||||||
Raise A Flag module -- (c) 2022 by Christian Franz and cf/x AG
|
Raise A Flag module -- (c) 2022-23 by Christian Franz and cf/x AG
|
||||||
|
|
||||||
Version History
|
|
||||||
1.0.0 - initial release
|
|
||||||
1.0.1 - synonym "raiseFlag!"
|
|
||||||
1.1.0 - DML update
|
|
||||||
1.2.0 - Watchflag update
|
|
||||||
1.2.1 - support for 'inc', 'dec', 'flip'
|
|
||||||
2.0.0 - dmlZones
|
|
||||||
- full method support
|
|
||||||
- full DML upgrade
|
|
||||||
- method attribute (synonym to 'value'
|
|
||||||
|
|
||||||
|
Version History
|
||||||
|
1.0.0 - initial release
|
||||||
|
1.0.1 - synonym "raiseFlag!"
|
||||||
|
1.1.0 - DML update
|
||||||
|
1.2.0 - Watchflag update
|
||||||
|
1.2.1 - support for 'inc', 'dec', 'flip'
|
||||||
|
2.0.0 - dmlZones
|
||||||
|
- full method support
|
||||||
|
- full DML upgrade
|
||||||
|
- method attribute (synonym to 'value')
|
||||||
--]]--
|
--]]--
|
||||||
function raiseFlag.addRaiseFlag(theZone)
|
function raiseFlag.addRaiseFlag(theZone)
|
||||||
table.insert(raiseFlag.flags, theZone)
|
table.insert(raiseFlag.flags, theZone)
|
||||||
@ -32,7 +31,6 @@ function raiseFlag.getRaiseFlagByName(aName)
|
|||||||
if raiseFlag.verbose then
|
if raiseFlag.verbose then
|
||||||
trigger.action.outText("+++rFlg: no raiseFlag with name <" .. aName ..">", 30)
|
trigger.action.outText("+++rFlg: no raiseFlag with name <" .. aName ..">", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,10 +39,10 @@ end
|
|||||||
--
|
--
|
||||||
function raiseFlag.createRaiseFlagWithZone(theZone)
|
function raiseFlag.createRaiseFlagWithZone(theZone)
|
||||||
-- get flag from faiseFlag itself
|
-- get flag from faiseFlag itself
|
||||||
if cfxZones.hasProperty(theZone, "raiseFlag") then
|
if theZone:hasProperty("raiseFlag") then
|
||||||
theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag", "<none>") -- the flag to raise
|
theZone.raiseFlag = theZone:getStringFromZoneProperty("raiseFlag", "<none>") -- the flag to raise
|
||||||
else
|
else
|
||||||
theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag!", "<none>") -- the flag to raise
|
theZone.raiseFlag = theZone:getStringFromZoneProperty("raiseFlag!", "<none>") -- the flag to raise
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pre-method DML raiseFlag is now upgraded to method.
|
-- pre-method DML raiseFlag is now upgraded to method.
|
||||||
@ -55,12 +53,7 @@ function raiseFlag.createRaiseFlagWithZone(theZone)
|
|||||||
theZone.flagValue = theZone:getStringFromZoneProperty("method", "inc")
|
theZone.flagValue = theZone:getStringFromZoneProperty("method", "inc")
|
||||||
end
|
end
|
||||||
theZone.flagValue = theZone.flagValue:lower()
|
theZone.flagValue = theZone.flagValue:lower()
|
||||||
|
|
||||||
theZone.minAfterTime, theZone.maxAfterTime = theZone:getPositiveRangeFromZoneProperty("afterTime", -1)
|
theZone.minAfterTime, theZone.maxAfterTime = theZone:getPositiveRangeFromZoneProperty("afterTime", -1)
|
||||||
|
|
||||||
-- method for triggering
|
|
||||||
-- watchflag:
|
|
||||||
-- triggerMethod
|
|
||||||
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||||
if theZone:hasProperty("raiseTriggerMethod") then
|
if theZone:hasProperty("raiseTriggerMethod") then
|
||||||
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty("raiseTriggerMethod", "change")
|
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty("raiseTriggerMethod", "change")
|
||||||
@ -70,7 +63,6 @@ function raiseFlag.createRaiseFlagWithZone(theZone)
|
|||||||
theZone.triggerStopFlag = theZone:getStringFromZoneProperty( "stopFlag?", "none")
|
theZone.triggerStopFlag = theZone:getStringFromZoneProperty( "stopFlag?", "none")
|
||||||
theZone.lastTriggerStopValue = theZone:getFlagValue(theZone.triggerStopFlag) -- save last value
|
theZone.lastTriggerStopValue = theZone:getFlagValue(theZone.triggerStopFlag) -- save last value
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.scheduleID = nil
|
theZone.scheduleID = nil
|
||||||
theZone.raiseStopped = false
|
theZone.raiseStopped = false
|
||||||
|
|
||||||
@ -94,21 +86,6 @@ function raiseFlag.triggered(args)
|
|||||||
if raiseFlag.verbose or theZone.verbose then
|
if raiseFlag.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++rFlg - raising <" .. theZone.raiseFlag .. "> with method '" .. command .. "'" ,30)
|
trigger.action.outText("+++rFlg - raising <" .. theZone.raiseFlag .. "> with method '" .. command .. "'" ,30)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[--
|
|
||||||
command = dcsCommon.trim(command)
|
|
||||||
if command == "inc" or command == "dec" or command == "flip" then
|
|
||||||
cfxZones.pollFlag(theZone.raiseFlag, command, theZone)
|
|
||||||
if raiseFlag.verbose or theZone.verbose then
|
|
||||||
trigger.action.outText("+++rFlg - raising <" .. theZone.raiseFlag .. "> with method " .. command ,30)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
cfxZones.setFlagValue(theZone.raiseFlag, theZone.flagValue, theZone)
|
|
||||||
if raiseFlag.verbose or theZone.verbose then
|
|
||||||
trigger.action.outText("+++rFlg - raising <" .. theZone.raiseFlag .. "> to value: " .. theZone.flagValue ,30)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--]]--
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -117,28 +94,23 @@ end
|
|||||||
function raiseFlag.update()
|
function raiseFlag.update()
|
||||||
-- call me in a second to poll triggers
|
-- call me in a second to poll triggers
|
||||||
timer.scheduleFunction(raiseFlag.update, {}, timer.getTime() + 1)
|
timer.scheduleFunction(raiseFlag.update, {}, timer.getTime() + 1)
|
||||||
|
|
||||||
for idx, aZone in pairs(raiseFlag.flags) do
|
for idx, aZone in pairs(raiseFlag.flags) do
|
||||||
-- make sure to re-start before reading time limit
|
-- make sure to re-start before reading time limit
|
||||||
if aZone:testZoneFlag(aZone.triggerStopFlag, aZone.raiseTriggerMethod, "lastTriggerStopValue") then
|
if aZone:testZoneFlag(aZone.triggerStopFlag, aZone.raiseTriggerMethod, "lastTriggerStopValue") then
|
||||||
theZone.raiseStopped = true -- we are done, no flag!
|
theZone.raiseStopped = true -- we are done, no flag!
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- config & go!
|
-- config & go!
|
||||||
--
|
--
|
||||||
|
|
||||||
function raiseFlag.readConfigZone()
|
function raiseFlag.readConfigZone()
|
||||||
local theZone = cfxZones.getZoneByName("raiseFlagConfig")
|
local theZone = cfxZones.getZoneByName("raiseFlagConfig")
|
||||||
if not theZone then
|
if not theZone then
|
||||||
theZone = cfxZones.createSimpleZone("raiseFlagConfig")
|
theZone = cfxZones.createSimpleZone("raiseFlagConfig")
|
||||||
end
|
end
|
||||||
|
|
||||||
raiseFlag.verbose = theZone.verbose
|
raiseFlag.verbose = theZone.verbose
|
||||||
|
|
||||||
if raiseFlag.verbose then
|
if raiseFlag.verbose then
|
||||||
trigger.action.outText("+++rFlg: read config", 30)
|
trigger.action.outText("+++rFlg: read config", 30)
|
||||||
end
|
end
|
||||||
@ -157,7 +129,7 @@ function raiseFlag.start()
|
|||||||
-- read config
|
-- read config
|
||||||
raiseFlag.readConfigZone()
|
raiseFlag.readConfigZone()
|
||||||
|
|
||||||
-- process cloner Zones
|
-- process raise Flags Zones
|
||||||
local attrZones = cfxZones.getZonesWithAttributeNamed("raiseFlag")
|
local attrZones = cfxZones.getZonesWithAttributeNamed("raiseFlag")
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes
|
raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
stopGap = {}
|
stopGap = {}
|
||||||
stopGap.version = "1.0.9"
|
stopGap.version = "1.0.10"
|
||||||
stopGap.verbose = false
|
stopGap.verbose = false
|
||||||
stopGap.ssbEnabled = true
|
stopGap.ssbEnabled = true
|
||||||
stopGap.ignoreMe = "-sg"
|
stopGap.ignoreMe = "-sg"
|
||||||
@ -48,6 +48,7 @@ stopGap.requiredLibs = {
|
|||||||
1.0.8 - added refreshInterval option as requested
|
1.0.8 - added refreshInterval option as requested
|
||||||
- refresh attribute config zone
|
- refresh attribute config zone
|
||||||
1.0.9 - in line with standalone (optimization not required for DML)
|
1.0.9 - in line with standalone (optimization not required for DML)
|
||||||
|
1.0.10 - some more verbosity for spIgnore and sgIgnore zones (DML only)
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -356,12 +357,22 @@ end
|
|||||||
--
|
--
|
||||||
function stopGap.createStopGapZone(theZone)
|
function stopGap.createStopGapZone(theZone)
|
||||||
local sg = theZone:getBoolFromZoneProperty("stopGap", true)
|
local sg = theZone:getBoolFromZoneProperty("stopGap", true)
|
||||||
if sg then theZone.sgIgnore = false else theZone.sgIgnore = true end
|
if sg then theZone.sgIgnore = false else
|
||||||
|
if theZone.verbose or stopGap.verbose then
|
||||||
|
trigger.action.outText("++sg: Ignoring player craft in zone <" ..theZone.name .."> for all modes", 30)
|
||||||
|
end
|
||||||
|
theZone.sgIgnore = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function stopGap.createStopGapSPZone(theZone)
|
function stopGap.createStopGapSPZone(theZone)
|
||||||
local sp = theZone:getBoolFromZoneProperty("stopGapSP", true)
|
local sp = theZone:getBoolFromZoneProperty("stopGapSP", true)
|
||||||
if sp then theZone.spIgnore = false else theZone.spIgnore = true end
|
if sp then theZone.spIgnore = false else
|
||||||
|
if theZone.verbose or stopGap.verbose then
|
||||||
|
trigger.action.outText("++sg: Ignoring player craft in zone <" ..theZone.name .."> for single-player mode", 30)
|
||||||
|
end
|
||||||
|
theZone.spIgnore = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tutorial & demo missions/demo - boom boom.miz
Normal file
BIN
tutorial & demo missions/demo - boom boom.miz
Normal file
Binary file not shown.
Binary file not shown.
BIN
tutorial & demo missions/demo - types and civil liveries.miz
Normal file
BIN
tutorial & demo missions/demo - types and civil liveries.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user