Version 1.5.1

DCS 2.9 Fixes, TDZ
This commit is contained in:
Christian Franz 2023-11-30 08:48:18 +01:00
parent a3cffa58d1
commit 663038db0a
14 changed files with 513 additions and 192 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
tdz = {}
tdz.version = "1.0.0"
tdz.version = "1.0.1"
tdz.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
@ -7,6 +7,14 @@ tdz.requiredLibs = {
--[[--
VERSION HISTORY
1.0.0 - Initial version
1.0.1 - visible
rwFill, rwFrame
tdzFill, tdzFrame
extend, expand
left, right
multiple zone support
hops detection improvement
helo attribute
--]]--
@ -18,10 +26,6 @@ tdz.timeoutAfter = 120 -- seconds.
-- rwy draw procs
--
function tdz.rotateXZPolyInRads(thePoly, rads)
if not rads then
trigger.action.outText("rotateXZPolyInRads (inner): no rads", 30)
return
end
local c = math.cos(rads)
local s = math.sin(rads)
for idx, p in pairs(thePoly) do
@ -33,23 +37,15 @@ function tdz.rotateXZPolyInRads(thePoly, rads)
end
function tdz.rotateXZPolyAroundCenterInRads(thePoly, center, rads)
if not rads then
trigger.action.outText("rotateXZPolyAroundCenterInRads: no rads", 30)
return
end
local negCtr = {x = -center.x, y = -center.y, z = -center.z}
tdz.translatePoly(thePoly, negCtr)
if not rads then
trigger.action.outText("WHOA! rotateXZPolyAroundCenterInRads: no rads", 30)
return
end
tdz.rotateXZPolyInRads(thePoly, rads)
tdz.translatePoly(thePoly, center)
end
function tdz.rotateXZPolyAroundCenterInDegrees(thePoly, center, degrees)
tdz.rotateXZPolyAroundCenterInRads(thePoly, center, degrees * 0.0174533)
end
--function tdz.rotateXZPolyAroundCenterInDegrees(thePoly, center, degrees)
-- tdz.rotateXZPolyAroundCenterInRads(thePoly, center, degrees * 0.0174533)
--end
function tdz.translatePoly(thePoly, v) -- straight rot, translate to 0 first
for idx, aPoint in pairs(thePoly) do
@ -87,6 +83,7 @@ function tdz.createTDZ(theZone)
local theBase = dcsCommon.getClosestAirbaseTo(p) -- never get FARPS
theZone.base = theBase
theZone.baseName = theBase:getName()
theZone.helos = false
-- get closest runway to TDZ
-- may get a bit hairy, so let's find a good way
@ -102,6 +99,7 @@ function tdz.createTDZ(theZone)
end
end
local bearing = nearestRwy.course * (-1)
if bearing < 0 then bearing = bearing + math.pi * 2 end
theZone.bearing = bearing
rwname = math.floor(dcsCommon.bearing2degrees(bearing)/10 + 0.5) -- nice number
degrees = math.floor(dcsCommon.bearing2degrees(bearing) * 10) / 10
@ -109,6 +107,11 @@ function tdz.createTDZ(theZone)
if degrees > 360 then degrees = degrees - 360 end
if rwname < 0 then rwname = rwname + 36 end
if rwname > 36 then rwname = rwname - 36 end
if tdz.verbose or theZone.verbose then
trigger.action.outText("TDZ: <" .. theZone.name .. "> attached to airfield " .. theZone.baseName .. " RW main (LEFT) is " .. rwname .. "0", 30)
end
local opName = rwname + 18
if opName > 36 then opName = opName - 36 end
if rwname < 10 then rwname = "0"..rwname end
@ -116,30 +119,45 @@ function tdz.createTDZ(theZone)
theZone.rwName = rwname .. "/" .. opName
theZone.opName = opName .. "/" .. rwname
local rwLen = nearestRwy.length
rwLen = rwLen + 2 * theZone:getNumberFromZoneProperty("extend", 0)
local rwWid = nearestRwy.width
rwWid = rwWid + 2 * theZone:getNumberFromZoneProperty("expand", 0)
local pos = nearestRwy.position
-- p1 is for distance to centerline calculation, defining a point
-- length away in direction bearing, setting up the line
-- theZone.rwCenter, theZone.p1
theZone.rwCenter = pos
local p1 = {x = pos.x + math.cos(bearing) * rwLen, y = 0, z = pos.z + math.sin(bearing) * rwLen}
theZone.visible = theZone:getBoolFromZoneProperty("visible", true)
theZone.rwP1 = p1
theZone.starts = theZone:getNumberFromZoneProperty("starts", 0)
theZone.ends = theZone:getNumberFromZoneProperty("ends", 610) -- m = 2000 ft
theZone.opposing = theZone:getBoolFromZoneProperty("opposing", true)
theZone.left = theZone:getBoolFromZoneProperty("left", true)
theZone.right = theZone:getBoolFromZoneProperty("right", true)
theZone.runwayZone = tdz.calcTDZone(theZone.name .. "-" .. rwname .. "main", pos, rwLen, rwWid, bearing)
theZone.runwayZone:drawZone({0, 0, 0, 1}, {0, 0, 0, 0}) -- black outline
theZone.rwFrame = theZone:getRGBAVectorFromZoneProperty("rwFrame", {0, 0, 0, 1}) -- black
theZone.rwFill = theZone:getRGBAVectorFromZoneProperty("rwFill", {0, 0, 0, 0}) -- nothing
if theZone.visible then
theZone.runwayZone:drawZone(theZone.rwFrame, theZone.rwFill)
end
local theTDZone = tdz.calcTDZone(theZone.name .. "-" .. rwname, pos, rwLen, rwWid, bearing, theZone.starts / rwLen, theZone.ends/rwLen)
-- to do: mark the various zones of excellence in different colors, or at least the excellent one with more color
theTDZone:drawZone({0, 1, 0, 1}, {0, 1, 0, .25})
theZone.tdzFrame = theZone:getRGBAVectorFromZoneProperty("tdzFrame", {0, 1, 0, 1}) -- green 100%
theZone.tdzFill = theZone:getRGBAVectorFromZoneProperty("tdzFill", {0, 1, 0, 0.25}) -- 25% green
if theZone.visible and theZone.left then
theTDZone:drawZone(theZone.tdzFrame, theZone.tdzFill)
end
theZone.normTDZone = theTDZone
if theZone.opposing then
theTDZone = tdz.calcTDZone(theZone.name .. "-" .. opName, pos, rwLen, rwWid, bearing + math.pi, theZone.starts / rwLen, theZone.ends/rwLen)
theTDZone:drawZone({0, 1, 0, 1}, {0, 1, 0, .25})
theZone.opTDZone = theTDZone
theZone.opBearing = bearing + math.pi
end
theTDZone = tdz.calcTDZone(theZone.name .. "-" .. opName, pos, rwLen, rwWid, bearing + math.pi, theZone.starts / rwLen, theZone.ends/rwLen)
if theZone.visible and theZone.right then
theTDZone:drawZone(theZone.tdzFrame, theZone.tdzFill)
end
theZone.opTDZone = theTDZone
theZone.opBearing = bearing + math.pi
if theZone.opBearing > 2 * math.pi then theZone.opBearing = theZone.opBearing - math.pi * 2 end
if theZone:hasProperty("landed!") then
theZone.landedFlag = theZone:getStringFromZoneProperty("landed!", "none")
end
@ -163,28 +181,68 @@ function tdz.playerLanded(theUnit, playerName)
-- make sure unit names match?
local entry = tdz.watchlist[playerName]
entry.hops = entry.hops + 1 -- uh oh.
return
end
-- we may want to filter helicopters
-- see if we touched down inside of one of our watched zones
-- and the directionality (left = landing dir, right = opDir)
-- matches
local p = theUnit:getPoint()
local theGroup = theUnit:getGroup()
local cat = theGroup:getCategory() -- DCS 2.9: no issues with groups...
local gID = theGroup:getID()
local hdg = dcsCommon.getUnitHeading(theUnit)
local msg = ""
local theZone = nil
local opposite = false
local dHdg, dOpHdg
for idx, aRunway in pairs(tdz.allTdz) do
local theRunway = aRunway.runwayZone
if theRunway:pointInZone(p) then
-- touchdown!
theZone = aRunway
if theZone.touchDownFlag then
theZone.pollFlag(theZone.touchDownFlag, theZone.method)
local allowUnit = (cat ~= 1) or aRunway.helos -- 1 = helos
if allowUnit and theRunway:pointInZone(p) then -- touched down
dHdg = math.abs(aRunway.bearing - hdg) -- 0..Pi
dOpHdg = math.abs(aRunway.opBearing - hdg)
opposite = false
if tdz.verbose or aRunway.verbose then
trigger.action.outText("TDZ: landing inside <" .. aRunway.name .. ">, myHdg = <" .. math.floor(hdg * 57.2958) .. ">, dHdg = <" .. dHdg * 57.29 .. ">, dOpHdg = <" .. dOpHdg * 57.29 .. ">, rw = <" .. math.floor(aRunway.bearing * 57.2958) .. ">, rwOp = <" .. math.floor(aRunway.opBearing * 57.2958) .. ">", 30)
end
if dOpHdg < dHdg then
opposite = true
dHdg = dOpHdg
if tdz.verbose or aRunway.verbose then
trigger.action.outText("TDZ: landing inside <" .. aRunway.name .. ">, *OPPOSING*", 30)
end
else
if tdz.verbose or aRunway.verbose then
trigger.action.outText("TDZ: landing inside <" .. aRunway.name .. ">, ---INLINE---", 30)
end
end
-- see if directionality matches
if ((opposite == false) and aRunway.left) or
((opposite == true) and aRunway.right)
then
theZone = aRunway -- FOUND!
if theZone.touchDownFlag then
theZone.pollFlag(theZone.touchDownFlag, theZone.method)
end
trigger.action.outTextForGroup(gID, "Touchdown! Come to a FULL STOP for evaluation", 30)
else
if aRunway.verbose or tdz.verbose then
trigger.action.outText("TDZ: ignored touchdown in runway for zone <" .. aRunway.name .. ">, directionality filtered.", 30)
end
end
trigger.action.outTextForGroup(gID, "Touchdown! Come to a FULL STOP for evaluation", 30)
end
end
if not theZone then return end -- no landing eval zone hit
if not theZone then
if tdz.verbose then
trigger.action.outText("TDZ: no touchdown inside zones registered", 30)
end
return
end -- no landing eval zone hit
-- Warning: finds the LAST that matches inZone and left/right
-- start a new watchlist entry
local entry = {}
@ -200,14 +258,6 @@ function tdz.playerLanded(theUnit, playerName)
entry.theZone = theZone
-- see if we are in main or opposite direction
local hdg = dcsCommon.getUnitHeading(theUnit)
local dHdg = math.abs(theZone.bearing - hdg) -- 0..Pi
local dOpHdg = math.abs(theZone.opBearing - hdg)
local opposite = false
if dOpHdg < dHdg then
opposite = true
dHdg = dOpHdg
end
if dHdg > math.pi * 1.5 then -- > 270+
dHdg = dHdg - math.pi * 1.5
elseif dHdg > math.pi / 2 then -- > 90+
@ -223,12 +273,12 @@ function tdz.playerLanded(theUnit, playerName)
local kkm = math.floor(vel * 19.4383) / 10
entry.msg = entry.msg .. "\nLanded heading " .. lHdg .. "°, diverging by " .. dHdg .. "° from runway heading, velocity at touchdown " .. vkm .. " kmh/" .. kkm .. " kts, touchdown " .. offcenter .. " m off centerline\n"
-- inside TDZ?
-- inside TDZ? Directionality was already checked
local tdZone = theZone.normTDZone
if opposite and theZone.opposing then
if opposite then
tdZone = theZone.opTDZone
end
if tdZone:pointInZone(p) then
-- yes, how far behind threshold
-- project point onto line to see how far inside
@ -333,6 +383,11 @@ end
-- Start
--
function tdz.readConfigZone()
local theZone = cfxZones.getZoneByName("tdzConfig")
if not theZone then
theZone = cfxZones.createSimpleZone("tdzConfig")
end
tdz.verbose = theZone.verbose
end
function tdz.start()
@ -362,4 +417,4 @@ end
if not tdz.start() then
trigger.action.outText("cf/x TDZ aborted: missing libraries", 30)
tdz = nil
end
end

View File

@ -1,5 +1,5 @@
autoCSAR = {}
autoCSAR.version = "1.1.0"
autoCSAR.version = "2.0.0"
autoCSAR.requiredLibs = {
"dcsCommon", -- always
"cfxZones", -- Zones, of course
@ -13,6 +13,7 @@ autoCSAR.trackedEjects = {} -- we start tracking on eject
1.0.0 - Initial Version
1.1.0 - allow open water CSAR, fake pilot with GRG Soldier
- can be disabled by seaCSAR = false
2.0.0 - OOP, code clean-up
--]]--
function autoCSAR.removeGuy(args)
@ -32,7 +33,6 @@ end
function autoCSAR.createNewCSAR(theUnit)
if not csarManager then
trigger.action.outText("+++aCSAR: CSAR Manager not loaded, aborting", 30)
-- return
end
-- enter with unit from landing_after_eject event
-- unit has no group
@ -50,12 +50,8 @@ function autoCSAR.createNewCSAR(theUnit)
-- for later expansion
local theGroup = theUnit:getGroup()
if theGroup then
-- now happens for faked sea CSAR units
--trigger.action.outText("We have a group for <" .. theUnit:getName() .. ">", 30)
end
-- now, if theUnit is over open water, this will be killed instantly
-- if theUnit is over open water, it is killed instantly by DCS
-- and must therefore be replaced with a stand-in
local pPoint = theUnit:getPoint()
pPoint.y = pPoint.z -- make it getSurfaceType compatible
@ -93,7 +89,6 @@ function autoCSAR.createNewCSAR(theUnit)
end
function autoCSAR:onEvent(event)
-- trigger.action.outText("autoCSAR: event = " .. event.id, 30)
if event.id == 31 then -- landing_after_eject, does not happen at sea
-- to prevent double invocations for same process
-- check that we are still tracking this ejection
@ -105,11 +100,6 @@ function autoCSAR:onEvent(event)
return
end
autoCSAR.createNewCSAR(event.initiator)
-- autoCSAR.trackedEjects[event.initiator] = nil
-- trigger.action.outText("autocsar: LAE for " .. autoCSAR.trackedEjects[event.initiator], 30)
-- else
-- trigger.action.outText("autoCSAR: ignored LAE event", 30)
-- end
end
end
@ -118,11 +108,7 @@ function autoCSAR:onEvent(event)
-- see if this happened over open water and immediately
-- create a seaCSAR
--local uid = tonumber(event.initiator:getID())
-- trigger.action.outText("autoCSAR: started tracking - chair + pilot", 30)
-- autoCSAR.trackedEjects[event.initiator] = "chair+pilot" -- start with this
if autoCSAR.isOverWater(event.initiator) then
--trigger.action.outText("attempting to walk on water", 30)
autoCSAR.createNewCSAR(event.initiator)
end
@ -132,38 +118,6 @@ function autoCSAR:onEvent(event)
end
end
--[[--
if event.id == 33 then -- separate chair from pilot
if event.initiator then
--local uid = tonumber(event.initiator:getID())
--local pid = tonumber(event.target:getID())
--if uid == 0 then
--trigger.action.outText("uid = 0, abort tracking", 30)
--return
--end
trigger.action.outText("autoCSAR: track change from seat to pilot <" .. event.target:getName() .. ">", 30)
autoCSAR.trackedEjects[event.initiator] = "chair only"
autoCSAR.trackedEjects[event.target] = "pilot"
end
end
if event.id == 9 then -- pilot dead
if event.initiator then
--local uid = tonumber(event.initiator:getID())
trigger.action.outText("autoCSAR: pilot id=xxx dead", 30)
if autoCSAR.trackedEjects[event.initiator] then
trigger.action.outText("confirm tracked pilot dead after ejection", 30)
if autoCSAR.isOverWater(event.initiator) then
trigger.action.outText("attempt to walk on water", 30)
autoCSAR.createNewCSAR(event.initiator)
end
autoCSAR.trackedEjects[event.initiator] = nil
end
else
trigger.action.outText("autoCSAR - no initiator for zed", 30)
end
end
--]]--
end
@ -175,18 +129,18 @@ function autoCSAR.readConfigZone()
trigger.action.outText("+++aCSAR: NO config zone!", 30)
end
end
autoCSAR.redCSAR = cfxZones.getBoolFromZoneProperty(theZone, "red", true)
if cfxZones.hasProperty(theZone, "redCSAR") then
autoCSAR.redCSAR = cfxZones.getBoolFromZoneProperty(theZone, "redCSAR", true)
autoCSAR.verbose = theZone.verbose
autoCSAR.redCSAR = theZone:getBoolFromZoneProperty("red", true)
if theZone:hasProperty("redCSAR") then
autoCSAR.redCSAR = theZone:getBoolFromZoneProperty("redCSAR", true)
end
autoCSAR.blueCSAR = cfxZones.getBoolFromZoneProperty(theZone, "blue", true)
if cfxZones.hasProperty(theZone, "blueCSAR") then
autoCSAR.blueCSAR = cfxZones.getBoolFromZoneProperty(theZone, "blueCSAR", true)
autoCSAR.blueCSAR = theZone:getBoolFromZoneProperty("blue", true)
if theZone:hasProperty("blueCSAR") then
autoCSAR.blueCSAR = theZone:getBoolFromZoneProperty("blueCSAR", true)
end
autoCSAR.seaCSAR = cfxZones.getBoolFromZoneProperty(theZone, "seaCSAR", true)
autoCSAR.seaCSAR = theZone:getBoolFromZoneProperty("seaCSAR", true)
if autoCSAR.verbose then
trigger.action.outText("+++aCSAR: read config", 30)

