Version 2,27

The Debugger XRef
This commit is contained in:
Christian Franz 2024-07-04 11:03:00 +02:00
parent 0513fac2f2
commit 76083ff2b6
14 changed files with 641 additions and 42 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxMX = {} cfxMX = {}
cfxMX.version = "2.0.1" cfxMX.version = "2.0.2"
cfxMX.verbose = false cfxMX.verbose = false
--[[-- --[[--
Mission data decoder. Access to ME-built mission structures Mission data decoder. Access to ME-built mission structures
@ -12,7 +12,7 @@ cfxMX.verbose = false
2.0.0 - clean-up 2.0.0 - clean-up
- harmonized with cfxGroups - harmonized with cfxGroups
2.0.1 - groupHotByName 2.0.1 - groupHotByName
2.0.2 - partOfGroupDataInZone(), allGroupsInZoneByData() from milHelo
--]]-- --]]--
cfxMX.groupNamesByID = {} cfxMX.groupNamesByID = {}
@ -343,6 +343,38 @@ function cfxMX.catText2ID(inText)
return outCat return outCat
end end
function cfxMX.partOfGroupDataInZone(theZone, theUnits) -- move to mx?
--local zP --= cfxZones.getPoint(theZone)
local zP = theZone:getDCSOrigin() -- don't use getPoint now.
zP.y = 0
for idx, aUnit in pairs(theUnits) do
local uP = {}
uP.x = aUnit.x
uP.y = 0
uP.z = aUnit.y -- !! y-z
if theZone:pointInZone(uP) then return true end
end
return false
end
function cfxMX.allGroupsInZoneByData(theZone) -- returns groups indexed by name and count
local theGroupsInZone = {}
local count = 0
for groupName, groupData in pairs(cfxMX.groupDataByName) do
if groupData.units then
if cfxMX.partOfGroupDataInZone(theZone, groupData.units) then
theGroupsInZone[groupName] = groupData -- DATA! work on clones!
count = count + 1
if theZone.verbose then
trigger.action.outText("+++cfxMX: added group <" .. groupName .. "> for zone <" .. theZone.name .. ">", 30)
end
end
end
end
return theGroupsInZone, count
end
function cfxMX.start() function cfxMX.start()
cfxMX.createCrossReferences() cfxMX.createCrossReferences()

View File

