mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 1.2.1
CloneZones: - nameScheme - indentical
This commit is contained in:
parent
46afa49c3a
commit
43d598f035
Binary file not shown.
Binary file not shown.
@ -1,10 +1,10 @@
|
|||||||
cfxMX = {}
|
cfxMX = {}
|
||||||
cfxMX.version = "1.2.4"
|
cfxMX.version = "1.2.5"
|
||||||
cfxMX.verbose = false
|
cfxMX.verbose = false
|
||||||
--[[--
|
--[[--
|
||||||
Mission data decoder. Access to ME-built mission structures
|
Mission data decoder. Access to ME-built mission structures
|
||||||
|
|
||||||
Copyright (c) 2022 by Christian Franz and cf/x AG
|
Copyright (c) 2022, 2023 by Christian Franz and cf/x AG
|
||||||
|
|
||||||
Version History
|
Version History
|
||||||
1.0.0 - initial version
|
1.0.0 - initial version
|
||||||
@ -24,9 +24,11 @@ cfxMX.verbose = false
|
|||||||
1.2.3 - groupTypeByName
|
1.2.3 - groupTypeByName
|
||||||
- groupCoalitionByName
|
- groupCoalitionByName
|
||||||
1.2.4 - playerUnit2Group cross index
|
1.2.4 - playerUnit2Group cross index
|
||||||
|
1.2.5 - unitIDbyName index added
|
||||||
--]]--
|
--]]--
|
||||||
cfxMX.groupNamesByID = {}
|
cfxMX.groupNamesByID = {}
|
||||||
cfxMX.groupIDbyName = {}
|
cfxMX.groupIDbyName = {}
|
||||||
|
cfxMX.unitIDbyName = {}
|
||||||
cfxMX.groupDataByName = {}
|
cfxMX.groupDataByName = {}
|
||||||
cfxMX.groupTypeByName = {} -- category of group: "helicopter", "plane", "ship"...
|
cfxMX.groupTypeByName = {} -- category of group: "helicopter", "plane", "ship"...
|
||||||
cfxMX.groupCoalitionByName = {}
|
cfxMX.groupCoalitionByName = {}
|
||||||
@ -234,7 +236,7 @@ function cfxMX.createCrossReferences()
|
|||||||
trigger.action.outText("+++MX: <" .. obj_type_name .. "> unknown type for <" .. aName .. ">", 30)
|
trigger.action.outText("+++MX: <" .. obj_type_name .. "> unknown type for <" .. aName .. ">", 30)
|
||||||
end
|
end
|
||||||
-- now iterate all units in this group
|
-- now iterate all units in this group
|
||||||
-- for player into
|
-- for unit xref like player info and ID
|
||||||
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.skill then
|
if unit_data.skill then
|
||||||
if unit_data.skill == "Client" or unit_data.skill == "Player" then
|
if unit_data.skill == "Client" or unit_data.skill == "Player" then
|
||||||
@ -244,6 +246,7 @@ function cfxMX.createCrossReferences()
|
|||||||
cfxMX.playerUnit2Group[unit_data.name] = group_data
|
cfxMX.playerUnit2Group[unit_data.name] = group_data
|
||||||
end -- if unit skill client
|
end -- if unit skill client
|
||||||
end -- if has skill
|
end -- if has skill
|
||||||
|
cfxMX.unitIDbyName[unit_data.name] = unit_data.unitId
|
||||||
end -- for all units
|
end -- for all units
|
||||||
end -- for all groups
|
end -- for all groups
|
||||||
end --if has category data
|
end --if has category data
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxObjectSpawnZones = {}
|
cfxObjectSpawnZones = {}
|
||||||
cfxObjectSpawnZones.version = "1.3.0"
|
cfxObjectSpawnZones.version = "1.3.1"
|
||||||
cfxObjectSpawnZones.requiredLibs = {
|
cfxObjectSpawnZones.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
|
||||||
@ -30,6 +30,8 @@ cfxObjectSpawnZones.verbose = false
|
|||||||
-- 1.3.0 - better synonym handling
|
-- 1.3.0 - better synonym handling
|
||||||
-- - useDelicates link to delicate when spawned
|
-- - useDelicates link to delicate when spawned
|
||||||
-- - spawned single and multi-objects can be made delicates
|
-- - spawned single and multi-objects can be made delicates
|
||||||
|
-- 1.3.1 - baseName can be set to zone's name by giving "*"
|
||||||
|
|
||||||
|
|
||||||
-- respawn currently happens after theSpawns is deleted and cooldown seconds have passed
|
-- respawn currently happens after theSpawns is deleted and cooldown seconds have passed
|
||||||
cfxObjectSpawnZones.allSpawners = {}
|
cfxObjectSpawnZones.allSpawners = {}
|
||||||
@ -92,6 +94,10 @@ function cfxObjectSpawnZones.createSpawner(inZone)
|
|||||||
|
|
||||||
theSpawner.rawOwner = coalition.getCountryCoalition(theSpawner.country)
|
theSpawner.rawOwner = coalition.getCountryCoalition(theSpawner.country)
|
||||||
theSpawner.baseName = cfxZones.getStringFromZoneProperty(inZone, "baseName", dcsCommon.uuid("objSpwn"))
|
theSpawner.baseName = cfxZones.getStringFromZoneProperty(inZone, "baseName", dcsCommon.uuid("objSpwn"))
|
||||||
|
theSpawner.baseName = dcsCommon.trim(theSpawner.baseName)
|
||||||
|
if theSpawner.baseName == "*" then
|
||||||
|
theSpawner.baseName = inZone.name -- convenience shortcut
|
||||||
|
end
|
||||||
--cfxZones.getZoneProperty(inZone, "baseName")
|
--cfxZones.getZoneProperty(inZone, "baseName")
|
||||||
theSpawner.cooldown = cfxZones.getNumberFromZoneProperty(inZone, "cooldown", 60)
|
theSpawner.cooldown = cfxZones.getNumberFromZoneProperty(inZone, "cooldown", 60)
|
||||||
theSpawner.lastSpawnTimeStamp = -10000 -- just init so it will always work
|
theSpawner.lastSpawnTimeStamp = -10000 -- just init so it will always work
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxSpawnZones = {}
|
cfxSpawnZones = {}
|
||||||
cfxSpawnZones.version = "1.7.1"
|
cfxSpawnZones.version = "1.7.2"
|
||||||
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
|
||||||
@ -63,6 +63,7 @@ cfxSpawnZones.spawnedGroups = {}
|
|||||||
-- 1.7.0 - persistence support
|
-- 1.7.0 - persistence support
|
||||||
-- 1.7.1 - improved verbosity
|
-- 1.7.1 - improved verbosity
|
||||||
-- - spelling check
|
-- - spelling check
|
||||||
|
-- 1.7.2 - baseName now can can be set to zone name by issuing "*"
|
||||||
--
|
--
|
||||||
-- new version requires cfxGroundTroops, where they are
|
-- new version requires cfxGroundTroops, where they are
|
||||||
--
|
--
|
||||||
@ -198,6 +199,10 @@ function cfxSpawnZones.createSpawner(inZone)
|
|||||||
theSpawner.rawOwner = coalition.getCountryCoalition(theSpawner.country)
|
theSpawner.rawOwner = coalition.getCountryCoalition(theSpawner.country)
|
||||||
--theSpawner.baseName = cfxZones.getZoneProperty(inZone, "baseName")
|
--theSpawner.baseName = cfxZones.getZoneProperty(inZone, "baseName")
|
||||||
theSpawner.baseName = cfxZones.getStringFromZoneProperty(inZone, "baseName", dcsCommon.uuid("SpwnDflt"))
|
theSpawner.baseName = cfxZones.getStringFromZoneProperty(inZone, "baseName", dcsCommon.uuid("SpwnDflt"))
|
||||||
|
theSpawner.baseName = dcsCommon.trim(theSpawner.baseName)
|
||||||
|
if theSpawner.baseName == "*" then
|
||||||
|
theSpawner.baseName = inZone.name -- convenience shortcut
|
||||||
|
end
|
||||||
|
|
||||||
theSpawner.cooldown = cfxZones.getNumberFromZoneProperty(inZone, "cooldown", 60)
|
theSpawner.cooldown = cfxZones.getNumberFromZoneProperty(inZone, "cooldown", 60)
|
||||||
theSpawner.autoRemove = cfxZones.getBoolFromZoneProperty(inZone, "autoRemove", false)
|
theSpawner.autoRemove = cfxZones.getBoolFromZoneProperty(inZone, "autoRemove", false)
|
||||||
|
|||||||
@ -116,6 +116,7 @@ cfxZones.version = "3.0.0"
|
|||||||
- 3.0.0 - support for DCS 2.8 linkUnit attribute, integration with
|
- 3.0.0 - support for DCS 2.8 linkUnit attribute, integration with
|
||||||
linedUnit and warning.
|
linedUnit and warning.
|
||||||
- initZoneVerbosity()
|
- initZoneVerbosity()
|
||||||
|
- 3.0.1 - updateMovingZones() better tracks linked units by name
|
||||||
|
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
@ -2304,13 +2305,22 @@ end
|
|||||||
|
|
||||||
function cfxZones.updateMovingZones()
|
function cfxZones.updateMovingZones()
|
||||||
cfxZones.updateSchedule = timer.scheduleFunction(cfxZones.updateMovingZones, {}, timer.getTime() + 1/cfxZones.ups)
|
cfxZones.updateSchedule = timer.scheduleFunction(cfxZones.updateMovingZones, {}, timer.getTime() + 1/cfxZones.ups)
|
||||||
-- simply scan all cfx zones for the linkedUnit property and if there
|
-- simply scan all cfx zones for the linkName property, and if present
|
||||||
-- update the zone's points
|
-- update the zone's points
|
||||||
for aName,aZone in pairs(cfxZones.zones) do
|
for aName,aZone in pairs(cfxZones.zones) do
|
||||||
|
-- only do this if ther is a linkName property,
|
||||||
|
-- else this zone isn't linked. link name is harmonized from
|
||||||
|
-- both linkUnit non-DML and linedUnit DML
|
||||||
|
if aZone.linkName then
|
||||||
if aZone.linkBroken then
|
if aZone.linkBroken then
|
||||||
-- try to relink
|
-- try to relink
|
||||||
cfxZones.initLink(aZone)
|
cfxZones.initLink(aZone)
|
||||||
|
else --if aZone.linkName then
|
||||||
|
-- always re-acquire linkedUnit via Unit.getByName()
|
||||||
|
-- this way we gloss over any replacements via spawns
|
||||||
|
aZone.linkedUnit = Unit.getByName(aZone.linkName)
|
||||||
end
|
end
|
||||||
|
|
||||||
if aZone.linkedUnit then
|
if aZone.linkedUnit then
|
||||||
local theUnit = aZone.linkedUnit
|
local theUnit = aZone.linkedUnit
|
||||||
-- has a link. is link existing?
|
-- has a link. is link existing?
|
||||||
@ -2323,16 +2333,24 @@ function cfxZones.updateMovingZones()
|
|||||||
end
|
end
|
||||||
cfxZones.offsetZone(aZone, dx, dy)
|
cfxZones.offsetZone(aZone, dx, dy)
|
||||||
else
|
else
|
||||||
-- we lost link
|
-- we lost link (track level)
|
||||||
aZone.linkBroken = true
|
aZone.linkBroken = true
|
||||||
aZone.linkedUnit = nil
|
aZone.linkedUnit = nil
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
-- we lost link (top level)
|
||||||
|
aZone.linkBroken = true
|
||||||
|
aZone.linkedUnit = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- this zone isn't linked
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cfxZones.initLink(theZone)
|
function cfxZones.initLink(theZone)
|
||||||
--trigger.action.outText("enter initlink for <" .. theZone.name .. ">", 30)
|
--trigger.action.outText("enter initlink for <" .. theZone.name .. ">")
|
||||||
|
--if true then return end
|
||||||
--trigger.action.outText("entry verbose check: <" .. theZone.name .. "> is verbose = " .. dcsCommon.bool2YesNo(theZone.verbose), 30)
|
--trigger.action.outText("entry verbose check: <" .. theZone.name .. "> is verbose = " .. dcsCommon.bool2YesNo(theZone.verbose), 30)
|
||||||
theZone.linkBroken = true
|
theZone.linkBroken = true
|
||||||
theZone.linkedUnit = nil
|
theZone.linkedUnit = nil
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cloneZones = {}
|
cloneZones = {}
|
||||||
cloneZones.version = "1.6.3"
|
cloneZones.version = "1.7.0"
|
||||||
cloneZones.verbose = false
|
cloneZones.verbose = false
|
||||||
cloneZones.requiredLibs = {
|
cloneZones.requiredLibs = {
|
||||||
"dcsCommon", -- always
|
"dcsCommon", -- always
|
||||||
@ -17,9 +17,14 @@ cloneZones.callbacks = {}
|
|||||||
cloneZones.unitXlate = {}
|
cloneZones.unitXlate = {}
|
||||||
cloneZones.groupXlate = {} -- used to translate original groupID to cloned. only holds last spawned group id
|
cloneZones.groupXlate = {} -- used to translate original groupID to cloned. only holds last spawned group id
|
||||||
cloneZones.uniqueCounter = 9200000 -- we start group numbering here
|
cloneZones.uniqueCounter = 9200000 -- we start group numbering here
|
||||||
|
cloneZones.lclUniqueCounter = 1 -- zone-local init value, can be config'dHeading
|
||||||
|
cloneZones.globalCounter = 1 -- module-global count
|
||||||
|
|
||||||
cloneZones.allClones = {} -- all clones spawned, regularly GC'd
|
cloneZones.allClones = {} -- all clones spawned, regularly GC'd
|
||||||
cloneZones.allCObjects = {} -- all clones objects
|
cloneZones.allCObjects = {} -- all clones objects
|
||||||
|
|
||||||
|
cloneZones.respawnOnGroupID = true
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
Clones Groups from ME mission data
|
Clones Groups from ME mission data
|
||||||
Copyright (c) 2022 by Christian Franz and cf/x AG
|
Copyright (c) 2022 by Christian Franz and cf/x AG
|
||||||
@ -75,6 +80,17 @@ cloneZones.allCObjects = {} -- all clones objects
|
|||||||
1.6.3 - removed verbosity bug with rndLoc
|
1.6.3 - removed verbosity bug with rndLoc
|
||||||
uniqueNameGroupData has provisions for naming scheme
|
uniqueNameGroupData has provisions for naming scheme
|
||||||
new uniqueNameStaticData() for naming scheme
|
new uniqueNameStaticData() for naming scheme
|
||||||
|
1.6.4 - uniqueCounter is now configurable via config zone
|
||||||
|
new lclUniqueCounter config, also added to persistence
|
||||||
|
new globalCount
|
||||||
|
1.7.0 - wildcard "*" for masterOwner
|
||||||
|
- identical attribute: makes identical ID and name for unit and group as template
|
||||||
|
- new sameIDUnitData()
|
||||||
|
- nameScheme attribute: allow parametric names
|
||||||
|
- <o>, <z>, <s> wildcards
|
||||||
|
- <uid>, <lcl>, <i>, <g> wildcards
|
||||||
|
- identical=true overrides nameScheme
|
||||||
|
- masterOwner "*" convenience shortcut
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -168,6 +184,8 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
|||||||
trigger.action.outText("+++clnZ: new cloner <" .. theZone.name ..">", 30)
|
trigger.action.outText("+++clnZ: new cloner <" .. theZone.name ..">", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
theZone.myUniqueCounter = cloneZones.lclUniqueCounter -- init local counter
|
||||||
|
|
||||||
local localZones = cloneZones.allGroupsInZoneByData(theZone)
|
local localZones = cloneZones.allGroupsInZoneByData(theZone)
|
||||||
local localObjects = cfxZones.allStaticsInZone(theZone, true) -- true = use DCS origin, not moved zone
|
local localObjects = cfxZones.allStaticsInZone(theZone, true) -- true = use DCS origin, not moved zone
|
||||||
if theZone.verbose then
|
if theZone.verbose then
|
||||||
@ -301,7 +319,14 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
|||||||
end
|
end
|
||||||
|
|
||||||
if cfxZones.hasProperty(theZone, "masterOwner") then
|
if cfxZones.hasProperty(theZone, "masterOwner") then
|
||||||
theZone.masterOwner = cfxZones.getStringFromZoneProperty(theZone, "masterOwner", "<none>")
|
theZone.masterOwner = cfxZones.getStringFromZoneProperty(theZone, "masterOwner", "*")
|
||||||
|
theZone.masterOwner = dcsCommon.trim(theZone.masterOwner)
|
||||||
|
if theZone.masterOwner == "*" then
|
||||||
|
theZone.masterOwner = theZone.name
|
||||||
|
if theZone.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: masterOwner for <" .. theZone.name .. "> successfully to to itself, currently owned by faction <" .. theZone.owner .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
theZone.turn = cfxZones.getNumberFromZoneProperty(theZone, "turn", 0)
|
theZone.turn = cfxZones.getNumberFromZoneProperty(theZone, "turn", 0)
|
||||||
@ -326,6 +351,20 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
|||||||
|
|
||||||
theZone.onRoad = cfxZones.getBoolFromZoneProperty(theZone, "onRoad", false)
|
theZone.onRoad = cfxZones.getBoolFromZoneProperty(theZone, "onRoad", false)
|
||||||
|
|
||||||
|
-- check for name scheme and / or identical
|
||||||
|
if cfxZones.hasProperty(theZone, "identical") then
|
||||||
|
theZone.identical = cfxZones.getBoolFromZoneProperty(theZone, "identical", false)
|
||||||
|
if theZone.identical == false then theZone.identical = nil end
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "nameScheme") then
|
||||||
|
theZone.nameScheme = cfxZones.getStringFromZoneProperty(theZone, "nameScheme", "<o>-<uid>") -- default to [<original name> "-" <uuid>]
|
||||||
|
end
|
||||||
|
|
||||||
|
if theZone.identical and theZone.nameScheme then
|
||||||
|
trigger.action.outText("+++clnZ: WARNING - clone zone <" .. theZone.name .. "> has both IDENTICAL and NAMESCHEME attributes. nameScheme is ignored.", 30)
|
||||||
|
theZone.nameScheme = nil
|
||||||
|
end
|
||||||
-- we end with clear plate
|
-- we end with clear plate
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -509,17 +548,97 @@ function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWayp
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function cloneZones.nameFromSchema(schema, inName, theZone, sourceName, i)
|
||||||
|
-- default schema (classic) is "<o>-<uid>"
|
||||||
|
local outName = schema
|
||||||
|
local iter = i
|
||||||
|
|
||||||
|
-- replace all occurences of <o> with original name
|
||||||
|
outName = outName:gsub("<o>", inName)
|
||||||
|
|
||||||
|
-- replace all occurences of <z> with zone name
|
||||||
|
outName = outName:gsub("<z>", theZone.name)
|
||||||
|
-- replace all occurences of <s> with source zone name
|
||||||
|
outName = outName:gsub("<s>", sourceName)
|
||||||
|
|
||||||
|
-- uid (uuid) with auto-increment
|
||||||
|
local pos = string.find(outName, "<uid>")
|
||||||
|
while (pos and pos > 0) do
|
||||||
|
local uid = tostring(dcsCommon.numberUUID())
|
||||||
|
outName = outName:gsub("<uid>", uid, 1) -- only first substitution
|
||||||
|
pos = string.find(outName, "<uid>")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- i (iter) with increment
|
||||||
|
pos = string.find(outName, "<i>")
|
||||||
|
while (pos and pos > 0) do
|
||||||
|
local uid = tostring(iter)
|
||||||
|
outName = outName:gsub("<i>", uid, 1) -- only first substitution
|
||||||
|
iter = iter + 1
|
||||||
|
pos = string.find(outName, "<i>")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- lcl local (zonal) count with increment
|
||||||
|
pos = string.find(outName, "<lcl>")
|
||||||
|
while (pos and pos > 0) do
|
||||||
|
local uid = tostring(theZone.myUniqueCounter)
|
||||||
|
outName = outName:gsub("<lcl>", uid, 1) -- only first substitution
|
||||||
|
theZone.myUniqueCounter = theZone.myUniqueCounter + 1
|
||||||
|
pos = string.find(outName, "<lcl>")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- g global (module) count with increment
|
||||||
|
pos = string.find(outName, "<g>")
|
||||||
|
while (pos and pos > 0) do
|
||||||
|
local uid = tostring(cloneZones.globalCounter)
|
||||||
|
outName = outName:gsub("<g>", uid, 1) -- only first substitution
|
||||||
|
cloneZones.globalCounter = cloneZones.globalCounter + 1
|
||||||
|
pos = string.find(outName, "<g>")
|
||||||
|
end
|
||||||
|
|
||||||
|
--if theZone.verbose then
|
||||||
|
-- trigger.action.outText("+++cln: schema [" .. schema .. "] for unit <" .. inName .. "> in zone <" .. theZone.name .. "> returns <" .. outName .. ">, iter = " .. iter, 30)
|
||||||
|
--end
|
||||||
|
return outName, iter
|
||||||
|
end
|
||||||
|
|
||||||
function cloneZones.uniqueID()
|
function cloneZones.uniqueID()
|
||||||
local uid = cloneZones.uniqueCounter
|
local uid = cloneZones.uniqueCounter
|
||||||
cloneZones.uniqueCounter = cloneZones.uniqueCounter + 1
|
cloneZones.uniqueCounter = cloneZones.uniqueCounter + 1
|
||||||
return uid
|
return uid
|
||||||
end
|
end
|
||||||
|
|
||||||
function cloneZones.uniqueNameGroupData(theData, theCloneZone)
|
function cloneZones.uniqueNameGroupData(theData, theCloneZone, sourceName)
|
||||||
|
if not sourceName then sourceName = theCloneZone.name end
|
||||||
theData.name = dcsCommon.uuid(theData.name)
|
theData.name = dcsCommon.uuid(theData.name)
|
||||||
local units = theData.units
|
local units = theData.units
|
||||||
|
local iterCount = 1
|
||||||
|
local newName = "none"
|
||||||
|
local allNames = {} -- enforce unique names inside group
|
||||||
for idx, aUnit in pairs(units) do
|
for idx, aUnit in pairs(units) do
|
||||||
if theCloneZone and theCloneZone.namingScheme then
|
if theCloneZone and theCloneZone.nameScheme then
|
||||||
|
local schema = theCloneZone.nameScheme
|
||||||
|
newName, iterCount = cloneZones.nameFromSchema(schema, aUnit.name, theCloneZone, sourceName, iterCount)
|
||||||
|
|
||||||
|
-- make sure that this name is has not been generated yet
|
||||||
|
-- inside the same group
|
||||||
|
local hasChanged = false
|
||||||
|
local schemeName = newName
|
||||||
|
while dcsCommon.arrayContainsString(allNames, newName) do
|
||||||
|
newName = newName .. "x"
|
||||||
|
hasChanged = true
|
||||||
|
end
|
||||||
|
if theCloneZone.verbose and hasChanged then
|
||||||
|
trigger.action.outText("cnlz: nameScheme [" .. theCloneZone.nameScheme .. "] failsafe: changed <" .. schemeName .. "> to <" .. newName .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(allNames, newName)
|
||||||
|
|
||||||
|
if theCloneZone.verbose then
|
||||||
|
trigger.action.outText("clnZ: zone <" .. theCloneZone.name .. "> unit schema <" .. schema .. ">: <" .. aUnit.name .. "> --> <" .. newName .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
aUnit.name = newName -- dcsCommon.uuid(aUnit.name)
|
||||||
else
|
else
|
||||||
-- default naming scheme: <name>-<uuid>
|
-- default naming scheme: <name>-<uuid>
|
||||||
aUnit.name = dcsCommon.uuid(aUnit.name)
|
aUnit.name = dcsCommon.uuid(aUnit.name)
|
||||||
@ -527,9 +646,25 @@ function cloneZones.uniqueNameGroupData(theData, theCloneZone)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cloneZones.uniqueNameStaticData(theData, spawnZone)
|
function cloneZones.uniqueNameStaticData(theData, theCloneZone, sourcename)
|
||||||
theData.name = dcsCommon.uuid(theData.name)
|
if not sourceName then sourceName = theCloneZone.name end
|
||||||
|
|
||||||
|
-- WARNING: unlike GroupData enters with UNIT data
|
||||||
|
local iterCount = 1
|
||||||
|
local newName = "none"
|
||||||
|
if theCloneZone and theCloneZone.nameScheme then
|
||||||
|
local schema = theCloneZone.nameScheme
|
||||||
|
newName, iterCount = cloneZones.nameFromSchema(schema, theData.name, theCloneZone, sourceName, iterCount)
|
||||||
|
|
||||||
|
if theCloneZone.verbose then
|
||||||
|
trigger.action.outText("clnZ: zone <" .. theCloneZone.name .. "> static schema <" .. schema .. ">: <" .. theData.name .. "> --> <" .. newName .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
theData.name = newName -- dcsCommon.uuid(theData.name)
|
||||||
|
else
|
||||||
|
-- default naming scheme: <name>-<uuid>
|
||||||
|
theData.name = dcsCommon.uuid(theData.name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cloneZones.uniqueIDGroupData(theData)
|
function cloneZones.uniqueIDGroupData(theData)
|
||||||
@ -547,6 +682,16 @@ function cloneZones.uniqueIDUnitData(theData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cloneZones.sameIDUnitData(theData)
|
||||||
|
if not theData then return end
|
||||||
|
if not theData.units then return end
|
||||||
|
local units = theData.units
|
||||||
|
for idx, aUnit in pairs(units) do
|
||||||
|
aUnit.CZorigID = aUnit.unitId
|
||||||
|
aUnit.CZTargetID = aUnit.unitId
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function cloneZones.resolveOwnership(spawnZone, ctry)
|
function cloneZones.resolveOwnership(spawnZone, ctry)
|
||||||
if not spawnZone.masterOwner then return ctry end
|
if not spawnZone.masterOwner then return ctry end
|
||||||
local masterZone = cfxZones.getZoneByName(spawnZone.masterOwner)
|
local masterZone = cfxZones.getZoneByName(spawnZone.masterOwner)
|
||||||
@ -750,14 +895,14 @@ end
|
|||||||
|
|
||||||
function cloneZones.handoffTracking(theGroup, theZone)
|
function cloneZones.handoffTracking(theGroup, theZone)
|
||||||
if not groupTracker then
|
if not groupTracker then
|
||||||
trigger.action.outText("+++clne: <" .. theZone.name .. "> trackWith requires groupTracker module", 30)
|
trigger.action.outText("+++clnZ: <" .. theZone.name .. "> trackWith requires groupTracker module", 30)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local trackerName = theZone.trackWith
|
local trackerName = theZone.trackWith
|
||||||
--if trackerName == "*" then trackerName = theZone.name end
|
--if trackerName == "*" then trackerName = theZone.name end
|
||||||
-- now assemble a list of all trackers
|
-- now assemble a list of all trackers
|
||||||
if cloneZones.verbose or theZone.verbose then
|
if cloneZones.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++clne: clone pass-off: " .. trackerName, 30)
|
trigger.action.outText("+++clnZ: clone pass-off: " .. trackerName, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
local trackerNames = {}
|
local trackerNames = {}
|
||||||
@ -771,22 +916,127 @@ function cloneZones.handoffTracking(theGroup, theZone)
|
|||||||
if theName == "*" then theName = theZone.name end
|
if theName == "*" then theName = theZone.name end
|
||||||
local theTracker = groupTracker.getTrackerByName(theName)
|
local theTracker = groupTracker.getTrackerByName(theName)
|
||||||
if not theTracker then
|
if not theTracker then
|
||||||
trigger.action.outText("+++clne: <" .. theZone.name .. ">: cannot find tracker named <".. theName .. ">", 30)
|
trigger.action.outText("+++clnZ: <" .. theZone.name .. ">: cannot find tracker named <".. theName .. ">", 30)
|
||||||
else
|
else
|
||||||
groupTracker.addGroupToTracker(theGroup, theTracker)
|
groupTracker.addGroupToTracker(theGroup, theTracker)
|
||||||
if cloneZones.verbose or theZone.verbose then
|
if cloneZones.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++clne: added " .. theGroup:getName() .. " to tracker " .. theName, 30)
|
trigger.action.outText("+++clnZ: added " .. theGroup:getName() .. " to tracker " .. theName, 30)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cloneZones.validateSpawnUnitData(aUnit, theZone, unitNames)
|
||||||
|
-- entry with unit data construct
|
||||||
|
-- also used for static objects!
|
||||||
|
if not aUnit then return end
|
||||||
|
if not theZone then return end
|
||||||
|
-- we only verify replacement if identical or name sheme attribute
|
||||||
|
if not (theZone.identical or theZone.nameScheme) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if unitNames[aUnit.name] then
|
||||||
|
trigger.action.outText("clnZ: <" .. theZone.name .. "> validation warning - Unit/Object name <" .. aUnit.name .. ">: duplicate name within spawn cycle, will be repaced", 30)
|
||||||
|
else
|
||||||
|
unitNames[aUnit.name] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local theUnit = Unit.getByName(aUnit.name)
|
||||||
|
if theUnit and Unit.isExist(theUnit) then
|
||||||
|
if cloneZones.verbose or theZone.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: cloner <" .. theZone.name .. "> will replace existing UNIT <" .. aUnit.name .. ">", 30)
|
||||||
|
end
|
||||||
|
-- since we are about to replace a unit, we also steal the ID
|
||||||
|
local stolenID = theUnit:getID()
|
||||||
|
aUnit.unitId = stolenID
|
||||||
|
else
|
||||||
|
-- now check if we are about to grab an MX data ID
|
||||||
|
-- and ned to steal that
|
||||||
|
local stolenID = cfxMX.unitIDbyName[aUnit.name]
|
||||||
|
if stolenID then
|
||||||
|
if cloneZones.verbose or theZone.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: cloner <" .. theZone.name .. "> will replace MX UNIT ID <" .. aUnit.name .. "> by appropriating ID <" .. stolenID .. ">", 30)
|
||||||
|
end
|
||||||
|
aUnit.unitId = stolenID
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- check against static objects.
|
||||||
|
local theStatic = StaticObject.getByName(aUnit.name)
|
||||||
|
if theStatic and StaticObject.isExist(theStatic) then
|
||||||
|
trigger.action.outText("+++clnZ: cloner <" .. theZone.name .. "> will replace existing STATIC <" .. aUnit.name .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.validateSpawnGroupData(theData, theZone, groupNames, unitNames)
|
||||||
|
-- entry with group construct
|
||||||
|
if not theData then return end
|
||||||
|
if not theZone then return end
|
||||||
|
-- we only verify replacement if identical or name sheme attribute
|
||||||
|
if not (theZone.identical or theZone.nameScheme) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if groupNames[theData.name] then
|
||||||
|
trigger.action.outText("clnZ: <" .. theZone.name .. "> validation warning - group name <" .. theData.name .. ">: duplicate within spawn, previous spawn will be removed", 30)
|
||||||
|
else
|
||||||
|
groupNames[theData.name] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
local theGroup = Group.getByName(theData.name)
|
||||||
|
if theGroup and Group.isExist(theGroup) and theGroup:getSize() > 0 then
|
||||||
|
trigger.action.outText("+++clnZ: cloner <" .. theZone.name .. "> will replace existing GROUP <" .. theData.name .. ">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not theData.units then return end
|
||||||
|
local units = theData.units
|
||||||
|
for idx, aUnit in pairs(units) do
|
||||||
|
cloneZones.validateSpawnUnitData(aUnit, theZone, unitNames)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.forcedRespawn(args)
|
||||||
|
local theData = args[1]
|
||||||
|
local spawnedGroups = args[2]
|
||||||
|
local pos = args[3]
|
||||||
|
local verbose = args[4]
|
||||||
|
local rawData = dcsCommon.clone(theData)
|
||||||
|
if verbose then
|
||||||
|
trigger.action.outText("clnZ: enter forced respawn of <" .. theData.name .. "> to meet ID " .. theData.CZTargetID .. " (currently set for <" .. theData.groupId .. ">)", 30)
|
||||||
|
end
|
||||||
|
-- we now try to spawn again, with hopes of receiving the
|
||||||
|
-- correct id
|
||||||
|
local theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
||||||
|
|
||||||
|
-- make sure that this time the id matches
|
||||||
|
local newGroupID = theGroup:getID()
|
||||||
|
if newGroupID == theData.CZTargetID then
|
||||||
|
if verbose then
|
||||||
|
trigger.action.outText("GOOD REPLACEMENT new ID <" .. newGroupID .. "> matches target <" .. theData.CZTargetID .. "> for <" .. theData.name .. ">", 30)
|
||||||
|
-- we can now remove the former group
|
||||||
|
-- and replace it with the new one
|
||||||
|
trigger.action.outText("will replace table entry at <" .. pos .. "> with new group", 30)
|
||||||
|
end
|
||||||
|
spawnedGroups[pos] = theGroup
|
||||||
|
else
|
||||||
|
-- we need to try again in one second
|
||||||
|
if verbose then
|
||||||
|
trigger.action.outText("FAIL: new ID <" .. newGroupID .. "> does not match target <" .. theData.CZTargetID .. "> for <" .. theData.name .. ">. Will re-try in 1s", 30)
|
||||||
|
end
|
||||||
|
spawnedGroups[pos] = theGroup -- replace so we don't fail checks
|
||||||
|
timer.scheduleFunction(cloneZones.forcedRespawn, args, timer.getTime() + 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||||
if cloneZones.verbose or spawnZone.verbose then
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
trigger.action.outText("+++clnZ: spawning with template <" .. theZone.name .. "> for spawner <" .. spawnZone.name .. ">", 30)
|
trigger.action.outText("+++clnZ: spawning with template <" .. theZone.name .. "> for spawner <" .. spawnZone.name .. ">", 30)
|
||||||
end
|
end
|
||||||
-- theZone is the cloner with the template (source)
|
-- theZone is the cloner with the TEMPLATE (source)
|
||||||
-- spawnZone is the spawner with settings (target location)
|
-- spawnZone is the spawner with SETTINGS and DESTINATION (target location)
|
||||||
local newCenter = cfxZones.getPoint(spawnZone) -- includes zone following updates
|
local newCenter = cfxZones.getPoint(spawnZone) -- includes zone following updates
|
||||||
local oCenter = cfxZones.getDCSOrigin(theZone) -- get original coords on map for cloning offsets
|
local oCenter = cfxZones.getDCSOrigin(theZone) -- get original coords on map for cloning offsets
|
||||||
-- calculate zoneDelta, is added to all vectors
|
-- calculate zoneDelta, is added to all vectors
|
||||||
@ -811,8 +1061,14 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
rawData.CZorigName = rawData.name -- save original group name
|
rawData.CZorigName = rawData.name -- save original group name
|
||||||
local origID = rawData.groupId -- save original group ID
|
local origID = rawData.groupId -- save original group ID
|
||||||
rawData.CZorigID = origID
|
rawData.CZorigID = origID
|
||||||
|
if spawnZone.identical then
|
||||||
|
cloneZones.sameIDUnitData(rawData) -- set up CZTargetID for units to be same as in template
|
||||||
|
else
|
||||||
|
-- only assign new ids when 'identical' flag is not active
|
||||||
cloneZones.uniqueIDGroupData(rawData) -- assign unique ID we know
|
cloneZones.uniqueIDGroupData(rawData) -- assign unique ID we know
|
||||||
cloneZones.uniqueIDUnitData(rawData) -- assign unique ID for units -- saves old unitId as CZorigID
|
cloneZones.uniqueIDUnitData(rawData) -- assign unique ID for units -- saves old unitId as CZorigID
|
||||||
|
end
|
||||||
|
|
||||||
rawData.CZTargetID = rawData.groupId -- save
|
rawData.CZTargetID = rawData.groupId -- save
|
||||||
if rawData.name ~= aGroupName then
|
if rawData.name ~= aGroupName then
|
||||||
trigger.action.outText("Clone: FAILED name check", 30)
|
trigger.action.outText("Clone: FAILED name check", 30)
|
||||||
@ -823,7 +1079,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
|
|
||||||
-- update their position if not spawning to exact same location
|
-- update their position if not spawning to exact same location
|
||||||
if cloneZones.verbose or theZone.verbose or spawnZone.verbose then
|
if cloneZones.verbose or theZone.verbose or spawnZone.verbose then
|
||||||
trigger.action.outText("+++clnZ: tmpl delta x = <" .. math.floor(zoneDelta.x) .. ">, y = <" .. math.floor(zoneDelta.z) .. "> for tmpl <" .. theZone.name .. "> to cloner <" .. spawnZone.name .. ">", 30)
|
--trigger.action.outText("+++clnZ: tmpl delta x = <" .. math.floor(zoneDelta.x) .. ">, y = <" .. math.floor(zoneDelta.z) .. "> for tmpl <" .. theZone.name .. "> to cloner <" .. spawnZone.name .. ">", 30)
|
||||||
end
|
end
|
||||||
-- update routes when not spawning same location
|
-- update routes when not spawning same location
|
||||||
cloneZones.updateLocationsInGroupData(rawData, zoneDelta, spawnZone.moveRoute, rotCenter, spawnZone.turn / 57.2958 +
|
cloneZones.updateLocationsInGroupData(rawData, zoneDelta, spawnZone.moveRoute, rotCenter, spawnZone.turn / 57.2958 +
|
||||||
@ -925,8 +1181,11 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
-- apply turning
|
-- apply turning
|
||||||
dcsCommon.rotateGroupData(rawData, spawnZone.turn + 57.2958 *dHeading, newCenter.x, newCenter.z)
|
dcsCommon.rotateGroupData(rawData, spawnZone.turn + 57.2958 *dHeading, newCenter.x, newCenter.z)
|
||||||
|
|
||||||
-- make sure unit and group names are unique
|
-- make sure unit and group names are unique unless
|
||||||
cloneZones.uniqueNameGroupData(rawData, spawnZone)
|
-- we have identical active
|
||||||
|
if not spawnZone.identical then
|
||||||
|
cloneZones.uniqueNameGroupData(rawData, spawnZone, theZone.name)
|
||||||
|
end
|
||||||
|
|
||||||
-- see what country we spawn for
|
-- see what country we spawn for
|
||||||
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
||||||
@ -939,6 +1198,8 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
cloneZones.resolveReferences(theZone, dataToSpawn)
|
cloneZones.resolveReferences(theZone, dataToSpawn)
|
||||||
|
|
||||||
-- now spawn all raw data
|
-- now spawn all raw data
|
||||||
|
local groupCollector = {} -- to detect cross-group conflicts
|
||||||
|
local unitCollector = {} -- to detect cross-group conflicts
|
||||||
for idx, rawData in pairs (dataToSpawn) do
|
for idx, rawData in pairs (dataToSpawn) do
|
||||||
-- now spawn and save to clones
|
-- now spawn and save to clones
|
||||||
-- first norm and clone data for later save
|
-- first norm and clone data for later save
|
||||||
@ -958,6 +1219,12 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
local theData = dcsCommon.clone(rawData)
|
local theData = dcsCommon.clone(rawData)
|
||||||
cloneZones.allClones[rawData.name] = theData
|
cloneZones.allClones[rawData.name] = theData
|
||||||
|
|
||||||
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
|
-- optional spawn validation report before we spawn
|
||||||
|
cloneZones.validateSpawnGroupData(rawData, spawnZone, groupCollector, unitCollector)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- SPAWN NOW!!!!
|
||||||
local theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
local theGroup = coalition.addGroup(rawData.CZctry, rawData.CZtheCat, rawData)
|
||||||
table.insert(spawnedGroups, theGroup)
|
table.insert(spawnedGroups, theGroup)
|
||||||
|
|
||||||
@ -977,9 +1244,17 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
local uID = tonumber(gUnit:getID())
|
local uID = tonumber(gUnit:getID())
|
||||||
if uID == aUnit.CZTargetID then
|
if uID == aUnit.CZTargetID then
|
||||||
-- all good
|
-- all good
|
||||||
|
else
|
||||||
|
-- mismatch. may happen when namingScheme causes
|
||||||
|
-- unit to be reallocated to existing unit.
|
||||||
|
if spawnZone.verbose then
|
||||||
|
if spawnZone.nameScheme then
|
||||||
|
trigger.action.outText("clnZ: nameScheme - unit <" .. uName .. ">: ÎD mapped to existing: " .. uID , 30)
|
||||||
else
|
else
|
||||||
trigger.action.outText("clnZ: post-clone verification failed for unit <" .. uName .. ">: ÎD mismatch: " .. uID .. " -- " .. aUnit.CZTargetID, 30)
|
trigger.action.outText("clnZ: post-clone verification failed for unit <" .. uName .. ">: ÎD mismatch: " .. uID .. " -- " .. aUnit.CZTargetID, 30)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
cloneZones.unitXlate[aUnit.CZorigID] = uID
|
cloneZones.unitXlate[aUnit.CZorigID] = uID
|
||||||
else
|
else
|
||||||
trigger.action.outText("clnZ: post-clone verifiaction failed for unit <" .. uName .. ">: not found", 30)
|
trigger.action.outText("clnZ: post-clone verifiaction failed for unit <" .. uName .. ">: not found", 30)
|
||||||
@ -987,11 +1262,28 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- check if our assigned ID matches the handed out by
|
-- check if our assigned ID matches the handed out by
|
||||||
-- DCS
|
-- DCS. Mismatches can happen, and are only noted
|
||||||
if newGroupID == rawData.CZTargetID then
|
if newGroupID == rawData.CZTargetID then
|
||||||
-- we are good
|
-- we are good
|
||||||
else
|
else
|
||||||
trigger.action.outText("clnZ: MISMATCH " .. rawData.name .. " target ID " .. rawData.CZTargetID .. " does not match " .. newGroupID, 30)
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
|
trigger.action.outText("clnZ: Note: GROUP ID spawn changed for <" .. rawData.name .. ">: target ID " .. rawData.CZTargetID .. " (target) returns " .. newGroupID .. " (actual) in <" .. spawnZone.name .. ">", 30)
|
||||||
|
--trigger.action.outText("Note: theData.groupId is <" .. theData.groupId .. ">", 30)
|
||||||
|
--if spawnZone.identical then
|
||||||
|
-- trigger.action.outText("(Identical = true detected for this zone)", 30)
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
|
||||||
|
if cloneZones.respawnOnGroupID then
|
||||||
|
-- remove last entry in table, will be added later
|
||||||
|
local pos = #spawnedGroups
|
||||||
|
|
||||||
|
timer.scheduleFunction(cloneZones.forcedRespawn, {theData, spawnedGroups, pos, spawnZone.verbose}, timer.getTime() + 2) -- initial gap: 2 seconds for DCS to sort itself out
|
||||||
|
else
|
||||||
|
-- we note it in the spawn data for the group so
|
||||||
|
-- persistence works fine
|
||||||
|
theData.groupId = newGroupID
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
cloneZones.invokeCallbacks(spawnZone, "did spawn group", theGroup)
|
cloneZones.invokeCallbacks(spawnZone, "did spawn group", theGroup)
|
||||||
@ -1019,10 +1311,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
|
|
||||||
-- randomize if enabled
|
-- randomize if enabled
|
||||||
if spawnZone.rndLoc then
|
if spawnZone.rndLoc then
|
||||||
--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
|
local loc, dx, dy = cfxZones.createRandomPointInZone(spawnZone) -- also supports polygonal zones
|
||||||
rawData.x = rawData.x + dx
|
rawData.x = rawData.x + dx
|
||||||
rawData.y = rawData.y + dy
|
rawData.y = rawData.y + dy
|
||||||
@ -1044,10 +1333,12 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
-- apply turning
|
-- apply turning
|
||||||
dcsCommon.rotateUnitData(rawData, spawnZone.turn + 57.2958 * dHeading, newCenter.x, newCenter.z)
|
dcsCommon.rotateUnitData(rawData, spawnZone.turn + 57.2958 * dHeading, newCenter.x, newCenter.z)
|
||||||
|
|
||||||
|
if not spawnZone.identical then
|
||||||
-- make sure static name is unique and remember original
|
-- make sure static name is unique and remember original
|
||||||
cloneZones.uniqueNameStaticData(rawData, spawnZone)
|
cloneZones.uniqueNameStaticData(rawData, spawnZone, theZone.name)
|
||||||
--rawData.name = dcsCommon.uuid(rawData.name)
|
--rawData.name = dcsCommon.uuid(rawData.name)
|
||||||
rawData.unitId = cloneZones.uniqueID()
|
rawData.unitId = cloneZones.uniqueID()
|
||||||
|
end
|
||||||
rawData.CZTargetID = rawData.unitId
|
rawData.CZTargetID = rawData.unitId
|
||||||
|
|
||||||
-- see what country we spawn for
|
-- see what country we spawn for
|
||||||
@ -1075,6 +1366,11 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
local theData = dcsCommon.clone(rawData)
|
local theData = dcsCommon.clone(rawData)
|
||||||
cloneZones.allCObjects[rawData.name] = theData
|
cloneZones.allCObjects[rawData.name] = theData
|
||||||
|
|
||||||
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
|
-- optional spawn validation report before we spawn
|
||||||
|
cloneZones.validateSpawnUnitData(rawData, spawnZone, unitCollector)
|
||||||
|
end
|
||||||
|
|
||||||
local theStatic = coalition.addStaticObject(ctry, rawData)
|
local theStatic = coalition.addStaticObject(ctry, rawData)
|
||||||
local newStaticID = tonumber(theStatic:getID())
|
local newStaticID = tonumber(theStatic:getID())
|
||||||
table.insert(spawnedStatics, theStatic)
|
table.insert(spawnedStatics, theStatic)
|
||||||
@ -1082,8 +1378,10 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
-- statics
|
-- statics
|
||||||
if newStaticID == rawData.CZTargetID then
|
if newStaticID == rawData.CZTargetID then
|
||||||
else
|
else
|
||||||
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
trigger.action.outText("Static ID mismatch: " .. newStaticID .. " vs (target) " .. rawData.CZTargetID .. " for " .. rawData.name, 30)
|
trigger.action.outText("Static ID mismatch: " .. newStaticID .. " vs (target) " .. rawData.CZTargetID .. " for " .. rawData.name, 30)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
cloneZones.unitXlate[origID] = newStaticID -- same as units
|
cloneZones.unitXlate[origID] = newStaticID -- same as units
|
||||||
|
|
||||||
cloneZones.invokeCallbacks(theZone, "did spawn static", theStatic)
|
cloneZones.invokeCallbacks(theZone, "did spawn static", theStatic)
|
||||||
@ -1096,11 +1394,11 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
|||||||
if cfxCargoManager then
|
if cfxCargoManager then
|
||||||
cfxCargoManager.addCargo(theStatic)
|
cfxCargoManager.addCargo(theStatic)
|
||||||
if cloneZones.verbose or spawnZone.verbose then
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
trigger.action.outText("+++clne: added CARGO " .. theStatic:getName() .. " to cargo manager ", 30)
|
trigger.action.outText("+++clnZ: added CARGO " .. theStatic:getName() .. " to cargo manager ", 30)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if cloneZones.verbose or spawnZone.verbose then
|
if cloneZones.verbose or spawnZone.verbose then
|
||||||
trigger.action.outText("+++clne: CARGO " .. theStatic:getName() .. " detected, not managerd", 30)
|
trigger.action.outText("+++clnZ: CARGO " .. theStatic:getName() .. " detected, not managerd", 30)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1298,7 +1596,7 @@ function cloneZones.doOnStart()
|
|||||||
if theZone.onStart then
|
if theZone.onStart then
|
||||||
if theZone.isStarted then
|
if theZone.isStarted then
|
||||||
if cloneZones.verbose or theZone.verbose then
|
if cloneZones.verbose or theZone.verbose then
|
||||||
trigger.action.outText("+++clnz: onStart pre-empted for <" .. theZone.name .. "> by persistence", 30)
|
trigger.action.outText("+++clnZ: onStart pre-empted for <" .. theZone.name .. "> by persistence", 30)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if cloneZones.verbose or theZone.verbose then
|
if cloneZones.verbose or theZone.verbose then
|
||||||
@ -1418,6 +1716,8 @@ function cloneZones.saveData()
|
|||||||
for idx, theCloner in pairs(cloneZones.cloners) do
|
for idx, theCloner in pairs(cloneZones.cloners) do
|
||||||
local cData = {}
|
local cData = {}
|
||||||
local cName = theCloner.name
|
local cName = theCloner.name
|
||||||
|
cData.myUniqueCounter = theCloner.myUniqueCounter
|
||||||
|
|
||||||
-- mySpawns: all groups i'm curently observing for empty!
|
-- mySpawns: all groups i'm curently observing for empty!
|
||||||
-- myStatics: dto for objects
|
-- myStatics: dto for objects
|
||||||
local mySpawns = {}
|
local mySpawns = {}
|
||||||
@ -1440,11 +1740,13 @@ function cloneZones.saveData()
|
|||||||
-- save globals
|
-- save globals
|
||||||
theData.cuid = cloneZones.uniqueCounter -- replace whatever is larger
|
theData.cuid = cloneZones.uniqueCounter -- replace whatever is larger
|
||||||
theData.uuid = dcsCommon.simpleUUID -- replace whatever is larger
|
theData.uuid = dcsCommon.simpleUUID -- replace whatever is larger
|
||||||
|
theData.globalCount = cloneZones.globalCount
|
||||||
|
|
||||||
-- save to struct and pass back
|
-- save to struct and pass back
|
||||||
theData.clones = allCloneData
|
theData.clones = allCloneData
|
||||||
theData.objects = allSOData
|
theData.objects = allSOData
|
||||||
theData.cloneZones = cloners
|
theData.cloneZones = cloners
|
||||||
|
|
||||||
return theData
|
return theData
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1503,6 +1805,11 @@ function cloneZones.loadData()
|
|||||||
local theCloner = cloneZones.getCloneZoneByName(cName)
|
local theCloner = cloneZones.getCloneZoneByName(cName)
|
||||||
if theCloner then
|
if theCloner then
|
||||||
theCloner.isStarted = true -- ALWAYS TRUE WHEN WE COME HERE! cData.isStarted
|
theCloner.isStarted = true -- ALWAYS TRUE WHEN WE COME HERE! cData.isStarted
|
||||||
|
-- init myUniqueCounter if it exists
|
||||||
|
if cData.myUniqueCounter then
|
||||||
|
theCloner.myUniqueCounter = cData.myUniqueCounter
|
||||||
|
end
|
||||||
|
|
||||||
local mySpawns = {}
|
local mySpawns = {}
|
||||||
for idx, aName in pairs(cData.mySpawns) do
|
for idx, aName in pairs(cData.mySpawns) do
|
||||||
local theGroup = Group.getByName(aName)
|
local theGroup = Group.getByName(aName)
|
||||||
@ -1536,7 +1843,9 @@ function cloneZones.loadData()
|
|||||||
if theData.uuiD and theData.uuid > dcsCommon.simpleUUID then
|
if theData.uuiD and theData.uuid > dcsCommon.simpleUUID then
|
||||||
dcsCommon.simpleUUID = theData.uuid
|
dcsCommon.simpleUUID = theData.uuid
|
||||||
end
|
end
|
||||||
|
if theData.globalCount and theData.globalCount > cloneZones.globalCount then
|
||||||
|
cloneZones.globalCount = theData.globalCount
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -1551,6 +1860,18 @@ function cloneZones.readConfigZone()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "uniqueCount") then
|
||||||
|
cloneZones.uniqueCounter = cfxZones.getNumberFromZoneProperty(theZone, "uniqueCount", cloneZone.uniqueCounter)
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "localCount") then
|
||||||
|
cloneZones.lclUniqueCounter = cfxZones.getNumberFromZoneProperty(theZone, "localCount", cloneZone.lclUniqueCounter)
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "globalCount") then
|
||||||
|
cloneZones.globalCounter = cfxZones.getNumberFromZoneProperty(theZone, "globalCount", cloneZone.globalCounter)
|
||||||
|
end
|
||||||
|
|
||||||
cloneZones.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
cloneZones.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||||
|
|
||||||
if cloneZones.verbose then
|
if cloneZones.verbose then
|
||||||
@ -1622,4 +1943,9 @@ end
|
|||||||
- AFAC
|
- AFAC
|
||||||
- FAC Assign group
|
- FAC Assign group
|
||||||
- set freq for unit
|
- set freq for unit
|
||||||
|
|
||||||
|
-- fixedName: immutable name, no safe renaming. always use ID and name without changing it. very special use case.
|
||||||
|
nameTest - optional safety / debug feature that will name-test each unit that is about to be spawned for replacement. Maybe auto turn on when verbose is set?
|
||||||
|
identical - make a clone of template and do not touch name nor id. will fully replace
|
||||||
|
make example where transport can be different plane types but have same name
|
||||||
--]]--
|
--]]--
|
||||||
@ -691,6 +691,31 @@ dcsCommon.version = "2.8.0"
|
|||||||
end
|
end
|
||||||
|
|
||||||
function dcsCommon.bearingFromAtoB(A, B) -- coords in x, z
|
function dcsCommon.bearingFromAtoB(A, B) -- coords in x, z
|
||||||
|
if not A then
|
||||||
|
trigger.action.outText("WARNING: no 'A' in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not B then
|
||||||
|
trigger.action.outText("WARNING: no 'A' in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not A.x then
|
||||||
|
trigger.action.outText("WARNING: no 'A.x' (type A =<" .. type(A) .. ">)in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not A.y then
|
||||||
|
trigger.action.outText("WARNING: no 'A.x' (type A =<" .. type(A) .. ">)in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not B.x then
|
||||||
|
trigger.action.outText("WARNING: no 'B.x' (type B =<" .. type(B) .. ">)in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
if not B.y then
|
||||||
|
trigger.action.outText("WARNING: no 'B.y' (type B =<" .. type(B) .. ">)in bearingFromAtoB", 30)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
dx = B.x - A.x
|
dx = B.x - A.x
|
||||||
dz = B.z - A.z
|
dz = B.z - A.z
|
||||||
bearing = math.atan2(dz, dx) -- in radiants
|
bearing = math.atan2(dz, dx) -- in radiants
|
||||||
|
|||||||
@ -32,7 +32,7 @@ function smr.restartMission()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- main update loop, checked once per secon
|
-- main update loop, checked once per second
|
||||||
local lTime = DCS.getModelTime()
|
local lTime = DCS.getModelTime()
|
||||||
function smr.onSimulationFrame()
|
function smr.onSimulationFrame()
|
||||||
if lTime + 1 < DCS.getModelTime() then
|
if lTime + 1 < DCS.getModelTime() then
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user