View File

@ -166,6 +166,9 @@ function cfxOwnedZones.addOwnedZone(aZone)
cfxOwnedZones.zones[aZone] = aZone
cfxOwnedZones.drawZoneInMap(aZone)
if aZone.verbose or cfxOwnedZones.verbose then
trigger.action.outText("+++owdZ: detected zone <" .. aZone.name .. ">", 30)
end
end
--
@ -326,6 +329,7 @@ function cfxOwnedZones.update()
end
end
end
-- count blue units
for idx, aGroup in pairs(allBlue) do
if Group.isExist(aGroup) then
@ -345,6 +349,11 @@ function cfxOwnedZones.update()
end
end
end
if theZone.verbose then
trigger.action.outText("+++owdZ: zone <" .. theZone.name .. ">: red inside: <" .. theZone.numRed .. ">, blue inside: <>" .. theZone.numBlue, 30)
end
-- trigger.action.outText(theZone.name .. " blue: " .. theZone.numBlue .. " red " .. theZone.numRed, 30)
local lastOwner = theZone.owner
local newOwner = 0 -- neutral is default

View File

@ -1,5 +1,5 @@
cfxPlayerScore = {}
cfxPlayerScore.version = "2.2.0"
cfxPlayerScore.version = "3.0.0"
cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers
cfxPlayerScore.badSound = "Death BRASS.wav"
cfxPlayerScore.scoreSound = "Quest Snare 3.wav"
@ -80,7 +80,12 @@ cfxPlayerScore.firstSave = true -- to force overwrite
- new scoreSummaryForPlayersOfCoalition()
- new noGrief option in config
- improved guards when checking ownership (nil zone owner)
2.0.0 - score flags for red and blue
2.2.0 - score flags for red and blue
3.0.0 - dmlFlags OOP
- redScore#
- blueScore#
- sceneryObject detection improvements
- DCS 2.9 safe
--]]--
@ -120,19 +125,19 @@ cfxPlayerScore.landing = 0 -- if > 0 it scores as feat
cfxPlayerScore.unit2player = {} -- lookup and reverse look-up
function cfxPlayerScore.addSafeZone(theZone)
theZone.scoreSafe = cfxZones.getCoalitionFromZoneProperty(theZone, "scoreSafe", 0)
theZone.scoreSafe = theZone:getCoalitionFromZoneProperty("scoreSafe", 0)
table.insert(cfxPlayerScore.safeZones, theZone)
end
function cfxPlayerScore.addKillZone(theZone)
theZone.killZone = cfxZones.getCoalitionFromZoneProperty(theZone, "killZone", 0) -- value currently ignored
theZone.duet = cfxZones.getBoolFromZoneProperty(theZone, "duet", false) -- does killer have to be in zone?
theZone.killZone = theZone:getCoalitionFromZoneProperty("killZone", 0) -- value currently ignored
theZone.duet = theZone:getBoolFromZoneProperty("duet", false) -- does killer have to be in zone?
table.insert(cfxPlayerScore.killZones, theZone)
end
function cfxPlayerScore.addFeatZone(theZone)
theZone.coalition = cfxZones.getCoalitionFromZoneProperty(theZone, "feat", 0) -- who can earn, 0 for all sides
theZone.featType = cfxZones.getStringFromZoneProperty(theZone, "featType", "kill")
theZone.coalition = theZone:getCoalitionFromZoneProperty("feat", 0) -- who can earn, 0 for all sides
theZone.featType = theZone:getStringFromZoneProperty("featType", "kill")
theZone.featType = string.upper(theZone.featType)
if theZone.featType == "LAND" then theZone.featType = "LANDING" end
if theZone.featType ~= "KILL" and
@ -141,12 +146,12 @@ function cfxPlayerScore.addFeatZone(theZone)
then
theZone.featType = "KILL"
end
theZone.featDesc = cfxZones.getStringFromZoneProperty(theZone, "description", "(some feat)")
theZone.featNum = cfxZones.getNumberFromZoneProperty(theZone, "awardLimit", -1) -- how many times this can be awarded, -1 is infinite
theZone.ppOnce = cfxZones.getBoolFromZoneProperty(theZone, "awardOnce", false)
theZone.featDesc = theZone:getStringFromZoneProperty("description", "(some feat)")
theZone.featNum = ctheZone:getNumberFromZoneProperty("awardLimit", -1) -- how many times this can be awarded, -1 is infinite
theZone.ppOnce = theZone:getBoolFromZoneProperty("awardOnce", false)
theZone.awardedTo = {} -- by player name: true/false
table.insert(cfxPlayerScore.featZones, theZone)
if cfxPlayerScore.verbose then
if cfxPlayerScore.verbose or theZone.verbose then
trigger.action.outText("+++ feat zone <" .. theZone.name .. "> read: [" .. theZone.featDesc .. "] for <" .. theZone.featType .. ">", 30)
end
end
@ -284,8 +289,15 @@ function cfxPlayerScore.cat2BaseScore(inCat)
end
function cfxPlayerScore.object2score(inVictim) -- does not have group
if not inVictim then return end
if not inVictim then return 0 end
local inName = inVictim:getName()
if dcsCommon.isSceneryObject(inVictim) then
local desc = inVictim:getDesc()
if not desc then return 0 end
-- same as object destruct detector to
-- avoid ID changes
inName = desc.typeName
end
if not inName then return 0 end
if type(inName) == "number" then
inName = tostring(inName)
@ -323,7 +335,7 @@ end
function cfxPlayerScore.unit2score(inUnit)
local vicGroup = inUnit:getGroup()
local vicCat = vicGroup:getCategory()
local vicCat = vicGroup:getCategory()-- group cat, not 2.9 affected
local vicType = inUnit:getTypeName()
local vicName = inUnit:getName()
if type(vicName) == "number" then vicName = tostring(vicName) end
@ -879,18 +891,7 @@ function cfxPlayerScore.killDetected(theEvent)
-- see which weapon was used. gun kills score 2x
local killMeth = ""
local killWeap = theEvent.weapon
--[[--
if killWeap then
local killWeapType = killWeap:getCategory()
if killWeapType == 0 then
killMeth = " with GUNS"
scoreMod = scoreMod * 2
else
local kWeapon = killWeap:getTypeName()
killMeth = " with " .. kWeapon
end
end
--]]--
if pk then
vicDesc = victim:getPlayerName() .. " in " .. vicDesc
scoreMod = scoreMod * cfxPlayerScore.pkMod
@ -1266,6 +1267,17 @@ function cfxPlayerScore.readConfigZone(theZone)
theZone, "reportCoalition", false) -- also show coalition score
cfxPlayerScore.noGrief = cfxZones.getBoolFromZoneProperty(theZone, "noGrief", true) -- noGrief = only add positive score
if theZone:hasProperty("redScore#") then
cfxPlayerScore.redScoreOut = theZone:getStringFromZoneProperty("redScore#")
theZone:setFlagValue(cfxPlayerScore.redScoreOut, cfxPlayerScore.coalitionScore[1])
end
if theZone:hasProperty("blueScore#") then
cfxPlayerScore.blueScoreOut = theZone:getStringFromZoneProperty("blueScore#")
theZone:setFlagValue(cfxPlayerScore.blueScoreOut, cfxPlayerScore.coalitionScore[2])
end
end
--
@ -1304,6 +1316,13 @@ function cfxPlayerScore.loadData()
if theData.coalitionScore then
cfxPlayerScore.coalitionScore = theData.coalitionScore
end
if cfxPlayerScore.redScoreOut then
cfxZones.setFlagValue(cfxPlayerScore.redScoreOut, cfxPlayerScore.coalitionScore[1], cfxPlayerScore)
end
if cfxPlayerScore.blueScoreOut then
cfxZones.setFlagValue(cfxPlayerScore.blueScoreOut, cfxPlayerScore.coalitionScore[2], cfxPlayerScore)
end
local featData = theData.featData
if featData then
for name, data in pairs(featData) do
@ -1429,6 +1448,14 @@ function cfxPlayerScore.update()
end
end
end
-- set output flags if they are set
if cfxPlayerScore.redScoreOut then
cfxZones.setFlagValue(cfxPlayerScore.redScoreOut, cfxPlayerScore.coalitionScore[1], cfxPlayerScore)
end
if cfxPlayerScore.blueScoreOut then
cfxZones.setFlagValue(cfxPlayerScore.blueScoreOut, cfxPlayerScore.coalitionScore[2], cfxPlayerScore)
end
end
--
-- start
@ -1443,12 +1470,9 @@ function cfxPlayerScore.start()
-- read my score table
-- identify and process a score table zones
local theZone = cfxZones.getZoneByName("playerScoreTable")
if not theZone then
-- trigger.action.outText("+++scr: no score table!", 30)
else
if theZone then
-- read all into my types registry, replacing whatever is there
cfxPlayerScore.typeScore = cfxZones.getAllZoneProperties(theZone)
-- trigger.action.outText("+++scr: read score table", 30)
end
-- read score tiggers and values
@ -1486,13 +1510,10 @@ function cfxPlayerScore.start()
-- now read my config zone
local theZone = cfxZones.getZoneByName("playerScoreConfig")
if not theZone then
-- trigger.action.outText("+++pScr: no config!", 30)
theZone = cfxZones.createSimpleZone("playerScoreConfig")
end
cfxPlayerScore.readConfigZone(theZone)
-- trigger.action.outText("+++scr: read config", 30)
-- read all scoreSafe zones
local safeZones = cfxZones.zonesWithProperty("scoreSafe")
for k, aZone in pairs(safeZones) do

