mirror of
https://github.com/weyne85/DML.git
synced 2025-10-29 16:57:49 +00:00
Initial commit
This commit is contained in:
572
modules/civAir.lua
Normal file
572
modules/civAir.lua
Normal file
@@ -0,0 +1,572 @@
|
||||
civAir = {}
|
||||
civAir.version = "1.4.0"
|
||||
--[[--
|
||||
1.0.0 initial version
|
||||
1.1.0 exclude list for airfields
|
||||
1.1.1 bug fixes with remove flight
|
||||
and betweenHubs
|
||||
check if slot is really free before spawning
|
||||
add overhead waypoint
|
||||
1.1.2 inAir start possible
|
||||
1.2.0 civAir can use own config file
|
||||
1.2.1 slight update to config file (moved active/idle)
|
||||
1.3.0 add ability to use zones to add closest airfield to
|
||||
trafficCenters or excludeAirfields
|
||||
1.4.0 ability to load config from zone to override
|
||||
all configs it finds
|
||||
module check
|
||||
removed obsolete civAirConfig module
|
||||
|
||||
|
||||
--]]--
|
||||
|
||||
civAir.ups = 0.05 -- updates per second
|
||||
civAir.initialAirSpawns = true -- when true has population spawn in-air at start
|
||||
civAir.verbose = false
|
||||
|
||||
-- aircraftTypes contains the type names for the neutral air traffic
|
||||
-- each entry has the same chance to be chose, so to make an
|
||||
-- aircraft more probably to appear, add its type multiple times
|
||||
-- like here with the Yak-40
|
||||
civAir.aircraftTypes = {"Yak-40", "Yak-40", "C-130", "C-17A", "IL-76MD", "An-30M", "An-26B"} -- civilian planes type strings as described here https://github.com/mrSkortch/DCS-miscScripts/tree/master/ObjectDB
|
||||
|
||||
-- maxTraffic is the number of neutral flights that are
|
||||
-- concurrently under way
|
||||
civAir.maxTraffic = 10 -- number of flights at the same time
|
||||
civAir.maxIdle = 8 * 60 -- seconds of ide time before it is removed after landing
|
||||
civAir.trafficAirbases = {
|
||||
randomized = 0, -- between any on map
|
||||
localHubs = 1, -- between any two airfields inside the same random hub listed in trafficCenters
|
||||
betweenHubs = 2 -- between any in random hub 1 to any in random hub 2
|
||||
}
|
||||
|
||||
civAir.trafficRange = 100 -- 120000 -- defines hub size, in meters. Make it 100 to make it only that airfield
|
||||
-- ABPickmethod determines how airfields are picked
|
||||
-- for air traffic
|
||||
civAir.ABPickMethod = civAir.trafficAirbases.betweenHubs
|
||||
civAir.trafficCenters = {
|
||||
--"batu",
|
||||
--"kobul",
|
||||
--"senaki",
|
||||
--"kutai",
|
||||
} -- trafficCenters is used with hubs. Each entry defines a hub
|
||||
-- where we collect airdromes etc based on range
|
||||
-- simply add a string to identify the hub center
|
||||
-- e.g. "senak" to define "Senaki Kolkhi"
|
||||
-- to have planes only fly between airfields in 100 km range
|
||||
-- around senaki kolkhi, enter only senaki as traffic center, set
|
||||
-- trafficRange to 100000 and ABPickMethod to localHubs
|
||||
-- to have traffic only between any airfields listed
|
||||
-- in trafficCenters, set trafficRange to a small value
|
||||
-- like 100 meters and set ABPickMethod to betweenHubs
|
||||
-- to have flights that always cross the map with multiple
|
||||
-- airfields, choose two or three hubs that are 300 km apart,
|
||||
-- then set trafficRange to 150000 and ABPickMethod to betweenHubs
|
||||
-- you can also place zones on the map and add a
|
||||
-- civAir attribute. If the attribute value is anything
|
||||
-- but "exclude", the closest airfield to the zone
|
||||
-- is added to trafficCenters
|
||||
-- if you leave this list empty, and do not add airfields
|
||||
-- by zones, the list is automatically populated by all
|
||||
-- airfields in the map
|
||||
|
||||
civAir.excludeAirfields = {
|
||||
--"senaki",
|
||||
}
|
||||
-- list all airfields that must NOT be included in
|
||||
-- civilian activities. Will be used for neither landing
|
||||
-- nor departure. overrides any airfield that was included
|
||||
-- in trafficCenters. Here, Senaki is off limits for
|
||||
-- civilian air traffic
|
||||
-- can be populated by zone on the map that have the
|
||||
-- 'civAir' attribute with value "exclude"
|
||||
|
||||
civAir.requiredLibs = {
|
||||
"dcsCommon", -- common is of course needed for everything
|
||||
"cfxZones", -- zones management foc CSAR and CSAR Mission zones
|
||||
}
|
||||
|
||||
civAir.activePlanes = {}
|
||||
civAir.idlePlanes = {}
|
||||
|
||||
function civAir.readConfigZone()
|
||||
-- note: must match exactly!!!!
|
||||
local theZone = cfxZones.getZoneByName("CivAirConfig")
|
||||
if not theZone then
|
||||
trigger.action.outText("***civA: NO config zone!", 30)
|
||||
return
|
||||
end
|
||||
|
||||
trigger.action.outText("civA: found config zone!", 30)
|
||||
|
||||
-- ok, for each property, load it if it exists
|
||||
if cfxZones.hasProperty(theZone, "aircraftTypes") then
|
||||
civAir.aircraftTypes = cfxZones.getStringFromZoneProperty(theZone, "aircraftTypes", "Yak-40")
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "ups") then
|
||||
civAir.ups = cfxZones.getNumberFromZoneProperty(theZone, "ups", 0.05)
|
||||
if civAir.ups < .0001 then civAir.ups = 0.05 end
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "maxTraffic") then
|
||||
civAir.maxTraffic = cfxZones.getNumberFromZoneProperty(theZone, "maxTraffic", 10)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "maxIdle") then
|
||||
civAir.maxIdle = cfxZones.getNumberFromZoneProperty(theZone, "maxIdle", 8 * 60)
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "trafficRange") then
|
||||
civAir.trafficRange = cfxZones.getNumberFromZoneProperty(theZone, "trafficRange", 120000) -- 120 km
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "ABPickMethod") then
|
||||
civAir.ABPickMethod = cfxZones.getNumberFromZoneProperty(theZone, "ABPickMethod", 0) -- randomized any
|
||||
end
|
||||
|
||||
if cfxZones.hasProperty(theZone, "initialAirSpawns") then
|
||||
civAir.initialAirSpawns = cfxZones.getBoolFromZoneProperty(theZone, "initialAirSpawns", true)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function civAir.addPlane(thePlaneUnit) -- warning: is actually a group
|
||||
if not thePlaneUnit then return end
|
||||
civAir.activePlanes[thePlaneUnit:getName()] = thePlaneUnit
|
||||
end
|
||||
|
||||
function civAir.removePlaneGroupByName(aName)
|
||||
if not aName then
|
||||
return
|
||||
end
|
||||
if civAir.activePlanes[aName] then
|
||||
--trigger.action.outText("civA: REMOVING " .. aName .. " ***", 30)
|
||||
civAir.activePlanes[aName] = nil
|
||||
else
|
||||
trigger.action.outText("civA: warning - ".. aName .." remove req but not found", 30)
|
||||
end
|
||||
end
|
||||
|
||||
function civAir.removePlane(thePlaneUnit) -- warning: is actually a group
|
||||
if not thePlaneUnit then return end
|
||||
if not thePlaneUnit:isExist() then return end
|
||||
civAir.activePlanes[thePlaneUnit:getName()] = nil
|
||||
end
|
||||
|
||||
function civAir.getPlane(aName) -- warning: returns GROUP!
|
||||
return civAir.activePlanes[aName]
|
||||
end
|
||||
|
||||
-- get an air base, may exclude an airbase from choice
|
||||
-- method is dependent on
|
||||
function civAir.getAnAirbase(excludeThisOne)
|
||||
-- different methods to select a base
|
||||
-- purely random from current list
|
||||
local theAB;
|
||||
if civAir.ABPickMethod == civAir.trafficAirbases.randomized then
|
||||
repeat
|
||||
local allAB = dcsCommon.getAirbasesWhoseNameContains("*", 0) -- all airfields, no Ships nor FABS
|
||||
theAB = dcsCommon.pickRandom(allAB)
|
||||
until theAB ~= excludeThisOne
|
||||
return theAB
|
||||
end
|
||||
|
||||
if civAir.ABPickMethod == civAir.trafficAirbases.localHubs then
|
||||
-- first, pick a hub name
|
||||
end
|
||||
|
||||
trigger.action.outText("civA: warning - unknown method <" .. civAir.ABPickMethod .. ">", 30)
|
||||
return nil
|
||||
end
|
||||
|
||||
function civAir.excludeAirbases(inList, excludeList)
|
||||
if not inList then return {} end
|
||||
if not excludeList then return inList end
|
||||
if #excludeList < 1 then return inList end
|
||||
|
||||
local theDict = {}
|
||||
-- build dict
|
||||
for idx, aBase in pairs(inList) do
|
||||
theDict[aBase:getName()] = aBase
|
||||
end
|
||||
|
||||
-- now iterate through all excludes and remove them from dics
|
||||
for idx, aName in pairs (excludeList) do
|
||||
local allOfflimitAB = dcsCommon.getAirbasesWhoseNameContains(aName, 0)
|
||||
for idx2, illegalBase in pairs (allOfflimitAB) do
|
||||
theDict[illegalBase:getName()] = nil
|
||||
end
|
||||
end
|
||||
-- now linearise (make array) from dict
|
||||
local theArray = dcsCommon.enumerateTable(theDict)
|
||||
return theArray
|
||||
end
|
||||
|
||||
function civAir.getTwoAirbases()
|
||||
local fAB
|
||||
local sAB
|
||||
-- get any two airbases on the map
|
||||
if civAir.ABPickMethod == civAir.trafficAirbases.randomized then
|
||||
local allAB = dcsCommon.getAirbasesWhoseNameContains("*", 0) -- all airfields, no Ships nor FABS, all coalitions
|
||||
-- remove illegal source/dest airfields
|
||||
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
|
||||
|
||||
fAB = dcsCommon.pickRandom(allAB)
|
||||
repeat
|
||||
sAB = dcsCommon.pickRandom(allAB)
|
||||
until fAB ~= sAB or (#allAB < 2)
|
||||
return fAB, sAB
|
||||
end
|
||||
|
||||
-- pick a hub, and then selct any two different airbases in the hub
|
||||
if civAir.ABPickMethod == civAir.trafficAirbases.localHubs then
|
||||
local hubName = dcsCommon.pickRandom(civAir.trafficCenters)
|
||||
-- get the airfield that is identified by this
|
||||
local theHub = dcsCommon.getFirstAirbaseWhoseNameContains(hubName, 0) -- only airfields, all coalitions
|
||||
-- get all airbases that surround in range
|
||||
local allAB = dcsCommon.getAirbasesInRangeOfAirbase(
|
||||
theHub, -- centered on this base
|
||||
true, -- include hub itself
|
||||
civAir.trafficRange, -- hub size in meters
|
||||
0 -- only airfields
|
||||
)
|
||||
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
|
||||
fAB = dcsCommon.pickRandom(allAB)
|
||||
repeat
|
||||
sAB = dcsCommon.pickRandom(allAB)
|
||||
until fAB ~= sAB or (#allAB < 2)
|
||||
return fAB, sAB
|
||||
end
|
||||
|
||||
-- pick two hubs: one for source, one for destination airfields,
|
||||
-- then pick an airfield from each hub
|
||||
if civAir.ABPickMethod == civAir.trafficAirbases.betweenHubs then
|
||||
--trigger.action.outText("between", 30)
|
||||
local sourceHubName = dcsCommon.pickRandom(civAir.trafficCenters)
|
||||
--trigger.action.outText("picked " .. sourceHubName, 30)
|
||||
local sourceHub = dcsCommon.getFirstAirbaseWhoseNameContains(sourceHubName, 0)
|
||||
--trigger.action.outText("sourceHub " .. sourceHub:getName(), 30)
|
||||
|
||||
local destHub
|
||||
repeat destHubName = dcsCommon.pickRandom(civAir.trafficCenters)
|
||||
until destHubName ~= sourceHubName or #civAir.trafficCenters < 2
|
||||
destHub = dcsCommon.getFirstAirbaseWhoseNameContains(destHubName, 0)
|
||||
--trigger.action.outText("destHub " .. destHub:getName(), 30)
|
||||
local allAB = dcsCommon.getAirbasesInRangeOfAirbase(
|
||||
sourceHub, -- centered on this base
|
||||
true, -- include hub itself
|
||||
civAir.trafficRange, -- hub size in meters
|
||||
0 -- only airfields
|
||||
)
|
||||
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
|
||||
fAB = dcsCommon.pickRandom(allAB)
|
||||
allAB = dcsCommon.getAirbasesInRangeOfAirbase(
|
||||
destHub, -- centered on this base
|
||||
true, -- include hub itself
|
||||
civAir.trafficRange, -- hub size in meters
|
||||
0 -- only airfields
|
||||
)
|
||||
allAB = civAir.excludeAirbases(allAB, civAir.excludeAirfields)
|
||||
sAB = dcsCommon.pickRandom(allAB)
|
||||
return fAB, sAB
|
||||
end
|
||||
|
||||
|
||||
trigger.action.outText("civA: warning - unknown method <" .. civAir.ABPickMethod .. "> in getTwoAirbases()", 30)
|
||||
end
|
||||
|
||||
function civAir.parkingIsFree(fromWP)
|
||||
-- iterate over all currently registres flights and make
|
||||
-- sure that their location isn't closer than 10m to my new parking
|
||||
local loc = {}
|
||||
loc.x = fromWP.x
|
||||
loc.y = fromWP.alt
|
||||
loc.z = fromWP.z
|
||||
|
||||
for name, aPlaneGroup in pairs(civAir.activePlanes) do
|
||||
if aPlaneGroup:isExist() then
|
||||
local aPlane = aPlaneGroup:getUnit(1)
|
||||
if aPlane:isExist() then
|
||||
pos = aPlane:getPoint()
|
||||
local delta = dcsCommon.dist(loc, pos)
|
||||
if delta < 21 then
|
||||
-- way too close
|
||||
trigger.action.outText("civA: too close for comfort - " .. aPlane:getName() .. " occupies my slot", 30)
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
civAir.airStartSeparation = 0
|
||||
function civAir.createFlight(name, theTypeString, fromAirfield, toAirfield, inAirStart)
|
||||
if not fromAirfield then
|
||||
trigger.action.outText("civA: NIL fromAirfield", 30)
|
||||
return nil
|
||||
end
|
||||
|
||||
if not toAirfield then
|
||||
trigger.action.outText("civA: NIL toAirfield", 30)
|
||||
return nil
|
||||
end
|
||||
|
||||
local theGroup = dcsCommon.createEmptyAircraftGroupData (name)
|
||||
local theAUnit = dcsCommon.createAircraftUnitData(name .. "-civA", theTypeString, false)
|
||||
theAUnit.payload.fuel = 100000
|
||||
dcsCommon.addUnitToGroupData(theAUnit, theGroup)
|
||||
|
||||
local fromWP = dcsCommon.createTakeOffFromParkingRoutePointData(fromAirfield)
|
||||
if not fromWP then
|
||||
trigger.action.outText("civA: fromWP create failed", 30)
|
||||
return nil
|
||||
end
|
||||
if inAirStart then
|
||||
-- modify WP into an in-air point
|
||||
fromWP.alt = fromWP.alt + 3000 + civAir.airStartSeparation -- 9000 ft overhead + separation
|
||||
fromWP.action = "Turning Point"
|
||||
fromWP.type = "Turning Point"
|
||||
|
||||
fromWP.speed = 150;
|
||||
fromWP.airdromeId = nil
|
||||
|
||||
theAUnit.alt = fromWP.alt
|
||||
theAUnit.speed = fromWP.speed
|
||||
end
|
||||
-- sometimes, when landing kicks in too early, the plane lands
|
||||
-- at the wrong airfield. AI sucks.
|
||||
-- so we force overflight of target airfield
|
||||
local overheadWP = dcsCommon.createOverheadAirdromeRoutPintData(toAirfield)
|
||||
local toWP = dcsCommon.createLandAtAerodromeRoutePointData(toAirfield)
|
||||
if not toWP then
|
||||
trigger.action.outText("civA: toWP create failed", 30)
|
||||
return nil
|
||||
end
|
||||
|
||||
if not civAir.parkingIsFree(fromWP) then
|
||||
trigger.action.outText("civA: failed free parking check for flight " .. name, 30)
|
||||
return nil
|
||||
end
|
||||
|
||||
dcsCommon.moveGroupDataTo(theGroup,
|
||||
fromWP.x,
|
||||
fromWP.y)
|
||||
dcsCommon.addRoutePointForGroupData(theGroup, fromWP)
|
||||
dcsCommon.addRoutePointForGroupData(theGroup, overheadWP)
|
||||
dcsCommon.addRoutePointForGroupData(theGroup, toWP)
|
||||
|
||||
-- spawn
|
||||
local groupCat = Group.Category.AIRPLANE
|
||||
local theSpawnedGroup = coalition.addGroup(82, groupCat, theGroup) -- 82 is UN peacekeepers
|
||||
return theSpawnedGroup
|
||||
end
|
||||
|
||||
-- flightCount is a global that holds the number of flights we track
|
||||
civAir.flightCount = 0
|
||||
function civAir.createNewFlight(inAirStart)
|
||||
|
||||
civAir.flightCount = civAir.flightCount + 1
|
||||
local fAB, sAB = civAir.getTwoAirbases() -- from AB
|
||||
|
||||
local name = fAB:getName() .. "-" .. sAB:getName().. "/" .. civAir.flightCount
|
||||
local TypeString = dcsCommon.pickRandom(civAir.aircraftTypes)
|
||||
local theFlight = civAir.createFlight(name, TypeString, fAB, sAB, inAirStart)
|
||||
|
||||
if not theFlight then
|
||||
-- flight was not able to spawn.
|
||||
trigger.action.outText("civA: aborted civ spawn on fAB:" .. fAB:getName(), 30)
|
||||
return
|
||||
end
|
||||
|
||||
civAir.addPlane(theFlight) -- track it
|
||||
|
||||
if civAir.verbose then
|
||||
trigger.action.outText("civA: created flight from <" .. fAB:getName() .. "> to <" .. sAB:getName() .. ">", 30)
|
||||
end
|
||||
end
|
||||
|
||||
function civAir.airStartPopulation()
|
||||
local numAirStarts = civAir.maxTraffic / 2
|
||||
civAir.airStartSeparation = 0
|
||||
while numAirStarts > 0 do
|
||||
numAirStarts = numAirStarts - 1
|
||||
civAir.airStartSeparation = civAir.airStartSeparation + 200
|
||||
civAir.createNewFlight(true)
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
-- U P D A T E L O O P
|
||||
--
|
||||
|
||||
function civAir.update()
|
||||
-- reschedule me in the future. ups = updates per second.
|
||||
timer.scheduleFunction(civAir.update, {}, timer.getTime() + 1/civAir.ups)
|
||||
|
||||
-- clean-up first:
|
||||
-- any group that no longer exits will be removed from the array
|
||||
local removeMe = {}
|
||||
for name, group in pairs (civAir.activePlanes) do
|
||||
if not group:isExist() then
|
||||
table.insert(removeMe, name) -- mark for deletion
|
||||
--Group.destroy(group) -- may break
|
||||
end
|
||||
end
|
||||
|
||||
for idx, name in pairs(removeMe) do
|
||||
civAir.activePlanes[name] = nil
|
||||
trigger.action.outText("civA: warning - removed " .. name .. " from active roster, no longer exists", 30)
|
||||
end
|
||||
|
||||
|
||||
-- now, run through all existing flights and update their
|
||||
-- idle times. also count how many planes there are
|
||||
local planeNum = 0
|
||||
local overduePlanes = {}
|
||||
local now = timer.getTime()
|
||||
for name, aPlaneGroup in pairs(civAir.activePlanes) do
|
||||
local speed = 0
|
||||
if aPlaneGroup:isExist() then
|
||||
local aPlane = aPlaneGroup:getUnit(1)
|
||||
|
||||
if aPlane and aPlane:isExist() and aPlane:getLife() >= 1 then
|
||||
planeNum = planeNum + 1
|
||||
local vel = aPlane:getVelocity()
|
||||
speed = dcsCommon.mag(vel.x, vel.y, vel.z)
|
||||
else
|
||||
-- force removal of group
|
||||
civAir.idlePlanes[name] = -1000
|
||||
speed = 0
|
||||
end
|
||||
else
|
||||
-- force removal
|
||||
civAir.idlePlanes[name] = -1000
|
||||
speed = 0
|
||||
end
|
||||
|
||||
if speed < 0.5 then
|
||||
if not civAir.idlePlanes[name] then
|
||||
civAir.idlePlanes[name] = now
|
||||
end
|
||||
local idleTime = now - civAir.idlePlanes[name]
|
||||
--trigger.action.outText("civA: Idling <" .. name .. "> for t=" .. idleTime, 30)
|
||||
if idleTime > civAir.maxIdle then
|
||||
table.insert(overduePlanes, name)
|
||||
end
|
||||
else
|
||||
-- zero out idle plane
|
||||
civAir.idlePlanes[name] = nil
|
||||
end
|
||||
--]]--
|
||||
end
|
||||
|
||||
-- see if we have less than max flights running
|
||||
if planeNum < civAir.maxTraffic then
|
||||
-- spawn a new plane. just one per pass
|
||||
civAir.createNewFlight()
|
||||
end
|
||||
|
||||
-- now remove all planes that are overdue
|
||||
for idx, aName in pairs(overduePlanes) do
|
||||
local aFlight = civAir.getPlane(aName) -- returns a group
|
||||
civAir.removePlaneGroupByName(aName) -- remove from roster
|
||||
if aFlight and aFlight:isExist() then
|
||||
-- destroy can only work if group isexist!
|
||||
Group.destroy(aFlight) -- remember: flights are groups!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function civAir.doDebug(any)
|
||||
trigger.action.outText("cf/x civTraffic debugger.", 30)
|
||||
local desc = "Active Planes:"
|
||||
local now = timer.getTime()
|
||||
for name, group in pairs (civAir.activePlanes) do
|
||||
desc = desc .. "\n" .. name
|
||||
if civAir.idlePlanes[name] then
|
||||
delay = now - civAir.idlePlanes[name]
|
||||
desc = desc .. " (idle for " .. delay .. ")"
|
||||
end
|
||||
end
|
||||
trigger.action.outText(desc, 30)
|
||||
end
|
||||
|
||||
function civAir.collectHubs()
|
||||
local pZones = cfxZones.zonesWithProperty("civAir")
|
||||
|
||||
for k, aZone in pairs(pZones) do
|
||||
local value = cfxZones.getStringFromZoneProperty(aZone, "civAir", "")
|
||||
local af = dcsCommon.getClosestAirbaseTo(aZone.point, 0) -- 0 = only airfields, not farp or ships
|
||||
if af then
|
||||
local afName = af:getName()
|
||||
if value:lower() == "exclude" then
|
||||
table.insert(civAir.excludeAirfields, afName)
|
||||
else
|
||||
table.insert(civAir.trafficCenters, afName)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function civAir.listTrafficCenters()
|
||||
trigger.action.outText("Traffic Centers", 30)
|
||||
for idx, aName in pairs(civAir.trafficCenters) do
|
||||
trigger.action.outText(aName, 30)
|
||||
end
|
||||
end
|
||||
|
||||
-- start
|
||||
function civAir.start()
|
||||
-- module check
|
||||
if not dcsCommon.libCheck("cfx civAir", civAir.requiredLibs) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- see if there is a config zone and load it
|
||||
civAir.readConfigZone()
|
||||
|
||||
-- look for zones to add to air fields list
|
||||
civAir.collectHubs()
|
||||
|
||||
-- make sure there is something in trafficCenters
|
||||
if #civAir.trafficCenters < 1 then
|
||||
trigger.action.outText("+++civTraffic: auto-populating", 30)
|
||||
-- simply add airfields on the map
|
||||
local allBases = dcsCommon.getAirbasesWhoseNameContains("*", 0)
|
||||
for idx, aBase in pairs(allBases) do
|
||||
local afName = aBase:getName()
|
||||
--trigger.action.outText("+++civTraffic: adding " .. afName, 30)
|
||||
table.insert(civAir.trafficCenters, afName)
|
||||
end
|
||||
end
|
||||
|
||||
civAir.listTrafficCenters()
|
||||
|
||||
-- air-start half population if allowed
|
||||
if civAir.initialAirSpawns then
|
||||
civAir.airStartPopulation()
|
||||
end
|
||||
|
||||
-- start the update loop
|
||||
civAir.update()
|
||||
|
||||
-- say hi!
|
||||
trigger.action.outText("cf/x civTraffic v" .. civAir.version .. " started.", 30)
|
||||
return true
|
||||
end
|
||||
|
||||
if not civAir.start() then
|
||||
trigger.action.outText("cf/x civAir aborted: missing libraries", 30)
|
||||
civAir = nil
|
||||
end
|
||||
|
||||
--[[--
|
||||
Additional ideas
|
||||
source to target method
|
||||
--]]--
|
||||
Reference in New Issue
Block a user