mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-09 18:27:47 +00:00
FG v0.0.4
This commit is contained in:
@@ -2,7 +2,10 @@
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Nice stuff.
|
||||
-- * Monitor flight status of elements or entire group.
|
||||
-- * Monitor fuel and ammo status.
|
||||
-- * Sophisicated task queueing system.
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -20,8 +23,14 @@
|
||||
-- @field Wrapper.Group#GROUP flightgroup Flight group object.
|
||||
-- @field #string type Aircraft type of flight group.
|
||||
-- @field #table element Table of elements, i.e. units of the group.
|
||||
-- @field #table waypoints Table of waypoints.
|
||||
-- @field #table coordinates Table of waypoint coordinates.
|
||||
-- @field #table taskqueue Queue of tasks.
|
||||
-- @field #number taskcounter Running number of task ids.
|
||||
-- @field #number taskcurrent ID of current task. If 0, there is no current task assigned.
|
||||
-- @field Core.Set#SET_UNIT detectedunits Set of detected units.
|
||||
-- @field Wrapper.Airbase#AIRBASE homebase The home base of the flight group.
|
||||
-- @field Wrapper.Airbase#AIRBASE destination The destination base of the flight group.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Be surprised!
|
||||
@@ -41,17 +50,20 @@ FLIGHTGROUP = {
|
||||
sid = nil,
|
||||
groupname = nil,
|
||||
flightgroup = nil,
|
||||
grouptemplate = nil,
|
||||
type = nil,
|
||||
waypoints = nil,
|
||||
coordinates = nil,
|
||||
element = {},
|
||||
taskqueue = {},
|
||||
taskcounter = nil,
|
||||
taskcurrent = nil,
|
||||
detectedunits = {},
|
||||
homebase = nil,
|
||||
destination = nil,
|
||||
speedmax = nil,
|
||||
range = nil,
|
||||
altmax = nil,
|
||||
taskcounter = nil,
|
||||
taskcurrent = nil,
|
||||
}
|
||||
|
||||
|
||||
@@ -107,9 +119,9 @@ FLIGHTGROUP.Mission={
|
||||
|
||||
--- Flight group tasks.
|
||||
-- @type FLIGHTGROUP.TaskStatus
|
||||
-- @param #string SCHEDULED Task is sheduled.
|
||||
-- @param #string EXECUTING Task is being executed.
|
||||
-- @param #string ACCOMPLISHED Task is accomplished.
|
||||
-- @field #string SCHEDULED Task is sheduled.
|
||||
-- @field #string EXECUTING Task is being executed.
|
||||
-- @field #string ACCOMPLISHED Task is accomplished.
|
||||
FLIGHTGROUP.TaskStatus={
|
||||
SCHEDULED="scheduled",
|
||||
EXECUTING="executing",
|
||||
@@ -128,15 +140,23 @@ FLIGHTGROUP.TaskStatus={
|
||||
|
||||
--- FLIGHTGROUP class version.
|
||||
-- @field #string version
|
||||
FLIGHTGROUP.version="0.0.3"
|
||||
FLIGHTGROUP.version="0.0.4"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: A lot!
|
||||
-- TODO: Add tasks:
|
||||
-- TODO: Add tasks.
|
||||
-- TODO: Add EPLRS, TACAN.
|
||||
-- TODO: Get ammo.
|
||||
-- TODO: Get pylons.
|
||||
-- TODO: Fuel threshhold ==> RTB.
|
||||
-- TODO: ROE, Afterburner restrict
|
||||
-- TODO: Respawn? With correct loadout, fuelstate.
|
||||
-- TODO: Waypoints, read, add, insert, detour.
|
||||
-- TODO: Damage?
|
||||
-- TODO: shot events?
|
||||
-- TODO:
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@@ -169,15 +189,19 @@ function FLIGHTGROUP:New(groupname)
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||
|
||||
self:AddTransition("*", "FlightStatus", "*") -- FLIGHTGROUP status update.
|
||||
self:AddTransition("*", "QueueUpdate", "*") -- Update task queue.
|
||||
self:AddTransition("*", "AddDetectedUnit", "*") -- Add a newly detected unit to the detected units set.
|
||||
self:AddTransition("*", "LostDetectedUnit", "*") -- Group lost a detected target.
|
||||
|
||||
self:AddTransition("*", "RTB", "Returning") -- Group is returning to base.
|
||||
self:AddTransition("*", "Orbit", "Orbiting") -- Group is holding position.
|
||||
|
||||
self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint.
|
||||
|
||||
self:AddTransition("*", "TaskExecute", "Airborne") -- Group will execute a task.
|
||||
self:AddTransition("*", "TaskDone", "Airborne") -- Group finished a task.
|
||||
self:AddTransition("*", "TaskCancel", "Airborne") -- Cancel current task.
|
||||
self:AddTransition("*", "TaskPause", "Airborne") -- Pause current task.
|
||||
|
||||
self:AddTransition("*", "ElementSpawned", "*") -- An element was spawned.
|
||||
self:AddTransition("*", "ElementParking", "*") -- An element was spawned.
|
||||
@@ -187,6 +211,8 @@ function FLIGHTGROUP:New(groupname)
|
||||
self:AddTransition("*", "ElementArrived", "*") -- An element arrived.
|
||||
self:AddTransition("*", "ElementDead", "*") -- An element crashed, ejected, or pilot dead.
|
||||
|
||||
self:AddTransition("*", "ElementOutOfAmmo", "*") -- An element is completely out of ammo.
|
||||
|
||||
self:AddTransition("*", "FlightSpawned", "Spawned") -- The whole flight group is airborne.
|
||||
self:AddTransition("*", "FlightParking", "Parking") -- The whole flight group is airborne.
|
||||
self:AddTransition("*", "FlightTaxiing", "Taxiing") -- The whole flight group is airborne.
|
||||
@@ -195,7 +221,8 @@ function FLIGHTGROUP:New(groupname)
|
||||
self:AddTransition("*", "FlightArrived", "Arrived") -- The whole flight group has arrived.
|
||||
self:AddTransition("*", "FlightDead", "Dead") -- The whole flight group is dead.
|
||||
|
||||
|
||||
self:AddTransition("*", "FlightOutOfAmmo", "*") -- Flight is completely out of ammo.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
@@ -271,24 +298,35 @@ end
|
||||
-- @param #string description Brief text describing the task, e.g. "Attack SAM".
|
||||
-- @param #table task DCS task table stucture.
|
||||
-- @param #number prio Priority of the task.
|
||||
-- @param #string clock Mission time when task is executed.
|
||||
-- @param #string clock Mission time when task is executed. Default in 60 seconds. If argument passed as #number, it defines a relative delay in seconds.
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:AddTask(description, task, prio, clock)
|
||||
|
||||
-- Increase coutner.
|
||||
self.taskcounter=self.taskcounter+1
|
||||
|
||||
local newtask={} --#FLIGHTGROUP.Task
|
||||
|
||||
-- Set time.
|
||||
local time=timer.getAbsTime()+60
|
||||
if clock then
|
||||
if type(clock)=="string" then
|
||||
time=UTILS.ClockToSeconds(clock)
|
||||
elseif type(clock)=="number" then
|
||||
time=timer.getAbsTime()+clock
|
||||
end
|
||||
end
|
||||
|
||||
-- Task data structure.
|
||||
local newtask={} --#FLIGHTGROUP.Task
|
||||
newtask.description=description
|
||||
newtask.status=FLIGHTGROUP.TaskStatus.SCHEDULED
|
||||
newtask.dcstask=task
|
||||
newtask.prio=prio or 50
|
||||
newtask.time=clock and UTILS.ClockToSeconds(clock) or timer.getAbsTime()+60
|
||||
newtask.time=time
|
||||
newtask.id=self.taskcounter
|
||||
|
||||
self:T2({newtask=newtask})
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.taskqueue, newtask)
|
||||
|
||||
return self
|
||||
@@ -390,6 +428,22 @@ function FLIGHTGROUP:onafterStart(From, Event, To)
|
||||
self:__FlightStatus(-1)
|
||||
end
|
||||
|
||||
--- On after Start event. Starts the FLIGHTGROUP FSM and event handlers.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Wrapper.Group#GROUP Group Flight group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Group#GROUP Group The group object.
|
||||
function FLIGHTGROUP:onafterFlightSpawned(From, Event, To, Group)
|
||||
|
||||
self.template=self.flightgroup:GetTemplate()
|
||||
|
||||
-- Init waypoints.
|
||||
self:_InitWaypoints()
|
||||
|
||||
end
|
||||
|
||||
--- On after "FlightStatus" event.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Wrapper.Group#GROUP Group Flight group.
|
||||
@@ -428,19 +482,6 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To)
|
||||
end
|
||||
self:I(text)
|
||||
|
||||
-- Check no current task.
|
||||
if self.taskcurrent<=0 then
|
||||
|
||||
-- Get task from queue.
|
||||
local task=self:GetTask()
|
||||
|
||||
-- Execute task if any.
|
||||
if task then
|
||||
self:TaskExecute(task)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Task queue.
|
||||
text="Tasks:"
|
||||
for i,_task in pairs(self.taskqueue) do
|
||||
@@ -462,6 +503,30 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To)
|
||||
self:__FlightStatus(-30)
|
||||
end
|
||||
|
||||
--- On after "FlightStatus" event.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param Wrapper.Group#GROUP Group Flight group.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterQueueUpdate(From, Event, To)
|
||||
|
||||
-- Check no current task.
|
||||
if self.taskcurrent<=0 then
|
||||
|
||||
-- Get task from queue.
|
||||
local task=self:GetTask()
|
||||
|
||||
-- Execute task if any.
|
||||
if task then
|
||||
self:TaskExecute(task)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self:__QueueUpdate(-1)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Events
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -793,7 +858,7 @@ function FLIGHTGROUP:onafterTaskPause(From, Event, To, Task)
|
||||
self.flightgroup:ClearTasks()
|
||||
|
||||
-- Task status executing.
|
||||
Task.status=FLIGHTGROUP.TaskStatus.PAUSED
|
||||
Task.status=1 --FLIGHTGROUP.TaskStatus.PAUSED
|
||||
|
||||
end
|
||||
|
||||
@@ -925,7 +990,7 @@ function FLIGHTGROUP:TaskIntercept(bandit)
|
||||
-- Start uncontrolled group.
|
||||
self.flightgroup:StartUncontrolled()
|
||||
|
||||
--airboss:SetExcludeAI()
|
||||
--FLIGHTGROUP:SetExcludeAI()
|
||||
|
||||
-- Route group
|
||||
self.flightgroup:Route(wp)
|
||||
@@ -1064,6 +1129,139 @@ function FLIGHTGROUP:GetElementByName(unitname)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get task by its id.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #number id Task id.
|
||||
-- @param #string status (Optional) Only return tasks with this status, e.g. FLIGHTGROUP.TaskStatus.SCHEDULED.
|
||||
-- @return #FLIGHTGROUP.Task The task or nil.
|
||||
function FLIGHTGROUP:GetTaskByID(id, status)
|
||||
|
||||
for _,_task in pairs(self.taskqueue) do
|
||||
local task=_task --#FLIGHTGROUP.Task
|
||||
|
||||
if task.id==id then
|
||||
if status==nil or status==task.status then
|
||||
return task
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Get next waypoint of the flight group.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return Core.Point#COORDINATE Coordinate of the next waypoint.
|
||||
-- @return #number Number of waypoint.
|
||||
function FLIGHTGROUP:GetNextWaypoint()
|
||||
|
||||
-- Next waypoint.
|
||||
local Nextwp=nil
|
||||
if self.currentwp==#self.waypoints then
|
||||
Nextwp=1
|
||||
else
|
||||
Nextwp=self.currentwp+1
|
||||
end
|
||||
|
||||
-- Debug output
|
||||
local text=string.format("Current WP=%d/%d, next WP=%d", self.currentwp, #self.waypoints, Nextwp)
|
||||
self:T2(self.lid..text)
|
||||
|
||||
-- Next waypoint.
|
||||
local nextwp=self.waypoints[Nextwp] --Core.Point#COORDINATE
|
||||
|
||||
return nextwp,Nextwp
|
||||
end
|
||||
|
||||
|
||||
--- Update route of group, e.g after new waypoints and/or waypoint tasks have been added.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:_UpdateRoute()
|
||||
|
||||
local wp={}
|
||||
|
||||
for i=self.currentwp,#self.waypoints do
|
||||
table.insert(wp, self.waypoints[i])
|
||||
end
|
||||
|
||||
self.flightgroup:GetTaskRoute()
|
||||
self.flightgroup:TaskRoute(wp)
|
||||
self.flightgroup:Route(wp, 1)
|
||||
end
|
||||
|
||||
--- Initialize Mission Editor waypoints.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @return #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:_InitWaypoints()
|
||||
|
||||
-- Waypoints of group as defined in the ME.
|
||||
self.waypoints=self.flightgroup:GetTemplateRoutePoints()
|
||||
|
||||
-- Init array.
|
||||
self.coordinates={}
|
||||
|
||||
-- Set waypoint table.
|
||||
for i,point in ipairs(self.waypoints or {}) do
|
||||
|
||||
-- Coordinate of the waypoint
|
||||
local coord=COORDINATE:New(point.x, point.alt, point.y)
|
||||
|
||||
-- Set velocity of the coordinate.
|
||||
coord:SetVelocity(point.speed)
|
||||
|
||||
-- Add to table.
|
||||
table.insert(self.coordinates, coord)
|
||||
|
||||
-- Debug info.
|
||||
if self.Debug then
|
||||
coord:MarkToAll(string.format("Flight %s waypoint %d, Speed=%.1f knots", self.groupname, i, UTILS.MpsToKnots(point.speed)))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self.currentwp=1
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Function called when a group is passing a waypoint.
|
||||
--@param Wrapper.Group#GROUP group Group that passed the waypoint
|
||||
--@param #FLIGHTGROUP flightgroup Flightgroup object.
|
||||
--@param #number i Waypoint number that has been reached.
|
||||
--@param #number final Final waypoint number.
|
||||
function FLIGHGROUP._PassingWaypoint(group, flightgroup, i, final)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Group %s passing waypoint %d of %d.", group:GetName(), i, final)
|
||||
|
||||
-- Debug smoke and marker.
|
||||
if flightgroup.Debug then
|
||||
local pos=group:GetCoordinate()
|
||||
pos:SmokeRed()
|
||||
local MarkerID=pos:MarkToAll(string.format("Group %s reached waypoint %d", group:GetName(), i))
|
||||
end
|
||||
|
||||
-- Debug message.
|
||||
MESSAGE:New(text,10):ToAllIf(flightgroup.Debug)
|
||||
flightgroup:T(flightgroup.sid..text)
|
||||
|
||||
-- Set current waypoint.
|
||||
flightgroup.currentwp=i
|
||||
|
||||
-- Passing Waypoint event.
|
||||
flightgroup:PassingWaypoint(i)
|
||||
|
||||
-- If final waypoint reached, do route all over again.
|
||||
if i==final and final>1 then
|
||||
--TODO: final waypoint reached! what next?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- Check if a unit is and element of the flightgroup.
|
||||
-- @param #FLIGHTGROUP self
|
||||
@@ -1367,6 +1565,138 @@ function FLIGHTGROUP:_GetOnboardNumber(unitname)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the number of shells a unit or group currently has. For a group the ammo count of all units is summed up.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #FLIGHTGROUP.Element element The element.
|
||||
-- @param #boolean display Display ammo table as message to all. Default false.
|
||||
-- @return #number Total amount of ammo the whole group has left.
|
||||
-- @return #number Number of shells left.
|
||||
-- @return #number Number of rockets left.
|
||||
-- @return #number Number of bombs left.
|
||||
-- @return #number Number of missiles left.
|
||||
function FLIGHTGROUP:GetAmmoElement(element, display)
|
||||
|
||||
-- Default is display false.
|
||||
if display==nil then
|
||||
display=false
|
||||
end
|
||||
|
||||
-- Init counter.
|
||||
local nammo=0
|
||||
local nshells=0
|
||||
local nrockets=0
|
||||
local nmissiles=0
|
||||
local nbombs=0
|
||||
|
||||
local unit=element.unit
|
||||
|
||||
|
||||
-- Output.
|
||||
local text=string.format("FLIGHTGROUP group %s - unit %s:\n", self.groupname, unit:GetName())
|
||||
|
||||
-- Get ammo table.
|
||||
local ammotable=unit:GetAmmo()
|
||||
|
||||
if ammotable then
|
||||
|
||||
local weapons=#ammotable
|
||||
|
||||
-- Display ammo table
|
||||
if display then
|
||||
self:E(FLIGHTGROUP.id..string.format("Number of weapons %d.", weapons))
|
||||
self:E({ammotable=ammotable})
|
||||
self:E(FLIGHTGROUP.id.."Ammotable:")
|
||||
for id,bla in pairs(ammotable) do
|
||||
self:E({id=id, ammo=bla})
|
||||
end
|
||||
end
|
||||
|
||||
-- Loop over all weapons.
|
||||
for w=1,weapons do
|
||||
|
||||
-- Number of current weapon.
|
||||
local Nammo=ammotable[w]["count"]
|
||||
|
||||
-- Type name of current weapon.
|
||||
local Tammo=ammotable[w]["desc"]["typeName"]
|
||||
|
||||
local _weaponString = UTILS.Split(Tammo,"%.")
|
||||
local _weaponName = _weaponString[#_weaponString]
|
||||
|
||||
-- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3
|
||||
local Category=ammotable[w].desc.category
|
||||
|
||||
-- Get missile category: Weapon.MissileCategory AAM=1, SAM=2, BM=3, ANTI_SHIP=4, CRUISE=5, OTHER=6
|
||||
local MissileCategory=nil
|
||||
if Category==Weapon.Category.MISSILE then
|
||||
MissileCategory=ammotable[w].desc.missileCategory
|
||||
end
|
||||
|
||||
-- We are specifically looking for shells or rockets here.
|
||||
if Category==Weapon.Category.SHELL then
|
||||
|
||||
-- Add up all shells.
|
||||
nshells=nshells+Nammo
|
||||
|
||||
-- Debug info.
|
||||
text=text..string.format("- %d shells of type %s\n", Nammo, _weaponName)
|
||||
|
||||
elseif Category==Weapon.Category.ROCKET then
|
||||
|
||||
-- Add up all rockets.
|
||||
nrockets=nrockets+Nammo
|
||||
|
||||
-- Debug info.
|
||||
text=text..string.format("- %d rockets of type %s\n", Nammo, _weaponName)
|
||||
|
||||
elseif Category==Weapon.Category.BOMB then
|
||||
|
||||
-- Add up all rockets.
|
||||
nbombs=nbombs+Nammo
|
||||
|
||||
-- Debug info.
|
||||
text=text..string.format("- %d bombs of type %s\n", Nammo, _weaponName)
|
||||
|
||||
elseif Category==Weapon.Category.MISSILE then
|
||||
|
||||
-- Add up all cruise missiles (category 5)
|
||||
if MissileCategory==Weapon.MissileCategory.AAM then
|
||||
nmissiles=nmissiles+Nammo
|
||||
elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then
|
||||
nmissiles=nmissiles+Nammo
|
||||
elseif MissileCategory==Weapon.MissileCategory.BM then
|
||||
nmissiles=nmissiles+Nammo
|
||||
elseif MissileCategory==Weapon.MissileCategory.OTHER then
|
||||
nmissiles=nmissiles+Nammo
|
||||
end
|
||||
|
||||
-- Debug info.
|
||||
text=text..string.format("- %d %s missiles of type %s\n", Nammo, self:_MissileCategoryName(MissileCategory), _weaponName)
|
||||
|
||||
else
|
||||
|
||||
-- Debug info.
|
||||
text=text..string.format("- %d unknown ammo of type %s (category=%d, missile category=%s)\n", Nammo, Tammo, Category, tostring(MissileCategory))
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-- Debug text and send message.
|
||||
if display then
|
||||
self:I(self.sid..text)
|
||||
else
|
||||
self:T3(self.sid..text)
|
||||
end
|
||||
MESSAGE:New(text, 10):ToAllIf(display or self.Debug)
|
||||
|
||||
-- Total amount of ammunition.
|
||||
nammo=nshells+nrockets+nmissiles+nbombs
|
||||
|
||||
return nammo, nshells, nrockets, nbombs, nmissiles
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user