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.version = "1.4.1"
|
||||
rndFlags.version = "2.0.0"
|
||||
rndFlags.verbose = false
|
||||
rndFlags.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -33,6 +33,7 @@ rndFlags.requiredLibs = {
|
||||
- minor clean-up
|
||||
1.4.0 - persistence
|
||||
1.4.1 - a little less verbosity
|
||||
2.0.0 - dmlZones, OOP
|
||||
|
||||
--]]
|
||||
|
||||
@ -59,14 +60,14 @@ end
|
||||
--
|
||||
function rndFlags.createRNDWithZone(theZone)
|
||||
local flags = ""
|
||||
if cfxZones.hasProperty(theZone, "RND!") then
|
||||
flags = cfxZones.getStringFromZoneProperty(theZone, "RND!", "")
|
||||
elseif cfxZones.hasProperty(theZone, "flags!") then
|
||||
if theZone:hasProperty("RND!") then
|
||||
flags = theZone:getStringFromZoneProperty("RND!", "")
|
||||
elseif theZone:hasProperty("flags!") then
|
||||
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: deprecated 'flags!' usage, use 'RND!' instead.", 30)
|
||||
flags = cfxZones.getStringFromZoneProperty(theZone, "flags!", "")
|
||||
elseif cfxZones.hasProperty(theZone, "flags") then
|
||||
flags = theZone:getStringFromZoneProperty("flags!", "")
|
||||
elseif theZone:hasProperty("flags") then
|
||||
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
|
||||
trigger.action.outText("+++RND: warning - zone <" .. theZone.name .. ">: no flags defined!", 30)
|
||||
end
|
||||
@ -78,73 +79,65 @@ function rndFlags.createRNDWithZone(theZone)
|
||||
trigger.action.outText("+++RND: output set for <" .. theZone.name .. "> is <" .. flags .. ">",30)
|
||||
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
|
||||
trigger.action.outText("+++RND: pollSize is <" .. theZone.pollSizeMin .. ", " .. theZone.pollSize .. ">", 30)
|
||||
end
|
||||
|
||||
|
||||
theZone.remove = cfxZones.getBoolFromZoneProperty(theZone, "remove", false)
|
||||
theZone.remove = theZone:getBoolFromZoneProperty("remove", false)
|
||||
theZone.rndTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||
|
||||
-- watchflag:
|
||||
-- triggerMethod
|
||||
theZone.rndTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
||||
|
||||
if cfxZones.hasProperty(theZone, "rndTriggerMethod") then
|
||||
theZone.rndTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "rndTriggerMethod", "change")
|
||||
if theZone:hasProperty("rndTriggerMethod") then
|
||||
theZone.rndTriggerMethod = theZone:getStringFromZoneProperty("rndTriggerMethod", "change")
|
||||
end
|
||||
|
||||
-- trigger flag
|
||||
if cfxZones.hasProperty(theZone, "f?") then
|
||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
|
||||
if theZone:hasProperty("f?") then
|
||||
theZone.triggerFlag = theZone:getStringFromZoneProperty("f?", "none")
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "in?") then
|
||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none")
|
||||
if theZone:hasProperty("in?") then
|
||||
theZone.triggerFlag = theZone:getStringFromZoneProperty("in?", "none")
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "rndPoll?") then
|
||||
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "rndPoll?", "none")
|
||||
if theZone:hasProperty("rndPoll?") then
|
||||
theZone.triggerFlag = theZone:getStringFromZoneProperty("rndPoll?", "none")
|
||||
end
|
||||
|
||||
|
||||
if theZone.triggerFlag then
|
||||
theZone.lastTriggerValue = cfxZones.getFlagValue(theZone.triggerFlag, theZone)
|
||||
theZone.lastTriggerValue = theZone:getFlagValue(theZone.triggerFlag)
|
||||
if rndFlags.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++RND: randomizer in <" .. theZone:getName() .. "> triggers on flag <" .. theZone.triggerFlag .. ">", 30)
|
||||
end
|
||||
--trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value
|
||||
end
|
||||
|
||||
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
||||
theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false)
|
||||
|
||||
if not theZone.onStart and not theZone.triggerFlag then
|
||||
-- theZone.onStart = true
|
||||
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
|
||||
trigger.action.outText("+++RND - WARNING: no triggers and no onStart, RND in <" .. theZone.name .. "> can't be triggered.", 30)
|
||||
end
|
||||
|
||||
theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
|
||||
if cfxZones.hasProperty(theZone, "rndMethod") then
|
||||
theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "rndMethod", "inc")
|
||||
theZone.rndMethod = theZone:getStringFromZoneProperty("method", "inc")
|
||||
if theZone:hasProperty("rndMethod") then
|
||||
theZone.rndMethod = theZone:getStringFromZoneProperty("rndMethod", "inc")
|
||||
end
|
||||
|
||||
theZone.reshuffle = cfxZones.getBoolFromZoneProperty(theZone, "reshuffle", false)
|
||||
theZone.reshuffle = theZone:getBoolFromZoneProperty("reshuffle", false)
|
||||
if theZone.reshuffle then
|
||||
-- create a backup copy we can reshuffle from
|
||||
theZone.flagStore = dcsCommon.copyArray(theFlags)
|
||||
end
|
||||
|
||||
-- done flag OLD, to be deprecated
|
||||
if cfxZones.hasProperty(theZone, "done+1") then
|
||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "<none>")
|
||||
if theZone:hasProperty("done+1") then
|
||||
theZone.doneFlag = theZone:getStringFromZoneProperty("done+1", "<none>")
|
||||
trigger.action.outText("Warning: RND zone <" .. theZone.name .. "> uses depreceated 'done+1'.", 30)
|
||||
|
||||
-- now NEW replacements
|
||||
elseif cfxZones.hasProperty(theZone, "done!") then
|
||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done!", "<none>")
|
||||
elseif cfxZones.hasProperty(theZone, "rndDone!") then
|
||||
theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "rndDone!", "<none>")
|
||||
elseif theZone:hasProperty("done!") then
|
||||
theZone.doneFlag = theZone:getStringFromZoneProperty("done!", "<none>")
|
||||
elseif theZone:hasProperty("rndDone!") then
|
||||
theZone.doneFlag = theZone.getStringFromZoneProperty("rndDone!", "<none>")
|
||||
end
|
||||
|
||||
end
|
||||
@ -210,7 +203,7 @@ function rndFlags.fire(theZone)
|
||||
trigger.action.outText("+++RND: polling " .. theFlag .. " with " .. theZone.rndMethod, 30)
|
||||
end
|
||||
|
||||
cfxZones.pollFlag(theFlag, theZone.rndMethod, theZone)
|
||||
theZone:pollFlag(theFlag, theZone.rndMethod)
|
||||
end
|
||||
|
||||
-- remove if requested
|
||||
@ -317,9 +310,7 @@ function rndFlags.readConfigZone()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
rndFlags.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||
|
||||
rndFlags.verbose = theZone.verbose
|
||||
if rndFlags.verbose then
|
||||
trigger.action.outText("***RND: read config", 30)
|
||||
end
|
||||
@ -349,17 +340,15 @@ function rndFlags.start()
|
||||
-- now create an rnd gen for each one and add them
|
||||
-- to our watchlist
|
||||
for k, aZone in pairs(attrZones) do
|
||||
rndFlags.createRNDWithZone(aZone) -- process attribute and add to zone
|
||||
rndFlags.addRNDZone(aZone) -- remember it so we can smoke it
|
||||
rndFlags.createRNDWithZone(aZone)
|
||||
rndFlags.addRNDZone(aZone)
|
||||
end
|
||||
|
||||
-- obsolete here
|
||||
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
|
||||
rndFlags.createRNDWithZone(aZone) -- process attribute and add to zone
|
||||
rndFlags.addRNDZone(aZone) -- remember it so we can smoke it
|
||||
rndFlags.createRNDWithZone(aZone)
|
||||
rndFlags.addRNDZone(aZone)
|
||||
end
|
||||
|
||||
-- persistence
|
||||
|
||||
@ -1,9 +1,15 @@
|
||||
tdz = {}
|
||||
tdz.version = "0.9.0dev"
|
||||
tdz.version = "1.0.0"
|
||||
tdz.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
"cfxZones", -- Zones, of course
|
||||
}
|
||||
--[[--
|
||||
VERSION HISTORY
|
||||
1.0.0 - Initial version
|
||||
|
||||
--]]--
|
||||
|
||||
tdz.allTdz = {}
|
||||
tdz.watchlist = {}
|
||||
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
|
||||
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)
|
||||
if not a then a = 0 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)
|
||||
-- make it a dml zone
|
||||
local theNewZone = cfxZones.createSimplePolyZone(name, center, poly)
|
||||
return theNewZone--, left, right
|
||||
return theNewZone
|
||||
end
|
||||
|
||||
--
|
||||
@ -181,7 +163,6 @@ function tdz.playerLanded(theUnit, playerName)
|
||||
-- make sure unit names match?
|
||||
local entry = tdz.watchlist[playerName]
|
||||
entry.hops = entry.hops + 1 -- uh oh.
|
||||
-- trigger.action.outText("Bump!")
|
||||
end
|
||||
|
||||
-- we may want to filter helicopters
|
||||
@ -226,7 +207,6 @@ function tdz.playerLanded(theUnit, playerName)
|
||||
if dOpHdg < dHdg then
|
||||
opposite = true
|
||||
dHdg = dOpHdg
|
||||
trigger.action.outText("opposite rwy detected", 30)
|
||||
end
|
||||
if dHdg > math.pi * 1.5 then -- > 270+
|
||||
dHdg = dHdg - math.pi * 1.5
|
||||
|
||||
@ -1,18 +1,34 @@
|
||||
bombRange = {}
|
||||
bombRange.version = "1.0.0"
|
||||
bombRange.version = "1.1.0"
|
||||
bombRange.dh = 1 -- meters above ground level burst
|
||||
|
||||
bombRange.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
"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.collector = {} -- post-impact collections for 0.5 secs
|
||||
bombRange.ranges = {} -- all bomb ranges
|
||||
bombRange.playerData = {} -- player accumulated data
|
||||
bombRange.unitComms = {} -- command interface per unit
|
||||
bombRange.tracking = false -- if true, we are tracking projectiles
|
||||
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)
|
||||
table.insert(bombRange.bombs, theBomb)
|
||||
@ -44,7 +60,7 @@ function bombRange.createRange(theZone) -- has bombRange attribte to mark it
|
||||
end
|
||||
theZone.details = theZone:getBoolFromZoneProperty("details", false)
|
||||
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.smokeColor = theZone:getSmokeColorStringFromZoneProperty("smokeColor", "blue")
|
||||
theZone.flagHits = theZone:getBoolFromZoneProperty("flagHits", false)
|
||||
@ -237,26 +253,51 @@ end
|
||||
-- Event Proccing
|
||||
--
|
||||
function bombRange.suspectedHit(weapon, target)
|
||||
if not bombRange.tracking then
|
||||
return
|
||||
end
|
||||
local wType = weapon:getTypeName()
|
||||
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
|
||||
if theType == aType then return end
|
||||
if theType == aType then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- try and match target to my known statics, exit if match
|
||||
if not target.getID then return end -- units have no getID!
|
||||
local theID = tonumber(target:getID())
|
||||
if bombRange.myStatics[theID] then
|
||||
return
|
||||
if target.getID then -- units have no getID, so skip for those
|
||||
local theID = tonumber(target:getID())
|
||||
if bombRange.myStatics[theID] then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- look through the tracked weapons for a match
|
||||
local filtered = {}
|
||||
-- look through the collector (recent impacted) first
|
||||
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
|
||||
if b.weapon == weapon then
|
||||
hasfound = true
|
||||
@ -264,6 +305,8 @@ function bombRange.suspectedHit(weapon, target)
|
||||
b.pos = weapon:getPoint()
|
||||
b.v = weapon:getVelocity()
|
||||
bombRange.impacted(b, target)
|
||||
|
||||
-- trigger.action.outText("susHit: filtering live b <" .. b.name .. ">", 30)
|
||||
else
|
||||
table.insert(filtered, b)
|
||||
end
|
||||
@ -273,16 +316,106 @@ function bombRange.suspectedHit(weapon, target)
|
||||
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)
|
||||
if not event.initiator then return end
|
||||
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
|
||||
bombRange.suspectedHit(event.weapon, event.target)
|
||||
return
|
||||
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 pName = nil
|
||||
if theUnit.getPlayerName and theUnit:getPlayerName() ~= nil then
|
||||
@ -314,6 +447,7 @@ function bombRange:onEvent(event)
|
||||
b.weapon = w
|
||||
b.released = timer.getTime()
|
||||
b.relPos = b.pos
|
||||
b.ID = dcsCommon.uuid("bomb")
|
||||
table.insert(bombRange.bombs, b)
|
||||
if not bombRange.tracking then
|
||||
timer.scheduleFunction(bombRange.updateBombs, {}, timer.getTime() + 1/bombRange.ups)
|
||||
@ -336,14 +470,25 @@ end
|
||||
--
|
||||
-- Update
|
||||
--
|
||||
function bombRange.impacted(weapon, target)
|
||||
function bombRange.impacted(weapon, target, finalPass)
|
||||
local targetName = nil
|
||||
local ipos = weapon.pos -- default to weapon location
|
||||
if target then
|
||||
ipos = target:getPoint()
|
||||
if target then
|
||||
targetName = target:getDesc()
|
||||
if targetName then targetName = targetName.displayName 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
|
||||
-- not an object hit, interpolate the impact point on ground:
|
||||
-- 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)
|
||||
return
|
||||
end
|
||||
|
||||
if minDist > theRange.clipDist then
|
||||
-- no taget zone inside clip dist. disregard this one, too far off
|
||||
if bombRange.reportLongMisses then
|
||||
@ -383,11 +529,11 @@ function bombRange.impacted(weapon, target)
|
||||
return
|
||||
end
|
||||
|
||||
if theRange.smokeHits then
|
||||
if (not target) and theRange.smokeHits then
|
||||
trigger.action.smoke(ipos, theRange.smokeColor)
|
||||
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 p = {x=ipos.x, y=ipos.z}
|
||||
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)
|
||||
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
|
||||
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 tDist = dcsCommon.dist(ipos, weapon.relPos)/1000
|
||||
tDist = math.floor(tDist*100) /100
|
||||
@ -404,7 +579,7 @@ function bombRange.impacted(weapon, target)
|
||||
end
|
||||
|
||||
local msg = ""
|
||||
if theRange:pointInZone(ipos) then
|
||||
if impactInside then
|
||||
local percentage = 0
|
||||
if theRange.isPoly then
|
||||
percentage = 100
|
||||
@ -430,29 +605,45 @@ function bombRange.impacted(weapon, target)
|
||||
bombRange.addImpactForWeapon(weapon, true, percentage)
|
||||
else
|
||||
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.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."
|
||||
bombRange.addImpactForWeapon(weapon, false, 0)
|
||||
end
|
||||
if theRange.reporter then
|
||||
trigger.action.outTextForGroup(weapon.gID,msg , 30)
|
||||
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
|
||||
|
||||
function bombRange.updateBombs()
|
||||
|
||||
local now = timer.getTime()
|
||||
local filtered = {}
|
||||
for idx, theWeapon in pairs(bombRange.bombs) do
|
||||
if Weapon.isExist(theWeapon.weapon) then
|
||||
-- update pos and vel
|
||||
theWeapon.pos = theWeapon.weapon:getPoint()
|
||||
theWeapon.v = theWeapon.weapon:getVelocity()
|
||||
theWeapon.t = now
|
||||
table.insert(filtered, theWeapon)
|
||||
else
|
||||
-- interpolate the impact position from last position
|
||||
bombRange.impacted(theWeapon)
|
||||
-- put on collector to time out in 1 seconds to allow
|
||||
-- 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
|
||||
|
||||
@ -468,6 +659,19 @@ function bombRange.updateBombs()
|
||||
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
|
||||
--
|
||||
@ -508,7 +712,7 @@ function bombRange.readConfigZone()
|
||||
bombRange.filterTypes = dcsCommon.trimArray(theSet)
|
||||
bombRange.reportLongMisses = theZone:getBoolFromZoneProperty("reportLongMisses", 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")
|
||||
if theZone:hasProperty("signIn!") then
|
||||
bombRange.signIn = theZone:getStringFromZoneProperty("signIn!", 30)
|
||||
@ -551,6 +755,9 @@ function bombRange.start()
|
||||
-- add event handler
|
||||
world.addEventHandler(bombRange)
|
||||
|
||||
-- start GC
|
||||
bombRange.GC()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
cfxObjectDestructDetector = {}
|
||||
cfxObjectDestructDetector.version = "1.3.0"
|
||||
cfxObjectDestructDetector.version = "2.0.0"
|
||||
cfxObjectDestructDetector.verbose = false
|
||||
cfxObjectDestructDetector.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -12,11 +12,11 @@ cfxObjectDestructDetector.requiredLibs = {
|
||||
1.1.0 added support for method, f! and destroyed!
|
||||
1.2.0 DML / Watchflag support
|
||||
1.3.0 Persistence support
|
||||
|
||||
|
||||
Detect when an object with OBJECT ID as assigned in ME dies
|
||||
*** EXTENDS ZONES
|
||||
|
||||
2.0.0 dmlZone OOP support
|
||||
clean-up
|
||||
re-wrote object determination to not be affected by
|
||||
ID changes (happens with map updates)
|
||||
fail addZone when name property is missing
|
||||
--]]--
|
||||
|
||||
cfxObjectDestructDetector.objectZones = {}
|
||||
@ -31,7 +31,7 @@ end
|
||||
|
||||
function cfxObjectDestructDetector.invokeCallbacksFor(zone)
|
||||
for idx, theCB in pairs (cfxObjectDestructDetector.callbacks) do
|
||||
theCB(zone, zone.ID, zone.name)
|
||||
theCB(zone, zone.ID, zone.name, zone.objName)
|
||||
end
|
||||
end
|
||||
|
||||
@ -55,104 +55,55 @@ end
|
||||
-- processing of zones
|
||||
--
|
||||
function cfxObjectDestructDetector.processObjectDestructZone(aZone)
|
||||
aZone.name = cfxZones.getStringFromZoneProperty(aZone, "NAME", aZone.name)
|
||||
-- aZone.coalition = cfxZones.getCoalitionFromZoneProperty(aZone, "coalition", 0)
|
||||
aZone.ID = cfxZones.getNumberFromZoneProperty(aZone, "OBJECT ID", 1) -- THIS!
|
||||
if aZone:hasProperty("name") then
|
||||
aZone.objName = string.upper(aZone:getStringFromZoneProperty("NAME", "default"))
|
||||
else
|
||||
trigger.action.outText("+++OOD: Zone <" .. aZone.name .. "> lacks name attribute, ignored for destruct detection.")
|
||||
return false
|
||||
end
|
||||
|
||||
-- persistence interface
|
||||
aZone.isDestroyed = false
|
||||
|
||||
--[[-- old code, to be decom'd --]]--
|
||||
if cfxZones.hasProperty(aZone, "setFlag") then
|
||||
aZone.setFlag = cfxZones.getStringFromZoneProperty(aZone, "setFlag", "999")
|
||||
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")
|
||||
aZone.oddMethod = aZone:getStringFromZoneProperty("method", "inc")
|
||||
if aZone:hasProperty("oddMethod") then
|
||||
aZone.oddMethod = aZone:getStringFromZoneProperty("oddMethod", "inc")
|
||||
end
|
||||
|
||||
-- DML method support
|
||||
aZone.oddMethod = cfxZones.getStringFromZoneProperty(aZone, "method", "inc")
|
||||
if cfxZones.hasProperty(aZone, "oddMethod") then
|
||||
aZone.oddMethod = cfxZones.getStringFromZoneProperty(aZone, "oddMethod", "inc")
|
||||
end
|
||||
|
||||
|
||||
-- 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")
|
||||
if aZone:hasProperty("f!") then
|
||||
aZone.outDestroyFlag = aZone:getStringFromZoneProperty("f!", "*none")
|
||||
elseif aZone:hasProperty("destroyed!") then
|
||||
aZone.outDestroyFlag = aZone:getStringFromZoneProperty("destroyed!", "*none")
|
||||
elseif aZone:hasProperty("objectDestroyed!") then
|
||||
aZone.outDestroyFlag = aZone:getStringFromZoneProperty( "objectDestroyed!", "*none")
|
||||
end
|
||||
return true
|
||||
end
|
||||
--
|
||||
-- MAIN DETECTOR
|
||||
-- ON EVENT
|
||||
--
|
||||
-- invoke callbacks when an object was destroyed
|
||||
function cfxObjectDestructDetector:onEvent(event)
|
||||
if event.id == world.event.S_EVENT_DEAD then
|
||||
if not event.initiator then return end
|
||||
local id = event.initiator:getName()
|
||||
if not id then return end
|
||||
local theObject = event.initiator
|
||||
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
|
||||
if (not aZone.isDestroyed) and aZone.ID == id 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 (not aZone.isDestroyed) and aZone.objName == matchMe then
|
||||
if aZone.outDestroyFlag then
|
||||
cfxZones.pollFlag(aZone.outDestroyFlag, aZone.oddMethod, aZone)
|
||||
aZone:pollFlag(aZone.outDestroyFlag, aZone.oddMethod)
|
||||
end
|
||||
|
||||
-- invoke callbacks
|
||||
cfxObjectDestructDetector.invokeCallbacksFor(aZone)
|
||||
if aZone.verbose or cfxObjectDestructDetector.verbose then
|
||||
trigger.action.outText("OBJECT KILL: " .. id, 30)
|
||||
end
|
||||
|
||||
-- we could now remove the object from the list
|
||||
-- for better performance since it cant
|
||||
-- die twice
|
||||
|
||||
-- save state for persistence
|
||||
aZone.isDestroyed = true
|
||||
|
||||
aZone.isDestroyed = true
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -172,7 +123,7 @@ function cfxObjectDestructDetector.saveData() -- invoked by persistence
|
||||
-- the isDestroyed and flag info info
|
||||
info = {}
|
||||
info.isDestroyed = aZone.isDestroyed
|
||||
info.outDestroyVal = cfxZones.getFlagValue(aZone.outDestroyFlag, aZone)
|
||||
info.outDestroyVal = aZone:getFlagValue(aZone.outDestroyFlag)
|
||||
zoneInfo[aZone.name] = info
|
||||
end
|
||||
-- expasion proof: assign as own field
|
||||
@ -202,7 +153,7 @@ function cfxObjectDestructDetector.loadMission()
|
||||
local theZone = cfxObjectDestructDetector.getObjectDetectZoneByName(zName)
|
||||
if theZone then
|
||||
theZone.isDestroyed = info.isDestroyed
|
||||
cfxZones.setFlagValue(theZone.outDestroyFlag, info.outDestroyVal, theZone)
|
||||
theZone:setFlagValue(theZone.outDestroyFlag, info.outDestroyVal)
|
||||
if cfxObjectDestructDetector.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++oDDet: persistence setting flag <" .. theZone.outDestroyFlag .. "> to <" .. info.outDestroyVal .. ">",30)
|
||||
end
|
||||
@ -246,14 +197,14 @@ function cfxObjectDestructDetector.start()
|
||||
return false
|
||||
end
|
||||
|
||||
-- collect all zones with 'OBJECT id' attribute
|
||||
-- collect all spawn zones
|
||||
-- collect all zones with 'OBJECT ID' attribute
|
||||
local attrZones = cfxZones.getZonesWithAttributeNamed("OBJECT ID")
|
||||
|
||||
|
||||
for k, aZone in pairs(attrZones) do
|
||||
cfxObjectDestructDetector.processObjectDestructZone(aZone) -- process attribute and add to zone properties (extend zone)
|
||||
cfxObjectDestructDetector.addObjectDetectZone(aZone)
|
||||
if cfxObjectDestructDetector.processObjectDestructZone(aZone) then
|
||||
cfxObjectDestructDetector.addObjectDetectZone(aZone)
|
||||
end
|
||||
end
|
||||
|
||||
-- add myself as event handler
|
||||
@ -276,8 +227,6 @@ function cfxObjectDestructDetector.start()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- say hi
|
||||
trigger.action.outText("cfx Object Destruct Zones v" .. cfxObjectDestructDetector.version .. " started.", 30)
|
||||
return true
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
civAir = {}
|
||||
civAir.version = "2.0.0"
|
||||
civAir.version = "3.0.0"
|
||||
--[[--
|
||||
1.0.0 initial version
|
||||
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
|
||||
flights are now of random neutral countries
|
||||
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.initialAirSpawns = true -- when true has population spawn in-air at start
|
||||
civAir.verbose = false
|
||||
|
||||
-- aircraftTypes contains the type names for the neutral air traffic
|
||||
-- each entry has the same chance to be chose, so to make an
|
||||
-- aircraft more probably to appear, add its type multiple times
|
||||
-- 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
|
||||
civAir.aircraftTypes = {}
|
||||
civAir.dcsBuiltinTypes = {"Yak-40", "C-130", "C-17A", "IL-76MD", "An-30M", "An-26B"}
|
||||
civAir.CAMTypes = { "A_320", "A_330", "A_380", "B_727", "B_737", "B_747", "B_757", "Cessna_210N", "DC_10",}
|
||||
|
||||
-- maxTraffic is the number of neutral flights that are
|
||||
-- concurrently under way
|
||||
civAir.liveries = {
|
||||
|
||||
-- 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.maxIdle = 8 * 60 -- seconds of ide time before it is removed after landing
|
||||
|
||||
|
||||
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 = {}
|
||||
-- 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.landingOnly = {} -- use only to land at
|
||||
civAir.inoutZones = {} -- off-map connector zones
|
||||
@ -86,40 +104,106 @@ function civAir.readConfigZone()
|
||||
-- note: must match exactly!!!!
|
||||
local theZone = cfxZones.getZoneByName("civAirConfig")
|
||||
if not theZone then
|
||||
trigger.action.outText("***civA: NO config zone!", 30)
|
||||
theZone = cfxZones.createSimpleZone("civAirConfig")
|
||||
end
|
||||
|
||||
-- ok, for each property, load it if it exists
|
||||
if theZone:hasProperty("aircraftTypes") then
|
||||
local theTypes = theZone:getStringFromZoneProperty( "aircraftTypes", civAir.aircraftTypes) -- "Yak-40")
|
||||
local typeArray = dcsCommon.splitString(theTypes, ",")
|
||||
typeArray = dcsCommon.trimArray(typeArray)
|
||||
civAir.aircraftTypes = typeArray
|
||||
end
|
||||
civAir.verbose = theZone.verbose
|
||||
civAir.ups = theZone:getNumberFromZoneProperty("ups", 0.05)
|
||||
if civAir.ups < .0001 then civAir.ups = 0.05 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
|
||||
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxTraffic", 10)
|
||||
elseif theZone:hasProperty("maxFlights") then
|
||||
else --if theZone:hasProperty("maxFlights") then
|
||||
civAir.maxTraffic = theZone:getNumberFromZoneProperty( "maxFlights", 10)
|
||||
end
|
||||
|
||||
-- if theZone:hasProperty("maxIdle") then
|
||||
civAir.maxIdle = theZone:getNumberFromZoneProperty("maxIdle", 8 * 60)
|
||||
-- end
|
||||
civAir.maxIdle = theZone:getNumberFromZoneProperty("maxIdle", 8 * 60)
|
||||
|
||||
-- if theZone:hasProperty("initialAirSpawns") then
|
||||
civAir.initialAirSpawns = theZone:getBoolFromZoneProperty( "initialAirSpawns", true)
|
||||
-- end
|
||||
civAir.initialAirSpawns = theZone:getBoolFromZoneProperty( "initialAirSpawns", true)
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
local value = theZone:getStringFromZoneProperty("civAir", "")
|
||||
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
|
||||
table.insert(civAir.departOnly, inoutName) -- start in inbound zone
|
||||
civAir.inoutZones[inoutName] = theZone
|
||||
-- theZone.inbound = true
|
||||
elseif dcsCommon.stringStartsWith(value, "outb") then
|
||||
table.insert(civAir.landingOnly, inoutName)
|
||||
civAir.inoutZones[inoutName] = theZone
|
||||
-- theZone.outbound = true
|
||||
elseif dcsCommon.stringStartsWith(value, "in/out") then
|
||||
table.insert(civAir.trafficCenters, inoutName)
|
||||
civAir.inoutZones[inoutName] = theZone
|
||||
-- theZone.inbound = true
|
||||
-- theZone.outbound = true
|
||||
else
|
||||
table.insert(civAir.trafficCenters, afName) -- note that adding the same twice makes it more likely to be picked
|
||||
end
|
||||
@ -231,8 +311,7 @@ function civAir.getTwoAirbases()
|
||||
sAB = dcsCommon.pickRandom(filteredAB)
|
||||
tries = tries + 1 -- only try 10 times
|
||||
until fAB ~= sAB or tries > 10
|
||||
|
||||
|
||||
|
||||
local civA = {}
|
||||
if not (dcsCommon.stringStartsWith(fAB, '***')) then
|
||||
civA.AB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
|
||||
@ -295,9 +374,15 @@ function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAi
|
||||
|
||||
local theGroup = dcsCommon.createEmptyAircraftGroupData (name)
|
||||
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
|
||||
dcsCommon.addUnitToGroupData(theAUnit, theGroup)
|
||||
|
||||
|
||||
local fromWP
|
||||
if fromAirfield.AB then
|
||||
fromWP = dcsCommon.createTakeOffFromParkingRoutePointData(fromAirfield.AB)
|
||||
@ -384,13 +469,7 @@ function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAi
|
||||
dcsCommon.addRoutePointForGroupData(theGroup, toWP)
|
||||
|
||||
-- spawn
|
||||
local groupCat = Group.Category.AIRPLANE
|
||||
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
|
||||
local theSpawnedGroup = coalition.addGroup(civAir.owner, groupCat, theGroup) -- 82 is UN peacekeepers
|
||||
if zoneApproach then
|
||||
-- track this flight to target zone
|
||||
civAir.outboundFlights[name] = zoneApproach
|
||||
@ -436,6 +515,20 @@ function civAir.airStartPopulation()
|
||||
civAir.airStartSeparation = civAir.airStartSeparation + 200
|
||||
civAir.createNewFlight(true)
|
||||
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
|
||||
|
||||
--
|
||||
@ -609,7 +702,7 @@ function civAir.start()
|
||||
|
||||
-- see if there is a config zone and load it
|
||||
civAir.readConfigZone()
|
||||
|
||||
|
||||
-- look for zones to add to air fields list
|
||||
civAir.collectHubs()
|
||||
|
||||
@ -632,12 +725,15 @@ function civAir.start()
|
||||
end
|
||||
|
||||
-- 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
|
||||
civAir.airStartPopulation()
|
||||
timer.scheduleFunction(civAir.airStartPopulation, {}, timer.getTime() + 5)
|
||||
else
|
||||
-- start update in 15 seconds
|
||||
timer.scheduleFunction(civAir.update, {}, timer.getTime() + 15)
|
||||
end
|
||||
|
||||
-- start the update loop
|
||||
civAir.update()
|
||||
-- start outbound tracking
|
||||
civAir.trackOutbound()
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
cloneZones = {}
|
||||
cloneZones.version = "1.9.0"
|
||||
cloneZones.version = "1.9.1"
|
||||
cloneZones.verbose = false
|
||||
cloneZones.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -106,6 +106,7 @@ cloneZones.respawnOnGroupID = true
|
||||
- cooldown attribute
|
||||
- cloner collects all types used
|
||||
- groupScheme attribute
|
||||
1.9.1 - useAI attribute
|
||||
--]]--
|
||||
|
||||
--
|
||||
@ -404,6 +405,8 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
||||
theZone.nameScheme = nil
|
||||
theZone.groupScheme = nil
|
||||
end
|
||||
|
||||
theZone.useAI = theZone:getBoolFromZoneProperty("useAI", true)
|
||||
-- we end with clear plate
|
||||
end
|
||||
|
||||
@ -1256,6 +1259,8 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||
-- see what country we spawn for
|
||||
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
||||
rawData.CZctry = ctry -- save ctry
|
||||
-- set AI on or off
|
||||
rawData.useAI = spawnZone.useAI
|
||||
table.insert(dataToSpawn, rawData)
|
||||
end
|
||||
|
||||
@ -1295,6 +1300,11 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||
theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
||||
table.insert(spawnedGroups, theGroup)
|
||||
|
||||
-- turn off AI if disabled
|
||||
if not rawData.useAI then
|
||||
cloneZones.turnOffAI({theGroup})
|
||||
end
|
||||
|
||||
-- update groupXlate table from spawned group
|
||||
-- so we can later reference them with other clones
|
||||
local newGroupID = theGroup:getID() -- new ID assigned by DCS
|
||||
@ -1515,6 +1525,13 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||
return spawnedGroups, spawnedStatics
|
||||
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
|
||||
function cloneZones.spawnWithSpawner(theZone)
|
||||
-- analog to cfxSpawnZones.spawnWithSpawner(theSpawner)
|
||||
@ -1950,6 +1967,10 @@ function cloneZones.loadData()
|
||||
local gdClone = dcsCommon.clone(gData)
|
||||
cloneZones.allClones[gName] = gdClone
|
||||
local theGroup = coalition.addGroup(cty, cat, gData)
|
||||
-- turn off AI if disabled
|
||||
if not gData.useAI then
|
||||
cloneZones.turnOffAI({theGroup})
|
||||
end
|
||||
end
|
||||
|
||||
-- spawn all static objects
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
dcsCommon = {}
|
||||
dcsCommon.version = "2.9.5"
|
||||
dcsCommon.version = "2.9.6"
|
||||
--[[-- VERSION HISTORY
|
||||
2.2.6 - compassPositionOfARelativeToB
|
||||
- clockPositionOfARelativeToB
|
||||
@ -175,6 +175,7 @@ dcsCommon.version = "2.9.5"
|
||||
2.9.3 - getAirbasesWhoseNameContains now supports category tables for filtering
|
||||
2.9.4 - new bearing2degrees()
|
||||
2.9.5 - distanceOfPointPToLineXZ(p, p1, p2)
|
||||
2.9.6 - new addToTableIfNew()
|
||||
|
||||
--]]--
|
||||
|
||||
@ -402,6 +403,13 @@ dcsCommon.version = "2.9.5"
|
||||
end
|
||||
return outTable
|
||||
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
|
||||
--
|
||||
@ -2404,38 +2412,9 @@ end
|
||||
theString = string.upper(theString)
|
||||
thePrefix = string.upper(theString)
|
||||
end
|
||||
-- new code because old 'string.find' had some really
|
||||
-- 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
|
||||
|
||||
-- superseded: string.find (s, pattern [, init [, plain]]) solves the problem
|
||||
local i, j = string.find(theString, thePrefix, 1, true)
|
||||
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
|
||||
|
||||
function dcsCommon.removePrefix(theString, thePrefix)
|
||||
|
||||
@ -13,7 +13,9 @@ fireFX.fx = {}
|
||||
1.0.0 - Initial version
|
||||
1.1.0 - persistence
|
||||
1.1.1 - agl attribute
|
||||
|
||||
2.0.0 - dmlZones OOP
|
||||
- rndLoc
|
||||
|
||||
--]]--
|
||||
|
||||
function fireFX.addFX(theZone)
|
||||
@ -35,7 +37,7 @@ end
|
||||
--
|
||||
function fireFX.createFXWithZone(theZone)
|
||||
-- decode size and fire
|
||||
local theSize = cfxZones.getStringFromZoneProperty(theZone, "fireFX", "none")
|
||||
local theSize = theZone:getStringFromZoneProperty("fireFX", "none")
|
||||
theSize = dcsCommon.trim(theSize)
|
||||
theSize = string.upper(theSize)
|
||||
local fxCode = 1
|
||||
@ -59,22 +61,22 @@ function fireFX.createFXWithZone(theZone)
|
||||
trigger.action.outText("+++ffx: new FX with code = <" .. fxCode .. ">", 30)
|
||||
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 cfxZones.hasProperty(theZone, "start?") then
|
||||
theZone.fxStart = cfxZones.getStringFromZoneProperty(theZone, "start?", "*<none>")
|
||||
theZone.fxLastStart = cfxZones.getFlagValue(theZone.fxStart, theZone)
|
||||
if theZone:hasProperty("start?") then
|
||||
theZone.fxStart = theZone:getStringFromZoneProperty("start?", "*<none>")
|
||||
theZone.fxLastStart = theZone:getFlagValue(theZone.fxStart)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "stop?") then
|
||||
theZone.fxStop = cfxZones.getStringFromZoneProperty(theZone, "stop?", "*<none>")
|
||||
theZone.fxLastStop = cfxZones.getFlagValue(theZone.fxStop, theZone)
|
||||
if theZone:hasProperty("stop?") then
|
||||
theZone.fxStop = theZone:getStringFromZoneProperty("stop?", "*<none>")
|
||||
theZone.fxLastStop = theZone:getFlagValue(theZone.fxStop)
|
||||
end
|
||||
|
||||
theZone.fxOnStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
||||
theZone.fxOnStart = theZone:getBoolFromZoneProperty("onStart", false)
|
||||
theZone.burning = false
|
||||
|
||||
if not theZone.fxOnStart and not theZone.fxStart then
|
||||
@ -84,14 +86,23 @@ function fireFX.createFXWithZone(theZone)
|
||||
-- output method (not needed)
|
||||
|
||||
-- trigger method
|
||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "fxTriggerMethod", "change")
|
||||
if cfxZones.hasProperty(theZone, "triggerMethod") then
|
||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
||||
theZone.fxTriggerMethod = theZone:getStringFromZoneProperty( "fxTriggerMethod", "change")
|
||||
if theZone:hasProperty("triggerMethod") then
|
||||
theZone.fxTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||
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
|
||||
trigger.action.outText("+++ffx: new FX <".. theZone.name ..">", 30)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
@ -99,18 +110,29 @@ end
|
||||
--
|
||||
function fireFX.startTheFire(theZone)
|
||||
if not theZone.burning then
|
||||
local p = cfxZones.getPoint(theZone)
|
||||
p.y = land.getHeight({x = p.x, y = p.z}) + theZone.agl
|
||||
local preset = theZone.fxCode
|
||||
local density = theZone.density
|
||||
trigger.action.effectSmokeBig(p, preset, density, theZone.name)
|
||||
theZone.fireNames = {}
|
||||
local num = cfxZones.randomInRange(theZone.min, theZone.max)
|
||||
for i = 1, num do
|
||||
local p = cfxZones.getPoint(theZone)
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
function fireFX.extinguishFire(theZone)
|
||||
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
|
||||
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.version = "1.3.3"
|
||||
pulseFlags.version = "2.0.0"
|
||||
pulseFlags.verbose = false
|
||||
pulseFlags.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -39,6 +39,9 @@ pulseFlags.requiredLibs = {
|
||||
- 1.3.1 typos corrected
|
||||
- 1.3.2 removed last pulse's timeID upon entry in doPulse
|
||||
- 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)
|
||||
if cfxZones.hasProperty(theZone, "pulse") then
|
||||
theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse", "*none") -- the flag to pulse
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "pulse!") then
|
||||
theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse!", "*none") -- the flag to pulse
|
||||
if theZone:hasProperty("pulse") then
|
||||
theZone.pulseFlag = theZone:getStringFromZoneProperty("pulse", "*none") -- the flag to pulse
|
||||
trigger.action.outText("Warning: pulser in zone <" .. theZone.name .. "> uses deprecated attribuet 'pulse'.", 30)
|
||||
elseif theZone:hasProperty("pulse!") then
|
||||
theZone.pulseFlag = theZone:getStringFromZoneProperty("pulse!", "*none") -- the flag to pulse
|
||||
end
|
||||
|
||||
-- time can be number, or number-number range
|
||||
theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "time", 1)
|
||||
if cfxZones.hasProperty(theZone, "pulseInterval") then
|
||||
theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "pulseInterval", 1)
|
||||
theZone.minTime = 1
|
||||
theZone.time = 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
|
||||
|
||||
if pulseFlags.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> time is <".. theZone.minTime ..", " .. theZone.time .. "!", 30)
|
||||
end
|
||||
|
||||
|
||||
theZone.pulses = -1 -- set to infinite
|
||||
if cfxZones.hasProperty(theZone, "pulses") then
|
||||
local minP
|
||||
local maxP
|
||||
minP, maxP = cfxZones.getPositiveRangeFromZoneProperty(theZone, "pulses", 1)
|
||||
if theZone:hasProperty("pulses") then
|
||||
local minP, maxP = theZone:getPositiveRangeFromZoneProperty("pulses", 1)
|
||||
if minP == maxP then theZone.pulses = minP
|
||||
else
|
||||
theZone.pulses = cfxZones.randomInRange(minP, maxP)
|
||||
end
|
||||
end
|
||||
|
||||
if pulseFlags.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++pulF: zone <" .. theZone.name .. "> set to <" .. theZone.pulses .. "> pulses", 30)
|
||||
end
|
||||
|
||||
|
||||
theZone.pulsesLeft = 0 -- will start new cycle
|
||||
|
||||
-- watchflag:
|
||||
-- triggerMethod
|
||||
theZone.pulseTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
||||
theZone.pulseTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||
|
||||
if cfxZones.hasProperty(theZone, "pulseTriggerMethod") then
|
||||
theZone.pulseTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "pulseTriggerMethod", "change")
|
||||
if theZone:hasProperty("pulseTriggerMethod") then
|
||||
theZone.pulseTriggerMethod = theZone:getStringFromZoneProperty("pulseTriggerMethod", "change")
|
||||
end
|
||||
|
||||
-- trigger flags
|
||||
if cfxZones.hasProperty(theZone, "activate?") then
|
||||
theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "activate?", "none")
|
||||
theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value
|
||||
if theZone:hasProperty("activate?") then
|
||||
theZone.activatePulseFlag = theZone:getStringFromZoneProperty("activate?", "none")
|
||||
theZone.lastActivateValue = theZone:getFlagValue(theZone.activatePulseFlag)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "startPulse?") then
|
||||
theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "startPulse?", "none")
|
||||
theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value
|
||||
if theZone:hasProperty("startPulse?") then
|
||||
theZone.activatePulseFlag = theZone:getStringFromZoneProperty("startPulse?", "none")
|
||||
theZone.lastActivateValue = theZone:getFlagValue(theZone.activatePulseFlag)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "pause?") then
|
||||
theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pause?", "*none")
|
||||
theZone.lastPauseValue = cfxZones.getFlagValue(theZone.pausePulseFlag, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value
|
||||
if theZone:hasProperty("pause?") then
|
||||
theZone.pausePulseFlag = theZone:getStringFromZoneProperty("pause?", "*none")
|
||||
theZone.lastPauseValue = theZone:getFlagValue(theZone.pausePulseFlag)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "pausePulse?") then
|
||||
theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pausePulse?", "*none")
|
||||
theZone.lastPauseValue = cfxZones.getFlagValue(theZone.pausePulseFlag, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value
|
||||
if theZone:hasProperty("pausePulse?") then
|
||||
theZone.pausePulseFlag = theZone:getStringFromZoneProperty( "pausePulse?", "*none")
|
||||
theZone.lastPauseValue = theZone:getFlagValue(theZone.pausePulseFlag)
|
||||
end
|
||||
|
||||
-- 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)
|
||||
-- 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.pulsePaused = cfxZones.getBoolFromZoneProperty(theZone, "pulseStopped", false)
|
||||
end
|
||||
--]]--
|
||||
|
||||
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")
|
||||
theZone.pulseMethod = theZone:getStringFromZoneProperty("method", "inc")
|
||||
|
||||
if theZone:hasProperty("outputMethod") then
|
||||
theZone.pulseMethod = theZone:getStringFromZoneProperty( "outputMethod", "inc")
|
||||
end
|
||||
-- done flag
|
||||
if cfxZones.hasProperty(theZone, "done+1") then
|
||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "*none")
|
||||
if theZone:hasProperty("pulsesDone!") then
|
||||
theZone.pulseDoneFlag = theZone:getStringFromZoneProperty("pulsesDone!", "*none")
|
||||
end
|
||||
if cfxZones.hasProperty(theZone, "pulsesDone!") then
|
||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "pulsesDone!", "*none")
|
||||
if theZone:hasProperty("done!") then
|
||||
theZone.pulseDoneFlag = theZone:getStringFromZoneProperty("done!", "*none")
|
||||
end
|
||||
if cfxZones.hasProperty(theZone, "done!") then
|
||||
theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done!", "*none")
|
||||
end
|
||||
|
||||
theZone.pulsing = false -- not running
|
||||
theZone.hasPulsed = false
|
||||
theZone.zeroPulse = cfxZones.getBoolFromZoneProperty(theZone, "zeroPulse", true)
|
||||
theZone.zeroPulse = theZone:getBoolFromZoneProperty("zeroPulse", true)
|
||||
end
|
||||
|
||||
--
|
||||
@ -185,8 +168,7 @@ function pulseFlags.doPulse(args)
|
||||
trigger.action.outText("+++pulF: will bang " .. theZone.pulseFlag, 30);
|
||||
end
|
||||
|
||||
cfxZones.pollFlag(theZone.pulseFlag, theZone.pulseMethod, theZone)
|
||||
|
||||
theZone:pollFlag(theZone.pulseFlag, theZone.pulseMethod)
|
||||
-- decrease count
|
||||
if theZone.pulses > 0 then
|
||||
-- only do this if ending
|
||||
@ -196,11 +178,10 @@ function pulseFlags.doPulse(args)
|
||||
if theZone.pulsesLeft < 1 then
|
||||
-- increment done flag if set
|
||||
if theZone.pulseDoneFlag then
|
||||
--local currVal = cfxZones.getFlagValue(theZone.pulseDoneFlag, theZone)-- trigger.misc.getUserFlag(theZone.pulseDoneFlag)
|
||||
cfxZones.pollFlag(theZone.pulseDoneFlag, "inc", theZone) -- trigger.action.setUserFlag(theZone.pulseDoneFlag, currVal + 1)
|
||||
theZone:pollFlag(theZone.pulseDoneFlag, theZone.pulseMethod)
|
||||
end
|
||||
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
|
||||
theZone.pulsing = false
|
||||
theZone.pulsePaused = true
|
||||
@ -218,7 +199,6 @@ function pulseFlags.doPulse(args)
|
||||
-- if we get here, schedule next pulse
|
||||
local delay = cfxZones.randomDelayFromPositiveRange(theZone.minTime, theZone.time)
|
||||
|
||||
|
||||
-- schedule in delay time
|
||||
theZone.scheduledTime = timer.getTime() + delay
|
||||
theZone.timerID = timer.scheduleFunction(pulseFlags.doPulse, args, theZone.scheduledTime)
|
||||
@ -228,7 +208,6 @@ function pulseFlags.doPulse(args)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- start new pulse, will reset
|
||||
function pulseFlags.startNewPulse(theZone)
|
||||
theZone.pulsesLeft = theZone.pulses
|
||||
@ -241,7 +220,6 @@ function pulseFlags.startNewPulse(theZone)
|
||||
end
|
||||
|
||||
function pulseFlags.update()
|
||||
-- call me in a second to poll triggers
|
||||
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
||||
|
||||
for idx, aZone in pairs(pulseFlags.pulses) do
|
||||
@ -249,10 +227,7 @@ function pulseFlags.update()
|
||||
if aZone.pulsing then
|
||||
-- this zone has a pulse and has scheduled
|
||||
-- a new pulse, nothing to do
|
||||
|
||||
else
|
||||
-- this zone has not scheduled a new pulse
|
||||
-- let's see why
|
||||
if aZone.pulsePaused then
|
||||
-- ok, zone is paused. all clear
|
||||
else
|
||||
@ -263,7 +238,7 @@ function pulseFlags.update()
|
||||
|
||||
-- see if we got a pause or activate command
|
||||
-- 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
|
||||
trigger.action.outText("+++pulF: activating <" .. aZone.name .. ">", 30)
|
||||
end
|
||||
@ -271,7 +246,7 @@ function pulseFlags.update()
|
||||
end
|
||||
|
||||
-- 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
|
||||
trigger.action.outText("+++pulF: pausing <" .. aZone.name .. ">", 30)
|
||||
end
|
||||
@ -296,11 +271,9 @@ function pulseFlags.readConfigZone()
|
||||
if pulseFlags.verbose then
|
||||
trigger.action.outText("+++pulF: NO config zone!", 30)
|
||||
end
|
||||
return
|
||||
theZone = cfxZones.createSimpleZone("pulseFlagsConfig")
|
||||
end
|
||||
|
||||
pulseFlags.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||
|
||||
pulseFlags.verbose = theZone.verbose
|
||||
if pulseFlags.verbose then
|
||||
trigger.action.outText("+++pulF: read config", 30)
|
||||
end
|
||||
@ -385,25 +358,19 @@ function pulseFlags.start()
|
||||
-- read config
|
||||
pulseFlags.readConfigZone()
|
||||
|
||||
-- process RND Zones
|
||||
-- process "pulse" Zones - deprecated!!
|
||||
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
|
||||
pulseFlags.createPulseWithZone(aZone) -- process attribute and add to zone
|
||||
pulseFlags.addPulse(aZone) -- remember it so we can pulse it
|
||||
pulseFlags.createPulseWithZone(aZone)
|
||||
pulseFlags.addPulse(aZone)
|
||||
end
|
||||
|
||||
attrZones = cfxZones.getZonesWithAttributeNamed("pulse!")
|
||||
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
|
||||
pulseFlags.createPulseWithZone(aZone) -- process attribute and add to zone
|
||||
pulseFlags.addPulse(aZone) -- remember it so we can pulse it
|
||||
pulseFlags.createPulseWithZone(aZone)
|
||||
pulseFlags.addPulse(aZone)
|
||||
end
|
||||
|
||||
-- load any saved data
|
||||
@ -417,7 +384,6 @@ function pulseFlags.start()
|
||||
end
|
||||
|
||||
-- start update in 1 second
|
||||
--pulseFlags.update()
|
||||
timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1)
|
||||
|
||||
trigger.action.outText("cfx Pulse Flags v" .. pulseFlags.version .. " started.", 30)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
raiseFlag = {}
|
||||
raiseFlag.version = "1.2.1"
|
||||
raiseFlag.version = "2.0.0"
|
||||
raiseFlag.verbose = false
|
||||
raiseFlag.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -7,19 +7,18 @@ raiseFlag.requiredLibs = {
|
||||
}
|
||||
raiseFlag.flags = {}
|
||||
--[[--
|
||||
Raise A Flag module -- (c) 2022 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'
|
||||
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')
|
||||
--]]--
|
||||
function raiseFlag.addRaiseFlag(theZone)
|
||||
table.insert(raiseFlag.flags, theZone)
|
||||
@ -32,7 +31,6 @@ function raiseFlag.getRaiseFlagByName(aName)
|
||||
if raiseFlag.verbose then
|
||||
trigger.action.outText("+++rFlg: no raiseFlag with name <" .. aName ..">", 30)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@ -41,10 +39,10 @@ end
|
||||
--
|
||||
function raiseFlag.createRaiseFlagWithZone(theZone)
|
||||
-- get flag from faiseFlag itself
|
||||
if cfxZones.hasProperty(theZone, "raiseFlag") then
|
||||
theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag", "<none>") -- the flag to raise
|
||||
if theZone:hasProperty("raiseFlag") then
|
||||
theZone.raiseFlag = theZone:getStringFromZoneProperty("raiseFlag", "<none>") -- the flag to raise
|
||||
else
|
||||
theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag!", "<none>") -- the flag to raise
|
||||
theZone.raiseFlag = theZone:getStringFromZoneProperty("raiseFlag!", "<none>") -- the flag to raise
|
||||
end
|
||||
|
||||
-- pre-method DML raiseFlag is now upgraded to method.
|
||||
@ -55,12 +53,7 @@ function raiseFlag.createRaiseFlagWithZone(theZone)
|
||||
theZone.flagValue = theZone:getStringFromZoneProperty("method", "inc")
|
||||
end
|
||||
theZone.flagValue = theZone.flagValue:lower()
|
||||
|
||||
theZone.minAfterTime, theZone.maxAfterTime = theZone:getPositiveRangeFromZoneProperty("afterTime", -1)
|
||||
|
||||
-- method for triggering
|
||||
-- watchflag:
|
||||
-- triggerMethod
|
||||
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
|
||||
if theZone:hasProperty("raiseTriggerMethod") then
|
||||
theZone.raiseTriggerMethod = theZone:getStringFromZoneProperty("raiseTriggerMethod", "change")
|
||||
@ -70,7 +63,6 @@ function raiseFlag.createRaiseFlagWithZone(theZone)
|
||||
theZone.triggerStopFlag = theZone:getStringFromZoneProperty( "stopFlag?", "none")
|
||||
theZone.lastTriggerStopValue = theZone:getFlagValue(theZone.triggerStopFlag) -- save last value
|
||||
end
|
||||
|
||||
theZone.scheduleID = nil
|
||||
theZone.raiseStopped = false
|
||||
|
||||
@ -94,21 +86,6 @@ function raiseFlag.triggered(args)
|
||||
if raiseFlag.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++rFlg - raising <" .. theZone.raiseFlag .. "> with method '" .. command .. "'" ,30)
|
||||
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
|
||||
|
||||
--
|
||||
@ -117,28 +94,23 @@ end
|
||||
function raiseFlag.update()
|
||||
-- call me in a second to poll triggers
|
||||
timer.scheduleFunction(raiseFlag.update, {}, timer.getTime() + 1)
|
||||
|
||||
for idx, aZone in pairs(raiseFlag.flags) do
|
||||
-- make sure to re-start before reading time limit
|
||||
if aZone:testZoneFlag(aZone.triggerStopFlag, aZone.raiseTriggerMethod, "lastTriggerStopValue") then
|
||||
theZone.raiseStopped = true -- we are done, no flag!
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- config & go!
|
||||
--
|
||||
|
||||
function raiseFlag.readConfigZone()
|
||||
local theZone = cfxZones.getZoneByName("raiseFlagConfig")
|
||||
if not theZone then
|
||||
theZone = cfxZones.createSimpleZone("raiseFlagConfig")
|
||||
end
|
||||
|
||||
raiseFlag.verbose = theZone.verbose
|
||||
|
||||
if raiseFlag.verbose then
|
||||
trigger.action.outText("+++rFlg: read config", 30)
|
||||
end
|
||||
@ -157,7 +129,7 @@ function raiseFlag.start()
|
||||
-- read config
|
||||
raiseFlag.readConfigZone()
|
||||
|
||||
-- process cloner Zones
|
||||
-- process raise Flags Zones
|
||||
local attrZones = cfxZones.getZonesWithAttributeNamed("raiseFlag")
|
||||
for k, aZone in pairs(attrZones) do
|
||||
raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
stopGap = {}
|
||||
stopGap.version = "1.0.9"
|
||||
stopGap.version = "1.0.10"
|
||||
stopGap.verbose = false
|
||||
stopGap.ssbEnabled = true
|
||||
stopGap.ignoreMe = "-sg"
|
||||
@ -48,6 +48,7 @@ stopGap.requiredLibs = {
|
||||
1.0.8 - added refreshInterval option as requested
|
||||
- refresh attribute config zone
|
||||
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)
|
||||
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
|
||||
|
||||
function stopGap.createStopGapSPZone(theZone)
|
||||
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
|
||||
|
||||
--
|
||||
|
||||
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