@ -1,5 +1,5 @@
cfxZones = {} cfxZones = {}
cfxZones.version = "4.3.4" cfxZones.version = "4.3.6"
-- cf/x zone management module -- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable -- reads dcs zones and makes them accessible and mutable
@ -53,6 +53,11 @@ cfxZones.version = "4.3.4"
- 4.3.2 - new getListFromZoneProperty() - 4.3.2 - new getListFromZoneProperty()
- 4.3.3 - hardened calculateZoneBounds - 4.3.3 - hardened calculateZoneBounds
- 4.3.4 - rewrote zone bounds for poly zones - 4.3.4 - rewrote zone bounds for poly zones
- 4.3.5 - hardened getStringFromZoneProperty against number value returns (WebEd bug)
- 4.3.6 - tiny optimization in isPointInsideQuad
- moving zone - hardening code for static objects
- moving zones - now deriving dx, dy,uHeading from dcsCommon xref for linked zones
--]]-- --]]--
-- --
@ -208,7 +213,7 @@ function cfxZones.readFromDCS(clearfirst)
-- add to my table -- add to my table
cfxZones.zones[upperName] = newZone -- WARNING: UPPER ZONE!!! cfxZones.zones[upperName] = newZone -- WARNING: UPPER ZONE!!!
--trigger.action.outText("znd: procced " .. newZone.name .. " with radius " .. newZone.radius, 30)
else else
if cfxZones.verbose then if cfxZones.verbose then
trigger.action.outText("cf/x zones: malformed zone #" .. i .. " dropped", 10) trigger.action.outText("cf/x zones: malformed zone #" .. i .. " dropped", 10)
@ -706,7 +711,7 @@ function cfxZones.isPointInsideQuad(thePoint, A, B, C, D)
-- so all we need to do is make sure all results of isLeft for all -- so all we need to do is make sure all results of isLeft for all
-- four sides are the same -- four sides are the same
mustMatch = isLeftXZ(A, B, thePoint) -- all test results must be the same and we are ok local mustMatch = isLeftXZ(A, B, thePoint) -- all test results must be the same and we are ok
-- they just must be the same side. -- they just must be the same side.
if (cfxZones.isLeftXZ(B, C, thePoint ~= mustMatch)) then return false end -- on other side than all before if (cfxZones.isLeftXZ(B, C, thePoint ~= mustMatch)) then return false end -- on other side than all before
if (cfxZones.isLeftXZ(C, D, thePoint ~= mustMatch)) then return false end if (cfxZones.isLeftXZ(C, D, thePoint ~= mustMatch)) then return false end
@ -2220,6 +2225,9 @@ function cfxZones.getStringFromZoneProperty(theZone, theProperty, default)
-- OOP heavy duty test here -- OOP heavy duty test here
local p = theZone:getZoneProperty(theProperty) local p = theZone:getZoneProperty(theProperty)
if not p then return default end if not p then return default end
if type(p) == "number" then
p = tostring(p)
end
if type(p) == "string" then if type(p) == "string" then
p = dcsCommon.trim(p) p = dcsCommon.trim(p)
if p == "" then p = default end if p == "" then p = default end
@ -2232,6 +2240,9 @@ function dmlZone:getStringFromZoneProperty(theProperty, default)
if not default then default = "" end if not default then default = "" end
local p = self:getZoneProperty(theProperty) local p = self:getZoneProperty(theProperty)
if not p then return default end if not p then return default end
if type(p) == "number" then
p = tostring(p)
end
if type(p) == "string" then if type(p) == "string" then
p = dcsCommon.trim(p) p = dcsCommon.trim(p)
if p == "" then p = default end if p == "" then p = default end
@ -3341,7 +3352,9 @@ function cfxZones.linkUnitToZone(theUnit, theZone, dx, dy) -- note: dy is really
theZone.dx = dx theZone.dx = dx
theZone.dy = dy theZone.dy = dy
theZone.rxy = math.sqrt(dx * dx + dy * dy) -- radius theZone.rxy = math.sqrt(dx * dx + dy * dy) -- radius
local unitHeading = dcsCommon.getUnitHeading(theUnit) local uName = theUnit:getName()
-- local unitHeading = dcsCommon.getUnitHeading(theUnit)
local unitHeading = dcsCommon.unitName2Heading[uName] -- get original unit's heading from ME
local bearingOffset = math.atan2(dy, dx) -- rads local bearingOffset = math.atan2(dy, dx) -- rads
if bearingOffset < 0 then bearingOffset = bearingOffset + 2 * 3.141592 end if bearingOffset < 0 then bearingOffset = bearingOffset + 2 * 3.141592 end
@ -3431,8 +3444,9 @@ function cfxZones.updateMovingZones()
cfxZones.initLink(aZone) cfxZones.initLink(aZone)
else --if aZone.linkName then else --if aZone.linkName then
-- always re-acquire linkedUnit via Unit.getByName() -- always re-acquire linkedUnit via Unit.getByName()
-- this way we gloss over any replacements via spawns -- this way we gloss over any replacements via spawns/clones
aZone.linkedUnit = Unit.getByName(aZone.linkName) aZone.linkedUnit = Unit.getByName(aZone.linkName)
if not aZone.linkUnit then aZone.linkUnit = StaticObject.getByName(aZone.linkName) end
end end
if aZone.linkedUnit then if aZone.linkedUnit then
@ -3465,14 +3479,15 @@ end
function cfxZones.initLink(theZone) function cfxZones.initLink(theZone)
theZone.linkBroken = true theZone.linkBroken = true
theZone.linkedUnit = nil theZone.linkedUnit = nil
theUnit = Unit.getByName(theZone.linkName) theUnit = Unit.getByName(theZone.linkName) -- unit or static
if not theUnit then theUnit = StaticObject.getByName(theZone.linkName) end
if theUnit then if theUnit then
local dx = 0 local dx = 0
local dz = 0 local dz = 0
if theZone.useOffset or theZone.useHeading then if theZone.useOffset or theZone.useHeading then
local A = cfxZones.getDCSOrigin(theZone) local A = cfxZones.getDCSOrigin(theZone)
local B = theUnit:getPoint() local B = dcsCommon.getOrigPositionByID(theZone.linkedUID)
local delta = dcsCommon.vSub(A,B) local delta = dcsCommon.vSub(A,B)
dx = delta.x dx = delta.x
dz = delta.z dz = delta.z
@ -3483,7 +3498,6 @@ function cfxZones.initLink(theZone)
trigger.action.outText("Link established for zone <" .. theZone.name .. "> to unit <" .. theZone.linkName .. ">: dx=<" .. math.floor(dx) .. ">, dz=<" .. math.floor(dz) .. "> dist = <" .. math.floor(math.sqrt(dx * dx + dz * dz)) .. ">" , 30) trigger.action.outText("Link established for zone <" .. theZone.name .. "> to unit <" .. theZone.linkName .. ">: dx=<" .. math.floor(dx) .. ">, dz=<" .. math.floor(dz) .. "> dist = <" .. math.floor(math.sqrt(dx * dx + dz * dz)) .. ">" , 30)
end end
theZone.linkBroken = nil theZone.linkBroken = nil
else else
if theZone.verbose then if theZone.verbose then
trigger.action.outText("Linked unit: no unit <" .. theZone.linkName .. "> to link <" .. theZone.name .. "> to", 30) trigger.action.outText("Linked unit: no unit <" .. theZone.linkName .. "> to link <" .. theZone.name .. "> to", 30)
@ -3494,14 +3508,14 @@ end
function dmlZone:initLink() function dmlZone:initLink()
self.linkBroken = true self.linkBroken = true
self.linkedUnit = nil self.linkedUnit = nil
theUnit = Unit.getByName(self.linkName) theUnit = Unit.getByName(self.linkName) -- unit or static
if not theUnit then theUnit = StaticObject.getByName(self.linkName) end
if theUnit then if theUnit then
local dx = 0 local dx = 0
local dz = 0 local dz = 0
if self.useOffset or self.useHeading then if self.useOffset or self.useHeading then
local A = self:getDCSOrigin() local A = self:getDCSOrigin()
local B = theUnit:getPoint() local B = dcsCommon.getOrigPositionByID(self.linkedUID)
local delta = dcsCommon.vSub(A,B) local delta = dcsCommon.vSub(A,B)
dx = delta.x dx = delta.x
dz = delta.z dz = delta.z
@ -3509,7 +3523,7 @@ function dmlZone:initLink()
self:linkUnitToZone(theUnit, dx, dz) -- also sets theZone.linkedUnit self:linkUnitToZone(theUnit, dx, dz) -- also sets theZone.linkedUnit
if self.verbose then if self.verbose then
trigger.action.outText("Link established for zone <" .. self.name .. "> to unit <" .. self.linkName .. ">: dx=<" .. math.floor(dx) .. ">, dz=<" .. math.floor(dz) .. "> dist = <" .. math.floor(math.sqrt(dx * dx + dz * dz)) .. ">" , 30) trigger.action.outText("DML:Link established for zone <" .. self.name .. "> to unit <" .. self.linkName .. ">: dx=<" .. math.floor(dx) .. ">, dz=<" .. math.floor(dz) .. "> dist = <" .. math.floor(math.sqrt(dx * dx + dz * dz)) .. ">" , 30)
end end
self.linkBroken = nil self.linkBroken = nil
@ -3531,27 +3545,33 @@ function cfxZones.startMovingZones()
-- late 2022 with 2.8 -- late 2022 with 2.8
if aZone.dcsZone.linkUnit then if aZone.dcsZone.linkUnit then
local theID = aZone.dcsZone.linkUnit local theID = aZone.dcsZone.linkUnit
lU = dcsCommon.getUnitNameByID(theID) lU = dcsCommon.getUnitNameByID(theID) -- can be unit OR STATIC OBJECT
if not lU then if not lU then
trigger.action.outText("WARNING: Zone <" .. aZone.name .. ">: cannot resolve linked unit ID <" .. theID .. ">", 30) trigger.action.outText("WARNING: Zone <" .. aZone.name .. ">: cannot resolve linked unit ID <" .. theID .. ">", 30)
lU = "***DML link err***" lU = "***DML link err***"
end end
elseif cfxZones.hasProperty(aZone, "linkedUnit") then aZone.linkedUID = lU
lU = cfxZones.getZoneProperty(aZone, "linkedUnit") elseif aZone:hasProperty("linkedUnit") then
lU = aZone:getZoneProperty("linkedUnit") -- getString: name of unit
local luid = dcsCommon.unitName2ID[lU]
if luid then
aZone.linkedUID = luid
else
trigger.action.outText("WARNING: zone <" .. aZone.name .. "> linked unit (by attribute) <" .. lU .. "> does not exist!", 30)
lU = nil
end
end end
-- sanity check -- sanity check
if aZone.dcsZone.linkUnit and cfxZones.hasProperty(aZone, "linkedUnit") then if aZone.dcsZone.linkUnit and aZone:hasProperty("linkedUnit") then
trigger.action.outText("WARNING: Zone <" .. aZone.name .. "> has dual unit link definition. Will use link to unit <" .. lU .. ">", 30) trigger.action.outText("WARNING: Zone <" .. aZone.name .. "> has dual unit link definition. Will use link to unit <" .. lU .. ">", 30)
end end
if lU then if lU then
aZone.linkName = lU aZone.linkName = lU
aZone.useOffset = cfxZones.getBoolFromZoneProperty(aZone, "useOffset", false) aZone.useOffset = aZone:getBoolFromZoneProperty("useOffset", false)
aZone.useHeading = cfxZones.getBoolFromZoneProperty(aZone, "useHeading", false) aZone.useHeading = aZone:getBoolFromZoneProperty("useHeading", false)
cfxZones.initLink(aZone) cfxZones.initLink(aZone)
end end
end end

