Version 1.2.0

LINK UNIT support
This commit is contained in:
Christian Franz 2022-12-29 12:36:54 +01:00
parent 3de20ed5f1
commit 46afa49c3a
5 changed files with 176 additions and 57 deletions

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxZones = {}
cfxZones.version = "2.9.2"
cfxZones.version = "3.0.0"
-- cf/x zone management module
-- reads dcs zones and makes them accessible and mutable
@ -113,6 +113,9 @@ cfxZones.version = "2.9.2"
- createRandomZoneInZone uses createRandomPointInPolyZone
- new createRandomPointInZone()
- new randomPointInZone()
- 3.0.0 - support for DCS 2.8 linkUnit attribute, integration with
linedUnit and warning.
- initZoneVerbosity()
--]]--
@ -216,8 +219,18 @@ function cfxZones.readFromDCS(clearfirst)
-- so we need to change (x,y) into (x, 0, z). Since Zones have no
-- altitude (they are an infinite cylinder) this works. Remember to
-- drop y from zone calculations to see if inside.
newZone.point = cfxZones.createPoint(dcsZone.x, 0, dcsZone.y)
newZone.dcsOrigin = cfxZones.createPoint(dcsZone.x, 0, dcsZone.y)
-- WARNING: ME linked zones have a relative x any y
-- to the linked unit
if dcsZone.linkUnit then
-- calculate the zone's real position by accessing the unit's MX data
-- as precached by dcsCommon
local ux, uy = dcsCommon.getUnitStartPosByID(dcsZone.linkUnit)
newZone.point = cfxZones.createPoint(ux + dcsZone.x, 0, uy + dcsZone.y)
newZone.dcsOrigin = cfxZones.createPoint(ux + dcsZone.x, 0, uy + dcsZone.y)
else
newZone.point = cfxZones.createPoint(dcsZone.x, 0, dcsZone.y)
newZone.dcsOrigin = cfxZones.createPoint(dcsZone.x, 0, dcsZone.y)
end
-- start type processing. if zone.type exists, we have a mission
-- created with 2.7 or above, else earlier
@ -2319,22 +2332,29 @@ function cfxZones.updateMovingZones()
end
function cfxZones.initLink(theZone)
--trigger.action.outText("enter initlink for <" .. theZone.name .. ">", 30)
--trigger.action.outText("entry verbose check: <" .. theZone.name .. "> is verbose = " .. dcsCommon.bool2YesNo(theZone.verbose), 30)
theZone.linkBroken = true
theZone.linkedUnit = nil
theUnit = Unit.getByName(theZone.linkName)
if theUnit then
--trigger.action.outText("initlink has link to <" .. theZone.linkName .. "> for <" .. theZone.name .. ">", 30)
local dx = 0
local dz = 0
if theZone.useOffset or theZone.useHeading then
local delta = dcsCommon.vSub(cfxZones.getDCSOrigin(theZone),theUnit:getPoint()) -- delta = B - A
local A = cfxZones.getDCSOrigin(theZone)
local B = theUnit:getPoint()
local delta = dcsCommon.vSub(A,B)
dx = delta.x
dz = delta.z
end
cfxZones.linkUnitToZone(theUnit, theZone, dx, dz) -- also sets theZone.linkedUnit
--trigger.action.outText("verbose check: <" .. theZone.name .. "> is verbose = " .. dcsCommon.bool2YesNo(theZone.verbose), 30)
if theZone.verbose then
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
theZone.linkBroken = nil
--trigger.action.outText("done linking <" .. theZone.linkName .. "> to zone <" .. theZone.name .. ">", 30)
else
if theZone.verbose then
trigger.action.outText("Linked unit: no unit <" .. theZone.linkName .. "> to link <" .. theZone.name .. "> to", 30)
@ -2343,49 +2363,48 @@ function cfxZones.initLink(theZone)
end
function cfxZones.startMovingZones()
-- read all zoness, and look for a property called 'linkedUnit'
-- read all zones, and look for a property called 'linkedUnit'
-- which will make them a linked zone if there is a unit that exists
-- also suppors 'useOffset' and 'useHeading'
for aName,aZone in pairs(cfxZones.zones) do
local lU = nil
if cfxZones.hasProperty(aZone, "linkedUnit") then
-- check if DCS zone has the linkUnit new attribute introduced in
-- late 2022 with 2.8
if aZone.dcsZone.linkUnit then
local theID = aZone.dcsZone.linkUnit
lU = dcsCommon.getUnitNameByID(theID)
if not lU then
trigger.action.outText("WARNING: Zone <" .. aZone.name .. ">: cannot resolve linked unit ID <" .. theID .. ">", 30)
lU = "***DML link err***"
end
elseif cfxZones.hasProperty(aZone, "linkedUnit") then
lU = cfxZones.getZoneProperty(aZone, "linkedUnit")
end
-- sanity check
if aZone.dcsZone.linkUnit and cfxZones.hasProperty(aZone, "linkedUnit") then
trigger.action.outText("WARNING: Zone <" .. aZone.name .. "> has dual unit link definition. Will use link to unit <" .. lU .. ">", 30)
end
if lU then
aZone.linkName = lU
aZone.useOffset = cfxZones.getBoolFromZoneProperty(aZone, "useOffset", false)
aZone.useHeading = cfxZones.getBoolFromZoneProperty(aZone, "useHeading", false)
cfxZones.initLink(aZone)
--[[--
-- this zone is linked to a unit
theUnit = Unit.getByName(lU)
local useOffset = cfxZones.getBoolFromZoneProperty(aZone, "useOffset", false)
if useOffset then aZone.useOffset = true end
local useHeading = cfxZones.getBoolFromZoneProperty(aZone, "useHeading")
if useHeading then aZone.useHeading = true end
if theUnit then
local dx = 0
local dz = 0
if useOffset or useHeading then
local delta = dcsCommon.vSub(aZone.point,theUnit:getPoint()) -- delta = B - A
dx = delta.x
dz = delta.z
end
cfxZones.linkUnitToZone(theUnit, aZone, dx, dz)
--trigger.action.outText("Link setup: dx=<" .. dx .. ">, dz=<" .. dz .. ">", 30)
if useOffset then
end
else
trigger.action.outText("Linked unit: no unit to link <" .. aZone.name .. "> to", 30)
end
--]]--
end
end
end
function cfxZones.initZoneVerbosity()
for aName,aZone in pairs(cfxZones.zones) do
-- support for zone-local verbose flag
aZone.verbose = cfxZones.getBoolFromZoneProperty(aZone, "verbose", false)
end
end
--
-- init
--
@ -2405,6 +2424,9 @@ function cfxZones.init()
aZone.owner = cfxZones.getCoalitionFromZoneProperty(aZone, "owner", 0)
end
-- enable all zone's verbose flags if present
-- must be done BEFORE we start the moving zones
cfxZones.initZoneVerbosity()
-- now initialize moving zones
cfxZones.startMovingZones()