View File

@ -1,5 +1,5 @@
cfxZones = {}
cfxZones.version = "4.0.9"
cfxZones.version = "4.0.10"
-- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable
@ -65,6 +65,7 @@ cfxZones.version = "4.0.9"
- createPolyZone now correctly sets zone.point
- createPolyZone now correctly inits dcsOrigin
- createCircleZone noew correctly inits dcsOrigin
- 4.0.10 - getBoolFromZoneProperty also supports "on" (=true) and "off" (=false)
--]]--
--
@ -2380,13 +2381,13 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal)
if defaultVal == false then
-- only go true if exact match to yes or true
theBool = false
theBool = (p == 'true') or (p == 'yes') or p == "1"
theBool = (p == 'true') or (p == 'yes') or (p == "1") or (p == "on")
return theBool
end
local theBool = true
-- only go false if exactly no or false or "0"
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0")
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off")
return theBool
end

View File

@ -1,5 +1,5 @@
civAir = {}
civAir.version = "3.0.0"
civAir.version = "3.0.1"
--[[--
1.0.0 initial version
1.1.0 exclude list for airfields
@ -42,6 +42,9 @@ civAir.version = "3.0.0"
new CAM attribute
deafault to one Yak-40 if neither
support for 'civil_liveries' zone
3.0.1 protest option, on by default
protest action
spawning now works correctly for groupType
--]]--
@ -183,6 +186,7 @@ function civAir.readConfigZone()
end
end
civAir.protest = theZone:getBoolFromZoneProperty("protest", true)
end
function civAir.addTypesAndLiveries(rawIn)
@ -333,7 +337,7 @@ function civAir.getTwoAirbases()
end
function civAir.parkingIsFree(fromWP)
-- iterate over all currently registres flights and make
-- iterate over all currently registred flights and make
-- sure that their location isn't closer than 10m to my new parking
local loc = {}
loc.x = fromWP.x
@ -469,6 +473,7 @@ function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAi
dcsCommon.addRoutePointForGroupData(theGroup, toWP)
-- spawn
local groupCat = Group.Category.AIRPLANE
local theSpawnedGroup = coalition.addGroup(civAir.owner, groupCat, theGroup) -- 82 is UN peacekeepers
if zoneApproach then
-- track this flight to target zone
@ -576,7 +581,6 @@ function civAir.update()
for name, group in pairs (civAir.activePlanes) do
if not group:isExist() then
table.insert(removeMe, name) -- mark for deletion
--Group.destroy(group) -- may break
end
end
@ -648,8 +652,45 @@ function civAir.update()
end
end
--
-- onEvent: detect hits / kills
--
function civAir:onEvent(event)
if not civAir.protest then return end
if not event.initiator then return end
local theUnit = event.initiator
if not Unit.isExist(theUnit) then return end
if event.id == 28 then -- kill event
-- check if the unit that was willed is one of mine
local target = event.target
if not target then return end
if not target.getGroup then return end
local theGroup = target:getGroup()
if not theGroup then return end
local theName = theGroup:getName()
-- see if theName matches one of my flights
local theFlight = civAir.activePlanes[theName]
if not theFlight then return end
-- if we get here, a civ plane got killed
if not theUnit.getPlayerName then return end
local thePlayer = theUnit:getPlayerName()
if not thePlayer then return end
-- now protest!
local details = ""
if event.weapon and event.weapon:getTypeName() then
details = " was attacked with a < .. event.weapon.getTypeName() .. > and"
end
trigger.action.outText("\n======== N E W S F L A S H ========\nUnarmed civilian flight <" .. theName .. ">" .. details .. " has become a victim of war crime. Sadly, all lives on board of the civil flight were lost.\n\nArmed Forced pilot <" .. thePlayer .. "> and their <" .. theUnit:getTypeName() .. "> were reported lethally armed and weapons hot in the same area; <" .. thePlayer .. "> is ordered to remand to base immediately, pending court-martial.\n\n====== E N D M E S S A G E ======\n", 30)
end
end
--
-- misc stuff
--
function civAir.doDebug(any)
trigger.action.outText("cf/x civTraffic debugger.", 30)
local desc = "Active Planes:"
@ -737,6 +778,9 @@ function civAir.start()
-- start outbound tracking
civAir.trackOutbound()
-- sign up for events
world.addEventHandler(civAir)
-- say hi!
trigger.action.outText("cf/x civAir v" .. civAir.version .. " started.", 30)
return true

