mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-20 17:07:54 +00:00
Ops
This commit is contained in:
@@ -1,730 +0,0 @@
|
|||||||
--- **Functional** - (R2.5) - Replace client aircraft by statics until a player enters.
|
|
||||||
--
|
|
||||||
-- Make the DCS world a bit more lively!
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Easy!
|
|
||||||
--
|
|
||||||
-- ## Known (DCS) Issues
|
|
||||||
--
|
|
||||||
-- * Does not support clients on ships.
|
|
||||||
-- * Does not support Harriers and helicopters on parking spots below a shelter.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **Hardcard** (aka Goreuncle on the MOOSE discord)
|
|
||||||
-- ### Contributions: funkyfranky
|
|
||||||
--
|
|
||||||
-- @module Functional.Swapr
|
|
||||||
-- @image Functional_SWAPR.png
|
|
||||||
|
|
||||||
--- SWAPR class.
|
|
||||||
-- @type SWAPR
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #boolean Debug Debug mode on/off.
|
|
||||||
-- @field #string lid Log debug id text.
|
|
||||||
-- @field Core.Set#SET_CLIENT clientset Set of clients to be replaced.
|
|
||||||
-- @field #table statics Table of static objects.
|
|
||||||
-- @field #table statictemplate Table of static template
|
|
||||||
-- @extends Core.Fsm#FSM
|
|
||||||
|
|
||||||
--- Swap clients and statics
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- 
|
|
||||||
--
|
|
||||||
-- # SWAPR Concept
|
|
||||||
--
|
|
||||||
-- SWAPR will enable you to easily spawn static aircraft on client slots. When a player enters a client slot, the static object is removed and the player aircraft spawned.
|
|
||||||
-- This makes the airbases look a lot more alive.
|
|
||||||
--
|
|
||||||
-- # Simple Script
|
|
||||||
--
|
|
||||||
-- The basic script is very simple and consists of only two lines:
|
|
||||||
--
|
|
||||||
-- local clientset=SET_CLIENT:New():FilterActive(false):FilterOnce()
|
|
||||||
-- swapr=SWAPR:New(clientset)
|
|
||||||
--
|
|
||||||
-- The first line defines a set of clients (here all) that will be replaced by statics.
|
|
||||||
-- The second lines initiates the SWAPR script. That's all.
|
|
||||||
--
|
|
||||||
-- **Note** that Harrier and helicopter clients are automatically removed from the client set if they are placed on a sheltered parking spot. Otherwise the statics would be spawned
|
|
||||||
-- on top of the shelter roof.
|
|
||||||
--
|
|
||||||
-- Similarly, clients on ships are removed as these would be spawned at sea level and not on the ship itself.
|
|
||||||
--
|
|
||||||
-- All these are *DCS side restriction* when spawning statics.
|
|
||||||
--
|
|
||||||
-- # Debugging
|
|
||||||
--
|
|
||||||
-- In case you have problems, it is always a good idea to have a look at your DCS log file. You find it in your "Saved Games" folder, so for example in
|
|
||||||
-- C:\Users\<yourname>\Saved Games\DCS\Logs\dcs.log
|
|
||||||
-- All output concerning the @{#SWAPR} class should have the string "SWAPR" in the corresponding line.
|
|
||||||
-- Searching for lines that contain the string "error" or "nil" can also give you a hint what's wrong.
|
|
||||||
--
|
|
||||||
-- The verbosity of the output can be increased by adding the following lines to your script:
|
|
||||||
--
|
|
||||||
-- BASE:TraceOnOff(true)
|
|
||||||
-- BASE:TraceLevel(1)
|
|
||||||
-- BASE:TraceClass("SWAPR")
|
|
||||||
--
|
|
||||||
-- To get even more output you can increase the trace level to 2 or even 3, c.f. @{Core.Base#BASE} for more details.
|
|
||||||
--
|
|
||||||
-- ## Debug Mode
|
|
||||||
--
|
|
||||||
-- You have the option to enable the debug mode for this class via the @{#SWAPR.SetDebugModeON} function.
|
|
||||||
-- If enabled, text messages about the helo status will be displayed on screen and marks of the pattern created on the F10 map.
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- @field #SWAPR
|
|
||||||
SWAPR = {
|
|
||||||
ClassName = "SWAPR",
|
|
||||||
Debug = false,
|
|
||||||
lid = nil,
|
|
||||||
clientset = nil,
|
|
||||||
statics = {},
|
|
||||||
statictemplate = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Class version.
|
|
||||||
-- @field #string version
|
|
||||||
SWAPR.version="0.0.2"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- TODO list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- DONE: Check for clients on ships ==> get airdrome id from first route point.
|
|
||||||
-- DONE: Check that harrier and helo clients are not spawned in shelters ==> get parking spot type for these units in _Prepare()
|
|
||||||
-- TODO: Check what happens if statics are destroyed.
|
|
||||||
-- TODO: Check what happens if clients eject, crash or are shot down.
|
|
||||||
-- TODO: Check that parking spot is not blocked by other aircraft or statics when spawning a static replacement.
|
|
||||||
-- TODO: Add FSM events, e.g. static spawned, static destroyed etc.
|
|
||||||
-- TODO: Add user functions, e.g. for defining the static FARP offset.
|
|
||||||
-- TODO: Safe/load static templates to/from disk.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new SWAPR object.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param Core.Set#SET_CLIENT clientset (Optional) Set of clients to be replaced. Default all.
|
|
||||||
-- @return #SWAPR SWAPR object.
|
|
||||||
function SWAPR:New(clientset)
|
|
||||||
|
|
||||||
-- Inherit everthing from FSM class.
|
|
||||||
local self = BASE:Inherit(self, FSM:New()) -- #SWAPR
|
|
||||||
|
|
||||||
-- Carrier type.
|
|
||||||
self.clientset=clientset or SET_CLIENT:New():FilterActive(false):FilterOnce()
|
|
||||||
|
|
||||||
-- Log ID.
|
|
||||||
self.lid=string.format("SWAPR | ")
|
|
||||||
|
|
||||||
-- Debug trace.
|
|
||||||
if false then
|
|
||||||
self.Debug=true
|
|
||||||
BASE:TraceOnOff(true)
|
|
||||||
BASE:TraceClass(self.ClassName)
|
|
||||||
BASE:TraceLevel(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Events are handled directly by DCS.
|
|
||||||
self:T(self.lid.."Events are handled directly by DCS.")
|
|
||||||
world.addEventHandler(self)
|
|
||||||
|
|
||||||
self:HandleEvent(EVENTS.RemoveUnit)
|
|
||||||
|
|
||||||
-- Prepare stuff by temporarity spawning aircraft to determine the heading.
|
|
||||||
self:_Prepare()
|
|
||||||
|
|
||||||
-----------------------
|
|
||||||
--- FSM Transitions ---
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
-- Start State.
|
|
||||||
self:SetStartState("Stopped")
|
|
||||||
|
|
||||||
-- Add FSM transitions.
|
|
||||||
-- From State --> Event --> To State
|
|
||||||
self:AddTransition("Stopped", "Start", "Running")
|
|
||||||
self:AddTransition("*", "Status", "*")
|
|
||||||
self:AddTransition("*", "Stop", "Stopped")
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" that starts the rescue helo. Initializes parameters and starts event handlers.
|
|
||||||
-- @function [parent=#SWAPR] Start
|
|
||||||
-- @param #SWAPR self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" that starts the rescue helo after a delay. Initializes parameters and starts event handlers.
|
|
||||||
-- @function [parent=#SWAPR] __Start
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Status" that updates the helo status.
|
|
||||||
-- @function [parent=#SWAPR] Status
|
|
||||||
-- @param #SWAPR self
|
|
||||||
|
|
||||||
--- Triggers the delayed FSM event "Status" that updates the helo status.
|
|
||||||
-- @function [parent=#SWAPR] __Status
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" that stops the rescue helo. Event handlers are stopped.
|
|
||||||
-- @function [parent=#SWAPR] Stop
|
|
||||||
-- @param #SWAPR self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" that stops the rescue helo after a delay. Event handlers are stopped.
|
|
||||||
-- @function [parent=#SWAPR] __Stop
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Event handler
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
--- General event handler.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #table Event DCS event table.
|
|
||||||
function SWAPR:onEvent(Event)
|
|
||||||
self:F3(Event)
|
|
||||||
|
|
||||||
if Event == nil or Event.initiator == nil then
|
|
||||||
self:T3("Skipping onEvent. Event or Event.initiator unknown.")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
if Unit.getByName(Event.initiator:getName()) == nil then
|
|
||||||
self:T3("Skipping onEvent. Initiator unit name unknown.")
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get unit name and category.
|
|
||||||
local IniUnitName = Event.initiator:getName()
|
|
||||||
local IniCategory = Event.initiator:getCategory()
|
|
||||||
|
|
||||||
-- Get client.
|
|
||||||
local client=self.clientset:FindClient(IniUnitName)
|
|
||||||
|
|
||||||
-- This is not an event involving a client in the defined set.
|
|
||||||
if not client then
|
|
||||||
self:T3(self.lid.."Event not associated with client aircraft!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.id==EVENTS.Birth then
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
-- BIRTH EVENT --
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
if IniCategory==1 then
|
|
||||||
|
|
||||||
---------------
|
|
||||||
-- UNIT BORN --
|
|
||||||
---------------
|
|
||||||
|
|
||||||
local IniDCSGroup = Event.initiator:getGroup()
|
|
||||||
local IniGroupName = Event.initiator:getGroup():getName()
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Event birth of unit %s of group %s", tostring(IniUnitName), tostring(IniGroupName)))
|
|
||||||
|
|
||||||
-- Get unit.
|
|
||||||
local unit=UNIT:FindByName(IniUnitName)
|
|
||||||
|
|
||||||
if unit then
|
|
||||||
|
|
||||||
--unit:SmokeGreen()
|
|
||||||
|
|
||||||
-- Group and name.
|
|
||||||
local group=unit:GetGroup()
|
|
||||||
local groupname=group:GetName()
|
|
||||||
|
|
||||||
-- Check if this is prepare step to determine the heading.
|
|
||||||
if string.find(groupname, "_SWAPR") then
|
|
||||||
--unit:SmokeBlue()
|
|
||||||
|
|
||||||
-- Get info necessary for the static template.
|
|
||||||
local heading=unit:GetHeading()
|
|
||||||
local coord=unit:GetCoordinate()
|
|
||||||
local actype=unit:GetTypeName()
|
|
||||||
local livery=self:_GetLiveryFromTemplate(IniUnitName)
|
|
||||||
local airbase=self:_GetAirbaseFromTemplate(IniUnitName)
|
|
||||||
|
|
||||||
-- FARPS suck!
|
|
||||||
if airbase:GetAirbaseCategory()==Airbase.Category.HELIPAD then
|
|
||||||
local parkingid=self:_GetParkingFromTemplate(IniUnitName)
|
|
||||||
self:T2(self.lid..string.format("FARP parking id=%s", tostring(parkingid)))
|
|
||||||
if parkingid then
|
|
||||||
local spot=airbase:GetParkingSpotData(parkingid)
|
|
||||||
coord=spot.Coordinate
|
|
||||||
coord.z=coord.z+5
|
|
||||||
coord.x=coord.x+5
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add static template to table.
|
|
||||||
local statictemplate=self:_AddStaticTemplate(IniUnitName, actype, coord.x, coord.z, heading, unit:GetCountry(), livery)
|
|
||||||
|
|
||||||
-- Destroy unit ==> triggers a remove unit event.
|
|
||||||
unit:Destroy()
|
|
||||||
|
|
||||||
-- Replace aircraft by static.
|
|
||||||
--self:_Aircraft2Static(unit)
|
|
||||||
|
|
||||||
else
|
|
||||||
self:I(self.lid..string.format("Client %s spawned!", IniUnitName))
|
|
||||||
|
|
||||||
-- Get static that is in place of the spawned client.
|
|
||||||
local static=self.statics[IniUnitName] --Wrapper.Static#STATIC
|
|
||||||
|
|
||||||
-- Remove static.
|
|
||||||
if static then
|
|
||||||
self:I(self.lid..string.format("Destroying static %s!", IniUnitName))
|
|
||||||
|
|
||||||
-- Looks like the MOOSE Destroy function is not fast enough!
|
|
||||||
static:destroy()
|
|
||||||
self.statics[IniUnitName]=nil
|
|
||||||
else
|
|
||||||
self:E(self.lid..string.format("WARNING: No static %s to destroy!", IniUnitName))
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif IniCategory==3 then
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
-- STATIC BORN --
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
self:I(self.lid..string.format("Event birth of static %s", tostring(IniUnitName)))
|
|
||||||
|
|
||||||
-- WORKS!
|
|
||||||
local static=STATIC:FindByName(IniUnitName, true)
|
|
||||||
|
|
||||||
-- Add spawned static to table.
|
|
||||||
--self.statics[IniUnitName]=static
|
|
||||||
self.statics[IniUnitName]=Event.initiator
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif Event.id==EVENTS.PlayerLeaveUnit then
|
|
||||||
|
|
||||||
-----------------
|
|
||||||
-- PLAYER LEFT --
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
self:I(self.lid..string.format("Event player leave unit %s", IniUnitName))
|
|
||||||
|
|
||||||
-- Spawn static. Needs to be delayed a tad or DCS crashes to desktop.
|
|
||||||
local statictemplate=self.statictemplate[IniUnitName]
|
|
||||||
if statictemplate then
|
|
||||||
self:ScheduleOnce(0.1, SWAPR._SpawnStaticAircraft, self, statictemplate)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- General event handler.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
|
||||||
function SWAPR:OnEventRemoveUnit(EventData)
|
|
||||||
self:I(EventData)
|
|
||||||
|
|
||||||
if EventData and EventData.IniUnitName then
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I(self.lid..string.format("Event removed unit %s!", EventData.IniUnitName))
|
|
||||||
|
|
||||||
-- Spawn static aircraft.
|
|
||||||
local statictemplate=self.statictemplate[EventData.IniUnitName]
|
|
||||||
if statictemplate then
|
|
||||||
self:ScheduleOnce(0.1, SWAPR._SpawnStaticAircraft, self, statictemplate)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Spawn functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Add template to static table.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string name Name of the static.
|
|
||||||
-- @param #string actype Type of the aircraft.
|
|
||||||
-- @param #number x X coordinate of spawn place.
|
|
||||||
-- @param #number y Y coordinate of spawn place.
|
|
||||||
-- @param #number heading Heading of static.
|
|
||||||
-- @param #number country Country ID of static.
|
|
||||||
-- @param #string livery Livery ID of the static.
|
|
||||||
-- @return #table Static template.
|
|
||||||
function SWAPR:_AddStaticTemplate(name, actype, x, y, heading, country, livery)
|
|
||||||
|
|
||||||
-- Heading is in rad not degrees!
|
|
||||||
local headingrad=0
|
|
||||||
if heading then
|
|
||||||
headingrad=math.rad(heading)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Static template table.
|
|
||||||
local static={
|
|
||||||
livery_id=livery,
|
|
||||||
heading=headingrad,
|
|
||||||
type=actype,
|
|
||||||
name=name,
|
|
||||||
y=y ,
|
|
||||||
x=x ,
|
|
||||||
CountryID=country,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T2({statictemplate=static})
|
|
||||||
|
|
||||||
self.statictemplate[name]=static
|
|
||||||
|
|
||||||
return static
|
|
||||||
end
|
|
||||||
|
|
||||||
--- General event handler.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #table template The static template.
|
|
||||||
function SWAPR:_SpawnStaticAircraft(template)
|
|
||||||
self:I({statictemplate=template})
|
|
||||||
|
|
||||||
if template and not self.statics[template.name] then
|
|
||||||
|
|
||||||
-- Spawn static.
|
|
||||||
local static=coalition.addStaticObject(template.CountryID, template)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T2({spawnedstatic=static})
|
|
||||||
self:T(self.lid..string.format("Spawned static %s", template.name))
|
|
||||||
|
|
||||||
else
|
|
||||||
self:T3(self.lid.."WARNING: Static template is nil!")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Replace a whole aircraft group by statics.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param Wrapper.Group#GROUP group
|
|
||||||
function SWAPR:_AircraftGroup2Statics(group)
|
|
||||||
|
|
||||||
-- Get the group template.
|
|
||||||
local grouptemplate=group:GetTemplate()
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T3({grouptemplate=grouptemplate})
|
|
||||||
|
|
||||||
for i,_unit in pairs(group:GetUnits()) do
|
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
-- Get unit name.
|
|
||||||
local unitname=unit:GetName()
|
|
||||||
|
|
||||||
local statictemplate=self.statictemplate[unitname]
|
|
||||||
local static=self.statics[unitname]
|
|
||||||
|
|
||||||
if statictemplate and not static then
|
|
||||||
|
|
||||||
-- Destroy the unit.
|
|
||||||
unit:Destroy()
|
|
||||||
|
|
||||||
-- Spawn static aircraft instead.
|
|
||||||
self:_SpawnStaticAircraft(statictemplate)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Replace a single aircraft unit by static.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param Wrapper.Unit#UNIT unit The unit to be replaced.
|
|
||||||
function SWAPR:_Aircraft2Static(unit)
|
|
||||||
|
|
||||||
if unit and unit:IsAlive() then
|
|
||||||
|
|
||||||
-- Get the group template.
|
|
||||||
local grouptemplate=unit:GetGroup():GetTemplate()
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T3({grouptemplate=grouptemplate})
|
|
||||||
|
|
||||||
-- Get unit name.
|
|
||||||
local unitname=unit:GetName()
|
|
||||||
|
|
||||||
-- Get the static template.
|
|
||||||
local statictemplate=self.statictemplate[unitname]
|
|
||||||
|
|
||||||
-- Get the static to check if there already is one.
|
|
||||||
local static=self.statics[unitname]
|
|
||||||
|
|
||||||
if statictemplate and not static then
|
|
||||||
|
|
||||||
-- Destroy the unit ==> triggers a RemoveUnit event.
|
|
||||||
unit:Destroy()
|
|
||||||
|
|
||||||
-- Spawn static aircraft instead.
|
|
||||||
self:_SpawnStaticAircraft(statictemplate)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Temporarily spawn uncontrolled aircraft at all client spots to get the correct headings.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
function SWAPR:_Prepare()
|
|
||||||
|
|
||||||
local remove={}
|
|
||||||
for _,_client in pairs(self.clientset:GetSet()) do
|
|
||||||
local client=_client --Wrapper.Client#CLIENT
|
|
||||||
|
|
||||||
-- Unit name
|
|
||||||
local unitname=client.ClientName
|
|
||||||
|
|
||||||
-- Get airbase if any.
|
|
||||||
local airbase=self:_GetAirbaseFromTemplate(unitname)
|
|
||||||
|
|
||||||
-- First check that this is not a cliened spawned in air or on a ship.
|
|
||||||
if airbase==nil then
|
|
||||||
-- Spawned in air ==> remove!
|
|
||||||
self:I(self.lid..string.format("Removing client %s because of air start.", unitname))
|
|
||||||
table.insert(remove, client)
|
|
||||||
elseif airbase:GetAirbaseCategory()==Airbase.Category.SHIP then
|
|
||||||
self:I(self.lid..string.format("Removing client %s because spawned on ship.", unitname))
|
|
||||||
table.insert(remove, client)
|
|
||||||
else
|
|
||||||
|
|
||||||
if true then
|
|
||||||
|
|
||||||
---
|
|
||||||
-- Spawn a group to get parameters in particular the heading on the parking spot as this is not correct in the template.
|
|
||||||
---
|
|
||||||
|
|
||||||
-- Check that harriers are not spawned in shelters because they would appear on top of them.
|
|
||||||
-- TODO: Need to do the same of helos?
|
|
||||||
local _continue=true
|
|
||||||
if self:_GetTypeFromTemplate(unitname)=="AV8BNA" then
|
|
||||||
local parkingid=self:_GetParkingFromTemplate(unitname)
|
|
||||||
if parkingid then
|
|
||||||
env.info(string.format("Harrier parking spot id %d", parkingid))
|
|
||||||
local spot=airbase:GetParkingSpotData(parkingid)
|
|
||||||
if spot and spot.TerminalType==AIRBASE.TerminalType.Shelter then
|
|
||||||
_continue=false
|
|
||||||
table.insert(remove, client)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if _continue then
|
|
||||||
|
|
||||||
-- Client group name.
|
|
||||||
local groupname=_DATABASE.Templates.Units[unitname].GroupName
|
|
||||||
|
|
||||||
-- Client group template copy.
|
|
||||||
local grouptemplate=UTILS.DeepCopy(_DATABASE:GetGroupTemplate(groupname))
|
|
||||||
|
|
||||||
-- Nillify the group ID.
|
|
||||||
grouptemplate.groupId=nil
|
|
||||||
|
|
||||||
-- Set skill.
|
|
||||||
for i=1,#grouptemplate.units do
|
|
||||||
local unit=grouptemplate.units[i]
|
|
||||||
unit.skill="Good"
|
|
||||||
-- Nillify the unit ID.
|
|
||||||
unit.unitId=nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Uncontrolled
|
|
||||||
grouptemplate.uncontrolled=true
|
|
||||||
|
|
||||||
-- Add _SWAPR to the group name so that we find it in birth event.
|
|
||||||
grouptemplate.name=string.format("%s_SWAPR", groupname)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I({grouptemplate=grouptemplate})
|
|
||||||
|
|
||||||
-- Spawn group.
|
|
||||||
local group=_DATABASE:Spawn(grouptemplate)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
---
|
|
||||||
-- Get all info from template. Unfortunately, heading is always 0 in the template, i.e. all statics would face due North!
|
|
||||||
---
|
|
||||||
|
|
||||||
local livery=self:_GetLiveryFromTemplate(unitname)
|
|
||||||
local x,y=self:_GetPositionFromTemplate(unitname)
|
|
||||||
local actype=self:_GetTypeFromTemplate(unitname)
|
|
||||||
local heading=self:_GetHeadingFromTemplate(unitname)
|
|
||||||
|
|
||||||
-- TODO: country!
|
|
||||||
local template=self:_AddStaticTemplate(unitname, actype, x, y, heading, 1, livery)
|
|
||||||
|
|
||||||
self:_SpawnStaticAircraft(template)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
for _,_client in pairs(remove) do
|
|
||||||
local client=_client --Wrapper.Client#CLIENT
|
|
||||||
self.clientset:RemoveClientsByName(client.ClientName)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:I(self.lid..string.format("Number of clients left after prepare = %d", self.clientset:Count()))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Misc functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Get livery from unit.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return #string Livery ID.
|
|
||||||
function SWAPR:_GetLiveryFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
for _,unit in pairs(grouptemplate.units) do
|
|
||||||
if unit.name==unitname then
|
|
||||||
return tostring(unit.livery_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get livery from unit.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return #number X coordinate.
|
|
||||||
-- @return #number Y coordinate.
|
|
||||||
function SWAPR:_GetPositionFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
for _,unit in pairs(grouptemplate.units) do
|
|
||||||
if unit.name==unitname then
|
|
||||||
return tonumber(unit.x), tonumber(unit.y)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get livery from unit.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return #string Aircraft type.
|
|
||||||
function SWAPR:_GetTypeFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
for _,unit in pairs(grouptemplate.units) do
|
|
||||||
if unit.name==unitname then
|
|
||||||
return tostring(unit.type)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get livery from unit.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return #number Heading in degrees.
|
|
||||||
function SWAPR:_GetHeadingFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
for _,unit in pairs(grouptemplate.units) do
|
|
||||||
if unit.name==unitname then
|
|
||||||
return tonumber(unit.heading)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get airbase from template.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return Wrapper.Airbase#AIRBASE The airbase object or nil.
|
|
||||||
function SWAPR:_GetAirbaseFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
-- First waypoint.
|
|
||||||
local wp=grouptemplate.route.points[1]
|
|
||||||
|
|
||||||
local airbase=nil --Wrapper.Airbase#AIRBASE
|
|
||||||
local id=-666
|
|
||||||
if wp.airdromeId then
|
|
||||||
id=tonumber(wp.airdromeId)
|
|
||||||
elseif wp.helipadId then
|
|
||||||
id=tonumber(wp.helipadId)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find airbase by its id.
|
|
||||||
airbase=AIRBASE:FindByID(id)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
if airbase then
|
|
||||||
self:T3(self.lid..string.format("Found airbase %s for unit %s, id=%d", airbase:GetName(), unitname, id))
|
|
||||||
else
|
|
||||||
self:T3(self.lid..string.format("Found NO airbase for unit %s, id=%d", unitname,id))
|
|
||||||
end
|
|
||||||
|
|
||||||
return airbase
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get parking id from template.
|
|
||||||
-- @param #SWAPR self
|
|
||||||
-- @param #string unitname Name of the unit.
|
|
||||||
-- @return #number Parking id or nil.
|
|
||||||
function SWAPR:_GetParkingFromTemplate(unitname)
|
|
||||||
|
|
||||||
local grouptemplate=_DATABASE:GetGroupTemplateFromUnitName(unitname)
|
|
||||||
|
|
||||||
for _,unit in pairs(grouptemplate.units) do
|
|
||||||
if unit.name==unitname then
|
|
||||||
return tonumber(unit.parking)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@@ -37,6 +37,8 @@ __Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Wrapper/Mark.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Wrapper/DCSTask.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
||||||
@@ -67,7 +69,6 @@ __Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Functional/RAT2.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/RAT2.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/RatCraft.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/RatCraft.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/FlightModelData.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/FlightModelData.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/SWAPR.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
-- @field #table pointsTANKER Table of Tanker points.
|
-- @field #table pointsTANKER Table of Tanker points.
|
||||||
-- @field #table pointsAWACS Table of AWACS points.
|
-- @field #table pointsAWACS Table of AWACS points.
|
||||||
-- @field Ops.WingCommander#WINGCOMMANDER wingcommander The wing commander responsible for this airwing.
|
-- @field Ops.WingCommander#WINGCOMMANDER wingcommander The wing commander responsible for this airwing.
|
||||||
|
--
|
||||||
|
-- @field Ops.RescueHelo#RESCUEHELO rescuehelo The rescue helo.
|
||||||
|
-- @field Ops.RecoveryTanker#RECOVERYTANKER recoverytanker The recoverytanker.
|
||||||
|
--
|
||||||
-- @extends Functional.Warehouse#WAREHOUSE
|
-- @extends Functional.Warehouse#WAREHOUSE
|
||||||
|
|
||||||
--- Be surprised!
|
--- Be surprised!
|
||||||
@@ -79,11 +83,10 @@ AIRWING = {
|
|||||||
-- @type AIRWING.Payload
|
-- @type AIRWING.Payload
|
||||||
-- @field #string unitname Name of the unit this pylon was extracted from.
|
-- @field #string unitname Name of the unit this pylon was extracted from.
|
||||||
-- @field #string aircrafttype Type of aircraft, which can use this payload.
|
-- @field #string aircrafttype Type of aircraft, which can use this payload.
|
||||||
-- @field #table missiontypes Mission types for which this payload can be used.
|
-- @field #table capabilities Mission types and performances for which this payload can be used.
|
||||||
-- @field #table pylons Pylon data extracted for the unit template.
|
-- @field #table pylons Pylon data extracted for the unit template.
|
||||||
-- @field #number navail Number of available payloads of this type.
|
-- @field #number navail Number of available payloads of this type.
|
||||||
-- @field #boolean unlimited If true, this payload is unlimited and does not get consumed.
|
-- @field #boolean unlimited If true, this payload is unlimited and does not get consumed.
|
||||||
-- @field #number priority Priority of the payload.
|
|
||||||
|
|
||||||
--- Patrol data.
|
--- Patrol data.
|
||||||
-- @type AIRWING.PatrolData
|
-- @type AIRWING.PatrolData
|
||||||
@@ -95,7 +98,7 @@ AIRWING = {
|
|||||||
|
|
||||||
--- AIRWING class version.
|
--- AIRWING class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRWING.version="0.1.5"
|
AIRWING.version="0.1.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -103,7 +106,6 @@ AIRWING.version="0.1.5"
|
|||||||
|
|
||||||
-- TODO: Spawn in air or hot.
|
-- TODO: Spawn in air or hot.
|
||||||
-- TODO: Make special request to transfer squadrons to anther airwing (or warehouse).
|
-- TODO: Make special request to transfer squadrons to anther airwing (or warehouse).
|
||||||
-- TODO: Border zone or even multiple zones.
|
|
||||||
-- TODO: Check that airbase has enough parking spots if a request is BIG. Alternatively, split requests.
|
-- TODO: Check that airbase has enough parking spots if a request is BIG. Alternatively, split requests.
|
||||||
-- DONE: Add squadrons to warehouse.
|
-- DONE: Add squadrons to warehouse.
|
||||||
-- DONE: Build mission queue.
|
-- DONE: Build mission queue.
|
||||||
@@ -146,6 +148,9 @@ function AIRWING:New(warehousename, airwingname)
|
|||||||
self.nflightsTANKERboom=0
|
self.nflightsTANKERboom=0
|
||||||
self.nflightsTANKERprobe=0
|
self.nflightsTANKERprobe=0
|
||||||
|
|
||||||
|
self.nflightsRecoveryTanker=0
|
||||||
|
self.nflightsRescuehelo=0
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
------------------------
|
------------------------
|
||||||
@@ -240,32 +245,36 @@ function AIRWING:NewPayload(Unit, MissionTypes, Npayloads, Unlimited, Priority)
|
|||||||
MissionTypes={MissionTypes}
|
MissionTypes={MissionTypes}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add ORBIT for all.
|
|
||||||
if not self:CheckMissionType(AUFTRAG.Type.ORBIT, MissionTypes) then
|
|
||||||
table.insert(MissionTypes, AUFTRAG.Type.ORBIT)
|
|
||||||
end
|
|
||||||
|
|
||||||
if Unit then
|
if Unit then
|
||||||
|
|
||||||
local payload={} --#AIRWING.Payload
|
local payload={} --#AIRWING.Payload
|
||||||
|
|
||||||
|
--TODO: capability
|
||||||
|
|
||||||
payload.unitname=Unit:GetName()
|
payload.unitname=Unit:GetName()
|
||||||
payload.aircrafttype=Unit:GetTypeName()
|
payload.aircrafttype=Unit:GetTypeName()
|
||||||
payload.missiontypes=MissionTypes or {}
|
payload.capabilities=MissionTypes or {}
|
||||||
payload.pylons=Unit:GetTemplatePayload()
|
payload.pylons=Unit:GetTemplatePayload()
|
||||||
payload.navail=Npayloads or 99
|
payload.navail=Npayloads or 99
|
||||||
payload.unlimited=Unlimited
|
payload.unlimited=Unlimited
|
||||||
if Unlimited then
|
if Unlimited then
|
||||||
payload.navail=1
|
payload.navail=1
|
||||||
end
|
end
|
||||||
payload.priority=Priority or 50
|
|
||||||
|
|
||||||
-- Add payload
|
-- Add payload
|
||||||
table.insert(self.payloads, payload)
|
table.insert(self.payloads, payload)
|
||||||
|
|
||||||
|
-- Add ORBIT for all.
|
||||||
|
if not self:CheckMissionType(AUFTRAG.Type.ORBIT, MissionTypes) then
|
||||||
|
local capability={} --Ops.Auftrag#AUFTRAG.Capability
|
||||||
|
capability.MissionType=AUFTRAG.Type.ORBIT
|
||||||
|
capability.Performance=50
|
||||||
|
--table.insert(MissionTypes, capability)
|
||||||
|
end
|
||||||
|
|
||||||
-- Info
|
-- Info
|
||||||
self:I(self.lid..string.format("Adding new payload from unit %s for aircraft type %s: N=%d (unlimited=%s), prio=%d, missions: %s",
|
self:I(self.lid..string.format("Adding new payload from unit %s for aircraft type %s: N=%d (unlimited=%s), prio=%d, missions: %s",
|
||||||
payload.unitname, payload.aircrafttype, payload.navail, tostring(payload.unlimited), payload.priority, table.concat(payload.missiontypes, ", ")))
|
payload.unitname, payload.aircrafttype, payload.navail, tostring(payload.unlimited), payload.priority, table.concat(MissionTypes, ", ")))
|
||||||
|
|
||||||
return payload
|
return payload
|
||||||
end
|
end
|
||||||
@@ -763,7 +772,7 @@ function AIRWING:CheckTANKER()
|
|||||||
for _,_mission in pairs(self.missionqueue) do
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
|
||||||
if mission:IsNotOver() and self:CheckMissionType(mission.type, AUFTRAG.Type.TANKER) then
|
if mission:IsNotOver() and mission.type==AUFTRAG.Type.TANKER then
|
||||||
if mission.refuelSystem==0 then
|
if mission.refuelSystem==0 then
|
||||||
Nboom=Nboom+1
|
Nboom=Nboom+1
|
||||||
elseif mission.refuelSystem==1 then
|
elseif mission.refuelSystem==1 then
|
||||||
@@ -833,6 +842,13 @@ function AIRWING:CheckAWACS()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check how many AWACS missions are assigned and add number of missing missions.
|
||||||
|
-- @param #AIRWING self
|
||||||
|
-- @return #AIRWING self
|
||||||
|
function AIRWING:CheckRecoveryTanker()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check how many AWACS missions are assigned and add number of missing missions.
|
--- Check how many AWACS missions are assigned and add number of missing missions.
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup.
|
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flightgroup.
|
||||||
@@ -912,8 +928,7 @@ function AIRWING:_GetNextMission()
|
|||||||
if can then
|
if can then
|
||||||
|
|
||||||
-- Optimize the asset selection. Most useful assets will come first.
|
-- Optimize the asset selection. Most useful assets will come first.
|
||||||
-- TODO: This could be moved to AUFTRAG, right?
|
self:_OptimizeAssetSelection(assets, mission)
|
||||||
--self:_OptimizeAssetSelection(assets, mission)
|
|
||||||
|
|
||||||
-- Check that mission.assets table is clean.
|
-- Check that mission.assets table is clean.
|
||||||
if mission.assets and #mission.assets>0 then
|
if mission.assets and #mission.assets>0 then
|
||||||
@@ -968,6 +983,23 @@ function AIRWING:_OptimizeAssetSelection(assets, Mission)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function score(Asset)
|
||||||
|
local asset=Asset --#AIRWING.SquadronAsset
|
||||||
|
|
||||||
|
score=0
|
||||||
|
|
||||||
|
-- Prefer highly skilled assets.
|
||||||
|
if asset.skill==AI.Skill.GOOD then
|
||||||
|
score=score+10
|
||||||
|
elseif asset.skill==AI.Skill.HIGH then
|
||||||
|
score=score+20
|
||||||
|
elseif asset.skill==AI.Skill.EXCELLENT then
|
||||||
|
score=score+30
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-- Sort results table wrt distacance.
|
-- Sort results table wrt distacance.
|
||||||
local function optimize(a, b)
|
local function optimize(a, b)
|
||||||
local assetA=a --#AIRWING.SquadronAsset
|
local assetA=a --#AIRWING.SquadronAsset
|
||||||
@@ -1563,7 +1595,7 @@ function AIRWING:CanMission(Mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the mission for a given mission ID (Autragsnummer).
|
--- Check if a mission type is contained in a list of possible types.
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @param #string MissionType The requested mission type.
|
-- @param #string MissionType The requested mission type.
|
||||||
-- @param #table PossibleTypes A table with possible mission types.
|
-- @param #table PossibleTypes A table with possible mission types.
|
||||||
@@ -1583,6 +1615,23 @@ function AIRWING:CheckMissionType(MissionType, PossibleTypes)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if a mission type is contained in a list of possible capabilities.
|
||||||
|
-- @param #AIRWING self
|
||||||
|
-- @param #string MissionType The requested mission type.
|
||||||
|
-- @param #table PossibleTypes A table with possible capabilities.
|
||||||
|
-- @return #boolean If true, the requested mission type is part of the possible mission types.
|
||||||
|
function AIRWING:CheckMissionCapability(MissionType, Capabilities)
|
||||||
|
|
||||||
|
for _,cap in pairs(Capabilities) do
|
||||||
|
local capability=cap --Ops.Auftrag#AUFTRAG.Capability
|
||||||
|
if capability.MissionType==MissionType then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns the mission for a given mission ID (Autragsnummer).
|
--- Returns the mission for a given mission ID (Autragsnummer).
|
||||||
-- @param #AIRWING self
|
-- @param #AIRWING self
|
||||||
-- @param #number mid Mission ID (Auftragsnummer).
|
-- @param #number mid Mission ID (Auftragsnummer).
|
||||||
|
|||||||
@@ -273,13 +273,18 @@ AUFTRAG.TargetType={
|
|||||||
AIRBASE="Airbase",
|
AIRBASE="Airbase",
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
--- Target data.
|
||||||
-- @type AUFTRAG.TargetData
|
-- @type AUFTRAG.TargetData
|
||||||
-- @field Wrapper.Positionable#POSITIONABLE Target Target Object.
|
-- @field Wrapper.Positionable#POSITIONABLE Target Target Object.
|
||||||
-- @field #string Type Target type: "Group", "Unit", "Static", "Coordinate", "Airbase.
|
-- @field #string Type Target type: "Group", "Unit", "Static", "Coordinate", "Airbase.
|
||||||
-- @field #number Ninital Number of initial targets.
|
-- @field #number Ninital Number of initial targets.
|
||||||
-- @field #number Lifepoints Total life points.
|
-- @field #number Lifepoints Total life points.
|
||||||
|
|
||||||
|
--- Mission capability.
|
||||||
|
-- @type AUFTRAG.Capability
|
||||||
|
-- @field #string MissionType Type of mission.
|
||||||
|
-- @field #number Performance Number describing the performance level. The higher the better.
|
||||||
|
|
||||||
--- Mission success.
|
--- Mission success.
|
||||||
-- @type AUFTRAG.Success
|
-- @type AUFTRAG.Success
|
||||||
-- @field #string ENGAGED Target was engaged.
|
-- @field #string ENGAGED Target was engaged.
|
||||||
@@ -2297,6 +2302,29 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskEmbarking(self, Vec2, self.transportGroupSet, Duration, DistributionGroupSet)
|
local DCStask=CONTROLLABLE.TaskEmbarking(self, Vec2, self.transportGroupSet, Duration, DistributionGroupSet)
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.RESCUEHELO then
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- RESCUE HELO Mission --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
local DCStask={}
|
||||||
|
|
||||||
|
DCStask.id="Formation"
|
||||||
|
|
||||||
|
local param={}
|
||||||
|
param.unitname=""
|
||||||
|
param.offsetX=20
|
||||||
|
param.offsetY=20
|
||||||
|
param.offsetZ=20
|
||||||
|
param.alitude=70
|
||||||
|
|
||||||
|
DCStask.params=param
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -2628,7 +2628,6 @@ function FLIGHTGROUP:onafterPassingWaypoint(From, Event, To, n, N)
|
|||||||
|
|
||||||
-- Execute waypoint tasks.
|
-- Execute waypoint tasks.
|
||||||
if #taskswp>0 then
|
if #taskswp>0 then
|
||||||
--self:PushTask(self.group:TaskCombo(taskswp))
|
|
||||||
self:SetTask(self.group:TaskCombo(taskswp))
|
self:SetTask(self.group:TaskCombo(taskswp))
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3390,37 +3389,63 @@ function FLIGHTGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
-- Task status executing.
|
-- Task status executing.
|
||||||
Task.status=FLIGHTGROUP.TaskStatus.EXECUTING
|
Task.status=FLIGHTGROUP.TaskStatus.EXECUTING
|
||||||
|
|
||||||
-- If task is scheduled (not waypoint) set task.
|
if Task.dcstask.id=="Formation" then
|
||||||
if Task.type==FLIGHTGROUP.TaskType.SCHEDULED then
|
|
||||||
|
|
||||||
local DCStasks={}
|
-- Set of group(s) to follow Mother.
|
||||||
if Task.dcstask.id=='ComboTask' then
|
local followset=SET_GROUP:New():AddGroup(self.group)
|
||||||
-- Loop over all combo tasks.
|
|
||||||
for TaskID, Task in ipairs(Task.dcstask.params.tasks) do
|
local param=Task.dcstask.params
|
||||||
table.insert(DCStasks, Task)
|
|
||||||
|
-- Define AI Formation object.
|
||||||
|
Task.formation=AI_FORMATION:New(param.carrier, followset, "Formation", "Follow X at given parameters.")
|
||||||
|
|
||||||
|
-- Formation parameters.
|
||||||
|
Task.formation:FormationCenterWing(-param.offsetX, 50, math.abs(param.altitude), 50, param.offsetZ, 50)
|
||||||
|
|
||||||
|
-- Set follow time interval.
|
||||||
|
Task.formation:SetFollowTimeInterval(param.dtFollow)
|
||||||
|
|
||||||
|
-- Formation mode.
|
||||||
|
Task.formation:SetFlightModeFormation(self.group)
|
||||||
|
|
||||||
|
-- Start formation FSM.
|
||||||
|
Task.formation:Start()
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- If task is scheduled (not waypoint) set task.
|
||||||
|
if Task.type==FLIGHTGROUP.TaskType.SCHEDULED then
|
||||||
|
|
||||||
|
local DCStasks={}
|
||||||
|
if Task.dcstask.id=='ComboTask' then
|
||||||
|
-- Loop over all combo tasks.
|
||||||
|
for TaskID, Task in ipairs(Task.dcstask.params.tasks) do
|
||||||
|
table.insert(DCStasks, Task)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert(DCStasks, Task.dcstask)
|
||||||
end
|
end
|
||||||
else
|
|
||||||
table.insert(DCStasks, Task.dcstask)
|
-- Combo task.
|
||||||
|
local TaskCombo=self.group:TaskCombo(DCStasks)
|
||||||
|
|
||||||
|
-- Stop condition!
|
||||||
|
local TaskCondition=self.group:TaskCondition(nil, Task.stopflag:GetName(), 1, nil, Task.duration)
|
||||||
|
|
||||||
|
-- Controlled task.
|
||||||
|
local TaskControlled=self.group:TaskControlled(TaskCombo, TaskCondition)
|
||||||
|
|
||||||
|
-- Task done.
|
||||||
|
local TaskDone=self.group:TaskFunction("FLIGHTGROUP._TaskDone", self, Task)
|
||||||
|
|
||||||
|
-- Final task.
|
||||||
|
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
|
||||||
|
|
||||||
|
-- Set task for group.
|
||||||
|
self:SetTask(TaskFinal, 1)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Combo task.
|
|
||||||
local TaskCombo=self.group:TaskCombo(DCStasks)
|
|
||||||
|
|
||||||
-- Stop condition!
|
|
||||||
local TaskCondition=self.group:TaskCondition(nil, Task.stopflag:GetName(), 1, nil, Task.duration)
|
|
||||||
|
|
||||||
-- Controlled task.
|
|
||||||
local TaskControlled=self.group:TaskControlled(TaskCombo, TaskCondition)
|
|
||||||
|
|
||||||
-- Task done.
|
|
||||||
local TaskDone=self.group:TaskFunction("FLIGHTGROUP._TaskDone", self, Task)
|
|
||||||
|
|
||||||
-- Final task.
|
|
||||||
local TaskFinal=self.group:TaskCombo({TaskControlled, TaskDone})
|
|
||||||
|
|
||||||
-- Set task for group.
|
|
||||||
self:SetTask(TaskFinal, 1)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get mission of this task (if any).
|
-- Get mission of this task (if any).
|
||||||
@@ -3490,6 +3515,11 @@ function FLIGHTGROUP:onafterTaskCancel(From, Event, To, Task)
|
|||||||
-- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone()
|
-- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone()
|
||||||
Task.stopflag:Set(1)
|
Task.stopflag:Set(1)
|
||||||
|
|
||||||
|
if Task.dcstask.id=="Formation" then
|
||||||
|
Task.formation:Stop()
|
||||||
|
self:TaskDone(Task)
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
@@ -3577,10 +3607,6 @@ function FLIGHTGROUP:onafterTaskDone(From, Event, To, Task)
|
|||||||
self:_CheckFlightDone(1)
|
self:_CheckFlightDone(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Update route. This is necessary because of the route task being overwritten. But we want to fly to the remaining waypoints.
|
|
||||||
-- TODO: Since TaskExecute does use PushTask now, it should not be necessary to update the route, right?
|
|
||||||
--self:__UpdateRoute(-1)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -3739,10 +3765,8 @@ function FLIGHTGROUP:onafterMissionCancel(From, Event, To, Mission)
|
|||||||
-- Note that two things can happen.
|
-- Note that two things can happen.
|
||||||
-- 1.) Flight is still on the way to the waypoint (status should be STARTED). In this case there would not be a current task!
|
-- 1.) Flight is still on the way to the waypoint (status should be STARTED). In this case there would not be a current task!
|
||||||
-- 2.) Flight already passed the mission waypoint (status should be EXECUTING).
|
-- 2.) Flight already passed the mission waypoint (status should be EXECUTING).
|
||||||
self:TaskCancel(Task)
|
|
||||||
|
|
||||||
-- Set current mission to nil.
|
self:TaskCancel(Task)
|
||||||
--self.currentmission=nil
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@@ -4452,34 +4476,6 @@ function FLIGHTGROUP:_UpdateWaypointTasks()
|
|||||||
local TaskPassingWaypoint=self.group:TaskFunction("FLIGHTGROUP._PassingWaypoint", self, i)
|
local TaskPassingWaypoint=self.group:TaskFunction("FLIGHTGROUP._PassingWaypoint", self, i)
|
||||||
table.insert(taskswp, TaskPassingWaypoint)
|
table.insert(taskswp, TaskPassingWaypoint)
|
||||||
|
|
||||||
|
|
||||||
-- For some reason THIS DOES NOT WORK if executed at the last waypoint if it is an AIR WAYPOINT.
|
|
||||||
-- I have moved it to the onafterpassingwaypoint function instead.
|
|
||||||
|
|
||||||
if false then
|
|
||||||
|
|
||||||
-- Get taks
|
|
||||||
local tasks=self:GetTasksWaypoint(i)
|
|
||||||
|
|
||||||
for _,task in pairs(tasks) do
|
|
||||||
local Task=task --#FLIGHTGROUP.Task
|
|
||||||
|
|
||||||
-- Task execute.
|
|
||||||
table.insert(taskswp, self.group:TaskFunction("FLIGHTGROUP._TaskExecute", self, Task))
|
|
||||||
|
|
||||||
-- Stop condition if userflag is set to 1.
|
|
||||||
local TaskCondition=self.group:TaskCondition(nil, Task.stopflag:GetName(), 1, nil, Task.duration)
|
|
||||||
|
|
||||||
-- Controlled task.
|
|
||||||
table.insert(taskswp, self.group:TaskControlled(Task.dcstask, TaskCondition))
|
|
||||||
|
|
||||||
-- Task done.
|
|
||||||
table.insert(taskswp, self.group:TaskFunction("FLIGHTGROUP._TaskDone", self, Task))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Waypoint task combo.
|
-- Waypoint task combo.
|
||||||
wp.task=self.group:TaskCombo(taskswp)
|
wp.task=self.group:TaskCombo(taskswp)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -223,8 +223,9 @@ end
|
|||||||
--- Set mission types this squadron is able to perform.
|
--- Set mission types this squadron is able to perform.
|
||||||
-- @param #SQUADRON self
|
-- @param #SQUADRON self
|
||||||
-- @param #table MissionTypes Table of mission types. Can also be passed as a #string if only one type.
|
-- @param #table MissionTypes Table of mission types. Can also be passed as a #string if only one type.
|
||||||
|
-- @param #number Performance Performance describing how good this mission can be performed. Higher is better. Default 50. Max 100.
|
||||||
-- @return #SQUADRON self
|
-- @return #SQUADRON self
|
||||||
function SQUADRON:SetMissonTypes(MissionTypes)
|
function SQUADRON:AddMissonCapability(MissionTypes, Performance)
|
||||||
|
|
||||||
-- Ensure Missiontypes is a table.
|
-- Ensure Missiontypes is a table.
|
||||||
if MissionTypes and type(MissionTypes)~="table" then
|
if MissionTypes and type(MissionTypes)~="table" then
|
||||||
@@ -233,11 +234,18 @@ function SQUADRON:SetMissonTypes(MissionTypes)
|
|||||||
|
|
||||||
-- Add ORBIT for all.
|
-- Add ORBIT for all.
|
||||||
if not self:CheckMissionType(AUFTRAG.Type.ORBIT, MissionTypes) then
|
if not self:CheckMissionType(AUFTRAG.Type.ORBIT, MissionTypes) then
|
||||||
table.insert(MissionTypes, AUFTRAG.Type.ORBIT)
|
--table.insert(MissionTypes, AUFTRAG.Type.ORBIT)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set table.
|
-- Set table.
|
||||||
self.missiontypes=MissionTypes
|
self.missiontypes=self.missiontypes or {} --MissionTypes
|
||||||
|
|
||||||
|
for _,missiontype in pairs(MissionTypes) do
|
||||||
|
local capability={} --Ops.Auftrag#AUFTRAG.Capability
|
||||||
|
capability.MissionType=missiontype
|
||||||
|
capability.Performance=Performance
|
||||||
|
table.insert(self.missiontypes, capability)
|
||||||
|
end
|
||||||
|
|
||||||
self:I(self.missiontypes)
|
self:I(self.missiontypes)
|
||||||
|
|
||||||
@@ -293,6 +301,23 @@ function SQUADRON:SetAirwing(Airwing)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- This squadron can do recue helo operations for boat ops.
|
||||||
|
-- @param #SQUADRON self
|
||||||
|
-- @return #SQUADRON self
|
||||||
|
function SQUADRON:SetCanRescueHelo()
|
||||||
|
self.canrescuehelo=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- This squadron can do recovery tanker operations for boat ops.
|
||||||
|
-- @param #SQUADRON self
|
||||||
|
-- @return #SQUADRON self
|
||||||
|
function SQUADRON:SetCanRescueHelo()
|
||||||
|
self.canrecoverytanker=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Add airwing asset to squadron.
|
--- Add airwing asset to squadron.
|
||||||
-- @param #SQUADRON self
|
-- @param #SQUADRON self
|
||||||
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
|
||||||
@@ -475,9 +500,7 @@ end
|
|||||||
function SQUADRON:_CheckAssetStatus()
|
function SQUADRON:_CheckAssetStatus()
|
||||||
|
|
||||||
for _,_asset in pairs(self.assets) do
|
for _,_asset in pairs(self.assets) do
|
||||||
local asset=_asset --#SQUADRON.Flight
|
local asset=_asset
|
||||||
|
|
||||||
flight.flightgroup:IsSpawned()
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -516,7 +539,7 @@ function SQUADRON:CanMission(Mission)
|
|||||||
|
|
||||||
-- On duty?=
|
-- On duty?=
|
||||||
if not self:IsOnDuty() then
|
if not self:IsOnDuty() then
|
||||||
self:I(self.lid..string.format("Sqaud in not OnDuty but in state %s", self:GetState()))
|
self:I(self.lid..string.format("Squad in not OnDuty but in state %s", self:GetState()))
|
||||||
return false, assets
|
return false, assets
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -560,10 +583,8 @@ function SQUADRON:CanMission(Mission)
|
|||||||
|
|
||||||
-- Check if the payload of this asset is compatible with the mission.
|
-- Check if the payload of this asset is compatible with the mission.
|
||||||
-- Note: we do not check the payload as an asset that is on a PATROL mission should be able to do an intercept as well!
|
-- Note: we do not check the payload as an asset that is on a PATROL mission should be able to do an intercept as well!
|
||||||
--if self:CheckMissionType(Mission.type, asset.payload.missiontypes) then
|
-- TODO: Check if asset actually has weapons left. Difficult!
|
||||||
-- TODO: Check if asset actually has weapons left. Difficult!
|
table.insert(assets, asset)
|
||||||
table.insert(assets, asset)
|
|
||||||
--end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -600,7 +621,7 @@ function SQUADRON:CanMission(Mission)
|
|||||||
-- Asset is still in STOCK
|
-- Asset is still in STOCK
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Check that asset is not already requeseted for another mission.
|
-- Check that asset is not already requested for another mission.
|
||||||
if not asset.requested then
|
if not asset.requested then
|
||||||
|
|
||||||
-- Check if we got a payload and reserve it for this asset.
|
-- Check if we got a payload and reserve it for this asset.
|
||||||
|
|||||||
@@ -392,32 +392,6 @@ function WINGCOMMANDER:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Create missions for all new contacts.
|
|
||||||
--[[
|
|
||||||
for _,_contact in pairs(self.ContactsUnknown) do
|
|
||||||
local contact=_contact --#WINGCOMMANDER.Contact
|
|
||||||
local group=contact.group --Wrapper.Group#GROUP
|
|
||||||
|
|
||||||
-- Create a mission based on group category.
|
|
||||||
local mission=AUFTRAG:NewAUTO(group)
|
|
||||||
|
|
||||||
|
|
||||||
-- Add mission to queue.
|
|
||||||
if mission then
|
|
||||||
|
|
||||||
--TODO: Better amount of necessary assets. Count units in asset and in contact. Might need nassetMin/Max.
|
|
||||||
mission.nassets=1
|
|
||||||
|
|
||||||
-- Set mission contact.
|
|
||||||
contact.mission=mission
|
|
||||||
|
|
||||||
-- Add mission to queue.
|
|
||||||
self:AddMission(mission)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- Create missions for all new contacts.
|
-- Create missions for all new contacts.
|
||||||
local Nred=0
|
local Nred=0
|
||||||
local Nyellow=0
|
local Nyellow=0
|
||||||
|
|||||||
@@ -0,0 +1,345 @@
|
|||||||
|
--- **Wrapper** - Markers On the F10 map.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Manage aircraft recovery.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
-- @module Wrapper.Marker
|
||||||
|
-- @image Wrapper_Marker.png
|
||||||
|
|
||||||
|
|
||||||
|
--- Marker class.
|
||||||
|
-- @type MARKER
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||||
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
|
-- @field #number mid Marker ID.
|
||||||
|
-- @field Core.Point#COORDINATE coordinate Coordinate of the mark.
|
||||||
|
-- @field #string text Text displayed in the mark panel.
|
||||||
|
-- @field #string message Message dispayed when the mark is added.
|
||||||
|
-- @field #boolean readonly Marker is read-only.
|
||||||
|
-- @field #number coalition Coalition to which the marker is displayed.
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
--- **Ground Control**: Airliner X, Good news, you are clear to taxi to the active.
|
||||||
|
-- **Pilot**: Roger, What's the bad news?
|
||||||
|
-- **Ground Control**: No bad news at the moment, but you probably want to get gone before I find any.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
|
-- # The MARKER Concept
|
||||||
|
--
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #MARKER
|
||||||
|
MARKER = {
|
||||||
|
ClassName = "MARKER",
|
||||||
|
Debug = false,
|
||||||
|
lid = nil,
|
||||||
|
mid = nil,
|
||||||
|
coordinate = nil,
|
||||||
|
text = nil,
|
||||||
|
message = nil,
|
||||||
|
readonly = nil,
|
||||||
|
coalition = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Holding point
|
||||||
|
-- @type MARKER.HoldingPoint
|
||||||
|
-- @field Core.Point#COORDINATE pos0 First poosition of racetrack holding point.
|
||||||
|
-- @field Core.Point#COORDINATE pos1 Second position of racetrack holding point.
|
||||||
|
-- @field #number angelsmin Smallest holding altitude in angels.
|
||||||
|
-- @field #number angelsmax Largest holding alitude in angels.
|
||||||
|
|
||||||
|
|
||||||
|
--- Marker class version.
|
||||||
|
-- @field #string version
|
||||||
|
MARKER.version="0.0.1"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- TODO list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Handle events.
|
||||||
|
-- TODO: Some more...
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new MARKER class object.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
|
||||||
|
-- @param #string Text Text displayed on the mark panel.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:New(Coordinate, Text)
|
||||||
|
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
||||||
|
|
||||||
|
self.coordinate=Coordinate
|
||||||
|
|
||||||
|
self.text=Text
|
||||||
|
|
||||||
|
-- Defaults
|
||||||
|
self.readonly=false
|
||||||
|
self.message=""
|
||||||
|
|
||||||
|
-- Get ID.
|
||||||
|
self.mid=UTILS.GetMarkID()
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Stopped")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("*", "Added", "Shown") -- Marker was added.
|
||||||
|
self:AddTransition("*", "Removed", "Shown") -- Marker was added.
|
||||||
|
|
||||||
|
self:AddTransition("*", "Change", "*") -- Update status.
|
||||||
|
|
||||||
|
-- Handle events.
|
||||||
|
self:HandleEvent(EVENTS.MarkAdded)
|
||||||
|
self:HandleEvent(EVENTS.MarkRemoved)
|
||||||
|
self:HandleEvent(EVENTS.MarkChange)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- User API Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Marker is readonly.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ReadOnly()
|
||||||
|
|
||||||
|
self.readonly=true
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Marker is readonly.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text Message displayed when the marker is added.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Message(Text)
|
||||||
|
|
||||||
|
self.message=Text or ""
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for everyone.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToAll()
|
||||||
|
|
||||||
|
self.toall=true
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for a specific coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Coalition Coalition 1=Red, 2=Blue, 0=Neutral. See `coaliton.side.RED`.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToCoalition(Coalition)
|
||||||
|
|
||||||
|
self.coalition=Coalition
|
||||||
|
|
||||||
|
self.tocoaliton=true
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the blue coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToBlue()
|
||||||
|
self:ToCoalition(coalition.side.BLUE)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the blue coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToRed()
|
||||||
|
self:ToCoalition(coalition.side.RED)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the neutral coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToNeutral()
|
||||||
|
self:ToCoalition(coalition.side.NEUTRAL)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Place marker visible for a specific group only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Wrapper.Group#GROUP Group The group to which te
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToGroup(Group)
|
||||||
|
|
||||||
|
-- Check if group exists.
|
||||||
|
if Group and Group:IsAlive()~=nil then
|
||||||
|
|
||||||
|
self.groupid=Group:GetID()
|
||||||
|
|
||||||
|
if self.groupid then
|
||||||
|
|
||||||
|
self.groupname=Group:GetName()
|
||||||
|
|
||||||
|
self.togroup=true
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
--TODO: Warning!
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update the text displayed on the mark panel.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text Updated text.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:UpdateText(Text)
|
||||||
|
|
||||||
|
self.text=Text
|
||||||
|
|
||||||
|
self:Refresh()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update the coordinate where the marker is displayed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The new coordinate.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:UpdateCoordinate(Coordinate)
|
||||||
|
|
||||||
|
self.coordinate=Coordinate
|
||||||
|
|
||||||
|
self:Refresh()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Refresh the marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Refresh()
|
||||||
|
|
||||||
|
if self.toall then
|
||||||
|
|
||||||
|
self:ToAll()
|
||||||
|
|
||||||
|
elseif self.tocoaliton then
|
||||||
|
|
||||||
|
self:ToCoalition(self.coalition)
|
||||||
|
|
||||||
|
elseif self.togroup then
|
||||||
|
|
||||||
|
local group=GROUP:FindByName(self.groupname)
|
||||||
|
|
||||||
|
self:ToGroup(group)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Remove()
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.removeMark(self.mid)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Event function when a MARKER is added.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkAdded(EventData)
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
self.shown=true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event function when a MARKER is removed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkRemoved(EventData)
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
self.shown=false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event function when a MARKER changed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkChange(EventData)
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
Reference in New Issue
Block a user