mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 0.97
Clone Zones MX delayFlags Attack of the CloneZ miz
This commit is contained in:
parent
9162ea3acf
commit
5ae7f36482
Binary file not shown.
@ -278,7 +278,9 @@ end
|
|||||||
function rndFlags.startCycle()
|
function rndFlags.startCycle()
|
||||||
for idx, theZone in pairs(rndFlags.rndGen) do
|
for idx, theZone in pairs(rndFlags.rndGen) do
|
||||||
if theZone.onStart then
|
if theZone.onStart then
|
||||||
trigger.action.outText("+++RND: starting " .. theZone.name, 30)
|
if rndFlags.verbose then
|
||||||
|
trigger.action.outText("+++RND: starting " .. theZone.name, 30)
|
||||||
|
end
|
||||||
rndFlags.fire(theZone)
|
rndFlags.fire(theZone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
81
modules/cfxMX.lua
Normal file
81
modules/cfxMX.lua
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
cfxMX = {}
|
||||||
|
cfxMX.version = "1.0.0"
|
||||||
|
--[[--
|
||||||
|
Mission data decoder. Access to ME-built mission structures
|
||||||
|
|
||||||
|
Copyright (c) 2022 by Christian Franz and cf/x AG
|
||||||
|
|
||||||
|
Version History
|
||||||
|
1.0.0 - initial version
|
||||||
|
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
function cfxMX.getGroupFromDCSbyName(aName, fetchOriginal)
|
||||||
|
if not fetchOriginal then fetchOriginal = false end
|
||||||
|
-- fetch the group description for goup named aName (if exists)
|
||||||
|
-- returned structure must be parsed for useful information
|
||||||
|
-- returns data, category, countyID and coalitionID
|
||||||
|
-- unless fetchOriginal is true, creates a deep clone of
|
||||||
|
-- group data structure
|
||||||
|
|
||||||
|
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
|
||||||
|
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"
|
||||||
|
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
|
||||||
|
if group_data.name == aName then
|
||||||
|
local theGroup = group_data
|
||||||
|
-- usually we return a copy of this
|
||||||
|
if not fetchOriginal then
|
||||||
|
theGroup = dcsCommon.clone(group_data)
|
||||||
|
end
|
||||||
|
return theGroup, category, countryID
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
return nil, "none", "none"
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfxMX.catText2ID(inText)
|
||||||
|
local outCat = 0 -- airplane
|
||||||
|
local c = inText:lower()
|
||||||
|
if c == "helicopter" then outCat = 1 end
|
||||||
|
if c == "ship" then outCat = 3 end
|
||||||
|
if c == "plane" then outCat = 0 end -- redundant
|
||||||
|
if c == "vehicle" then outCat = 2 end
|
||||||
|
if c == "train" then outCat = 4 end
|
||||||
|
if c == "static" then outCat = -1 end
|
||||||
|
return outCat
|
||||||
|
end
|
||||||
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
cfxOwnedZones = {}
|
cfxOwnedZones = {}
|
||||||
cfxOwnedZones.version = "1.1.0"
|
cfxOwnedZones.version = "1.1.1"
|
||||||
cfxOwnedZones.verbose = false
|
cfxOwnedZones.verbose = false
|
||||||
cfxOwnedZones.announcer = true
|
cfxOwnedZones.announcer = true
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
@ -39,6 +39,7 @@ cfxOwnedZones.announcer = true
|
|||||||
- remove exiting defenders from zone after cap to avoid
|
- remove exiting defenders from zone after cap to avoid
|
||||||
shocked state
|
shocked state
|
||||||
- announcer
|
- announcer
|
||||||
|
1.1.1 - conq+1 flag
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
cfxOwnedZones.requiredLibs = {
|
cfxOwnedZones.requiredLibs = {
|
||||||
@ -201,6 +202,10 @@ function cfxOwnedZones.addOwnedZone(aZone)
|
|||||||
local paused = cfxZones.getBoolFromZoneProperty(aZone, "paused", false)
|
local paused = cfxZones.getBoolFromZoneProperty(aZone, "paused", false)
|
||||||
aZone.paused = paused
|
aZone.paused = paused
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(aZone, "conq+1") then
|
||||||
|
cfxOwnedZones.conqueredFlag = cfxZones.getNumberFromZoneProperty(theZone, "conq+1", -1)
|
||||||
|
end
|
||||||
|
|
||||||
aZone.unbeatable = cfxZones.getBoolFromZoneProperty(aZone, "unbeatable", false)
|
aZone.unbeatable = cfxZones.getBoolFromZoneProperty(aZone, "unbeatable", false)
|
||||||
aZone.untargetable = cfxZones.getBoolFromZoneProperty(aZone, "untargetable", false)
|
aZone.untargetable = cfxZones.getBoolFromZoneProperty(aZone, "untargetable", false)
|
||||||
aZone.hidden = cfxZones.getBoolFromZoneProperty(aZone, "hidden", false)
|
aZone.hidden = cfxZones.getBoolFromZoneProperty(aZone, "hidden", false)
|
||||||
@ -489,6 +494,11 @@ function cfxOwnedZones.zoneConquered(aZone, theSide, formerOwner) -- 0 = neutral
|
|||||||
trigger.action.outSoundForCoalition(1, "Death BRASS.wav")
|
trigger.action.outSoundForCoalition(1, "Death BRASS.wav")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- increase conq flag
|
||||||
|
if aZone.conqueredFlag then
|
||||||
|
local lastVal = trigger.misc.getUserFlag(aZone.conqueredFlag)
|
||||||
|
trigger.action.setUserFlag)aZone.conqueredFlag, lastVal + 1)
|
||||||
|
end
|
||||||
-- invoke callbacks now
|
-- invoke callbacks now
|
||||||
cfxOwnedZones.invokeConqueredCallbacks(aZone, theSide, formerOwner)
|
cfxOwnedZones.invokeConqueredCallbacks(aZone, theSide, formerOwner)
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
--
|
--
|
||||||
|
|
||||||
cfxZones = {}
|
cfxZones = {}
|
||||||
cfxZones.version = "2.5.2"
|
cfxZones.version = "2.5.3"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
- 2.2.4 - getCoalitionFromZoneProperty
|
- 2.2.4 - getCoalitionFromZoneProperty
|
||||||
- getStringFromZoneProperty
|
- getStringFromZoneProperty
|
||||||
@ -45,6 +45,9 @@ cfxZones.version = "2.5.2"
|
|||||||
- 2.5.1 - markZoneWithSmoke supports alt attribute
|
- 2.5.1 - markZoneWithSmoke supports alt attribute
|
||||||
- 2.5.2 - getPoint also writes through to zone itself for optimization
|
- 2.5.2 - getPoint also writes through to zone itself for optimization
|
||||||
- new method getPositiveRangeFromZoneProperty(theZone, theProperty, default)
|
- new method getPositiveRangeFromZoneProperty(theZone, theProperty, default)
|
||||||
|
- 2.5.3 - new getAllGroupsInZone()
|
||||||
|
- 2.5.4 - cleaned up getZoneProperty break on no properties
|
||||||
|
- extractPropertyFromDCS trims key and property
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
cfxZones.verbose = true
|
cfxZones.verbose = true
|
||||||
@ -543,19 +546,28 @@ end
|
|||||||
--
|
--
|
||||||
-- units / groups in zone
|
-- units / groups in zone
|
||||||
--
|
--
|
||||||
|
function cfxZones.allGroupsInZone(theZone, categ) -- categ is optional, must be code
|
||||||
|
-- warning: does not check for exiting!
|
||||||
|
local inZones = {}
|
||||||
|
local coals = {0, 1, 2} -- all coalitions
|
||||||
|
for idx, coa in pairs(coals) do
|
||||||
|
local allGroups = coalition.getGroups(coa, categ)
|
||||||
|
for key, group in pairs(allGroups) do -- iterate all groups
|
||||||
|
if cfxZones.isGroupPartiallyInZone(group, theZone) then
|
||||||
|
table.insert(inZones, group)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return inZones
|
||||||
|
end
|
||||||
|
|
||||||
function cfxZones.groupsOfCoalitionPartiallyInZone(coal, theZone, categ) -- categ is optional
|
function cfxZones.groupsOfCoalitionPartiallyInZone(coal, theZone, categ) -- categ is optional
|
||||||
local groupsInZone = {}
|
local groupsInZone = {}
|
||||||
local allGroups = coalition.getGroups(coal, categ)
|
local allGroups = coalition.getGroups(coal, categ)
|
||||||
for key, group in pairs(allGroups) do -- iterate all groups
|
for key, group in pairs(allGroups) do -- iterate all groups
|
||||||
if group:isExist() then
|
if group:isExist() then
|
||||||
|
|
||||||
|
|
||||||
if cfxZones.isGroupPartiallyInZone(group, theZone) then
|
if cfxZones.isGroupPartiallyInZone(group, theZone) then
|
||||||
|
|
||||||
table.insert(groupsInZone, group)
|
table.insert(groupsInZone, group)
|
||||||
else
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -566,20 +578,13 @@ function cfxZones.isGroupPartiallyInZone(aGroup, aZone)
|
|||||||
if not aGroup then return false end
|
if not aGroup then return false end
|
||||||
if not aZone then return false end
|
if not aZone then return false end
|
||||||
|
|
||||||
|
|
||||||
-- needs to be implemented
|
|
||||||
if not aGroup:isExist() then return false end
|
if not aGroup:isExist() then return false end
|
||||||
local allUnits = aGroup:getUnits()
|
local allUnits = aGroup:getUnits()
|
||||||
for uk, aUnit in pairs (allUnits) do
|
for uk, aUnit in pairs (allUnits) do
|
||||||
if aUnit:isExist() and aUnit:getLife() > 1 then
|
if aUnit:isExist() and aUnit:getLife() > 1 then
|
||||||
|
|
||||||
local p = aUnit:getPoint()
|
local p = aUnit:getPoint()
|
||||||
-- p.y = 0 -- zones have no altitude
|
|
||||||
-- modification of isPointInsideZone now takes care of this
|
|
||||||
if cfxZones.isPointInsideZone(p, aZone) then
|
if cfxZones.isPointInsideZone(p, aZone) then
|
||||||
return true
|
return true
|
||||||
else
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -589,7 +594,6 @@ end
|
|||||||
function cfxZones.isEntireGroupInZone(aGroup, aZone)
|
function cfxZones.isEntireGroupInZone(aGroup, aZone)
|
||||||
if not aGroup then return false end
|
if not aGroup then return false end
|
||||||
if not aZone then return false end
|
if not aZone then return false end
|
||||||
-- needs to be implemented
|
|
||||||
if not aGroup:isExist() then return false end
|
if not aGroup:isExist() then return false end
|
||||||
local allUnits = aGroup:getUnits()
|
local allUnits = aGroup:getUnits()
|
||||||
for uk, aUnit in pairs (allUnits) do
|
for uk, aUnit in pairs (allUnits) do
|
||||||
@ -1047,6 +1051,8 @@ function cfxZones.getAllZoneProperties(theZone, caseInsensitive) -- return as di
|
|||||||
end
|
end
|
||||||
|
|
||||||
function cfxZones.extractPropertyFromDCS(theKey, theProperties)
|
function cfxZones.extractPropertyFromDCS(theKey, theProperties)
|
||||||
|
-- trim
|
||||||
|
theKey = dcsCommon.trim(theKey)
|
||||||
-- make lower case conversion if not case sensitive
|
-- make lower case conversion if not case sensitive
|
||||||
if not cfxZones.caseSensitiveProperties then
|
if not cfxZones.caseSensitiveProperties then
|
||||||
theKey = string.lower(theKey)
|
theKey = string.lower(theKey)
|
||||||
@ -1055,7 +1061,8 @@ function cfxZones.extractPropertyFromDCS(theKey, theProperties)
|
|||||||
-- iterate all keys and compare to what we are looking for
|
-- iterate all keys and compare to what we are looking for
|
||||||
for i=1, #theProperties do
|
for i=1, #theProperties do
|
||||||
local theP = theProperties[i]
|
local theP = theProperties[i]
|
||||||
local existingKey = theP.key
|
|
||||||
|
local existingKey = dcsCommon.trim(theP.key)
|
||||||
if not cfxZones.caseSensitiveProperties then
|
if not cfxZones.caseSensitiveProperties then
|
||||||
existingKey = string.lower(existingKey)
|
existingKey = string.lower(existingKey)
|
||||||
end
|
end
|
||||||
@ -1073,7 +1080,7 @@ function cfxZones.getZoneProperty(cZone, theKey)
|
|||||||
end
|
end
|
||||||
if not theKey then
|
if not theKey then
|
||||||
trigger.action.outText("+++zone: no property key in getZoneProperty for zone " .. cZone.name, 30)
|
trigger.action.outText("+++zone: no property key in getZoneProperty for zone " .. cZone.name, 30)
|
||||||
breakme.here = 1
|
-- breakme.here = 1
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1349,6 +1356,8 @@ function cfxZones.init()
|
|||||||
-- note, all zones with this property are by definition owned zones.
|
-- note, all zones with this property are by definition owned zones.
|
||||||
-- and hence will be read anyway. this will merely ensure that the
|
-- and hence will be read anyway. this will merely ensure that the
|
||||||
-- ownership is established right away
|
-- ownership is established right away
|
||||||
|
-- unless owned zones module is missing, in which case
|
||||||
|
-- ownership is still established
|
||||||
local pZones = cfxZones.zonesWithProperty("owner")
|
local pZones = cfxZones.zonesWithProperty("owner")
|
||||||
for n, aZone in pairs(pZones) do
|
for n, aZone in pairs(pZones) do
|
||||||
aZone.owner = cfxZones.getCoalitionFromZoneProperty(aZone, "owner", 0)
|
aZone.owner = cfxZones.getCoalitionFromZoneProperty(aZone, "owner", 0)
|
||||||
|
|||||||
451
modules/cloneZone.lua
Normal file
451
modules/cloneZone.lua
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
cloneZones = {}
|
||||||
|
cloneZones.version = "1.0.0"
|
||||||
|
cloneZones.verbose = false
|
||||||
|
cloneZones.requiredLibs = {
|
||||||
|
"dcsCommon", -- always
|
||||||
|
"cfxZones", -- Zones, of course
|
||||||
|
"cfxMX",
|
||||||
|
}
|
||||||
|
cloneZones.cloners = {}
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
Clones Groups from ME mission data
|
||||||
|
Copyright (c) 2022 by Christian Franz and cf/x AG
|
||||||
|
|
||||||
|
Version History
|
||||||
|
1.0.0 - initial version
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
--
|
||||||
|
-- adding / removing from list
|
||||||
|
--
|
||||||
|
function cloneZones.addCloneZone(theZone)
|
||||||
|
table.insert(cloneZones.cloners, theZone)
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.getCloneZoneByName(aName)
|
||||||
|
for idx, aZone in pairs(cloneZones.cloners) do
|
||||||
|
if aName == aZone.name then return aZone end
|
||||||
|
end
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: no clone with name <" .. aName ..">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- reading zones
|
||||||
|
--
|
||||||
|
|
||||||
|
|
||||||
|
function cloneZones.createClonerWithZone(theZone) -- has "Cloner"
|
||||||
|
local localZones = cfxZones.allGroupsInZone(theZone)
|
||||||
|
theZone.cloner = true -- this is a cloner zoner
|
||||||
|
theZone.mySpawns = {}
|
||||||
|
--theZone.groupVectors = {}
|
||||||
|
theZone.origin = cfxZones.getPoint(theZone) -- save reference point for all groupVectors
|
||||||
|
|
||||||
|
-- source tells us which template to use. it can be the following:
|
||||||
|
-- nothing (no attribute) - then we use whatever groups are in zone to
|
||||||
|
-- spawn as template
|
||||||
|
-- name of another spawner that provides the template
|
||||||
|
-- we can't simply use a group name as we lack the reference
|
||||||
|
-- location for delta
|
||||||
|
if cfxZones.hasProperty(theZone, "source") then
|
||||||
|
theZone.source = cfxZones.getStringFromZoneProperty(theZone, "source", "<none>")
|
||||||
|
if theZone.source == "<none>" then theZone.source = nil end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not theZone.source then
|
||||||
|
theZone.cloneNames = {} -- names of the groups. only present in template spawners
|
||||||
|
for idx, aGroup in pairs(localZones) do
|
||||||
|
local gName = aGroup:getName()
|
||||||
|
if gName then
|
||||||
|
table.insert(theZone.cloneNames, gName)
|
||||||
|
table.insert(theZone.mySpawns, aGroup) -- collect them for initial despawn
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
cloneZones.despawnAll(theZone)
|
||||||
|
if #theZone.cloneNames < 1 then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: WARNING - Template in clone zone <" .. theZone.name .. "> is empty", 30)
|
||||||
|
end
|
||||||
|
theZone.cloneNames = nil
|
||||||
|
end
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText(theZone.name .. " clone template saved", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- f? and spawn? map to the same
|
||||||
|
if cfxZones.hasProperty(theZone, "f?") then
|
||||||
|
theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
|
||||||
|
theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value
|
||||||
|
end
|
||||||
|
if cfxZones.hasProperty(theZone, "spawn?") then
|
||||||
|
theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "spawn?", "none")
|
||||||
|
theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value
|
||||||
|
end
|
||||||
|
|
||||||
|
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
||||||
|
|
||||||
|
theZone.moveRoute = cfxZones.getBoolFromZoneProperty(theZone, "moveRoute", false)
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "empty+1") then
|
||||||
|
theZone.emptyFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty+1", "<None>") -- note string on number default
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "masterOwner") then
|
||||||
|
theZone.masterOwner = cfxZones.getStringFromZoneProperty(theZone, "masterOwner", "<none>")
|
||||||
|
end
|
||||||
|
|
||||||
|
--cloneZones.spawnWithCloner(theZone)
|
||||||
|
theZone.turn = cfxZones.getNumberFromZoneProperty(theZone, "turn", 0)
|
||||||
|
|
||||||
|
-- make sure we spawn at least once
|
||||||
|
-- bad idea, since we may want to simply create a template
|
||||||
|
-- if not theZone.spawnFlag then theZone.onStart = true end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- spawning, despawning
|
||||||
|
--
|
||||||
|
|
||||||
|
function cloneZones.despawnAll(theZone)
|
||||||
|
for idx, aGroup in pairs(theZone.mySpawns) do
|
||||||
|
Group.destroy(aGroup)
|
||||||
|
end
|
||||||
|
theZone.mySpawns = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.updateLocationsInGroupData(theData, zoneDelta, adjustAllWaypoints)
|
||||||
|
--trigger.action.outText("Update loc - zone delta: [" .. zoneDelta.x .. "," .. zoneDelta.z .. "]", 30)
|
||||||
|
-- remember that zoneDelta's [z] modifies theData's y!!
|
||||||
|
theData.x = theData.x + zoneDelta.x
|
||||||
|
theData.y = theData.y + zoneDelta.z -- !!!
|
||||||
|
local units = theData.units
|
||||||
|
for idx, aUnit in pairs(units) do
|
||||||
|
aUnit.x = aUnit.x + zoneDelta.x
|
||||||
|
aUnit.y = aUnit.y + zoneDelta.z -- again!!!!
|
||||||
|
end
|
||||||
|
-- now modifiy waypoints. we ALWAYS adjust the
|
||||||
|
-- first waypoint, but only all others if asked
|
||||||
|
-- to
|
||||||
|
local theRoute = theData.route
|
||||||
|
-- TODO: vehicles can have 'spans' - may need to program for
|
||||||
|
-- those as well. we currently only go for points
|
||||||
|
if theRoute then
|
||||||
|
local thePoints = theRoute.points
|
||||||
|
if thePoints and #thePoints > 0 then
|
||||||
|
if adjustAllWaypoints then
|
||||||
|
for i=1, #thePoints do
|
||||||
|
thePoints[i].x = thePoints[i].x + zoneDelta.x
|
||||||
|
thePoints[i].y = thePoints[i].y + zoneDelta.z -- (!!)
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- only first point
|
||||||
|
thePoints[1].x = thePoints[1].x + zoneDelta.x
|
||||||
|
thePoints[1].y = thePoints[1].y + zoneDelta.z -- (!!)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- if there is an airodrome id given in first waypoint,
|
||||||
|
-- adjust for closest location
|
||||||
|
local firstPoint = thePoints[1]
|
||||||
|
if firstPoint.airdromeId then
|
||||||
|
trigger.action.outText("first: airdrome adjust for " .. theData.name .. " now is " .. firstPoint.airdromeId, 30)
|
||||||
|
local loc = {}
|
||||||
|
loc.x = firstPoint.x
|
||||||
|
loc.y = 0
|
||||||
|
loc.z = firstPoint.y
|
||||||
|
local bestAirbase = dcsCommon.getClosestAirbaseTo(loc)
|
||||||
|
firstPoint.airdromeId = bestAirbase:getID()
|
||||||
|
trigger.action.outText("first: adjusted to " .. firstPoint.airdromeId, 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- adjust last point (landing)
|
||||||
|
if #thePoints > 1 then
|
||||||
|
local lastPoint = thePoints[#thePoints]
|
||||||
|
if firstPoint.airdromeId then
|
||||||
|
trigger.action.outText("last: airdrome adjust for " .. theData.name .. " now is " .. lastPoint.airdromeId, 30)
|
||||||
|
local loc = {}
|
||||||
|
loc.x = lastPoint.x
|
||||||
|
loc.y = 0
|
||||||
|
loc.z = lastPoint.y
|
||||||
|
local bestAirbase = dcsCommon.getClosestAirbaseTo(loc)
|
||||||
|
lastPoint.airdromeId = bestAirbase:getID()
|
||||||
|
trigger.action.outText("last: adjusted to " .. lastPoint.airdromeId, 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.uniqueNameGroupData(theData)
|
||||||
|
theData.name = dcsCommon.uuid(theData.name)
|
||||||
|
local units = theData.units
|
||||||
|
for idx, aUnit in pairs(units) do
|
||||||
|
aUnit.name = dcsCommon.uuid(aUnit.name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function cloneZones.resolveOwnership(spawnZone, ctry)
|
||||||
|
if not spawnZone.masterOwner then return ctry end
|
||||||
|
|
||||||
|
local masterZone = cfxZones.getZoneByName(spawnZone.masterOwner)
|
||||||
|
if not masterZone then
|
||||||
|
trigger.action.outText("+++clnZ: cloner " .. spawnZone.name .. " could not fine master owner <" .. spawnZone.masterOwner .. ">", 30)
|
||||||
|
return ctry
|
||||||
|
end
|
||||||
|
|
||||||
|
if not masterZone.owner then
|
||||||
|
return ctry
|
||||||
|
end
|
||||||
|
|
||||||
|
ctry = dcsCommon.getACountryForCoalition(masterZone.owner)
|
||||||
|
return ctry
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||||
|
--trigger.action.outText("ENTER: Spawn with template " .. theZone.name .. " for spawnZone " .. spawnZone.name, 30)
|
||||||
|
-- theZone is the zoner with the template
|
||||||
|
-- spawnZone is the spawner with settings
|
||||||
|
--if not spawnZone then spawnZone = theZone end
|
||||||
|
local newCenter = cfxZones.getPoint(spawnZone)
|
||||||
|
-- calculate zoneDelta, is added to all vectors
|
||||||
|
local zoneDelta = dcsCommon.vSub(newCenter, theZone.origin)
|
||||||
|
|
||||||
|
local spawnedGroups = {}
|
||||||
|
|
||||||
|
for idx, aGroupName in pairs(theZone.cloneNames) do
|
||||||
|
local rawData, cat, ctry = cfxMX.getGroupFromDCSbyName(aGroupName)
|
||||||
|
|
||||||
|
if rawData.name == aGroupName then
|
||||||
|
else
|
||||||
|
trigger.action.outText("Clone: FAILED name check", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- now use raw data to spawn and see if it works outabox
|
||||||
|
local theCat = cfxMX.catText2ID(cat)
|
||||||
|
--TODO: if theCat == -1 the group is static, may need to code for that
|
||||||
|
|
||||||
|
-- update their position if not spawning to exact same location
|
||||||
|
cloneZones.updateLocationsInGroupData(rawData, zoneDelta, spawnZone.moveRoute)
|
||||||
|
|
||||||
|
-- apply turning
|
||||||
|
dcsCommon.rotateGroupData(rawData, spawnZone.turn, newCenter.x, newCenter.z)
|
||||||
|
|
||||||
|
-- make sure all names (group and units) are unique
|
||||||
|
cloneZones.uniqueNameGroupData(rawData)
|
||||||
|
|
||||||
|
-- see waht country we spawn for
|
||||||
|
ctry = cloneZones.resolveOwnership(spawnZone, ctry)
|
||||||
|
|
||||||
|
local theGroup = coalition.addGroup(ctry, theCat, rawData)
|
||||||
|
table.insert(spawnedGroups, theGroup)
|
||||||
|
end
|
||||||
|
|
||||||
|
return spawnedGroups
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.spawnWithCloner(theZone)
|
||||||
|
if not theZone then
|
||||||
|
trigger.action.outText("+++clnZ: nil zone on spawnWithCloner", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if not theZone.cloner then
|
||||||
|
trigger.action.outText("+++clnZ: spawnWithCloner invoked with non-cloner <" .. theZone.name .. ">", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- force spawn with this spawner
|
||||||
|
local templateZone = theZone
|
||||||
|
if theZone.source then
|
||||||
|
-- we use a different zone for templates
|
||||||
|
-- souce can be a comma separated list
|
||||||
|
local templateName = theZone.source
|
||||||
|
if dcsCommon.containsString(templateName, ",") then
|
||||||
|
local allNames = templateName
|
||||||
|
local templates = dcsCommon.splitString(templateName, ",")
|
||||||
|
templateName = dcsCommon.pickRandom(templates)
|
||||||
|
templateName = dcsCommon.trim(templateName)
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: picked random template <" .. templateName .."> for from <" .. allNames .. "> for cloner " .. theZone.name, 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local newTemplate = cloneZones.getCloneZoneByName(templateName)
|
||||||
|
if not newTemplate then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: no clone source with name <" .. templateName .."> for cloner " .. theZone.name, 30)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
templateZone = newTemplate
|
||||||
|
end
|
||||||
|
|
||||||
|
-- make sure our template is filled
|
||||||
|
if not templateZone.cloneNames then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: clone source template <".. templateZone.name .. "> for clone zone <" .. theZone.name .."> is empty", 30)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- local myLoc = cfxZones.getPoint(theZone)
|
||||||
|
local theClones = cloneZones.spawnWithTemplateForZone(templateZone, theZone)
|
||||||
|
-- reset hasClones so we know our spawns are full and we can
|
||||||
|
-- detect complete destruction
|
||||||
|
if theClones and #theClones > 0 then
|
||||||
|
theZone.hasClones = true
|
||||||
|
theZone.mySpawns = theClones
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.countLiveUnits(theZone)
|
||||||
|
if not theZone then return 0 end
|
||||||
|
if not theZone.mySpawns then return 0 end
|
||||||
|
local count = 0
|
||||||
|
for idx, aGroup in pairs(theZone.mySpawns) do
|
||||||
|
if aGroup:isExist() then
|
||||||
|
local allUnits = aGroup:getUnits()
|
||||||
|
for idy, aUnit in pairs(allUnits) do
|
||||||
|
if aUnit:isExist() and aUnit:getLife() >= 1 then
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.hasLiveUnits(theZone)
|
||||||
|
if not theZone then return 0 end
|
||||||
|
if not theZone.mySpawns then return 0 end
|
||||||
|
for idx, aGroup in pairs(theZone.mySpawns) do
|
||||||
|
if aGroup:isExist() then
|
||||||
|
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
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.pollFlag(flagNum, method)
|
||||||
|
-- we currently ignore method
|
||||||
|
local num = trigger.misc.getUserFlag(flagNum)
|
||||||
|
trigger.action.setUserFlag(flagNum, num+1)
|
||||||
|
end
|
||||||
|
--
|
||||||
|
-- UPDATE
|
||||||
|
--
|
||||||
|
function cloneZones.update()
|
||||||
|
timer.scheduleFunction(cloneZones.update, {}, timer.getTime() + 1)
|
||||||
|
|
||||||
|
for idx, aZone in pairs(cloneZones.cloners) do
|
||||||
|
-- see if pulse is running
|
||||||
|
|
||||||
|
-- see if we got spawn? command
|
||||||
|
if aZone.spawnFlag then
|
||||||
|
local currTriggerVal = trigger.misc.getUserFlag(aZone.spawnFlag)
|
||||||
|
if currTriggerVal ~= aZone.lastSpawnValue
|
||||||
|
then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: spawn triggered for <" .. aZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
cloneZones.spawnWithCloner(aZone)
|
||||||
|
aZone.lastSpawnValue = currTriggerVal
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- see if we are empty and should signal
|
||||||
|
if aZone.emptyFlag and aZone.hasClones then
|
||||||
|
if cloneZones.countLiveUnits(aZone) < 1 then
|
||||||
|
-- we are depleted. poll flag once, then remember we have
|
||||||
|
-- polled
|
||||||
|
cloneZones.pollFlag(aZone.emptyFlag)
|
||||||
|
aZone.hasClones = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.onStart()
|
||||||
|
--trigger.action.outText("+++clnZ: Enter atStart", 30)
|
||||||
|
for idx, theZone in pairs(cloneZones.cloners) do
|
||||||
|
if theZone.onStart then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: atStart will spawn for <"..theZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
cloneZones.spawnWithCloner(theZone)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- START
|
||||||
|
--
|
||||||
|
function cloneZones.readConfigZone()
|
||||||
|
local theZone = cfxZones.getZoneByName("cloneZonesConfig")
|
||||||
|
if not theZone then
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: NO config zone!", 30)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
cloneZones.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||||
|
|
||||||
|
if cloneZones.verbose then
|
||||||
|
trigger.action.outText("+++clnZ: read config", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cloneZones.start()
|
||||||
|
-- lib check
|
||||||
|
if not dcsCommon.libCheck then
|
||||||
|
trigger.action.outText("cfx Clone Zones requires dcsCommon", 30)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not dcsCommon.libCheck("cfx Clone Zones",
|
||||||
|
cloneZones.requiredLibs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- read config
|
||||||
|
cloneZones.readConfigZone()
|
||||||
|
|
||||||
|
-- process cloner Zones
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("cloner")
|
||||||
|
|
||||||
|
-- now create an rnd gen for each one and add them
|
||||||
|
-- to our watchlist
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
cloneZones.createClonerWithZone(aZone) -- process attribute and add to zone
|
||||||
|
cloneZones.addCloneZone(aZone) -- remember it so we can smoke it
|
||||||
|
end
|
||||||
|
|
||||||
|
-- run through onStart
|
||||||
|
cloneZones.onStart()
|
||||||
|
|
||||||
|
-- start update
|
||||||
|
cloneZones.update()
|
||||||
|
|
||||||
|
trigger.action.outText("cfx Clone Zones v" .. cloneZones.version .. " started.", 30)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- let's go!
|
||||||
|
if not cloneZones.start() then
|
||||||
|
trigger.action.outText("cf/x Clone Zones aborted: missing libraries", 30)
|
||||||
|
cloneZones = nil
|
||||||
|
end
|
||||||
@ -1,5 +1,5 @@
|
|||||||
dcsCommon = {}
|
dcsCommon = {}
|
||||||
dcsCommon.version = "2.5.2"
|
dcsCommon.version = "2.5.3"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
2.2.6 - compassPositionOfARelativeToB
|
2.2.6 - compassPositionOfARelativeToB
|
||||||
- clockPositionOfARelativeToB
|
- clockPositionOfARelativeToB
|
||||||
@ -58,6 +58,7 @@ dcsCommon.version = "2.5.2"
|
|||||||
2.5.1 - added SA-18 Igla manpad to unitIsInfantry()
|
2.5.1 - added SA-18 Igla manpad to unitIsInfantry()
|
||||||
2.5.2 - added copyArray method
|
2.5.2 - added copyArray method
|
||||||
- corrected heading in createStaticObjectData
|
- corrected heading in createStaticObjectData
|
||||||
|
2.5.3 - corrected rotateGroupData bug for cz
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
-- dcsCommon is a library of common lua functions
|
-- dcsCommon is a library of common lua functions
|
||||||
@ -1444,7 +1445,10 @@ dcsCommon.version = "2.5.2"
|
|||||||
|
|
||||||
function dcsCommon.rotateGroupData(theGroup, degrees, cx, cz)
|
function dcsCommon.rotateGroupData(theGroup, degrees, cx, cz)
|
||||||
if not cx then cx = 0 end
|
if not cx then cx = 0 end
|
||||||
if not cy then cy = 0 end
|
if not cz then cz = 0 end
|
||||||
|
local cy = cz
|
||||||
|
--trigger.action.outText("+++dcsC:rotGrp cy,cy = "..cx .. "," .. cy, 30)
|
||||||
|
|
||||||
local rads = degrees * 3.14152 / 180
|
local rads = degrees * 3.14152 / 180
|
||||||
-- turns all units in group around the group's center by degrees.
|
-- turns all units in group around the group's center by degrees.
|
||||||
-- may also need to turn individual units by same amount
|
-- may also need to turn individual units by same amount
|
||||||
|
|||||||
263
modules/delayFlags.lua
Normal file
263
modules/delayFlags.lua
Normal file
@ -0,0 +1,263 @@
|
|||||||
|
delayFlag = {}
|
||||||
|
delayFlag.version = "1.0.0"
|
||||||
|
delayFlag.verbose = false
|
||||||
|
delayFlag.requiredLibs = {
|
||||||
|
"dcsCommon", -- always
|
||||||
|
"cfxZones", -- Zones, of course
|
||||||
|
}
|
||||||
|
delayFlag.flags = {}
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
delay flags - simple flag switch & delay, allows for randomize
|
||||||
|
and dead man switching
|
||||||
|
|
||||||
|
Copyright (c) 2022 by Christian Franz and cf/x AG
|
||||||
|
|
||||||
|
Version History
|
||||||
|
1.0.0 - Initial Version
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
function delayFlag.addDelayZone(theZone)
|
||||||
|
table.insert(delayFlag.flags, theZone)
|
||||||
|
end
|
||||||
|
|
||||||
|
function delayFlag.getDelayZoneByName(aName)
|
||||||
|
for idx, aZone in pairs(delayFlag.flags) do
|
||||||
|
if aName == aZone.name then return aZone end
|
||||||
|
end
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: no delay flag with name <" .. aName ..">", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- read attributes
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- create rnd gen from zone
|
||||||
|
--
|
||||||
|
function delayFlag.createTimerWithZone(theZone)
|
||||||
|
-- delay
|
||||||
|
theZone.delayMin, theZone.delayMax = cfxZones.getPositiveRangeFromZoneProperty(theZone, "timeDelay", 1) -- same as zone signature
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: time delay is <" .. theZone.delayMin .. ", " .. theZone.delayMax .. "> seconds", 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- trigger flag
|
||||||
|
if cfxZones.hasProperty(theZone, "f?") then
|
||||||
|
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none")
|
||||||
|
end
|
||||||
|
|
||||||
|
if cfxZones.hasProperty(theZone, "in?") then
|
||||||
|
theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none")
|
||||||
|
end
|
||||||
|
|
||||||
|
if theZone.triggerFlag then
|
||||||
|
theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
theZone.method = cfxZones.getStringFromZoneProperty(theZone, "method", "flip")
|
||||||
|
|
||||||
|
-- out flag
|
||||||
|
if cfxZones.hasProperty(theZone, "out!") then
|
||||||
|
theZone.outFlag = cfxZones.getNumberFromZoneProperty(theZone, "out!", -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- on start
|
||||||
|
if cfxZones.hasProperty(theZone, "onStart") then
|
||||||
|
theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- message
|
||||||
|
if cfxZones.hasProperty(theZone, "message") then
|
||||||
|
theZone.myMessage = cfxZones.getBoolStringZoneProperty(theZone, "message", "<none>")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- init
|
||||||
|
theZone.running = false
|
||||||
|
theZone.timeLimit = -1
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- do the pulling
|
||||||
|
--
|
||||||
|
function delayFlag.pollFlag(theFlag, method)
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: polling flag " .. theFlag .. " with " .. method, 30)
|
||||||
|
end
|
||||||
|
|
||||||
|
method = method:lower()
|
||||||
|
local currVal = trigger.misc.getUserFlag(theFlag)
|
||||||
|
if method == "inc" or method == "f+1" then
|
||||||
|
trigger.action.setUserFlag(theFlag, currVal + 1)
|
||||||
|
|
||||||
|
elseif method == "dec" or method == "f-1" then
|
||||||
|
trigger.action.setUserFlag(theFlag, currVal - 1)
|
||||||
|
|
||||||
|
elseif method == "off" or method == "f=0" then
|
||||||
|
trigger.action.setUserFlag(theFlag, 0)
|
||||||
|
|
||||||
|
elseif method == "flip" or method == "xor" then
|
||||||
|
if currVal ~= 0 then
|
||||||
|
trigger.action.setUserFlag(theFlag, 0)
|
||||||
|
else
|
||||||
|
trigger.action.setUserFlag(theFlag, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
if method ~= "on" and method ~= "f=1" then
|
||||||
|
trigger.action.outText("+++RND: unknown method <" .. method .. "> - using 'on'", 30)
|
||||||
|
end
|
||||||
|
-- default: on.
|
||||||
|
trigger.action.setUserFlag(theFlag, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local newVal = trigger.misc.getUserFlag(theFlag)
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF flag <" .. theFlag .. "> changed from " .. currVal .. " to " .. newVal, 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- update
|
||||||
|
--
|
||||||
|
|
||||||
|
function delayFlag.startDelay(theZone)
|
||||||
|
-- refresh timer
|
||||||
|
theZone.running = true
|
||||||
|
|
||||||
|
-- set new expiry date
|
||||||
|
local delayMax = theZone.delayMax
|
||||||
|
local delayMin = theZone.delayMin
|
||||||
|
local delay = delayMax
|
||||||
|
|
||||||
|
if delayMin ~= delayMax then
|
||||||
|
-- pick random in range , say 3-7 --> 5 s!
|
||||||
|
local delayDiff = (delayMax - delayMin) + 1 -- 7-3 + 1
|
||||||
|
delay = dcsCommon.smallRandom(delayDiff) - 1 --> 0-4
|
||||||
|
delay = delay + delayMin
|
||||||
|
if delay > theZone.delayMax then delay = theZone.delayMax end
|
||||||
|
if delay < 1 then delay = 1 end
|
||||||
|
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: delay " .. theZone.name .. " range " .. delayMin .. "-" .. delayMax .. ": selected " .. delay, 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
theZone.timeLimit = timer.getTime() + delay
|
||||||
|
end
|
||||||
|
|
||||||
|
function delayFlag.update()
|
||||||
|
-- call me in a second to poll triggers
|
||||||
|
timer.scheduleFunction(delayFlag.update, {}, timer.getTime() + 1)
|
||||||
|
|
||||||
|
local now = timer.getTime()
|
||||||
|
|
||||||
|
for idx, aZone in pairs(delayFlag.flags) do
|
||||||
|
-- make sure to re-start before reading time limit
|
||||||
|
if aZone.triggerFlag then
|
||||||
|
local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerFlag)
|
||||||
|
if currTriggerVal ~= aZone.lastTriggerValue
|
||||||
|
then
|
||||||
|
if delayFlag.verbose then
|
||||||
|
if aZone.running then
|
||||||
|
trigger.action.outText("+++dlyF: re-starting timer " .. aZone.name, 30)
|
||||||
|
else
|
||||||
|
trigger.action.outText("+++dlyF: init timer for " .. aZone.name, 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
delayFlag.startDelay(aZone) -- we restart even if running
|
||||||
|
aZone.lastTriggerValue = currTriggerVal
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if aZone.running then
|
||||||
|
-- check expiry
|
||||||
|
if now > aZone.timeLimit then
|
||||||
|
-- end timer
|
||||||
|
aZone.running = false
|
||||||
|
-- poll flag
|
||||||
|
delayFlag.pollFlag(aZone.outFlag, aZone.method)
|
||||||
|
-- say message
|
||||||
|
if aZone.myMessage then
|
||||||
|
trigger.action.outText(aZone.myMessage, 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- START
|
||||||
|
--
|
||||||
|
function delayFlag.readConfigZone()
|
||||||
|
local theZone = cfxZones.getZoneByName("cloneZonesConfig")
|
||||||
|
if not theZone then
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: NO config zone!", 30)
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
delayFlag.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||||
|
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: read config", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function delayFlag.onStart()
|
||||||
|
for idx, theZone in pairs(delayFlag.flags) do
|
||||||
|
if theZone.onStart then
|
||||||
|
if delayFlag.verbose then
|
||||||
|
trigger.action.outText("+++dlyF: onStart for <"..theZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
delayFlag.startDelay(theZone)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function delayFlag.start()
|
||||||
|
-- lib check
|
||||||
|
if not dcsCommon.libCheck then
|
||||||
|
trigger.action.outText("cfx Delay Flags requires dcsCommon", 30)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not dcsCommon.libCheck("cfx Delay Flags",
|
||||||
|
delayFlag.requiredLibs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- read config
|
||||||
|
delayFlag.readConfigZone()
|
||||||
|
|
||||||
|
-- process cloner Zones
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("timeDelay")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
delayFlag.createTimerWithZone(aZone) -- process attributes
|
||||||
|
delayFlag.addDelayZone(aZone) -- add to list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- kick onStart
|
||||||
|
delayFlag.onStart()
|
||||||
|
|
||||||
|
-- start update
|
||||||
|
delayFlag.update()
|
||||||
|
|
||||||
|
trigger.action.outText("cfx Delay Flag v" .. delayFlag.version .. " started.", 30)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- let's go!
|
||||||
|
if not delayFlag.start() then
|
||||||
|
trigger.action.outText("cfx Delay Flag aborted: missing libraries", 30)
|
||||||
|
delayFlag = nil
|
||||||
|
end
|
||||||
Binary file not shown.
BIN
tutorial & demo missions/demo - Attack of the CloneZ.miz
Normal file
BIN
tutorial & demo missions/demo - Attack of the CloneZ.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user