diff --git a/Doc/DML Documentation.pdf b/Doc/DML Documentation.pdf index 6874369..6827ec1 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 55e4bc9..43938be 100644 Binary files a/Doc/DML Quick Reference.pdf and b/Doc/DML Quick Reference.pdf differ diff --git a/modules/RNDFlags.lua b/modules/RNDFlags.lua index 268696c..6be4f58 100644 --- a/modules/RNDFlags.lua +++ b/modules/RNDFlags.lua @@ -1,5 +1,5 @@ rndFlags = {} -rndFlags.version = "1.0.0" +rndFlags.version = "1.1.0" rndFlags.verbose = false rndFlags.requiredLibs = { "dcsCommon", -- always @@ -13,7 +13,15 @@ rndFlags.requiredLibs = { Version History 1.0.0 - Initial Version - + 1.1.0 - DML flag conversion: + flagArrayFromString: strings OK, trim + remove pollFlag + pollFlag from cfxZones, include zone + randomBetween for pollSize + pollFlag to bang done with inc + getFlagValue in update + some code clean-up + rndMethod synonym --]] rndFlags.rndGen = {} @@ -32,9 +40,9 @@ function rndFlags.flagArrayFromString(inString) local flags = {} local rawElements = dcsCommon.splitString(inString, ",") - + -- go over all elements for idx, anElement in pairs(rawElements) do - if dcsCommon.containsString(anElement, "-") then + if dcsCommon.stringStartsWithDigit(anElement) and dcsCommon.containsString(anElement, "-") then -- interpret this as a range local theRange = dcsCommon.splitString(anElement, "-") local lowerBound = theRange[1] @@ -51,7 +59,7 @@ function rndFlags.flagArrayFromString(inString) -- now add add numbers to flags for f=lowerBound, upperBound do table.insert(flags, f) - --trigger.action.outText("+++RND: added <" .. f .. "> (range)", 30) + end else -- bounds illegal @@ -59,10 +67,10 @@ function rndFlags.flagArrayFromString(inString) end else -- single number - f = tonumber(anElement) + f = dcsCommon.trim(anElement) -- DML flag upgrade: accept strings tonumber(anElement) if f then table.insert(flags, f) - --trigger.action.outText("+++RND: added <" .. f .. "> (single)", 30) + else trigger.action.outText("+++RND: ignored element <" .. anElement .. "> (single)", 30) end @@ -101,8 +109,16 @@ function rndFlags.createRNDWithZone(theZone) theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none") end + if cfxZones.hasProperty(theZone, "in?") then + theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") + end + + if cfxZones.hasProperty(theZone, "rndPoll?") then + theZone.triggerFlag = cfxZones.getStringFromZoneProperty(theZone, "rndPoll?", "none") + end + if theZone.triggerFlag then - theZone.lastTriggerValue = trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value + theZone.lastTriggerValue = cfxZones.getFlagValue(theZone.triggerFlag, theZone) --trigger.misc.getUserFlag(theZone.triggerFlag) -- save last value end theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) @@ -111,7 +127,10 @@ function rndFlags.createRNDWithZone(theZone) theZone.onStart = true end - theZone.method = cfxZones.getStringFromZoneProperty(theZone, "method", "on") + theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "method", "on") + if cfxZones.hasProperty(theZone, "rndMethod") then + theZone.rndMethod = cfxZones.getStringFromZoneProperty(theZone, "rndMethod", "on") + end theZone.reshuffle = cfxZones.getBoolFromZoneProperty(theZone, "reshuffle", false) if theZone.reshuffle then @@ -119,8 +138,6 @@ function rndFlags.createRNDWithZone(theZone) theZone.flagStore = dcsCommon.copyArray(theFlags) end - --theZone.rndPollSize = cfxZones.getBoolFromZoneProperty(theZone, "rndPollSize", false) - -- done flag if cfxZones.hasProperty(theZone, "done+1") then theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "none") @@ -137,42 +154,6 @@ end -- -- fire RND -- -function rndFlags.pollFlag(theFlag, method) - if rndFlags.verbose then - trigger.action.outText("+++RND: 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("+++RND: unknown method <" .. method .. "> - using 'on'", 30) - end - -- default: on. - trigger.action.setUserFlag(theFlag, 1) - end - - local newVal = trigger.misc.getUserFlag(theFlag) - if rndFlags.verbose then - trigger.action.outText("+++RND: flag <" .. theFlag .. "> changed from " .. currVal .. " to " .. newVal, 30) - end -end function rndFlags.fire(theZone) -- fire this rnd @@ -181,38 +162,19 @@ function rndFlags.fire(theZone) rndFlags.reshuffle(theZone) end - local availableFlags = dcsCommon.copyArray(theZone.myFlags)--{} --- for idx, aFlag in pairs(theZone.myFlags) do --- table.insert(availableFlags, aFlag) --- end + local availableFlags = dcsCommon.copyArray(theZone.myFlags) -- do this pollSize times - local pollSize = theZone.pollSize - local pollSizeMin = theZone.pollSizeMin - - if pollSize ~= pollSizeMin then - -- pick random in range , say 3-7 --> 5 items! - pollSize = (pollSize - pollSizeMin) + 1 -- 7-3 + 1 - pollSize = dcsCommon.smallRandom(pollSize) - 1 --> 0-4 --- trigger.action.outText("+++RND: RAW pollsize " .. pollSize, 30) - pollSize = pollSize + pollSizeMin --- trigger.action.outText("+++RND: adj pollsize " .. pollSize, 30) - if pollSize > theZone.pollSize then pollSize = theZone.pollSize end - if pollSize < 1 then pollSize = 1 end - - if rndFlags.verbose then - trigger.action.outText("+++RND: RND " .. theZone.name .. " range " .. pollSizeMin .. "-" .. theZone.pollSize .. ": selected " .. pollSize, 30) - end - end + local pollSize = dcsCommon.randomBetween(theZone.pollSizeMin, theZone.pollSize) + if #availableFlags < 1 then if rndFlags.verbose then trigger.action.outText("+++RND: RND " .. theZone.name .. " ran out of flags. aborting fire", 30) end - if theZone.doneFlag then - local currVal = trigger.misc.getUserFlag(theZone.doneFlag) - trigger.action.setUserFlag(theZone.doneFlag, currVal + 1) + if theZone.doneFlag then + cfxZones.pollFlag(theZone.doneFlag, "inc", theZone) end return @@ -239,8 +201,8 @@ function rndFlags.fire(theZone) -- poll this flag and remove from available local theFlag = table.remove(availableFlags,theFlagIndex) - rndFlags.pollFlag(theFlag, theZone.method) - + --rndFlags.pollFlag(theFlag, theZone.rndMethod) + cfxZones.pollFlag(theFlag, theZone.rndMethod, theZone) end -- remove if requested @@ -258,7 +220,7 @@ function rndFlags.update() for idx, aZone in pairs(rndFlags.rndGen) do if aZone.triggerFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.triggerFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerFlag) if currTriggerVal ~= aZone.lastTriggerValue then if rndFlags.verbose then @@ -347,6 +309,3 @@ if not rndFlags.start() then rndFlags = nil end ---[[ -pulser / repeat until ---]] \ No newline at end of file diff --git a/modules/cfxArtilleryZones.lua b/modules/cfxArtilleryZones.lua index 334872d..d2a6e94 100644 --- a/modules/cfxArtilleryZones.lua +++ b/modules/cfxArtilleryZones.lua @@ -25,7 +25,9 @@ cfxArtilleryZones.verbose = false - made compatible with linked zones - added silent attribute - added transition time to arty command chatter - 2.0.2 - boom?, arty? synonyms + 2.0.2 - boom?, arty? synonyms + 2.1.0 - DML Flag Support + - code cleanup Artillery Target Zones *** EXTENDS ZONES *** Target Zones for artillery. Can determine which zones are in range and visible and then handle artillery barrage to this zone @@ -276,8 +278,7 @@ function cfxArtilleryZones.doFireAt(aZone, maxDistFromCenter) boomArgs.zone = aZone local timeVar = 5 * (2 * dcsCommon.randomPercent() - 1.0) -- +/- 1.5 seconds if timeVar < 0 then timeVar = -timeVar end --- if transitionTime + timeVar < 0 then timeVar = -timeVar end - --boomArgs.tDelta = timeVar + timer.scheduleFunction(cfxArtilleryZones.doBoom, boomArgs, timer.getTime() + transitionTime + timeVar) end @@ -286,22 +287,9 @@ function cfxArtilleryZones.doFireAt(aZone, maxDistFromCenter) end function cfxArtilleryZones.simFireAtZone(aZone, aGroup, dist) - -- all very simple. We simulate shellNum - -- projectiles impacting in aZone - -- before calling doFire, we calculate accuracy - -- for given dist if not dist then dist = aZone.spotRange end - --local transitionTime = 20 -- seconds until shells hit - --transitionTime = aZone.transitionTime - --local shellNum = 17 - --if aZone.shellNum then shellNum = aZone.shellNum end - --local shellBaseStrength = 500 - --if aZone.shellStrength then local shellBaseStrength = aZone.shellStrength - --local shellVariance = 0.2 -- +/-10% - --shellVariance = aZone.shellVariance - --local center = {x=aZone.point.x, y=aZone.landHeight, z=aZone.point.z} -- center of where shells hit local maxAccuracy = 100 -- m radius when close local minAccuracy = 500 -- m radius whan at max sport dist @@ -314,23 +302,7 @@ function cfxArtilleryZones.simFireAtZone(aZone, aGroup, dist) end currAccuracy = math.floor(currAccuracy) cfxArtilleryZones.doFireAt(aZone, currAccuracy) - --[[-- Old code follows - for i=1, shellNum do - - local thePoint = dcsCommon.randomPointInCircle(currAccuracy, 0, center.x, center.z) - thePoint.y = land.getHeight({x=thePoint.x, y=thePoint.z}) - local boomArgs = {} - local strVar = shellBaseStrength * shellVariance - strVar = strVar * (2 * dcsCommon.randomPercent() - 1.0) -- go from -1 to 1 - - boomArgs.strength = shellBaseStrength + strVar - thePoint.y = land.getHeight({x = thePoint.x, y = thePoint.z}) + 1 -- elevate to ground height + 1 - boomArgs.point = thePoint - local timeVar = 5 * (2 * dcsCommon.randomPercent() - 1.0) -- +/- 1.5 seconds - boomArgs.tDelta = timeVar - timer.scheduleFunction(cfxArtilleryZones.doBoom, boomArgs, timer.getTime() + transitionTime + timeVar) - end - --]]-- + aZone.artyCooldownTimer = timer.getTime() + aZone.cooldown -- 120 -- 2 minutes reload if not aZone.silent then local addInfo = " with d=" .. dist .. ", var = " .. currAccuracy .. " pB=" .. shellBaseStrength .. " tt=" .. aZone.transitionTime @@ -360,7 +332,6 @@ function cfxArtilleryZones.simSmokeZone(aZone, aGroup, aColor) local currAccuracy = 200 local thePoint = dcsCommon.randomPointInCircle(currAccuracy, 50, center.x, center.z) --- thePoint.y = land.getHeight({ x = thePoint.x, y = thePoint.z}) timer.scheduleFunction(cfxArtilleryZones.doSmoke, {thePoint, aColor}, timer.getTime() + transitionTime) @@ -387,7 +358,7 @@ function cfxArtilleryZones.update() -- iterate all zones to see if a trigger has changed for idx, aZone in pairs(cfxArtilleryZones.artilleryZones) do if aZone.artyTriggerFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.artyTriggerFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.artyTriggerFlag, aZone) -- trigger.misc.getUserFlag(aZone.artyTriggerFlag) if currTriggerVal ~= aZone.lastTriggerValue then -- a triggered release! @@ -438,17 +409,3 @@ if not cfxArtilleryZones.start() then cfxArtilleryZones = nil end - ---[[-- - -TODO: link artillery units that are starting fire, stop when all inside is destroyed -TODO: "Free" link: look for closest artillery zone that is not cooling down or engaged with diofferent targets and is in range -DONE: smoke target zon -DONE: add smoke to UI menu -DONE: move doBoom from demon to this module -DONE: trigger on flag -DONE: inflight time for arty projectiles -DONE: invoke callback for firing -TODO: duration param for bombardment -TODO: silent attribute ---]]-- \ No newline at end of file diff --git a/modules/cfxObjectSpawnZones.lua b/modules/cfxObjectSpawnZones.lua index d5a38af..1256a92 100644 --- a/modules/cfxObjectSpawnZones.lua +++ b/modules/cfxObjectSpawnZones.lua @@ -1,5 +1,5 @@ cfxObjectSpawnZones = {} -cfxObjectSpawnZones.version = "1.1.5" +cfxObjectSpawnZones.version = "1.2.0" cfxObjectSpawnZones.requiredLibs = { "dcsCommon", -- common is of course needed for everything -- pretty stupid to check for this since we @@ -24,35 +24,8 @@ cfxObjectSpawnZones.ups = 1 -- 1.1.3 - ME-triggered flag via f? and triggerFlag -- 1.1.4 - activate?, pause? attributes -- 1.1.5 - spawn?, spawnObjects? synonyms - --- Object spawn zones have the following major uses: --- - dynamically spawn cargo --- - litter a zone with static obejcts quickly --- - linking static dynamic objects with ships, including cargo --- --- --- How do we recognize an object spawn zone? --- contains a "objectSpawner" attribute --- a spawner must also have the following attributes --- - objectSpawner - anything, must be present to signal. put in 'ground' to be able to expand to other types --- - types - type strings, comma separated. They all spawn in the same spot. --- see here: https://github.com/mrSkortch/DCS-miscScripts/tree/master/ObjectDB --- - count - repeat types n times. optional, defaults to 1 --- - country - defaults to 2 (usa) -- see here https://wiki.hoggitworld.com/view/DCS_enum_country --- some important: 0 = Russia, 2 = US, 82 = UN neutral --- country is converted to coalition and then assigned to --- Joint Task Force upon spawn --- - baseName - MANDATORY, for naming spawned objects - MUST BE UNIQUE!!!! --- - heading in DEGREES (default 0 = north ) direction entire group is facing --- - weight - weight in kg if transportable --- - isCargo - boolean yes means it can be carried by other units --- - cooldown - seconds to cool down before re-spawning --- - maxSpawns - how many times we spawn. default = 1, -1 = unlimited --- - requestable -- via comms menu, will auto-pause --- - managed -- if cargo, it's automatically passed to cfx cargo manager for handling (if cargo manager is loaded) --- - (linkedUnit) for placing on ships --- - (useOffset) for not using ship's center - +-- 1.2.0 - DML flag upgrade + -- respawn currently happens after theSpawns is deleted and cooldown seconds have passed cfxObjectSpawnZones.allSpawners = {} cfxObjectSpawnZones.callbacks = {} -- signature: cb(reason, group, spawner) @@ -83,30 +56,31 @@ function cfxObjectSpawnZones.createSpawner(inZone) -- connect with ME if a trigger flag is given if cfxZones.hasProperty(inZone, "f?") then theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "f?", "none") - theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) end if cfxZones.hasProperty(inZone, "spawn?") then theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawn?", "none") - theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) end if cfxZones.hasProperty(inZone, "spawnObjects?") then theSpawner.triggerFlag = cfxZones.getStringFromZoneProperty(inZone, "spawnObjects?", "none") - theSpawner.lastTriggerValue = trigger.misc.getUserFlag(theSpawner.triggerFlag) end + if theSpawner.triggerFlag then + theSpawner.lastTriggerValue = cfxZones.getFlagValue(theSpawner.triggerFlag, theSpawner) -- trigger.misc.getUserFlag(theSpawner.triggerFlag) + end + + if cfxZones.hasProperty(inZone, "activate?") then theSpawner.activateFlag = cfxZones.getStringFromZoneProperty(inZone, "activate?", "none") - theSpawner.lastActivateValue = trigger.misc.getUserFlag(theSpawner.activateFlag) + theSpawner.lastActivateValue = cfxZones.getFlagValue(theSpawner.activateFlag, theSpawner) --trigger.misc.getUserFlag(theSpawner.activateFlag) end if cfxZones.hasProperty(inZone, "pause?") then theSpawner.pauseFlag = cfxZones.getStringFromZoneProperty(inZone, "pause?", "none") - theSpawner.lastPauseValue = trigger.misc.getUserFlag(theSpawner.pauseFlag) + theSpawner.lastPauseValue = cfxZones.getFlagValue(theSpawner.lastPauseValue, theSpawner) -- trigger.misc.getUserFlag(theSpawner.pauseFlag) end - --theSpawner.types = cfxZones.getZoneProperty(inZone, "types") theSpawner.types = cfxZones.getStringFromZoneProperty(inZone, "types", "White_Tyre") local n = cfxZones.getNumberFromZoneProperty(inZone, "count", 1) -- DO NOT CONFUSE WITH OWN PROPERTY COUNT for unique names!!! if n < 1 then n = 1 end -- sanity check. @@ -140,13 +114,11 @@ function cfxObjectSpawnZones.createSpawner(inZone) theSpawner.requestable = cfxZones.getBoolFromZoneProperty(inZone, "requestable", false) if theSpawner.requestable then theSpawner.paused = true end - -- see if it is linked to a ship to set realtive orig headiong if inZone.linkedUnit then local shipUnit = inZone.linkedUnit theSpawner.linkedUnit = shipUnit - --trigger.action.outText("+++obSpZ: zone " .. inZone.name .. " linked to ship (?) " .. shipUnit:getName() .. " of cat " .. shipUnit:getCategory(), 30) local origHeading = dcsCommon.getUnitHeadingDegrees(shipUnit) @@ -155,10 +127,7 @@ function cfxObjectSpawnZones.createSpawner(inZone) theSpawner.dx = delta.x theSpawner.dy = delta.z - --theSpawner.dx = inZone.dx - --theSpawner.dy = inZone.dy theSpawner.origHeading = origHeading - --trigger.action.outText("+++obSpZ: with dx = " .. theSpawner.dx .. " dy = " .. theSpawner.dy .. " hdg = " .. origHeading, 30) end return theSpawner end @@ -198,18 +167,8 @@ function cfxObjectSpawnZones.getRequestableSpawnersInRange(aPoint, aRange, aSide local delta = dcsCommon.dist(aPoint, cfxZones.getPoint(aZone)) if delta>aRange then hasMatch = false end if aSide ~= 0 then - --[[-- - -- check if side is correct for owned zone - - --]]-- + end - --[[-- - if aSide ~= aSpawner.rawOwner then - -- only return spawners with this side - -- note: this will NOT work with neutral players - hasMatch = false - end - --]]-- if not aSpawner.requestable then hasMatch = false @@ -228,10 +187,6 @@ end -- function cfxObjectSpawnZones.verifySpawnOwnership(spawner) - --[[-- - -- returns false ONLY if masterSpawn disagrees - - --]]-- return true end @@ -433,7 +388,7 @@ function cfxObjectSpawnZones.update() local needsSpawn = cfxObjectSpawnZones.needsSpawning(spawner) -- check if perhaps our watchtrigger causes spawn if spawner.pauseFlag then - local currTriggerVal = trigger.misc.getUserFlag(spawner.pauseFlag) + local currTriggerVal = cfxZones.getFlagValue(spawner.pauseFlag, spawner)-- trigger.misc.getUserFlag(spawner.pauseFlag) if currTriggerVal ~= spawner.lastPauseValue then spawner.paused = true needsSpawn = false @@ -442,7 +397,7 @@ function cfxObjectSpawnZones.update() end if spawner.triggerFlag then - local currTriggerVal = trigger.misc.getUserFlag(spawner.triggerFlag) + local currTriggerVal = cfxZones.getFlagValue(spawner.triggerFlag, spawner)-- trigger.misc.getUserFlag(spawner.triggerFlag) if currTriggerVal ~= spawner.lastTriggerValue then needsSpawn = true spawner.lastTriggerValue = currTriggerVal @@ -450,7 +405,7 @@ function cfxObjectSpawnZones.update() end if spawner.activateFlag then - local currTriggerVal = trigger.misc.getUserFlag(spawner.activateFlag) + local currTriggerVal = spawner.getFlagValue(spawner.activateFlag, spawner) -- trigger.misc.getUserFlag(spawner.activateFlag) if currTriggerVal ~= spawner.lastActivateValue then spawner.paused = false spawner.lastActivateValue = currTriggerVal @@ -517,7 +472,3 @@ if not cfxObjectSpawnZones.start() then cfxObjectSpawnZones = nil end ---[[-- -IMPROVEMENTS - 'formations' - concentric, pile, random, array etc. ---]]-- \ No newline at end of file diff --git a/modules/cfxPlayerScore.lua b/modules/cfxPlayerScore.lua index 1a7482f..fad3660 100644 --- a/modules/cfxPlayerScore.lua +++ b/modules/cfxPlayerScore.lua @@ -1,5 +1,5 @@ cfxPlayerScore = {} -cfxPlayerScore.version = "1.2.0" +cfxPlayerScore.version = "1.3.0" cfxPlayerScore.badSound = "Death BRASS.wav" cfxPlayerScore.scoreSound = "Quest Snare 3.wav" cfxPlayerScore.announcer = true @@ -16,6 +16,13 @@ cfxPlayerScore.announcer = true - announcer attribute - badSound name - scoreSound name + 1.3.0 - object2score + - static objects also can score + - can now also score members of group by adding group name + - scenery objects are now supported. use the + number that is given under OBJECT ID when + using assign as... + --]]-- cfxPlayerScore.requiredLibs = { @@ -54,16 +61,46 @@ function cfxPlayerScore.cat2BaseScore(inCat) return 1 end +function cfxPlayerScore.object2score(inVictim) -- does not have group + if not inVictim then return end + local inName = inVictim:getName() + if not inName then return 0 end + if type(inName) == "number" then + inName = tostring(inName) + end + + local objectScore = cfxPlayerScore.typeScore[inName] + if not objectScore then + -- try the type desc + local theType = inVictim:getTypeName() + objectScore = cfxPlayerScore.typeScore[theType] + end + + if type(objectScore) == "string" then + objectScore = tonumber(objectScore) + end + if not objectScore then return 0 end + return objectScore +end + function cfxPlayerScore.unit2score(inUnit) local vicGroup = inUnit:getGroup() local vicCat = vicGroup:getCategory() local vicType = inUnit:getTypeName() local vicName = inUnit:getName() + if type(vicName) == "number" then vicName = tostring(vicName) end -- simply extend by adding items to the typescore table.concat -- we first try by unit name. This allows individual -- named hi-value targets to have individual scores local uScore = cfxPlayerScore.typeScore[vicName] + + -- see if all members of group score + if not uScore then + local grpName = vicGroup:getName() + uScore = cfxPlayerScore.typeScore[grpName] + end + if uScore == nil then -- WE NOW TRY TO ACCESS BY VICTIM'S TYPE STRING uScore = cfxPlayerScore.typeScore[vicType] @@ -155,6 +192,14 @@ function cfxPlayerScore.isNamedUnit(theUnit) end return false end + +function cfxPlayerScore.awardScoreTo(killSide, theScore, killerName) + local playerScore = cfxPlayerScore.updateScoreForPlayer(killerName, theScore) + + if cfxPlayerScore.announcer then + trigger.action.outTextForCoalition(killSide, "Killscore: " .. theScore .. " for a total of " .. playerScore .. " for " .. killerName, 30) + end +end -- -- EVENT HANDLING -- @@ -167,22 +212,18 @@ function cfxPlayerScore.preProcessor(theEvent) -- there is an initiator, and the initiator is -- a player if theEvent.initiator == nil then - -- trigger.action.outText("+++scr pre: nil INITIATOR", 30) return false end - --trigger.action.outText("+++scr pre: initiator is " .. theEvent.initiator:getName(), 30) local killer = theEvent.initiator if theEvent.target == nil then - if cfxPlayerScore.verbose then trigger.action.outText("+++scr pre: nil TARGET", 30) end + if cfxPlayerScore.verbose then + trigger.action.outText("+++scr pre: nil TARGET", 30) + end return false end local wasPlayer = cfxPlayer.isPlayerUnit(killer) - if wasPlayer then - else - end - return wasPlayer end return false @@ -196,6 +237,7 @@ function cfxPlayerScore.killDetected(theEvent) -- we are only getting called when and if -- a kill occured and killer was a player -- and target exists + local killer = theEvent.initiator local killerName = killer:getPlayerName() if not killerName then killerName = "" end @@ -207,12 +249,19 @@ function cfxPlayerScore.killDetected(theEvent) -- was it a player kill? local pk = cfxPlayer.isPlayerUnit(victim) - -- was it a scenery object + -- was it a scenery object? local wasBuilding = dcsCommon.isSceneryObject(victim) if wasBuilding then + -- these objects have no coalition; we simply award the score if + -- it exists in look-up table. + local staticScore = cfxPlayerScore.object2score(victim) + if staticScore > 0 then + trigger.action.outSoundForCoalition(killSide, cfxPlayerScore.scoreSound) + cfxPlayerScore.awardScoreTo(killSide, staticScore, killerName) + end return end - + -- was it fraternicide? local vicSide = victim:getCoalition() local fraternicide = killSide == vicSide @@ -221,8 +270,26 @@ function cfxPlayerScore.killDetected(theEvent) -- see what kind of unit (category) we killed -- and look up base score - if not victim.getGroup then - if cfxPlayerScore.verbose then trigger.action.outText("+++scr: no group for " .. killVehicle .. ", killed by " .. killerName .. ", no score", 30) end + if not victim.getGroup then + -- static objects have no group + + local staticName = victim:getName() -- on statics, this returns + -- name as entered in TOP LINE + local staticScore = cfxPlayerScore.object2score(victim) + if staticScore > 0 then + -- this was a named static, return the score - unless our own + if fraternicide then + scoreMod = -2 * scoreMod + trigger.action.outSoundForCoalition(killSide, cfxPlayerScore.badSound) + else + trigger.action.outSoundForCoalition(killSide, cfxPlayerScore.scoreSound) + end + staticScore = scoreMod * staticScore + cfxPlayerScore.awardScoreTo(killSide, staticScore, killerName) + else + -- no score, no mentions + end + return end @@ -276,13 +343,8 @@ function cfxPlayerScore.killDetected(theEvent) end local totalScore = unitScore * scoreMod - - local playerScore = cfxPlayerScore.updateScoreForPlayer(killerName, totalScore) - - if cfxPlayerScore.announcer then - trigger.action.outTextForCoalition(killSide, "Killscore: " .. totalScore .. " for a total of " .. playerScore .. " for " .. killerName, 30) - end - --trigger.action.outTextForCoalition(killSide, cfxPlayerScore.scoreTextForPlayerNamed(killerName), 30) + cfxPlayerScore.awardScoreTo(killSide, totalScore, killerName) + end function cfxPlayerScore.readConfigZone(theZone) diff --git a/modules/cfxSmokeZones.lua b/modules/cfxSmokeZones.lua index 96a306f..4fa1737 100644 --- a/modules/cfxSmokeZones.lua +++ b/modules/cfxSmokeZones.lua @@ -13,7 +13,7 @@ cfxSmokeZone.requiredLibs = { - added f? attribute --> onFlag - broke out startSmoke 1.0.4 - startSmoke? synonym - - alphanum flag upgrade + - alphanum DML flag upgrade - random color support SMOKE ZONES *** EXTENDS ZONES *** diff --git a/modules/cfxZones.lua b/modules/cfxZones.lua index 0cfb669..b7b2a61 100644 --- a/modules/cfxZones.lua +++ b/modules/cfxZones.lua @@ -6,7 +6,7 @@ -- cfxZones = {} -cfxZones.version = "2.5.6" +cfxZones.version = "2.5.7" --[[-- VERSION HISTORY - 2.2.4 - getCoalitionFromZoneProperty - getStringFromZoneProperty @@ -50,10 +50,11 @@ cfxZones.version = "2.5.6" - extractPropertyFromDCS trims key and property - 2.5.5 - pollFlag() centralized for banging - allStaticsInZone - - 2.5.6 - flag accessor setFlagValue(), getFlagValue + - 2.5.6 - flag accessor setFlagValue(), getFlagValue() - pollFlag supports theZone as final parameter - randomDelayFromPositiveRange - isMEFlag + - 2.5.7 - pollFlag supports dml flags --]]-- cfxZones.verbose = false @@ -1064,22 +1065,33 @@ function cfxZones.pollFlag(theFlag, method, theZone) trigger.action.outText("+++zones: polling flag " .. theFlag .. " with " .. method, 30) end + if not theZone then + trigger.action.outText("+++zones: nil theZone on pollFlag", 30) + end + method = method:lower() - local currVal = trigger.misc.getUserFlag(theFlag) + --trigger.action.outText("+++zones: polling " .. theZone.name .. " method " .. method .. " flag " .. theFlag, 30) + local currVal = cfxZones.getFlagValue(theFlag, theZone) if method == "inc" or method == "f+1" then - trigger.action.setUserFlag(theFlag, currVal + 1) + --trigger.action.setUserFlag(theFlag, currVal + 1) + cfxZones.setFlagValue(theFlag, currVal+1, theZone) elseif method == "dec" or method == "f-1" then - trigger.action.setUserFlag(theFlag, currVal - 1) - + -- trigger.action.setUserFlag(theFlag, currVal - 1) + cfxZones.setFlagValue(theFlag, currVal-1, theZone) + elseif method == "off" or method == "f=0" then - trigger.action.setUserFlag(theFlag, 0) - + -- trigger.action.setUserFlag(theFlag, 0) + cfxZones.setFlagValue(theFlag, 0, theZone) + elseif method == "flip" or method == "xor" then if currVal ~= 0 then - trigger.action.setUserFlag(theFlag, 0) +-- trigger.action.setUserFlag(theFlag, 0) + cfxZones.setFlagValue(theFlag, 0, theZone) + else - trigger.action.setUserFlag(theFlag, 1) + --trigger.action.setUserFlag(theFlag, 1) + cfxZones.setFlagValue(theFlag, 1, theZone) end else @@ -1087,11 +1099,13 @@ function cfxZones.pollFlag(theFlag, method, theZone) trigger.action.outText("+++zones: unknown method <" .. method .. "> - using 'on'", 30) end -- default: on. - trigger.action.setUserFlag(theFlag, 1) +-- trigger.action.setUserFlag(theFlag, 1) + cfxZones.setFlagValue(theFlag, 1, theZone) + end - local newVal = trigger.misc.getUserFlag(theFlag) if cfxZones.verbose then + local newVal = cfxZones.getFlagValue(theFlag, theZone) trigger.action.outText("+++zones: flag <" .. theFlag .. "> changed from " .. currVal .. " to " .. newVal, 30) end end @@ -1120,7 +1134,7 @@ function cfxZones.setFlagValue(theFlag, theValue, theZone) -- now do wildcard processing. we have alphanumeric if dcsCommon.stringStartsWith(theFlag, "*") then - theFlag = zoneName .. theFlag + theFlag = zoneName .. theFlag end trigger.action.setUserFlag(theFlag, theValue) end @@ -1128,7 +1142,7 @@ end function cfxZones.getFlagValue(theFlag, theZone) local zoneName = "" if not theZone then - trigger.action.outText("+++Zne: no zone on getFlagValue") + trigger.action.outText("+++Zne: no zone on getFlagValue", 30) else zoneName = theZone.name -- for flag wildcards end diff --git a/modules/cloneZone.lua b/modules/cloneZone.lua index 90873c2..db7c1dc 100644 --- a/modules/cloneZone.lua +++ b/modules/cloneZone.lua @@ -1,5 +1,5 @@ cloneZones = {} -cloneZones.version = "1.2.0" +cloneZones.version = "1.3.0" cloneZones.verbose = false cloneZones.requiredLibs = { "dcsCommon", -- always @@ -31,6 +31,7 @@ cloneZones.uniqueCounter = 9200000 -- we start group numbering here - linkUnit resolve - clone? synonym - empty! and method attributes + 1.3.0 - DML flag upgrade --]]-- @@ -179,46 +180,54 @@ function cloneZones.createClonerWithZone(theZone) -- has "Cloner" end end - -- f? and spawn? map to the same + -- f? and spawn? and other synonyms map to the same if cfxZones.hasProperty(theZone, "f?") then theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none") - 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 end - -- synonyms if cfxZones.hasProperty(theZone, "clone?") then theZone.spawnFlag = cfxZones.getStringFromZoneProperty(theZone, "clone?", "none") - theZone.lastSpawnValue = trigger.misc.getUserFlag(theZone.spawnFlag) -- save last value + end + + if theZone.spawnFlag then + theZone.lastSpawnValue = cfxZones.getFlagValue(theZone.spawnFlag, theZone) end -- deSpawn? if cfxZones.hasProperty(theZone, "deSpawn?") then theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "deSpawn?", "none") - theZone.lastDeSpawnValue = trigger.misc.getUserFlag(theZone.deSpawnFlag) -- save last value end + if cfxZones.hasProperty(theZone, "deClone?") then + theZone.deSpawnFlag = cfxZones.getStringFromZoneProperty(theZone, "deClone?", "none") + end + + if theZone.deSpawnFlag then + theZone.lastDeSpawnValue = cfxZones.getFlagValue(theZone.deSpawnFlag, theZone) + end + + -- to be deprecated theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) theZone.moveRoute = cfxZones.getBoolFromZoneProperty(theZone, "moveRoute", false) theZone.preWipe = cfxZones.getBoolFromZoneProperty(theZone, "preWipe", false) + -- to be deprecated if cfxZones.hasProperty(theZone, "empty+1") then - theZone.emptyFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty+1", "") -- note string on number default + theZone.emptyFlag = cfxZones.getStringFromZoneProperty(theZone, "empty+1", "") -- note string on number default end if cfxZones.hasProperty(theZone, "empty!") then - theZone.emptyBangFlag = cfxZones.getNumberFromZoneProperty(theZone, "empty!", "") -- note string on number default + theZone.emptyBangFlag = cfxZones.getStringFromZoneProperty(theZone, "empty!", "") -- note string on number default end theZone.method = cfxZones.getStringFromZoneProperty(theZone, "method", "inc") @@ -804,11 +813,13 @@ function cloneZones.hasLiveUnits(theZone) end -- old code, deprecated +--[[-- function cloneZones.pollFlag(flagNum, method) -- we currently ignore method local num = trigger.misc.getUserFlag(flagNum) trigger.action.setUserFlag(flagNum, num+1) end +--]]-- -- -- UPDATE -- @@ -818,7 +829,7 @@ function cloneZones.update() for idx, aZone in pairs(cloneZones.cloners) do -- see if deSpawn was pulled. Must run before spawn if aZone.deSpawnFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.deSpawnFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.deSpawnFlag, aZone) -- trigger.misc.getUserFlag(aZone.deSpawnFlag) if currTriggerVal ~= aZone.lastDeSpawnValue then if cloneZones.verbose then trigger.action.outText("+++clnZ: DEspawn triggered for <" .. aZone.name .. ">", 30) @@ -830,7 +841,7 @@ function cloneZones.update() -- see if we got spawn? command if aZone.spawnFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.spawnFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.spawnFlag, aZone) -- trigger.misc.getUserFlag(aZone.spawnFlag) if currTriggerVal ~= aZone.lastSpawnValue then if cloneZones.verbose then @@ -846,11 +857,15 @@ function cloneZones.update() if isEmpty then -- see if we need to bang a flag if aZone.emptyFlag then - cloneZones.pollFlag(aZone.emptyFlag) + --cloneZones.pollFlag(aZone.emptyFlag) + cfxZones.pollFlag(aZone.emptyFlag, 'inc', aZone) end if aZone.emptyBangFlag then - cfxZones.pollFlag(aZone.emptyBangFlag, aZone.method) + cfxZones.pollFlag(aZone.emptyBangFlag, aZone.method, aZone) + if cloneZones.verbose then + trigger.action.outText("+++clnZ: bang! on " .. aZone.emptyBangFlag, 30) + end end -- invoke callbacks cloneZones.invokeCallbacks(aZone, "empty", {}) diff --git a/modules/countDown.lua b/modules/countDown.lua index 2f391de..2516fe7 100644 --- a/modules/countDown.lua +++ b/modules/countDown.lua @@ -1,6 +1,7 @@ countDown = {} -countDown.version = "1.1.0" +countDown.version = "1.2.0" countDown.verbose = true +countDown.ups = 1 countDown.requiredLibs = { "dcsCommon", -- always "cfxZones", -- Zones, of course @@ -16,6 +17,9 @@ countDown.requiredLibs = { - corrected verbose (erroneously always suppressed) - triggerFlag --> triggerCountFlag 1.1.1 - corrected bug in invokeCallback + 1.2.0 - DML Flags + - counterOut! + - ups config --]]-- @@ -85,33 +89,37 @@ function countDown.createCountDownWithZone(theZone) -- trigger flag "count" / "start?" if cfxZones.hasProperty(theZone, "count?") then - theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "none") + theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "count?", "") end -- can also use in? for counting. we always use triggerCountFlag if cfxZones.hasProperty(theZone, "in?") then - theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "none") + theZone.triggerCountFlag = cfxZones.getStringFromZoneProperty(theZone, "in?", "") end if theZone.triggerCountFlag then - theZone.lastCountTriggerValue = trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value + theZone.lastCountTriggerValue = cfxZones.getFlagValue(theZone.triggerCountFlag, theZone) -- trigger.misc.getUserFlag(theZone.triggerCountFlag) -- save last value end -- zero! bang if cfxZones.hasProperty(theZone, "zero!") then - theZone.zeroFlag = cfxZones.getNumberFromZoneProperty(theZone, "zero!", -1) + theZone.zeroFlag = cfxZones.getStringFromZoneProperty(theZone, "zero!", "") end if cfxZones.hasProperty(theZone, "out!") then - theZone.zeroFlag = cfxZones.getNumberFromZoneProperty(theZone, "out!", -1) + theZone.zeroFlag = cfxZones.getStringFromZoneProperty(theZone, "out!", "") end -- TMinus! bang if cfxZones.hasProperty(theZone, "tMinus!") then - theZone.tMinusFlag = cfxZones.getNumberFromZoneProperty(theZone, "tMinus!", -1) + theZone.tMinusFlag = cfxZones.getStringFromZoneProperty(theZone, "tMinus!", "") end + -- counterOut val + if cfxZones.hasProperty(theZone, "counterOut!") then + theZone.counterOut = cfxZones.getStringFromZoneProperty(theZone, "counterOut!", "") + end end -- @@ -128,6 +136,10 @@ function countDown.isTriggered(theZone) local belowZero = false local looping = false + if theZone.counterOut then + cfxZones.setFlagValue(theZone.counterOut, val, theZone) + end + if val > 0 then tMinus = true -- see if we need to bang Tminus @@ -135,7 +147,7 @@ function countDown.isTriggered(theZone) if countDown.verbose then trigger.action.outText("+++cntD: TMINUTS", 30) end - cfxZones.pollFlag(theZone.tMinusFlag, theZone.method) + cfxZones.pollFlag(theZone.tMinusFlag, theZone.method, theZone) end elseif val == 0 then @@ -145,7 +157,7 @@ function countDown.isTriggered(theZone) if countDown.verbose then trigger.action.outText("+++cntD: ZERO", 30) end - cfxZones.pollFlag(theZone.zeroFlag, theZone.method) + cfxZones.pollFlag(theZone.zeroFlag, theZone.method, theZone) end if theZone.loop then @@ -164,7 +176,7 @@ function countDown.isTriggered(theZone) if countDown.verbose then trigger.action.outText("+++cntD: Below Zero", 30) end - cfxZones.pollFlag(theZone.zeroFlag, theZone.method) + cfxZones.pollFlag(theZone.zeroFlag, theZone.method, theZone) end end @@ -178,20 +190,20 @@ function countDown.isTriggered(theZone) end function countDown.update() - -- call me in a second to poll triggers - timer.scheduleFunction(countDown.update, {}, timer.getTime() + 1) + -- call me in a second/ups to poll triggers + timer.scheduleFunction(countDown.update, {}, timer.getTime() + 1/countDown.ups) for idx, aZone in pairs(countDown.counters) do -- make sure to re-start before reading time limit if aZone.triggerCountFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerCountFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.triggerCountFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerCountFlag) if currTriggerVal ~= aZone.lastCountTriggerValue then if countDown.verbose then trigger.action.outText("+++cntD: triggered on in?", 30) end countDown.isTriggered(aZone) - aZone.lastCountTriggerValue = trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value + aZone.lastCountTriggerValue = cfxZones.getFlagValue(aZone.triggerCountFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerCountFlag) -- save last value end end end @@ -209,6 +221,11 @@ function countDown.readConfigZone() return end + countDown.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 1) + -- slowest is once avery 1000 seconds = 17 minutes, doesn't make much sense slower than 1/second anyway + + if countDown.ups < 0.001 then countDown.ups = 0.001 end + countDown.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) if countDown.verbose then diff --git a/modules/delayFlags.lua b/modules/delayFlags.lua index 0629083..4f78423 100644 --- a/modules/delayFlags.lua +++ b/modules/delayFlags.lua @@ -1,5 +1,5 @@ delayFlag = {} -delayFlag.version = "1.0.4" +delayFlag.version = "1.1.0" delayFlag.verbose = false delayFlag.requiredLibs = { "dcsCommon", -- always @@ -23,6 +23,11 @@ delayFlag.flags = {} - removed message attribute, moved to own module - triggerFlag --> triggerDelayFlag 1.0.4 - startDelay + 1.1.0 - DML flag upgrade + - removed onStart. use local raiseFlag instead + - delayDone! synonym + - pauseDelay? + - unpauseDelay? --]]-- @@ -69,7 +74,7 @@ function delayFlag.createTimerWithZone(theZone) end if theZone.triggerDelayFlag then - theZone.lastDelayTriggerValue = trigger.misc.getUserFlag(theZone.triggerDelayFlag) -- save last value + theZone.lastDelayTriggerValue = cfxZones.getFlagValue(theZone.triggerDelayFlag, theZone) -- trigger.misc.getUserFlag(theZone.triggerDelayFlag) -- save last value end @@ -77,17 +82,24 @@ function delayFlag.createTimerWithZone(theZone) -- out flag if cfxZones.hasProperty(theZone, "out!") then - theZone.outFlag = cfxZones.getNumberFromZoneProperty(theZone, "out!", -1) + theZone.delayDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "out!", -1) end - -- on start - if cfxZones.hasProperty(theZone, "onStart") then - theZone.onStart = cfxZones.getBoolFromZoneProperty(theZone, "onStart", false) + if cfxZones.hasProperty(theZone, "delayDone!") then + theZone.delayDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "delayDone!", -1) end + + -- stop the press! + if cfxZones.hasProperty(theZone, "stopDelay?") then + theZone.triggerStopDelay = cfxZones.getStringFromZoneProperty(theZone, "stopDelay?", "none") + theZone.lastTriggerStopValue = cfxZones.getFlagValue(theZone.triggerStopDelay, theZone) + end + + -- init - theZone.running = false + theZone.delayRunning = false theZone.timeLimit = -1 end @@ -99,7 +111,7 @@ end function delayFlag.startDelay(theZone) -- refresh timer - theZone.running = true + theZone.delayRunning = true -- set new expiry date local delayMax = theZone.delayMax @@ -129,13 +141,24 @@ function delayFlag.update() local now = timer.getTime() for idx, aZone in pairs(delayFlag.flags) do + -- see if we need to stop + if aZone.triggerStopDelay then + local currTriggerVal = cfxZones.getFlagValue(aZone.triggerStopDelay, aZone) + if currTriggerVal ~= lastTriggerStopValue then + aZone.delayRunning = false -- simply stop. + if delayFlag.verbose then + trigger.action.outText("+++dlyF: stopped delay " .. aZone.name, 30) + end + end + end + -- make sure to re-start before reading time limit if aZone.triggerDelayFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.triggerDelayFlag) + local currTriggerVal = cfxZones.getFlagValue(aZone.triggerDelayFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerDelayFlag) if currTriggerVal ~= aZone.lastDelayTriggerValue then if delayFlag.verbose then - if aZone.running then + if aZone.delayRunning then trigger.action.outText("+++dlyF: re-starting timer " .. aZone.name, 30) else trigger.action.outText("+++dlyF: init timer for " .. aZone.name, 30) @@ -146,17 +169,16 @@ function delayFlag.update() end end - if aZone.running then + if aZone.delayRunning then -- check expiry if now > aZone.timeLimit then -- end timer - aZone.running = false + aZone.delayRunning = false -- poll flag - cfxZones.pollFlag(aZone.outFlag, aZone.method) - -- say message - --if aZone.myMessage then - -- trigger.action.outText(aZone.myMessage, 30) - --end + cfxZones.pollFlag(aZone.delayDoneFlag, aZone.method, aZone) + if delayFlag.verbose then + trigger.action.outText("+++dlyF: banging on " .. aZone.delayDoneFlag, 30) + end end end @@ -167,7 +189,7 @@ end -- START -- function delayFlag.readConfigZone() - local theZone = cfxZones.getZoneByName("delayZonesConfig") + local theZone = cfxZones.getZoneByName("delayFlagsConfig") if not theZone then if delayFlag.verbose then trigger.action.outText("+++dlyF: NO config zone!", 30) @@ -182,6 +204,7 @@ function delayFlag.readConfigZone() end end +--[[-- function delayFlag.onStart() for idx, theZone in pairs(delayFlag.flags) do if theZone.onStart then @@ -192,6 +215,7 @@ function delayFlag.onStart() end end end +--]]-- function delayFlag.start() -- lib check @@ -215,7 +239,7 @@ function delayFlag.start() end -- kick onStart - delayFlag.onStart() + --delayFlag.onStart() -- start update delayFlag.update() diff --git a/modules/messenger.lua b/modules/messenger.lua index 34a8257..6727a59 100644 --- a/modules/messenger.lua +++ b/modules/messenger.lua @@ -1,5 +1,5 @@ messenger = {} -messenger.version = "1.0.1" +messenger.version = "1.1.0" messenger.verbose = false messenger.requiredLibs = { "dcsCommon", -- always @@ -11,6 +11,10 @@ messenger.messengers = {} 1.0.0 - initial version 1.0.1 - messageOut? synonym - spelling types in about + 1.1.0 - DML flag support + - clearScreen option + - inValue? + - message preprocessor --]]-- @@ -41,11 +45,13 @@ function messenger.createMessengerDownWithZone(theZone) theZone.soundFile = cfxZones.getStringFromZoneProperty(theZone, "soundFile", "") + theZone.clearScreen = cfxZones.getBoolFromZoneProperty(theZone, "clearScreen", false) + -- alternate version: messages: list of messages, need string parser first theZone.duration = cfxZones.getNumberFromZoneProperty(theZone, "duration", 30) - -- trigger flag "count" / "start?" + -- trigger flag f? in? messageOut? if cfxZones.hasProperty(theZone, "f?") then theZone.triggerMessagerFlag = cfxZones.getStringFromZoneProperty(theZone, "f?", "none") end @@ -60,31 +66,57 @@ function messenger.createMessengerDownWithZone(theZone) end if theZone.triggerMessagerFlag then - theZone.lastMessageTriggerValue = trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value + theZone.lastMessageTriggerValue = cfxZones.getFlagValue(theZone.triggerMessagerFlag, theZone)-- trigger.misc.getUserFlag(theZone.triggerMessagerFlag) -- save last value end if cfxZones.hasProperty(theZone, "coalition") then theZone.coalition = cfxZones.getCoalitionFromZoneProperty(theZone, "coalition", 0) end + -- flag whose value can be read + if cfxZones.hasProperty(theZone, "messageValue?") then + theZone.messageValue = cfxZones.getStringFromZoneProperty(theZone, "messageValue?", "") + end + end -- -- Update -- +function messenger.getMessage(theZone) + local msg = theZone.message + -- see if it has a "$val" in there + local zName = theZone.name + if not zName then zName = "" end + local zVal = "" + if theZone.messageValue then + zVal = cfxZones.getFlagValue(theZone.messageValue, theZone) + zVal = tostring(zVal) + if not zVal then zVal = "" end + end + + + -- replace *zone and *value wildcards + msg = string.gsub(msg, "*name", zName) + msg = string.gsub(msg, "*value", zVal) + + return msg +end + function messenger.isTriggered(theZone) -- this module has triggered local fileName = "l10n/DEFAULT/" .. theZone.soundFile - local msg = theZone.message + local msg = messenger.getMessage(theZone) + 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.outTextForCoalition(theZone.coalition, msg, theZone.duration, theZone.clearScreen) trigger.action.outSoundForCoalition(theZone.coalition, fileName) else -- out to all - trigger.action.outText(msg, theZone.duration) + trigger.action.outText(msg, theZone.duration, theZone.clearScreen) trigger.action.outSound(fileName) end end @@ -96,14 +128,14 @@ function messenger.update() 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) + local currTriggerVal = cfxZones.getFlagValue(aZone.triggerMessagerFlag, aZone) -- 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 + aZone.lastMessageTriggerValue = cfxZones.getFlagValue(aZone.triggerMessagerFlag, aZone) -- trigger.misc.getUserFlag(aZone.triggerMessagerFlag) -- save last value end end end @@ -159,4 +191,9 @@ end if not messenger.start() then trigger.action.outText("cfx Messenger aborted: missing libraries", 30) messenger = nil -end \ No newline at end of file +end + +--[[-- +Wildcard extension: + messageValue supports multiple flags like 1-3, *hi ther, *bingo and then *value[name] returns that value +--]]-- \ No newline at end of file diff --git a/modules/pulseFlags.lua b/modules/pulseFlags.lua index 47e7e77..7267d59 100644 --- a/modules/pulseFlags.lua +++ b/modules/pulseFlags.lua @@ -1,5 +1,5 @@ pulseFlags = {} -pulseFlags.version = "1.0.3" +pulseFlags.version = "1.1.0" pulseFlags.verbose = false pulseFlags.requiredLibs = { "dcsCommon", -- always @@ -18,6 +18,15 @@ pulseFlags.requiredLibs = { uses randomDelayFromPositiveRange flag! now is string WARNING: still needs full alphaNum flag upgrade + - 1.1.0 Full DML flag integration + removed zone! + made pulse and pulse! the out flag carrier + done! + pulsesDone! synonym + pausePulse? synonym + pulseMethod synonym + startPulse? synonym + pulseStopped synonym --]]-- @@ -32,8 +41,14 @@ end -- function pulseFlags.createPulseWithZone(theZone) - theZone.flag = cfxZones.getStringFromZoneProperty(theZone, "flag!", -1) -- the flag to pulse + if cfxZones.hasProperty(theZone, "pulse") then + theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse", "*none") -- the flag to pulse + end + if cfxZones.hasProperty(theZone, "pulse!") then + theZone.pulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pulse!", "*none") -- the flag to pulse + end + -- time can be number, or number-number range theZone.minTime, theZone.time = cfxZones.getPositiveRangeFromZoneProperty(theZone, "time", 1) if pulseFlags.verbose then @@ -45,23 +60,45 @@ function pulseFlags.createPulseWithZone(theZone) -- trigger flags if cfxZones.hasProperty(theZone, "activate?") then - theZone.activateFlag = cfxZones.getStringFromZoneProperty(theZone, "activate?", "none") - theZone.lastActivateValue = trigger.misc.getUserFlag(theZone.activateFlag) -- save last value + theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "activate?", "none") + theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value + end + + if cfxZones.hasProperty(theZone, "startPulse?") then + theZone.activatePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "startPulse?", "none") + theZone.lastActivateValue = cfxZones.getFlagValue(theZone.activatePulseFlag, theZone) -- trigger.misc.getUserFlag(theZone.activatePulseFlag) -- save last value end if cfxZones.hasProperty(theZone, "pause?") then - theZone.pauseFlag = cfxZones.getStringFromZoneProperty(theZone, "pause?", "none") - theZone.lastPauseValue = trigger.misc.getUserFlag(theZone.pauseFlag) -- save last value + theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pause?", "*none") + theZone.lastPauseValue = cfxZones.getFlagValue(theZone.lastPauseValue, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value end - theZone.paused = cfxZones.getBoolFromZoneProperty(theZone, "paused", false) + if cfxZones.hasProperty(theZone, "pausePulse?") then + theZone.pausePulseFlag = cfxZones.getStringFromZoneProperty(theZone, "pausePulse?", "*none") + theZone.lastPauseValue = cfxZones.getFlagValue(theZone.lastPauseValue, theZone)-- trigger.misc.getUserFlag(theZone.pausePulseFlag) -- save last value + end + theZone.pulsePaused = cfxZones.getBoolFromZoneProperty(theZone, "paused", false) + + if cfxZones.hasProperty(theZone, "pulseStopped") then + theZone.pulsePaused = cfxZones.getBoolFromZoneProperty(theZone, "pulseStopped", false) + end theZone.method = cfxZones.getStringFromZoneProperty(theZone, "method", "flip") + if cfxZones.hasProperty(theZone, "pulseMethod") then + theZone.method = cfxZones.getStringFromZoneProperty(theZone, "pulseMethod", "flip") + end -- done flag if cfxZones.hasProperty(theZone, "done+1") then - theZone.doneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "none") + theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done+1", "*none") + end + if cfxZones.hasProperty(theZone, "pulsesDone!") then + theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "pulsesDone!", "*none") + end + if cfxZones.hasProperty(theZone, "done!") then + theZone.pulseDoneFlag = cfxZones.getStringFromZoneProperty(theZone, "done!", "*none") end theZone.pulsing = false -- not running @@ -78,7 +115,7 @@ function pulseFlags.doPulse(args) local theZone = args[1] -- check if we have been paused. if so, simply -- exit with no new schedule - if theZone.paused then + if theZone.pulsePaused then theZone.pulsing = false return end @@ -86,7 +123,11 @@ function pulseFlags.doPulse(args) -- do a poll on flags -- first, we only do an initial pulse if zeroPulse is set if theZone.hasPulsed or theZone.zeroPulse then - cfxZones.pollFlag(theZone.flag, theZone.method, theZone) + if pulseFlags.verbose then + trigger.action.outText("+++pulF: will bang " .. theZone.pulseFlag, 30); + end + + cfxZones.pollFlag(theZone.pulseFlag, theZone.method, theZone) -- decrease count if theZone.pulses > 0 then @@ -96,15 +137,15 @@ function pulseFlags.doPulse(args) -- 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) + if theZone.pulseDoneFlag then + --local currVal = cfxZones.getFlagValue(theZone.pulseDoneFlag, theZone)-- trigger.misc.getUserFlag(theZone.pulseDoneFlag) + cfxZones.pollFlag(theZone.pulseDoneFlag, "inc", theZone) -- trigger.action.setUserFlag(theZone.pulseDoneFlag, currVal + 1) end if pulseFlags.verbose then trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> ended!", 30) end theZone.pulsing = false - theZone.paused = true + theZone.pulsePaused = true return end end @@ -117,18 +158,8 @@ function pulseFlags.doPulse(args) 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 - local varPart = delay - theZone.minTime + 1 - varPart = dcsCommon.smallRandom(varPart) - 1 - delay = theZone.minTime + varPart - end - --]]-- local delay = cfxZones.randomDelayFromPositiveRange(theZone.minTime, theZone.time) - --trigger.action.outText("***PulF: pulse <" .. theZone.name .. "> scheduled in ".. delay .."!", 30) -- schedule in delay time theZone.timerID = timer.scheduleFunction(pulseFlags.doPulse, args, timer.getTime() + delay) @@ -162,7 +193,7 @@ function pulseFlags.update() else -- this zone has not scheduled a new pulse -- let's see why - if aZone.paused then + if aZone.pulsePaused then -- ok, zone is paused. all clear else -- zone isn't paused. we need to start the zone @@ -171,24 +202,28 @@ function pulseFlags.update() end -- see if we got a pause or activate command - if aZone.activateFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.activateFlag) + if aZone.activatePulseFlag then + local currTriggerVal = cfxZones.getFlagValue(aZone.activatePulseFlag, aZone) -- trigger.misc.getUserFlag(aZone.activatePulseFlag) if currTriggerVal ~= aZone.lastActivateValue then - trigger.action.outText("+++PulF: activating <" .. aZone.name .. ">", 30) + if pulseFlags.verbose then + trigger.action.outText("+++PulF: activating <" .. aZone.name .. ">", 30) + end aZone.lastActivateValue = currTriggerVal - aZone.paused = false -- will start anew + aZone.pulsePaused = false -- will start anew end end - if aZone.pauseFlag then - local currTriggerVal = trigger.misc.getUserFlag(aZone.pauseFlag) + if aZone.pausePulseFlag then + local currTriggerVal = cfxZones.getFlagValue(aZone.pausePulseFlag, aZone)-- trigger.misc.getUserFlag(aZone.pausePulseFlag) if currTriggerVal ~= aZone.lastPauseValue then - trigger.action.outText("+++PulF: pausing <" .. aZone.name .. ">", 30) + if pulseFlags.verbose then + trigger.action.outText("+++PulF: pausing <" .. aZone.name .. ">", 30) + end aZone.lastPauseValue = currTriggerVal - aZone.paused = true -- prevents new start + aZone.pulsePaused = true -- prevents new start if aZone.timerID then timer.removeFunction(aZone.timerID) aZone.timerID = nil @@ -242,6 +277,15 @@ function pulseFlags.start() pulseFlags.addPulse(aZone) -- remember it so we can pulse it end + local attrZones = cfxZones.getZonesWithAttributeNamed("pulse!") + + -- now create a pulse gen for each one and add them + -- to our watchlist + for k, aZone in pairs(attrZones) do + pulseFlags.createPulseWithZone(aZone) -- process attribute and add to zone + pulseFlags.addPulse(aZone) -- remember it so we can pulse it + end + -- start update in 1 second --pulseFlags.update() timer.scheduleFunction(pulseFlags.update, {}, timer.getTime() + 1) diff --git a/modules/raiseFlag.lua b/modules/raiseFlag.lua index 3705c40..6358aa3 100644 --- a/modules/raiseFlag.lua +++ b/modules/raiseFlag.lua @@ -1,5 +1,5 @@ raiseFlag = {} -raiseFlag.version = "1.0.0" +raiseFlag.version = "1.0.1" raiseFlag.verbose = false raiseFlag.requiredLibs = { "dcsCommon", -- always @@ -11,6 +11,8 @@ raiseFlag.flags = {} Version History 1.0.0 - initial release + 1.0.1 - synonym "raiseFlag!" + --]]-- function raiseFlag.addRaiseFlag(theZone) table.insert(raiseFlag.flags, theZone) @@ -32,8 +34,12 @@ end -- function raiseFlag.createRaiseFlagWithZone(theZone) -- get flag from faiseFlag itself - theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag", "") -- the flag to raise - + if cfxZones.hasProperty(theZone, "raiseFlag") then + theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag", "") -- the flag to raise + else + theZone.raiseFlag = cfxZones.getStringFromZoneProperty(theZone, "raiseFlag!", "") -- the flag to raise + end + theZone.flagValue = cfxZones.getNumberFromZoneProperty(theZone, "value", 1) -- value to set to theZone.minAfterTime, theZone.maxAfterTime = cfxZones.getPositiveRangeFromZoneProperty(theZone, "afterTime", -1) @@ -109,7 +115,7 @@ function raiseFlag.start() trigger.action.outText("cfx raise flag requires dcsCommon", 30) return false end - if not dcsCommon.libCheck("cfx Count Down", raiseFlag.requiredLibs) then + if not dcsCommon.libCheck("cfx Raise Flag", raiseFlag.requiredLibs) then return false end @@ -122,6 +128,12 @@ function raiseFlag.start() raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes raiseFlag.addRaiseFlag(aZone) -- add to list end + -- try synonym + attrZones = cfxZones.getZonesWithAttributeNamed("raiseFlag!") + for k, aZone in pairs(attrZones) do + raiseFlag.createRaiseFlagWithZone(aZone) -- process attributes + raiseFlag.addRaiseFlag(aZone) -- add to list + end -- start update raiseFlag.update() diff --git a/modules/unGrief.lua b/modules/unGrief.lua new file mode 100644 index 0000000..428ff92 --- /dev/null +++ b/modules/unGrief.lua @@ -0,0 +1,119 @@ +unGrief = {} +unGrief.version = "1.0.0" +unGrief.verbose = false +unGrief.requiredLibs = { + "dcsCommon", -- always + "cfxZones", -- Zones, of course +} + +unGrief.enabledFlagValue = 0 -- DO NOT CHANGE, MUST MATCH SSB +unGrief.disabledFlagValue = unGrief.enabledFlagValue + 100 -- DO NOT CHANGE +--[[-- + unGrief - allow only so many friendly kills. + + Version History + 1.0.0 - initial release + +--]]-- + +unGrief.griefers = {} -- offenders are stored here + +-- event proccer +function unGrief:onEvent(theEvent) + if not theEvent then return end + if theEvent.id ~= 28 then return end -- only S_EVENT_KILL events allowed + if not theEvent.initiator then return end -- no initiator, no interest + if not theEvent.target then return end -- wtf happened here? begone! + local killer = theEvent.initiator + if not killer:isExist() then return end -- may have exited already + local stiff = theEvent.target + if not killer.getPlayerName then return end -- wierd stuff happening here + local playerName = killer:getPlayerName() + if not playerName then return end -- AI kill, not interesting + + -- map (scenery) objects don't have coalition, so check this first + if not stiff.getCoalition then return end + + -- get the two coalitions involved + local killSide = killer:getCoalition() + local stiffSide = stiff:getCoalition() + + if killSide ~= stiffSide then return end -- fair & square + + -- if we get here, we have a problem. + local previousKills = unGrief.griefers[playerName] + if not previousKills then previousKills = 0 end + + previousKills = previousKills + 1 + unGrief.griefers[playerName] = previousKills + + if previousKills <= unGrief.graceKills then + -- ok, let them off with a warning + trigger.action.outText(playerName .. " has killed one of their own. YOU ARE ON NOTICE!", 30) + return + end + + -- ok, time to get serious + trigger.action.outText(playerName .. " is killing their own. ".. previousKills .. " kills recorded so far. We disaprove", 30) + + -- lets set them up the bomb + local p = killer:getPoint() + + if unGrief.retaliation == "ssb" then + -- use ssb to kick/block the entire group + local theGroup = killer:getGroup() + if not theGroup then return end -- you got lucky! + local groupName = theGroup:getName() + -- tell ssb to kick now: + trigger.action.setUserFlag(groupName, unGrief.disabledFlagValue) + return + end + -- aaand all your base are belong to us! + trigger.action.explosion(p, 100) + trigger.action.outText("Have a nice day, " .. playerName, 30) + -- (or kick via SSB or do some other stuff. be creative to boot this idiot) +end + +function unGrief.readConfigZone() + local theZone = cfxZones.getZoneByName("unGriefConfig") + if not theZone then + if unGrief.verbose then + trigger.action.outText("+++uGrf: NO config zone!", 30) + end + return + end + + unGrief.verbose = cfxZones.getBoolFromZoneProperty(theZone, "verbose", false) + + unGrief.graceKills = cfxZones.getNumberFromZoneProperty(theZone, "graceKills", 1) + unGrief.retaliation = cfxZones.getStringFromZoneProperty(theZone, "retaliation", "boom") -- other possible methods: ssb + if unGrief.verbose then + trigger.action.outText("+++uGrf: read config", 30) + end +end + +function unGrief.start() + -- lib check + if not dcsCommon.libCheck then + trigger.action.outText("cfx unGrief requires dcsCommon", 30) + return false + end + if not dcsCommon.libCheck("cfx unGrief", unGrief.requiredLibs) then + return false + end + + -- read config + unGrief.readConfigZone() + + -- connect event proccer + world.addEventHandler(unGrief) + + trigger.action.outText("cfx unGrief v" .. unGrief.version .. " started.", 30) + return true +end + +-- let's go! +if not unGrief.start() then + trigger.action.outText("cfx unGrief aborted: missing libraries", 30) + unGrief = nil +end diff --git a/tutorial & demo missions/demo - Pulsing Fun.miz b/tutorial & demo missions/demo - Pulsing Fun.miz index f6d656c..72bcb03 100644 Binary files a/tutorial & demo missions/demo - Pulsing Fun.miz and b/tutorial & demo missions/demo - Pulsing Fun.miz differ diff --git a/tutorial & demo missions/demo - Random Glory.miz b/tutorial & demo missions/demo - Random Glory.miz index 8d0e34f..623dc60 100644 Binary files a/tutorial & demo missions/demo - Random Glory.miz and b/tutorial & demo missions/demo - Random Glory.miz differ diff --git a/tutorial & demo missions/demo - The Zonal Countdown.miz b/tutorial & demo missions/demo - The Zonal Countdown.miz new file mode 100644 index 0000000..c9bd74a Binary files /dev/null and b/tutorial & demo missions/demo - The Zonal Countdown.miz differ diff --git a/tutorial & demo missions/demo - flag fun.miz b/tutorial & demo missions/demo - flag fun.miz index db39f1d..5486a64 100644 Binary files a/tutorial & demo missions/demo - flag fun.miz and b/tutorial & demo missions/demo - flag fun.miz differ diff --git a/tutorial & demo missions/demo - more score.miz b/tutorial & demo missions/demo - more score.miz new file mode 100644 index 0000000..d71560a Binary files /dev/null and b/tutorial & demo missions/demo - more score.miz differ diff --git a/tutorial & demo missions/full - frog men combat training.miz b/tutorial & demo missions/full - frog men combat training.miz index 0b585e6..58ad78c 100644 Binary files a/tutorial & demo missions/full - frog men combat training.miz and b/tutorial & demo missions/full - frog men combat training.miz differ