219
modules/convoy.lua Normal file
View File

@ -0,0 +1,219 @@
convoy = {}
convoy.version = "0.0.0"
convoy.requiredLibs = {
"dcsCommon",
"cfxZones",
"cfxMX",
}
convoy.zones = {}
convoy.running = {}
convoy.ups = 1
function convoy.addConvoyZone(theZone)
convoy.zones[theZone.name] = theZone
end
function convoy.readConvoyZone(theZone)
theZone.coa = theZone:getCoalitionFromZoneProperty("coalition", 0)
if theZone:hasProperty("masterOwner") then
local mo = theZone:getStringFromZoneProperty("masterOwner")
local mz = cfxZones.getZoneByName(mo)
if not mz then
trigger.action.outText("+++cvoy: WARNING: Master Owner <" .. mo .. "> for zone <" .. theZone.name .. "> does not exist!", 30)
else
theZone.masterOwner = mz
end
theZone.isDynamic = theZone:getBoolFromZoneProperty("dynamic", true)
end
-- get groups inside me.
local myGroups, count = cfxMX.allGroupsInZoneByData(theZone)
trigger.action.outText("zone <" .. theZone.name .. ">: <" .. count .. "> convoy groups", 30)
theZone.myGroups = myGroups
theZone.unique = theZone:getBoolFromZoneProperty("unique", true)
theZone.preWipe = theZone:getBoolFromZoneProperty("preWipe", true) or theZone.unique
theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false)
-- wipe all existing
for groupName, data in pairs(myGroups) do
local g = Group.getByName(groupName)
if g then
Group.destroy(g)
end
end
end
function convoy.startConvoy(theZone)
-- make sure my coa is set up correctly
local mo = theZone.masterOwner
if mo then
theZone.owner = mo.owner
if theZone.isDynamic then
theZone.coa = mo.owner
end
end
-- iterate all groups
local spawns = {}
for gName, gOrig in pairs(theZone.myGroups) do
trigger.action.outText("convoy: startting group <" .. gName .. "> for zone <" .. theZone.name .. ">", 30)
local gData = dcsCommon.clone(gOrig)
-- make unique names for group and units if desired
if theZone.unique then
gData.name = dcsCommon.uuid(gOrig.name)
for idx, theUnit in pairs (gData.units) do
theUnit.name = dcsCommon.uuid(theUnit.name)
end
end
convoy.amendData(theZone, gData) -- add actions to route
-- wipe existing if requested
if theZone.preWipe then
end
local catRaw = cfxMX.groupTypeByName[gName]
local gCat = Group.Category.GROUND
if catRaw == "helicopter" then
gCat = Group.Category.HELICOPTER
elseif catRaw == "plane" then
gCat = Group.Category.AIRPLANE
elseif catRaw == "vehicle" then
gCat = Group.Category.GROUND
else -- missing so far: ship
trigger.action.outText("+++milH: ignored group <" .. gName .. ">: unknown type <" .. catRaw .. ">", 30)
end
local cty = dcsCommon.getACountryForCoalition(theZone.coa)
local theSpawnedGroup = coalition.addGroup(cty, gCat, gData)
spawns[gData.name] = theSpawnedGroup
trigger.action.outText("convoy <" .. theSpawnedGroup:getName() .. "> spawned for <" .. theZone.name .. ">", 30)
end
end
function convoy.amendData(theZone, theData)
-- place a callback action for each waypoint
-- in data block
if not theData.route then return end
local route = theData.route
if not route.points then return end
local points = route.points
local np = #points
if np < 1 then return end
trigger.action.outText("convoy: group <" .. theData.name .. ">, zone <" .. theZone.name .. ">, points=<" .. np .. ">", 30)
-- for i=1, np do
local newPoints = {}
for idx, aPoint in pairs(points) do
local wp = dcsCommon.clone(aPoint) -- points[i]
local tasks = wp.task.params.tasks
--local i = idx
-- if not tasks then tasks = {} end
-- if tasks then
-- dcsCommon.dumpVar2Str("RAW tasks 1bc " .. idx, tasks)
local tnew = #tasks + 1 -- new number for this task
local t = {
["number"] = tnew,
["auto"] = false,
["id"] = "WrappedAction",
["enabled"] = true,
["params"] = {
["action"] = {
["id"] = "Script",
["params"] = {
["command"] = "trigger.action.outText(\"convoy reached WP Index " .. idx .." = WP(" .. idx-1 .. ") of " .. np .. "\", 30)",
}, -- end of ["params"]
}, -- end of ["action"]
}, -- end of ["params"]
} -- end of task
-- add t to tasks
table.insert(tasks, t)
-- tasks[tnew] = t
-- dcsCommon.dumpVar2Str("tasks for modded 1bc " .. idx, tasks)
newPoints[idx] = wp
trigger.action.outText("convoy: added wp task to wp <" .. idx .. ">", 30)
-- end
-- dcsCommon.dumpVar2Str("modded point 1BC WP" .. idx, wp)
newPoints[idx] = wp
end
route.points = newPoints
-- dcsCommon.dumpVar2Str("points", points)
end
--
-- UPDATE
--
function convoy.update()
timer.scheduleFunction(convoy.update, {}, timer.getTime() + 1/convoy.ups)
-- update all master owners
for idx, theZone in pairs (convoy.zones) do
--[[-- local mo = theZone.masterOwner
if mo then
theZone.owner = mo.owner
if theZone.isDynamic then
theZone.coa = mo.owner
end
end --]]--
end
end
--
-- START
--
function convoy.readConfigZone()
local theZone = cfxZones.getZoneByName("convoyConfig")
if not theZone then
theZone = cfxZones.createSimpleZone("convoyConfig")
end
convoy.verbose = theZone.verbose
convoy.ups = theZone:getNumberFromZoneProperty("ups", 1)
end
function convoy.start()
if not dcsCommon.libCheck then
trigger.action.outText("cfx convoy requires dcsCommon", 30)
return false
end
if not dcsCommon.libCheck("cfx convoy", convoy.requiredLibs) then
return false
end
-- read config
convoy.readConfigZone()
-- process convoy Zones
local attrZones = cfxZones.getZonesWithAttributeNamed("convoy")
for k, aZone in pairs(attrZones) do
convoy.readConvoyZone(aZone) -- process attributes
convoy.addConvoyZone(aZone) -- add to list
end
-- start update
timer.scheduleFunction(convoy.update, {}, timer.getTime() + 1/convoy.ups)
-- start all zones that have onstart
for gName, theZone in pairs(convoy.zones) do
if theZone.onStart then
convoy.startConvoy(theZone)
end
end
return true
end
if not convoy.start() then
trigger.action.outText("convoy failed to start up")
convoy = nil
end
--[[--
convoy module
place over a fully configured group, will clone on command (start?)
reportWaypoint option. Add small script to each and every waypoint, will create report
destinationReached! -- adds script to last waypoint to hit this signal, also inits cb
dead! signal and cb. only applies to ground troops? can they disembark troops when hit?
attacked signal each time a unit is destroyed
importantType - type that must survive=
coalition / masterOwner
isActive# 0/1
can only have one active convoy
can it have helicopters?
--]]--

