mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #1362 from FlightControl-Master/FF/Ops
Ops Enhancements
This commit is contained in:
commit
bad8dc2220
@ -913,7 +913,7 @@ do -- FSM
|
|||||||
--- Check if FSM is in state.
|
--- Check if FSM is in state.
|
||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @param #string State State name.
|
-- @param #string State State name.
|
||||||
-- @param #boolean If true, FSM is in this state.
|
-- @return #boolean If true, FSM is in this state.
|
||||||
function FSM:Is( State )
|
function FSM:Is( State )
|
||||||
return self.current == State
|
return self.current == State
|
||||||
end
|
end
|
||||||
@ -921,7 +921,7 @@ do -- FSM
|
|||||||
--- Check if FSM is in state.
|
--- Check if FSM is in state.
|
||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @param #string State State name.
|
-- @param #string State State name.
|
||||||
-- @param #boolean If true, FSM is in this state.
|
-- @return #boolean If true, FSM is in this state.
|
||||||
function FSM:is(state)
|
function FSM:is(state)
|
||||||
return self.current == state
|
return self.current == state
|
||||||
end
|
end
|
||||||
|
|||||||
@ -284,6 +284,12 @@ do -- COORDINATE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return the coordinates itself. Sounds stupid but can be useful for compatibility.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:GetCoordinate()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Return the coordinates of the COORDINATE in Vec3 format.
|
--- Return the coordinates of the COORDINATE in Vec3 format.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
@ -733,6 +739,13 @@ do -- COORDINATE
|
|||||||
return Velocity or 0
|
return Velocity or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return the "name" of the COORDINATE. Obviously, a coordinate does not have a name like a unit, static or group. So here we take the MGRS coordinates of the position.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #string MGRS coordinates.
|
||||||
|
function COORDINATE:GetName()
|
||||||
|
local name=self:ToStringMGRS()
|
||||||
|
return rname
|
||||||
|
end
|
||||||
|
|
||||||
--- Return velocity text of the COORDINATE.
|
--- Return velocity text of the COORDINATE.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
-- @field #number dT Time interval between function calls in seconds.
|
-- @field #number dT Time interval between function calls in seconds.
|
||||||
-- @field #number ncalls Counter of function calls.
|
-- @field #number ncalls Counter of function calls.
|
||||||
-- @field #number ncallsMax Max number of function calls. If reached, timer is stopped.
|
-- @field #number ncallsMax Max number of function calls. If reached, timer is stopped.
|
||||||
|
-- @field #boolean isrunning If `true`, timer is running. Else it was not started yet or was stopped.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- *Better three hours too soon than a minute too late.* - William Shakespeare
|
--- *Better three hours too soon than a minute too late.* - William Shakespeare
|
||||||
@ -111,7 +112,7 @@ _TIMERID=0
|
|||||||
|
|
||||||
--- TIMER class version.
|
--- TIMER class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
TIMER.version="0.1.0"
|
TIMER.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -143,6 +144,9 @@ function TIMER:New(Function, ...)
|
|||||||
-- Number of function calls.
|
-- Number of function calls.
|
||||||
self.ncalls=0
|
self.ncalls=0
|
||||||
|
|
||||||
|
-- Not running yet.
|
||||||
|
self.isrunning=false
|
||||||
|
|
||||||
-- Increase counter
|
-- Increase counter
|
||||||
_TIMERID=_TIMERID+1
|
_TIMERID=_TIMERID+1
|
||||||
|
|
||||||
@ -186,6 +190,9 @@ function TIMER:Start(Tstart, dT, Duration)
|
|||||||
-- Set log id.
|
-- Set log id.
|
||||||
self.lid=string.format("TIMER UID=%d/%d | ", self.uid, self.tid)
|
self.lid=string.format("TIMER UID=%d/%d | ", self.uid, self.tid)
|
||||||
|
|
||||||
|
-- Is now running.
|
||||||
|
self.isrunning=true
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Starting Timer in %.3f sec, dT=%s, Tstop=%s", self.Tstart-Tnow, tostring(self.dT), tostring(self.Tstop)))
|
self:T(self.lid..string.format("Starting Timer in %.3f sec, dT=%s, Tstop=%s", self.Tstart-Tnow, tostring(self.dT), tostring(self.Tstop)))
|
||||||
|
|
||||||
@ -210,6 +217,9 @@ function TIMER:Stop(Delay)
|
|||||||
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
|
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
|
||||||
timer.removeFunction(self.tid)
|
timer.removeFunction(self.tid)
|
||||||
|
|
||||||
|
-- Not running any more.
|
||||||
|
self.isrunning=false
|
||||||
|
|
||||||
-- Remove DB entry.
|
-- Remove DB entry.
|
||||||
--_TIMERDB[self.uid]=nil
|
--_TIMERDB[self.uid]=nil
|
||||||
|
|
||||||
@ -229,6 +239,13 @@ function TIMER:SetMaxFunctionCalls(Nmax)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if the timer has been started and was not stopped.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @return #boolean If `true`, the timer is running.
|
||||||
|
function TIMER:IsRunning()
|
||||||
|
return self.isrunning
|
||||||
|
end
|
||||||
|
|
||||||
--- Call timer function.
|
--- Call timer function.
|
||||||
-- @param #TIMER self
|
-- @param #TIMER self
|
||||||
-- @param #number time DCS model time in seconds.
|
-- @param #number time DCS model time in seconds.
|
||||||
|
|||||||
@ -736,7 +736,66 @@ do -- Airbase
|
|||||||
|
|
||||||
end -- Airbase
|
end -- Airbase
|
||||||
|
|
||||||
|
do -- Spot
|
||||||
|
|
||||||
|
--- [DCS Class Spot](https://wiki.hoggitworld.com/view/DCS_Class_Spot)
|
||||||
|
-- Represents a spot from laser or IR-pointer.
|
||||||
|
-- @type Spot
|
||||||
|
-- @field #Spot.Category Category enum that stores spot categories.
|
||||||
|
|
||||||
|
--- Enum that stores spot categories.
|
||||||
|
-- @type Spot.Category
|
||||||
|
-- @field #string INFRA_RED
|
||||||
|
-- @field #string LASER
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a laser ray emanating from the given object to a point in 3d space.
|
||||||
|
-- @function [parent=#Spot] createLaser
|
||||||
|
-- @param DCS#Object Source The source object of the laser.
|
||||||
|
-- @param DCS#Vec3 LocalRef An optional 3D offset for the source.
|
||||||
|
-- @param DCS#Vec3 Vec3 Target coordinate where the ray is pointing at.
|
||||||
|
-- @param #number LaserCode Any 4 digit number between 1111 and 1788.
|
||||||
|
-- @return #Spot
|
||||||
|
|
||||||
|
--- Creates an infrared ray emanating from the given object to a point in 3d space. Can be seen with night vision goggles.
|
||||||
|
-- @function [parent=#Spot] createInfraRed
|
||||||
|
-- @param DCS#Object Source Source position of the IR ray.
|
||||||
|
-- @param DCS#Vec3 LocalRef An optional 3D offset for the source.
|
||||||
|
-- @param DCS#Vec3 Vec3 Target coordinate where the ray is pointing at.
|
||||||
|
-- @return #Spot
|
||||||
|
|
||||||
|
--- Returns a vec3 table of the x, y, and z coordinates for the position of the given object in 3D space. Coordinates are dependent on the position of the maps origin.
|
||||||
|
-- @function [parent=#Spot] getPoint
|
||||||
|
-- @param #Spot self
|
||||||
|
-- @return DCS#Vec3 Point in 3D, where the beam is pointing at.
|
||||||
|
|
||||||
|
--- Sets the destination point from which the source of the spot is drawn toward.
|
||||||
|
-- @function [parent=#Spot] setPoint
|
||||||
|
-- @param #Spot self
|
||||||
|
-- @param DCS#Vec3 Vec3 Point in 3D, where the beam is pointing at.
|
||||||
|
|
||||||
|
--- Returns the number that is used to define the laser code for which laser designation can track.
|
||||||
|
-- @function [parent=#Spot] getCode
|
||||||
|
-- @param #Spot self
|
||||||
|
-- @return #number Code The laser code used.
|
||||||
|
|
||||||
|
--- Sets the number that is used to define the laser code for which laser designation can track.
|
||||||
|
-- @function [parent=#Spot] setCode
|
||||||
|
-- @param #Spot self
|
||||||
|
-- @param #number Code The laser code. Default value is 1688.
|
||||||
|
|
||||||
|
--- Destroys the spot.
|
||||||
|
-- @function [parent=#Spot] destroy
|
||||||
|
-- @param #Spot self
|
||||||
|
|
||||||
|
--- Gets the category of the spot (laser or IR).
|
||||||
|
-- @function [parent=#Spot] getCategory
|
||||||
|
-- @param #Spot self
|
||||||
|
-- @return #string Category.
|
||||||
|
|
||||||
|
Spot = {} --#Spot
|
||||||
|
|
||||||
|
end -- Spot
|
||||||
|
|
||||||
do -- Controller
|
do -- Controller
|
||||||
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||||
|
|||||||
@ -152,7 +152,7 @@ AIRWING = {
|
|||||||
|
|
||||||
--- AIRWING class version.
|
--- AIRWING class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRWING.version="0.5.0"
|
AIRWING.version="0.5.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@ -472,11 +472,19 @@ function AIRWING:FetchPayloadFromStock(UnitType, MissionType, Payloads)
|
|||||||
return nil
|
return nil
|
||||||
elseif #payloads==1 then
|
elseif #payloads==1 then
|
||||||
-- Only one payload anyway.
|
-- Only one payload anyway.
|
||||||
return payloads[1]
|
local payload=payloads[1] --#AIRWING.Payload
|
||||||
|
if not payload.unlimited then
|
||||||
|
payload.navail=payload.navail-1
|
||||||
|
end
|
||||||
|
return payload
|
||||||
else
|
else
|
||||||
-- Sort payloads.
|
-- Sort payloads.
|
||||||
table.sort(payloads, sortpayloads)
|
table.sort(payloads, sortpayloads)
|
||||||
return payloads[1]
|
local payload=payloads[1] --#AIRWING.Payload
|
||||||
|
if not payload.unlimited then
|
||||||
|
payload.navail=payload.navail-1
|
||||||
|
end
|
||||||
|
return payload
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,12 +1,29 @@
|
|||||||
--- **Ops** - Enhanced Ground Group.
|
--- **Ops** - Enhanced Ground Group.
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- ## Main Features:
|
||||||
--
|
--
|
||||||
-- * Dynamically add and remove waypoints.
|
-- * Patrol waypoints *ad infinitum*
|
||||||
|
-- * Easy change of ROE and alarm state, formation and other settings
|
||||||
|
-- * Dynamically add and remove waypoints
|
||||||
|
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||||
|
-- * Convenient checks when the group enters or leaves a zone
|
||||||
|
-- * Detection events for new, known and lost units
|
||||||
|
-- * Simple LASER and IR-pointer setup
|
||||||
|
-- * Compatible with AUFTRAG class
|
||||||
|
-- * Many additional events that the mission designer can hook into
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Armygroup).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ==
|
||||||
|
--
|
||||||
-- @module Ops.ArmyGroup
|
-- @module Ops.ArmyGroup
|
||||||
-- @image OPS_ArmyGroup.png
|
-- @image OPS_ArmyGroup.png
|
||||||
|
|
||||||
@ -15,6 +32,7 @@
|
|||||||
-- @type ARMYGROUP
|
-- @type ARMYGROUP
|
||||||
-- @field #boolean adinfinitum Resume route at first waypoint when final waypoint is reached.
|
-- @field #boolean adinfinitum Resume route at first waypoint when final waypoint is reached.
|
||||||
-- @field #boolean formationPerma Formation that is used permanently and overrules waypoint formations.
|
-- @field #boolean formationPerma Formation that is used permanently and overrules waypoint formations.
|
||||||
|
-- @field #boolean isMobile If true, group is mobile.
|
||||||
-- @extends Ops.OpsGroup#OPSGROUP
|
-- @extends Ops.OpsGroup#OPSGROUP
|
||||||
|
|
||||||
--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B. Sledge
|
--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B. Sledge
|
||||||
@ -36,7 +54,12 @@ ARMYGROUP = {
|
|||||||
--- Army group element.
|
--- Army group element.
|
||||||
-- @type ARMYGROUP.Element
|
-- @type ARMYGROUP.Element
|
||||||
-- @field #string name Name of the element, i.e. the unit.
|
-- @field #string name Name of the element, i.e. the unit.
|
||||||
|
-- @field Wrapper.Unit#UNIT unit The UNIT object.
|
||||||
|
-- @field #string status The element status.
|
||||||
-- @field #string typename Type name.
|
-- @field #string typename Type name.
|
||||||
|
-- @field #number length Length of element in meters.
|
||||||
|
-- @field #number width Width of element in meters.
|
||||||
|
-- @field #number height Height of element in meters.
|
||||||
|
|
||||||
--- Army Group version.
|
--- Army Group version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
@ -46,7 +69,10 @@ ARMYGROUP.version="0.3.0"
|
|||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: A lot.
|
-- TODO: Suppression of fire.
|
||||||
|
-- TODO: Check if group is mobile.
|
||||||
|
-- TODO: F10 menu.
|
||||||
|
-- DONE: Rearm. Specify a point where to go and wait until ammo is full.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
@ -54,12 +80,12 @@ ARMYGROUP.version="0.3.0"
|
|||||||
|
|
||||||
--- Create a new ARMYGROUP class object.
|
--- Create a new ARMYGROUP class object.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #string GroupName Name of the group.
|
-- @param Wrapper.Group#GROUP Group The group object. Can also be given by its group name as `#string`.
|
||||||
-- @return #ARMYGROUP self
|
-- @return #ARMYGROUP self
|
||||||
function ARMYGROUP:New(GroupName)
|
function ARMYGROUP:New(Group)
|
||||||
|
|
||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
local self=BASE:Inherit(self, OPSGROUP:New(GroupName)) -- #ARMYGROUP
|
local self=BASE:Inherit(self, OPSGROUP:New(Group)) -- #ARMYGROUP
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("ARMYGROUP %s | ", self.groupname)
|
self.lid=string.format("ARMYGROUP %s | ", self.groupname)
|
||||||
@ -73,11 +99,15 @@ function ARMYGROUP:New(GroupName)
|
|||||||
-- Add FSM transitions.
|
-- Add FSM transitions.
|
||||||
-- From State --> Event --> To State
|
-- From State --> Event --> To State
|
||||||
self:AddTransition("*", "FullStop", "Holding") -- Hold position.
|
self:AddTransition("*", "FullStop", "Holding") -- Hold position.
|
||||||
self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
|
self:AddTransition("*", "Cruise", "Cruising") -- Cruise along the given route of waypoints.
|
||||||
|
|
||||||
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
||||||
self:AddTransition("OnDetour", "DetourReached", "Cruising") -- Group reached the detour coordinate.
|
self:AddTransition("OnDetour", "DetourReached", "Cruising") -- Group reached the detour coordinate.
|
||||||
|
|
||||||
|
self:AddTransition("*", "Rearm", "Rearm") -- Group is send to a coordinate and waits until ammo is refilled.
|
||||||
|
self:AddTransition("Rearm", "Rearming", "Rearming") -- Group has arrived at the rearming coodinate and is waiting to be fully rearmed.
|
||||||
|
self:AddTransition("Rearming", "Rearmed", "Cruising") -- Group was rearmed.
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
------------------------
|
------------------------
|
||||||
@ -104,6 +134,8 @@ function ARMYGROUP:New(GroupName)
|
|||||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||||
|
|
||||||
|
--self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
||||||
|
|
||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
self:__Status(-1)
|
self:__Status(-1)
|
||||||
|
|
||||||
@ -164,6 +196,8 @@ end
|
|||||||
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
||||||
function ARMYGROUP:AddTaskFireAtPoint(Coordinate, Clock, Radius, Nshots, WeaponType, Prio)
|
function ARMYGROUP:AddTaskFireAtPoint(Coordinate, Clock, Radius, Nshots, WeaponType, Prio)
|
||||||
|
|
||||||
|
Coordinate=self:_CoordinateFromObject(Coordinate)
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
||||||
|
|
||||||
local task=self:AddTask(DCStask, Clock, nil, Prio)
|
local task=self:AddTask(DCStask, Clock, nil, Prio)
|
||||||
@ -182,6 +216,8 @@ end
|
|||||||
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
||||||
function ARMYGROUP:AddTaskWaypointFireAtPoint(Coordinate, Waypoint, Radius, Nshots, WeaponType, Prio)
|
function ARMYGROUP:AddTaskWaypointFireAtPoint(Coordinate, Waypoint, Radius, Nshots, WeaponType, Prio)
|
||||||
|
|
||||||
|
Coordinate=self:_CoordinateFromObject(Coordinate)
|
||||||
|
|
||||||
Waypoint=Waypoint or self:GetWaypointNext()
|
Waypoint=Waypoint or self:GetWaypointNext()
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
||||||
@ -224,7 +260,7 @@ end
|
|||||||
|
|
||||||
--- Check if the group is currently on a detour.
|
--- Check if the group is currently on a detour.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @return #boolean If true, group is on a detour
|
-- @return #boolean If true, group is on a detour.
|
||||||
function ARMYGROUP:IsOnDetour()
|
function ARMYGROUP:IsOnDetour()
|
||||||
return self:Is("OnDetour")
|
return self:Is("OnDetour")
|
||||||
end
|
end
|
||||||
@ -266,6 +302,9 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
|||||||
self:_CheckDetectedUnits()
|
self:_CheckDetectedUnits()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Check ammo status.
|
||||||
|
self:_CheckAmmoStatus()
|
||||||
|
|
||||||
-- Update position etc.
|
-- Update position etc.
|
||||||
self:_UpdatePosition()
|
self:_UpdatePosition()
|
||||||
|
|
||||||
@ -282,11 +321,11 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
|||||||
local alarm=self:GetAlarmstate()
|
local alarm=self:GetAlarmstate()
|
||||||
local speed=UTILS.MpsToKnots(self.velocity)
|
local speed=UTILS.MpsToKnots(self.velocity)
|
||||||
local speedEx=UTILS.MpsToKnots(self:GetExpectedSpeed())
|
local speedEx=UTILS.MpsToKnots(self:GetExpectedSpeed())
|
||||||
local formation=self.option.Formation
|
local formation=self.option.Formation or "unknown"
|
||||||
|
|
||||||
-- Info text.
|
-- Info text.
|
||||||
local text=string.format("%s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
|
local text=string.format("%s [ROE-AS=%d-%d T/M=%d/%d]: Wp=%d/%d-->%d (final %s), Speed=%.1f (%d), Heading=%03d",
|
||||||
fsmstate, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), speed, speedEx, self.heading, roe, alarm, formation, nTaskTot, nMissions)
|
fsmstate, roe, alarm, nTaskTot, nMissions, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), tostring(self.passedfinalwp), speed, speedEx, self.heading)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -340,7 +379,7 @@ function ARMYGROUP:onafterSpawned(From, Event, To)
|
|||||||
-- Update position.
|
-- Update position.
|
||||||
self:_UpdatePosition()
|
self:_UpdatePosition()
|
||||||
|
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
|
|
||||||
-- Set default ROE.
|
-- Set default ROE.
|
||||||
self:SwitchROE(self.option.ROE)
|
self:SwitchROE(self.option.ROE)
|
||||||
@ -358,10 +397,19 @@ function ARMYGROUP:onafterSpawned(From, Event, To)
|
|||||||
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, true)
|
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Formation
|
||||||
|
if not self.option.Formation then
|
||||||
|
self.option.Formation=self.optionDefault.Formation
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update route.
|
-- Update route.
|
||||||
|
if #self.waypoints>1 then
|
||||||
self:Cruise(nil, self.option.Formation or self.optionDefault.Formation)
|
self:Cruise(nil, self.option.Formation or self.optionDefault.Formation)
|
||||||
|
else
|
||||||
|
self:FullStop()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -375,6 +423,10 @@ end
|
|||||||
-- @param #number Formation Formation of the group.
|
-- @param #number Formation Formation of the group.
|
||||||
function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Update route n=%s, Speed=%s, Formation=%s", tostring(n), tostring(Speed), tostring(Formation))
|
||||||
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Update route from this waypoint number onwards.
|
-- Update route from this waypoint number onwards.
|
||||||
n=n or self:GetWaypointIndexNext(self.adinfinitum)
|
n=n or self:GetWaypointIndexNext(self.adinfinitum)
|
||||||
|
|
||||||
@ -451,9 +503,6 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
|||||||
local wp=_wp
|
local wp=_wp
|
||||||
local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or 0, wp.type, wp.speed, wp.alt, wp.action)
|
local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or 0, wp.type, wp.speed, wp.alt, wp.action)
|
||||||
self:T(text)
|
self:T(text)
|
||||||
if false and wp.coordinate then
|
|
||||||
wp.coordinate:MarkToAll(text)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -479,6 +528,43 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "GotoWaypoint" event. Group will got to the given waypoint and execute its route from there.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #number UID The goto waypoint unique ID.
|
||||||
|
-- @param #number Speed (Optional) Speed to waypoint in knots.
|
||||||
|
-- @param #number Formation (Optional) Formation to waypoint.
|
||||||
|
function ARMYGROUP:onafterGotoWaypoint(From, Event, To, UID, Speed, Formation)
|
||||||
|
|
||||||
|
local n=self:GetWaypointIndex(UID)
|
||||||
|
|
||||||
|
--env.info(string.format("FF AG Goto waypoint UID=%s Index=%s, Speed=%s, Formation=%s", tostring(UID), tostring(n), tostring(Speed), tostring(Formation)))
|
||||||
|
|
||||||
|
if n then
|
||||||
|
|
||||||
|
-- TODO: switch to re-enable waypoint tasks.
|
||||||
|
if false then
|
||||||
|
local tasks=self:GetTasksWaypoint(n)
|
||||||
|
|
||||||
|
for _,_task in pairs(tasks) do
|
||||||
|
local task=_task --Ops.OpsGroup#OPSGROUP.Task
|
||||||
|
task.status=OPSGROUP.TaskStatus.SCHEDULED
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Speed to waypoint.
|
||||||
|
Speed=Speed or self:GetSpeedToWaypoint(n)
|
||||||
|
|
||||||
|
-- Update the route.
|
||||||
|
self:UpdateRoute(n, Speed, Formation)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- On after "Detour" event.
|
--- On after "Detour" event.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -508,6 +594,55 @@ function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation,
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "Rearm" event.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to rearm.
|
||||||
|
-- @param #number Formation Formation of the group.
|
||||||
|
function ARMYGROUP:onafterRearm(From, Event, To, Coordinate, Formation)
|
||||||
|
|
||||||
|
-- ID of current waypoint.
|
||||||
|
local uid=self:GetWaypointCurrent().uid
|
||||||
|
|
||||||
|
-- Add waypoint after current.
|
||||||
|
local wp=self:AddWaypoint(Coordinate, nil, uid, Formation, true)
|
||||||
|
|
||||||
|
-- Set if we want to resume route after reaching the detour waypoint.
|
||||||
|
wp.detour=0
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Rearming" event.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function ARMYGROUP:onafterRearming(From, Event, To)
|
||||||
|
|
||||||
|
-- Get current position.
|
||||||
|
local pos=self:GetCoordinate()
|
||||||
|
|
||||||
|
-- Create a new waypoint.
|
||||||
|
local wp=pos:WaypointGround(0)
|
||||||
|
|
||||||
|
-- Create new route consisting of only this position ==> Stop!
|
||||||
|
self:Route({wp})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Rearmed" event.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function ARMYGROUP:onafterRearmed(From, Event, To)
|
||||||
|
|
||||||
|
self:_CheckGroupDone(1)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- On after "DetourReached" event.
|
--- On after "DetourReached" event.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -549,7 +684,7 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed, Formation)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after Start event. Starts the ARMYGROUP FSM and event handlers.
|
--- On after "Stop" event.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
@ -631,7 +766,7 @@ function ARMYGROUP:OnEventDead(EventData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Event function handling the crash of a unit.
|
--- Event function handling when a unit is removed from the game.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
function ARMYGROUP:OnEventRemoveUnit(EventData)
|
function ARMYGROUP:OnEventRemoveUnit(EventData)
|
||||||
@ -654,6 +789,22 @@ function ARMYGROUP:OnEventRemoveUnit(EventData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Event function handling when a unit is hit.
|
||||||
|
-- @param #ARMYGROUP self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function ARMYGROUP:OnEventHit(EventData)
|
||||||
|
|
||||||
|
-- Check that this is the right group.
|
||||||
|
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
|
||||||
|
local unit=EventData.IniUnit
|
||||||
|
local group=EventData.IniGroup
|
||||||
|
local unitname=EventData.IniUnitName
|
||||||
|
|
||||||
|
-- TODO: suppression
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Routing
|
-- Routing
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -668,6 +819,8 @@ end
|
|||||||
-- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
|
-- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
|
||||||
function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation, Updateroute)
|
function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation, Updateroute)
|
||||||
|
|
||||||
|
local coordinate=self:_CoordinateFromObject(Coordinate)
|
||||||
|
|
||||||
-- Set waypoint index.
|
-- Set waypoint index.
|
||||||
local wpnumber=self:GetWaypointIndexAfterID(AfterWaypointWithID)
|
local wpnumber=self:GetWaypointIndexAfterID(AfterWaypointWithID)
|
||||||
|
|
||||||
@ -680,7 +833,7 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
|||||||
Speed=Speed or self:GetSpeedCruise()
|
Speed=Speed or self:GetSpeedCruise()
|
||||||
|
|
||||||
-- Create a Naval waypoint.
|
-- Create a Naval waypoint.
|
||||||
local wp=Coordinate:WaypointGround(UTILS.KnotsToKmph(Speed), Formation)
|
local wp=coordinate:WaypointGround(UTILS.KnotsToKmph(Speed), Formation)
|
||||||
|
|
||||||
-- Create waypoint data table.
|
-- Create waypoint data table.
|
||||||
local waypoint=self:_CreateWaypoint(wp)
|
local waypoint=self:_CreateWaypoint(wp)
|
||||||
@ -689,15 +842,15 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
|||||||
self:_AddWaypoint(waypoint, wpnumber)
|
self:_AddWaypoint(waypoint, wpnumber)
|
||||||
|
|
||||||
-- Get closest point to road.
|
-- Get closest point to road.
|
||||||
waypoint.roadcoord=Coordinate:GetClosestPointToRoad(false)
|
waypoint.roadcoord=coordinate:GetClosestPointToRoad(false)
|
||||||
if waypoint.roadcoord then
|
if waypoint.roadcoord then
|
||||||
waypoint.roaddist=Coordinate:Get2DDistance(waypoint.roadcoord)
|
waypoint.roaddist=coordinate:Get2DDistance(waypoint.roadcoord)
|
||||||
else
|
else
|
||||||
waypoint.roaddist=1000*1000 --1000 km.
|
waypoint.roaddist=1000*1000 --1000 km.
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Adding waypoint UID=%d (index=%d), Speed=%.1f knots, Dist2Road=%d m, Action=%s", waypoint.uid, wpnumber, Speed, waypoint.roaddist, waypoint.action))
|
self:T(self.lid..string.format("Adding waypoint UID=%d (index=%d), Speed=%.1f knots, Dist2Road=%d m, Action=%s", waypoint.uid, wpnumber, Speed, waypoint.roaddist, waypoint.action))
|
||||||
|
|
||||||
-- Update route.
|
-- Update route.
|
||||||
if Updateroute==nil or Updateroute==true then
|
if Updateroute==nil or Updateroute==true then
|
||||||
@ -726,8 +879,8 @@ function ARMYGROUP:_InitGroup()
|
|||||||
self.isNaval=false
|
self.isNaval=false
|
||||||
self.isGround=true
|
self.isGround=true
|
||||||
|
|
||||||
-- Ships are always AI.
|
-- Ground are always AI.
|
||||||
self.ai=true
|
self.isAI=true
|
||||||
|
|
||||||
-- Is (template) group late activated.
|
-- Is (template) group late activated.
|
||||||
self.isLateActivated=self.template.lateActivation
|
self.isLateActivated=self.template.lateActivation
|
||||||
@ -765,30 +918,44 @@ function ARMYGROUP:_InitGroup()
|
|||||||
for _,_unit in pairs(units) do
|
for _,_unit in pairs(units) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- TODO: this is wrong when grouping is used!
|
||||||
|
local unittemplate=unit:GetTemplate()
|
||||||
|
|
||||||
local element={} --#ARMYGROUP.Element
|
local element={} --#ARMYGROUP.Element
|
||||||
element.name=unit:GetName()
|
element.name=unit:GetName()
|
||||||
element.typename=unit:GetTypeName()
|
|
||||||
element.status=OPSGROUP.ElementStatus.INUTERO
|
|
||||||
element.unit=unit
|
element.unit=unit
|
||||||
|
element.status=OPSGROUP.ElementStatus.INUTERO
|
||||||
|
element.typename=unit:GetTypeName()
|
||||||
|
element.skill=unittemplate.skill or "Unknown"
|
||||||
|
element.ai=true
|
||||||
|
element.category=element.unit:GetUnitCategory()
|
||||||
|
element.categoryname=element.unit:GetCategoryName()
|
||||||
|
element.size, element.length, element.height, element.width=unit:GetObjectSize()
|
||||||
|
element.ammo0=self:GetAmmoUnit(unit, false)
|
||||||
|
|
||||||
|
-- Debug text.
|
||||||
|
if self.verbose>=2 then
|
||||||
|
local text=string.format("Adding element %s: status=%s, skill=%s, category=%s (%d), size: %.1f (L=%.1f H=%.1f W=%.1f)",
|
||||||
|
element.name, element.status, element.skill, element.categoryname, element.category, element.size, element.length, element.height, element.width)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add element to table.
|
||||||
table.insert(self.elements, element)
|
table.insert(self.elements, element)
|
||||||
|
|
||||||
self:GetAmmoUnit(unit, false)
|
-- Get Descriptors.
|
||||||
|
self.descriptors=self.descriptors or unit:GetDesc()
|
||||||
|
|
||||||
|
-- Set type name.
|
||||||
|
self.actype=self.actype or unit:GetTypeName()
|
||||||
|
|
||||||
if unit:IsAlive() then
|
if unit:IsAlive() then
|
||||||
|
-- Trigger spawned event.
|
||||||
self:ElementSpawned(element)
|
self:ElementSpawned(element)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get first unit. This is used to extract other parameters.
|
|
||||||
local unit=self.group:GetUnit(1)
|
|
||||||
|
|
||||||
if unit then
|
|
||||||
|
|
||||||
self.descriptors=unit:GetDesc()
|
|
||||||
|
|
||||||
self.actype=unit:GetTypeName()
|
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
||||||
@ -808,8 +975,6 @@ function ARMYGROUP:_InitGroup()
|
|||||||
-- Init done.
|
-- Init done.
|
||||||
self.groupinitialized=true
|
self.groupinitialized=true
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,26 @@
|
|||||||
--- **Ops** - Auftrag (mission) for Ops.
|
--- **Ops** - Auftrag (mission) for Ops.
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- ## Main Features:
|
||||||
--
|
--
|
||||||
-- * Simplifies defining and executing DCS tasks.
|
-- * Simplifies defining and executing DCS tasks
|
||||||
-- * Additional useful events.
|
-- * Additional useful events
|
||||||
-- * Set mission start/stop times.
|
-- * Set mission start/stop times
|
||||||
-- * Set mission priority and urgency (can cancel running missions).
|
-- * Set mission priority and urgency (can cancel running missions)
|
||||||
-- * Specific mission options for ROE, ROT, formation, etc.
|
-- * Specific mission options for ROE, ROT, formation, etc.
|
||||||
-- * Interface to FLIGHTGROUP, AIRWING and WINGCOMMANDER classes.
|
-- * Compatible with FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, WINGCOMMANDER and CHIEF classes
|
||||||
-- * FSM events when a mission is done, successful or failed.
|
-- * FSM events when a mission is done, successful or failed
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Auftrag).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
-- @module Ops.Auftrag
|
-- @module Ops.Auftrag
|
||||||
-- @image OPS_Auftrag.png
|
-- @image OPS_Auftrag.png
|
||||||
|
|
||||||
@ -1682,6 +1690,13 @@ function AUFTRAG:GetPriority()
|
|||||||
return self.prio
|
return self.prio
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get casualties, i.e. number of units that died during this mission.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @return #number Number of dead units.
|
||||||
|
function AUFTRAG:GetCasualties()
|
||||||
|
return self.Ncasualties or 0
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if mission is "urgent".
|
--- Check if mission is "urgent".
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @return #boolean If `true`, mission is "urgent".
|
-- @return #boolean If `true`, mission is "urgent".
|
||||||
@ -1942,7 +1957,7 @@ function AUFTRAG:IsReadyToCancel()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Evaluate failure condition. One is enough.
|
||||||
local failure=self:EvalConditionsAny(self.conditionFailure)
|
local failure=self:EvalConditionsAny(self.conditionFailure)
|
||||||
|
|
||||||
if failure then
|
if failure then
|
||||||
@ -1950,6 +1965,7 @@ function AUFTRAG:IsReadyToCancel()
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Evaluate success consitions. One is enough.
|
||||||
local success=self:EvalConditionsAny(self.conditionSuccess)
|
local success=self:EvalConditionsAny(self.conditionSuccess)
|
||||||
|
|
||||||
if success then
|
if success then
|
||||||
|
|||||||
@ -1,16 +1,30 @@
|
|||||||
--- **Ops** - Enhanced Airborne Group.
|
--- **Ops** - Enhanced Airborne Group.
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- ## Main Features:
|
||||||
--
|
--
|
||||||
-- * Monitor flight status of elements and/or the entire group.
|
-- * Monitor flight status of elements and/or the entire group
|
||||||
-- * Monitor fuel and ammo status.
|
-- * Monitor fuel and ammo status
|
||||||
-- * Conveniently set radio freqencies, TACAN, ROE etc.
|
-- * Conveniently set radio freqencies, TACAN, ROE etc
|
||||||
-- * Sophisticated task queueing system.
|
-- * Order helos to land at specifc coordinates
|
||||||
-- * Many additional events for each element and the whole group.
|
-- * Dynamically add and remove waypoints
|
||||||
|
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||||
|
-- * Convenient checks when the group enters or leaves a zone
|
||||||
|
-- * Detection events for new, known and lost units
|
||||||
|
-- * Simple LASER and IR-pointer setup
|
||||||
|
-- * Compatible with AUFTRAG class
|
||||||
|
-- * Many additional events that the mission designer can hook into
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Flightgroup).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
-- @module Ops.FlightGroup
|
-- @module Ops.FlightGroup
|
||||||
-- @image OPS_FlightGroup.png
|
-- @image OPS_FlightGroup.png
|
||||||
|
|
||||||
@ -50,7 +64,7 @@
|
|||||||
--
|
--
|
||||||
-- @extends Ops.OpsGroup#OPSGROUP
|
-- @extends Ops.OpsGroup#OPSGROUP
|
||||||
|
|
||||||
--- *To invent an airplane is nothing. To build one is something. To fly is everything.* -- Otto Lilienthal
|
--- *To invent an airplane is nothing; to build one is something; to fly is everything.* -- Otto Lilienthal
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -186,6 +200,7 @@ FLIGHTGROUP.version="0.6.0"
|
|||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: VTOL aircraft.
|
||||||
-- TODO: Use new UnitLost event instead of crash/dead.
|
-- TODO: Use new UnitLost event instead of crash/dead.
|
||||||
-- TODO: Options EPLRS, Afterburner restrict etc.
|
-- TODO: Options EPLRS, Afterburner restrict etc.
|
||||||
-- DONE: Add TACAN beacon.
|
-- DONE: Add TACAN beacon.
|
||||||
@ -210,7 +225,7 @@ FLIGHTGROUP.version="0.6.0"
|
|||||||
|
|
||||||
--- Create a new FLIGHTGROUP object and start the FSM.
|
--- Create a new FLIGHTGROUP object and start the FSM.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
-- @param Wrapper.Group#GROUP group The group object. Can also be given as #string with the name of the group.
|
-- @param Wrapper.Group#GROUP Group The group object. Can also be given by its group name as `#string`.
|
||||||
-- @return #FLIGHTGROUP self
|
-- @return #FLIGHTGROUP self
|
||||||
function FLIGHTGROUP:New(group)
|
function FLIGHTGROUP:New(group)
|
||||||
|
|
||||||
@ -396,7 +411,7 @@ function FLIGHTGROUP:SetFlightControl(flightcontrol)
|
|||||||
table.insert(flightcontrol.flights, self)
|
table.insert(flightcontrol.flights, self)
|
||||||
|
|
||||||
-- Update flight's F10 menu.
|
-- Update flight's F10 menu.
|
||||||
if self.ai==false then
|
if self.isAI==false then
|
||||||
self:_UpdateMenu(0.5)
|
self:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -705,7 +720,7 @@ end
|
|||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
---- Update status.
|
---- Update status.
|
||||||
-- @param #FLIHGTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
||||||
|
|
||||||
-- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase.
|
-- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase.
|
||||||
@ -1040,7 +1055,7 @@ function FLIGHTGROUP:OnEventEngineStartup(EventData)
|
|||||||
-- TODO: could be that this element is part of a human flight group.
|
-- TODO: could be that this element is part of a human flight group.
|
||||||
-- Problem: when player starts hot, the AI does too and starts to taxi immidiately :(
|
-- Problem: when player starts hot, the AI does too and starts to taxi immidiately :(
|
||||||
-- when player starts cold, ?
|
-- when player starts cold, ?
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
self:ElementEngineOn(element)
|
self:ElementEngineOn(element)
|
||||||
else
|
else
|
||||||
if element.ai then
|
if element.ai then
|
||||||
@ -1447,7 +1462,7 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
|||||||
-- Update position.
|
-- Update position.
|
||||||
self:_UpdatePosition()
|
self:_UpdatePosition()
|
||||||
|
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
|
|
||||||
-- Set ROE.
|
-- Set ROE.
|
||||||
self:SwitchROE(self.option.ROE)
|
self:SwitchROE(self.option.ROE)
|
||||||
@ -1522,7 +1537,7 @@ function FLIGHTGROUP:onafterParking(From, Event, To)
|
|||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.PARKING)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.PARKING)
|
||||||
|
|
||||||
-- Update player menu.
|
-- Update player menu.
|
||||||
if not self.ai then
|
if not self.isAI then
|
||||||
self:_UpdateMenu(0.5)
|
self:_UpdateMenu(0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1547,7 +1562,7 @@ function FLIGHTGROUP:onafterTaxiing(From, Event, To)
|
|||||||
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
if self.flightcontrol and airbase and self.flightcontrol.airbasename==airbase:GetName() then
|
||||||
|
|
||||||
-- Add AI flight to takeoff queue.
|
-- Add AI flight to takeoff queue.
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
-- AI flights go directly to TAKEOFF as we don't know when they finished taxiing.
|
-- AI flights go directly to TAKEOFF as we don't know when they finished taxiing.
|
||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAKEOFF)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.TAKEOFF)
|
||||||
else
|
else
|
||||||
@ -1586,7 +1601,7 @@ end
|
|||||||
function FLIGHTGROUP:onafterAirborne(From, Event, To)
|
function FLIGHTGROUP:onafterAirborne(From, Event, To)
|
||||||
self:T(self.lid..string.format("Flight airborne"))
|
self:T(self.lid..string.format("Flight airborne"))
|
||||||
|
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
self:_CheckGroupDone(1)
|
self:_CheckGroupDone(1)
|
||||||
else
|
else
|
||||||
self:_UpdateMenu()
|
self:_UpdateMenu()
|
||||||
@ -1737,7 +1752,7 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n)
|
|||||||
--end
|
--end
|
||||||
|
|
||||||
-- Only AI flights.
|
-- Only AI flights.
|
||||||
if not self.ai then
|
if not self.isAI then
|
||||||
allowed=false
|
allowed=false
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1840,7 +1855,7 @@ end
|
|||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
function FLIGHTGROUP:_CheckGroupDone(delay)
|
function FLIGHTGROUP:_CheckGroupDone(delay)
|
||||||
|
|
||||||
if self:IsAlive() and self.ai then
|
if self:IsAlive() and self.isAI then
|
||||||
|
|
||||||
if delay and delay>0 then
|
if delay and delay>0 then
|
||||||
-- Delayed call.
|
-- Delayed call.
|
||||||
@ -2099,7 +2114,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
|
|
||||||
local routeto=false
|
local routeto=false
|
||||||
if fc or world.event.S_EVENT_KILL then
|
if fc or world.event.S_EVENT_KILL then
|
||||||
@ -2279,7 +2294,7 @@ function FLIGHTGROUP:onafterHolding(From, Event, To)
|
|||||||
-- Set flight status to holding
|
-- Set flight status to holding
|
||||||
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.HOLDING)
|
self.flightcontrol:SetFlightStatus(self, FLIGHTCONTROL.FlightStatus.HOLDING)
|
||||||
|
|
||||||
if not self.ai then
|
if not self.isAI then
|
||||||
self:_UpdateMenu()
|
self:_UpdateMenu()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2626,10 +2641,10 @@ function FLIGHTGROUP:_InitGroup()
|
|||||||
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
||||||
|
|
||||||
-- Is this purely AI?
|
-- Is this purely AI?
|
||||||
self.ai=not self:_IsHuman(group)
|
self.isAI=not self:_IsHuman(group)
|
||||||
|
|
||||||
-- Create Menu.
|
-- Create Menu.
|
||||||
if not self.ai then
|
if not self.isAI then
|
||||||
self.menu=self.menu or {}
|
self.menu=self.menu or {}
|
||||||
self.menu.atc=self.menu.atc or {}
|
self.menu.atc=self.menu.atc or {}
|
||||||
self.menu.atc.root=self.menu.atc.root or MENU_GROUP:New(self.group, "ATC")
|
self.menu.atc.root=self.menu.atc.root or MENU_GROUP:New(self.group, "ATC")
|
||||||
@ -2665,7 +2680,7 @@ function FLIGHTGROUP:_InitGroup()
|
|||||||
text=text..string.format("Ceiling = %.1f feet\n", UTILS.MetersToFeet(self.ceiling))
|
text=text..string.format("Ceiling = %.1f feet\n", UTILS.MetersToFeet(self.ceiling))
|
||||||
text=text..string.format("Tanker type = %s\n", tostring(self.tankertype))
|
text=text..string.format("Tanker type = %s\n", tostring(self.tankertype))
|
||||||
text=text..string.format("Refuel type = %s\n", tostring(self.refueltype))
|
text=text..string.format("Refuel type = %s\n", tostring(self.refueltype))
|
||||||
text=text..string.format("AI = %s\n", tostring(self.ai))
|
text=text..string.format("AI = %s\n", tostring(self.isAI))
|
||||||
text=text..string.format("Helicopter = %s\n", tostring(self.group:IsHelicopter()))
|
text=text..string.format("Helicopter = %s\n", tostring(self.group:IsHelicopter()))
|
||||||
text=text..string.format("Elements = %d\n", #self.elements)
|
text=text..string.format("Elements = %d\n", #self.elements)
|
||||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||||
@ -2729,6 +2744,7 @@ function FLIGHTGROUP:AddElementByName(unitname)
|
|||||||
element.ai=true
|
element.ai=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Debug text.
|
||||||
local text=string.format("Adding element %s: status=%s, skill=%s, modex=%s, fuelmass=%.1f (%d), category=%d, categoryname=%s, callsign=%s, ai=%s",
|
local text=string.format("Adding element %s: status=%s, skill=%s, modex=%s, fuelmass=%.1f (%d), category=%d, categoryname=%s, callsign=%s, ai=%s",
|
||||||
element.name, element.status, element.skill, element.modex, element.fuelmass, element.fuelrel*100, element.category, element.categoryname, element.callsign, tostring(element.ai))
|
element.name, element.status, element.skill, element.modex, element.fuelmass, element.fuelrel*100, element.category, element.categoryname, element.callsign, tostring(element.ai))
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|||||||
@ -1,15 +1,33 @@
|
|||||||
--- **Ops** - Enhanced Naval Group.
|
--- **Ops** - Enhanced Naval Group.
|
||||||
--
|
--
|
||||||
-- **Main Features:**
|
-- ## Main Features:
|
||||||
--
|
--
|
||||||
-- * Dynamically add and remove waypoints.
|
-- * Let the group steam into the wind
|
||||||
-- * Let the group steam into the wind.
|
-- * Command a full stop
|
||||||
-- * Command a full stop.
|
-- * Patrol waypoints *ad infinitum*
|
||||||
-- * Let a submarine dive and surface.
|
-- * Collision warning, if group is heading towards a land mass
|
||||||
|
-- * Automatic pathfinding, e.g. around islands
|
||||||
|
-- * Let a submarine dive and surface
|
||||||
|
-- * Manage TACAN and ICLS beacons
|
||||||
|
-- * Dynamically add and remove waypoints
|
||||||
|
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||||
|
-- * Convenient checks when the group enters or leaves a zone
|
||||||
|
-- * Detection events for new, known and lost units
|
||||||
|
-- * Simple LASER and IR-pointer setup
|
||||||
|
-- * Compatible with AUFTRAG class
|
||||||
|
-- * Many additional events that the mission designer can hook into
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Navygroup)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
-- @module Ops.NavyGroup
|
-- @module Ops.NavyGroup
|
||||||
-- @image OPS_NavyGroup.png
|
-- @image OPS_NavyGroup.png
|
||||||
|
|
||||||
@ -19,6 +37,7 @@
|
|||||||
-- @field #boolean turning If true, group is currently turning.
|
-- @field #boolean turning If true, group is currently turning.
|
||||||
-- @field #NAVYGROUP.IntoWind intowind Into wind info.
|
-- @field #NAVYGROUP.IntoWind intowind Into wind info.
|
||||||
-- @field #table Qintowind Queue of "into wind" turns.
|
-- @field #table Qintowind Queue of "into wind" turns.
|
||||||
|
-- @field #number intowindcounter Counter of into wind IDs.
|
||||||
-- @field #number depth Ordered depth in meters.
|
-- @field #number depth Ordered depth in meters.
|
||||||
-- @field #boolean collisionwarning If true, collition warning.
|
-- @field #boolean collisionwarning If true, collition warning.
|
||||||
-- @field #boolean pathfindingOn If true, enable pathfining.
|
-- @field #boolean pathfindingOn If true, enable pathfining.
|
||||||
@ -74,7 +93,9 @@ NAVYGROUP.version="0.5.0"
|
|||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Collision warning.
|
-- TODO: Extend, shorten turn into wind windows
|
||||||
|
-- TODO: Skipper menu.
|
||||||
|
-- DONE: Collision warning.
|
||||||
-- DONE: Detour, add temporary waypoint and resume route.
|
-- DONE: Detour, add temporary waypoint and resume route.
|
||||||
-- DONE: Stop and resume route.
|
-- DONE: Stop and resume route.
|
||||||
-- DONE: Add waypoints.
|
-- DONE: Add waypoints.
|
||||||
@ -109,7 +130,9 @@ function NAVYGROUP:New(GroupName)
|
|||||||
self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
|
self:AddTransition("*", "Cruise", "Cruising") -- Hold position.
|
||||||
|
|
||||||
self:AddTransition("*", "TurnIntoWind", "IntoWind") -- Command the group to turn into the wind.
|
self:AddTransition("*", "TurnIntoWind", "IntoWind") -- Command the group to turn into the wind.
|
||||||
self:AddTransition("*", "TurnIntoWindOver", "Cruising") -- Turn into wind is over.
|
self:AddTransition("IntoWind", "TurnedIntoWind", "IntoWind") -- Group turned into wind.
|
||||||
|
self:AddTransition("IntoWind", "TurnIntoWindStop", "IntoWind") -- Stop a turn into wind.
|
||||||
|
self:AddTransition("IntoWind", "TurnIntoWindOver", "Cruising") -- Turn into wind is over.
|
||||||
|
|
||||||
self:AddTransition("*", "TurningStarted", "*") -- Group started turning.
|
self:AddTransition("*", "TurningStarted", "*") -- Group started turning.
|
||||||
self:AddTransition("*", "TurningStopped", "*") -- Group stopped turning.
|
self:AddTransition("*", "TurningStopped", "*") -- Group stopped turning.
|
||||||
@ -144,14 +167,6 @@ function NAVYGROUP:New(GroupName)
|
|||||||
-- Initialize the group.
|
-- Initialize the group.
|
||||||
self:_InitGroup()
|
self:_InitGroup()
|
||||||
|
|
||||||
-- Debug trace.
|
|
||||||
if false then
|
|
||||||
self.Debug=true
|
|
||||||
BASE:TraceOnOff(true)
|
|
||||||
BASE:TraceClass(self.ClassName)
|
|
||||||
BASE:TraceLevel(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Handle events:
|
-- Handle events:
|
||||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||||
@ -272,7 +287,7 @@ function NAVYGROUP:AddTaskAttackGroup(TargetGroup, WeaponExpend, WeaponType, Clo
|
|||||||
return task
|
return task
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add aircraft recovery time window and recovery case.
|
--- Create a turn into wind window. Note that this is not executed as it not added to the queue.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #string starttime Start time, e.g. "8:00" for eight o'clock. Default now.
|
-- @param #string starttime Start time, e.g. "8:00" for eight o'clock. Default now.
|
||||||
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
||||||
@ -280,7 +295,7 @@ end
|
|||||||
-- @param #boolean uturn If true (or nil), carrier wil perform a U-turn and go back to where it came from before resuming its route to the next waypoint. If false, it will go directly to the next waypoint.
|
-- @param #boolean uturn If true (or nil), carrier wil perform a U-turn and go back to where it came from before resuming its route to the next waypoint. If false, it will go directly to the next waypoint.
|
||||||
-- @param #number offset Offset angle in degrees, e.g. to account for an angled runway. Default 0 deg.
|
-- @param #number offset Offset angle in degrees, e.g. to account for an angled runway. Default 0 deg.
|
||||||
-- @return #NAVYGROUP.IntoWind Recovery window.
|
-- @return #NAVYGROUP.IntoWind Recovery window.
|
||||||
function NAVYGROUP:CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
function NAVYGROUP:_CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
||||||
|
|
||||||
-- Absolute mission time in seconds.
|
-- Absolute mission time in seconds.
|
||||||
local Tnow=timer.getAbsTime()
|
local Tnow=timer.getAbsTime()
|
||||||
@ -335,17 +350,17 @@ function NAVYGROUP:CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
|||||||
return recovery
|
return recovery
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add aircraft recovery time window and recovery case.
|
--- Add a time window, where the groups steams into the wind.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #string starttime Start time, e.g. "8:00" for eight o'clock. Default now.
|
-- @param #string starttime Start time, e.g. "8:00" for eight o'clock. Default now.
|
||||||
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
||||||
-- @param #number speed Speed in knots during turn into wind leg.
|
-- @param #number speed Speed in knots during turn into wind leg.
|
||||||
-- @param #boolean uturn If true (or nil), carrier wil perform a U-turn and go back to where it came from before resuming its route to the next waypoint. If false, it will go directly to the next waypoint.
|
-- @param #boolean uturn If `true` (or `nil`), carrier wil perform a U-turn and go back to where it came from before resuming its route to the next waypoint. If false, it will go directly to the next waypoint.
|
||||||
-- @param #number offset Offset angle in degrees, e.g. to account for an angled runway. Default 0 deg.
|
-- @param #number offset Offset angle in degrees, e.g. to account for an angled runway. Default 0 deg.
|
||||||
-- @return #NAVYGROUP.IntoWind Recovery window.
|
-- @return #NAVYGROUP.IntoWind Turn into window data table.
|
||||||
function NAVYGROUP:AddTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
function NAVYGROUP:AddTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
||||||
|
|
||||||
local recovery=self:CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
local recovery=self:_CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
||||||
|
|
||||||
--TODO: check if window is overlapping with an other and if extend the window.
|
--TODO: check if window is overlapping with an other and if extend the window.
|
||||||
|
|
||||||
@ -355,6 +370,31 @@ function NAVYGROUP:AddTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
|||||||
return recovery
|
return recovery
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove steam into wind window from queue. If the window is currently active, it is stopped first.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #NAVYGROUP.IntoWind IntoWindData Turn into window data table.
|
||||||
|
-- @return #NAVYGROUP self
|
||||||
|
function NAVYGROUP:RemoveTurnIntoWind(IntoWindData)
|
||||||
|
|
||||||
|
-- Check if this is a window currently open.
|
||||||
|
if self.intowind and self.intowind.Id==IntoWindData.Id then
|
||||||
|
--env.info("FF stop in remove")
|
||||||
|
self:TurnIntoWindStop()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,_tiw in pairs(self.Qintowind) do
|
||||||
|
local tiw=_tiw --#NAVYGROUP.IntoWind
|
||||||
|
if tiw.Id==IntoWindData.Id then
|
||||||
|
--env.info("FF removing window "..tiw.Id)
|
||||||
|
table.remove(self.Qintowind, i)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if the group is currently holding its positon.
|
--- Check if the group is currently holding its positon.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
@ -527,6 +567,37 @@ function NAVYGROUP:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Recovery Windows
|
||||||
|
---
|
||||||
|
|
||||||
|
if self.verbose>=2 then
|
||||||
|
|
||||||
|
-- Debug output:
|
||||||
|
local text=string.format(self.lid.."Turn into wind time windows:")
|
||||||
|
|
||||||
|
-- Handle case with no recoveries.
|
||||||
|
if #self.Qintowind==0 then
|
||||||
|
text=text.." none!"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Loop over all slots.
|
||||||
|
for i,_recovery in pairs(self.Qintowind) do
|
||||||
|
local recovery=_recovery --#NAVYGROUP.IntoWind
|
||||||
|
|
||||||
|
-- Get start/stop clock strings.
|
||||||
|
local Cstart=UTILS.SecondsToClock(recovery.Tstart)
|
||||||
|
local Cstop=UTILS.SecondsToClock(recovery.Tstop)
|
||||||
|
|
||||||
|
-- Debug text.
|
||||||
|
text=text..string.format("\n[%d] ID=%d Start=%s Stop=%s Open=%s Over=%s", i, recovery.Id, Cstart, Cstop, tostring(recovery.Open), tostring(recovery.Over))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Tasks & Missions
|
-- Tasks & Missions
|
||||||
@ -568,7 +639,7 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
|
|||||||
-- Update position.
|
-- Update position.
|
||||||
self:_UpdatePosition()
|
self:_UpdatePosition()
|
||||||
|
|
||||||
if self.ai then
|
if self.isAI then
|
||||||
|
|
||||||
-- Set default ROE.
|
-- Set default ROE.
|
||||||
self:SwitchROE(self.option.ROE)
|
self:SwitchROE(self.option.ROE)
|
||||||
@ -592,7 +663,11 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Update route.
|
-- Update route.
|
||||||
|
if #self.waypoints>1 then
|
||||||
self:Cruise()
|
self:Cruise()
|
||||||
|
else
|
||||||
|
self:FullStop()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -757,19 +832,44 @@ function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On before "TurnIntoWindStop" event.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function NAVYGROUP:onbeforeTurnIntoWindStop(From, Event, To)
|
||||||
|
|
||||||
|
if self.intowind then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "TurnIntoWindStop" event.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function NAVYGROUP:onafterTurnIntoWindStop(From, Event, To)
|
||||||
|
self:TurnIntoWindOver(self.intowind)
|
||||||
|
end
|
||||||
|
|
||||||
--- On after "TurnIntoWindOver" event.
|
--- On after "TurnIntoWindOver" event.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param #number Duration Duration in seconds.
|
-- @param #NAVYGROUP.IntoWind IntoWindData Data table.
|
||||||
-- @param #number Speed Speed in knots.
|
function NAVYGROUP:onafterTurnIntoWindOver(From, Event, To, IntoWindData)
|
||||||
-- @param #boolean Uturn Return to the place we came from.
|
|
||||||
function NAVYGROUP:onafterTurnIntoWindOver(From, Event, To)
|
if IntoWindData and self.intowind and IntoWindData.Id==self.intowind.Id then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T2(self.lid.."Turn Into Wind Over!")
|
self:T2(self.lid.."Turn Into Wind Over!")
|
||||||
|
|
||||||
|
-- Window over and not open anymore.
|
||||||
self.intowind.Over=true
|
self.intowind.Over=true
|
||||||
self.intowind.Open=false
|
self.intowind.Open=false
|
||||||
|
|
||||||
@ -777,17 +877,39 @@ function NAVYGROUP:onafterTurnIntoWindOver(From, Event, To)
|
|||||||
self:RemoveWaypointByID(self.intowind.waypoint.uid)
|
self:RemoveWaypointByID(self.intowind.waypoint.uid)
|
||||||
|
|
||||||
if self.intowind.Uturn then
|
if self.intowind.Uturn then
|
||||||
self:T(self.lid.."Turn Into Wind Over ==> Uturn!")
|
|
||||||
|
---
|
||||||
|
-- U-turn ==> Go to coordinate where we left the route.
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Detour to where we left the route.
|
||||||
|
self:T(self.lid.."FF Turn Into Wind Over ==> Uturn!")
|
||||||
self:Detour(self.intowind.Coordinate, self:GetSpeedCruise(), 0, true)
|
self:Detour(self.intowind.Coordinate, self:GetSpeedCruise(), 0, true)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:T(self.lid.."FF Turn Into Wind Over ==> Next WP!")
|
|
||||||
|
---
|
||||||
|
-- Go directly to next waypoint.
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Next waypoint index and speed.
|
||||||
local indx=self:GetWaypointIndexNext()
|
local indx=self:GetWaypointIndexNext()
|
||||||
local speed=self:GetWaypointSpeed(indx)
|
local speed=self:GetWaypointSpeed(indx)
|
||||||
|
|
||||||
|
-- Update route.
|
||||||
|
self:T(self.lid..string.format("FF Turn Into Wind Over ==> Next WP Index=%d at %.1f knots via update route!", indx, speed))
|
||||||
self:__UpdateRoute(-1, indx, speed)
|
self:__UpdateRoute(-1, indx, speed)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set current window to nil.
|
||||||
self.intowind=nil
|
self.intowind=nil
|
||||||
|
|
||||||
|
-- Remove window from queue.
|
||||||
|
self:RemoveTurnIntoWind(IntoWindData)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "FullStop" event.
|
--- On after "FullStop" event.
|
||||||
@ -874,6 +996,11 @@ end
|
|||||||
function NAVYGROUP:onafterTurningStopped(From, Event, To)
|
function NAVYGROUP:onafterTurningStopped(From, Event, To)
|
||||||
self.turning=false
|
self.turning=false
|
||||||
self.collisionwarning=false
|
self.collisionwarning=false
|
||||||
|
|
||||||
|
if self:IsSteamingIntoWind() then
|
||||||
|
self:TurnedIntoWind()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "CollisionWarning" event.
|
--- On after "CollisionWarning" event.
|
||||||
@ -1009,10 +1136,10 @@ function NAVYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Depth, Up
|
|||||||
-- Check if a coordinate was given or at least a positionable.
|
-- Check if a coordinate was given or at least a positionable.
|
||||||
if not Coordinate:IsInstanceOf("COORDINATE") then
|
if not Coordinate:IsInstanceOf("COORDINATE") then
|
||||||
if Coordinate:IsInstanceOf("POSITIONABLE") or Coordinate:IsInstanceOf("ZONE_BASE") then
|
if Coordinate:IsInstanceOf("POSITIONABLE") or Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||||
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE. Trying to get coordinate")
|
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
|
||||||
Coordinate=Coordinate:GetCoordinate()
|
Coordinate=Coordinate:GetCoordinate()
|
||||||
else
|
else
|
||||||
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE!")
|
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1071,7 +1198,7 @@ function NAVYGROUP:_InitGroup()
|
|||||||
--self.isSubmarine=self.group:IsSubmarine()
|
--self.isSubmarine=self.group:IsSubmarine()
|
||||||
|
|
||||||
-- Ships are always AI.
|
-- Ships are always AI.
|
||||||
self.ai=true
|
self.isAI=true
|
||||||
|
|
||||||
-- Is (template) group late activated.
|
-- Is (template) group late activated.
|
||||||
self.isLateActivated=self.template.lateActivation
|
self.isLateActivated=self.template.lateActivation
|
||||||
@ -1111,29 +1238,44 @@ function NAVYGROUP:_InitGroup()
|
|||||||
for _,_unit in pairs(units) do
|
for _,_unit in pairs(units) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Get unit template.
|
||||||
|
local unittemplate=unit:GetTemplate()
|
||||||
|
|
||||||
local element={} --#NAVYGROUP.Element
|
local element={} --#NAVYGROUP.Element
|
||||||
element.name=unit:GetName()
|
element.name=unit:GetName()
|
||||||
element.typename=unit:GetTypeName()
|
|
||||||
element.status=OPSGROUP.ElementStatus.INUTERO
|
|
||||||
element.unit=unit
|
element.unit=unit
|
||||||
|
element.status=OPSGROUP.ElementStatus.INUTERO
|
||||||
|
element.typename=unit:GetTypeName()
|
||||||
|
element.skill=unittemplate.skill or "Unknown"
|
||||||
|
element.ai=true
|
||||||
|
element.category=element.unit:GetUnitCategory()
|
||||||
|
element.categoryname=element.unit:GetCategoryName()
|
||||||
|
element.size, element.length, element.height, element.width=unit:GetObjectSize()
|
||||||
|
element.ammo0=self:GetAmmoUnit(unit, false)
|
||||||
|
|
||||||
|
-- Debug text.
|
||||||
|
if self.verbose>=2 then
|
||||||
|
local text=string.format("Adding element %s: status=%s, skill=%s, category=%s (%d), size: %.1f (L=%.1f H=%.1f W=%.1f)",
|
||||||
|
element.name, element.status, element.skill, element.categoryname, element.category, element.size, element.length, element.height, element.width)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add element to table.
|
||||||
table.insert(self.elements, element)
|
table.insert(self.elements, element)
|
||||||
|
|
||||||
self:GetAmmoUnit(unit, false)
|
-- Get Descriptors.
|
||||||
|
self.descriptors=self.descriptors or unit:GetDesc()
|
||||||
|
|
||||||
|
-- Set type name.
|
||||||
|
self.actype=self.actype or unit:GetTypeName()
|
||||||
|
|
||||||
if unit:IsAlive() then
|
if unit:IsAlive() then
|
||||||
|
-- Trigger spawned event.
|
||||||
self:ElementSpawned(element)
|
self:ElementSpawned(element)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get first unit. This is used to extract other parameters.
|
|
||||||
local unit=self.group:GetUnit(1)
|
|
||||||
|
|
||||||
if unit then
|
|
||||||
|
|
||||||
self.descriptors=unit:GetDesc()
|
|
||||||
|
|
||||||
self.actype=unit:GetTypeName()
|
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
@ -1154,8 +1296,6 @@ function NAVYGROUP:_InitGroup()
|
|||||||
-- Init done.
|
-- Init done.
|
||||||
self.groupinitialized=true
|
self.groupinitialized=true
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1306,16 +1446,38 @@ function NAVYGROUP:_CheckTurnsIntoWind()
|
|||||||
|
|
||||||
-- Get current abs time.
|
-- Get current abs time.
|
||||||
local time=timer.getAbsTime()
|
local time=timer.getAbsTime()
|
||||||
local Cnow=UTILS.SecondsToClock(time)
|
|
||||||
|
|
||||||
-- Debug output:
|
if self.intowind then
|
||||||
local text=string.format(self.lid.."Recovery time windows:")
|
|
||||||
|
|
||||||
-- Handle case with no recoveries.
|
-- Check if time is over.
|
||||||
if #self.Qintowind==0 then
|
if time>=self.intowind.Tstop then
|
||||||
text=text.." none!"
|
self:TurnIntoWindOver(self.intowind)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Get next window.
|
||||||
|
local IntoWind=self:GetTurnIntoWindNext()
|
||||||
|
|
||||||
|
-- Start turn into wind.
|
||||||
|
if IntoWind then
|
||||||
|
self:TurnIntoWind(IntoWind)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the next turn into wind window, which is not yet running.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @return #NAVYGROUP.IntoWind Next into wind data. Could be `nil` if there is not next window.
|
||||||
|
function NAVYGROUP:GetTurnIntoWindNext()
|
||||||
|
|
||||||
|
if #self.Qintowind>0 then
|
||||||
|
|
||||||
|
-- Get current abs time.
|
||||||
|
local time=timer.getAbsTime()
|
||||||
|
|
||||||
-- Sort windows wrt to start time.
|
-- Sort windows wrt to start time.
|
||||||
table.sort(self.Qintowind, function(a, b) return a.Tstart<b.Tstart end)
|
table.sort(self.Qintowind, function(a, b) return a.Tstart<b.Tstart end)
|
||||||
|
|
||||||
@ -1323,49 +1485,21 @@ function NAVYGROUP:_CheckTurnsIntoWind()
|
|||||||
for _,_recovery in pairs(self.Qintowind) do
|
for _,_recovery in pairs(self.Qintowind) do
|
||||||
local recovery=_recovery --#NAVYGROUP.IntoWind
|
local recovery=_recovery --#NAVYGROUP.IntoWind
|
||||||
|
|
||||||
-- Get start/stop clock strings.
|
if time>=recovery.Tstart and time<recovery.Tstop and not (recovery.Open or recovery.Over) then
|
||||||
local Cstart=UTILS.SecondsToClock(recovery.Tstart)
|
return recovery
|
||||||
local Cstop=UTILS.SecondsToClock(recovery.Tstop)
|
|
||||||
|
|
||||||
-- Debug text.
|
|
||||||
text=text..string.format("\n- Start=%s Stop=%s Open=%s Closed=%s", Cstart, Cstop, tostring(recovery.Open), tostring(recovery.Over))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Debug output.
|
|
||||||
self:T(self.lid..text)
|
|
||||||
|
|
||||||
|
|
||||||
-- Loop over all slots.
|
|
||||||
for _,_recovery in pairs(self.Qintowind) do
|
|
||||||
local recovery=_recovery --#NAVYGROUP.IntoWind
|
|
||||||
|
|
||||||
if time>=recovery.Tstart and time<recovery.Tstop and not recovery.Open then
|
|
||||||
self:TurnIntoWind(recovery)
|
|
||||||
break
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If into wind, check if over.
|
|
||||||
if self.intowind then
|
|
||||||
if timer.getAbsTime()>=self.intowind.Tstop then
|
|
||||||
self:TurnIntoWindOver()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check queued turns into wind.
|
--- Get the turn into wind window, which is currently open.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @return #NAVYGROUP.IntoWind Next into wind data.
|
-- @return #NAVYGROUP.IntoWind Current into wind data. Could be `nil` if there is no window currenly open.
|
||||||
function NAVYGROUP:GetNextTurnIntoWind()
|
function NAVYGROUP:GetTurnIntoWindCurrent()
|
||||||
|
return self.intowind
|
||||||
-- Loop over all windows.
|
|
||||||
for _,_recovery in pairs(self.Qintowind) do
|
|
||||||
local recovery=_recovery --#NAVYGROUP.IntoWind
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get wind direction and speed at current position.
|
--- Get wind direction and speed at current position.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -2169,6 +2169,40 @@ function GROUP:GetThreatLevel()
|
|||||||
return threatlevelMax
|
return threatlevelMax
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the unit in the group with the highest threat level, which is still alive.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return Wrapper.Unit#UNIT The most dangerous unit in the group.
|
||||||
|
-- @return #number Threat level of the unit.
|
||||||
|
function GROUP:GetHighestThreat()
|
||||||
|
|
||||||
|
-- Get units of the group.
|
||||||
|
local units=self:GetUnits()
|
||||||
|
|
||||||
|
if units then
|
||||||
|
|
||||||
|
local threat=nil ; local maxtl=0
|
||||||
|
for _,_unit in pairs(units or {}) do
|
||||||
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
|
||||||
|
-- Threat level of group.
|
||||||
|
local tl=unit:GetThreatLevel()
|
||||||
|
|
||||||
|
-- Check if greater the current threat.
|
||||||
|
if tl>maxtl then
|
||||||
|
maxtl=tl
|
||||||
|
threat=unit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return threat, maxtl
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns true if the first unit of the GROUP is in the air.
|
--- Returns true if the first unit of the GROUP is in the air.
|
||||||
-- @param Wrapper.Group#GROUP self
|
-- @param Wrapper.Group#GROUP self
|
||||||
|
|||||||
@ -492,8 +492,7 @@ end
|
|||||||
|
|
||||||
--- Returns the unit's group if it exist and nil otherwise.
|
--- Returns the unit's group if it exist and nil otherwise.
|
||||||
-- @param Wrapper.Unit#UNIT self
|
-- @param Wrapper.Unit#UNIT self
|
||||||
-- @return Wrapper.Group#GROUP The Group of the Unit.
|
-- @return Wrapper.Group#GROUP The Group of the Unit or `nil` if the unit does not exist.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetGroup()
|
function UNIT:GetGroup()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user