diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index 3c818c7..0574cc6 100644 Binary files a/Doc/DML Documentation.pdf and b/Doc/DML Documentation.pdf differ diff --git a/Doc/DML Quick Reference.pdf b/Doc/DML Quick Reference.pdf index 789e345..973547a 100644 Binary files a/Doc/DML Quick Reference.pdf and b/Doc/DML Quick Reference.pdf differ diff --git a/modules/cfxReconMode.lua b/modules/cfxReconMode.lua index 982391a..4369c7a 100644 --- a/modules/cfxReconMode.lua +++ b/modules/cfxReconMode.lua @@ -1,5 +1,5 @@ cfxReconMode = {} -cfxReconMode.version = "2.0.0" +cfxReconMode.version = "2.1.0" cfxReconMode.verbose = false -- set to true for debug info cfxReconMode.reconSound = "UI_SCI-FI_Tone_Bright_Dry_20_stereo.wav" -- to be played when somethiong discovered @@ -73,6 +73,10 @@ VERSION HISTORY - event guard in onEvent - wildcard - , , wildcards + 2.0.1 - getGroup() guard for onEvent(). Objects now seem to birth. + 2.1.0 - processZoneMessage uses group's position, not zone + - silent attribute for priority targets + - activate / deactivate by flags cfxReconMode is a script that allows units to perform reconnaissance missions and, after detecting units, marks them on the map with @@ -449,7 +453,7 @@ function cfxReconMode.generateSALT(theScout, theGroup) return msg end -function cfxReconMode.processZoneMessage(inMsg, theZone) +function cfxReconMode.processZoneMessage(inMsg, theZone, theGroup) if not inMsg then return "" end local formerType = type(inMsg) if formerType ~= "string" then inMsg = tostring(inMsg) end @@ -471,6 +475,12 @@ function cfxReconMode.processZoneMessage(inMsg, theZone) -- replace with lat of zone point and with lon of zone point -- and with mgrs coords of zone point local currPoint = cfxZones.getPoint(theZone) + if theGroup and theGroup:isExist() then + -- only use group's point when group exists and alive + local theUnit = dcsCommon.getFirstLivingUnit(theGroup) + currPoint = theUnit:getPoint() + end + local lat, lon, alt = coord.LOtoLL(currPoint) lat, lon = dcsCommon.latLon2Text(lat, lon) outMsg = outMsg:gsub("", lat) @@ -483,8 +493,16 @@ function cfxReconMode.processZoneMessage(inMsg, theZone) end function cfxReconMode.detectedGroup(mySide, theScout, theGroup, theLoc) + -- see if it was a prio target and gather info + local inList, gName = cfxReconMode.isStringInList(theGroup:getName(), cfxReconMode.prioList) + local silent = false + if gName and cfxReconMode.zoneInfo[gName] then + local zInfo = cfxReconMode.zoneInfo[gName] + silent = zInfo.silent + end + -- put a mark on the map - if cfxReconMode.applyMarks then + if not silent and cfxReconMode.applyMarks then local theID = cfxReconMode.placeMarkForUnit(theLoc, mySide, theGroup) local gName = theGroup:getName() local args = {mySide, theScout, theGroup, theID, gName} @@ -496,7 +514,7 @@ function cfxReconMode.detectedGroup(mySide, theScout, theGroup, theLoc) end -- say something - if cfxReconMode.announcer then + if not silent and cfxReconMode.announcer then local msg = cfxReconMode.generateSALT(theScout, theGroup) trigger.action.outTextForCoalition(mySide, msg, 30) -- trigger.action.outTextForCoalition(mySide, theScout:getName() .. " reports new ground contact " .. theGroup:getName(), 30) @@ -509,7 +527,7 @@ function cfxReconMode.detectedGroup(mySide, theScout, theGroup, theLoc) end -- see if it was a prio target - local inList, gName = cfxReconMode.isStringInList(theGroup:getName(), cfxReconMode.prioList) + --local inList, gName = cfxReconMode.isStringInList(theGroup:getName(), cfxReconMode.prioList) if inList then -- if cfxReconMode.announcer then if cfxReconMode.verbose then @@ -528,8 +546,9 @@ function cfxReconMode.detectedGroup(mySide, theScout, theGroup, theLoc) local zInfo = cfxReconMode.zoneInfo[gName] if zInfo.prioMessage then -- prio message displays even when announcer is off + -- AND EVEN WHEN SILENT!!! local msg = zInfo.prioMessage - msg = cfxReconMode.processZoneMessage(msg, zInfo.theZone) + msg = cfxReconMode.processZoneMessage(msg, zInfo.theZone, theGroup) trigger.action.outTextForCoalition(mySide, msg, 30) if cfxReconMode.verbose or zInfo.theZone.verbose then trigger.action.outText("+++rcn: prio message sent for prio target zone <" .. zInfo.theZone.name .. ">",30) @@ -595,12 +614,42 @@ function cfxReconMode.performReconForUnit(theScout) end end +function cfxReconMode.doActivate() + cfxReconMode.active = true + if cfxReconMode.verbose then + trigger.action.outText("Recon Mode has activated", 30) + end +end +function cfxReconMode.doDeActivate() + cfxReconMode.active = false + if cfxReconMode.verbose then + trigger.action.outText("Recon Mode is OFF", 30) + end +end function cfxReconMode.updateQueues() -- schedule next call timer.scheduleFunction(cfxReconMode.updateQueues, {}, timer.getTime() + 1/cfxReconMode.ups) + -- check to turn on or off + -- check the flags for on/off + if cfxReconMode.activate then + if cfxZones.testZoneFlag(cfxReconMode, cfxReconMode.activate, "change","lastActivate") then + cfxReconMode.doActivate() + end + end + + if cfxReconMode.deactivate then + if cfxZones.testZoneFlag(cfxReconMode, cfxReconMode.deactivate, "change","lastDeActivate") then + cfxReconMode.doDeActivate() + end + end + + -- check if we are active + if not cfxReconMode.active then return end + + -- we only process the first aircraft in -- the scouts array, move it to processed and then shrink -- scouts table until it's empty. When empty, transfer all @@ -724,8 +773,12 @@ function cfxReconMode:onEvent(event) local theUnit = event.initiator if not theUnit:isExist() then return end + if not theUnit.getGroup then + -- strange, but seemingly can happen + return + end local theGroup = theUnit:getGroup() --- trigger.action.outText("+++rcn-ENTER onEvent: " .. event.id .. " for <" .. theUnit:getName() .. ">", 30) + if not theGroup then return end local gCat = theGroup:getCategory() -- only continue if cat = 0 (aircraft) or 1 (helo) @@ -945,6 +998,24 @@ function cfxReconMode.readConfigZone() cfxReconMode.mgrs = cfxZones.getBoolFromZoneProperty(theZone, "mgrs", false) + cfxReconMode.active = cfxZones.getBoolFromZoneProperty(theZone, "active", true) + if cfxZones.hasProperty(theZone, "activate?") then + cfxReconMode.activate = cfxZones.getStringFromZoneProperty(theZone, "activate?", "*") + cfxReconMode.lastActivate = cfxZones.getFlagValue(cfxReconMode.activate, theZone) + elseif cfxZones.hasProperty(theZone, "on?") then + cfxReconMode.activate = cfxZones.getStringFromZoneProperty(theZone, "on?", "*") + cfxReconMode.lastActivate = cfxZones.getFlagValue(cfxReconMode.activate, theZone) + end + + if cfxZones.hasProperty(theZone, "deactivate?") then + cfxReconMode.deactivate = cfxZones.getStringFromZoneProperty(theZone, "deactivate?", "*") + cfxReconMode.lastDeActivate = cfxZones.getFlagValue(cfxReconMode.deactivate, theZone) + elseif cfxZones.hasProperty(theZone, "off?") then + cfxReconMode.deactivate = cfxZones.getStringFromZoneProperty(theZone, "off?", "*") + cfxReconMode.lastDeActivate = cfxZones.getFlagValue(cfxReconMode.deactivate, theZone) + end + + cfxReconMode.theZone = theZone -- save this zone end @@ -961,6 +1032,8 @@ function cfxReconMode.processReconZone(theZone) local zInfo = {} zInfo.theZone = theZone zInfo.isBlack = isBlack + zInfo.silent = cfxZones.getBoolFromZoneProperty(theZone, "silent", false) + if cfxZones.hasProperty(theZone, "spotted!") then zInfo.theFlag = cfxZones.getStringFromZoneProperty(theZone, "spotted!", "*") end @@ -1104,9 +1177,7 @@ ideas: - renew lease. when already sighted, simply renew lease, maybe update location. - update marks and renew lease TODO: red+ and blue+ - flags to increase when a plane of the other side is detected -TODO: recon: scout and blind for aircraft in group to add / remove scouts, maybe use scout keyword -allow special bangs per priority group --]]-- diff --git a/modules/changer.lua b/modules/changer.lua index 2e977ad..e56451b 100644 --- a/modules/changer.lua +++ b/modules/changer.lua @@ -1,5 +1,5 @@ changer = {} -changer.version = "1.0.0" +changer.version = "1.0.1" changer.verbose = false changer.ups = 1 changer.requiredLibs = { @@ -10,6 +10,7 @@ changer.changers = {} --[[-- Version History 1.0.0 - Initial version + 1.0.1 - Better guards in config to avoid Zone getter warning Transmogrify an incoming signal to an output signal - not @@ -75,17 +76,22 @@ function changer.createChangerWithZone(theZone) trigger.action.outText("+++chgr: <" .. theZone.name .. "> starts paused", 30) end - theZone.changerOn = cfxZones.getStringFromZoneProperty(theZone, "on?", "*") - if cfxZones.hasProperty(theZone, "changeOn?") then + if cfxZones.hasProperty(theZone, "on?") then + theZone.changerOn = cfxZones.getStringFromZoneProperty(theZone, "on?", "*") + theZone.lastChangerOnValue = cfxZones.getFlagValue(theZone.changerOn, theZone) + elseif cfxZones.hasProperty(theZone, "changeOn?") then theZone.changerOn = cfxZones.getStringFromZoneProperty(theZone, "changeOn?", "*") + theZone.lastChangerOnValue = cfxZones.getFlagValue(theZone.changerOn, theZone) end - theZone.lastChangerOnValue = cfxZones.getFlagValue(theZone.changerOn, theZone) - theZone.changerOff = cfxZones.getStringFromZoneProperty(theZone, "off?", "*") - if cfxZones.hasProperty(theZone, "changeOff?") then + if cfxZones.hasProperty(theZone, "off?") then + theZone.changerOff = cfxZones.getStringFromZoneProperty(theZone, "off?", "*") + theZone.lastChangerOffValue = cfxZones.getFlagValue(theZone.changerOff, theZone) + elseif cfxZones.hasProperty(theZone, "changeOff?") then theZone.changerOff = cfxZones.getStringFromZoneProperty(theZone, "changeOff?", "*") + theZone.lastChangerOffValue = cfxZones.getFlagValue(theZone.changerOff, theZone) end - theZone.lastChangerOffValue = cfxZones.getFlagValue(theZone.changerOff, theZone) + if changer.verbose or theZone.verbose then trigger.action.outText("+++chgr: new changer zone <".. theZone.name ..">", 30) diff --git a/modules/cloneZone.lua b/modules/cloneZone.lua index f75db4b..8191a39 100644 --- a/modules/cloneZone.lua +++ b/modules/cloneZone.lua @@ -1,5 +1,5 @@ cloneZones = {} - cloneZones.version = "1.4.7" + cloneZones.version = "1.4.8" cloneZones.verbose = false cloneZones.requiredLibs = { "dcsCommon", -- always @@ -46,6 +46,7 @@ - cargo manager integration - pass cargo objects when present 1.4.6 - removed some verbosity for spawned aircraft with airfields on their routes 1.4.7 - DML watchflag and DML Flag polish, method-->cloneMethod + 1.4.8 - added 'wipe?' synonym --]]-- @@ -233,6 +234,10 @@ theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "deClone?", "none") end + if cfxZones.hasProperty(theZone, "wipe?") then + theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "wipe?", "none") + end + if theZone.deSpawnFlag then theZone.lastDeSpawnValue = cfxZones.getFlagValue(theZone.deSpawnFlag, theZone) end diff --git a/modules/guardianAngel.lua b/modules/guardianAngel.lua index 201a7e6..ce54d9c 100644 --- a/modules/guardianAngel.lua +++ b/modules/guardianAngel.lua @@ -1,5 +1,5 @@ guardianAngel = {} -guardianAngel.version = "3.0.0" +guardianAngel.version = "3.0.1" guardianAngel.ups = 10 guardianAngel.launchWarning = true -- detect launches and warn pilot guardianAngel.intervention = true -- remove missiles just before hitting @@ -53,6 +53,9 @@ guardianAngel.requiredLibs = { - hardened missile disappear code - all missiles are now tracked regardless whom they aim for - removed item.wp + 3.0.1 - corrected error on collateral (missing delay) + - Supporst cloned units + - removed legacy code This script detects missiles launched against protected aircraft an @@ -135,7 +138,6 @@ function guardianAngel.createQItem(theWeapon, theTarget, threat) local theItem = {} theItem.theWeapon = theWeapon -- weapon that we are tracking - --theItem.wP = theWeapon:getPoint() -- save location theItem.weaponName = theWeapon:getName() theItem.theTarget = theTarget theItem.tGroup = theTarget:getGroup() @@ -143,10 +145,8 @@ function guardianAngel.createQItem(theWeapon, theTarget, threat) theItem.targetName = theTarget:getName() theItem.launchTimeStamp = timer.getTime() - --theItem.lastCheckTimeStamp = -1000 theItem.lastDistance = math.huge theItem.detected = false - --theItem.lostTrack = false -- so we can detect sneakies! theItem.missed = false -- just keep watching for re-ack theItem.threat = threat theItem.lastDesc = "(new)" @@ -162,7 +162,6 @@ function guardianAngel.retargetItem(theItem, theTarget, threat) theItem.target = nil theItem.targetName = "(substitute)" theItem.lastDistance = math.huge - -- theItem.lostTrack = false theItem.missed = false theItem.lastDesc = "(retarget)" return @@ -211,24 +210,6 @@ function guardianAngel.calcSafeExplosionPoint(wpn, pln, dist) return newPoint end ---[[-- -function guardianAngel.bubbleCheck(wPos, w) - if true then return false end - for idx, aProtectee in pairs (guardianAngel.unitsToWatchOver) do - local uP = aProtectee:getPoint() - local d = math.floor(dcsCommon.dist(wPos, uP)) - if d < guardianAngel.minMissileDist * 2 then - trigger.action.outText("+++gA: gazing at w=" .. w:getName() .. " APR:" .. aProtectee:getName() .. ", d=" .. d .. ", cutoff=" .. guardianAngel.minMissileDist, 30) - if w:getTarget() then - trigger.action.outText("+++gA: w is targeting " .. w:getTarget():getName(), 30) - else - trigger.action.outText("+++gA: w is NOT targeting anything") - end - end - end - return false -end ---]]-- function guardianAngel.monitorItem(theItem) local w = theItem.theWeapon @@ -388,64 +369,9 @@ function guardianAngel.monitorItem(theItem) return false -- remove from list end else - --[[-- - if not theItem.lostTrack then - desc = desc .. "Missile LOST TRACK" - - if guardianAngel.announcer then - if guardianAngel.private then - trigger.action.outTextForGroup(ID, desc, 30) - else - trigger.action.outText(desc, 30) - end - end - guardianAngel.invokeCallbacks("trackloss", theItem.targetName, theItem.weaponName) - theItem.lostTrack = true - end - --]]-- - -- theItem.lastDistance = d - -- return true -- true because they can re-acquire! + end - --[[-- - if d > theItem.lastDistance then - -- this can be wrong because if a missile is launched - -- at an angle, it can initially look as if it missed - if not theItem.missed then - desc = desc .. " Missile MISSED!" - - if guardianAngel.announcer then - if guardianAngel.private then - trigger.action.outTextForGroup(ID, desc, 30) - else - trigger.action.outText(desc, 30) - end - end - guardianAngel.invokeCallbacks("miss", theItem.targetName, theItem.weaponName) - theItem.missed = true - end - theItem.lastDistance = d - return true -- better not disregard - they can re-acquire! - end - --]]-- - --[[-- - if theItem.missed and d < theItem.lastDistance then - desc = desc .. " Missile RE-ACQUIRED!" - - if guardianAngel.announcer then - if guardianAngel.private then - trigger.action.outTextForGroup(ID, desc, 30) - else - trigger.action.outText(desc, 30) - end - end - theItem.missed = false - guardianAngel.invokeCallbacks("reacquire", theItem.targetName, theItem.weaponName) - end - --]]-- - --- theItem.lastDistance = d - return true end @@ -729,7 +655,7 @@ function guardianAngel.somethingHappened(event) end end else - trigger.action.outText("***gA: no missile in the air for <" .. wName .. ">!!!!") + trigger.action.outText("***gA: no missile in the air for <" .. wName .. ">!!!!", 30) end -- let's see if the victim was in our list of protected -- units @@ -826,7 +752,6 @@ end function guardianAngel.collectPlayerUnits() -- make sure we have all existing player units -- at start of game --- if not guardianAngel.autoAddPlayer then return end for i=1, 2 do -- currently only two factions in dcs @@ -999,8 +924,3 @@ end --guardianAngel.addCallback(guardianAngel.testCB) --guardianAngel.invokeCallbacks("A", "B", "C") ---[[-- -to do - - turn on and off via flags - - zones that designate protected/unprotected aircraft - --]]-- \ No newline at end of file diff --git a/tutorial & demo missions/demo - Guardian Angel Reloaded.miz b/tutorial & demo missions/demo - Guardian Angel Reloaded.miz new file mode 100644 index 0000000..f291987 Binary files /dev/null and b/tutorial & demo missions/demo - Guardian Angel Reloaded.miz differ diff --git a/tutorial & demo missions/demo - recon mode - reloaded.miz b/tutorial & demo missions/demo - recon mode - reloaded.miz index 9c176bf..ff19c71 100644 Binary files a/tutorial & demo missions/demo - recon mode - reloaded.miz and b/tutorial & demo missions/demo - recon mode - reloaded.miz differ