View File

@ -1,5 +1,5 @@
dcsCommon = {} dcsCommon = {}
dcsCommon.version = "3.0.8" dcsCommon.version = "3.0.9"
--[[-- VERSION HISTORY --[[-- VERSION HISTORY
3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false 3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false
- point2text new intsOnly option - point2text new intsOnly option
@ -20,9 +20,12 @@ dcsCommon.version = "3.0.8"
- new pointXpercentYdegOffAB() - new pointXpercentYdegOffAB()
3.0.6 - new arrayContainsStringCaseInsensitive() 3.0.6 - new arrayContainsStringCaseInsensitive()
3.0.7 - fixed small bug in wildArrayContainsString 3.0.7 - fixed small bug in wildArrayContainsString
3.0.8 - deepCopy() and deepTableCopy() alternates to clone() to patch 3.0.9 - deepCopy() and deepTableCopy() alternates to clone() to patch
around a strange DCS 2.9 issue around a strange DCS 2.9 issue
Kiowa added to Troop Carriers Kiowa added to Troop Carriers
3.0.9 - new getOrigPositionByID()
- unitName2ID[] reverse lookup
- unitName2Heading
--]]-- --]]--
@ -45,6 +48,8 @@ dcsCommon.version = "3.0.8"
dcsCommon.unitID2Name = {} dcsCommon.unitID2Name = {}
dcsCommon.unitID2X = {} dcsCommon.unitID2X = {}
dcsCommon.unitID2Y = {} dcsCommon.unitID2Y = {}
dcsCommon.unitName2ID = {}
dcsCommon.unitName2Heading = {}
-- verify that a module is loaded. obviously not required -- verify that a module is loaded. obviously not required
-- for dcsCommon, but all higher-order modules -- for dcsCommon, but all higher-order modules
@ -97,15 +102,18 @@ dcsCommon.version = "3.0.8"
local aID = group_data.groupId local aID = group_data.groupId
-- store this reference -- store this reference
dcsCommon.groupID2Name[aID] = aName dcsCommon.groupID2Name[aID] = aName
-- trigger.action.outText("cmn: group <" .. aName .. "> has id <" .. aID .. ">", 30)
-- now iterate all units in this group -- now iterate all units in this group
-- for player into -- for player into
for unit_num, unit_data in pairs(group_data.units) do for unit_num, unit_data in pairs(group_data.units) do
if unit_data.name and unit_data.unitId then if unit_data.name and unit_data.unitId then
-- store this reference -- store this reference
dcsCommon.unitID2Name[unit_data.unitId] = unit_data.name dcsCommon.unitID2Name[unit_data.unitId] = unit_data.name
-- trigger.action.outText("cmn: unit/obj <" .. unit_data.name .. "> has id <" .. unit_data.unitId .. ">", 30)
dcsCommon.unitName2Heading[unit_data.name] = unit_data.heading
dcsCommon.unitID2X[unit_data.unitId] = unit_data.x dcsCommon.unitID2X[unit_data.unitId] = unit_data.x
dcsCommon.unitID2Y[unit_data.unitId] = unit_data.y dcsCommon.unitID2Y[unit_data.unitId] = unit_data.y
dcsCommon.unitName2ID[unit_data.name] = unit_data.unitId
end end
end -- for all units end -- for all units
end -- for all groups end -- for all groups
@ -121,9 +129,14 @@ dcsCommon.version = "3.0.8"
function dcsCommon.getUnitNameByID(theID) function dcsCommon.getUnitNameByID(theID)
-- accessor function for later expansion -- accessor function for later expansion
return dcsCommon.unitID2Name[theID] return dcsCommon.unitID2Name[theID] -- warning: can be unit or static object
end end
function dcsCommon.getOrigPositionByID(theID)
local p = {x=dcsCommon.unitID2X[theID], y=0, z=dcsCommon.unitID2Y[theID]}
return p
end
function dcsCommon.getGroupNameByID(theID) function dcsCommon.getGroupNameByID(theID)
-- accessor function for later expansion -- accessor function for later expansion
return dcsCommon.groupID2Name[theID] return dcsCommon.groupID2Name[theID]

