mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
1.1.5
LZ, fireFX, smrGUI
This commit is contained in:
parent
58d81e162f
commit
46712cba20
Binary file not shown.
Binary file not shown.
259
modules/LZ.lua
259
modules/LZ.lua
@ -1,5 +1,5 @@
|
||||
LZ = {}
|
||||
LZ.version = "0.0.0"
|
||||
LZ.version = "1.0.0"
|
||||
LZ.verbose = false
|
||||
LZ.ups = 1
|
||||
LZ.requiredLibs = {
|
||||
@ -9,10 +9,12 @@ LZ.requiredLibs = {
|
||||
LZ.LZs = {}
|
||||
|
||||
--[[--
|
||||
LZ - module to generate flag events when a unit lands to takes off inside
|
||||
the zone.
|
||||
|
||||
Version History
|
||||
1.0.0 - initial version
|
||||
|
||||
|
||||
--]]--
|
||||
|
||||
function LZ.addLZ(theZone)
|
||||
@ -27,22 +29,70 @@ function LZ.getLZByName(aName)
|
||||
trigger.action.outText("+++LZ: no LZ with name <" .. aName ..">", 30)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--
|
||||
-- read zone
|
||||
--
|
||||
function LZ.createLZWithZone(theZone)
|
||||
-- read main trigger
|
||||
theZone.triggerLZFlag = cfxZones.getStringFromZoneProperty(theZone, "lz!", "*<none>")
|
||||
|
||||
-- TriggerMethod: common and specific synonym
|
||||
theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
|
||||
|
||||
if cfxZones.hasProperty(theZone, "lzTriggerMethod") then
|
||||
theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "lzMethod", "change")
|
||||
if cfxZones.hasProperty(theZone, "landed!") then
|
||||
theZone.lzLanded = cfxZones.getStringFromZoneProperty(theZone, "landed!", "*<none>")
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "departed!") then
|
||||
theZone.lzDeparted = cfxZones.getStringFromZoneProperty(theZone, "departed!", "*<none>")
|
||||
end
|
||||
|
||||
-- who to look for
|
||||
theZone.coalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0)
|
||||
-- units / groups / types
|
||||
if cfxZones.hasProperty(theZone, "group") then
|
||||
theZone.lzGroups = cfxZones.getStringFromZoneProperty(theZone, "group", "<none>")
|
||||
theZone.lzGroups = dcsCommon.string2Array(theZone.lzGroups, ",", true)
|
||||
elseif cfxZones.hasProperty(theZone, "groups") then
|
||||
theZone.lzGroups = cfxZones.getStringFromZoneProperty(theZone, "groups", "<none>")
|
||||
theZone.lzGroups = dcsCommon.string2Array(theZone.lzGroups, ",", true)
|
||||
elseif cfxZones.hasProperty(theZone, "type") then
|
||||
theZone.lzTypes = cfxZones.getStringFromZoneProperty(theZone, "type", "ALL")
|
||||
theZone.lzTypes = dcsCommon.string2Array(theZone.lzTypes, ",", true)
|
||||
elseif cfxZones.hasProperty(theZone, "types") then
|
||||
theZone.lzTypes = cfxZones.getStringFromZoneProperty(theZone, "types", "ALL")
|
||||
theZone.lzTypes = dcsCommon.string2Array(theZone.lzTypes, ",", true)
|
||||
elseif cfxZones.hasProperty(theZone, "unit") then
|
||||
theZone.lzUnits = cfxZones.getStringFromZoneProperty(theZone, "unit", "none")
|
||||
theZone.lzUnits = dcsCommon.string2Array(theZone.lzUnits, ",", true)
|
||||
elseif cfxZones.hasProperty(theZone, "units") then
|
||||
theZone.lzUnits = cfxZones.getStringFromZoneProperty(theZone, "units", "none")
|
||||
theZone.lzUnits = dcsCommon.string2Array(theZone.lzUnits, ",", true)
|
||||
end
|
||||
|
||||
theZone.lzPlayerOnly = cfxZones.getBoolFromZoneProperty(theZone, "playerOnly", false)
|
||||
|
||||
-- output method
|
||||
theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "inc")
|
||||
if cfxZones.hasProperty(theZone, "outputMethod") then
|
||||
theZone.lzMethod = cfxZones.getStringFromZoneProperty(theZone, "outputMethod", "inc")
|
||||
end
|
||||
|
||||
-- trigger method
|
||||
theZone.lzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "lzTriggerMethod", "change")
|
||||
if cfxZones.hasProperty(theZone, "triggerMethod") then
|
||||
theZone.lzTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
||||
end
|
||||
|
||||
|
||||
-- pause / unpause
|
||||
theZone.lzIsPaused = cfxZones.getBoolFromZoneProperty(theZone, "isPaused", false)
|
||||
|
||||
if cfxZones.hasProperty(theZone, "pause?") then
|
||||
theZone.lzPause = cfxZones.getStringFromZoneProperty(theZone, "pause?", "*<none>")
|
||||
theZone.lzLastPause = cfxZones.getFlagValue(theZone.lzPause, theZone)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "continue?") then
|
||||
theZone.lzContinue = cfxZones.getStringFromZoneProperty(theZone, "continue?", "*<none>")
|
||||
theZone.lzLastContinue = cfxZones.getFlagValue(theZone.lzContinue, theZone)
|
||||
end
|
||||
|
||||
if LZ.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++LZ: new LZ <".. theZone.name ..">", 30)
|
||||
@ -50,45 +100,196 @@ function LZ.createLZWithZone(theZone)
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- MAIN ACTION
|
||||
--
|
||||
function LZ.processUpdate(theZone)
|
||||
function LZ.nameMatchForArray(theName, theArray, wildcard)
|
||||
theName = dcsCommon.trim(theName)
|
||||
if not theName then return false end
|
||||
if not theArray then return false end
|
||||
theName = string.upper(theName) -- case insensitive
|
||||
|
||||
-- trigger.action.outText("enter name match with <" .. theName .. "> look for match in <" .. dcsCommon.array2string(theArray) .. "> and wc <" .. wildcard .. ">", 30)
|
||||
for idx, entry in pairs(theArray) do
|
||||
|
||||
if wildcard and dcsCommon.stringEndsWith(entry, wildcard) then
|
||||
entry = dcsCommon.removeEnding(entry, wildcard)
|
||||
-- trigger.action.outText("trying to WC-match <" .. theName .. "> with <" .. entry .. ">", 30)
|
||||
if dcsCommon.stringStartsWith(theName, entry) then
|
||||
-- theName "hi there" matches wildcarded entry "hi*"
|
||||
return true
|
||||
end
|
||||
else
|
||||
-- trigger.action.outText("trying to simple-match <" .. theName .. "> with <" .. entry .. ">", 30)
|
||||
if theName == entry then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
-- trigger.action.outText ("no match for <" .. theName .. ">", 30)
|
||||
return false
|
||||
end
|
||||
|
||||
--
|
||||
-- Misc Processing
|
||||
--
|
||||
function LZ.unitIsInterestingForZone(theUnit, theZone)
|
||||
--trigger.action.outText("enter isInterestingB4pause for <" .. theUnit:getName() .. ">", 40)
|
||||
|
||||
-- see if zone is interested in this unit.
|
||||
if theZone.isPaused then
|
||||
return false
|
||||
end
|
||||
-- trigger.action.outText("enter isinteresting for <" .. theUnit:getName() .. ">", 40)
|
||||
if theZone.lzPlayerOnly then
|
||||
if not dcsCommon.isPlayerUnit(theUnit) then
|
||||
if theZone.verbose or LZ.verbose then
|
||||
trigger.action.outText("+++LZ: unit <" .. theUnit:getName() .. "> arriving/departing <" .. theZone.name .. "> is not a player unit", 30)
|
||||
end
|
||||
return false
|
||||
else
|
||||
-- trigger.action.outText("player match!", 30)
|
||||
end
|
||||
end
|
||||
|
||||
if theZone.coalition > 0 then
|
||||
local theGroup = theUnit:getGroup()
|
||||
local coa = theGroup:getCoalition()
|
||||
if coa ~= theZone.coalition then
|
||||
if theZone.verbose or LZ.verbose then
|
||||
trigger.action.outText("+++LZ: unit <" .. theUnit:getName() .. "> arriving/departing <" .. theZone.name .. "> does not match coa <" .. theZone.coalition .. ">", 30)
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
-- if we get here, we are filtered for coa and player
|
||||
if theZone.lzUnits then
|
||||
local theName = theUnit:getName()
|
||||
return LZ.nameMatchForArray(theName, theZone.lzUnits, "*")
|
||||
|
||||
elseif theZone.lzGroups then
|
||||
local theGroup = theUnit:getGroup()
|
||||
local theName = theGroup:getName()
|
||||
return LZ.nameMatchForArray(theName, theZone.lzGroups, "*")
|
||||
|
||||
elseif theZone.lzTypes then
|
||||
local theType = theUnit:getTypeName()
|
||||
local theGroup = theUnit:getGroup()
|
||||
local cat = theGroup:getCategory() -- can't trust unit:getCategory
|
||||
local coa = theGroup:getCoalition()
|
||||
for idx, aType in pairs (theZone.lzTypes) do
|
||||
|
||||
if aType == "ANY" or aType == "ALL" then
|
||||
return true
|
||||
|
||||
elseif aType == "HELO" or aType == "HELICOPTER" or aType == "HELICOPTERS" or aType == "HELOS" then
|
||||
if cat == 1 then
|
||||
return true
|
||||
end
|
||||
elseif aType == "PLANE" or aType == "PLANES" then
|
||||
if cat == 0 then
|
||||
return true
|
||||
end
|
||||
else
|
||||
if theType == aType then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end -- for all types
|
||||
|
||||
return false -- not a single match
|
||||
else
|
||||
-- we can return true since player and coa mismatch
|
||||
-- have already been filtered
|
||||
--[[-- -- neither type, unit, nor group
|
||||
local theGroup = theUnit:getGroup()
|
||||
local coa = theGroup:getCoalition()
|
||||
--
|
||||
--]]--
|
||||
return true -- theZone.coalition == coa end
|
||||
end
|
||||
|
||||
trigger.action.outText("+++LZ: unknown attribute check for <" .. theZone.name .. ">", 30)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--
|
||||
-- Event Handling
|
||||
--
|
||||
function LZ:onEvent(event)
|
||||
-- only interested in S_EVENT_BASE_CAPTURED events
|
||||
if event.id ~= world.event.S_EVENT_BASE_CAPTURED then
|
||||
-- make sure we have an initiator
|
||||
if not event.initiator then return end
|
||||
|
||||
-- only interested in S_EVENT_TAKEOFF and events
|
||||
if event.id ~= world.event.S_EVENT_TAKEOFF and
|
||||
event.id ~= world.event.S_EVENT_LAND then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
--if LZ.verbose or true then
|
||||
-- trigger.action.outText("+++LZ: on event proccing", 30)
|
||||
--end
|
||||
|
||||
local theUnit = event.initiator
|
||||
if not Unit.isExist(theUnit) then return end
|
||||
local p = theUnit:getPoint()
|
||||
|
||||
--if LZ.verbose or true then
|
||||
-- trigger.action.outText("+++LZ: before iterating zones", 30)
|
||||
--end
|
||||
|
||||
for idx, aZone in pairs(LZ.LZs) do
|
||||
-- check if landed inside and of correct type, colition, name whatever
|
||||
-- see if inside the zone
|
||||
local inZone, percent, dist = cfxZones.pointInZone(p, aZone)
|
||||
if inZone then
|
||||
-- see if this unit interests us at all
|
||||
if LZ.unitIsInterestingForZone(theUnit, aZone) then
|
||||
-- interesting unit in zone triggered the event
|
||||
if aZone.lzDeparted and event.id == world.event.S_EVENT_TAKEOFF then
|
||||
if LZ.verbose or aZone.verbose then
|
||||
trigger.action.outText("+++LZ: detected departure from <" .. aZone.name .. ">", 30)
|
||||
end
|
||||
cfxZones.pollFlag(aZone.lzDeparted, aZone.lzMethod, aZone)
|
||||
end
|
||||
|
||||
if aZone.lzLanded and event.id == world.event.S_EVENT_LAND then
|
||||
if LZ.verbose or aZone.verbose then
|
||||
trigger.action.outText("+++LZ: detected landing in <" .. aZone.name .. ">", 30)
|
||||
end
|
||||
cfxZones.pollFlag(aZone.lzLanded, aZone.lzMethod, aZone)
|
||||
end
|
||||
end -- if interesting
|
||||
else
|
||||
if LZ.verbose or true then
|
||||
-- trigger.action.outText("+++LZ: unit <" .. theUnit:getName() .. "> not in zone <" .. aZone.name .. ">", 30)
|
||||
end
|
||||
|
||||
end
|
||||
end -- if in zone
|
||||
end -- end for
|
||||
end
|
||||
|
||||
--
|
||||
-- Update
|
||||
--
|
||||
|
||||
function LZ.update()
|
||||
-- call me in a second to poll triggers
|
||||
timer.scheduleFunction(LZ.update, {}, timer.getTime() + 1/LZ.ups)
|
||||
|
||||
for idx, aZone in pairs(LZ.LZs) do
|
||||
-- see if we are triggered
|
||||
if cfxZones.testZoneFlag(aZone, aZone.triggerLZFlag, aZone.LZTriggerMethod, "lastTriggerLZValue") then
|
||||
-- see if we are being paused or unpaused
|
||||
if cfxZones.testZoneFlag(aZone, aZone.lzPause, aZone.LZTriggerMethod, "lzLastPause") then
|
||||
if LZ.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++LZ: triggered on main? for <".. aZone.name ..">", 30)
|
||||
trigger.action.outText("+++LZ: triggered pause? for <".. aZone.name ..">", 30)
|
||||
end
|
||||
LZ.processUpdate(aZone)
|
||||
aZone.isPaused = true
|
||||
end
|
||||
|
||||
if cfxZones.testZoneFlag(aZone, aZone.lzContinue, aZone.LZTriggerMethod, "lzLastContinue") then
|
||||
if LZ.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++LZ: triggered continue? for <".. aZone.name ..">", 30)
|
||||
end
|
||||
aZone.isPaused = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
@ -97,12 +298,13 @@ end
|
||||
function LZ.readConfigZone()
|
||||
local theZone = cfxZones.getZoneByName("LZConfig")
|
||||
if not theZone then
|
||||
theZone = cfxZones.createSimpleZone(LZConfig)
|
||||
if LZ.verbose then
|
||||
trigger.action.outText("+++LZ: NO config zone!", 30)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
LZ.lzCooldown = cfxZones.getNumberFromZoneProperty(theZone, "cooldown", 20)
|
||||
LZ.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||
|
||||
if LZ.verbose then
|
||||
@ -125,12 +327,15 @@ function LZ.start()
|
||||
|
||||
-- process LZ Zones
|
||||
-- old style
|
||||
local attrZones = cfxZones.getZonesWithAttributeNamed("lz!")
|
||||
local attrZones = cfxZones.getZonesWithAttributeNamed("lz")
|
||||
for k, aZone in pairs(attrZones) do
|
||||
LZ.createLZWithZone(aZone) -- process attributes
|
||||
LZ.addLZ(aZone) -- add to list
|
||||
end
|
||||
|
||||
-- connect event handler
|
||||
world.addEventHandler(LZ)
|
||||
|
||||
-- start update
|
||||
LZ.update()
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
cloneZones = {}
|
||||
cloneZones.version = "1.5.4"
|
||||
cloneZones.version = "1.5.5"
|
||||
cloneZones.verbose = false
|
||||
cloneZones.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
@ -61,7 +61,7 @@ cloneZones.allCObjects = {} -- all clones objects
|
||||
1.5.2 - fixed bug in trackWith: referencing wrong cloner
|
||||
1.5.3 - centerOnly/wholeGroups attribute for rndLoc, rndHeading and onRoad
|
||||
1.5.4 - parking for aircraft processing when cloning from template
|
||||
|
||||
1.5.5 - removed some verbosity
|
||||
|
||||
|
||||
--]]--
|
||||
@ -1053,7 +1053,7 @@ function cloneZones.spawnWithTemplateForZone(theZone, spawnZone)
|
||||
end
|
||||
|
||||
function cloneZones.spawnWithCloner(theZone)
|
||||
trigger.action.outText("+++clnZ: enter spawnWithCloner for <" .. theZone.name .. ">", 30)
|
||||
-- trigger.action.outText("+++clnZ: enter spawnWithCloner for <" .. theZone.name .. ">", 30)
|
||||
if not theZone then
|
||||
trigger.action.outText("+++clnZ: nil zone on spawnWithCloner", 30)
|
||||
return
|
||||
@ -1232,7 +1232,7 @@ end
|
||||
function cloneZones.doOnStart()
|
||||
for idx, theZone in pairs(cloneZones.cloners) do
|
||||
if theZone.onStart then
|
||||
trigger.action.outText("+++clnZ: onStart true for <" .. theZone.name .. ">", 30)
|
||||
-- trigger.action.outText("+++clnZ: onStart true for <" .. theZone.name .. ">", 30)
|
||||
if theZone.isStarted then
|
||||
if cloneZones.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++clnz: onStart pre-empted for <" .. theZone.name .. "> by persistence", 30)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
dcsCommon = {}
|
||||
dcsCommon.version = "2.7.2"
|
||||
dcsCommon.version = "2.7.4"
|
||||
--[[-- VERSION HISTORY
|
||||
2.2.6 - compassPositionOfARelativeToB
|
||||
- clockPositionOfARelativeToB
|
||||
@ -98,6 +98,9 @@ dcsCommon.version = "2.7.2"
|
||||
new decFlag()
|
||||
nil trap in stringStartsWith()
|
||||
new getClosestFreeSlotForCatInAirbaseTo()
|
||||
2.7.3 - new string2Array()
|
||||
- additional guard for isPlayerUnit
|
||||
2.7.4 - new array2string()
|
||||
|
||||
--]]--
|
||||
|
||||
@ -1853,6 +1856,33 @@ end
|
||||
return trimmedArray
|
||||
end
|
||||
|
||||
function dcsCommon.string2Array(inString, deli, uCase)
|
||||
if not inString then return {} end
|
||||
if not deli then return {} end
|
||||
if not uCase then uCase = false end
|
||||
if uCase then inString = string.upper(inString) end
|
||||
inString = dcsCommon.trim(inString)
|
||||
if dcsCommon.containsString(inString, deli) then
|
||||
local a = dcsCommon.splitString(inString, deli)
|
||||
a = dcsCommon.trimArray(a)
|
||||
return a
|
||||
else
|
||||
return {inString}
|
||||
end
|
||||
end
|
||||
|
||||
function dcsCommon.array2string(inArray, deli)
|
||||
if not deli then deli = "," end
|
||||
if type(inArray) ~= "table" then return "<err in array2string: not an array>" end
|
||||
local s = ""
|
||||
local count = 0
|
||||
for idx, ele in pairs(inArray) do
|
||||
if count > 0 then s = s .. deli .. " " end
|
||||
s = s .. ele
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
function dcsCommon.stripLF(theString)
|
||||
return theString:gsub("[\r\n]", "")
|
||||
end
|
||||
@ -2320,6 +2350,7 @@ end
|
||||
function dcsCommon.isPlayerUnit(theUnit)
|
||||
-- new patch. simply check if getPlayerName returns something
|
||||
if not theUnit then return false end
|
||||
if not Unit.isExist(theUnit) then return end
|
||||
if not theUnit.getPlayerName then return false end -- map/static object
|
||||
local pName = theUnit:getPlayerName()
|
||||
if pName then return true end
|
||||
|
||||
186
modules/fireFX.lua
Normal file
186
modules/fireFX.lua
Normal file
@ -0,0 +1,186 @@
|
||||
fireFX = {}
|
||||
fireFX.version = "1.0.0"
|
||||
fireFX.verbose = false
|
||||
fireFX.ups = 1
|
||||
fireFX.requiredLibs = {
|
||||
"dcsCommon", -- always
|
||||
"cfxZones", -- Zones, of course
|
||||
}
|
||||
fireFX.fx = {}
|
||||
|
||||
function fireFX.addFX(theZone)
|
||||
table.insert(fireFX.fx, theZone)
|
||||
end
|
||||
|
||||
function fireFX.getFXByName(aName)
|
||||
for idx, aZone in pairs(fireFX.fx) do
|
||||
if aName == aZone.name then return aZone end
|
||||
end
|
||||
if fireFX.verbose then
|
||||
trigger.action.outText("+++ffx: no fire FX with name <" .. aName ..">", 30)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- read zone
|
||||
--
|
||||
function fireFX.createFXWithZone(theZone)
|
||||
-- decode size and fire
|
||||
local theSize = cfxZones.getStringFromZoneProperty(theZone, "fireFX", "none")
|
||||
theSize = dcsCommon.trim(theSize)
|
||||
theSize = string.upper(theSize)
|
||||
local fxCode = 1
|
||||
if theSize == "S" or theSize == "SMALL" then fxCode = 1 end
|
||||
if theSize == "M" or theSize == "MEDIUM" then fxCode = 2 end
|
||||
if theSize == "L" or theSize == "LARGE" then fxCode = 3 end
|
||||
if theSize == "H" or theSize == "HUGE" then fxCode = 4 end
|
||||
if theSize == "XL" then fxCode = 4 end
|
||||
|
||||
local theFire = cfxZones.getBoolFromZoneProperty(theZone, "flames", true)
|
||||
|
||||
|
||||
if theFire then
|
||||
-- code stays as it is
|
||||
else
|
||||
-- smoke only
|
||||
fxCode = fxCode + 4
|
||||
end
|
||||
theZone.fxCode = fxCode
|
||||
if theZone.verbose or fireFX.verbose then
|
||||
trigger.action.outText("+++ffx: new FX with code = <" .. fxCode .. ">", 30)
|
||||
end
|
||||
|
||||
theZone.density = cfxZones.getNumberFromZoneProperty(theZone, "density", 0.5)
|
||||
|
||||
if cfxZones.hasProperty(theZone, "start?") then
|
||||
theZone.fxStart = cfxZones.getStringFromZoneProperty(theZone, "start?", "*<none>")
|
||||
theZone.fxLastStart = cfxZones.getFlagValue(theZone.fxStart, theZone)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "stop?") then
|
||||
theZone.fxStop = cfxZones.getStringFromZoneProperty(theZone, "stop?", "*<none>")
|
||||
theZone.fxLastStop = cfxZones.getFlagValue(theZone.fxStop, theZone)
|
||||
end
|
||||
|
||||
theZone.fxOnStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false)
|
||||
theZone.burning = false
|
||||
|
||||
if not theZone.fxOnStart and not theZone.fxStart then
|
||||
trigger.action.outText("+++ffx: WARNING - fireFX Zone <" .. theZone.name .. "> can't be started, neither onStart nor 'start?' defined", 30)
|
||||
end
|
||||
|
||||
-- output method (not needed)
|
||||
|
||||
-- trigger method
|
||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "fxTriggerMethod", "change")
|
||||
if cfxZones.hasProperty(theZone, "triggerMethod") then
|
||||
theZone.fxTriggerMethod = cfxZones.getStringFromZoneProperty(theZone, "triggerMethod", "change")
|
||||
end
|
||||
|
||||
if fireFX.verbose or theZone.verbose then
|
||||
trigger.action.outText("+++ffx: new FX <".. theZone.name ..">", 30)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- Update
|
||||
--
|
||||
function fireFX.startTheFire(theZone)
|
||||
if not theZone.burning then
|
||||
local p = cfxZones.getPoint(theZone)
|
||||
p.y = land.getHeight({x = p.x, y = p.z})
|
||||
local preset = theZone.fxCode
|
||||
local density = theZone.density
|
||||
trigger.action.effectSmokeBig(p, preset, density, theZone.name)
|
||||
theZone.burning = true
|
||||
end
|
||||
end
|
||||
|
||||
function fireFX.extinguishFire(theZone)
|
||||
if theZone.burning then
|
||||
trigger.action.effectSmokeStop(theZone.name)
|
||||
theZone.burning = false
|
||||
end
|
||||
end
|
||||
|
||||
function fireFX.update()
|
||||
-- call me in a second to poll triggers
|
||||
timer.scheduleFunction(fireFX.update, {}, timer.getTime() + 1/fireFX.ups)
|
||||
|
||||
for idx, aZone in pairs(fireFX.fx) do
|
||||
-- see if we are being paused or unpaused
|
||||
if cfxZones.testZoneFlag(aZone, aZone.fxStop, aZone.fxTriggerMethod, "fxLastStop") then
|
||||
if fireFX.verbose or aZone.verbose then
|
||||
trigger.action.outText("+++ffx: triggered 'stop?' for <".. aZone.name ..">", 30)
|
||||
end
|
||||
fireFX.extinguishFire(aZone)
|
||||
end
|
||||
|
||||
if cfxZones.testZoneFlag(aZone, aZone.fxStart, aZone.fxTriggerMethod, "fxLastStart") then
|
||||
if fireFX.verbose or aZone.verbose then
|
||||
trigger.action.outText("+++ffx: triggered 'start?' for <".. aZone.name ..">", 30)
|
||||
end
|
||||
fireFX.startTheFire(aZone)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Config & Start
|
||||
--
|
||||
function fireFX.readConfigZone()
|
||||
local theZone = cfxZones.getZoneByName("fireFXConfig")
|
||||
if not theZone then
|
||||
theZone = cfxZones.createSimpleZone(LZConfig)
|
||||
if fireFX.verbose then
|
||||
trigger.action.outText("+++ffx: NO config zone!", 30)
|
||||
end
|
||||
end
|
||||
|
||||
if fireFX.verbose then
|
||||
trigger.action.outText("+++ffx: read config", 30)
|
||||
end
|
||||
end
|
||||
|
||||
function fireFX.start()
|
||||
-- lib check
|
||||
if not dcsCommon.libCheck then
|
||||
trigger.action.outText("cfx fire FX requires dcsCommon", 30)
|
||||
return false
|
||||
end
|
||||
if not dcsCommon.libCheck("cfx fire FX", fireFX.requiredLibs) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- read config
|
||||
fireFX.readConfigZone()
|
||||
|
||||
-- process fireFX Zones
|
||||
-- old style
|
||||
local attrZones = cfxZones.getZonesWithAttributeNamed("fireFX")
|
||||
for k, aZone in pairs(attrZones) do
|
||||
fireFX.createFXWithZone(aZone) -- process attributes
|
||||
fireFX.addFX(aZone) -- add to list
|
||||
end
|
||||
|
||||
-- handle onStart
|
||||
for idx, theZone in pairs(fireFX.fx) do
|
||||
if theZone.fxOnStart then
|
||||
fireFX.startTheFire(theZone)
|
||||
end
|
||||
end
|
||||
|
||||
-- start update
|
||||
fireFX.update()
|
||||
|
||||
trigger.action.outText("cfx fire FX v" .. fireFX.version .. " started.", 30)
|
||||
return true
|
||||
end
|
||||
|
||||
-- let's go!
|
||||
if not fireFX.start() then
|
||||
trigger.action.outText("cfx fireFX aborted: missing libraries", 30)
|
||||
fireFX = nil
|
||||
end
|
||||
@ -1,5 +1,5 @@
|
||||
limitedAirframes = {}
|
||||
limitedAirframes.version = "1.5.0"
|
||||
limitedAirframes.version = "1.5.1"
|
||||
limitedAirframes.verbose = false
|
||||
limitedAirframes.enabled = true -- can be turned off
|
||||
limitedAirframes.userCanToggle = true -- F10 menu?
|
||||
@ -12,6 +12,7 @@ limitedAirframes.method = "inc"
|
||||
limitedAirframes.warningSound = "Quest Snare 3.wav"
|
||||
limitedAirframes.loseSound = "Death PIANO.wav"
|
||||
limitedAirframes.winSound = "Triumphant Victory.wav"
|
||||
limitedAirframes.announcer = true
|
||||
|
||||
limitedAirframes.requiredLibs = {
|
||||
"dcsCommon", -- common is of course needed for everything
|
||||
@ -50,6 +51,7 @@ limitedAirframes.requiredLibs = {
|
||||
currRed
|
||||
- 1.4.1 - removed dependency to cfxPlayer
|
||||
- 1.5.0 - persistence support
|
||||
- 1.5.1 - new "announcer" attribute
|
||||
|
||||
--]]--
|
||||
|
||||
@ -133,27 +135,17 @@ function limitedAirframes.readConfigZone()
|
||||
end
|
||||
|
||||
-- ok, for each property, load it if it exists
|
||||
-- if cfxZones.hasProperty(theZone, "enabled") then
|
||||
limitedAirframes.enabled = cfxZones.getBoolFromZoneProperty(theZone, "enabled", true)
|
||||
-- end
|
||||
limitedAirframes.enabled = cfxZones.getBoolFromZoneProperty(theZone, "enabled", true)
|
||||
|
||||
limitedAirframes.userCanToggle = cfxZones.getBoolFromZoneProperty(theZone, "userCanToggle", true)
|
||||
|
||||
-- if cfxZones.hasProperty(theZone, "userCanToggle") then
|
||||
limitedAirframes.userCanToggle = cfxZones.getBoolFromZoneProperty(theZone, "userCanToggle", true)
|
||||
-- end
|
||||
|
||||
|
||||
-- if cfxZones.hasProperty(theZone, "maxRed") then
|
||||
limitedAirframes.maxRed = cfxZones.getNumberFromZoneProperty(theZone, "maxRed", -1)
|
||||
-- end
|
||||
|
||||
-- if cfxZones.hasProperty(theZone, "maxBlue") then
|
||||
limitedAirframes.maxBlue = cfxZones.getNumberFromZoneProperty(theZone, "maxBlue", -1)
|
||||
-- end
|
||||
limitedAirframes.maxRed = cfxZones.getNumberFromZoneProperty(theZone, "maxRed", -1)
|
||||
|
||||
limitedAirframes.maxBlue = cfxZones.getNumberFromZoneProperty(theZone, "maxBlue", -1)
|
||||
|
||||
limitedAirframes.numRed = cfxZones.getStringFromZoneProperty(theZone, "#red", "*none")
|
||||
limitedAirframes.numBlue = cfxZones.getStringFromZoneProperty(theZone, "#blue", "*none")
|
||||
|
||||
|
||||
limitedAirframes.redWinsFlag = cfxZones.getStringFromZoneProperty(theZone, "redWins!", "*none")
|
||||
|
||||
if cfxZones.hasProperty(theZone, "redWinsFlag!") then
|
||||
@ -178,6 +170,8 @@ function limitedAirframes.readConfigZone()
|
||||
if cfxZones.hasProperty(theZone, "loseSound") then
|
||||
limitedAirframes.loseSound = cfxZones.getStringFromZoneProperty(theZone, "loseSound", "none")
|
||||
end
|
||||
|
||||
limitedAirframes.announcer = cfxZones.getBoolFromZoneProperty(theZone, "announcer", true)
|
||||
end
|
||||
|
||||
--
|
||||
@ -221,17 +215,18 @@ function limitedAirframes.addPlayerUnit(theUnit)
|
||||
end
|
||||
end
|
||||
limitedAirframes.playerUnits[uName] = pName
|
||||
trigger.action.outTextForCoalition(theSide, desc, 30)
|
||||
if limitedAirframes.announcer then
|
||||
trigger.action.outTextForCoalition(theSide, desc, 30)
|
||||
end
|
||||
end
|
||||
|
||||
function limitedAirframes.killPlayer(pName)
|
||||
limitedAirframes.updatePlayer(pName, "dead")
|
||||
--trigger.action.outText("+++lim: PILOT LOST: " .. pName .. ", NO CSAR", 30)
|
||||
|
||||
end
|
||||
|
||||
function limitedAirframes.killPlayerInUnit(theUnit)
|
||||
limitedAirframes.updatePlayerInUnit(theUnit, "dead")
|
||||
--trigger.action.outText("+++lim: PILOT LOST, NO CSAR", 30)
|
||||
end
|
||||
|
||||
function limitedAirframes.updatePlayerInUnit(theUnit, status)
|
||||
@ -476,7 +471,6 @@ function limitedAirframes.handlePlayerLeftUnit(event)
|
||||
local pName = limitedAirframes.getKnownUnitPilotByUnitName(theUnit:getName())
|
||||
local pStatus = limitedAirframes.getStatusOfPlayerInUnit(theUnit)
|
||||
-- player was already dead and has been accounted for
|
||||
--trigger.action.outText("limAir: Change Plane for player <" .. pName .. "> with status <" .. pStatus .. "> procced.", 30)
|
||||
return
|
||||
end
|
||||
|
||||
@ -485,11 +479,8 @@ function limitedAirframes.handlePlayerLeftUnit(event)
|
||||
local uPos = theUnit:getPoint()
|
||||
local meInside = cfxZones.getZonesContainingPoint(uPos, limitedAirframes.safeZones)
|
||||
local mySide = theUnit:getCoalition()
|
||||
--local speed = dcsCommon.getUnitSpeed(theUnit) -- this can cause problems with carriers, so check if below
|
||||
--local agl = dcsCommon.getUnitAGL(theUnit) -- this will cause problems with FARP and carriers.
|
||||
-- we now check the inAir
|
||||
local isInAir = theUnit:inAir()
|
||||
--trigger.action.outTextForCoalition(mySide, "limAir: safe check for Pilot " .. theUnit:getPlayerName() .. ": agl=" .. agl .. ", speed = " .. speed .. ", air status = " .. dcsCommon.bool2YesNo(isInAir), 30)
|
||||
|
||||
for i=1, #meInside do
|
||||
-- I'm inside all these zones. We look for the first
|
||||
@ -527,19 +518,18 @@ function limitedAirframes.handlePlayerLeftUnit(event)
|
||||
if isInAir then isSafe = false end
|
||||
|
||||
if isSafe then
|
||||
-- if limitedAirframes.verbose then
|
||||
trigger.action.outTextForCoalition(mySide, "Pilot " .. theUnit:getPlayerName() .. " left unit " .. theUnit:getName() .. " legally in zone " .. theSafeZone.name, 30)
|
||||
-- if limitedAirframes.announcer then
|
||||
-- trigger.action.outTextForCoalition(mySide, "Pilot " .. theUnit:getPlayerName() .. " left unit " .. theUnit:getName() .. " legally in zone " .. theSafeZone.name, 30)
|
||||
-- end
|
||||
-- remove from known player planes
|
||||
-- no more limitedAirframes.removePlayerUnit(theUnit)
|
||||
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
-- ditched outside safe harbour
|
||||
-- if limitedAirframes.verbose then
|
||||
if limitedAirframes.announcer then
|
||||
trigger.action.outTextForCoalition(mySide, "Pilot " .. theUnit:getPlayerName() .. " DITCHED unit " .. theUnit:getName() .. " -- PILOT is considered MIA", 30)
|
||||
-- end
|
||||
end
|
||||
|
||||
limitedAirframes.pilotLost(theUnit)
|
||||
if csarManager and csarManager.airframeDitched then
|
||||
@ -559,7 +549,9 @@ function limitedAirframes.pilotEjected(event)
|
||||
local theSide = theUnit:getCoalition()
|
||||
local pilot = limitedAirframes.getKnownUnitPilotByUnit(theUnit)
|
||||
local uName = theUnit:getName()
|
||||
trigger.action.outTextForCoalition(theSide, "Pilot <" .. pilot .. "> ejected from " .. uName .. ", now MIA", 30)
|
||||
if limitedAirframes.announcer then
|
||||
trigger.action.outTextForCoalition(theSide, "Pilot <" .. pilot .. "> ejected from " .. uName .. ", now MIA", 30)
|
||||
end
|
||||
|
||||
local hasLostTheWar = limitedAirframes.pilotLost(theUnit)
|
||||
|
||||
@ -575,7 +567,9 @@ function limitedAirframes.pilotDied(theUnit)
|
||||
local theSide = theUnit:getCoalition()
|
||||
local pilot = limitedAirframes.getKnownUnitPilotByUnit(theUnit)
|
||||
local uName = theUnit:getName()
|
||||
trigger.action.outTextForCoalition(theSide, "Pilot <" .. pilot .. "> is confirmed KIA while controlling " .. uName, 30)
|
||||
if limitedAirframes.announcer then
|
||||
trigger.action.outTextForCoalition(theSide, "Pilot <" .. pilot .. "> is confirmed KIA while controlling " .. uName, 30)
|
||||
end
|
||||
limitedAirframes.pilotLost(theUnit)
|
||||
end
|
||||
|
||||
@ -593,7 +587,7 @@ function limitedAirframes.pilotLost(theUnit)
|
||||
local theSide = theUnit:getCoalition()
|
||||
local pilot = limitedAirframes.getKnownUnitPilotByUnit(theUnit)
|
||||
local uName = theUnit:getName()
|
||||
--trigger.action.outTextForCoalition(theSide, "Pilot <" .. pilot .. "> is confirmed KIA while controlling " .. uName, 30)
|
||||
|
||||
|
||||
if theSide == 1 then -- red
|
||||
theOtherSide = 2
|
||||
@ -605,16 +599,16 @@ function limitedAirframes.pilotLost(theUnit)
|
||||
|
||||
if limitedAirframes.currRed == 0 then
|
||||
trigger.action.outTextForCoalition(theSide, "\nYou have lost almost all of your pilots.\n\nWARNING: Losing any more pilots WILL FAIL THE MISSION\n", 30)
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)--"Quest Snare 3.wav")
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)
|
||||
return false
|
||||
end
|
||||
|
||||
if limitedAirframes.currRed < 0 then
|
||||
-- red have lost all airframes
|
||||
trigger.action.outText("\nREDFORCE has lost all of their pilots.\n\nBLUEFORCE WINS!\n", 30)
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.loseSound) --"Death PIANO.wav")
|
||||
trigger.action.outSoundForCoalition(theOtherSide, limitedAirframes.winSound)--"Triumphant Victory.wav")
|
||||
-- trigger.action.setUserFlag(limitedAirframes.blueWinsFlag, 1 )
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.loseSound)
|
||||
trigger.action.outSoundForCoalition(theOtherSide, limitedAirframes.winSound)
|
||||
|
||||
cfxZones.pollFlag(limitedAirframes.blueWinsFlag, limitedAirframes.method, limitedAirframes.config)
|
||||
return true
|
||||
end
|
||||
@ -629,20 +623,22 @@ function limitedAirframes.pilotLost(theUnit)
|
||||
|
||||
if limitedAirframes.currBlue == 0 then
|
||||
trigger.action.outTextForCoalition(theSide, "\nYou have lost almost all of your pilots.\n\nWARNING: Losing any more pilots WILL FAIL THE MISSION\n", 30)
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)--"Quest Snare 3.wav")
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)
|
||||
return false
|
||||
end
|
||||
if limitedAirframes.currBlue < 0 then
|
||||
-- red have lost all airframes
|
||||
trigger.action.outText("\nBLUEFORCE has lost all of their pilots.\n\nREDFORCE WINS!\n", 30)
|
||||
-- trigger.action.setUserFlag(limitedAirframes.redWinsFlag, 1 )
|
||||
|
||||
cfxZones.pollFlag(limitedAirframes.redWinsFlag, limitedAirframes.method, limitedAirframes.config)
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.loseSound)--"Death PIANO.wav")
|
||||
trigger.action.outSoundForCoalition(theOtherSide, limitedAirframes.winSound)--"Triumphant Victory.wav")
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.loseSound)
|
||||
trigger.action.outSoundForCoalition(theOtherSide, limitedAirframes.winSound)
|
||||
return true
|
||||
end
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)--"Quest Snare 3.wav")
|
||||
trigger.action.outTextForCoalition(theSide, "You have lost a pilot! Remaining: " .. limitedAirframes.currBlue, 30)
|
||||
trigger.action.outSoundForCoalition(theSide, limitedAirframes.warningSound)
|
||||
-- if limitedAirframes.announcer then
|
||||
trigger.action.outTextForCoalition(theSide, "You have lost a pilot! Remaining: " .. limitedAirframes.currBlue, 30)
|
||||
-- end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
persistence = {}
|
||||
persistence.version = "1.0.2"
|
||||
persistence.version = "1.0.3"
|
||||
persistence.ups = 1 -- once every 1 seconds
|
||||
persistence.verbose = false
|
||||
persistence.active = false
|
||||
@ -22,6 +22,8 @@ persistence.requiredLibs = {
|
||||
- cfxZones interface
|
||||
- always output save location
|
||||
1.0.2 - QoL when verbosity is on
|
||||
1.0.3 - no longer always tells " mission saved to"
|
||||
new 'saveNotification" can be off
|
||||
|
||||
|
||||
PROVIDES LOAD/SAVE ABILITY TO MODULES
|
||||
@ -375,9 +377,9 @@ function persistence.doSaveMission()
|
||||
return
|
||||
end
|
||||
|
||||
-- if persistence.verbose then
|
||||
if persistence.saveNotification then
|
||||
trigger.action.outText("+++persistence: mission saved to\n" .. persistence.missionDir .. persistence.saveFileName, 30)
|
||||
-- end
|
||||
end
|
||||
end
|
||||
|
||||
function persistence.noteCleanRestart()
|
||||
@ -470,6 +472,8 @@ function persistence.readConfigZone()
|
||||
|
||||
persistence.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false)
|
||||
|
||||
persistence.saveNotification = cfxZones.getBoolFromZoneProperty(theZone, "saveNotification", true)
|
||||
|
||||
if persistence.verbose then
|
||||
trigger.action.outText("+++persistence: read config", 30)
|
||||
end
|
||||
|
||||
50
server modules/smrGUI.lua
Normal file
50
server modules/smrGUI.lua
Normal file
@ -0,0 +1,50 @@
|
||||
smr = {}
|
||||
smr.restartFlag = "simpleMissionRestart"
|
||||
--
|
||||
-- smr: simple mission restart (server module)
|
||||
-- in your mission, set flag "simpleMissionRestart" to a value < 0 (zero)
|
||||
-- and the server restarts the mission within one second
|
||||
--
|
||||
-- Created 20220902 by cfrag - version 1.0.0
|
||||
--
|
||||
|
||||
-- misc procs
|
||||
function smr.getServerFlagValue(theFlag)
|
||||
-- execute getUserFlag() in server space
|
||||
local val, errNo = net.dostring_in('server', " return trigger.misc.getUserFlag(\""..theFlag.."\"); ")
|
||||
if (not val) and errNo then
|
||||
net.log("smr - can't access flag, dostring_in returned <".. errNo .. ">")
|
||||
return 0
|
||||
else
|
||||
-- dostring_in returns a string, so convert to number
|
||||
return tonumber(val)
|
||||
end
|
||||
end
|
||||
|
||||
function smr.restartMission()
|
||||
local mn = DCS.getMissionFilename( )
|
||||
net.log("+++smr: restarting mission: ".. mn)
|
||||
net.send_chat("+++smr: restarting mission: ".. mn, true)
|
||||
local success = net.load_mission(mn)
|
||||
if not success then
|
||||
net.log("+++smr: FAILED to load <" .. mn .. ">")
|
||||
net.send_chat("+++smr: FAILED to load <" .. mn .. ">", true)
|
||||
end
|
||||
end
|
||||
|
||||
-- main update loop, checked once per secon
|
||||
local lTime = DCS.getModelTime()
|
||||
function smr.onSimulationFrame()
|
||||
if lTime + 1 < DCS.getModelTime() then
|
||||
-- set next time
|
||||
lTime = DCS.getModelTime()
|
||||
-- check to see if the restartFlag is set
|
||||
if not DCS.isServer() then return end
|
||||
if smr.getServerFlagValue(smr.restartFlag) > 0 then
|
||||
smr.restartMission()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- install smr in hooks
|
||||
DCS.setUserCallbacks(smr)
|
||||
BIN
tutorial & demo missions/demo - Depatures and Landings.miz
Normal file
BIN
tutorial & demo missions/demo - Depatures and Landings.miz
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user