mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
2.3.6
Yeller Model, The Debugger -x !, heloTroops' dropZones
This commit is contained in:
parent
0c1eb53a89
commit
b498a4e803
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
|||||||
cfxCargoReceiver = {}
|
cfxCargoReceiver = {}
|
||||||
cfxCargoReceiver.version = "2.0.0"
|
cfxCargoReceiver.version = "2.1.0"
|
||||||
cfxCargoReceiver.ups = 1 -- once a second
|
cfxCargoReceiver.ups = 1 -- once a second
|
||||||
cfxCargoReceiver.maxDirectionRange = 500 -- in m. distance when cargo manager starts talking to pilots who are carrying that cargo
|
cfxCargoReceiver.maxDirectionRange = 500 -- in m. distance when cargo manager starts talking to pilots who are carrying that cargo
|
||||||
cfxCargoReceiver.requiredLibs = {
|
cfxCargoReceiver.requiredLibs = {
|
||||||
@ -12,7 +12,10 @@ cfxCargoReceiver.requiredLibs = {
|
|||||||
- 2.0.0 no more cfxPlayer Dependency
|
- 2.0.0 no more cfxPlayer Dependency
|
||||||
dmlZones, OOP
|
dmlZones, OOP
|
||||||
clean-up
|
clean-up
|
||||||
|
- 2.1.0 code maintenance
|
||||||
|
cargo gets removed from mgr when touching ground
|
||||||
|
switch to cargoReceiver!
|
||||||
|
noBounce attribute
|
||||||
|
|
||||||
CargoReceiver is a zone enhancement you use to be automatically
|
CargoReceiver is a zone enhancement you use to be automatically
|
||||||
notified if a cargo was delivered inside the zone.
|
notified if a cargo was delivered inside the zone.
|
||||||
@ -25,26 +28,30 @@ cfxCargoReceiver.receiverZones = {}
|
|||||||
function cfxCargoReceiver.processReceiverZone(aZone) -- process attribute and add to zone
|
function cfxCargoReceiver.processReceiverZone(aZone) -- process attribute and add to zone
|
||||||
-- since the attribute is there, simply set the zones
|
-- since the attribute is there, simply set the zones
|
||||||
-- isCargoReceiver flag and we are good
|
-- isCargoReceiver flag and we are good
|
||||||
aZone.isCargoReceiver = true
|
aZone.isCargoReceiver = true -- so all zones can detect this. Necessary?
|
||||||
-- we can add additional processing here
|
aZone.autoRemove = aZone:getBoolFromZoneProperty("autoRemove", false)
|
||||||
aZone.autoRemove = aZone:getBoolFromZoneProperty("autoRemove", false) -- maybe add a removeDelay
|
|
||||||
aZone.removeDelay = aZone:getNumberFromZoneProperty("removeDelay", 1)
|
aZone.removeDelay = aZone:getNumberFromZoneProperty("removeDelay", 1)
|
||||||
if aZone.removeDelay < 1 then aZone.removeDelay = 1 end
|
if aZone.removeDelay < 1 then aZone.removeDelay = 1 end
|
||||||
aZone.silent = aZone:getBoolFromZoneProperty("silent", false)
|
aZone.silent = aZone:getBoolFromZoneProperty("silent", false)
|
||||||
|
|
||||||
|
|
||||||
-- new method support
|
|
||||||
aZone.cargoMethod = aZone:getStringFromZoneProperty("method", "inc")
|
aZone.cargoMethod = aZone:getStringFromZoneProperty("method", "inc")
|
||||||
if aZone:hasProperty("cargoMethod") then
|
if aZone:hasProperty("cargoMethod") then
|
||||||
aZone.cargoMethod = aZone:getStringFromZoneProperty("cargoMethod", "inc")
|
aZone.cargoMethod = aZone:getStringFromZoneProperty("cargoMethod", "inc")
|
||||||
end
|
end
|
||||||
|
|
||||||
if aZone:hasProperty("f!") then
|
-- save the names of cargos delivered to prevent 'bounce'
|
||||||
|
aZone.cargosDelivered = {} -- by cargo name
|
||||||
|
aZone.noBounce = aZone:getBoolFromZoneProperty("noBounce", true)
|
||||||
|
if aZone:hasProperty("cargoReceiver!") then
|
||||||
|
aZone.outReceiveFlag = aZone:getStringFromZoneProperty("cargoReceiver!", "*<none>")
|
||||||
|
elseif aZone:hasProperty("f!") then
|
||||||
aZone.outReceiveFlag = aZone:getStringFromZoneProperty("f!", "*<none>")
|
aZone.outReceiveFlag = aZone:getStringFromZoneProperty("f!", "*<none>")
|
||||||
elseif aZone:hasProperty("cargoReceived!") then
|
elseif aZone:hasProperty("cargoReceived!") then
|
||||||
aZone.outReceiveFlag = aZone:getStringFromZoneProperty( "cargoReceived!", "*<none>")
|
aZone.outReceiveFlag = aZone:getStringFromZoneProperty( "cargoReceived!", "*<none>")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not aZone.outReceiveFlag then
|
||||||
|
trigger.action.outText("+++crgR: receiver <" .. aZone.name .. "> has no output!", 30)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cfxCargoReceiver.addReceiverZone(aZone)
|
function cfxCargoReceiver.addReceiverZone(aZone)
|
||||||
@ -94,7 +101,7 @@ function cfxCargoReceiver.cargoEvent(event, object, name)
|
|||||||
|
|
||||||
if not event then return end
|
if not event then return end
|
||||||
if event == "grounded" then
|
if event == "grounded" then
|
||||||
-- this is actually the only one that interests us
|
-- this is the only one that interests us
|
||||||
if not object then
|
if not object then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
@ -106,21 +113,28 @@ function cfxCargoReceiver.cargoEvent(event, object, name)
|
|||||||
-- now invoke callbacks for all zones
|
-- now invoke callbacks for all zones
|
||||||
-- this is in
|
-- this is in
|
||||||
for name, aZone in pairs(cfxCargoReceiver.receiverZones) do
|
for name, aZone in pairs(cfxCargoReceiver.receiverZones) do
|
||||||
if cfxZones.pointInZone(loc, aZone) then
|
if aZone:pointInZone(loc) then
|
||||||
cfxCargoReceiver.invokeCallback("deliver", object, name, aZone)
|
cfxCargoReceiver.invokeCallback("deliver", object, name, aZone)
|
||||||
|
|
||||||
-- set flags as indicated
|
-- set flags as indicated
|
||||||
if aZone.outReceiveFlag then
|
if aZone.outReceiveFlag then
|
||||||
cfxZones.pollFlag(aZone.outReceiveFlag, aZone.cargoMethod, aZone)
|
if aZone.noBounce then
|
||||||
|
-- we only do this once for every named object
|
||||||
|
if not aZone.cargosDelivered[name] then
|
||||||
|
aZone.cargosDelivered[name] = true
|
||||||
|
aZone:pollFlag(aZone.outReceiveFlag, aZone.cargoMethod)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
aZone:pollFlag(aZone.outReceiveFlag, aZone.cargoMethod)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if aZone.autoRemove then
|
if aZone.autoRemove then
|
||||||
-- schedule this for in a few seconds?
|
-- schedule this for in a few seconds
|
||||||
local args = {}
|
local args = {}
|
||||||
args.theObject = object
|
args.theObject = object
|
||||||
args.theZone = aZone
|
args.theZone = aZone
|
||||||
timer.scheduleFunction(cfxCargoReceiver.removeCargo, args, timer.getTime() + aZone.removeDelay)
|
timer.scheduleFunction(cfxCargoReceiver.removeCargo, args, timer.getTime() + aZone.removeDelay)
|
||||||
--object:destroy()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -139,17 +153,13 @@ function cfxCargoReceiver.update()
|
|||||||
-- new we see if any of these are close to a delivery zone
|
-- new we see if any of these are close to a delivery zone
|
||||||
for idx, aCargo in pairs(liftedCargos) do
|
for idx, aCargo in pairs(liftedCargos) do
|
||||||
local thePoint = aCargo:getPoint()
|
local thePoint = aCargo:getPoint()
|
||||||
local receiver = cfxZones.getClosestZone(
|
local receiver = cfxZones.getClosestZone(thePoint, cfxCargoReceiver.receiverZones) -- must be indexed by name
|
||||||
thePoint,
|
|
||||||
cfxCargoReceiver.receiverZones -- must be indexed by name
|
|
||||||
)
|
|
||||||
-- we now check if we are in 'speaking range' and receiver can talk
|
-- we now check if we are in 'speaking range' and receiver can talk
|
||||||
-- modify delta by distance to boundary, not
|
-- modify delta by distance to boundary, not center
|
||||||
-- center
|
|
||||||
local delta = dcsCommon.distFlat(thePoint, cfxZones.getPoint(receiver))
|
local delta = dcsCommon.distFlat(thePoint, cfxZones.getPoint(receiver))
|
||||||
delta = delta - receiver.radius
|
delta = delta - receiver.radius
|
||||||
|
|
||||||
if (receiver.silent == false) and
|
if (not receiver.silent) and
|
||||||
(delta < cfxCargoReceiver.maxDirectionRange) then
|
(delta < cfxCargoReceiver.maxDirectionRange) then
|
||||||
-- this cargo can be talked down.
|
-- this cargo can be talked down.
|
||||||
-- find the player unit that is closest to in in hopes
|
-- find the player unit that is closest to in in hopes
|
||||||
@ -214,10 +224,14 @@ function cfxCargoReceiver.start()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- scan all zones for cargoReceiver flag
|
-- scan all zones for cargoReceiver flag
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("cargoReceiver!")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
cfxCargoReceiver.processReceiverZone(aZone)
|
||||||
|
cfxCargoReceiver.addReceiverZone(aZone)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- old version, LEGACY
|
||||||
local attrZones = cfxZones.getZonesWithAttributeNamed("cargoReceiver")
|
local attrZones = cfxZones.getZonesWithAttributeNamed("cargoReceiver")
|
||||||
|
|
||||||
-- now create a spawner for all, add them to the spawner updater, and spawn for all zones that are not
|
|
||||||
-- paused
|
|
||||||
for k, aZone in pairs(attrZones) do
|
for k, aZone in pairs(attrZones) do
|
||||||
cfxCargoReceiver.processReceiverZone(aZone) -- process attribute and add to zone
|
cfxCargoReceiver.processReceiverZone(aZone) -- process attribute and add to zone
|
||||||
cfxCargoReceiver.addReceiverZone(aZone) -- remember it so we can smoke it
|
cfxCargoReceiver.addReceiverZone(aZone) -- remember it so we can smoke it
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxZones = {}
|
cfxZones = {}
|
||||||
cfxZones.version = "4.4.2"
|
cfxZones.version = "4.4.3"
|
||||||
|
|
||||||
-- cf/x zone management module
|
-- cf/x zone management module
|
||||||
-- reads dcs zones and makes them accessible and mutable
|
-- reads dcs zones and makes them accessible and mutable
|
||||||
@ -32,6 +32,7 @@ cfxZones.version = "4.4.2"
|
|||||||
- dmlZone:getCoalition() dereferences masterOwner once
|
- dmlZone:getCoalition() dereferences masterOwner once
|
||||||
-4.4.1 - better verbosity for error in doPollFlag()
|
-4.4.1 - better verbosity for error in doPollFlag()
|
||||||
-4.4.2 - twn support for wildcards <twn: > and <loc:>
|
-4.4.2 - twn support for wildcards <twn: > and <loc:>
|
||||||
|
-4.4.3 - property name is trimmed (double check)
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
--
|
--
|
||||||
@ -123,7 +124,14 @@ function cfxZones.readFromDCS(clearfirst)
|
|||||||
else
|
else
|
||||||
newZone.properties = {}
|
newZone.properties = {}
|
||||||
end -- WARNING: REF COPY. May need to clone
|
end -- WARNING: REF COPY. May need to clone
|
||||||
|
--[[--
|
||||||
|
trigger.action.outText("zone <> properties:trimmed", 30)
|
||||||
|
local msg = "["
|
||||||
|
for idx, val in pairs(newZone.properties) do
|
||||||
|
msg = msg .. "<" .. val.key .. ">:<" .. dcsCommon.trim(val.key) .. ">, "
|
||||||
|
end
|
||||||
|
trigger.action.outText(msg, 30)
|
||||||
|
--]]--
|
||||||
local upperName = newZone.name:upper()
|
local upperName = newZone.name:upper()
|
||||||
|
|
||||||
-- location as 'point'
|
-- location as 'point'
|
||||||
@ -2158,7 +2166,14 @@ function cfxZones.extractPropertyFromDCS(theKey, theProperties)
|
|||||||
for i=1, #theProperties do
|
for i=1, #theProperties do
|
||||||
local theP = theProperties[i]
|
local theP = theProperties[i]
|
||||||
|
|
||||||
local existingKey = dcsCommon.trim(theP.key)
|
local existingKey = dcsCommon.trim(theP.key) -- does not work if ends on "#!?" - why?
|
||||||
|
--while len(existingKey) > 1 and string.sub(existingKey, -1) == " " do
|
||||||
|
-- existingKey = existingKey:sub(1, -2) -- trim manually
|
||||||
|
--end
|
||||||
|
if string.sub(existingKey, -1) == " " then
|
||||||
|
trigger.action.outText("+++ZONES: warning: unable to trim blanks from attribute name <" .. existingKey .. ">", 30)
|
||||||
|
end
|
||||||
|
-- trigger.action.outText("procced attribute name <" .. existingKey .. ">", 30)
|
||||||
if not cfxZones.caseSensitiveProperties then
|
if not cfxZones.caseSensitiveProperties then
|
||||||
existingKey = string.lower(existingKey)
|
existingKey = string.lower(existingKey)
|
||||||
end
|
end
|
||||||
@ -2388,6 +2403,7 @@ function dmlZone:hasProperty(theProperty)
|
|||||||
trigger.action.outText("+++zne: WARNING - hasProperty called with nil theProperty for zone <" .. self.name .. ">", 30)
|
trigger.action.outText("+++zne: WARNING - hasProperty called with nil theProperty for zone <" .. self.name .. ">", 30)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
theProperty = dcsCommon.trim(theProperty) -- strip leading and training blanks
|
||||||
local foundIt = self:getZoneProperty(theProperty)
|
local foundIt = self:getZoneProperty(theProperty)
|
||||||
if not foundIt then
|
if not foundIt then
|
||||||
-- check for possible forgotten or exchanged IO flags
|
-- check for possible forgotten or exchanged IO flags
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
civAir = {}
|
civAir = {}
|
||||||
civAir.version = "3.0.2"
|
civAir.version = "3.1.0"
|
||||||
--[[--
|
--[[--
|
||||||
3.0.0 liveries support
|
3.0.0 liveries support
|
||||||
default liveries for Yak-50 (main test case)
|
default liveries for Yak-50 (main test case)
|
||||||
@ -15,7 +15,12 @@ civAir.version = "3.0.2"
|
|||||||
protest action
|
protest action
|
||||||
spawning now works correctly for groupType
|
spawning now works correctly for groupType
|
||||||
3.0.2 clean-up
|
3.0.2 clean-up
|
||||||
|
3.1.0 better verbosity for startup info
|
||||||
|
dicts for departOnly and landingOnly
|
||||||
|
correctly filter depart only, land only, closed at start
|
||||||
|
Syria multiple "H" airfields DCS bug
|
||||||
|
filter airfields with no runways
|
||||||
|
getAirfieldNamed
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
civAir.ups = 0.05 -- updates per second. 0.05 = once every 20 seconds
|
civAir.ups = 0.05 -- updates per second. 0.05 = once every 20 seconds
|
||||||
@ -60,8 +65,11 @@ civAir.maxIdle = 8 * 60 -- seconds of ide time before it is removed after landin
|
|||||||
|
|
||||||
civAir.trafficCenters = {}
|
civAir.trafficCenters = {}
|
||||||
civAir.excludeAirfields = {}
|
civAir.excludeAirfields = {}
|
||||||
|
civAir.excludeAirfieldsDict = {}
|
||||||
civAir.departOnly = {} -- use only to start from
|
civAir.departOnly = {} -- use only to start from
|
||||||
|
civAir.departOnlyDict = {} -- as above, by af name
|
||||||
civAir.landingOnly = {} -- use only to land at
|
civAir.landingOnly = {} -- use only to land at
|
||||||
|
civAir.landingOnlyDict = {} -- as above, by af name
|
||||||
civAir.inoutZones = {} -- off-map connector zones
|
civAir.inoutZones = {} -- off-map connector zones
|
||||||
|
|
||||||
civAir.requiredLibs = {
|
civAir.requiredLibs = {
|
||||||
@ -180,7 +188,7 @@ end
|
|||||||
|
|
||||||
function civAir.processZone(theZone)
|
function civAir.processZone(theZone)
|
||||||
local value = theZone:getStringFromZoneProperty("civAir", "")
|
local value = theZone:getStringFromZoneProperty("civAir", "")
|
||||||
local af = dcsCommon.getClosestAirbaseTo(theZone.point, 0) -- 0 = only airfields, not farp or ships
|
local af = dcsCommon.getClosestAirbaseTo(theZone.point, 0) -- 0 = only airfields, not farp nor ships
|
||||||
local inoutName = "***" .. theZone:getName()
|
local inoutName = "***" .. theZone:getName()
|
||||||
|
|
||||||
if af then
|
if af then
|
||||||
@ -188,10 +196,13 @@ function civAir.processZone(theZone)
|
|||||||
value = value:lower()
|
value = value:lower()
|
||||||
if value == "exclude" or value == "closed" then
|
if value == "exclude" or value == "closed" then
|
||||||
table.insert(civAir.excludeAirfields, afName)
|
table.insert(civAir.excludeAirfields, afName)
|
||||||
|
civAir.excludeAirfieldsDict[afName] = afName
|
||||||
elseif dcsCommon.stringStartsWith(value, "depart") or dcsCommon.stringStartsWith(value, "start") or dcsCommon.stringStartsWith(value, "take") then
|
elseif dcsCommon.stringStartsWith(value, "depart") or dcsCommon.stringStartsWith(value, "start") or dcsCommon.stringStartsWith(value, "take") then
|
||||||
table.insert(civAir.departOnly, afName)
|
table.insert(civAir.departOnly, afName)
|
||||||
|
civAir.departOnlyDict[afName] = afName -- can fold many in one
|
||||||
elseif dcsCommon.stringStartsWith(value, "land") or dcsCommon.stringStartsWith(value, "arriv") then
|
elseif dcsCommon.stringStartsWith(value, "land") or dcsCommon.stringStartsWith(value, "arriv") then
|
||||||
table.insert(civAir.landingOnly, afName)
|
table.insert(civAir.landingOnly, afName)
|
||||||
|
civAir.landingOnlyDict[afName] = afName -- can fold many on one
|
||||||
elseif dcsCommon.stringStartsWith(value, "inb") then
|
elseif dcsCommon.stringStartsWith(value, "inb") then
|
||||||
table.insert(civAir.departOnly, inoutName) -- start in inbound zone
|
table.insert(civAir.departOnly, inoutName) -- start in inbound zone
|
||||||
civAir.inoutZones[inoutName] = theZone
|
civAir.inoutZones[inoutName] = theZone
|
||||||
@ -253,8 +264,8 @@ function civAir.filterAirfields(inAll, inFilter)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function civAir.getTwoAirbases()
|
function civAir.getTwoAirbases()
|
||||||
local fAB -- first airbase to depart
|
local fAB -- name of first airbase to depart from
|
||||||
local sAB -- second airbase to fly to
|
local sAB -- name second airbase to fly to
|
||||||
|
|
||||||
local departAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.departOnly)
|
local departAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.departOnly)
|
||||||
-- remove all currently excluded air bases from departure
|
-- remove all currently excluded air bases from departure
|
||||||
@ -263,11 +274,14 @@ function civAir.getTwoAirbases()
|
|||||||
if #filteredAB < 1 then
|
if #filteredAB < 1 then
|
||||||
trigger.action.outText("+++civA: too few departure airfields", 30)
|
trigger.action.outText("+++civA: too few departure airfields", 30)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
else
|
||||||
|
-- trigger.action.outText("+++civA: source (first) fields available: " .. #filteredAB, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- now pick the departure airfield
|
-- now pick the departure airfield
|
||||||
fAB = dcsCommon.pickRandom(filteredAB)
|
fAB = dcsCommon.pickRandom(filteredAB) -- returns an airfield name
|
||||||
|
-- trigger.action.outText("+++civA: picked first: <" .. fAB .. ">", 30)
|
||||||
|
|
||||||
-- now generate list of landing airfields
|
-- now generate list of landing airfields
|
||||||
local arriveAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.landingOnly)
|
local arriveAB = dcsCommon.combineTables(civAir.trafficCenters, civAir.landingOnly)
|
||||||
-- remove all currently excluded air bases from arrival
|
-- remove all currently excluded air bases from arrival
|
||||||
@ -277,6 +291,8 @@ function civAir.getTwoAirbases()
|
|||||||
if #filteredAB < 1 then
|
if #filteredAB < 1 then
|
||||||
trigger.action.outText("+++civA: too few arrival airfields", 30)
|
trigger.action.outText("+++civA: too few arrival airfields", 30)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
else
|
||||||
|
-- trigger.action.outText("+++civA: second (ARV) fields available: " .. #filteredAB, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- pick any second that are not the same
|
-- pick any second that are not the same
|
||||||
@ -285,10 +301,13 @@ function civAir.getTwoAirbases()
|
|||||||
sAB = dcsCommon.pickRandom(filteredAB)
|
sAB = dcsCommon.pickRandom(filteredAB)
|
||||||
tries = tries + 1 -- only try 10 times
|
tries = tries + 1 -- only try 10 times
|
||||||
until fAB ~= sAB or tries > 10
|
until fAB ~= sAB or tries > 10
|
||||||
|
|
||||||
|
-- trigger.action.outText("+++civA: picked SECOND: <" .. sAB .. ">", 30)
|
||||||
|
|
||||||
|
|
||||||
local civA = {}
|
local civA = {}
|
||||||
if not (dcsCommon.stringStartsWith(fAB, '***')) then
|
if not (dcsCommon.stringStartsWith(fAB, '***')) then
|
||||||
civA.AB = dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
|
civA.AB = civAir.getAirfieldNamed(fAB) -- dcsCommon.getFirstAirbaseWhoseNameContains(fAB, 0)
|
||||||
civA.name = civA.AB:getName()
|
civA.name = civA.AB:getName()
|
||||||
else
|
else
|
||||||
civA.zone = civAir.inoutZones[fAB]
|
civA.zone = civAir.inoutZones[fAB]
|
||||||
@ -296,16 +315,22 @@ function civAir.getTwoAirbases()
|
|||||||
end
|
end
|
||||||
local civB = {}
|
local civB = {}
|
||||||
if not (dcsCommon.stringStartsWith(sAB, '***')) then
|
if not (dcsCommon.stringStartsWith(sAB, '***')) then
|
||||||
civB.AB = dcsCommon.getFirstAirbaseWhoseNameContains(sAB, 0)
|
civB.AB = civAir.getAirfieldNamed(sAB) -- dcsCommon.getFirstAirbaseWhoseNameContains(sAB, 0)
|
||||||
civB.name = civB.AB:getName()
|
civB.name = civB.AB:getName()
|
||||||
else
|
else
|
||||||
civB.zone = civAir.inoutZones[sAB]
|
civB.zone = civAir.inoutZones[sAB]
|
||||||
civB.name = civB.zone:getName()
|
civB.name = civB.zone:getName()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- trigger.action.outText("+++civA: picked source AF <" .. civA.name .. "> and dest <" .. civB.name .. ">", 30)
|
||||||
|
|
||||||
return civA, civB -- fAB, sAB
|
return civA, civB -- fAB, sAB
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function civAir.getAirfieldNamed(name)
|
||||||
|
return Airbase.getByName(name)
|
||||||
|
end
|
||||||
|
|
||||||
function civAir.parkingIsFree(fromWP)
|
function civAir.parkingIsFree(fromWP)
|
||||||
-- iterate over all currently registred flights and make
|
-- iterate over all currently registred flights and make
|
||||||
-- sure that their location isn't closer than 10m to my new parking
|
-- sure that their location isn't closer than 10m to my new parking
|
||||||
@ -684,24 +709,48 @@ function civAir.collectHubs()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function civAir.listTrafficCenters()
|
function civAir.listTrafficCenters()
|
||||||
trigger.action.outText("Traffic Centers", 30)
|
local msg = "Traffic Centers:\n"
|
||||||
|
local other = false
|
||||||
for idx, aName in pairs(civAir.trafficCenters) do
|
for idx, aName in pairs(civAir.trafficCenters) do
|
||||||
trigger.action.outText(aName, 30)
|
if other then msg = msg .. ", " end
|
||||||
|
msg = msg .. aName
|
||||||
|
other = true
|
||||||
end
|
end
|
||||||
|
trigger.action.outText(msg .. "\n", 30)
|
||||||
|
|
||||||
|
msg = "Departure-Only:\n"
|
||||||
|
other = false
|
||||||
if #civAir.departOnly > 0 then
|
if #civAir.departOnly > 0 then
|
||||||
trigger.action.outText("Departure-Only:", 30)
|
|
||||||
for idx, aName in pairs(civAir.departOnly) do
|
for idx, aName in pairs(civAir.departOnly) do
|
||||||
trigger.action.outText(aName, 30)
|
if other then msg = msg .. ", " end
|
||||||
|
msg = msg .. aName
|
||||||
|
other = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
trigger.action.outText(msg .. "\n", 30)
|
||||||
|
|
||||||
|
msg = "Landing-Only:\n"
|
||||||
|
other = false
|
||||||
if #civAir.landingOnly > 0 then
|
if #civAir.landingOnly > 0 then
|
||||||
trigger.action.outText("Arrival/Landing-Only:", 30)
|
|
||||||
for idx, aName in pairs(civAir.landingOnly) do
|
for idx, aName in pairs(civAir.landingOnly) do
|
||||||
trigger.action.outText(aName, 30)
|
if other then msg = msg .. ", " end
|
||||||
|
msg = msg .. aName
|
||||||
|
other = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
trigger.action.outText(msg .. "\n", 30)
|
||||||
|
|
||||||
|
|
||||||
|
msg = "Closed:\n"
|
||||||
|
other = false
|
||||||
|
if #civAir.excludeAirfields > 0 then
|
||||||
|
for idx, aName in pairs(civAir.excludeAirfields) do
|
||||||
|
if other then msg = msg .. ", " end
|
||||||
|
msg = msg .. aName
|
||||||
|
other = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
trigger.action.outText(msg .. "\n", 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- start
|
-- start
|
||||||
@ -721,13 +770,27 @@ function civAir.start()
|
|||||||
if (#civAir.trafficCenters + #civAir.departOnly < 1) or
|
if (#civAir.trafficCenters + #civAir.departOnly < 1) or
|
||||||
(#civAir.trafficCenters + #civAir.landingOnly < 1)
|
(#civAir.trafficCenters + #civAir.landingOnly < 1)
|
||||||
then
|
then
|
||||||
|
trigger.action.outText("+++civA: marked traffic centers:" .. #civAir.trafficCenters .. "\n depart-only:" .. #civAir.departOnly .. "\n landing-only: " .. #civAir.landingOnly .. "\n", 30 )
|
||||||
trigger.action.outText("+++civA: auto-populating", 30)
|
trigger.action.outText("+++civA: auto-populating", 30)
|
||||||
-- simply add airfields on the map
|
-- simply add airfields on the map
|
||||||
|
-- and filter those that are excluded, land-only or depart only
|
||||||
local allBases = dcsCommon.getAirbasesWhoseNameContains("*", 0)
|
local allBases = dcsCommon.getAirbasesWhoseNameContains("*", 0)
|
||||||
for idx, aBase in pairs(allBases) do
|
for idx, aBase in pairs(allBases) do
|
||||||
local afName = aBase:getName()
|
local afName = aBase:getName()
|
||||||
|
if civAir.departOnlyDict[afName] or
|
||||||
table.insert(civAir.trafficCenters, afName)
|
civAir.landingOnlyDict[afName] or
|
||||||
|
civAir.excludeAirfieldsDict[afName]
|
||||||
|
then
|
||||||
|
trigger.action.outText("+++civA: filtering base " .. afName .. " for single-exception", 30)
|
||||||
|
else
|
||||||
|
-- syria special proccing
|
||||||
|
local rw = aBase:getRunways()
|
||||||
|
if #rw < 1 then
|
||||||
|
-- trigger.action.outText(afName .. " has no runways, filtered", 30)
|
||||||
|
else
|
||||||
|
table.insert(civAir.trafficCenters, afName)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
convoy = {}
|
convoy = {}
|
||||||
convoy.version = "1.1.0"
|
convoy.version = "1.2.0"
|
||||||
convoy.requiredLibs = {
|
convoy.requiredLibs = {
|
||||||
"dcsCommon",
|
"dcsCommon",
|
||||||
"cfxZones",
|
"cfxZones",
|
||||||
@ -32,7 +32,8 @@ VERSION HISTORY
|
|||||||
- warning when not onStart and no start?
|
- warning when not onStart and no start?
|
||||||
- say hi
|
- say hi
|
||||||
- removed destination attribute
|
- removed destination attribute
|
||||||
|
1.2.0 - convoyMethod
|
||||||
|
- convoyTriggerMethod
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
--[[-- CONVOY Structure
|
--[[-- CONVOY Structure
|
||||||
@ -174,6 +175,9 @@ function convoy.readConvoyZone(theZone)
|
|||||||
trigger.action.outText("+++CVY: Warning: Convoy zone <" .. theZone.name .. "> has disabled 'onStart' and has no 'spawn?' input. This convoy zone can't send out any convoys,", 30)
|
trigger.action.outText("+++CVY: Warning: Convoy zone <" .. theZone.name .. "> has disabled 'onStart' and has no 'spawn?' input. This convoy zone can't send out any convoys,", 30)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
theZone.convoyMethod = theZone:getStringFromZoneProperty("convoyMethod", "inc")
|
||||||
|
theZone.convoyTriggerMethod = theZone:getStringFromZoneProperty("convoyTriggerMethod", "change")
|
||||||
|
|
||||||
--[[--
|
--[[--
|
||||||
if theZone:hasProperty("destination") then -- remove me
|
if theZone:hasProperty("destination") then -- remove me
|
||||||
theZone.destination = theZone:getStringFromZoneProperty("destination", "none")
|
theZone.destination = theZone:getStringFromZoneProperty("destination", "none")
|
||||||
@ -560,7 +564,7 @@ function convoy.wpReached(gName, convName, idx, wpNum)
|
|||||||
convoy.invokeArrivedCallbacks(theConvoy)
|
convoy.invokeArrivedCallbacks(theConvoy)
|
||||||
-- hit the output flag if defined
|
-- hit the output flag if defined
|
||||||
if theZone.arrivedOut then
|
if theZone.arrivedOut then
|
||||||
theZone:pollFlag(theZone.arrivedOut, "inc")
|
theZone:pollFlag(theZone.arrivedOut, theZone.convoyMethod) -- "inc")
|
||||||
end
|
end
|
||||||
-- remove convoy from watchlist
|
-- remove convoy from watchlist
|
||||||
convoy.convoys[convName] = nil
|
convoy.convoys[convName] = nil
|
||||||
@ -845,7 +849,7 @@ function convoy.update()
|
|||||||
-- check for flags
|
-- check for flags
|
||||||
for idx, theZone in pairs (convoy.zones) do
|
for idx, theZone in pairs (convoy.zones) do
|
||||||
if theZone.spawnFlag and
|
if theZone.spawnFlag and
|
||||||
theZone:testZoneFlag(theZone.spawnFlag, "change", "lastSpawnFlag") then
|
theZone:testZoneFlag(theZone.spawnFlag, theZone.convoyTriggerMethod, "lastSpawnFlag") then
|
||||||
convoy.startConvoy(theZone)
|
convoy.startConvoy(theZone)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -900,7 +904,7 @@ function convoy.statusUpdate() -- every 10 seconds
|
|||||||
convoy.invokeAttackedCallbacks(theConvoy)
|
convoy.invokeAttackedCallbacks(theConvoy)
|
||||||
theZone = theConvoy.origin
|
theZone = theConvoy.origin
|
||||||
if theZone.attackedOut then
|
if theZone.attackedOut then
|
||||||
theZone:pollFlag(theZone.attackedOut, "inc")
|
theZone:pollFlag(theZone.attackedOut, theZone.convoyMethod) -- "inc")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -909,7 +913,7 @@ function convoy.statusUpdate() -- every 10 seconds
|
|||||||
convoy.invokeDestroyedCallbacks(theConvoy)
|
convoy.invokeDestroyedCallbacks(theConvoy)
|
||||||
theZone = theConvoy.origin
|
theZone = theConvoy.origin
|
||||||
if theZone.deadOut then
|
if theZone.deadOut then
|
||||||
theZone:pollFlag(theZone.deadOut, "inc")
|
theZone:pollFlag(theZone.deadOut, theZone.convoyMethod) -- "inc")
|
||||||
end
|
end
|
||||||
trigger.action.outTextForCoalition(theConvoy.coa, "Convoy " .. convName .. " enroute to " .. theConvoy.dest .. " was destroyed.", 30)
|
trigger.action.outTextForCoalition(theConvoy.coa, "Convoy " .. convName .. " enroute to " .. theConvoy.dest .. " was destroyed.", 30)
|
||||||
trigger.action.outSoundForCoalition(theConvoy.coa, convoy.actionSound)
|
trigger.action.outSoundForCoalition(theConvoy.coa, convoy.actionSound)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxHeloTroops = {}
|
cfxHeloTroops = {}
|
||||||
cfxHeloTroops.version = "3.1.5"
|
cfxHeloTroops.version = "4.0.0"
|
||||||
cfxHeloTroops.verbose = false
|
cfxHeloTroops.verbose = false
|
||||||
cfxHeloTroops.autoDrop = true
|
cfxHeloTroops.autoDrop = true
|
||||||
cfxHeloTroops.autoPickup = false
|
cfxHeloTroops.autoPickup = false
|
||||||
@ -25,6 +25,9 @@ cfxHeloTroops.requestRange = 500 -- meters
|
|||||||
- loadSound and disembarkSound
|
- loadSound and disembarkSound
|
||||||
3.1.4 - guarding destination access in save
|
3.1.4 - guarding destination access in save
|
||||||
3.1.5 - more guarding of destination access
|
3.1.5 - more guarding of destination access
|
||||||
|
4.0.0 - added dropZones
|
||||||
|
- enforceDropZones
|
||||||
|
- coalition for drop zones
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
|
|
||||||
@ -37,10 +40,24 @@ cfxHeloTroops.requiredLibs = {
|
|||||||
|
|
||||||
cfxHeloTroops.unitConfigs = {} -- all configs are stored by unit's name
|
cfxHeloTroops.unitConfigs = {} -- all configs are stored by unit's name
|
||||||
cfxHeloTroops.troopWeight = 100 -- kg average weight per trooper
|
cfxHeloTroops.troopWeight = 100 -- kg average weight per trooper
|
||||||
|
cfxHeloTroops.dropZones = {}
|
||||||
|
|
||||||
-- persistence support
|
-- persistence support
|
||||||
cfxHeloTroops.deployedTroops = {}
|
cfxHeloTroops.deployedTroops = {}
|
||||||
|
|
||||||
|
--
|
||||||
|
-- drop zones
|
||||||
|
--
|
||||||
|
function cfxHeloTroops.processDropZone(theZone)
|
||||||
|
theZone.droppedFlag = theZone:getStringFromZoneProperty("dropZone!", "cfxNone")
|
||||||
|
theZone.dropMethod = theZone:getStringFromZoneProperty("dropMethod", "inc")
|
||||||
|
theZone.dropCoa = theZone:getCoalitionFromZoneProperty("coalition", 0)
|
||||||
|
theZone.autoDespawn = theZone:getNumberFromZoneProperty("autoDespawn", -1)
|
||||||
|
end
|
||||||
|
|
||||||
|
--
|
||||||
|
-- comms
|
||||||
|
--
|
||||||
function cfxHeloTroops.resetConfig(conf)
|
function cfxHeloTroops.resetConfig(conf)
|
||||||
conf.autoDrop = cfxHeloTroops.autoDrop --if true, will drop troops on-board upon touchdown
|
conf.autoDrop = cfxHeloTroops.autoDrop --if true, will drop troops on-board upon touchdown
|
||||||
conf.autoPickup = cfxHeloTroops.autoPickup -- if true will load nearest troops upon touchdown
|
conf.autoPickup = cfxHeloTroops.autoPickup -- if true will load nearest troops upon touchdown
|
||||||
@ -576,16 +593,33 @@ function cfxHeloTroops.scoreWhenCapturing(theUnit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cfxHeloTroops.isInsideDropZone(theUnit)
|
||||||
|
local p = theUnit:getPoint()
|
||||||
|
for idx, theZone in pairs (cfxHeloTroops.dropZones) do
|
||||||
|
if theZone:isPointInsideZone(p) then return true end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
function cfxHeloTroops.doDeployTroops(args)
|
function cfxHeloTroops.doDeployTroops(args)
|
||||||
local conf = args[1]
|
local conf = args[1]
|
||||||
local what = args[2]
|
local what = args[2]
|
||||||
-- deploy the troops I have on board in formation
|
local theUnit = conf.unit
|
||||||
|
local theGroup = theUnit:getGroup()
|
||||||
|
local gid = theGroup:getID()
|
||||||
|
local inside = cfxHeloTroops.isInsideDropZone(theUnit)
|
||||||
|
if (not inside) and cfxHeloTroops.enforceDropZones then
|
||||||
|
trigger.action.outTextForGroup(gid, "You are outside an disembark/drop zone.", 30)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- deploy the troops I have on board
|
||||||
cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
||||||
|
|
||||||
-- interface with playerscore if we dropped
|
-- interface with playerscore if we dropped
|
||||||
-- inside an enemy-owned zone
|
-- inside an enemy-owned zone
|
||||||
if cfxPlayerScore and cfxOwnedZones then
|
if cfxPlayerScore and cfxOwnedZones then
|
||||||
local theUnit = conf.unit
|
--local theUnit = conf.unit
|
||||||
cfxHeloTroops.scoreWhenCapturing(theUnit)
|
cfxHeloTroops.scoreWhenCapturing(theUnit)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -630,7 +664,7 @@ function cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local chopperZone = cfxZones.createSimpleZone("choppa", p, 12) -- 12 m radius around choppa
|
local chopperZone = cfxZones.createSimpleZone("choppa", p, 12) -- 12 m radius around choppa
|
||||||
local theCoalition = theUnit:getGroup():getCoalition() -- make it choppers COALITION
|
local theCoalition = theUnit:getGroup():getCoalition() -- make it chopper's COALITION
|
||||||
local theGroup, theData = cfxZones.createGroundUnitsInZoneForCoalition (
|
local theGroup, theData = cfxZones.createGroundUnitsInZoneForCoalition (
|
||||||
theCoalition,
|
theCoalition,
|
||||||
theName, -- group name, may be tracked
|
theName, -- group name, may be tracked
|
||||||
@ -677,8 +711,39 @@ function cfxHeloTroops.deployTroopsFromHelicopter(conf)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- bang on all dropZones that we can find
|
||||||
|
for name, theZone in pairs(cfxHeloTroops.dropZones) do
|
||||||
|
-- can employ coalition test here as well, maybe later?
|
||||||
|
if theZone:isPointInsideZone(p) then
|
||||||
|
if theZone.dropCoa == 0 or theCoalition == theZone.dropCoa then
|
||||||
|
if cfxHeloTroops.verbose or theZone.verbose then
|
||||||
|
trigger.action.outText("+++Helo: will bang! on dropZone <" .. theZone.name .. "> output dropZone! <" .. theZone.droppedFlag .. "> with method <" .. theZone.dropMethod .. ">", 30)
|
||||||
|
end
|
||||||
|
theZone:pollFlag(theZone.droppedFlag, theZone.dropMethod)
|
||||||
|
end
|
||||||
|
if theZone.autoDespawn and theZone.autoDespawn > 0 then
|
||||||
|
args = {}
|
||||||
|
args.theZone = theZone
|
||||||
|
args.theGroup = theGroup
|
||||||
|
timer.scheduleFunction(cfxHeloTroops.autoDespawn, args, timer.getTime() + theZone.autoDespawn)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function cfxHeloTroops.autoDespawn(args)
|
||||||
|
if not args then return end
|
||||||
|
local theZone = args.theZone
|
||||||
|
local theGroup = args.theGroup
|
||||||
|
if theZone.verbose then
|
||||||
|
trigger.action.outText("+++Helo: auto-despawning drop in drop zone <" .. theZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
if not theGroup then return end
|
||||||
|
if Group.isExist(theGroup) then
|
||||||
|
Group.destroy(theGroup)
|
||||||
|
end
|
||||||
|
end
|
||||||
--
|
--
|
||||||
-- Loading Troops
|
-- Loading Troops
|
||||||
--
|
--
|
||||||
@ -882,7 +947,7 @@ function cfxHeloTroops.readConfigZone()
|
|||||||
theZone = cfxZones.createSimpleZone("heloTroopsConfig")
|
theZone = cfxZones.createSimpleZone("heloTroopsConfig")
|
||||||
end
|
end
|
||||||
|
|
||||||
cfxHeloTroops.verbose = theZone:getBoolFromZoneProperty("verbose", false)
|
cfxHeloTroops.verbose = theZone.verbose
|
||||||
|
|
||||||
if theZone:hasProperty("legalTroops") then
|
if theZone:hasProperty("legalTroops") then
|
||||||
local theTypesString = theZone:getStringFromZoneProperty("legalTroops", "")
|
local theTypesString = theZone:getStringFromZoneProperty("legalTroops", "")
|
||||||
@ -907,6 +972,7 @@ function cfxHeloTroops.readConfigZone()
|
|||||||
cfxHeloTroops.disembarkSound = theZone:getStringFromZoneProperty("disembarkSound", cfxHeloTroops.actionSound)
|
cfxHeloTroops.disembarkSound = theZone:getStringFromZoneProperty("disembarkSound", cfxHeloTroops.actionSound)
|
||||||
|
|
||||||
cfxHeloTroops.requestRange = theZone:getNumberFromZoneProperty("requestRange", 500)
|
cfxHeloTroops.requestRange = theZone:getNumberFromZoneProperty("requestRange", 500)
|
||||||
|
cfxHeloTroops.enforceDropZones = theZone:getBoolFromZoneProperty("enforceDropZones", false)
|
||||||
-- add own troop carriers
|
-- add own troop carriers
|
||||||
if theZone:hasProperty("troopCarriers") then
|
if theZone:hasProperty("troopCarriers") then
|
||||||
local tc = theZone:getStringFromZoneProperty("troopCarriers", "UH-1D")
|
local tc = theZone:getStringFromZoneProperty("troopCarriers", "UH-1D")
|
||||||
@ -999,6 +1065,13 @@ function cfxHeloTroops.start()
|
|||||||
-- read config zone
|
-- read config zone
|
||||||
cfxHeloTroops.readConfigZone()
|
cfxHeloTroops.readConfigZone()
|
||||||
|
|
||||||
|
-- read drop zones
|
||||||
|
local attrZones = cfxZones.getZonesWithAttributeNamed("dropZone!")
|
||||||
|
for k, aZone in pairs(attrZones) do
|
||||||
|
cfxHeloTroops.processDropZone(aZone)
|
||||||
|
cfxHeloTroops.dropZones[aZone.name] = aZone
|
||||||
|
end
|
||||||
|
|
||||||
-- start housekeeping
|
-- start housekeeping
|
||||||
cfxHeloTroops.houseKeeping()
|
cfxHeloTroops.houseKeeping()
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
cfxPlayerScore = {}
|
cfxPlayerScore = {}
|
||||||
cfxPlayerScore.version = "3.3.1"
|
cfxPlayerScore.version = "4.0.0"
|
||||||
cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers
|
cfxPlayerScore.name = "cfxPlayerScore" -- compatibility with flag bangers
|
||||||
cfxPlayerScore.badSound = "Death BRASS.wav"
|
cfxPlayerScore.badSound = "Death BRASS.wav"
|
||||||
cfxPlayerScore.scoreSound = "Quest Snare 3.wav"
|
cfxPlayerScore.scoreSound = "Quest Snare 3.wav"
|
||||||
@ -18,7 +18,9 @@ cfxPlayerScore.firstSave = true -- to force overwrite
|
|||||||
3.3.0 - case INsensitivity for all typeScore objects
|
3.3.0 - case INsensitivity for all typeScore objects
|
||||||
3.3.1 - fixes for DCS oddity in events after update
|
3.3.1 - fixes for DCS oddity in events after update
|
||||||
- cleanup
|
- cleanup
|
||||||
|
4.0.0 - own event handling, disco from dcsCommon
|
||||||
|
- early landing detection (unitSpawnTime)
|
||||||
|
|
||||||
TODO: Kill event no longer invoked for map objetcs, attribute
|
TODO: Kill event no longer invoked for map objetcs, attribute
|
||||||
to faction now, reverse invocation direction with PlayerScore
|
to faction now, reverse invocation direction with PlayerScore
|
||||||
--]]--
|
--]]--
|
||||||
@ -51,7 +53,7 @@ cfxPlayerScore.train = 5
|
|||||||
cfxPlayerScore.landing = 0 -- if > 0 it scores as feat
|
cfxPlayerScore.landing = 0 -- if > 0 it scores as feat
|
||||||
|
|
||||||
cfxPlayerScore.unit2player = {} -- lookup and reverse look-up
|
cfxPlayerScore.unit2player = {} -- lookup and reverse look-up
|
||||||
|
cfxPlayerScore.unitSpawnTime = {} -- lookup by unit name to prevent early landing
|
||||||
function cfxPlayerScore.addSafeZone(theZone)
|
function cfxPlayerScore.addSafeZone(theZone)
|
||||||
theZone.scoreSafe = theZone:getCoalitionFromZoneProperty("scoreSafe", 0)
|
theZone.scoreSafe = theZone:getCoalitionFromZoneProperty("scoreSafe", 0)
|
||||||
table.insert(cfxPlayerScore.safeZones, theZone)
|
table.insert(cfxPlayerScore.safeZones, theZone)
|
||||||
@ -570,7 +572,7 @@ function cfxPlayerScore.awardScoreTo(killSide, theScore, killerName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- EVENT HANDLING
|
-- EVENT PROCESSING / HANDLING
|
||||||
--
|
--
|
||||||
function cfxPlayerScore.linkUnitWithPlayer(theUnit)
|
function cfxPlayerScore.linkUnitWithPlayer(theUnit)
|
||||||
-- create the entries for lookup and reverseLooup tables
|
-- create the entries for lookup and reverseLooup tables
|
||||||
@ -583,7 +585,7 @@ function cfxPlayerScore.unlinkUnit(theUnit)
|
|||||||
local uName = theUnit:getName()
|
local uName = theUnit:getName()
|
||||||
cfxPlayerScore.unit2player[uName] = nil
|
cfxPlayerScore.unit2player[uName] = nil
|
||||||
end
|
end
|
||||||
|
--[[--
|
||||||
function cfxPlayerScore.preProcessor(theEvent)
|
function cfxPlayerScore.preProcessor(theEvent)
|
||||||
-- return true if the event should be processed
|
-- return true if the event should be processed
|
||||||
-- by us
|
-- by us
|
||||||
@ -721,10 +723,13 @@ function cfxPlayerScore.preProcessor(theEvent)
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
--]]--
|
||||||
|
|
||||||
|
--[[--
|
||||||
function cfxPlayerScore.postProcessor(theEvent)
|
function cfxPlayerScore.postProcessor(theEvent)
|
||||||
-- don't do anything
|
-- don't do anything
|
||||||
end
|
end
|
||||||
|
--]]--
|
||||||
|
|
||||||
function cfxPlayerScore.isStaticObject(theUnit)
|
function cfxPlayerScore.isStaticObject(theUnit)
|
||||||
if not theUnit.getGroup then return true end
|
if not theUnit.getGroup then return true end
|
||||||
@ -1091,7 +1096,165 @@ function cfxPlayerScore.handlePlayerDeath(theEvent)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cfxPlayerScore.handlePlayerEvent(theEvent)
|
--
|
||||||
|
-- event detection
|
||||||
|
--
|
||||||
|
function cfxPlayerScore.isScoreEvent(theEvent)
|
||||||
|
-- return true if the event results in a score event
|
||||||
|
if theEvent.initiator == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if cfxPlayerScore.verbose then
|
||||||
|
trigger.action.outText("Event preproc: " .. theEvent.id .. " (" .. dcsCommon.event2text(theEvent.id) .. ")", 30)
|
||||||
|
if theEvent.id == 8 or theEvent.id == 30 then -- dead or lost event
|
||||||
|
local who = theEvent.initiator
|
||||||
|
local name = "(nil ini)"
|
||||||
|
if who then
|
||||||
|
name = "(inval object)"
|
||||||
|
if who.getName then name = who:getName() end
|
||||||
|
end
|
||||||
|
trigger.action.outText("Dead/Lost subject: <" .. name .. ">", 30)
|
||||||
|
end
|
||||||
|
if theEvent.id == 2 then -- hit
|
||||||
|
local who = theEvent.initiator
|
||||||
|
local name = "(nil ini)"
|
||||||
|
if who then
|
||||||
|
name = "(inval initi)"
|
||||||
|
if who.getName then name = who:getName() end
|
||||||
|
if not name then -- WTF??? could be a weapon
|
||||||
|
name = "!nil getName!"
|
||||||
|
if who.getTypeName then name = who:getTypeName() end
|
||||||
|
if not name then
|
||||||
|
name = "WTFer"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local hit = theEvent.object
|
||||||
|
local hname = "(nil ini)"
|
||||||
|
if hit then
|
||||||
|
hname = "(inval object)"
|
||||||
|
if hit.getName then hname = hit:getName() end
|
||||||
|
end
|
||||||
|
trigger.action.outText("o:<" .. name .. "> hit <" .. hname .. ">", 30)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- check if this was FORMERLY a player plane
|
||||||
|
local theUnit = theEvent.initiator
|
||||||
|
if not theUnit.getName then return end -- fix for DCS update bug
|
||||||
|
local uName = theUnit:getName()
|
||||||
|
if cfxPlayerScore.unit2player[uName] then
|
||||||
|
-- this requires special IMMEDIATE handling when event is
|
||||||
|
-- one of the below
|
||||||
|
if theEvent.id == 5 or -- crash
|
||||||
|
theEvent.id == 8 or -- dead
|
||||||
|
theEvent.id == 9 or -- pilot_dead
|
||||||
|
theEvent.id == 30 or -- unit loss
|
||||||
|
theEvent.id == 6 then -- eject
|
||||||
|
-- these can lead to a pilot demerit
|
||||||
|
-- event does NOT have a player
|
||||||
|
cfxPlayerScore.handlePlayerDeath(theEvent)
|
||||||
|
return false -- false = no score event (any more)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- from here on, initiator must be player
|
||||||
|
if not theUnit.getPlayerName or
|
||||||
|
not theUnit:getPlayerName() then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if theEvent.id == 28 then -- kill, but only with target
|
||||||
|
local killer = theEvent.initiator
|
||||||
|
if not theEvent.target then
|
||||||
|
if cfxPlayerScore.verbose then
|
||||||
|
trigger.action.outText("+++scr kill nil TARGET", 30)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- if there are kill zones, we filter all kills that happen outside of kill zones
|
||||||
|
if #cfxPlayerScore.killZones > 0 then
|
||||||
|
local pLoc = theUnit:getPoint()
|
||||||
|
local tLoc = theEvent.target:getPoint()
|
||||||
|
local isIn, percent, dist, theZone = cfxZones.pointInOneOfZones(tLoc, cfxPlayerScore.killZones)
|
||||||
|
if not isIn then
|
||||||
|
if cfxPlayerScore.verbose then
|
||||||
|
trigger.action.outText("+++pScr: kill detected, but target <" .. theEvent.target:getName() .. "> was outside of any kill zones", 30)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if theZone.duet and not cfxZones.pointInZone(pLoc, theZone) then
|
||||||
|
-- player must be in same zone but was not
|
||||||
|
if cfxPlayerScore.verbose then
|
||||||
|
trigger.action.outText("+++pScr: kill detected, but player <" .. theUnit:getPlayerName() .. "> was outside of kill zone <" .. theZone.name .. ">", 30)
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- birth event for players initializes score if
|
||||||
|
-- not existed, and nils the queue
|
||||||
|
if theEvent.id == 15 then -- player birth
|
||||||
|
-- link player and unit
|
||||||
|
cfxPlayerScore.linkUnitWithPlayer(theUnit)
|
||||||
|
cfxPlayerScore.unitSpawnTime[uName] = timer.getTime() -- to detect 'early landing'
|
||||||
|
-- trigger.action.outText("Birth event", 30)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- take off. overwrites timestamp for last landing
|
||||||
|
-- so a blipping t/o does nor count. Pre-proc only
|
||||||
|
if theEvent.id == 3 or theEvent.id == 54 then
|
||||||
|
local now = timer.getTime()
|
||||||
|
local playerName = theUnit:getPlayerName()
|
||||||
|
cfxPlayerScore.lastPlayerLanding[playerName] = now -- overwrite
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- landing can score. but only the first landing in x seconds
|
||||||
|
-- and has spawned more than 10 seconds before
|
||||||
|
-- landing in safe zone promotes any queued scores to
|
||||||
|
-- permanent if enabled, then nils queue
|
||||||
|
if theEvent.id == 4 or theEvent.id == 55 then
|
||||||
|
-- trigger.action.outText("LANDING event", 30)
|
||||||
|
-- player landed. filter multiple landed events
|
||||||
|
local now = timer.getTime()
|
||||||
|
local playerName = theUnit:getPlayerName()
|
||||||
|
-- if player spawns on ground, DCS now can post a
|
||||||
|
-- "landing" event. filter
|
||||||
|
if cfxPlayerScore.unitSpawnTime[uName] and
|
||||||
|
now - cfxPlayerScore.unitSpawnTime[uName] < 10
|
||||||
|
then
|
||||||
|
cfxPlayerScore.lastPlayerLanding[playerName] = now -- just for the sake of it
|
||||||
|
-- trigger.action.outText("(DCS early landing bug ignored)", 30)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
-- trigger.action.outText("Time since spawn: " .. now - cfxPlayerScore.unitSpawnTime[uName], 30)
|
||||||
|
local lastLanding = cfxPlayerScore.lastPlayerLanding[playerName]
|
||||||
|
cfxPlayerScore.lastPlayerLanding[playerName] = now -- overwrite
|
||||||
|
if lastLanding and lastLanding + cfxPlayerScore.delayBetweenLandings > now then
|
||||||
|
if cfxPlayerScore.verbose then
|
||||||
|
trigger.action.outText("+++pScr: Player <" .. playerName .. "> touch-down ignored: too soon after last.", 30)
|
||||||
|
trigger.action.outText("now is <" .. now .. ">, between is <" .. cfxPlayerScore.delayBetweenLandings .. ">, last + between is <" .. lastLanding + cfxPlayerScore.delayBetweenLandings .. ">", 30)
|
||||||
|
end
|
||||||
|
-- filter this event, too soon
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfxPlayerScore:onEvent(theEvent)
|
||||||
|
if cfxPlayerScore.isScoreEvent(theEvent) then
|
||||||
|
cfxPlayerScore.handleScoreEvent(theEvent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function cfxPlayerScore.handleScoreEvent(theEvent)
|
||||||
if theEvent.id == 28 then
|
if theEvent.id == 28 then
|
||||||
-- kill from player detected.
|
-- kill from player detected.
|
||||||
cfxPlayerScore.killDetected(theEvent)
|
cfxPlayerScore.killDetected(theEvent)
|
||||||
@ -1134,7 +1297,9 @@ function cfxPlayerScore.handlePlayerEvent(theEvent)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
--
|
||||||
|
-- Config handling
|
||||||
|
--
|
||||||
function cfxPlayerScore.readConfigZone(theZone)
|
function cfxPlayerScore.readConfigZone(theZone)
|
||||||
cfxPlayerScore.verbose = theZone.verbose
|
cfxPlayerScore.verbose = theZone.verbose
|
||||||
-- default scores
|
-- default scores
|
||||||
@ -1450,9 +1615,10 @@ function cfxPlayerScore.start()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- subscribe to events and use dcsCommon's handler structure
|
-- subscribe to events and use dcsCommon's handler structure
|
||||||
dcsCommon.addEventHandler(cfxPlayerScore.handlePlayerEvent,
|
-- dcsCommon.addEventHandler(cfxPlayerScore.handlePlayerEvent,
|
||||||
cfxPlayerScore.preProcessor,
|
-- cfxPlayerScore.preProcessor,
|
||||||
cfxPlayerScore.postProcessor)
|
-- cfxPlayerScore.postProcessor)
|
||||||
|
world.addEventHandler(cfxPlayerScore)
|
||||||
-- now load all save data and populate map with troops that
|
-- now load all save data and populate map with troops that
|
||||||
-- we deployed last save.
|
-- we deployed last save.
|
||||||
if persistence then
|
if persistence then
|
||||||
|
|||||||
@ -21,6 +21,7 @@ radioMenu.lateGroups = {} -- dict by ID
|
|||||||
- added dynamic player support
|
- added dynamic player support
|
||||||
4.0.1 - MX no longer optional, so ask for it
|
4.0.1 - MX no longer optional, so ask for it
|
||||||
4.0.2 - ackSnd now also broadcasts to all if no group
|
4.0.2 - ackSnd now also broadcasts to all if no group
|
||||||
|
4.1.0 - outX --> valX verification. putting back in optional outX
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
function radioMenu.addRadioMenu(theZone)
|
function radioMenu.addRadioMenu(theZone)
|
||||||
@ -437,6 +438,11 @@ function radioMenu.createRadioMenuWithZone(theZone)
|
|||||||
if theZone:hasProperty("radioMethod") then
|
if theZone:hasProperty("radioMethod") then
|
||||||
theZone.radioMethod = theZone:getStringFromZoneProperty( "radioMethod", "inc")
|
theZone.radioMethod = theZone:getStringFromZoneProperty( "radioMethod", "inc")
|
||||||
end
|
end
|
||||||
|
-- note: outX currently overridden with valX
|
||||||
|
theZone.outMethA = theZone:getStringFromZoneProperty("outA", theZone.radioMethod)
|
||||||
|
theZone.outMethB = theZone:getStringFromZoneProperty("outB", theZone.radioMethod)
|
||||||
|
theZone.outMethC = theZone:getStringFromZoneProperty("outC", theZone.radioMethod)
|
||||||
|
theZone.outMethD = theZone:getStringFromZoneProperty("outD", theZone.radioMethod)
|
||||||
|
|
||||||
theZone.radioTriggerMethod = theZone:getStringFromZoneProperty("radioTriggerMethod", "change")
|
theZone.radioTriggerMethod = theZone:getStringFromZoneProperty("radioTriggerMethod", "change")
|
||||||
|
|
||||||
@ -731,6 +737,7 @@ function radioMenu.doMenuX(args)
|
|||||||
local outVal = theZone.outValA
|
local outVal = theZone.outValA
|
||||||
local ack = theZone.ackA
|
local ack = theZone.ackA
|
||||||
local ackSnd = theZone.ackASnd
|
local ackSnd = theZone.ackASnd
|
||||||
|
local meth = theZone.outMethA -- currently not used
|
||||||
|
|
||||||
-- decode A..X
|
-- decode A..X
|
||||||
if theItemIndex == "B"then
|
if theItemIndex == "B"then
|
||||||
@ -740,6 +747,7 @@ function radioMenu.doMenuX(args)
|
|||||||
outVal = theZone.outValB
|
outVal = theZone.outValB
|
||||||
ack = theZone.ackB
|
ack = theZone.ackB
|
||||||
ackSnd = theZone.ackBSnd
|
ackSnd = theZone.ackBSnd
|
||||||
|
meth = theZone.outMethB
|
||||||
elseif theItemIndex == "C" then
|
elseif theItemIndex == "C" then
|
||||||
cd = radioMenu.cdByGID(theZone.mcdC, theZone, theGroup) -- theZone.mcdC
|
cd = radioMenu.cdByGID(theZone.mcdC, theZone, theGroup) -- theZone.mcdC
|
||||||
busy = theZone.busyC
|
busy = theZone.busyC
|
||||||
@ -747,6 +755,7 @@ function radioMenu.doMenuX(args)
|
|||||||
outVal = theZone.outValC
|
outVal = theZone.outValC
|
||||||
ack = theZone.ackC
|
ack = theZone.ackC
|
||||||
ackSnd = theZone.ackCSnd
|
ackSnd = theZone.ackCSnd
|
||||||
|
meth = theZone.outMethC
|
||||||
elseif theItemIndex == "D" then
|
elseif theItemIndex == "D" then
|
||||||
cd = radioMenu.cdByGID(theZone.mcdD, theZone, theGroup) -- theZone.mcdD
|
cd = radioMenu.cdByGID(theZone.mcdD, theZone, theGroup) -- theZone.mcdD
|
||||||
busy = theZone.busyD
|
busy = theZone.busyD
|
||||||
@ -754,6 +763,7 @@ function radioMenu.doMenuX(args)
|
|||||||
outVal = theZone.outValD
|
outVal = theZone.outValD
|
||||||
ack = theZone.ackD
|
ack = theZone.ackD
|
||||||
ackSnd = theZone.ackDSnd
|
ackSnd = theZone.ackDSnd
|
||||||
|
meth = theZone.outMethD
|
||||||
end
|
end
|
||||||
|
|
||||||
-- see if we are on cooldown
|
-- see if we are on cooldown
|
||||||
@ -793,6 +803,7 @@ function radioMenu.doMenuX(args)
|
|||||||
-- poll flag, override with outVal if set
|
-- poll flag, override with outVal if set
|
||||||
if outVal then
|
if outVal then
|
||||||
--outVal = "#"..outVal -- we force immediate mode
|
--outVal = "#"..outVal -- we force immediate mode
|
||||||
|
-- now replaced by 'valX' attribute
|
||||||
theZone:pollFlag(theFlag, outVal)
|
theZone:pollFlag(theFlag, outVal)
|
||||||
if theZone.verbose or radioMenu.verbose then
|
if theZone.verbose or radioMenu.verbose then
|
||||||
trigger.action.outText("+++menu: overriding index " .. theItemIndex .. " output method <" .. theZone.radioMethod .. "> with immediate value <" .. outVal .. ">", 30)
|
trigger.action.outText("+++menu: overriding index " .. theItemIndex .. " output method <" .. theZone.radioMethod .. "> with immediate value <" .. outVal .. ">", 30)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
debugger = {}
|
debugger = {}
|
||||||
debugger.version = "3.0.0"
|
debugger.version = "3.1.0"
|
||||||
debugDemon = {}
|
debugDemon = {}
|
||||||
debugDemon.version = "2.1.0"
|
debugDemon.version = "2.1.0"
|
||||||
|
|
||||||
@ -45,7 +45,8 @@ debugger.log = ""
|
|||||||
- x *f
|
- x *f
|
||||||
- x *z
|
- x *z
|
||||||
- x ?
|
- x ?
|
||||||
|
3.1.0 - new DCS world events 57-61
|
||||||
|
- x ! xref hanging/unconnected
|
||||||
|
|
||||||
--]]--
|
--]]--
|
||||||
|
|
||||||
@ -122,7 +123,11 @@ debugDemon.eventList = {
|
|||||||
["54"] = "S_EVENT_MISSION_WINNER = 54",
|
["54"] = "S_EVENT_MISSION_WINNER = 54",
|
||||||
["55"] = "S_EVENT_POSTPONED_TAKEOFF = 55",
|
["55"] = "S_EVENT_POSTPONED_TAKEOFF = 55",
|
||||||
["56"] = "S_EVENT_POSTPONED_LAND = 56",
|
["56"] = "S_EVENT_POSTPONED_LAND = 56",
|
||||||
["57"] = "S_EVENT_MAX = 57",
|
["57"] = "S_EVENT_SIMULATION_FREEZE = 57",
|
||||||
|
["58"] = "S_EVENT_SIMULATION_UNFREEZE = 58",
|
||||||
|
["59"] = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_START = 59",
|
||||||
|
["60"] = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH = 60",
|
||||||
|
["61"] = "S_EVENT_MAX = 61",
|
||||||
}
|
}
|
||||||
|
|
||||||
debugger.spawnTypes = {
|
debugger.spawnTypes = {
|
||||||
@ -150,7 +155,7 @@ debugger.spawnTypes = {
|
|||||||
-- XREF MODULE
|
-- XREF MODULE
|
||||||
--
|
--
|
||||||
xref = {}
|
xref = {}
|
||||||
xref.version = "1.0.0"
|
xref.version = "1.1.0"
|
||||||
xref.dmlObjects = {} -- dict by zone name:upper()
|
xref.dmlObjects = {} -- dict by zone name:upper()
|
||||||
-- has inputs: dict of string for each '?' input, contains input flag name
|
-- has inputs: dict of string for each '?' input, contains input flag name
|
||||||
-- has output: dict of array for each output '!', contains output flag names as array
|
-- has output: dict of array for each output '!', contains output flag names as array
|
||||||
@ -158,7 +163,7 @@ xref.flags = {} -- dict by flag name
|
|||||||
-- has froms: dict of zone of attributes that can write to this flags
|
-- has froms: dict of zone of attributes that can write to this flags
|
||||||
-- has tos: dict of zones of attributes that read from flag
|
-- has tos: dict of zones of attributes that read from flag
|
||||||
|
|
||||||
function xref.getDmlObject(name)
|
function xref.getDmlObject(name) -- lazy alloc
|
||||||
name = name:upper()
|
name = name:upper()
|
||||||
local theObject = xref.dmlObjects[name]
|
local theObject = xref.dmlObjects[name]
|
||||||
if not theObject then
|
if not theObject then
|
||||||
@ -170,7 +175,7 @@ function xref.getDmlObject(name)
|
|||||||
return theObject
|
return theObject
|
||||||
end
|
end
|
||||||
|
|
||||||
function xref.getFlag(name, theZone)
|
function xref.getFlag(name, theZone) -- lazy alloc
|
||||||
if theZone and dcsCommon.stringStartsWith(name, "*") then
|
if theZone and dcsCommon.stringStartsWith(name, "*") then
|
||||||
-- local name conversion
|
-- local name conversion
|
||||||
name = theZone.name .. name
|
name = theZone.name .. name
|
||||||
@ -178,8 +183,8 @@ function xref.getFlag(name, theZone)
|
|||||||
local theFlag = xref.flags[name]
|
local theFlag = xref.flags[name]
|
||||||
if not theFlag then
|
if not theFlag then
|
||||||
theFlag = {}
|
theFlag = {}
|
||||||
theFlag.froms = {} -- dict by zone name/output that write to this flag
|
theFlag.froms = {} -- dict by zone name: OUTPUTS that write to this flag
|
||||||
theFlag.tos = {} -- dict by zone name / inputs that reads from this flag
|
theFlag.tos = {} -- dict by zone name: INPUTS that read from this flag
|
||||||
xref.flags[name] = theFlag
|
xref.flags[name] = theFlag
|
||||||
end
|
end
|
||||||
return theFlag
|
return theFlag
|
||||||
@ -236,20 +241,21 @@ function xref.scanMissionZones()
|
|||||||
-- iterate all properties
|
-- iterate all properties
|
||||||
local attributes = theZone:getAllZoneProperties()
|
local attributes = theZone:getAllZoneProperties()
|
||||||
for name, value in pairs(attributes) do
|
for name, value in pairs(attributes) do
|
||||||
|
local n2 = dcsCommon.trim(name)
|
||||||
-- find inputs
|
-- find inputs
|
||||||
if dcsCommon.stringEndsWith(name, "?") then
|
if dcsCommon.stringEndsWith(n2, "?") then
|
||||||
xref.addInput(theZone, name, value)
|
xref.addInput(theZone, n2, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- find outputs
|
-- find outputs
|
||||||
if dcsCommon.stringEndsWith(name, "!") then
|
if dcsCommon.stringEndsWith(n2, "!") then
|
||||||
xref.addOutput(theZone, name, value)
|
xref.addOutput(theZone, n2, value)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- other stuff, e.g. "#"
|
-- other stuff, e.g. "#"
|
||||||
-- find outputs
|
-- find outputs
|
||||||
if dcsCommon.stringEndsWith(name, "#") then
|
if dcsCommon.stringEndsWith(n2, "#") then
|
||||||
xref.addOutput(theZone, name, value)
|
xref.addOutput(theZone, n2, value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -289,8 +295,6 @@ function xref.xrefFlag(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- trigger.action.outText(msg, 30)
|
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -323,9 +327,7 @@ function xref.xrefZone(name, theObject)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- trigger.action.outText(msg, 30)
|
return msg
|
||||||
return msg
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function xref.xrefName(name)
|
function xref.xrefName(name)
|
||||||
@ -362,41 +364,93 @@ function xref.allZones()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function xref.xall()
|
function xref.xall()
|
||||||
msg = ""
|
local msg = ""
|
||||||
-- now dump all flags
|
-- now dump all flags
|
||||||
for flagName, data in pairs (xref.flags) do
|
for flagName, data in pairs (xref.flags) do
|
||||||
-- msg = msg .. xref.xrefFlag(flagName)
|
|
||||||
msg = msg .. xref.xrefName(flagName)
|
msg = msg .. xref.xrefName(flagName)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- dump all zones
|
-- dump all zones
|
||||||
for zoneName, data in pairs(xref.dmlObjects) do
|
for zoneName, data in pairs(xref.dmlObjects) do
|
||||||
-- msg = msg .. xref.xrefZone(zoneName, data)
|
|
||||||
msg = msg .. xref.xrefName(zoneName)
|
msg = msg .. xref.xrefName(zoneName)
|
||||||
end
|
end
|
||||||
return msg
|
return msg
|
||||||
-- trigger.action.outText(msg, 30)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function xref.unconnected()
|
||||||
|
local msg = "xref: unconnected flags/commands:\n"
|
||||||
|
local badFroms = {}
|
||||||
|
local badTos = {}
|
||||||
|
for name, theFlag in pairs(xref.flags) do
|
||||||
|
-- look for single-direction flags, i.e those that have
|
||||||
|
-- no froms or no tos.
|
||||||
|
if dcsCommon.getSizeOfTable(theFlag.froms) < 1 then
|
||||||
|
-- this flag has output referencing it, so the input hangs
|
||||||
|
badFroms[name] = theFlag
|
||||||
|
end
|
||||||
|
if dcsCommon.getSizeOfTable(theFlag.tos) < 1 then
|
||||||
|
-- this flag has output referencing it, so the input hangs
|
||||||
|
badTos[name] = theFlag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local hasUnconnected = false
|
||||||
|
if dcsCommon.getSizeOfTable(badFroms) > 0 then
|
||||||
|
msg = msg .. "<Flag/Command> used at [zone]:INPUT that listens for/to nothing:\n"
|
||||||
|
for name, theFlag in pairs(badFroms) do
|
||||||
|
msg = msg .. " <" .. name .. ">: "
|
||||||
|
local froms = theFlag.tos -- crossing from and to here!
|
||||||
|
for zName, outList in pairs(froms) do
|
||||||
|
msg = msg .. "[" .. zName .. "]:"
|
||||||
|
local c = 0
|
||||||
|
for idx, outName in pairs(outList) do
|
||||||
|
if c > 0 then msg = msg .. ", " end
|
||||||
|
c = 1
|
||||||
|
msg = msg .. outName
|
||||||
|
end
|
||||||
|
msg = msg .. "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
msg = msg .. " -- END OF LIST --\n\n"
|
||||||
|
hasUnconnected = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if dcsCommon.getSizeOfTable(badTos) > 0 then
|
||||||
|
msg = msg .. "<Flag/Command> used at [zone]:OUTPUT that sends to nobody:\n"
|
||||||
|
for name, theFlag in pairs(badTos) do
|
||||||
|
msg = msg .. " <" .. name .. ">: "
|
||||||
|
local tos = theFlag.froms -- crossing!
|
||||||
|
for zName, inList in pairs(tos) do
|
||||||
|
msg = msg .. "[" .. zName .. "]:"
|
||||||
|
local c = 0
|
||||||
|
for idx, inName in pairs(inList) do
|
||||||
|
if c > 0 then msg = msg .. ", " end
|
||||||
|
c = 1
|
||||||
|
msg = msg .. inName
|
||||||
|
end
|
||||||
|
end
|
||||||
|
msg = msg .. "\n"
|
||||||
|
end
|
||||||
|
hasUnconnected = true
|
||||||
|
msg = msg .. " -- END OF LIST --\n\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
if not hasUnconnected then
|
||||||
|
msg = msg .. "\n -- NONE --\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
return msg
|
||||||
|
end
|
||||||
|
|
||||||
function xref.start()
|
function xref.start()
|
||||||
xref.scanMissionZones()
|
xref.scanMissionZones()
|
||||||
local flagNum = dcsCommon.getSizeOfTable(xref.flags)
|
local flagNum = dcsCommon.getSizeOfTable(xref.flags)
|
||||||
local dmlObNum = dcsCommon.getSizeOfTable(xref.dmlObjects)
|
local dmlObNum = dcsCommon.getSizeOfTable(xref.dmlObjects)
|
||||||
trigger.action.outText("XRef v" .. xref.version .. " full DML object scan on mission complete:\n<" .. flagNum .. "> flags are referenced in <" .. dmlObNum .. "> DML zones", 30)
|
trigger.action.outText("XRef v" .. xref.version .. " full DML object scan on mission complete:\n<" .. flagNum .. "> flags are referenced in <" .. dmlObNum .. "> DML zones", 30)
|
||||||
|
|
||||||
-- trigger.action.outText(xref.xall(), 30)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- run the xref
|
-- run the xref
|
||||||
xref.start()
|
xref.start()
|
||||||
|
|
||||||
--[[--
|
|
||||||
to do
|
|
||||||
scan messenger and wildcards for flag access
|
|
||||||
|
|
||||||
--]]--
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- DEBUGGER MAIn
|
-- DEBUGGER MAIn
|
||||||
--
|
--
|
||||||
@ -436,7 +490,6 @@ function debugger.saveLog(name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- tracking flags
|
-- tracking flags
|
||||||
--
|
--
|
||||||
@ -764,7 +817,6 @@ function debugger.update()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Config & Start
|
-- Config & Start
|
||||||
--
|
--
|
||||||
@ -950,7 +1002,6 @@ function debugDemon:onEvent(theEvent)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if theEvent.id == world.event.S_EVENT_MARK_CHANGE then
|
if theEvent.id == world.event.S_EVENT_MARK_CHANGE then
|
||||||
-- trigger.action.outText("debugger: Mark Change event received", 30)
|
|
||||||
-- when changed, the mark's text is examined for a command
|
-- when changed, the mark's text is examined for a command
|
||||||
-- if it starts with the 'mark' string ("-" by default) it is processed
|
-- if it starts with the 'mark' string ("-" by default) it is processed
|
||||||
-- by the command processor
|
-- by the command processor
|
||||||
@ -958,42 +1009,26 @@ function debugDemon:onEvent(theEvent)
|
|||||||
-- else an error is displayed and the mark remains.
|
-- else an error is displayed and the mark remains.
|
||||||
if debugDemon.hasMark(theEvent.text) then
|
if debugDemon.hasMark(theEvent.text) then
|
||||||
-- strip the mark
|
-- strip the mark
|
||||||
local cCommand = dcsCommon.clone(theEvent.text, true)
|
local cCommand = dcsCommon.clone(theEvent.text)
|
||||||
local commandString = cCommand:sub(1+debugDemon.markOfDemon:len())
|
local commandString = cCommand:sub(1+debugDemon.markOfDemon:len())
|
||||||
-- break remainder apart into <command> <arg1> ... <argn>
|
-- break remainder apart into <command> <arg1> ... <argn>
|
||||||
local commands = dcsCommon.splitString(commandString, debugDemon.splitDelimiter)
|
local commands = dcsCommon.splitString(commandString, debugDemon.splitDelimiter)
|
||||||
|
|
||||||
-- this is a command. process it and then remove it if it was executed successfully
|
-- this is a command. process it and then remove it if it was executed successfully
|
||||||
local cTheEvent = dcsCommon.clone(theEvent, true) -- strip meta tables
|
local cTheEvent = dcsCommon.clone(theEvent) -- strip meta tables
|
||||||
local args = {commands, cTheEvent}
|
local args = {commands, cTheEvent}
|
||||||
-- defer execution for 0.1s to get out of trx bracked
|
-- defer execution for 0.1s to get out of trx bracked
|
||||||
timer.scheduleFunction(debugDemon.deferredDebug, args, timer.getTime() + 0.1)
|
timer.scheduleFunction(debugDemon.deferredDebug, args, timer.getTime() + 0.1)
|
||||||
debugDemon.activeIdx = cTheEvent.idx
|
debugDemon.activeIdx = cTheEvent.idx
|
||||||
--[[--
|
|
||||||
local success = debugDemon.executeCommand(commands, cTheEvent) -- execute on a clone, not original
|
|
||||||
|
|
||||||
-- remove this mark after successful execution
|
|
||||||
if success then
|
|
||||||
trigger.action.removeMark(theEvent.idx)
|
|
||||||
else
|
|
||||||
-- we could play some error sound
|
|
||||||
end
|
|
||||||
--]]--
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if theEvent.id == world.event.S_EVENT_MARK_REMOVED then
|
if theEvent.id == world.event.S_EVENT_MARK_REMOVED then
|
||||||
-- trigger.action.outText("Mark Remove received, removing idx <" .. theEvent.idx .. ">.", 30)
|
|
||||||
debugDemon.activeIdx = nil
|
debugDemon.activeIdx = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function debugDemon.deferredDebug(args)
|
function debugDemon.deferredDebug(args)
|
||||||
-- trigger.action.outText("enter deferred debug command", 30)
|
|
||||||
-- if not debugDemon.activeIdx then
|
|
||||||
-- trigger.action.outText("Debugger: window was closed, debug command ignored.", 30)
|
|
||||||
-- return
|
|
||||||
-- end
|
|
||||||
local commands = args[1]
|
local commands = args[1]
|
||||||
local cTheEvent = args[2]
|
local cTheEvent = args[2]
|
||||||
local success = debugDemon.executeCommand(commands, cTheEvent) -- execute on a clone, not original
|
local success = debugDemon.executeCommand(commands, cTheEvent) -- execute on a clone, not original
|
||||||
@ -1884,8 +1919,11 @@ function debugDemon.processXrefCommand(args, event)
|
|||||||
if not larg or larg == "" then larg = "?" end
|
if not larg or larg == "" then larg = "?" end
|
||||||
larg = larg:lower()
|
larg = larg:lower()
|
||||||
if larg == "?" then
|
if larg == "?" then
|
||||||
debugger.outText("*** xRef: ? = help (this), * = xref all, *f = list all DML flags, *z = list all DML zones, <name> xref flag or zone", 30)
|
debugger.outText("*** xRef: ? = help (this), ! = xref all 'hanging' or unconnected flags/commands, * = xref all, *f = list all DML flags, *z = list all DML zones, <name> xref flag or zone", 30)
|
||||||
return true -- leave up
|
return true -- leave up
|
||||||
|
elseif larg == "!" then
|
||||||
|
debugger.outText(xref.unconnected(), 30)
|
||||||
|
return true
|
||||||
elseif larg == "*" then
|
elseif larg == "*" then
|
||||||
debugger.outText(xref.xall(), 30)
|
debugger.outText(xref.xall(), 30)
|
||||||
return true
|
return true
|
||||||
|
|||||||
BIN
tutorial & demo missions/demo - Inferno at Sea.miz
Normal file
BIN
tutorial & demo missions/demo - Inferno at Sea.miz
Normal file
Binary file not shown.
BIN
tutorial & demo missions/demo - The Yeller Model.miz
Normal file
BIN
tutorial & demo missions/demo - The Yeller Model.miz
Normal file
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user