View File

@ -1,5 +1,5 @@
csarManager = {}
csarManager.version = "2.3.1"
csarManager.version = "2.3.2"
csarManager.verbose = false
csarManager.ups = 1
@ -73,6 +73,7 @@ csarManager.ups = 1
- delay asynch OK (message only)
- offset zone on randomized soldier
- smokeDist
- 2.3.2 - DCS 2.9 getCategory() fix
INTEGRATES AUTOMATICALLY WITH playerScore IF INSTALLED
@ -320,8 +321,9 @@ function csarManager.preProcessor(event)
-- make sure it has an initiator
if not event.initiator then return false end -- no initiator
local theUnit = event.initiator
local cat = theUnit:getCategory()
if cat ~= Unit.Category.HELICOPTER then
if not theUnit.getDesc then return fase end -- not a unit
local cat = theUnit:getDesc().category --theUnit:getCategory()
if cat ~= 1 then -- Unit.Category.HELICOPTER
return false
end

View File

@ -1,5 +1,5 @@
dcsCommon = {}
dcsCommon.version = "2.9.6"
dcsCommon.version = "2.9.8"
--[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB
@ -176,7 +176,8 @@ dcsCommon.version = "2.9.6"
2.9.4 - new bearing2degrees()
2.9.5 - distanceOfPointPToLineXZ(p, p1, p2)
2.9.6 - new addToTableIfNew()
2.9.7 - createSimpleRoutePointData also accepts speed
2.9.8 - isSceneryObject(theUnit) optimization, DCS 2.9 safe
--]]--
-- dcsCommon is a library of common lua functions
@ -1525,7 +1526,8 @@ dcsCommon.version = "2.9.6"
return rp
end
function dcsCommon.createSimpleRoutePointData(p, alt)
function dcsCommon.createSimpleRoutePointData(p, alt, speed)
if not speed then speed = 133 end
if not alt then alt = 8000 end -- 24'000 feet
local rp = {}
rp.x = p.x
@ -1534,7 +1536,7 @@ dcsCommon.version = "2.9.6"
rp.action = "Turning Point"
rp.type = "Turning Point"
rp.speed = 133; -- in m/s? If so, that's 360 km/h
rp.speed = speed; -- in m/s? If so, that's 360 km/h
rp.alt_type = "BARO"
return rp
end
@ -2877,7 +2879,8 @@ end
--
function dcsCommon.isSceneryObject(theUnit)
if not theUnit then return false end
return theUnit.getCoalition == nil -- scenery objects do not return a coalition
return Object.getCategory(theUnit) == 5
-- return theUnit.getCoalition == nil -- scenery objects do not return a coalition
end
function dcsCommon.isTroopCarrierType(theType, carriers)