View File

@ -1,5 +1,5 @@
milHelo = {} milHelo = {}
milHelo.version = "1.0.0" milHelo.version = "1.0.2"
milHelo.requiredLibs = { milHelo.requiredLibs = {
"dcsCommon", "dcsCommon",
"cfxZones", "cfxZones",
@ -31,10 +31,10 @@ end
function milHelo.addMilTargetZone(theZone) function milHelo.addMilTargetZone(theZone)
milHelo.targets[theZone.name] = theZone -- overwrite if duplicate milHelo.targets[theZone.name] = theZone -- overwrite if duplicate
end end
--[[--
function milHelo.partOfGroupDataInZone(theZone, theUnits) -- move to mx? function milHelo.partOfGroupDataInZone(theZone, theUnits) -- move to mx?
local zP = cfxZones.getPoint(theZone) --local zP --= cfxZones.getPoint(theZone)
zP = theZone:getDCSOrigin() -- don't use getPoint now. local zP = theZone:getDCSOrigin() -- don't use getPoint now.
zP.y = 0 zP.y = 0
for idx, aUnit in pairs(theUnits) do for idx, aUnit in pairs(theUnits) do
@ -63,6 +63,7 @@ function milHelo.allGroupsInZoneByData(theZone) -- move to MX?
end end
return theGroupsInZone, count return theGroupsInZone, count
end end
--]]--
function milHelo.readMilHeloZone(theZone) -- process attributes function milHelo.readMilHeloZone(theZone) -- process attributes
-- get mission type. part of milHelo -- get mission type. part of milHelo
@ -88,7 +89,7 @@ function milHelo.readMilHeloZone(theZone) -- process attributes
end end
-- get all groups inside me -- get all groups inside me
local myGroups, count = milHelo.allGroupsInZoneByData(theZone) local myGroups, count = cfxMX.allGroupsInZoneByData(theZone)
theZone.myGroups = myGroups theZone.myGroups = myGroups
theZone.groupCount = count theZone.groupCount = count
theZone.hGroups = {} theZone.hGroups = {}
@ -662,7 +663,7 @@ end
-- update and event -- update and event
-- --
function milHelo.update() function milHelo.update()
timer.scheduleFunction(milHelo.update, {}, timer.getTime() + 1) timer.scheduleFunction(milHelo.update, {}, timer.getTime() + 1/milHelo.ups)
-- update all master owners -- update all master owners
for idx, theZone in pairs (milHelo.zones) do for idx, theZone in pairs (milHelo.zones) do
local mo = theZone.masterOwner local mo = theZone.masterOwner
@ -791,6 +792,7 @@ function milHelo.readConfigZone()
end end
milHelo.verbose = theZone.verbose milHelo.verbose = theZone.verbose
milHelo.landingDuration = theZone:getNumberFromZoneProperty("landingDuration", 180) -- seconds = 3 minutes milHelo.landingDuration = theZone:getNumberFromZoneProperty("landingDuration", 180) -- seconds = 3 minutes
milHelo.ups = theZone:getNumberFromZoneProperty("ups", 1)
end end

View File

@ -1,5 +1,5 @@
cfxObjectDestructDetector = {} cfxObjectDestructDetector = {}
cfxObjectDestructDetector.version = "2.0.2" cfxObjectDestructDetector.version = "2.0.3"
cfxObjectDestructDetector.verbose = false cfxObjectDestructDetector.verbose = false
cfxObjectDestructDetector.requiredLibs = { cfxObjectDestructDetector.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -22,6 +22,7 @@ cfxObjectDestructDetector.requiredLibs = {
API for PlayerScore to pass back redScore/blueScore API for PlayerScore to pass back redScore/blueScore
if objects was killed by player if objects was killed by player
verbosity bug fixed after kill (ref to old ID) verbosity bug fixed after kill (ref to old ID)
2.0.3 if no output! given,a warning and default are given
--]]-- --]]--
cfxObjectDestructDetector.objectZones = {} cfxObjectDestructDetector.objectZones = {}
@ -81,6 +82,9 @@ function cfxObjectDestructDetector.processObjectDestructZone(aZone)
aZone.outDestroyFlag = aZone:getStringFromZoneProperty("destroyed!", "*none") aZone.outDestroyFlag = aZone:getStringFromZoneProperty("destroyed!", "*none")
elseif aZone:hasProperty("objectDestroyed!") then elseif aZone:hasProperty("objectDestroyed!") then
aZone.outDestroyFlag = aZone:getStringFromZoneProperty( "objectDestroyed!", "*none") aZone.outDestroyFlag = aZone:getStringFromZoneProperty( "objectDestroyed!", "*none")
else
trigger.action.outText("+++ODD: WARNING: destrcut detector <" .. aZone.name .. "> has no output! attribute", 30)
aZone.outDestroyFlag = "sorryIforgot" -- so saving works
end end
--PlayerScore interface (data) --PlayerScore interface (data)

View File

