Version 2.3.7

"drivable" support for spawners, some QoL, attribute deconflict
This commit is contained in:
Christian Franz 2024-11-21 09:47:12 +01:00
parent b498a4e803
commit 491a9d0838
8 changed files with 21456 additions and 21547 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -1,5 +1,5 @@
cfxZones = {} cfxZones = {}
cfxZones.version = "4.4.3" cfxZones.version = "4.4.4"
-- 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
@ -33,6 +33,7 @@ cfxZones.version = "4.4.3"
-4.4.1 - better verbosity for error in doPollFlag() -4.4.1 - better verbosity for error in doPollFlag()
-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
--]]-- --]]--
-- --
@ -1397,12 +1398,21 @@ end
-- creating units in a zone -- creating units in a zone
function cfxZones.createGroundUnitsInZoneForCoalition (theCoalition, groupName, theZone, theUnits, formation, heading, liveries) function cfxZones.createGroundUnitsInZoneForCoalition (theCoalition, groupName, theZone, theUnits, formation, heading, liveries, drivable)
-- theUnits can be string or table of string -- theUnits can be string or table of string
if not groupName then groupName = "G_"..theZone.name end if not groupName then groupName = "G_"..theZone.name end
if not drivable then drivable = false end
-- group name will be taken from zone name and prependend with "G_" -- group name will be taken from zone name and prependend with "G_"
local theGroup = dcsCommon.createGroundGroupWithUnits(groupName, theUnits, theZone.radius, nil, formation, nil, liveries) local theGroup = dcsCommon.createGroundGroupWithUnits(groupName, theUnits, theZone.radius, nil, formation, nil, liveries)
theGroup.uncontrollable = false -- just for completeness
if drivable then
local units = theGroup.units
for idx, theUnit in pairs(units) do
theUnit.playerCanDrive = drivable
end
end
-- turn the entire formation to heading -- turn the entire formation to heading
if (not heading) then heading = 0 end if (not heading) then heading = 0 end
dcsCommon.rotateGroupData(theGroup, heading) -- currently, group is still at origin, no cx, cy dcsCommon.rotateGroupData(theGroup, heading) -- currently, group is still at origin, no cx, cy

View File

@ -1,5 +1,5 @@
countDown = {} countDown = {}
countDown.version = "2.0.0" countDown.version = "2.0.1"
countDown.verbose = false countDown.verbose = false
countDown.ups = 1 countDown.ups = 1
countDown.requiredLibs = { countDown.requiredLibs = {
@ -17,6 +17,8 @@ countDown.requiredLibs = {
output method defaults to "inc" output method defaults to "inc"
better config parsing better config parsing
cleanup cleanup
2.0.1 - deconflicting 'count?' attribute: removed
--]]-- --]]--
countDown.counters = {} countDown.counters = {}
@ -91,19 +93,21 @@ function countDown.createCountDownWithZone(theZone)
theZone.ctdwnTriggerMethod = theZone:getStringFromZoneProperty("ctdwnTriggerMethod", "change") theZone.ctdwnTriggerMethod = theZone:getStringFromZoneProperty("ctdwnTriggerMethod", "change")
end end
-- trigger flag "count" / "start?" -- using deprecated input "count?"
if theZone:hasProperty("count?") then if theZone:hasProperty("count?") then
theZone.triggerCountFlag = theZone:getStringFromZoneProperty("count?", "<none>") trigger.action.outText("+++WARNING: countdown zone <" .. theZone.name .. "> uses deprecated 'count?' input: ignored, will not trigger.", 30)
elseif theZone:hasProperty("clock?") then else
theZone.triggerCountFlag = theZone:getStringFromZoneProperty("clock?", "<none>") if theZone:hasProperty("clock?") then
-- can also use in? for counting. we always use triggerCountFlag theZone.triggerCountFlag = theZone:getStringFromZoneProperty("clock?", "<none>")
elseif theZone:hasProperty("in?") then elseif theZone:hasProperty("in?") then
theZone.triggerCountFlag = theZone:getStringFromZoneProperty("in?", "<none>") theZone.triggerCountFlag = theZone:getStringFromZoneProperty("in?", "<none>")
end else
trigger.action.outText("+++WARNING: countdown zone <" .. theZone.name .. "> requires input: 'clock?' or 'in?', cannot trigger.", 30)
if theZone.triggerCountFlag then end
theZone.lastCountTriggerValue = cfxZones.getFlagValue(theZone.triggerCountFlag, theZone) if theZone.triggerCountFlag then
end theZone.lastCountTriggerValue = cfxZones.getFlagValue(theZone.triggerCountFlag, theZone)
end
end
-- reset -- reset
if theZone:hasProperty("reset?") then if theZone:hasProperty("reset?") then