View File

@ -1,5 +1,5 @@
pulseFlags = {}
pulseFlags.version = "2.0.0"
pulseFlags.version = "2.0.1"
pulseFlags.verbose = false
pulseFlags.requiredLibs = {
"dcsCommon", -- always
@ -41,7 +41,7 @@ pulseFlags.requiredLibs = {
- 1.3.3 removed 'pulsing' when pausing, so we can restart
- 2.0.0 dmlZones / OOP
using method on all outputs
- 2.0.1 activateZoneFlag now works correctly
--]]--
@ -238,7 +238,7 @@ function pulseFlags.update()
-- see if we got a pause or activate command
-- activatePulseFlag
if aZone:testZoneFlag(activatePulseFlag, aZone.pulseTriggerMethod, "lastActivateValue") then
if aZone:testZoneFlag(aZone.activatePulseFlag, aZone.pulseTriggerMethod, "lastActivateValue") then
if pulseFlags.verbose or aZone.verbose then
trigger.action.outText("+++pulF: activating <" .. aZone.name .. ">", 30)
end

View File

@ -1,8 +1,8 @@
-- theDebugger
debugger = {}
debugger.version = "1.1.2"
debugger.version = "2.0.0"
debugDemon = {}
debugDemon.version = "1.1.2"
debugDemon.version = "2.0.0"
debugger.verbose = false
debugger.ups = 4 -- every 0.25 second
@ -23,7 +23,12 @@ debugger.log = ""
- save <name>
1.1.1 - warning when trying to set a flag to a non-int
1.1.2 - remove command
2.0.0 - dmlZones OOP
- eventmon command
- all, off, event #
- standard events
- adding events
- events? attribute from any zone
--]]--
@ -39,7 +44,68 @@ debugger.debugZones = {}
debugger.debugUnits = {}
debugger.debugGroups = {}
debugger.debugObjects = {}
debugger.showEvents = {}
debugDemon.eventList = {
["0"] = "S_EVENT_INVALID = 0",
["1"] = "S_EVENT_SHOT = 1",
["2"] = "S_EVENT_HIT = 2",
["3"] = "S_EVENT_TAKEOFF = 3",
["4"] = "S_EVENT_LAND = 4",
["5"] = "S_EVENT_CRASH = 5",
["6"] = "S_EVENT_EJECTION = 6",
["7"] = "S_EVENT_REFUELING = 7",
["8"] = "S_EVENT_DEAD = 8",
["9"] = "S_EVENT_PILOT_DEAD = 9",
["10"] = "S_EVENT_BASE_CAPTURED = 10",
["11"] = "S_EVENT_MISSION_START = 11",
["12"] = "S_EVENT_MISSION_END = 12",
["13"] = "S_EVENT_TOOK_CONTROL = 13",
["14"] = "S_EVENT_REFUELING_STOP = 14",
["15"] = "S_EVENT_BIRTH = 15",
["16"] = "S_EVENT_HUMAN_FAILURE = 16",
["17"] = "S_EVENT_DETAILED_FAILURE = 17",
["18"] = "S_EVENT_ENGINE_STARTUP = 18",
["19"] = "S_EVENT_ENGINE_SHUTDOWN = 19",
["20"] = "S_EVENT_PLAYER_ENTER_UNIT = 20",
["21"] = "S_EVENT_PLAYER_LEAVE_UNIT = 21",
["22"] = "S_EVENT_PLAYER_COMMENT = 22",
["23"] = "S_EVENT_SHOOTING_START = 23",
["24"] = "S_EVENT_SHOOTING_END = 24",
["25"] = "S_EVENT_MARK_ADDED = 25",
["26"] = "S_EVENT_MARK_CHANGE = 26",
["27"] = "S_EVENT_MARK_REMOVED = 27",
["28"] = "S_EVENT_KILL = 28",
["29"] = "S_EVENT_SCORE = 29",
["30"] = "S_EVENT_UNIT_LOST = 30",
["31"] = "S_EVENT_LANDING_AFTER_EJECTION = 31",
["32"] = "S_EVENT_PARATROOPER_LENDING = 32",
["33"] = "S_EVENT_DISCARD_CHAIR_AFTER_EJECTION = 33",
["34"] = "S_EVENT_WEAPON_ADD = 34",
["35"] = "S_EVENT_TRIGGER_ZONE = 35",
["36"] = "S_EVENT_LANDING_QUALITY_MARK = 36",
["37"] = "S_EVENT_BDA = 37",
["38"] = "S_EVENT_AI_ABORT_MISSION = 38",
["39"] = "S_EVENT_DAYNIGHT = 39",
["40"] = "S_EVENT_FLIGHT_TIME = 40",
["41"] = "S_EVENT_PLAYER_SELF_KILL_PILOT = 41",
["42"] = "S_EVENT_PLAYER_CAPTURE_AIRFIELD = 42",
["43"] = "S_EVENT_EMERGENCY_LANDING = 43",
["44"] = "S_EVENT_UNIT_CREATE_TASK = 44",
["45"] = "S_EVENT_UNIT_DELETE_TASK = 45",
["46"] = "S_EVENT_SIMULATION_START = 46",
["47"] = "S_EVENT_WEAPON_REARM = 47",
["48"] = "S_EVENT_WEAPON_DROP = 48",
["49"] = "S_EVENT_UNIT_TASK_TIMEOUT = 49",
["50"] = "S_EVENT_UNIT_TASK_STAGE = 50",
["51"] = "S_EVENT_MAC_SUBTASK_SCORE = 51",
["52"] = "S_EVENT_MAC_EXTRA_SCORE = 52",
["53"] = "S_EVENT_MISSION_RESTART = 53",
["54"] = "S_EVENT_MISSION_WINNER = 54",
["55"] = "S_EVENT_POSTPONED_TAKEOFF = 55",
["56"] = "S_EVENT_POSTPONED_LAND = 56",
["57"] = "S_EVENT_MAX = 57",
}
--
-- Logging & saving
--
@ -110,13 +176,13 @@ end
--
function debugger.createDebuggerWithZone(theZone)
-- watchflag input trigger
theZone.debugInputMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
if cfxZones.hasProperty(theZone, "debugTriggerMethod") then
theZone.debugInputMethod = cfxZones.getStringFromZoneProperty(theZone, "debugTriggerMethod", "change")
elseif cfxZones.hasProperty(theZone, "inputMethod") then
theZone.debugInputMethod = cfxZones.getStringFromZoneProperty(theZone, "inputMethod", "change")
elseif cfxZones.hasProperty(theZone, "sayWhen") then
theZone.debugInputMethod = cfxZones.getStringFromZoneProperty(theZone, "sayWhen", "change")
theZone.debugInputMethod = theZone:getStringFromZoneProperty( "triggerMethod", "change")
if theZone.hasProperty("debugTriggerMethod") then
theZone.debugInputMethod = theZone:getStringFromZoneProperty("debugTriggerMethod", "change")
elseif theZone:hasProperty("inputMethod") then
theZone.debugInputMethod = theZone:getStringFromZoneProperty(theZone, "inputMethod", "change")
elseif theZone:hasProperty("sayWhen") then
theZone.debugInputMethod = theZone:getStringFromZoneProperty("sayWhen", "change")
end
-- say who we are and what we are monitoring
@ -125,13 +191,13 @@ function debugger.createDebuggerWithZone(theZone)
end
-- read main debug array
local theFlags = cfxZones.getStringFromZoneProperty(theZone, "debug?", "<none>")
local theFlags = theZone:getStringFromZoneProperty("debug?", "<none>")
-- now, create an array from that
local flagArray = cfxZones.flagArrayFromString(theFlags)
local valueArray = {}
-- now establish current values
for idx, aFlag in pairs(flagArray) do
local fVal = cfxZones.getFlagValue(aFlag, theZone)
local fVal = theZone:getFlagValue(aFlag)
if debugger.verbose or theZone.verbose then
debugger.outText(" monitoring flag <" .. aFlag .. ">, inital value is <" .. fVal .. ">", 30)
end
@ -140,28 +206,44 @@ function debugger.createDebuggerWithZone(theZone)
theZone.flagArray = flagArray
theZone.valueArray = valueArray
-- DML output method
theZone.debugOutputMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
if cfxZones.hasProperty(theZone, "outputMethod") then
theZone.debugOutputMethod = cfxZones.getStringFromZoneProperty(theZone, "outputMethod", "inc")
theZone.debugOutputMethod = theZone:getStringFromZoneProperty("method", "inc")
if theZone:hasProperty("outputMethod") then
theZone.debugOutputMethod = theZone:getStringFromZoneProperty("outputMethod", "inc")
end
if cfxZones.hasProperty(theZone, "debugMethod") then
theZone.debugOutputMethod = cfxZones.getStringFromZoneProperty(theZone, "debugMethod", "inc")
if theZone:hasProperty("debugMethod") then
theZone.debugOutputMethod = theZone:getStringFromZoneProperty("debugMethod", "inc")
end
-- notify!
if cfxZones.hasProperty(theZone, "notify!") then
theZone.debugNotify = cfxZones.getStringFromZoneProperty(theZone, "notify!", "<none>")
if theZone:hasProperty("notify!") then
theZone.debugNotify = theZone:getStringFromZoneProperty("notify!", "<none>")
end
-- debug message, can use all messenger vals plus <f> for flag name
-- we use out own default
-- with <f> meaning flag name, <p> previous value, <c> current value
theZone.debugMsg = cfxZones.getStringFromZoneProperty(theZone, "debugMsg", "---debug: <t> -- Flag <f> changed from <p> to <c> [<z>]")
theZone.debugMsg = theZone:getStringFromZoneProperty("debugMsg", "---debug: <t> -- Flag <f> changed from <p> to <c> [<z>]")
end
function debugger.createEventMonWithZone(theZone)
local theFlags = theZone:getStringFromZoneProperty("events?", "<none>")
local flagArray = cfxZones.flagArrayFromString(theFlags)
local valueArray = {}
-- now establish current values
if debugger.verbose or theZone.verbose then
debugger.outText("*** monitoring events defined in <" .. theZone.name .. ">:", 30)
end
for idx, aFlag in pairs(flagArray) do
local evt = tonumber(aFlag)
if evt and (debugger.verbose or theZone.verbose) then
if evt < 0 then evt = 0 end
if evt > 57 then evt = 57 end
debugger.showEvents[evt] = debugDemon.eventList[tostring(evt)]
debugger.outText(" monitoring event <" .. debugger.showEvents[evt] .. ">", 30)
end
end
end
--
@ -457,6 +539,17 @@ function debugger.start()
debugger.outText("***Warning: Zone <" .. aZone.name .. "> has a 'debug' flag. Are you perhaps missing a '?'", 30)
end
local attrZones = cfxZones.getZonesWithAttributeNamed("events?")
for k, aZone in pairs(attrZones) do
debugger.createEventMonWithZone(aZone) -- process attributes
end
local attrZones = cfxZones.getZonesWithAttributeNamed("events")
for k, aZone in pairs(attrZones) do
debugger.outText("***Warning: Zone <" .. aZone.name .. "> has a 'debug' flag. Are you perhaps missing a '?'", 30)
end
-- events
-- say if we are active
if debugger.verbose then
if debugger.active then
@ -493,7 +586,8 @@ debugDemon.verbose = false
Version History
1.0.0 - initial version
1.1.0 - save command, requires persistence
2.0.0 - eventmon
- dml zones OOP
--]]--
debugDemon.requiredLibs = {
@ -518,6 +612,10 @@ end
-- very simple: look if text begins with special sequence, and if so,
-- call the command processor.
function debugDemon:onEvent(theEvent)
-- first order of business: call the event monitor
debugDemon.doEventMon(theEvent)
-- now process our own
-- while we can hook into any of the three events,
-- we curently only utilize CHANGE Mark
if not (theEvent.id == world.event.S_EVENT_MARK_ADDED) and
@ -655,6 +753,10 @@ debugger.outText("*** debugger: commands are:" ..
"\n " .. debugDemon.markOfDemon .. "compare -- compare snapshot flag values with current" ..
"\n " .. debugDemon.markOfDemon .. "note <your note> -- add <your note> to the text log" ..
"\n\n " .. debugDemon.markOfDemon .. "remove <group/unit/object name> -- remove named item from mission" ..
"\n\n " .. debugDemon.markOfDemon .. "eventmon [all | off | <number> | ?] -- show events for all | none | event <number> | list" ..
"\n\n " .. debugDemon.markOfDemon .. "q <Lua Var> -- Query value of Lua variable <Lua Var>" ..
"\n " .. debugDemon.markOfDemon .. "w <Lua Var> [=] <Lua Value> -- Write <Lua Value> to variable <Lua Var>" ..
"\n\n " .. debugDemon.markOfDemon .. "start -- starts debugger" ..
"\n " .. debugDemon.markOfDemon .. "stop -- stop debugger" ..
@ -893,17 +995,7 @@ function debugDemon.processSnapCommand(args, event)
end
-- set up snapshot
local snapshot = debugDemon.createSnapshot(allObservers) --{}
--[[--
for idx, theZone in pairs(allObservers) do
-- iterate each observer
for idy, flagName in pairs (theZone.flagArray) do
local fullName = cfxZones.expandFlagName(flagName, theZone)
local fVal = trigger.misc.getUserFlag(fullName)
snapshot[fullName] = fVal
end
end
--]]--
local snapshot = debugDemon.createSnapshot(allObservers)
local sz = dcsCommon.getSizeOfTable(snapshot)
debugDemon.snapshot = snapshot
@ -1176,6 +1268,141 @@ function debugDemon.processRemoveCommand(args, event)
debugger.outText("*** remove: did not find anything called <" .. aName .. "> to remove", 30)
return true
end
function debugDemon.doEventMon(theEvent)
if not theEvent then return end
local ID = theEvent.id
if debugger.showEvents[ID] then
-- we show this event
m = "*** event <" .. debugger.showEvents[ID] .. ">"
-- see if we have initiator
if theEvent.initiator then
local theUnit = theEvent.initiator
if Unit.isExist(theUnit) then
m = m .. " for "
if theUnit.getPlayerName and theUnit:getPlayerName() then
m = m .. "player = " .. theUnit:getPlayerName() .. " in "
end
m = m .. "unit <" .. theUnit:getName() .. ">"
end
end
debugger.outText(m, 30)
end
end
function debugDemon.processEventMonCommand(args, event)
-- turn event monito on/off
-- syntax: -eventmon on|off
local aParam = dcsCommon.trim(event.remainder)
if not aParam or aParam:len() < 1 then
aParam = "all"
end
aParam = string.upper(aParam)
evtNum = tonumber(aParam)
if aParam == "ON" or aParam == "ALL" then
-- debugger.eventmon = true
debugger.outText("*** eventmon: turned ON, showing ALL events", 30)
local events = {}
for idx,evt in pairs(debugDemon.eventList) do
events[tonumber(idx)] = evt
end
debugger.showEvents = events
elseif evtNum then -- add the numbered to
debugger.eventmon = false
if evtNum <= 0 then evtNum = 0 end
if evtNum >= 57 then evtNum = 35 end
debugger.showEvents[evtNum] = debugDemon.eventList[tostring(evtNum)]
debugger.outText("*** eventmon: added event <" .. debugger.showEvents[evtNum] .. ">", 30)
elseif aParam == "OFF" then
debugger.showEvents = {}
debugger.outText("*** eventmon: removed all events from monitor list", 30)
elseif aParam == "?" then
local m = "*** eventmon: currently tracking these events:"
for idx, evt in pairs(debugger.showEvents) do
m = m .. "\n" .. evt
end
debugger.outText(m .. "\n*** end of list", 30)
else
debugger.outText("*** eventmon: unknown parameter <" .. event.remainder .. ">", 30)
end
return true
end
--
-- read and write directly to Lua tables
--
function debugDemon.processQueryCommand(args, event)
-- syntax -q <name> with name a (qualified) Lua table reference
local theName = args[1]
-- local p = args [2]
-- trigger.action.outText("args1 = " .. theName, 30)
-- if args[2] then trigger.action.outText("param = " .. args[2], 30) end
if not theName then
debugger.outText("*** q: missing Lua table/element name.", 30)
return false -- allows correction
end
theName = dcsCommon.stringRemainsStartingWith(event.remainder, theName)
-- put this into a string, and execute it
local exec = "return " .. theName
local f = loadstring(exec)
local res
if pcall(f) then
res = f()
if type(res) == "boolean" then
res = "[BOOL FALSE]"
if res then res = "[BOOL TRUE]" end
elseif type(res) == "table" then res = "[Lua Table]"
elseif type(res) == "nil" then res = "[NIL]"
elseif type(res) == "function" then res = "[Lua Function]"
elseif type(res) == "number" or type(res) == "string" then
res = res .. " (a " .. type(res) .. ")"
else res = "[Lua " .. type(res) .. "]"
end
else
res = "[Lua error]"
end
debugger.outText("[" .. dcsCommon.nowString() .. "] <" .. theName .. "> = ".. res, 30)
return true
end
function debugDemon.processWriteCommand(args, event)
-- syntax -w <name> <value> with name a (qualified) Lua table reference and value a Lua value (including strings, with quotes of course). {} means an empty set etc. you CAN call into DCS MSE with this, and create a lot of havoc.
-- also, allow "=" semantic, -w p = {x=1, y=2}
local theName = args[1]
if not theName then
debugger.outText("*** w: missing Lua table/element name.", 30)
return false -- allows correction
end
local param = args [2]
if param == "=" then param = args[3] end
if not param then
debugger.outText("*** w: missing value to set to")
return false
end
param = dcsCommon.stringRemainsStartingWith(event.remainder, param)
-- put this into a string, and execute it
local exec = theName .. " = " .. param
local f = loadstring(exec)
local res
if pcall(f) then
res = "<" .. theName .. "> set to <" .. param .. ">"
else
res = "[Unable to set - Lua error]"
end
debugger.outText("[" .. dcsCommon.nowString() .. "] " .. res, 30)
return true
end
--
-- init and start
--
@ -1246,7 +1473,10 @@ function debugDemon.init()
debugDemon.addCommndProcessor("help", debugDemon.processHelpCommand)
debugDemon.addCommndProcessor("remove", debugDemon.processRemoveCommand)
debugDemon.addCommndProcessor("eventmon", debugDemon.processEventMonCommand)
debugDemon.addCommndProcessor("q", debugDemon.processQueryCommand)
debugDemon.addCommndProcessor("w", debugDemon.processWriteCommand)
return true
end
@ -1272,7 +1502,7 @@ end
if debugDemon.init() then
debugDemon.start()
else
trigger.action.outText("*** interactive flag debugger failed to initialize.", 30)
trigger.action.outText("*** interactive debugger failed to initialize.", 30)
debugDemon = {}
end
@ -1287,7 +1517,9 @@ end
-q x.y returns table, 12 elements
-q a.b.x returns number 12
-q d.e.f returns string "asdasda..."
-q sada reuturs <nil>
-q sada returs <nil>
- xref: which zones/attributes reference a flag, g.g. '-xref go'
- dml version can config to start with events list, e.g. 1, 4, 7
--]]--

Binary file not shown.