@ -1,5 +1,5 @@
cfxSpawnZones = {} cfxSpawnZones = {}
cfxSpawnZones.version = "2.0.2" cfxSpawnZones.version = "2.0.3"
cfxSpawnZones.requiredLibs = { cfxSpawnZones.requiredLibs = {
"dcsCommon", -- common is of course needed for everything "dcsCommon", -- common is of course needed for everything
-- pretty stupid to check for this since we -- pretty stupid to check for this since we
@ -28,6 +28,7 @@ cfxSpawnZones.spawnedGroups = {}
- spawnWithSpawner direct link in spawner to spawnZones - spawnWithSpawner direct link in spawner to spawnZones
2.0.1 - fix in verifySpawnOwnership() when not master zone found 2.0.1 - fix in verifySpawnOwnership() when not master zone found
2.0.2 - new "moveFormation" attribute 2.0.2 - new "moveFormation" attribute
2.0.3 - corrected type in spawnUnits? attribute
--]]-- --]]--
@ -76,7 +77,7 @@ function cfxSpawnZones.createSpawner(inZone)
theSpawner.triggerFlag = inZone:getStringFromZoneProperty("spawn?", "none") theSpawner.triggerFlag = inZone:getStringFromZoneProperty("spawn?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
elseif inZone:hasProperty("spawnUnits?") then elseif inZone:hasProperty("spawnUnits?") then
theSpawner.triggerFlag = inZone:getStringFromZoneProperty( "spawnObject?", "none") theSpawner.triggerFlag = inZone:getStringFromZoneProperty( "spawnUnits?", "none")
theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag)
end end

View File

@ -1,5 +1,5 @@
stopGap = {} stopGap = {}
stopGap.version = "1.1.1" stopGap.version = "1.1.2"
stopGap.verbose = false stopGap.verbose = false
stopGap.ssbEnabled = true stopGap.ssbEnabled = true
stopGap.ignoreMe = "-sg" stopGap.ignoreMe = "-sg"
@ -51,6 +51,7 @@ stopGap.requiredLibs = {
1.0.10 - some more verbosity for spIgnore and sgIgnore zones (DML only) 1.0.10 - some more verbosity for spIgnore and sgIgnore zones (DML only)
1.1.0 - kickTheDead option 1.1.0 - kickTheDead option
1.1.1 - filter "from runway" clients 1.1.1 - filter "from runway" clients
1.1.2 - allNeutral (DML only)
--]]-- --]]--
@ -76,6 +77,10 @@ function stopGap.staticMXFromUnitMX(theGroup, theUnit)
theStatic.type = theUnit.type theStatic.type = theUnit.type
theStatic.name = theUnit.name -- will magically be replaced with player unit theStatic.name = theUnit.name -- will magically be replaced with player unit
theStatic.cty = cfxMX.countryByName[theGroup.name] theStatic.cty = cfxMX.countryByName[theGroup.name]
-- DML only: allNeutral
if stopGap.allNeutral then
theStatic.cty = dcsCommon.getACountryForCoalition(0)
end
return theStatic return theStatic
end end
@ -432,6 +437,7 @@ function stopGap.readConfigZone(theZone)
stopGap.refreshInterval = theZone:getNumberFromZoneProperty("refresh", -1) -- default: no refresh stopGap.refreshInterval = theZone:getNumberFromZoneProperty("refresh", -1) -- default: no refresh
stopGap.kickTheDead = theZone:getBoolFromZoneProperty("kickDead", true) stopGap.kickTheDead = theZone:getBoolFromZoneProperty("kickDead", true)
stopGap.allNeutral = theZone:getBoolFromZoneProperty("allNeutral", false)
end end
-- --
@ -492,4 +498,7 @@ end
if not stopGap.start() then if not stopGap.start() then
trigger.action.outText("+++ aborted stopGap v" .. stopGap.version .. " -- startup failed", 30) trigger.action.outText("+++ aborted stopGap v" .. stopGap.version .. " -- startup failed", 30)
stopGap = nil stopGap = nil
end end
--[[-- TODO
- allNeutral: spawn all player aircraft as neutral
--]]--

View File