View File

@ -1,5 +1,5 @@
cloneZones = {}
cloneZones.version = "1.6.1"
cloneZones.version = "1.6.3"
cloneZones.verbose = false
cloneZones.requiredLibs = {
"dcsCommon", -- always
@ -71,7 +71,10 @@ cloneZones.allCObjects = {} -- all clones objects
- cloning with rndLoc supports polygons
- corrected rndLoc without centerOnly to not include individual offsets
- ensure support of recovery tanker resolve cloned group
1.6.2 - optimization to hasLiveUnits()
1.6.3 - removed verbosity bug with rndLoc
uniqueNameGroupData has provisions for naming scheme
new uniqueNameStaticData() for naming scheme
--]]--
@ -512,14 +515,23 @@ function cloneZones.uniqueID()
return uid
end
function cloneZones.uniqueNameGroupData(theData)
function cloneZones.uniqueNameGroupData(theData, theCloneZone)
theData.name = dcsCommon.uuid(theData.name)
local units = theData.units
for idx, aUnit in pairs(units) do
aUnit.name = dcsCommon.uuid(aUnit.name)
if theCloneZone and theCloneZone.namingScheme then
else
-- default naming scheme: <name>-<uuid>
aUnit.name = dcsCommon.uuid(aUnit.name)
end
end
end
function cloneZones.uniqueNameStaticData(theData, spawnZone)
theData.name = dcsCommon.uuid(theData.name)
end
function cloneZones.uniqueIDGroupData(theData)
theData.groupId = cloneZones.uniqueID()
end
@ -821,21 +833,12 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
if spawnZone.rndLoc then
-- calculate the entire group's displacement
local units = rawData.units
--[[
local r = math.random() * spawnZone.radius
local phi = 6.2831 * math.random() -- that's 2Pi, folx
local dx = r * math.cos(phi)
local dy = r * math.sin(phi)
--]]
local loc, dx, dy = cfxZones.createRandomPointInZone(spawnZone) -- also supports polygonal zones
for idx, aUnit in pairs(units) do
if not spawnZone.centerOnly then
-- *every unit's displacement is randomized
-- r = math.random() * spawnZone.radius
-- phi = 6.2831 * math.random() -- that's 2Pi, folx
-- dx = r * math.cos(phi)
-- dy = r * math.sin(phi)
loc, dx, dy = cfxZones.createRandomPointInZone(spawnZone)
aUnit.x = loc.x
aUnit.y = loc.z
@ -844,7 +847,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
aUnit.y = aUnit.y + dy
end
if spawnZone.verbose or cloneZones.verbose then
trigger.action.outText("+++clnZ: <" .. spawnZone.name .. "> R = " .. spawnZone.radius .. ":G<" .. rawData.name .. "/" .. aUnit.name .. "> - rndLoc: r = " .. r .. ", dx = " .. dx .. ", dy= " .. dy .. ".", 30)
trigger.action.outText("+++clnZ: <" .. spawnZone.name .. "> R = " .. spawnZone.radius .. ":G<" .. rawData.name .. "/" .. aUnit.name .. "> - rndLoc: dx = " .. dx .. ", dy= " .. dy .. ".", 30)
end
end
@ -923,7 +926,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
dcsCommon.rotateGroupData(rawData, spawnZone.turn + 57.2958 *dHeading, newCenter.x, newCenter.z)
-- make sure unit and group names are unique
cloneZones.uniqueNameGroupData(rawData)
cloneZones.uniqueNameGroupData(rawData, spawnZone)
-- see what country we spawn for
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
@ -1042,7 +1045,8 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
dcsCommon.rotateUnitData(rawData, spawnZone.turn + 57.2958 * dHeading, newCenter.x, newCenter.z)
-- make sure static name is unique and remember original
rawData.name = dcsCommon.uuid(rawData.name)
cloneZones.uniqueNameStaticData(rawData, spawnZone)
--rawData.name = dcsCommon.uuid(rawData.name)
rawData.unitId = cloneZones.uniqueID()
rawData.CZTargetID = rawData.unitId
@ -1210,12 +1214,18 @@ function cloneZones.hasLiveUnits(theZone)
if theZone.mySpawns then
for idx, aGroup in pairs(theZone.mySpawns) do
if aGroup:isExist() then
-- an easier/faster method would be to invoke
-- aGroup:getSize()
local uNum = aGroup:getSize()
if uNum > 0 then return true end
--[[
local allUnits = aGroup:getUnits()
for idy, aUnit in pairs(allUnits) do
if aUnit:isExist() and aUnit:getLife() >= 1 then
return true
end
end
--]]--
end
end
end

