mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Version 2.4.0
Happy new year! smoking smoke trails module
This commit is contained in:
parent
bb301ecb30
commit
2274ba930d
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
cfxZones = {}
|
cfxZones = {}
|
||||||
cfxZones.version = "4.4.4"
|
cfxZones.version = "4.5.0"
|
||||||
|
|
||||||
-- cf/x zone management module
|
-- cf/x zone management module
|
||||||
-- reads dcs zones and makes them accessible and mutable
|
-- reads dcs zones and makes them accessible and mutable
|
||||||
@ -34,6 +34,12 @@ cfxZones.version = "4.4.4"
|
|||||||
-4.4.2 - twn support for wildcards <twn: > and <loc:>
|
-4.4.2 - twn support for wildcards <twn: > and <loc:>
|
||||||
-4.4.3 - property name is trimmed (double check)
|
-4.4.3 - property name is trimmed (double check)
|
||||||
-4.4.4 - createGroundUnitsInZoneForCoalition supports drivable
|
-4.4.4 - createGroundUnitsInZoneForCoalition supports drivable
|
||||||
|
-4.4.5 - corrected startMovingZones() for linked zones via ME's LINKZONE drop-down
|
||||||
|
-4.4.6 - corrected pattern bug in processDynamicAB()
|
||||||
|
-4.5.0 - corrected bug in getBoolFromZoneProperty for default = false and "rnd"
|
||||||
|
- rnd in bool can have = xxx param for percentage
|
||||||
|
- getSmokeColorNumberFromZoneProperty()
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -2467,20 +2473,40 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal)
|
|||||||
if type(defaultVal) ~= "boolean" then
|
if type(defaultVal) ~= "boolean" then
|
||||||
defaultVal = false
|
defaultVal = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if not theZone then
|
if not theZone then
|
||||||
trigger.action.outText("WARNING: NIL Zone in getBoolFromZoneProperty", 30)
|
trigger.action.outText("WARNING: NIL Zone in getBoolFromZoneProperty", 30)
|
||||||
return defaultVal
|
return defaultVal
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local p = cfxZones.getZoneProperty(theZone, theProperty)
|
local p = cfxZones.getZoneProperty(theZone, theProperty)
|
||||||
if not p then return defaultVal end
|
if not p then return defaultVal end
|
||||||
|
|
||||||
-- make sure we compare so default always works when
|
-- make sure we compare so default always works when
|
||||||
-- answer isn't exactly the opposite
|
-- answer isn't exactly the opposite
|
||||||
p = p:lower()
|
p = p:lower()
|
||||||
p = dcsCommon.trim(p)
|
p = dcsCommon.trim(p)
|
||||||
|
local p1 = p:find("=") -- pre-proccing for random
|
||||||
|
if p1 then
|
||||||
|
local r = p:sub(p1+1, -1)
|
||||||
|
p = p:sub(1,p1-1)
|
||||||
|
if r and string.len(r) > 0 then p1 = math.floor(tonumber(r)) else p1 = nil end
|
||||||
|
p = dcsCommon.trim(p)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- special: return a random value if p == "rnd" or "?" or "maybe"
|
||||||
|
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
|
||||||
|
local matchVal = 500 -- 50%
|
||||||
|
local theRnd = math.random(1000)
|
||||||
|
if p1 then
|
||||||
|
-- we have a numeric rnd=xxx.
|
||||||
|
matchVal = p1 * 10
|
||||||
|
end
|
||||||
|
if theZone.verbose then
|
||||||
|
trigger.action.outText("+++Zne: zone <" .. theZone.name .. "> getBool RND resolve for attr <" .. theProperty .. ">", 30)
|
||||||
|
if p1 then trigger.action.outText("rnd range set to <" .. p1 .. ">%", 30) end
|
||||||
|
trigger.action.outText("is rnd <" .. theRnd .. "> < match <" .. matchVal .. ">?", 30)
|
||||||
|
end
|
||||||
|
return (theRnd < matchVal)
|
||||||
|
end
|
||||||
|
|
||||||
if defaultVal == false then
|
if defaultVal == false then
|
||||||
-- only go true if exact match to yes or true
|
-- only go true if exact match to yes or true
|
||||||
theBool = false
|
theBool = false
|
||||||
@ -2488,11 +2514,6 @@ function cfxZones.getBoolFromZoneProperty(theZone, theProperty, defaultVal)
|
|||||||
return theBool
|
return theBool
|
||||||
end
|
end
|
||||||
|
|
||||||
-- special: return a random value if p == "rnd" or "?" or "maybe"
|
|
||||||
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
|
|
||||||
return (math.random(1000) < 500) -- 50:50
|
|
||||||
end
|
|
||||||
|
|
||||||
local theBool = true
|
local theBool = true
|
||||||
-- only go false if exactly no or false or "0"
|
-- only go false if exactly no or false or "0"
|
||||||
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off")
|
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p~="off")
|
||||||
@ -2504,14 +2525,35 @@ function dmlZone:getBoolFromZoneProperty(theProperty, defaultVal)
|
|||||||
if type(defaultVal) ~= "boolean" then
|
if type(defaultVal) ~= "boolean" then
|
||||||
defaultVal = false
|
defaultVal = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local p = self:getZoneProperty(theProperty)
|
local p = self:getZoneProperty(theProperty)
|
||||||
if not p then return defaultVal end
|
if not p then return defaultVal end
|
||||||
|
|
||||||
-- make sure we compare so default always works when
|
-- make sure we compare so default always works when
|
||||||
-- answer isn't exactly the opposite
|
-- answer isn't exactly the opposite
|
||||||
p = p:lower()
|
p = p:lower()
|
||||||
p = dcsCommon.trim(p)
|
p = dcsCommon.trim(p)
|
||||||
|
local p1 = p:find("=") -- pre-proccing for random
|
||||||
|
if p1 then
|
||||||
|
local r = p:sub(p1+1, -1)
|
||||||
|
p = p:sub(1,p1-1)
|
||||||
|
if r and string.len(r) > 0 then p1 = math.floor(tonumber(r)) else p1 = nil end
|
||||||
|
p = dcsCommon.trim(p)
|
||||||
|
end
|
||||||
|
-- special: return a random value if p == "rnd" or "?" or "maybe"
|
||||||
|
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
|
||||||
|
local matchVal = 500 -- 50%
|
||||||
|
local theRnd = math.random(1000)
|
||||||
|
if p1 then
|
||||||
|
-- we have a numeric rnd=xxx.
|
||||||
|
matchVal = p1 * 10
|
||||||
|
end
|
||||||
|
if self.verbose then
|
||||||
|
trigger.action.outText("+++Zne: zone <" .. self.name .. "> getBool RND resolve for attr <" .. theProperty .. ">", 30)
|
||||||
|
if p1 then trigger.action.outText("rnd range set to <" .. p1 .. ">%", 30) end
|
||||||
|
trigger.action.outText("is rnd <" .. theRnd .. "> < match <" .. matchVal .. ">?", 30)
|
||||||
|
end
|
||||||
|
return (theRnd < matchVal)
|
||||||
|
end
|
||||||
|
|
||||||
if defaultVal == false then
|
if defaultVal == false then
|
||||||
-- only go true if exact match to yes or true
|
-- only go true if exact match to yes or true
|
||||||
theBool = false
|
theBool = false
|
||||||
@ -2519,11 +2561,6 @@ function dmlZone:getBoolFromZoneProperty(theProperty, defaultVal)
|
|||||||
return theBool
|
return theBool
|
||||||
end
|
end
|
||||||
|
|
||||||
-- special: return a random value if p == "rnd" or "?" or "maybe"
|
|
||||||
if (p == "?") or (p == "rnd") or (p == "random") or (p == "maybe") then
|
|
||||||
return (math.random(1000) < 500) -- 50:50
|
|
||||||
end
|
|
||||||
|
|
||||||
local theBool = true
|
local theBool = true
|
||||||
-- only go false if exactly no or false or "0"
|
-- only go false if exactly no or false or "0"
|
||||||
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p ~= "off")
|
theBool = (p ~= 'false') and (p ~= 'no') and (p ~= "0") and (p ~= "off")
|
||||||
@ -2776,6 +2813,8 @@ function cfxZones.getSmokeColorStringFromZoneProperty(theZone, theProperty, defa
|
|||||||
end
|
end
|
||||||
|
|
||||||
function dmlZone:getSmokeColorStringFromZoneProperty(theProperty, default) -- smoke as 'red', 'green', or 1..5
|
function dmlZone:getSmokeColorStringFromZoneProperty(theProperty, default) -- smoke as 'red', 'green', or 1..5
|
||||||
|
return cfxZones.getSmokeColorStringFromZoneProperty(self, theProperty, default)
|
||||||
|
--[[
|
||||||
if not default then default = "red" end
|
if not default then default = "red" end
|
||||||
local s = self:getStringFromZoneProperty(theProperty, default)
|
local s = self:getStringFromZoneProperty(theProperty, default)
|
||||||
s = s:lower()
|
s = s:lower()
|
||||||
@ -2794,8 +2833,39 @@ function dmlZone:getSmokeColorStringFromZoneProperty(theProperty, default) -- sm
|
|||||||
s == "blue" then return s end
|
s == "blue" then return s end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
|
--]]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cfxZones.getSmokeColorNumberFromZoneProperty(theZone, theProperty, default) -- smoke as 'red', 'green', or 1..5
|
||||||
|
-- NOT identical to smoke numbers used in ctf!!!!
|
||||||
|
if not default then default = "red" end
|
||||||
|
local s = cfxZones.getStringFromZoneProperty(theZone, theProperty, default)
|
||||||
|
if not s or string.len(s) < 1 then s = default end
|
||||||
|
|
||||||
|
s = s:lower()
|
||||||
|
s = dcsCommon.trim(s)
|
||||||
|
-- check numbers
|
||||||
|
local n = tonumber(s)
|
||||||
|
if n then
|
||||||
|
if n >= 0 and n < 5 then return math.floor(n) end
|
||||||
|
return -1 -- random
|
||||||
|
end
|
||||||
|
|
||||||
|
if s == "green" then return 0
|
||||||
|
elseif s == "red" then return 1
|
||||||
|
elseif s == "white" then return 2
|
||||||
|
elseif s == "orange" then return 3
|
||||||
|
elseif s == "blue" then return 4
|
||||||
|
elseif s == "?" or s == "rnd" or s == "random" then return -1
|
||||||
|
else return -1 -- should NEVER happen
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function dmlZone:getSmokeColorNumberFromZoneProperty(theProperty, default)
|
||||||
|
return cfxZones.getSmokeColorNumberFromZoneProperty(self, theProperty, default)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function cfxZones.getFlareColorStringFromZoneProperty(theZone, theProperty, default) -- smoke as 'red', 'green', or 1..5
|
function cfxZones.getFlareColorStringFromZoneProperty(theZone, theProperty, default) -- smoke as 'red', 'green', or 1..5
|
||||||
if not default then default = "red" end
|
if not default then default = "red" end
|
||||||
local s = cfxZones.getStringFromZoneProperty(theZone, theProperty, default)
|
local s = cfxZones.getStringFromZoneProperty(theZone, theProperty, default)
|
||||||
@ -2820,6 +2890,8 @@ function cfxZones.getFlareColorStringFromZoneProperty(theZone, theProperty, defa
|
|||||||
end
|
end
|
||||||
|
|
||||||
function dmlZone:getFlareColorStringFromZoneProperty(theProperty, default) -- smoke as 'red', 'green', or 1..5
|
function dmlZone:getFlareColorStringFromZoneProperty(theProperty, default) -- smoke as 'red', 'green', or 1..5
|
||||||
|
return cfxZones.getFlareColorStringFromZoneProperty(self, theProperty, default)
|
||||||
|
--[[--
|
||||||
if not default then default = "red" end
|
if not default then default = "red" end
|
||||||
local s = self:getStringFromZoneProperty(theProperty, default)
|
local s = self:getStringFromZoneProperty(theProperty, default)
|
||||||
s = s:lower()
|
s = s:lower()
|
||||||
@ -2840,6 +2912,7 @@ function dmlZone:getFlareColorStringFromZoneProperty(theProperty, default) -- sm
|
|||||||
return s end
|
return s end
|
||||||
|
|
||||||
return default
|
return default
|
||||||
|
--]]--
|
||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -3166,21 +3239,37 @@ end
|
|||||||
|
|
||||||
function cfxZones.processDynamicAB(inMsg, locale)
|
function cfxZones.processDynamicAB(inMsg, locale)
|
||||||
local outMsg = inMsg
|
local outMsg = inMsg
|
||||||
|
local startLoc
|
||||||
|
local endLoc
|
||||||
|
local iter = 0
|
||||||
if not locale then locale = "A/B" end
|
if not locale then locale = "A/B" end
|
||||||
|
-- FULL REWORK: find has bugs in grep
|
||||||
-- <A/B: flagOrUnitName [val A | val B]>
|
-- <A/B: flagOrUnitName [text A | text B]>
|
||||||
local replacerValPattern = "<".. locale .. ":%s*[%s%w%*%d%.%-_]+" .. "%[[%s%w]+|[%s%w]+%]"..">"
|
local replacerValPattern = "<".. locale .. ":%s*[%s%w%*%d%.%-_]+" ..
|
||||||
|
"%[[%s%w%p%-%._]+" .. "|" ..
|
||||||
|
"[%s%w%p%-%._]+%]" .. ">" -- now with captures
|
||||||
repeat
|
repeat
|
||||||
local startLoc, endLoc = string.find(outMsg, replacerValPattern)
|
startLoc, endLoc = string.find(outMsg, replacerValPattern, 1) -- note "1"
|
||||||
if startLoc then
|
if startLoc then
|
||||||
local rp = string.sub(outMsg, startLoc, endLoc)
|
iter = iter + 1
|
||||||
-- get val/unit name
|
-- let's find the "real" endloc, since find returns all if more than one hit
|
||||||
|
local e1 = string.find(outMsg, "|", startLoc)
|
||||||
|
-- from there, find the end "]>" -- no blanks between them
|
||||||
|
if not e1 then trigger.action.outText("wildcard a/B : no delim | in <" .. outMsg .. "> after <" .. startLoc .. ">, returning", 30); return "err1" end
|
||||||
|
local e2 = string.find(outMsg, "%]>", e1)
|
||||||
|
if not e2 then trigger.action.outText("wildcard A/B: no lim %]> in <" .. outMsg .. "> after <" .. e2 .. ">, returning", 30); return "err3" end
|
||||||
|
local e3 = e2 + 1
|
||||||
|
local rp = string.sub(outMsg, startLoc, e3) -- endLoc) -- whole shebang
|
||||||
|
local asmLeft = "" -- instead of gsub we re-assemble
|
||||||
|
if startLoc > 1 then asmLeft = string.sub(outMsg, 1, startLoc-1) end -- left side
|
||||||
|
local asmRight = string.sub(outMsg, e3 + 1, -1) -- right side
|
||||||
|
-- get flag/unit name
|
||||||
local valA, valB = string.find(rp, ":%s*[%s%w%*%d%.%-_]+%[")
|
local valA, valB = string.find(rp, ":%s*[%s%w%*%d%.%-_]+%[")
|
||||||
local val = string.sub(rp, valA+1, valB-1)
|
local val = string.sub(rp, valA+1, valB-1)
|
||||||
val = dcsCommon.trim(val)
|
val = dcsCommon.trim(val)
|
||||||
-- get left and right
|
-- get left and right
|
||||||
local leftA, leftB = string.find(rp, "%[[%s%w]+|" ) -- from "[" to "|"
|
local leftA, leftB = string.find(rp, "%[[%s%w%p%-%._]+|" ) -- from "[" to "|"
|
||||||
local rightA, rightB = string.find(rp, "|[%s%w]+%]") -- from "|" to "]"
|
local rightA, rightB = string.find(rp, "|[%s%w%p%-%._]+%]") -- from "|" to "]"
|
||||||
left = string.sub(rp, leftA+1, leftB-1)
|
left = string.sub(rp, leftA+1, leftB-1)
|
||||||
left = dcsCommon.trim(left)
|
left = dcsCommon.trim(left)
|
||||||
right = string.sub(rp, rightA+1, rightB-1)
|
right = string.sub(rp, rightA+1, rightB-1)
|
||||||
@ -3196,9 +3285,10 @@ function cfxZones.processDynamicAB(inMsg, locale)
|
|||||||
|
|
||||||
local locString = left
|
local locString = left
|
||||||
if yesno then locString = right end
|
if yesno then locString = right end
|
||||||
outMsg = string.gsub(outMsg, replacerValPattern, locString, 1)
|
local tmp = asmLeft .. locString .. asmRight
|
||||||
|
outMsg = tmp
|
||||||
end
|
end
|
||||||
until not startLoc
|
until (not startLoc) or (iter > 10) -- max 2 iters
|
||||||
return outMsg
|
return outMsg
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3528,8 +3618,15 @@ function cfxZones.initLink(theZone)
|
|||||||
local dz = 0
|
local dz = 0
|
||||||
if theZone.useOffset or theZone.useHeading then
|
if theZone.useOffset or theZone.useHeading then
|
||||||
local A = cfxZones.getDCSOrigin(theZone)
|
local A = cfxZones.getDCSOrigin(theZone)
|
||||||
|
if not A.x then
|
||||||
|
trigger.action.outText("+++ zones: initlink - can't access orig pos.x for A", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
local B = dcsCommon.getOrigPositionByID(theZone.linkedUID)
|
local B = dcsCommon.getOrigPositionByID(theZone.linkedUID)
|
||||||
|
if not B.x then
|
||||||
|
trigger.action.outText("+++ zones: initlink - can't access orig.x unit for B", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
local delta = dcsCommon.vSub(A,B)
|
local delta = dcsCommon.vSub(A,B)
|
||||||
dx = delta.x
|
dx = delta.x
|
||||||
dz = delta.z
|
dz = delta.z
|
||||||
@ -3592,7 +3689,8 @@ function cfxZones.startMovingZones()
|
|||||||
trigger.action.outText("WARNING: Zone <" .. aZone.name .. ">: cannot resolve linked unit ID <" .. theID .. ">", 30)
|
trigger.action.outText("WARNING: Zone <" .. aZone.name .. ">: cannot resolve linked unit ID <" .. theID .. ">", 30)
|
||||||
lU = "***DML link err***"
|
lU = "***DML link err***"
|
||||||
end
|
end
|
||||||
aZone.linkedUID = lU
|
--aZone.linkedUID = lU -- wrong! must be UID, not name
|
||||||
|
aZone.linkedUID = theID
|
||||||
elseif aZone:hasProperty("linkedUnit") then
|
elseif aZone:hasProperty("linkedUnit") then
|
||||||
lU = aZone:getZoneProperty("linkedUnit") -- getString: name of unit
|
lU = aZone:getZoneProperty("linkedUnit") -- getString: name of unit
|
||||||
local luid = dcsCommon.unitName2ID[lU]
|
local luid = dcsCommon.unitName2ID[lU]
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
dcsCommon = {}
|
dcsCommon = {}
|
||||||
dcsCommon.version = "3.1.4"
|
dcsCommon.version = "3.1.5"
|
||||||
--[[-- VERSION HISTORY
|
--[[-- VERSION HISTORY
|
||||||
3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false
|
3.0.0 - removed bad bug in stringStartsWith, only relevant if caseSensitive is false
|
||||||
- point2text new intsOnly option
|
- point2text new intsOnly option
|
||||||
@ -33,6 +33,8 @@ dcsCommon.version = "3.1.4"
|
|||||||
- new DCS Patch section
|
- new DCS Patch section
|
||||||
3.1.4 - new processStringWildcardsForUnit
|
3.1.4 - new processStringWildcardsForUnit
|
||||||
- integrated into std wildcard proccing, unit optional
|
- integrated into std wildcard proccing, unit optional
|
||||||
|
3.1.5 - more verbosity on unitID2X
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
-- dcsCommon is a library of common lua functions
|
-- dcsCommon is a library of common lua functions
|
||||||
@ -155,6 +157,9 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
function dcsCommon.getOrigPositionByID(theID)
|
function dcsCommon.getOrigPositionByID(theID)
|
||||||
|
if not dcsCommon.unitID2X[theID] then
|
||||||
|
trigger.action.outText("common: getOrigPos - no unit by id for <" .. theID .. ">, type is <" .. type(theID) .. ">", 30)
|
||||||
|
end
|
||||||
local p = {x=dcsCommon.unitID2X[theID], y=0, z=dcsCommon.unitID2Y[theID]}
|
local p = {x=dcsCommon.unitID2X[theID], y=0, z=dcsCommon.unitID2Y[theID]}
|
||||||
return p
|
return p
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
fogger = {}
|
fogger = {}
|
||||||
fogger.version = "1.0.0"
|
fogger.version = "1.1.0"
|
||||||
fogger.requiredLibs = {
|
fogger.requiredLibs = {
|
||||||
"dcsCommon",
|
"dcsCommon",
|
||||||
"cfxZones",
|
"cfxZones",
|
||||||
@ -10,6 +10,8 @@ fogger.zones = {}
|
|||||||
A DML module (c) 2024 by Christian FRanz
|
A DML module (c) 2024 by Christian FRanz
|
||||||
|
|
||||||
- 1.0.0 - Initial version
|
- 1.0.0 - Initial version
|
||||||
|
- 1.1.0 - added lcl attribute
|
||||||
|
- added onStart
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
function fogger.createFogZone(theZone)
|
function fogger.createFogZone(theZone)
|
||||||
@ -22,7 +24,25 @@ function fogger.createFogZone(theZone)
|
|||||||
if theZone:hasProperty("thickness") then
|
if theZone:hasProperty("thickness") then
|
||||||
theZone.thickMin, theZone.thickMax = theZone:getPositiveRangeFromZoneProperty("thickness", 0,0)
|
theZone.thickMin, theZone.thickMax = theZone:getPositiveRangeFromZoneProperty("thickness", 0,0)
|
||||||
end
|
end
|
||||||
|
theZone.lcl = theZone:getBoolFromZoneProperty("lcl", false)
|
||||||
theZone.durMin, theZone.durMax = theZone:getPositiveRangeFromZoneProperty ("duration", 1, 1)
|
theZone.durMin, theZone.durMax = theZone:getPositiveRangeFromZoneProperty ("duration", 1, 1)
|
||||||
|
if theZone:hasProperty("onStart") then
|
||||||
|
--trigger.action.outText("+++fog: zone <" .. theZone.name .. "> HAS 'onStart' attribute", 30)
|
||||||
|
theZone.onStart = theZone:getBoolFromZoneProperty("onStart", false)
|
||||||
|
if theZone.onStart then
|
||||||
|
if theZone.verbose then
|
||||||
|
trigger.action.outText("+++fog: will schedule onStart fog in zone <" .. theZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
timer.scheduleFunction(fogger.doFog, theZone, timer.getTime() + 0.5)
|
||||||
|
else
|
||||||
|
--trigger.action.outText("+++ fog: onstart turned OFF", 30)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--trigger.action.outText("+++fog: zone <" .. theZone.name .. "> no 'onStart' attribute, turned off", 30)
|
||||||
|
end
|
||||||
|
if theZone.verbose then
|
||||||
|
trigger.action.outText("+++fog: zone <" .. theZone.name .. "> processed.", 30)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function fogger.doFog(theZone)
|
function fogger.doFog(theZone)
|
||||||
@ -31,7 +51,11 @@ function fogger.doFog(theZone)
|
|||||||
if vis < 100 then vis = 0 end
|
if vis < 100 then vis = 0 end
|
||||||
local thick = world.weather.getFogThickness()
|
local thick = world.weather.getFogThickness()
|
||||||
if theZone.thickMin then thick = dcsCommon.randomBetween(theZone.thickMin, theZone.thickMax) end
|
if theZone.thickMin then thick = dcsCommon.randomBetween(theZone.thickMin, theZone.thickMax) end
|
||||||
if thick < 100 then thick = 0 end
|
if thick < 100 then thick = 0
|
||||||
|
elseif theZone.lcl then
|
||||||
|
local p = theZone:getPoint()
|
||||||
|
thick = thick + land.getHeight({x = p.x, y = p.z})
|
||||||
|
end
|
||||||
local dur = dcsCommon.randomBetween(theZone.durMin, theZone.durMax)
|
local dur = dcsCommon.randomBetween(theZone.durMin, theZone.durMax)
|
||||||
if theZone.verbose or fogger.verbose then
|
if theZone.verbose or fogger.verbose then
|
||||||
trigger.action.outText("+++fog: will set fog vis = <" .. vis .. ">, thick = <" .. thick .. ">, transition <" .. dur .. "> secs", 30)
|
trigger.action.outText("+++fog: will set fog vis = <" .. vis .. ">, thick = <" .. thick .. ">, transition <" .. dur .. "> secs", 30)
|
||||||
|
|||||||
172
modules/smoking.lua
Normal file
172
modules/smoking.lua
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
smoking = {}
|
||||||
|
smoking.version = "1.0.0"
|
||||||
|
smoking.requiredLibs = { -- a DML module (c) 2025 by Christian Franz
|
||||||
|
"dcsCommon",
|
||||||
|
"cfxZones",
|
||||||
|
}
|
||||||
|
smoking.zones = {}
|
||||||
|
smoking.roots = {} -- groups that have already been inited
|
||||||
|
|
||||||
|
--[[-- VERSION HISTORY
|
||||||
|
- 1.0.0 initial version
|
||||||
|
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
-- FOR NOW REQUIRES SINGLE-UNIT PLAYER GROUPS
|
||||||
|
function smoking.createSmokingZone(theZone)
|
||||||
|
theZone.smColor = theZone:getSmokeColorNumberFromZoneProperty("smoking", "white")
|
||||||
|
if theZone.smColor > 0 then theZone.smColor = theZone.smColor + 1 end
|
||||||
|
theZone.smAlt = theZone:getNumberFromZoneProperty("alt", 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- event handler
|
||||||
|
function smoking:onEvent(theEvent)
|
||||||
|
if not theEvent then return end
|
||||||
|
if not theEvent.initiator then return end
|
||||||
|
local theUnit = theEvent.initiator
|
||||||
|
if not theUnit.getName then return end
|
||||||
|
if not theUnit.getPlayerName then return end
|
||||||
|
if not theUnit:getPlayerName() then return end
|
||||||
|
if not theUnit.getGroup then return end
|
||||||
|
local theGroup = theUnit:getGroup()
|
||||||
|
if not theGroup then return end
|
||||||
|
if theEvent.id == 15 and smoking.hasGUI then -- birth and gui on
|
||||||
|
local theColor = nil
|
||||||
|
local theAlt = smoking.smAlt -- default to global
|
||||||
|
-- see if we even want to install a menu
|
||||||
|
if dcsCommon.getSizeOfTable(smoking.zones) > 0 then
|
||||||
|
p = theUnit:getPoint()
|
||||||
|
for idx, theZone in pairs(smoking.zones) do
|
||||||
|
if theZone:pointInZone(p) then
|
||||||
|
theColor = theZone.smColor
|
||||||
|
theAlt = theZone.smAlt
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not theColor then return end
|
||||||
|
else
|
||||||
|
theColor = smoking.color -- use global color
|
||||||
|
end
|
||||||
|
if theColor < 1 then theColor = math.random(1, 5) end
|
||||||
|
local gName = theGroup:getName()
|
||||||
|
if smoking.roots[gName] then return end -- already inited
|
||||||
|
local uName = theUnit:getName()
|
||||||
|
local gID = theGroup:getID()
|
||||||
|
|
||||||
|
-- remove old group menu
|
||||||
|
if smoking.roots[gName] then
|
||||||
|
missionCommands.removeItemForGroup(gID, smoking.roots[gName])
|
||||||
|
end
|
||||||
|
|
||||||
|
-- handle main menu
|
||||||
|
local mainMenu = nil
|
||||||
|
if smoking.mainMenu then
|
||||||
|
mainMenu = radioMenu.getMainMenuFor(smoking.mainMenu)
|
||||||
|
end
|
||||||
|
|
||||||
|
local root = missionCommands.addSubMenuForGroup(gID, smoking.menuName, mainMenu)
|
||||||
|
smoking.roots[gName] = root
|
||||||
|
|
||||||
|
local args = {}
|
||||||
|
args.theUnit = theUnit
|
||||||
|
args.uName = uName
|
||||||
|
args.gID = gID
|
||||||
|
args.gName = gName
|
||||||
|
args.coa = theGroup:getCoalition()
|
||||||
|
args.smAlt = theAlt
|
||||||
|
args.smColor = theColor
|
||||||
|
-- now add the submenus for convoys
|
||||||
|
local m = missionCommands.addCommandForGroup(gID, "Smoke ON", root, smoking.redirectSmoke, args)
|
||||||
|
args = {} -- create new!! ref
|
||||||
|
args.theUnit = theUnit
|
||||||
|
args.uName = uName
|
||||||
|
args.gID = gID
|
||||||
|
args.gName = gName
|
||||||
|
args.coa = theGroup:getCoalition()
|
||||||
|
args.smAlt = 0
|
||||||
|
args.smColor = 0 -- color 0 = turn off
|
||||||
|
m = missionCommands.addCommandForGroup(gID, "Turn OFF smoke", root, smoking.redirectSmoke, args)
|
||||||
|
end -- if birth
|
||||||
|
end
|
||||||
|
|
||||||
|
function smoking.redirectSmoke(args) -- escape debug confines
|
||||||
|
timer.scheduleFunction(smoking.doSmoke, args, timer.getTime() + 0.1)
|
||||||
|
end
|
||||||
|
|
||||||
|
function smoking.doSmoke(args)
|
||||||
|
local uName = args.uName
|
||||||
|
local theColor = args.smColor
|
||||||
|
local theAlt = args.smAlt
|
||||||
|
trigger.action.ctfColorTag(uName, theColor, 0) -- , theAlt)
|
||||||
|
if smoking.verbose then
|
||||||
|
trigger.action.outText("+++smk: turning smoke trail for <" .. uName .. "> to <" .. theColor .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- config
|
||||||
|
function smoking.readConfigZone()
|
||||||
|
-- note: must match exactly!!!!
|
||||||
|
local theZone = cfxZones.getZoneByName("smokingConfig")
|
||||||
|
if not theZone then
|
||||||
|
theZone = cfxZones.createSimpleZone("smokingConfig")
|
||||||
|
end
|
||||||
|
smoking.ups = theZone:getNumberFromZoneProperty("ups", 1)
|
||||||
|
smoking.name = "smoking"
|
||||||
|
smoking.verbose = theZone.verbose
|
||||||
|
smoking.color = theZone:getSmokeColorNumberFromZoneProperty("color", "white" )
|
||||||
|
if smoking.color >= 0 then smoking.color = smoking.color + 1 end -- yeah, ctf aircraft smoke and ground smoke are NOT the same, ctf is gnd + 1. huzzah!
|
||||||
|
smoking.smAlt = theZone:getNumberFromZoneProperty("alt", 0)
|
||||||
|
smoking.menuName = theZone:getStringFromZoneProperty("menuName", "Smoke Trail")
|
||||||
|
smoking.hasGUI = theZone:getBoolFromZoneProperty("GUI", true)
|
||||||
|
if theZone:hasProperty("attachTo:") then
|
||||||
|
local attachTo = theZone:getStringFromZoneProperty("attachTo:", "<none>")
|
||||||
|
if radioMenu then -- requires optional radio menu to have loaded
|
||||||
|
local mainMenu = radioMenu.mainMenus[attachTo]
|
||||||
|
if mainMenu then
|
||||||
|
smoking.mainMenu = mainMenu
|
||||||
|
else
|
||||||
|
trigger.action.outText("+++smoking: cannot find super menu <" .. attachTo .. ">", 30)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
trigger.action.outText("+++smoking: REQUIRES radioMenu to run before smoking. 'AttachTo:' ignored.", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- go go go
|
||||||
|
function smoking.start()
|
||||||
|
-- lib check
|
||||||
|
if not dcsCommon.libCheck then
|
||||||
|
trigger.action.outText("smoking requires dcsCommon", 30)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if not dcsCommon.libCheck("smoking", smoking.requiredLibs) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- read config
|
||||||
|
smoking.readConfigZone()
|
||||||
|
-- process "fog?" Zones
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("smoking")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
smoking.createSmokingZone(aZone)
|
||||||
|
smoking.zones[aZone.name] = aZone
|
||||||
|
end
|
||||||
|
-- hook into events
|
||||||
|
world.addEventHandler(smoking)
|
||||||
|
|
||||||
|
trigger.action.outText("smoking v" .. smoking.version .. " started.", 30)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- let's go!
|
||||||
|
if not smoking.start() then
|
||||||
|
trigger.action.outText("smoking aborted: error on start", 30)
|
||||||
|
smoking = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--[[--
|
||||||
|
To Do:
|
||||||
|
- smoking zones where aircraft automatically turn on/off their smoke
|
||||||
|
- different smoke colors for red and blue in autosmoke zones
|
||||||
|
--]]--
|
||||||
BIN
tutorial & demo missions/demo - The smoke is ON.miz
Normal file
BIN
tutorial & demo missions/demo - The smoke is ON.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user