-- ==================================================================================== -- TUM.TERRITORIES - HANDLES THE MISSION SPECIAL ZONES (COALITION TERRITORIES, WATER AND BATTLE ZONES) -- ==================================================================================== -- (local) assignTerritoryToZone(coalitionID, zone) -- TUM.territories.getCenter(side) -- TUM.territories.getPointOwner(point) -- TUM.territories.getRandomPoint(side, surfaceType) -- TUM.territories.getSurfaceArea(side) -- TUM.territories.onInitialize() -- ==================================================================================== TUM.territories = {} do local coalitionZones = { {}, {} } local missionZones = {} local waterZones = {} local function addZoneToCoalition(zone, side) table.insert(coalitionZones[side], zone) local airbases = world.getAirbases() for _,ab in pairs(airbases) do local airbasePoint2 = DCSEx.math.vec3ToVec2(ab:getPoint()) if DCSEx.zones.isPointInside(zone, airbasePoint2) then if ab:getDesc().category ~= Airbase.Category.SHIP then -- Ignore ships ab:setCoalition(side) end end end end function TUM.territories.getMissionZones() return DCSEx.table.deepCopy(missionZones) end function TUM.territories.getWaterZones() return DCSEx.table.deepCopy(waterZones) end ------------------------------------- -- Returns the coalition to which belong a given point on the map. -- Return coalition.side.NEUTRAL if the point isn't in any coalition territory. -- @param point A vec2 or vec3 -- @return A value from the coalition.side enum ------------------------------------- function TUM.territories.getPointOwner(point) for side=1,2 do for _,z in ipairs(coalitionZones[side]) do if DCSEx.zones.isPointInside(z, point) then return side end end end return coalition.side.NEUTRAL end function TUM.territories.getTerritoryZones(side) return DCSEx.table.deepCopy(coalitionZones[side]) end function TUM.territories.getTerritoryCenter(side) local center = { x = 0, y = 0 } if #coalitionZones[side] == 0 then return center end for _,z in ipairs(coalitionZones[side]) do center.x = center.x + z.x center.y = center.y + z.y end -- TODO: bigger zones should skew the center in their favor center.x = center.x / #coalitionZones[side] center.y = center.y / #coalitionZones[side] return center end -- function TUM.territories.getCenter(side) -- return DCSEx.zones.getCenter(zones[side]) -- end -- function TUM.territories.getSurfaceArea(side) -- return DCSEx.zones.getSurfaceArea(zones[side]) -- end -- function TUM.territories.getZone(side) -- return DCSEx.table.deepCopy(zones[side]) -- end function TUM.territories.getRandomPointInTerritory(side, surfaceType) if #coalitionZones[side] == 0 then return nil end local zone = DCSEx.table.getRandom(coalitionZones[side]) -- TODO: bigger zones should be selected more often return DCSEx.zones.getRandomPointInside(zone, surfaceType) end ------------------------------------- -- Called on mission start up -- @return True if started up properly, false if an error happened ------------------------------------- function TUM.territories.onStartUp() coalitionZones = { {}, {} } missionZones = {} waterZones = {} -- Disable autocapture for all bases and give them to the neutral coalition for _,ab in pairs(world.getAirbases()) do ab:autoCapture(false) if ab:getDesc().category ~= Airbase.Category.SHIP then -- Ignore ships ab:setCoalition(coalition.side.NEUTRAL) end end local zones = DCSEx.zones.getAll() for _,z in ipairs(zones) do if DCSEx.string.startsWith(z.name:lower(), "blufor") then addZoneToCoalition(z, coalition.side.BLUE) elseif DCSEx.string.startsWith(z.name:lower(), "redfor") then addZoneToCoalition(z, coalition.side.RED) elseif DCSEx.string.startsWith(z.name:lower(), "water") then table.insert(waterZones, z) else local onlyZonesStartingWith = TUM.administrativeSettings.getValue(TUM.administrativeSettings.ONLY_ZONES_STARTINGWITH) if onlyZonesStartingWith and #onlyZonesStartingWith > 0 then if type(onlyZonesStartingWith) ~= "table" then onlyZonesStartingWith = { onlyZonesStartingWith } end for _, zonePrefix in ipairs(onlyZonesStartingWith) do if DCSEx.string.startsWith(z.name:lower(), zonePrefix:lower()) then table.insert(missionZones, z) break end end else local ignoreZonesStartingWith = TUM.administrativeSettings.getValue(TUM.administrativeSettings.IGNORE_ZONES_STARTINGWITH) if ignoreZonesStartingWith then if not DCSEx.string.startsWith(z.name:lower(), ignoreZonesStartingWith:lower()) then table.insert(missionZones, z) end else table.insert(missionZones, z) end end end end for side=1,2 do if #coalitionZones[side] == 0 or #coalition.getAirbases(side) == 0 then local name = DCSEx.dcs.getCoalitionAsString(side) local zoneName = "BLUFOR" if side == 1 then zoneName = "REDFOR" end TUM.log("Coalition "..name.." has no territory zones and/or controls no airfields. Please add zone with a name starting with "..zoneName.." in the mission editor and make sure at least one contains an airbase.", TUM.logger.logLevel.ERROR) return false end end if #missionZones == 0 then TUM.log("No mission zones found. Create at least one mission zone in the mission editor.", TUM.logger.logLevel.ERROR) return false end if #missionZones > 10 then TUM.log("Too many mission zones, extra zones removed.", TUM.logger.logLevel.WARNING) while #missionZones > 10 do table.remove(missionZones, 11) end end -- zones = {} -- zones[coalition.side.BLUE] = DCSEx.zones.getByName("BLUFOR") -- zones[coalition.side.RED] = DCSEx.zones.getByName("REDFOR") -- if not zones[coalition.side.BLUE] then -- TUM.log("BLUFOR zone not found.", TUM.logger.logLevel.ERROR) -- return false -- elseif not zones[coalition.side.RED] then -- TUM.log("REDFOR zone not found.", TUM.logger.logLevel.ERROR) -- return false -- end -- -- TODO: square kilometers if "metric system" enabled? -- for side=1,2 do -- TUM.log( -- "Coalition "..DCSEx.dcs.getCoalitionAsString(side):upper().."'s territory is ".. -- DCSEx.string.toStringThousandsSeparator(math.floor(TUM.territories.getSurfaceArea(side) / 2589988.110336)).." squared miles.") -- end return true end end