View File

@ -1,5 +1,5 @@
dcsCommon = {}
dcsCommon.version = "2.7.10"
dcsCommon.version = "2.8.0"
--[[-- VERSION HISTORY
2.2.6 - compassPositionOfARelativeToB
- clockPositionOfARelativeToB
@ -118,6 +118,11 @@ dcsCommon.version = "2.7.10"
- randomPointInCircle fixed erroneous local for x, z
- "scattered" formation repaired
2.7.10- semaphore groundwork
2.8.0 - new collectMissionIDs at start-up
- new getUnitNameByID
- new getGroupNameByID
- bool2YesNo alsco can return NIL
- new getUnitStartPosByID
--]]--
@ -134,6 +139,12 @@ dcsCommon.version = "2.7.10"
dcsCommon.troopCarriers = {"Mi-8MT", "UH-1H", "Mi-24P"} -- Ka-50 and Gazelle can't carry troops
dcsCommon.coalitionSides = {0, 1, 2}
-- lookup tables
dcsCommon.groupID2Name = {}
dcsCommon.unitID2Name = {}
dcsCommon.unitID2X = {}
dcsCommon.unitID2Y = {}
-- verify that a module is loaded. obviously not required
-- for dcsCommon, but all higher-order modules
function dcsCommon.libCheck(testingFor, requiredLibs)
@ -147,6 +158,82 @@ dcsCommon.version = "2.7.10"
return canRun
end
-- read all groups and units from miz and build a reference table
function dcsCommon.collectMissionIDs()
-- create cross reference tables to be able to get a group or
-- unit's name by ID
for coa_name_miz, coa_data in pairs(env.mission.coalition) do -- iterate all coalitions
local coa_name = coa_name_miz
if string.lower(coa_name_miz) == 'neutrals' then -- remove 's' at neutralS
coa_name = 'neutral'
end
-- directly convert coalition into number for easier access later
local coaNum = 0
if coa_name == "red" then coaNum = 1 end
if coa_name == "blue" then coaNum = 2 end
if type(coa_data) == 'table' then -- coalition = {bullseye, nav_points, name, county},
-- with county being an array
if coa_data.country then -- make sure there a country table for this coalition
for cntry_id, cntry_data in pairs(coa_data.country) do -- iterate all countries for this
-- per country = {id, name, vehicle, helicopter, plane, ship, static}
local countryName = string.lower(cntry_data.name)
local countryID = cntry_data.id
if type(cntry_data) == 'table' then -- filter strings .id and .name
for obj_type_name, obj_type_data in pairs(cntry_data) do
-- only look at helos, ships, planes and vehicles
if obj_type_name == "helicopter" or
obj_type_name == "ship" or
obj_type_name == "plane" or
obj_type_name == "vehicle" or
obj_type_name == "static" -- what about "cargo"?
then -- (so it's not id or name)
local category = obj_type_name
if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's at least one group!
for group_num, group_data in pairs(obj_type_data.group) do
local aName = group_data.name
local aID = group_data.groupId
-- store this reference
dcsCommon.groupID2Name[aID] = aName
-- now iterate all units in this group
-- for player into
for unit_num, unit_data in pairs(group_data.units) do
if unit_data.name and unit_data.unitId then
-- store this reference
dcsCommon.unitID2Name[unit_data.unitId] = unit_data.name
dcsCommon.unitID2X[unit_data.unitId] = unit_data.x
dcsCommon.unitID2Y[unit_data.unitId] = unit_data.y
end
end -- for all units
end -- for all groups
end --if has category data
end --if plane, helo etc... category
end --for all objects in country
end --if has country data
end --for all countries in coalition
end --if coalition has country table
end -- if there is coalition data
end --for all coalitions in mission
end
function dcsCommon.getUnitNameByID(theID)
-- accessor function for later expansion
return dcsCommon.unitID2Name[theID]
end
function dcsCommon.getGroupNameByID(theID)
-- accessor function for later expansion
return dcsCommon.groupID2Name[theID]
end
function dcsCommon.getUnitStartPosByID(theID)
local x = dcsCommon.unitID2X[theID]
local y = dcsCommon.unitID2Y[theID]
return x, y
end
-- returns only positive values, lo must be >0 and <= hi
function dcsCommon.randomBetween(loBound, hiBound)
if not loBound then loBound = 1 end
@ -2042,7 +2129,10 @@ end
end
function dcsCommon.bool2YesNo(theBool)
if not theBool then theBool = false end
if not theBool then
theBool = false
return "NIL"
end
if theBool then return "yes" end
return "no"
end
@ -2917,14 +3007,18 @@ function dcsCommon.setUserFlag(flagName, theValue)
end
trigger.action.setUserFlag(flagName, theValue)
end
--
--
-- INIT
--
--
-- init any variables the lib requires internally
-- init any variables, tables etc that the lib requires internally
function dcsCommon.init()
cbID = 0
-- create ID tables
dcsCommon.collectMissionIDs()
--dcsCommon.uuIdent = 0
if (dcsCommon.verbose) or true then
trigger.action.outText("dcsCommon v" .. dcsCommon.version .. " loaded", 10)
@ -2935,10 +3029,3 @@ end
-- do init.
dcsCommon.init()
--[[--
to do:
- formation 2Column
- formation 3Column
-]]--