@ -1,6 +1,5 @@
-- theDebugger 2.x
debugger = {} debugger = {}
debugger.version = "2.1.1" debugger.version = "3.0.0"
debugDemon = {} debugDemon = {}
debugDemon.version = "2.1.0" debugDemon.version = "2.1.0"
@ -40,6 +39,13 @@ debugger.log = ""
readback verification of flag set readback verification of flag set
fixed getProperty() in debugger with zone fixed getProperty() in debugger with zone
2.1.1 - removed bug that skipped events? when zone not verbose 2.1.1 - removed bug that skipped events? when zone not verbose
3.0.0 - xref module added
- x <zone/flag>
- x *
- x *f
- x *z
- x ?
--]]-- --]]--
@ -138,6 +144,263 @@ debugger.spawnTypes = {
["manpad"] = "Soldier stinger", ["manpad"] = "Soldier stinger",
["obj"] = "house2arm" ["obj"] = "house2arm"
} }
--
-- XREF MODULE
--
xref = {}
xref.version = "1.0.0"
xref.dmlObjects = {} -- dict by zone name:upper()
-- has inputs: dict of string for each '?' input, contains input flag name
-- has output: dict of array for each output '!', contains output flag names as array
xref.flags = {} -- dict by flag name
-- has froms: dict of zone of attributes that can write to this flags
-- has tos: dict of zones of attributes that read from flag
function xref.getDmlObject(name)
name = name:upper()
local theObject = xref.dmlObjects[name]
if not theObject then
theObject = {}
theObject.inputs = {} -- dict of string
theObject.outputs = {} -- dict of array
xref.dmlObjects[name] = theObject
end
return theObject
end
function xref.getFlag(name, theZone)
if theZone and dcsCommon.stringStartsWith(name, "*") then
-- local name conversion
name = theZone.name .. name
end
local theFlag = xref.flags[name]
if not theFlag then
theFlag = {}
theFlag.froms = {} -- dict by zone name/output that write to this flag
theFlag.tos = {} -- dict by zone name / inputs that reads from this flag
xref.flags[name] = theFlag
end
return theFlag
end
function xref.flagTo(flagName, inputName, theZone) -- connect flag to input in zone. Flag can connect to multiple inputs in same zone
local theFlag = xref.getFlag(flagName, theZone)
if not theFlag.tos[theZone.name] then
theFlag.tos[theZone.name] = {}
end
table.insert(theFlag.tos[theZone.name],inputName)
end
function xref.flagFrom(flagName, outputName, theZone) -- connect flag to output in zone. multiple outputs per zone
local theFlag = xref.getFlag(flagName, theZone)
if not theFlag.froms[theZone.name] then
theFlag.froms[theZone.name] = {}
end
table.insert(theFlag.froms[theZone.name], outputName)
end
function xref.addInput(theZone, inputName, inputFlagName)
local theObject = xref.getDmlObject(theZone.name)
local inputs = theObject.inputs
if not inputs then inputs = {} end
inputs[inputName] = inputFlagName -- each input connects one flag
xref.flagTo(inputFlagName, inputName, theZone)
theObject.inputs = inputs
end
function xref.addOutput(theZone, outputName, outputFlags)
local theObject = xref.getDmlObject(theZone.name)
local outputs = theObject.outputs
if not outputs then outputs = {} end
if dcsCommon.containsString(outputFlags, ",") then
local theArray = dcsCommon.splitString(outputFlags, ',')
theArray = dcsCommon.trimArray(theArray)
for idx, aFlagName in pairs(theArray) do
xref.flagFrom(aFlagName, outputName, theZone)
end
outputs[outputName] = theArray
else
local outputFlagName = dcsCommon.trim(outputFlags)
outputs[outputName] = {outputFlagName}
xref.flagFrom(outputFlagName, outputName, theZone)
end
theObject.outputs = outputs
end
function xref.scanMissionZones()
-- iterate all trigger zones
for idx, theZone in pairs(cfxZones.zones) do
-- iterate all properties
local attributes = theZone:getAllZoneProperties()
for name, value in pairs(attributes) do
-- find inputs
if dcsCommon.stringEndsWith(name, "?") then
xref.addInput(theZone, name, value)
end
-- find outputs
if dcsCommon.stringEndsWith(name, "!") then
xref.addOutput(theZone, name, value)
end
-- other stuff, e.g. "#"
-- find outputs
if dcsCommon.stringEndsWith(name, "#") then
xref.addOutput(theZone, name, value)
end
end
end
end
function xref.xrefFlag(name)
local msg = "\n<" .. name .. "> flag cross reference:"
local theFlag = xref.flags[name]
local tos = theFlag.tos
if dcsCommon.getSizeOfTable(tos) < 1 then
msg = msg .. "\n (NO INPUTS CONNECTED)"
else
msg = msg .. "\n '?' These zones/inputs? look at <" .. name .. ">:"
for zName, attributes in pairs (tos) do
msg = msg .. "\n " .. zName .. " - "
local c = 0
for idx, anInput in pairs(attributes) do
if c > 0 then msg = msg .. ", " end
c = 1
msg = msg .. anInput
end
end
end
local froms = theFlag.froms
if dcsCommon.getSizeOfTable(froms) < 1 then
msg = msg .. "\n (NO OUTPUTS CONNECTED)"
else
msg = msg .. "\n '!' These zones/outputs! change <" .. name .. ">:"
for zName, attributes in pairs (froms) do
msg = msg .. "\n " .. zName .." - "
local c = 0
for idx, anOutput in pairs(attributes) do
if c > 0 then msg = msg .. ", " end
c = 1
msg = msg .. anOutput
end
end
end
-- trigger.action.outText(msg, 30)
return msg
end
function xref.xrefZone(name, theObject)
local msg = "\nZone <" .. name .. "> :"
local ins = theObject.inputs
if dcsCommon.getSizeOfTable(ins) < 1 then
msg = msg .. "\n (NO INPUTS)"
else
msg = msg .. "\n has the following inputs:"
for iName, flagName in pairs (ins) do
msg = msg .. "\n " .. iName .. " : " .. flagName
end
end
local outs = theObject.outputs
if dcsCommon.getSizeOfTable(outs) < 1 then
msg = msg .. "\n (NO OUTPUTS)"
else
msg = msg .. "\n has the following outputs:"
for oName, flagList in pairs (outs) do
msg = msg .. "\n " .. oName .." - "
local c = 0
for idx, anOutput in pairs(flagList) do
if c > 0 then msg = msg .. ", " end
c = 1
msg = msg .. anOutput
end
end
end
-- trigger.action.outText(msg, 30)
return msg
end
function xref.xrefName(name)
if not name then name = "" end
if xref.flags[name] then
return xref.xrefFlag(name)
end
if xref.dmlObjects[name:upper()] then
return xref.xrefZone(name, xref.dmlObjects[name:upper()])
end
return "*** xref: <" .. name .. "> NOT USED WITH DML"
end
function xref.allFlags()
local msg = "xref: all flags used with DML in this mission:\n"
local c = 0
for name, data in pairs(xref.flags) do
if c > 0 then msg = msg .. ", " end
c = 1
msg = msg .. "<" .. name .. ">"
end
return msg
end
function xref.allZones()
local msg = "xref: all DML Zones in this mission:\n"
local c = 0
for name, data in pairs(xref.dmlObjects) do
if c > 0 then msg = msg .. ", " end
c = 1
msg = msg .. "<" .. name .. ">"
end
return msg
end
function xref.xall()
msg = ""
-- now dump all flags
for flagName, data in pairs (xref.flags) do
-- msg = msg .. xref.xrefFlag(flagName)
msg = msg .. xref.xrefName(flagName)
end
-- dump all zones
for zoneName, data in pairs(xref.dmlObjects) do
-- msg = msg .. xref.xrefZone(zoneName, data)
msg = msg .. xref.xrefName(zoneName)
end
return msg
-- trigger.action.outText(msg, 30)
end
function xref.start()
xref.scanMissionZones()
local flagNum = dcsCommon.getSizeOfTable(xref.flags)
local dmlObNum = dcsCommon.getSizeOfTable(xref.dmlObjects)
trigger.action.outText("XRef v" .. xref.version .. " full DML object scan on mission complete:\n<" .. flagNum .. "> flags are referenced in <" .. dmlObNum .. "> DML zones", 30)
-- trigger.action.outText(xref.xall(), 30)
end
-- run the xref
xref.start()
--[[--
to do
scan messenger and wildcards for flag access
--]]--
--
-- DEBUGGER MAIn
--
-- --
-- Logging & saving -- Logging & saving
-- --
@ -824,6 +1087,9 @@ debugger.outText("*** debugger: commands are:" ..
"\n " .. debugDemon.markOfDemon .. "inc <flagname> -- increase flag by 1, changing it" .. "\n " .. debugDemon.markOfDemon .. "inc <flagname> -- increase flag by 1, changing it" ..
"\n " .. debugDemon.markOfDemon .. "flip <flagname> -- when flag's value is 0, set it to 1, else to 0" .. "\n " .. debugDemon.markOfDemon .. "flip <flagname> -- when flag's value is 0, set it to 1, else to 0" ..
"\n\n " .. debugDemon.markOfDemon .. "x <zone/flagname> -- cross reference DML zone or flag" ..
"\n\n " .. debugDemon.markOfDemon .. "observe <flagname> [with <observername>] -- observe a flag for change" .. "\n\n " .. debugDemon.markOfDemon .. "observe <flagname> [with <observername>] -- observe a flag for change" ..
"\n " .. debugDemon.markOfDemon .. "o <flagname> [with <observername>] -- observe a flag for change" .. "\n " .. debugDemon.markOfDemon .. "o <flagname> [with <observername>] -- observe a flag for change" ..
"\n " .. debugDemon.markOfDemon .. "forget <flagname> [with <observername>] -- stop observing a flag" .. "\n " .. debugDemon.markOfDemon .. "forget <flagname> [with <observername>] -- stop observing a flag" ..
@ -1609,6 +1875,36 @@ function debugDemon.processBoomCommand(args, event)
debugger.outText("*** boom: placed <" .. power .. "> explosion at <" .. dcsCommon.point2text(p, true) .. ">.", 30) debugger.outText("*** boom: placed <" .. power .. "> explosion at <" .. dcsCommon.point2text(p, true) .. ">.", 30)
end end
--
-- xref
--
function debugDemon.processXrefCommand(args, event)
-- syntax: -x <name> | "*" | "*f" "*z"
local larg = args[1]
if not larg or larg == "" then larg = "?" end
larg = larg:lower()
if larg == "?" then
debugger.outText("*** xRef: ? = help (this), * = xref all, *f = list all DML flags, *z = list all DML zones, <name> xref flag or zone", 30)
return true -- leave up
elseif larg == "*" then
debugger.outText(xref.xall(), 30)
return true
elseif larg == "*f" then
debugger.outText(xref.allFlags(), 30)
return true
elseif larg == "*z" then
debugger.outText(xref.allZones(), 30)
return true
else
larg = event.remainder
larg = dcsCommon.trim(larg)
if not larg then larg = "" end
local msg = xref.xrefName(larg)
debugger.outText(msg, 30)
return true
end
end
-- --
-- spawning units at the location of the mark -- spawning units at the location of the mark
-- --
@ -1965,6 +2261,7 @@ function debugDemon.init()
debugDemon.addCommndProcessor("a", debugDemon.processAnalyzeCommand) debugDemon.addCommndProcessor("a", debugDemon.processAnalyzeCommand)
debugDemon.addCommndProcessor("smoke", debugDemon.processSmokeCommand) debugDemon.addCommndProcessor("smoke", debugDemon.processSmokeCommand)
debugDemon.addCommndProcessor("boom", debugDemon.processBoomCommand) debugDemon.addCommndProcessor("boom", debugDemon.processBoomCommand)
debugDemon.addCommndProcessor("x", debugDemon.processXrefCommand)
return true return true
end end

View File

@ -1,5 +1,5 @@
williePete = {} williePete = {}
williePete.version = "2.0.4" williePete.version = "2.0.5"
williePete.ups = 10 -- we update at 10 fps, so accuracy of a williePete.ups = 10 -- we update at 10 fps, so accuracy of a
-- missile moving at Mach 2 is within 33 meters, -- missile moving at Mach 2 is within 33 meters,
-- with interpolation even at 3 meters -- with interpolation even at 3 meters
@ -21,6 +21,7 @@ williePete.requiredLibs = {
2.0.2 - hardened playerUpdate() 2.0.2 - hardened playerUpdate()
2.0.3 - further hardened playerUpdate() 2.0.3 - further hardened playerUpdate()
2.0.4 - support for the Kiowa's Hydra M259 2.0.4 - support for the Kiowa's Hydra M259
2.0.5 - support for Mirage F1 WP that differ from Gazelle (?)
--]]-- --]]--
williePete.willies = {} williePete.willies = {}
@ -32,7 +33,8 @@ williePete.blastedObjects = {} -- used when we detonate something
-- recognizes WP munitions. May require regular update when new -- recognizes WP munitions. May require regular update when new
-- models come out. -- models come out.
williePete.smokeWeapons = {"HYDRA_70_M274","HYDRA_70_MK61","HYDRA_70_MK1","HYDRA_70_WTU1B","HYDRA_70_M156","HYDRA_70_M158","BDU_45B","BDU_33","BDU_45","BDU_45LGB","BDU_50HD","BDU_50LD","BDU_50LGB","C_8CM", "SNEB_TYPE254_H1_GREEN", "SNEB_TYPE254_H1_RED", "SNEB_TYPE254_H1_YELLOW", "FFAR M156 WP", williePete.smokeWeapons = {"HYDRA_70_M274","HYDRA_70_MK61","HYDRA_70_MK1","HYDRA_70_WTU1B","HYDRA_70_M156","HYDRA_70_M158","BDU_45B","BDU_33","BDU_45","BDU_45LGB","BDU_50HD","BDU_50LD","BDU_50LGB","C_8CM", "SNEB_TYPE254_H1_GREEN", "SNEB_TYPE254_H1_RED", "SNEB_TYPE254_H1_YELLOW",
"SNEB_TYPE254_F1B_YELLOW", "SNEB_TYPE254_F1B_GREEN", "SNEB_TYPE254_F1B_RED", "FFAR M156 WP",
"HYDRA_70_M259"} "HYDRA_70_M259"}
function williePete.addWillie(theWillie) function williePete.addWillie(theWillie)