diff --git a/_docs/GetStarted.md b/_docs/GetStarted.md index c53c3e0..8104858 100644 --- a/_docs/GetStarted.md +++ b/_docs/GetStarted.md @@ -187,4 +187,18 @@ It can be friendly forces driving around. A FARP with surrounding units and tent ## Airbases, Farps and Carriers -On top of units and missions, airbases, farps and carriers are big parts of a mission. \ No newline at end of file +On top of units and missions, airbases, farps and carriers are big parts of a mission. + + +### Carriers + +Aircraft carriers and fleets are very nice, but what use have they if they won't move along with the front line?
+For a carrier fleet to be managed it needs to abide to the name `CARRIERGROUP__`
+For example, we have a single carrier here with the groupname: `CARRIERGROUP_ALPHA_fleet`
+To let the framework know where you want the carrier to be at which stages of the mission you can create `CARRIERROUTE__[-]_` zones.
+In the image below we have 2 zones. `CARRIERROUTE_ALPHA_[1-2]_ROUTE` and `CARRIERROUTE_ALPHA_[3-4]_ROUTE`.
+This tells the framework where carriergroup `ALPHA` should go so you can have multiple smaller subfleets.
+ + + +![carrierroutes](img/carrierroutes.png) \ No newline at end of file diff --git a/_docs/img/carrierroutes.png b/_docs/img/carrierroutes.png new file mode 100644 index 0000000..2dbe64d Binary files /dev/null and b/_docs/img/carrierroutes.png differ diff --git a/_miz/SPEARHEADDEV.miz b/_miz/SPEARHEADDEV.miz index 08f48b4..b3c02be 100644 Binary files a/_miz/SPEARHEADDEV.miz and b/_miz/SPEARHEADDEV.miz differ diff --git a/classes/fleetClasses/FleetGroup.lua b/classes/fleetClasses/FleetGroup.lua new file mode 100644 index 0000000..d3a182c --- /dev/null +++ b/classes/fleetClasses/FleetGroup.lua @@ -0,0 +1,132 @@ +local FleetGroup = {} + +function FleetGroup:new(fleetGroupName, database, logger) + local o = {} + + setmetatable(o, { __index = self }) + + o.fleetGroupName = fleetGroupName + o.logger = logger + + local split_name = Spearhead.Util.split_string(fleetGroupName, "_") + if Spearhead.Util.tableLength(split_name) < 2 then + Spearhead.AddMissionEditorWarning("CARRIERGROUP should have at least 2 parts. CARRIERGROUP_") + return nil + end + o.fleetNameIdentifier = split_name[2] + + o.targetZonePerStage = {} + o.currentTargetZone = nil + o.pointsPerZone = {} + + do --INIT + local carrierRouteZones = database:getCarrierRouteZones() + for _, zoneName in pairs(carrierRouteZones) do + if Spearhead.Util.strContains(string.lower(zoneName), "_".. string.lower(o.fleetNameIdentifier) .. "_" ) == true then + local zone = Spearhead.DcsUtil.getZoneByName(zoneName) + if zone and zone.zone_type == Spearhead.DcsUtil.ZoneType.Polygon then + local split_string = Spearhead.Util.split_string(zoneName, "_") + if Spearhead.Util.tableLength(split_string) < 3 then + Spearhead.AddMissionEditorWarning( + "CARRIERROUTE should at least have 3 parts. Check the documentation for: " .. zoneName) + else + local function GetTwoFurthestPoints(zone) + local function getDist(a, b) + return math.sqrt((b.x - a.x) ^ 2 + (b.z - a.z) ^ 2) + end + + local biggest = nil + local biggestA = nil + local biggestB = nil + + for i = 1, 3 do + for ii = i + 1, 4 do + local a = zone.verts[i] + local b = zone.verts[ii] + local dist = getDist(a, b) + + if biggest == nil or dist > biggest then + biggestA = a + biggestB = b + biggest = dist + end + end + end + return { x = biggestA.x, z = biggestA.z }, { x = biggestB.x, z = biggestB.z } + end + + local function getMinMaxStage(namePart) + if namePart == nil then + return nil, nil + end + + if Spearhead.Util.startswith(namePart, "%[") == true then + namePart = Spearhead.Util.split_string(namePart, "[")[1] + end + + if Spearhead.Util.strContains(namePart, "%]") == true then + namePart = Spearhead.Util.split_string(namePart, "]")[1] + end + + local split_numbers = Spearhead.Util.split_string(namePart, "-") + if Spearhead.Util.tableLength(split_numbers) < 2 then + Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[-]: " .. zoneName) + return nil, nil + end + + local first = tonumber(split_numbers[1]) + local second = tonumber(split_numbers[2]) + + if first == nil or second == nil then + Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[-]: " .. zoneName) + return nil, nil + end + return first, second + end + + local pointA, pointB = GetTwoFurthestPoints(zone) + local first, second = getMinMaxStage(split_string[3]) + if first ~= nil and second ~= nil then + for i = first, second do + o.targetZonePerStage[tostring(i)] = zoneName + end + o.pointsPerZone[zoneName] = { pointA = pointA, pointB = pointB } + else + Spearhead.AddMissionEditorWarning("CARRIERROUTE zone stage numbers not in the format _[-]: " .. zoneName) + end + end + else + Spearhead.AddMissionEditorWarning("CARRIERROUTE cannot be a cilinder: " .. zoneName) + end + end + end + end + + local SetTaskAsync = function(input, time) + local targetZone = input.targetZone + local task = input.task + local groupName = input.groupName + local logger = input.logger + + local group = Group.getByName(groupName) + if group then + logger:info("Sending " .. fleetGroupName .. " to " .. targetZone) + group:getController():setTask(task) + end + end + + o.OnStageNumberChanged = function(self, number) + local targetZone = self.targetZonePerStage[tostring(number)] + if targetZone and targetZone ~= self.currentTargetZone then + local points = self.pointsPerZone[targetZone] + local task = Spearhead.RouteUtil.CreateCarrierRacetrack(points.pointA, points.pointB) + timer.scheduleFunction(SetTaskAsync, { task = task, targetZone = targetZone, groupName = self.fleetGroupName, logger = self.logger }, timer.getTime() + 5) + end + end + + Spearhead.Events.AddStageNumberChangedListener(o) + return o +end + +if not Spearhead.internal then Spearhead.internal = {} end +Spearhead.internal.FleetGroup = FleetGroup diff --git a/classes/fleetClasses/GlobalFleetManager.lua b/classes/fleetClasses/GlobalFleetManager.lua new file mode 100644 index 0000000..ec546a6 --- /dev/null +++ b/classes/fleetClasses/GlobalFleetManager.lua @@ -0,0 +1,21 @@ + + +local GlobalFleetManager = {} + +local fleetGroups = {} + +GlobalFleetManager.start = function(database) + + local logger = Spearhead.LoggerTemplate:new("CARRIERFLEET", Spearhead.LoggerTemplate.LogLevelOptions.DEBUG) + + local all_groups = Spearhead.DcsUtil.getAllGroupNames() + for _, groupName in pairs(all_groups) do + if Spearhead.Util.startswith(string.lower(groupName), "carriergroup" ) == true then + logger:info("Registering " .. groupName .. " as a managed fleet") + local carrierGroup = Spearhead.internal.FleetGroup:new(groupName, database, logger) + table.insert(fleetGroups, carrierGroup) + end + end +end + +Spearhead.internal.GlobalFleetManager = GlobalFleetManager \ No newline at end of file diff --git a/classes/spearhead_base.lua b/classes/spearhead_base.lua index eb41293..3537cb8 100644 --- a/classes/spearhead_base.lua +++ b/classes/spearhead_base.lua @@ -1,4 +1,3 @@ - --- DEFAULT Values if Spearhead == nil then Spearhead = {} end @@ -84,6 +83,14 @@ do -- INIT UTIL return str:find('^' .. findable) ~= nil end + ---comment + ---@param str string + ---@param findable string + ---@return boolean + UTIL.strContains = function(str, findable) + return str:find(findable) ~= nil + end + ---comment ---@param str string ---@param findableTable table @@ -1256,13 +1263,85 @@ do --setup route util } }, "" end + + ROUTE_UTIL.CreateCarrierRacetrack = function(pointA, pointB) + return { + id = "Mission", + params = { + airborne = false, + route = { + points = { + [1] = + { + ["alt"] = -0, + ["type"] = "Turning Point", + ["ETA"] = 0, + ["alt_type"] = "BARO", + ["formation_template"] = "", + ["y"] = pointA.z, + ["x"] = pointA.x, + ["ETA_locked"] = false, + ["speed"] = 13.88888, + ["action"] = "Turning Point", + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = {}, + }, -- end of ["params"] + }, -- end of ["task"] + ["speed_locked"] = true, + }, + [2] = + { + ["alt"] = -0, + ["type"] = "Turning Point", + ["ETA"] = -0, + ["alt_type"] = "BARO", + ["formation_template"] = "", + ["y"] = pointB.z, + ["x"] = pointB.x, + ["ETA_locked"] = false, + ["speed"] = 13.88888, + ["action"] = "Turning Point", + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["auto"] = false, + ["id"] = "GoToWaypoint", + ["number"] = 1, + ["params"] = + { + ["fromWaypointIndex"] = 2, + ["nWaypointIndx"] = 1, + }, + }, + }, + }, + }, + ["speed_locked"] = true, + } + } + } + } + }, "" + end end Spearhead.RouteUtil = ROUTE_UTIL local SpearheadEvents = {} do - local SpearheadLogger = Spearhead.LoggerTemplate:new("Spearhead Events", Spearhead.LoggerTemplate.LogLevelOptions.INFO) + local SpearheadLogger = Spearhead.LoggerTemplate:new("Spearhead Events", + Spearhead.LoggerTemplate.LogLevelOptions.INFO) do -- STAGE NUMBER CHANGED local OnStageNumberChangedListeners = {} @@ -1455,9 +1534,8 @@ do end end - do --COMMANDS + do --COMMANDS do -- status updates - local onStatusRequestReceivedListeners = {} ---comment ---@param listener table object with OnStatusRequestReceived(self, groupId) @@ -1470,9 +1548,9 @@ do table.insert(onStatusRequestReceivedListeners, listener) end - local triggerStatusRequestReceived = function (groupId) + local triggerStatusRequestReceived = function(groupId) for _, callable in pairs(onStatusRequestReceivedListeners) do - local succ, err = pcall(function () + local succ, err = pcall(function() callable:OnStatusRequestReceived(groupId) end) end @@ -1481,7 +1559,8 @@ do SpearheadEvents.AddCommandsToGroup = function(groupId) local base = "MISSIONS" if groupId then - missionCommands.addCommandForGroup(groupId, "Stage Status", nil, triggerStatusRequestReceived, groupId) + missionCommands.addCommandForGroup(groupId, "Stage Status", nil, triggerStatusRequestReceived, + groupId) end end @@ -1489,7 +1568,7 @@ do local id = net.get_my_player_id() if id == 0 then SpearheadLogger:info("Single Player detected") - + local unit = world.getPlayer() if unit then local groupId = unit:getGroup():getID() @@ -1497,19 +1576,20 @@ do --DEBUG COMMANDS do - local activateStage = function (number) + local activateStage = function(number) SpearheadEvents.PublishStageNumberChanged(number) end - missionCommands.addSubMenuForGroup(groupId , "debug" , nil) - missionCommands.addSubMenuForGroup(groupId , "Set Stage" , {"debug"}) + missionCommands.addSubMenuForGroup(groupId, "debug", nil) + missionCommands.addSubMenuForGroup(groupId, "Set Stage", { "debug" }) for i = 0, 9 do local menuName = tostring(i) .. ".." - missionCommands.addSubMenuForGroup(groupId , menuName, {"debug", "Set Stage"}) + missionCommands.addSubMenuForGroup(groupId, menuName, { "debug", "Set Stage" }) for ii = 0, 9 do - local number = tonumber(tostring(i) .. tostring(ii)) - missionCommands.addCommandForGroup(groupId, "Stage " .. tostring(number), { "debug", "Set Stage", menuName }, activateStage, number) + local number = tonumber(tostring(i) .. tostring(ii)) + missionCommands.addCommandForGroup(groupId, "Stage " .. tostring(number), + { "debug", "Set Stage", menuName }, activateStage, number) end end end diff --git a/classes/spearhead_db.lua b/classes/spearhead_db.lua index e1f3451..e346f00 100644 --- a/classes/spearhead_db.lua +++ b/classes/spearhead_db.lua @@ -28,6 +28,7 @@ do -- DB o.tables.random_mission_zones = {} o.tables.farp_zones = {} o.tables.cap_route_zones = {} + o.tables.carrier_route_zones = {} o.tables.stage_zonesByNumer = {} o.tables.stage_numberPerzone = {} @@ -66,6 +67,10 @@ do -- DB if string.lower(split_string[1]) == "caproute" then table.insert(o.tables.cap_route_zones, zone_name) end + + if string.lower(split_string[1]) == "carrierroute" then + table.insert(o.tables.carrier_route_zones, zone_name) + end end end end @@ -181,7 +186,8 @@ do -- DB end end end - + + o.tables.farpZonesPerStage = {} for _, farpZoneName in pairs(o.tables.farp_zones) do @@ -437,6 +443,7 @@ do -- DB end end end + o.Logger:debug(o.tables.capRoutesPerStageNumber) o.tables.missionCodes = {} @@ -517,6 +524,10 @@ do -- DB return self.tables.stage_zones end + o.getCarrierRouteZones = function (self) + return self.tables.carrier_route_zones + end + o.getMissionsForStage = function (self, stagename) return self.tables.missionZonesPerStage[stagename] or {} end diff --git a/main.lua b/main.lua index b604929..a9a9f04 100644 --- a/main.lua +++ b/main.lua @@ -21,7 +21,7 @@ local stageConfig = { Spearhead.internal.GlobalCapManager.start(databaseManager, capConfig, stageConfig) Spearhead.internal.GlobalStageManager.start(databaseManager, stageConfig) - +Spearhead.internal.GlobalFleetManager.start(databaseManager) Spearhead.Events.PublishStageNumberChanged(1)