diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index e5917a7..aa56b2c 100644 Binary files a/Doc/DML Documentation.pdf and b/Doc/DML Documentation.pdf differ diff --git a/modules/cfxOwnedZones.lua b/modules/cfxOwnedZones.lua index a6244f8..59a8890 100644 --- a/modules/cfxOwnedZones.lua +++ b/modules/cfxOwnedZones.lua @@ -1,5 +1,5 @@ cfxOwnedZones = {} -cfxOwnedZones.version = "1.1.1" +cfxOwnedZones.version = "1.1.2" cfxOwnedZones.verbose = false cfxOwnedZones.announcer = true --[[-- VERSION HISTORY @@ -40,6 +40,7 @@ cfxOwnedZones.announcer = true shocked state - announcer 1.1.1 - conq+1 flag +1.1.2 - corrected type bug in zoneConquered --]]-- cfxOwnedZones.requiredLibs = { @@ -497,7 +498,7 @@ function cfxOwnedZones.zoneConquered(aZone, theSide, formerOwner) -- 0 = neutral -- increase conq flag if aZone.conqueredFlag then local lastVal = trigger.misc.getUserFlag(aZone.conqueredFlag) - trigger.action.setUserFlag)aZone.conqueredFlag, lastVal + 1) + trigger.action.setUserFlag(aZone.conqueredFlag, lastVal + 1) end -- invoke callbacks now cfxOwnedZones.invokeConqueredCallbacks(aZone, theSide, formerOwner) diff --git a/modules/cfxSSBClient.lua b/modules/cfxSSBClient.lua index 5a025c0..906eecb 100644 --- a/modules/cfxSSBClient.lua +++ b/modules/cfxSSBClient.lua @@ -35,6 +35,7 @@ Version History and interator - reUseAfter option for single-use - dcsCommon, cfxZones import + 2.0.1 - stricter verbosity: moved more comments to verbose only WHAT IT IS SSB Client is a small script that forms the client-side counterpart to @@ -124,37 +125,7 @@ function cfxSSBClient.bindGroupToAirfield(groupName, airfieldName) if not airfieldName then airfieldName = "" end trigger.action.outText("+++SSB: Binding Group " .. groupName .. " to " .. airfieldName .. " failed.", 30) end ---[[-- -function cfxSSBClient.dist(point1, point2) -- returns distance between two points - local x = point1.x - point2.x - local y = point1.y - point2.y - local z = point1.z - point2.z - - return (x*x + y*y + z*z)^0.5 -end ---]]-- - --- see if instring conatins what, defaults to case insensitive ---[[-- -function cfxSSBClient.containsString(inString, what, caseSensitive) - if (not caseSensitive) then - inString = string.upper(inString) - what = string.upper(what) - end - return string.find(inString, what) -end ---]]-- ---[[-- -function cfxSSBClient.arrayContainsString(theArray, theString) - -- warning: case sensitive! - if not theArray then return false end - if not theString then return false end - for i = 1, #theArray do - if theArray[i] == theString then return true end - end - return false -end ---]]-- + function cfxSSBClient.getClosestAirbaseTo(thePoint) local delta = math.huge @@ -256,7 +227,9 @@ function cfxSSBClient.openSlotForCrashedGroupNamed(gName) if not pGroup then return end cfxSSBClient.crashedGroups[gName] = nil -- set to nil to forget this happened cfxSSBClient.setSlotAccessForGroup(pGroup) -- set by current occupation status - trigger.action.outText("+++SSBC:SU: re-opened slot for group <" .. gName .. ">", 30) + if cfxSSBClient.verbose then + trigger.action.outText("+++SSBC:SU: re-opened slot for group <" .. gName .. ">", 30) + end end function cfxSSBClient:onEvent(event) @@ -282,7 +255,9 @@ function cfxSSBClient:onEvent(event) -- remember this unit as player controlled plane -- because player and plane can easily disconnect cfxSSBClient.playerPlanes[uName] = playerName - trigger.action.outText("+++SSBC:SU: noted " .. playerName .. " piloting player unit " .. uName, 30) + if cfxSSBClient.verbose then + trigger.action.outText("+++SSBC:SU: noted " .. playerName .. " piloting player unit " .. uName, 30) + end return end @@ -298,7 +273,9 @@ function cfxSSBClient:onEvent(event) local thePilot = cfxSSBClient.playerPlanes[uName] if not thePilot then -- ignore. not a player plane - trigger.action.outText("+++SSBC:SU: ignored crash for NPC unit <" .. uName .. ">", 30) + if cfxSSBClient.verbose then + trigger.action.outText("+++SSBC:SU: ignored crash for NPC unit <" .. uName .. ">", 30) + end return end -- if we get here, a player-owned plane has crashed diff --git a/modules/cloneZone.lua b/modules/cloneZone.lua index fdbcd4c..23a12de 100644 --- a/modules/cloneZone.lua +++ b/modules/cloneZone.lua @@ -1,5 +1,5 @@ cloneZones = {} -cloneZones.version = "1.1.0" +cloneZones.version = "1.1.1" cloneZones.verbose = false cloneZones.requiredLibs = { "dcsCommon", -- always @@ -17,6 +17,7 @@ cloneZones.cloners = {} 1.0.1 - preWipe attribute 1.1.0 - support for static objects - despawn? attribute + 1.1.1 - despawnAll: isExist guard --]]-- @@ -100,6 +101,11 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner" theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value end + if cfxZones.hasProperty(theZone, "in?") then + theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "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 @@ -142,13 +148,17 @@ function cloneZones.despawnAll(theZone) trigger.action.outText("wiping <" .. theZone.name .. ">", 30) end for idx, aGroup in pairs(theZone.mySpawns) do - Group.destroy(aGroup) + if aGroup:isExist() then + Group.destroy(aGroup) + end end for idx, aStatic in pairs(theZone.myStatics) do -- warning! may be mismatch because we are looking at groups -- not objects. let's see - trigger.action.outText("Destroying static <" .. aStatic:getName() .. ">", 30) - Object.destroy(aStatic) -- we don't aStatio:destroy() to find out what it is + if aStatic:isExist() then + trigger.action.outText("Destroying static <" .. aStatic:getName() .. ">", 30) + Object.destroy(aStatic) -- we don't aStatio:destroy() to find out what it is + end end theZone.mySpawns = {} theZone.myStatics = {} diff --git a/modules/countDown.lua b/modules/countDown.lua index 07a4239..5d88be4 100644 --- a/modules/countDown.lua +++ b/modules/countDown.lua @@ -1,5 +1,5 @@ countDown = {} -countDown.version = "1.0.0" +countDown.version = "1.1.0" countDown.verbose = true countDown.requiredLibs = { "dcsCommon", -- always @@ -12,11 +12,14 @@ countDown.requiredLibs = { Version History 1.0.0 - initial version + 1.1.0 - Lua interface: callbacks + - corrected verbose (erroneously always suppressed) + - triggerFlag --> triggerCountFlag --]]-- countDown.counters = {} - +countDown.callbacks = {} -- -- add/remove zones @@ -36,6 +39,27 @@ function countDown.getCountDownZoneByName(aName) return nil end + +-- +-- callbacks +-- +function countDown.addCallback(theCallback) + if not theCallback then return end + table.insert(countDown.callbacks, theCallback) +end + +function countDown.invokeCallbacks(theZone, val, tminus, zero, belowZero, looping) + if not val then val = 1 end + if not tminus then tminus = false end + if not zero then zero = false end + if not belowZero then belowZero = false end + + -- invoke anyone who wants to know that a group + -- of people was rescued. + for idx, cb in pairs(csarManager.csarCompleteCB) do + cb(theZone, val, tminus, zero, belowZero, looping) + end +end -- -- read attributes -- @@ -60,17 +84,17 @@ function countDown.createCountDownWithZone(theZone) -- trigger flag "count" / "start?" if cfxZones.hasProperty(theZone, "count?") then - theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "none") + theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "none") end - -- can also use in? for counting. we always use triggerflag + -- can also use in? for counting. we always use triggerCountFlag if cfxZones.hasProperty(theZone, "in?") then - theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") + theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") end - if theZone.triggerFlag then - theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value + if theZone.triggerCountFlag then + theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value end -- zero! bang @@ -95,14 +119,19 @@ end function countDown.isTriggered(theZone) -- this module has triggered local val = theZone.currVal - 1 -- decrease counter - if theZone.verbose then + if countDown.verbose then trigger.action.outText("+++cntD: enter triggered: val now: " .. val, 30) end + local tMinus = false + local zero = false + local belowZero = false + local looping = false + if val > 0 then - + tMinus = true -- see if we need to bang Tminus if theZone.tMinusFlag then - if theZone.verbose then + if countDown.verbose then trigger.action.outText("+++cntD: TMINUTS", 30) end cfxZones.pollFlag(theZone.tMinusFlag, theZone.method) @@ -110,8 +139,9 @@ function countDown.isTriggered(theZone) elseif val == 0 then -- reached zero + zero = true if theZone.zeroFlag then - if theZone.verbose then + if countDown.verbose then trigger.action.outText("+++cntD: ZERO", 30) end cfxZones.pollFlag(theZone.zeroFlag, theZone.method) @@ -119,7 +149,8 @@ function countDown.isTriggered(theZone) if theZone.loop then -- restart time - if theZone.verbose then + looping = true + if countDown.verbose then trigger.action.outText("+++cntD: Looping", 30) end val = dcsCommon.randomBetween(theZone.startMinVal, theZone.startMaxVal) @@ -127,8 +158,9 @@ function countDown.isTriggered(theZone) else -- below zero + belowZero = true if theZone.belowZero and theZone.zeroFlag then - if theZone.verbose then + if countDown.verbose then trigger.action.outText("+++cntD: Below Zero", 30) end cfxZones.pollFlag(theZone.zeroFlag, theZone.method) @@ -136,6 +168,10 @@ function countDown.isTriggered(theZone) end + -- callbacks + countDown.invokeCallbacks(theZone, val, tMinus, zero, belowZero, looping) + + -- update & return theZone.currVal = val end @@ -146,15 +182,15 @@ function countDown.update() for idx, aZone in pairs(countDown.counters) do -- make sure to re-start before reading time limit - if aZone.triggerFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerFlag) + if aZone.triggerCountFlag then + local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerCountFlag) if currTriggerVal ~= aZone.lastTriggerValue then - if aZone.verbose then + if countDown.verbose then trigger.action.outText("+++cntD: triggered on in?", 30) end countDown.isTriggered(aZone) - aZone.lastTriggerValue = trigger.misc.getUserFlag(aZone.triggerFlag) -- save last value + aZone.lastTriggerValue = trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value end end end diff --git a/modules/delayFlags.lua b/modules/delayFlags.lua index 961b85d..8e49cb2 100644 --- a/modules/delayFlags.lua +++ b/modules/delayFlags.lua @@ -1,5 +1,5 @@ delayFlag = {} -delayFlag.version = "1.0.0" +delayFlag.version = "1.0.2" delayFlag.verbose = false delayFlag.requiredLibs = { "dcsCommon", -- always @@ -19,6 +19,8 @@ delayFlag.flags = {} 1.0.2 - slight spelling correction - using cfxZones for polling - removed pollFlag + 1.0.3 - bug fix for config zone name + - removed message attribute, moved to own module --]]-- @@ -89,47 +91,6 @@ function delayFlag.createTimerWithZone(theZone) 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("+++dlyF: 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 -- @@ -204,7 +165,7 @@ end -- START -- function delayFlag.readConfigZone() - local theZone = cfxZones.getZoneByName("cloneZonesConfig") + local theZone = cfxZones.getZoneByName("delayZonesConfig") if not theZone then if delayFlag.verbose then trigger.action.outText("+++dlyF: NO config zone!", 30) diff --git a/modules/messenger.lua b/modules/messenger.lua new file mode 100644 index 0000000..a326800 --- /dev/null +++ b/modules/messenger.lua @@ -0,0 +1,156 @@ +messenger = {} +messenger.version = "1.0.0" +messenger.verbose = false +messenger.requiredLibs = { + "dcsCommon", -- always + "cfxZones", -- Zones, of course +} +messenger.messengers = {} +--[[-- + Version History + 1.0.0 - initial version + +--]]-- + +function messenger.addMessenger(theZone) + table.insert(messenger.messengers, theZone) +end + +function messenger.getMessengerByName(aName) + for idx, aZone in pairs(messenger.messengers) do + if aName == aZone.name then return aZone end + end + if messenger.verbose then + trigger.action.outText("+++msgr: no messenger with name <" .. aName ..">", 30) + end + + return nil +end + +-- +-- read attributes +-- +function messenger.createMessengerDownWithZone(theZone) + -- start val - a range + theZone.message = cfxZones.getStringFromZoneProperty(theZone, "message", "") + + theZone.spaceBefore = cfxZones.getBoolFromZoneProperty(theZone, "spaceBefore", false) + theZone.spaceAfter = cfxZones.getBoolFromZoneProperty(theZone, "spaceAfter", false) + + theZone.soundFile = cfxZones.getStringFromZoneProperty(theZone, "soundFile", "") + + -- alternate version: messages: list of messages, need string parser first + + theZone.duration = cfxZones.getNumberFromZoneProperty(theZone, "duration", 30) + + -- trigger flag "count" / "start?" + if cfxZones.hasProperty(theZone, "f?") then + theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none") + end + + -- can also use in? for counting. we always use triggerMessagerFlag + if cfxZones.hasProperty(theZone, "in?") then + theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") + end + + if theZone.triggerMessagerFlag then + theZone.lastMessageTriggerValue = trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value + end + + if cfxZones.hasProperty(theZone, "coalition") then + theZone.coalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0) + end + +end + +-- +-- Update +-- +function messenger.isTriggered(theZone) + -- this module has triggered + local fileName = "l10n/DEFAULT/" .. theZone.soundFile + local msg = theZone.message + if theZone.spaceBefore then msg = "\n"..msg end + if theZone.spaceAfter then msg = msg .. "\n" end + + if theZone.coalition then + trigger.action.outTextForCoalition(theZone.coalition, msg, theZone.duration) + trigger.action.outSoundForCoalition(theZone.coalition, fileName) + else + -- out to all + trigger.action.outText(msg, theZone.duration) + trigger.action.outSound(fileName) + end +end + +function messenger.update() + -- call me in a second to poll triggers + timer.scheduleFunction(messenger.update, {}, timer.getTime() + 1) + + for idx, aZone in pairs(messenger.messengers) do + -- make sure to re-start before reading time limit + if aZone.triggerMessagerFlag then + local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerMessagerFlag) + if currTriggerVal ~= aZone.lastMessageTriggerValue + then + if messenger.verbose then + trigger.action.outText("+++msgr: triggered on in?", 30) + end + messenger.isTriggered(aZone) + aZone.lastMessageTriggerValue = trigger.misc.getUserFlag(aZone.triggerMessagerFlag) -- save last value + end + end + end +end + +-- +-- Config & Start +-- +function messenger.readConfigZone() + local theZone = cfxZones.getZoneByName("messengerConfig") + if not theZone then + if messenger.verbose then + trigger.action.outText("+++msgr: NO config zone!", 30) + end + return + end + + messenger.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) + + if messenger.verbose then + trigger.action.outText("+++msgr: read config", 30) + end +end + +function messenger.start() + -- lib check + if not dcsCommon.libCheck then + trigger.action.outText("cfx Count Down requires dcsCommon", 30) + return false + end + if not dcsCommon.libCheck("cfx Count Down", messenger.requiredLibs) then + return false + end + + -- read config + messenger.readConfigZone() + + -- process cloner Zones + local attrZones = cfxZones.getZonesWithAttributeNamed("messenger") + for k, aZone in pairs(attrZones) do + messenger.createMessengerDownWithZone(aZone) -- process attributes + messenger.addMessenger(aZone) -- add to list + end + + -- start update + messenger.update() + + trigger.action.outText("cfx Messenger v" .. messenger.version .. " started.", 30) + return true +end + +-- let's go! +if not messenger.start() then + trigger.action.outText("cfx Messenger aborted: missing libraries", 30) + messenger = nil +end \ No newline at end of file diff --git a/modules/nameStats.lua b/modules/nameStats.lua index c671a72..5bd8679 100644 --- a/modules/nameStats.lua +++ b/modules/nameStats.lua @@ -1,5 +1,5 @@ nameStats = {} -nameStats.version = "1.1.0" +nameStats.version = "1.1.1" --[[-- package that allows generic and global access to data, stored by name and path. Can be used to manage score, cargo, statistics etc. diff --git a/modules/pulseFlags.lua b/modules/pulseFlags.lua index 128e470..49cea4c 100644 --- a/modules/pulseFlags.lua +++ b/modules/pulseFlags.lua @@ -1,5 +1,5 @@ pulseFlags = {} -pulseFlags.version = "1.0.1" +pulseFlags.version = "1.0.2" pulseFlags.verbose = false pulseFlags.requiredLibs = { "dcsCommon", -- always @@ -13,6 +13,7 @@ pulseFlags.requiredLibs = { Version History - 1.0.0 Initial version - 1.0.1 pause behavior debugged + - 1.0.2 zero pulse optional initial pulse suppress --]]-- @@ -60,7 +61,8 @@ function pulseFlags.createPulseWithZone(theZone) end theZone.pulsing = false -- not running - + theZone.hasPulsed = false + theZone.zeroPulse = cfxZones.getBoolFromZoneProperty(theZone, "zeroPulse", true) end -- @@ -113,32 +115,40 @@ function pulseFlags.doPulse(args) return end - -- do a poll on flags - pulseFlags.pollFlag(theZone.flag, theZone.method) + -- do a poll on flags + -- first, we only do an initial pulse if zeroPulse is set + if theZone.hasPulsed or theZone.zeroPulse then + pulseFlags.pollFlag(theZone.flag, theZone.method) - -- decrease count - if theZone.pulses > 0 then - -- only do this if ending - theZone.pulsesLeft = theZone.pulsesLeft - 1 - - -- see if we are done - if theZone.pulsesLeft < 1 then - -- increment done flag if set - if theZone.doneFlag then - local currVal = trigger.misc.getUserFlag(theZone.doneFlag) - trigger.action.setUserFlag(theZone.doneFlag, currVal + 1) + -- decrease count + if theZone.pulses > 0 then + -- only do this if ending + theZone.pulsesLeft = theZone.pulsesLeft - 1 + + -- see if we are done + if theZone.pulsesLeft < 1 then + -- increment done flag if set + if theZone.doneFlag then + local currVal = trigger.misc.getUserFlag(theZone.doneFlag) + trigger.action.setUserFlag(theZone.doneFlag, currVal + 1) + end + if pulseFlags.verbose then + trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> ended!", 30) + end + theZone.pulsing = false + theZone.paused = true + return end - if pulseFlags.verbose then - trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> ended!", 30) - end - theZone.pulsing = false - theZone.paused = true - return + end + else + if pulseFlags.verbose then + trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> delaying zero pulse!", 30) end end - -- if we get here, we'll do another one soon - -- refresh pulse + theZone.hasPulsed = true -- we are past initial pulse + + -- if we get here, schedule next pulse local delay = theZone.time if theZone.minTime > 0 and theZone.minTime < delay then -- we want a randomized from time from minTime .. delay diff --git a/tutorial & demo missions/demo - bottled messages.miz b/tutorial & demo missions/demo - bottled messages.miz new file mode 100644 index 0000000..41e484e Binary files /dev/null and b/tutorial & demo missions/demo - bottled messages.miz differ diff --git a/tutorial & demo missions/full - frog men combat training.miz b/tutorial & demo missions/full - frog men combat training.miz new file mode 100644 index 0000000..0b585e6 Binary files /dev/null and b/tutorial & demo missions/full - frog men combat training.miz differ