View File

@ -1,5 +1,5 @@
income = {} income = {}
income.version = "0.0.0" income.version = "0.9.8"
income.requiredLibs = { income.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
"cfxZones", -- Zones, of course "cfxZones", -- Zones, of course
@ -8,7 +8,6 @@ income.requiredLibs = {
income.sources = {} income.sources = {}
function income.addIncomeZone(theZone) function income.addIncomeZone(theZone)
income.sources[theZone.name] = theZone income.sources[theZone.name] = theZone
end end
@ -35,12 +34,7 @@ function income.update()
-- schedule next round -- schedule next round
timer.scheduleFunction(income.update, {}, timer.getTime() + income.interval) timer.scheduleFunction(income.update, {}, timer.getTime() + income.interval)
local neuI, redI, blueI = income.neutral, income.red, income.blue local neuI, redI, blueI = income.neutral, income.red, income.blue
-- base income
-- bank.addFunds(0, income.neutral)
-- bank.addFunds(1, income.red)
-- bank.addFunds(2, income.blue)
for idx, theZone in pairs(income.sources) do for idx, theZone in pairs(income.sources) do
local ni = income.getIncomeForZoneAndCoa(theZone, 0) local ni = income.getIncomeForZoneAndCoa(theZone, 0)
@ -50,14 +44,26 @@ function income.update()
blueI = blueI + bi blueI = blueI + bi
neuI = neuI + ni neuI = neuI + ni
end end
if income.requirePlayers then
bank.addFunds(0, neuI) local p = coalition.getPlayers(0)
bank.addFunds(1, redI) if #p > 0 then
bank.addFunds(2, blueI) bank.addFunds(0, neuI)
end
p = coalition.getPlayers(1)
if #p > 0 then
bank.addFunds(1, redI)
end
p = coalition.getPlayers(2)
if #p > 0 then
bank.addFunds(2, blueI)
end
else
bank.addFunds(0, neuI)
bank.addFunds(1, redI)
bank.addFunds(2, blueI)
end
if income.announceTicks then if income.announceTicks then
-- trigger.action.outText(income.tickMessage, 30)
local has, balance = bank.getBalance(0) local has, balance = bank.getBalance(0)
local tick = string.gsub(income.tickMessage, "<i>", neuI) local tick = string.gsub(income.tickMessage, "<i>", neuI)
trigger.action.outTextForCoalition(0, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30) trigger.action.outTextForCoalition(0, "\n" .. tick .. "\nNew balance: §" .. balance .. "\n", 30)
@ -81,17 +87,15 @@ function income.readConfigZone()
if not theZone then if not theZone then
theZone = cfxZones.createSimpleZone("incomeConfig") theZone = cfxZones.createSimpleZone("incomeConfig")
end end
income.base = theZone:getNumberFromZoneProperty ("base", 10) income.base = theZone:getNumberFromZoneProperty ("base", 10)
income.red = theZone:getNumberFromZoneProperty ("red", income.base) income.red = theZone:getNumberFromZoneProperty ("red", income.base)
income.blue = theZone:getNumberFromZoneProperty ("blue", income.base) income.blue = theZone:getNumberFromZoneProperty ("blue", income.base)
income.neutral = theZone:getNumberFromZoneProperty ("neutral", income.base) income.neutral = theZone:getNumberFromZoneProperty ("neutral", income.base)
income.interval = theZone:getNumberFromZoneProperty("interval", 10 * 60) -- every 10 minutes income.interval = theZone:getNumberFromZoneProperty("interval", 10 * 60) -- every 10 minutes
income.tickMessage = theZone:getStringFromZoneProperty("tickMessage", "New funds from income available: §<i>") income.tickMessage = theZone:getStringFromZoneProperty("tickMessage", "New funds from income available: §<i>")
income.announceTicks = theZone:getBoolFromZoneProperty("announceTicks", true) income.announceTicks = theZone:getBoolFromZoneProperty("announceTicks", true)
income.reportSound = theZone:getStringFromZoneProperty("reportSound", "<none>") income.reportSound = theZone:getStringFromZoneProperty("reportSound", "<none>")
income.requirePlayers = theZone:getBoolFromZoneProperty("requirePlayers", true)
income.verbose = theZone.verbose income.verbose = theZone.verbose
end end
@ -118,7 +122,6 @@ function income.start()
-- schedule first tick -- schedule first tick
timer.scheduleFunction(income.update, {}, timer.getTime() + income.interval) timer.scheduleFunction(income.update, {}, timer.getTime() + income.interval)
trigger.action.outText("income v" .. income.version .. " started.", 30) trigger.action.outText("income v" .. income.version .. " started.", 30)
return true return true
end end

View File

@ -1,5 +1,5 @@
messenger = {} messenger = {}
messenger.version = "3.2.0" messenger.version = "3.2.1"
messenger.verbose = false messenger.verbose = false
messenger.requiredLibs = { messenger.requiredLibs = {
"dcsCommon", -- always "dcsCommon", -- always
@ -14,7 +14,8 @@ messenger.messengers = {}
3.1.0 - msgGroup supports multiple groups, separated by comma 3.1.0 - msgGroup supports multiple groups, separated by comma
- msgUnit supports multiple units, separated by comma - msgUnit supports multiple units, separated by comma
3.2.0 - loc and twn wildcard support (inherited from zones) 3.2.0 - loc and twn wildcard support (inherited from zones)
3.2.1 - corrected typo in verbose on trigger message
- increased verbosity when active for audio
--]]-- --]]--
function messenger.addMessenger(theZone) function messenger.addMessenger(theZone)
@ -32,7 +33,6 @@ function messenger.getMessengerByName(aName)
return nil return nil
end end
-- --
-- Dynamic Group and Dynamic Unit processing are -- Dynamic Group and Dynamic Unit processing are
-- unique to messenger, and are not available via -- unique to messenger, and are not available via
@ -165,7 +165,6 @@ function messenger.dynamicUnitProcessing(inMsg, theZone, theUnit)
return outMsg return outMsg
end end
-- --
-- read attributes -- read attributes
-- --
@ -313,8 +312,7 @@ function messenger.getMessage(theZone)
-- remainder hand-off to cfxZones (refactoring of messenger code -- remainder hand-off to cfxZones (refactoring of messenger code
msg = cfxZones.processStringWildcards(msg, theZone, theZone.msgTimeFormat, theZone.imperialUnits, theZone.msgResponses) msg = cfxZones.processStringWildcards(msg, theZone, theZone.msgTimeFormat, theZone.imperialUnits, theZone.msgResponses)
return msg return msg
end end
@ -322,7 +320,7 @@ function messenger.isTriggered(theZone)
-- this module has triggered -- this module has triggered
if theZone.messageOff then if theZone.messageOff then
if messenger.verbose or theZone.verbose then if messenger.verbose or theZone.verbose then
trigger.action.outFlag("msg: message for <".. theZone.name .."> is OFF",30) trigger.action.outText("msg: message for <".. theZone.name .."> is OFF",30)
end end
return return
end end
@ -341,6 +339,9 @@ function messenger.isTriggered(theZone)
trigger.action.outTextForCoalition(theZone.msgCoalition, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForCoalition(theZone.msgCoalition, msg, theZone.duration, theZone.clearScreen)
end end
trigger.action.outSoundForCoalition(theZone.msgCoalition, fileName) trigger.action.outSoundForCoalition(theZone.msgCoalition, fileName)
if messenger.verbose or theZone.verbose then
trigger.action.outText("+++msg: messenger in <" .. theZone.name .. "> playing sound file <" .. fileName .. "> to coa " .. theZone.msgCoalition, 30)
end
elseif theZone.msgGroup then elseif theZone.msgGroup then
for idx, aGroupName in pairs(theZone.msgGroup) do for idx, aGroupName in pairs(theZone.msgGroup) do
local theGroup = Group.getByName(aGroupName) local theGroup = Group.getByName(aGroupName)
@ -351,6 +352,9 @@ function messenger.isTriggered(theZone)
trigger.action.outTextForGroup(ID, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForGroup(ID, msg, theZone.duration, theZone.clearScreen)
end end
trigger.action.outSoundForGroup(ID, fileName) trigger.action.outSoundForGroup(ID, fileName)
if messenger.verbose or theZone.verbose then
trigger.action.outText("+++msg: messenger in <" .. theZone.name .. "> playing sound file <" .. fileName .. "> to unit group ID " .. ID .. " <" .. theGroup:getName() .. ">", 30)
end
end end
end end
elseif theZone.msgUnit then elseif theZone.msgUnit then
@ -363,6 +367,9 @@ function messenger.isTriggered(theZone)
trigger.action.outTextForUnit(ID, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForUnit(ID, msg, theZone.duration, theZone.clearScreen)
end end
trigger.action.outSoundForUnit(ID, fileName) trigger.action.outSoundForUnit(ID, fileName)
if messenger.verbose or theZone.verbose then
trigger.action.outText("+++msg: messenger in <" .. theZone.name .. "> playing sound file <" .. fileName .. "> to unit ID " .. ID, 30)
end
end end
end end
elseif theZone:getLinkedUnit() then elseif theZone:getLinkedUnit() then
@ -379,19 +386,24 @@ function messenger.isTriggered(theZone)
trigger.action.outTextForCoalition(coa, msg, theZone.duration, theZone.clearScreen) trigger.action.outTextForCoalition(coa, msg, theZone.duration, theZone.clearScreen)
end end
trigger.action.outSoundForCoalition(coa, fileName) trigger.action.outSoundForCoalition(coa, fileName)
if messenger.verbose or theZone.verbose then
trigger.action.outText("+++msg: messenger in <" .. theZone.name .. "> playing sound file <" .. fileName .. "> to coa " .. coa, 30)
end
else else
-- out to all -- out to all
if #msg > 0 or theZone.clearScreen then if #msg > 0 or theZone.clearScreen then
trigger.action.outText(msg, theZone.duration, theZone.clearScreen) trigger.action.outText(msg, theZone.duration, theZone.clearScreen)
end end
trigger.action.outSound(fileName) trigger.action.outSound(fileName)
if messenger.verbose or theZone.verbose then
trigger.action.outText("+++msg: messenger in <" .. theZone.name .. "> playing sound file to all <" .. fileName .. ">", 30)
end
end end
end end
function messenger.update() function messenger.update()
-- call me in a second to poll triggers -- call me in a second to poll triggers
timer.scheduleFunction(messenger.update, {}, timer.getTime() + 1) timer.scheduleFunction(messenger.update, {}, timer.getTime() + 1)
for idx, aZone in pairs(messenger.messengers) do for idx, aZone in pairs(messenger.messengers) do
-- make sure to re-start before reading time limit -- make sure to re-start before reading time limit
-- new trigger code -- new trigger code
@ -432,9 +444,7 @@ function messenger.readConfigZone()
end end
theZone = cfxZones.createSimpleZone("messengerConfig") theZone = cfxZones.createSimpleZone("messengerConfig")
end end
messenger.verbose = theZone:getBoolFromZoneProperty("verbose", false) messenger.verbose = theZone:getBoolFromZoneProperty("verbose", false)
if messenger.verbose then if messenger.verbose then
trigger.action.outText("+++msgr: read config", 30) trigger.action.outText("+++msgr: read config", 30)
end end
@ -452,16 +462,7 @@ function messenger.start()
-- read config -- read config
messenger.readConfigZone() messenger.readConfigZone()
-- process messenger Zones
-- old style
--[[--
local attrZones = cfxZones.getZonesWithAttributeNamed("messenger")
for k, aZone in pairs(attrZones) do
messenger.createMessengerWithZone(aZone) -- process attributes
messenger.addMessenger(aZone) -- add to list
end
--]]--
-- new style that saves messageOut? flag by reading flags -- new style that saves messageOut? flag by reading flags
attrZones = cfxZones.getZonesWithAttributeNamed("messenger?") attrZones = cfxZones.getZonesWithAttributeNamed("messenger?")
for k, aZone in pairs(attrZones) do for k, aZone in pairs(attrZones) do

View File

@ -7,6 +7,7 @@ cfxSmokeZone.requiredLibs = {
--[[-- --[[--
Version History Version History
2.0.0 - clean up 2.0.0 - clean up
2.0.1 - deprecating "f?"
--]]-- --]]--
cfxSmokeZone.smokeZones = {} cfxSmokeZone.smokeZones = {}
@ -37,6 +38,7 @@ function cfxSmokeZone.processSmokeZone(aZone)
if aZone:hasProperty("f?") then if aZone:hasProperty("f?") then
aZone.onFlag = aZone:getStringFromZoneProperty("f?", "*<none>") aZone.onFlag = aZone:getStringFromZoneProperty("f?", "*<none>")
trigger.action.outText("+++smokeZones: WARNING: smoke zone <" .. aZone.name .. "> uses deprecated attribute 'f?' - use 'startSmoke?' instead.", 30)
elseif aZone:hasProperty("startSmoke?") then elseif aZone:hasProperty("startSmoke?") then
aZone.onFlag = aZone:getStringFromZoneProperty("startSmoke?", "none") aZone.onFlag = aZone:getStringFromZoneProperty("startSmoke?", "none")
end end

View File

@ -1,5 +1,5 @@
cfxSpawnZones = {} cfxSpawnZones = {}
cfxSpawnZones.version = "2.1.0" cfxSpawnZones.version = "2.2.0"
cfxSpawnZones.requiredLibs = { cfxSpawnZones.requiredLibs = {
"dcsCommon", -- common is of course needed for everything "dcsCommon", -- common is of course needed for everything
-- pretty stupid to check for this since we -- pretty stupid to check for this since we
@ -31,6 +31,7 @@ cfxSpawnZones.spawnedGroups = {}
2.0.3 - corrected type in spawnUnits? attribute 2.0.3 - corrected type in spawnUnits? attribute
2.1.0 - masterOwner update for dmlZones. 2.1.0 - masterOwner update for dmlZones.
since spawners don't extend zones, this is still old-school since spawners don't extend zones, this is still old-school
2.2.0 - "drivable" spawner attribute
--]]-- --]]--
@ -109,7 +110,7 @@ function cfxSpawnZones.createSpawner(inZone)
end end
theSpawner.types = theSpawner.types .. repeater theSpawner.types = theSpawner.types .. repeater
end end
theSpawner.drivable = inZone:getBoolFromZoneProperty("drivable", false)
theSpawner.country = inZone:getNumberFromZoneProperty("country", 0) theSpawner.country = inZone:getNumberFromZoneProperty("country", 0)
if inZone:hasProperty("masterOwner") then if inZone:hasProperty("masterOwner") then
theSpawner.masterZoneName = inZone:getStringFromZoneProperty("masterOwner", "") theSpawner.masterZoneName = inZone:getStringFromZoneProperty("masterOwner", "")
@ -299,7 +300,10 @@ function cfxSpawnZones.spawnWithSpawner(aSpawner)
aSpawner.zone, aSpawner.zone,
unitTypes, unitTypes,
aSpawner.formation, aSpawner.formation,
aSpawner.heading) aSpawner.heading,
nil, -- liveries
aSpawner.drivable
)
if cfxSpawnZones.verbose or theZone.verbose then if cfxSpawnZones.verbose or theZone.verbose then
-- check created group size versus requested size -- check created group size versus requested size
trigger.action.outText("+++spwn: created <" .. theGroup:getSize() .. "> units, requested <" .. #unitTypes .. "> units, formation <" .. aSpawner.formation .. ">", 30) trigger.action.outText("+++spwn: created <" .. theGroup:getSize() .. "> units, requested <" .. #unitTypes .. "> units, formation <" .. aSpawner.formation .. ">", 30)