mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge branch 'FF/Ops' into FF/OpsDev
This commit is contained in:
commit
cb0f453a8d
926
Moose Development/Moose/Functional/Autolase.lua
Normal file
926
Moose Development/Moose/Functional/Autolase.lua
Normal file
@ -0,0 +1,926 @@
|
|||||||
|
--- **Functional** - Autolase targets in the field.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- **AUOTLASE** - Autolase targets in the field.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Missions:
|
||||||
|
--
|
||||||
|
-- ### [Autolase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/)
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Detect and lase contacts automatically
|
||||||
|
-- * Targets are lased by threat priority order
|
||||||
|
-- * Use FSM events to link functionality into your scripts
|
||||||
|
-- * Easy setup
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
--- Spot on!
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # 1 Autolase concept
|
||||||
|
--
|
||||||
|
-- * Detect and lase contacts automatically
|
||||||
|
-- * Targets are lased by threat priority order
|
||||||
|
-- * Use FSM events to link functionality into your scripts
|
||||||
|
-- * Easy set-up
|
||||||
|
--
|
||||||
|
-- # 2 Basic usage
|
||||||
|
--
|
||||||
|
-- ## 2.2 Set up a group of Recce Units:
|
||||||
|
--
|
||||||
|
-- local FoxSet = SET_GROUP:New():FilterPrefixes("Recce"):FilterCoalitions("blue"):FilterStart()
|
||||||
|
--
|
||||||
|
-- ## 2.3 (Optional) Set up a group of pilots, this will drive who sees the F10 menu entry:
|
||||||
|
--
|
||||||
|
-- local Pilotset = SET_CLIENT:New():FilterCoalitions("blue"):FilterActive(true):FilterStart()
|
||||||
|
--
|
||||||
|
-- ## 2.4 Set up and start Autolase:
|
||||||
|
--
|
||||||
|
-- local autolaser = AUTOLASE:New(FoxSet,coalition.side.BLUE,"Wolfpack",Pilotset)
|
||||||
|
--
|
||||||
|
-- ## 2.5 Example - Using a fixed laser code for a specific Recce unit:
|
||||||
|
--
|
||||||
|
-- local recce = SPAWN:New("Reaper")
|
||||||
|
-- :InitDelayOff()
|
||||||
|
-- :OnSpawnGroup(
|
||||||
|
-- function (group)
|
||||||
|
-- local unit = group:GetUnit(1)
|
||||||
|
-- local name = unit:GetName()
|
||||||
|
-- autolaser:SetRecceLaserCode(name,1688)
|
||||||
|
-- end
|
||||||
|
-- )
|
||||||
|
-- :InitCleanUp(60)
|
||||||
|
-- :InitLimit(1,0)
|
||||||
|
-- :SpawnScheduled(30,0.5)
|
||||||
|
--
|
||||||
|
-- ## 2.6 Example - Inform pilots about events:
|
||||||
|
--
|
||||||
|
-- autolaser:SetNotifyPilots(true) -- defaults to true, also shown if debug == true
|
||||||
|
-- -- Note - message are shown to pilots in the #SET_CLIENT only if using the pilotset option, else to the coalition.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- ### Author: **applevangelist**
|
||||||
|
-- @module Functional.Autolase
|
||||||
|
-- @image Designation.JPG
|
||||||
|
--
|
||||||
|
-- Date: Oct 2021
|
||||||
|
--
|
||||||
|
--- Class AUTOLASE
|
||||||
|
-- @type AUTOLASE
|
||||||
|
-- @field #string ClassName
|
||||||
|
-- @field #string lid
|
||||||
|
-- @field #number verbose
|
||||||
|
-- @field #string alias
|
||||||
|
-- @field #boolean debug
|
||||||
|
-- @field #string version
|
||||||
|
-- @extends Ops.Intel#INTEL
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @field #AUTOLASE
|
||||||
|
AUTOLASE = {
|
||||||
|
ClassName = "AUTOLASE",
|
||||||
|
lid = "",
|
||||||
|
verbose = 0,
|
||||||
|
alias = "",
|
||||||
|
debug = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Laser spot info
|
||||||
|
-- @type AUTOLASE.LaserSpot
|
||||||
|
-- @field Core.Spot#SPOT laserspot
|
||||||
|
-- @field Wrapper.Unit#UNIT lasedunit
|
||||||
|
-- @field Wrapper.Unit#UNIT lasingunit
|
||||||
|
-- @field #number lasercode
|
||||||
|
-- @field #string location
|
||||||
|
-- @field #number timestamp
|
||||||
|
-- @field #string unitname
|
||||||
|
-- @field #string reccename
|
||||||
|
-- @field #string unittype
|
||||||
|
|
||||||
|
--- AUTOLASE class version.
|
||||||
|
-- @field #string version
|
||||||
|
AUTOLASE.version = "0.0.8"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- Begin Functional.Autolase.lua
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Constructor for a new Autolase instance.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param Core.Set#SET_GROUP RecceSet Set of detecting and lasing units
|
||||||
|
-- @param #number Coalition Coalition side. Can also be passed as a string "red", "blue" or "neutral".
|
||||||
|
-- @param #string Alias (Optional) An alias how this object is called in the logs etc.
|
||||||
|
-- @param Core.Set#SET_CLIENT PilotSet (Optional) Set of clients for precision bombing, steering menu creation. Leave nil for a coalition-wide F10 entry and display.
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
|
||||||
|
BASE:T({RecceSet, Coalition, Alias, PilotSet})
|
||||||
|
|
||||||
|
-- Inherit everything from BASE class.
|
||||||
|
local self=BASE:Inherit(self, BASE:New()) -- #AUTOLASE
|
||||||
|
|
||||||
|
if Coalition and type(Coalition)=="string" then
|
||||||
|
if Coalition=="blue" then
|
||||||
|
self.coalition=coalition.side.BLUE
|
||||||
|
elseif Coalition=="red" then
|
||||||
|
self.coalition=coalition.side.RED
|
||||||
|
elseif Coalition=="neutral" then
|
||||||
|
self.coalition=coalition.side.NEUTRAL
|
||||||
|
else
|
||||||
|
self:E("ERROR: Unknown coalition in AUTOLASE!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set alias.
|
||||||
|
if Alias then
|
||||||
|
self.alias=tostring(Alias)
|
||||||
|
else
|
||||||
|
self.alias="Lion"
|
||||||
|
if self.coalition then
|
||||||
|
if self.coalition==coalition.side.RED then
|
||||||
|
self.alias="Wolf"
|
||||||
|
elseif self.coalition==coalition.side.BLUE then
|
||||||
|
self.alias="Fox"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- inherit from INTEL
|
||||||
|
local self=BASE:Inherit(self, INTEL:New(RecceSet, Coalition, Alias)) -- #AUTOLASE
|
||||||
|
|
||||||
|
self.RecceSet = RecceSet
|
||||||
|
self.DetectVisual = true
|
||||||
|
self.DetectOptical = true
|
||||||
|
self.DetectRadar = true
|
||||||
|
self.DetectIRST = true
|
||||||
|
self.DetectRWR = true
|
||||||
|
self.DetectDLINK = true
|
||||||
|
self.LaserCodes = UTILS.GenerateLaserCodes()
|
||||||
|
self.LaseDistance = 5000
|
||||||
|
self.LaseDuration = 300
|
||||||
|
self.GroupsByThreat = {}
|
||||||
|
self.UnitsByThreat = {}
|
||||||
|
self.RecceNames = {}
|
||||||
|
self.RecceLaserCode = {}
|
||||||
|
self.RecceUnitNames= {}
|
||||||
|
self.maxlasing = 4
|
||||||
|
self.CurrentLasing = {}
|
||||||
|
self.lasingindex = 0
|
||||||
|
self.deadunitnotes = {}
|
||||||
|
self.usepilotset = false
|
||||||
|
self.reporttimeshort = 10
|
||||||
|
self.reporttimelong = 30
|
||||||
|
self.smoketargets = false
|
||||||
|
self.smokecolor = SMOKECOLOR.Red
|
||||||
|
self.notifypilots = true
|
||||||
|
self.targetsperrecce = {}
|
||||||
|
self.RecceUnits = {}
|
||||||
|
self.forcecooldown = true
|
||||||
|
self.cooldowntime = 60
|
||||||
|
self.useSRS = false
|
||||||
|
self.SRSPath = ""
|
||||||
|
self.SRSFreq = 251
|
||||||
|
self.SRSMod = radio.modulation.AM
|
||||||
|
|
||||||
|
-- Set some string id for output to DCS.log file.
|
||||||
|
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("*", "Monitor", "*") -- Start FSM
|
||||||
|
self:AddTransition("*", "Lasing", "*") -- Lasing target
|
||||||
|
self:AddTransition("*", "TargetLost", "*") -- Lost target
|
||||||
|
self:AddTransition("*", "TargetDestroyed", "*") -- Target destroyed
|
||||||
|
self:AddTransition("*", "RecceKIA", "*") -- Recce KIA
|
||||||
|
self:AddTransition("*", "LaserTimeout", "*") -- Laser timed out
|
||||||
|
self:AddTransition("*", "Cancel", "*") -- Stop Autolase
|
||||||
|
|
||||||
|
-- Menu Entry
|
||||||
|
if not PilotSet then
|
||||||
|
self.Menu = MENU_COALITION_COMMAND:New(self.coalition,"Autolase",nil,self.ShowStatus,self)
|
||||||
|
else
|
||||||
|
self.usepilotset = true
|
||||||
|
self.pilotset = PilotSet
|
||||||
|
self:HandleEvent(EVENTS.PlayerEnterAircraft)
|
||||||
|
self:SetPilotMenu()
|
||||||
|
end
|
||||||
|
|
||||||
|
self:SetClusterAnalysis(false, false)
|
||||||
|
|
||||||
|
self:__Start(2)
|
||||||
|
self:__Monitor(math.random(5,10))
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
--- Pseudo Functions ---
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Monitor".
|
||||||
|
-- @function [parent=#AUTOLASE] Status
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Monitor" after a delay.
|
||||||
|
-- @function [parent=#AUTOLASE] __Status
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Cancel".
|
||||||
|
-- @function [parent=#AUTOLASE] Cancel
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Cancel" after a delay.
|
||||||
|
-- @function [parent=#AUTOLASE] __Cancel
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- On After "RecceKIA" event.
|
||||||
|
-- @function [parent=#AUTOLASE] OnAfterRecceKIA
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string RecceName The lost Recce
|
||||||
|
|
||||||
|
--- On After "TargetDestroyed" event.
|
||||||
|
-- @function [parent=#AUTOLASE] OnAfterTargetDestroyed
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The destroyed unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
|
||||||
|
--- On After "TargetLost" event.
|
||||||
|
-- @function [parent=#AUTOLASE] OnAfterTargetLost
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The lost unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
|
||||||
|
--- On After "LaserTimeout" event.
|
||||||
|
-- @function [parent=#AUTOLASE] OnAfterLaserTimeout
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The lost unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
|
||||||
|
--- On After "Lasing" event.
|
||||||
|
-- @function [parent=#AUTOLASE] OnAfterLasing
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param Functional.Autolase#AUTOLASE.LaserSpot LaserSpot The LaserSpot data table
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- Helper Functions
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- (Internal) Function to set pilot menu.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetPilotMenu()
|
||||||
|
local pilottable = self.pilotset:GetSetObjects() or {}
|
||||||
|
for _,_unit in pairs (pilottable) do
|
||||||
|
local Unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
if Unit and Unit:IsAlive() then
|
||||||
|
local Group = Unit:GetGroup()
|
||||||
|
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group)
|
||||||
|
lasemenu:Refresh()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Event function for new pilots.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:OnEventPlayerEnterAircraft(EventData)
|
||||||
|
self:SetPilotMenu()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to get a laser code by recce name
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string RecceName Unit(!) name of the Recce
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:GetLaserCode(RecceName)
|
||||||
|
local code = 1688
|
||||||
|
if self.RecceLaserCode[RecceName] == nil then
|
||||||
|
code = self.LaserCodes[math.random(#self.LaserCodes)]
|
||||||
|
self.RecceLaserCode[RecceName] = code
|
||||||
|
else
|
||||||
|
code = self.RecceLaserCode[RecceName]
|
||||||
|
end
|
||||||
|
return code
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function enable sending messages via SRS.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #boolean OnOff Switch usage on and off
|
||||||
|
-- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalon
|
||||||
|
-- @param #number Frequency Frequency to send, e.g. 243
|
||||||
|
-- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation)
|
||||||
|
self.useSRS = OnOff or true
|
||||||
|
self.SRSPath = Path or "E:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
|
self.SRSFreq = Frequency or 271
|
||||||
|
self.SRSMod = Modulation or radio.modulation.AM
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function set max lasing targets
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number Number Max number of targets to lase at once
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetMaxLasingTargets(Number)
|
||||||
|
self.maxlasing = Number or 4
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function set notify pilots on events
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #boolean OnOff Switch messaging on (true) or off (false)
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetNotifyPilots(OnOff)
|
||||||
|
self.notifypilots = OnOff and true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function to set a specific code to a Recce.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string RecceName (Unit!) Name of the Recce
|
||||||
|
-- @param #number Code The lase code
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetRecceLaserCode(RecceName, Code)
|
||||||
|
local code = Code or 1688
|
||||||
|
self.RecceLaserCode[RecceName] = code
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function to force laser cooldown and cool down time
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #boolean OnOff Switch cool down on (true) or off (false) - defaults to true
|
||||||
|
-- @param #number Seconds Number of seconds for cooldown - dafaults to 60 seconds
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetLaserCoolDown(OnOff, Seconds)
|
||||||
|
self.forcecooldown = OnOff and true
|
||||||
|
self.cooldowntime = Seconds or 60
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function to set message show times.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number long Longer show time
|
||||||
|
-- @param #number short Shorter show time
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetReportingTimes(long, short)
|
||||||
|
self.reporttimeshort = short or 10
|
||||||
|
self.reporttimelong = long or 30
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function to set lasing distance in meters and duration in seconds
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number Distance (Max) distance for lasing in meters - default 5000 meters
|
||||||
|
-- @param #number Duration (Max) duration for lasing in seconds - default 300 secs
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetLasingParameters(Distance, Duration)
|
||||||
|
self.LaseDistance = Distance or 5000
|
||||||
|
self.LaseDuration = Duration or 300
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Function to set smoking of targets.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #boolean OnOff Switch smoking on or off
|
||||||
|
-- @param #number Color Smokecolor, e.g. SMOKECOLOR.Red
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetSmokeTargets(OnOff,Color)
|
||||||
|
self.smoketargets = OnOff
|
||||||
|
self.smokecolor = Color or SMOKECOLOR.Red
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to calculate line of sight.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
|
-- @return #number LOS Line of sight in meters
|
||||||
|
function AUTOLASE:GetLosFromUnit(Unit)
|
||||||
|
local lasedistance = self.LaseDistance
|
||||||
|
local unitheight = Unit:GetHeight()
|
||||||
|
local coord = Unit:GetCoordinate()
|
||||||
|
local landheight = coord:GetLandHeight()
|
||||||
|
local asl = unitheight - landheight
|
||||||
|
if asl > 100 then
|
||||||
|
local absquare = lasedistance^2+asl^2
|
||||||
|
lasedistance = math.sqrt(absquare)
|
||||||
|
end
|
||||||
|
return lasedistance
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to check on lased targets.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:CleanCurrentLasing()
|
||||||
|
local lasingtable = self.CurrentLasing
|
||||||
|
local newtable = {}
|
||||||
|
local newreccecount = {}
|
||||||
|
local lasing = 0
|
||||||
|
|
||||||
|
for _ind,_entry in pairs(lasingtable) do
|
||||||
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
||||||
|
if not newreccecount[entry.reccename] then
|
||||||
|
newreccecount[entry.reccename] = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,_recce in pairs (self.RecceSet:GetSetObjects()) do
|
||||||
|
local recce = _recce --Wrapper.Group#GROUP
|
||||||
|
if recce and recce:IsAlive() then
|
||||||
|
local unit = recce:GetUnit(1)
|
||||||
|
local name = unit:GetName()
|
||||||
|
if not self.RecceUnits[name] then
|
||||||
|
self.RecceUnits[name] = { name=name, unit=unit, cooldown = false, timestamp = timer.getAbsTime() }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _ind,_entry in pairs(lasingtable) do
|
||||||
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
||||||
|
local valid = 0
|
||||||
|
local reccedead = false
|
||||||
|
local unitdead = false
|
||||||
|
local lostsight = false
|
||||||
|
local timeout = false
|
||||||
|
local Tnow = timer.getAbsTime()
|
||||||
|
-- check recce dead
|
||||||
|
local recce = entry.lasingunit
|
||||||
|
if recce and recce:IsAlive() then
|
||||||
|
valid = valid + 1
|
||||||
|
else
|
||||||
|
reccedead = true
|
||||||
|
self:__RecceKIA(2,entry.reccename)
|
||||||
|
end
|
||||||
|
-- check entry dead
|
||||||
|
local unit = entry.lasedunit
|
||||||
|
if unit and unit:IsAlive() == true then
|
||||||
|
valid = valid + 1
|
||||||
|
else
|
||||||
|
unitdead = true
|
||||||
|
if not self.deadunitnotes[entry.unitname] then
|
||||||
|
self.deadunitnotes[entry.unitname] = true
|
||||||
|
self:__TargetDestroyed(2,entry.unitname,entry.reccename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- check entry out of sight
|
||||||
|
if not reccedead and not unitdead then
|
||||||
|
if self:CanLase(recce,unit) then
|
||||||
|
valid = valid + 1
|
||||||
|
else
|
||||||
|
lostsight = true
|
||||||
|
entry.laserspot:LaseOff()
|
||||||
|
self:__TargetLost(2,entry.unitname,entry.reccename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- check timed out
|
||||||
|
local timestamp = entry.timestamp
|
||||||
|
if Tnow - timestamp < self.LaseDuration and not lostsight then
|
||||||
|
valid = valid + 1
|
||||||
|
else
|
||||||
|
timeout = true
|
||||||
|
entry.laserspot:LaseOff()
|
||||||
|
|
||||||
|
self.RecceUnits[entry.reccename].cooldown = true
|
||||||
|
self.RecceUnits[entry.reccename].timestamp = timer.getAbsTime()
|
||||||
|
|
||||||
|
if not lostsight then
|
||||||
|
self:__LaserTimeout(2,entry.unitname,entry.reccename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if valid == 4 then
|
||||||
|
self.lasingindex = self.lasingindex + 1
|
||||||
|
newtable[self.lasingindex] = entry
|
||||||
|
newreccecount[entry.reccename] = newreccecount[entry.reccename] + 1
|
||||||
|
lasing = lasing + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.CurrentLasing = newtable
|
||||||
|
self.targetsperrecce = newreccecount
|
||||||
|
return lasing
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to show status.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param Wrapper.Group#GROUP Group (Optional) show to a certain group
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:ShowStatus(Group)
|
||||||
|
local report = REPORT:New("Autolase")
|
||||||
|
local reccetable = self.RecceSet:GetSetObjects()
|
||||||
|
for _,_recce in pairs(reccetable) do
|
||||||
|
if _recce and _recce:IsAlive() then
|
||||||
|
local unit = _recce:GetUnit(1)
|
||||||
|
local name = unit:GetName()
|
||||||
|
local code = self:GetLaserCode(name)
|
||||||
|
report:Add(string.format("Recce %s has code %d",name,code))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local lines = 0
|
||||||
|
for _ind,_entry in pairs(self.CurrentLasing) do
|
||||||
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
||||||
|
local reccename = entry.reccename
|
||||||
|
local typename = entry.unittype
|
||||||
|
local code = entry.lasercode
|
||||||
|
local locationstring = entry.location
|
||||||
|
local text = string.format("%s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
|
||||||
|
report:Add(text)
|
||||||
|
lines = lines + 1
|
||||||
|
end
|
||||||
|
if lines == 0 then
|
||||||
|
report:Add("No targets!")
|
||||||
|
end
|
||||||
|
local reporttime = self.reporttimelong
|
||||||
|
if lines == 0 then reporttime = self.reporttimeshort end
|
||||||
|
if Group and Group:IsAlive() then
|
||||||
|
local m = MESSAGE:New(report:Text(),reporttime,"Info"):ToGroup(Group)
|
||||||
|
else
|
||||||
|
local m = MESSAGE:New(report:Text(),reporttime,"Info"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to show messages.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string Message The message to be sent
|
||||||
|
-- @param #number Duration Duration in seconds
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:NotifyPilots(Message,Duration)
|
||||||
|
if self.usepilotset then
|
||||||
|
local pilotset = self.pilotset:GetSetObjects() --#table
|
||||||
|
for _,_pilot in pairs(pilotset) do
|
||||||
|
local pilot = _pilot -- Wrapper.Unit#UNIT
|
||||||
|
if pilot and pilot:IsAlive() then
|
||||||
|
local Group = pilot:GetGroup()
|
||||||
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToGroup(Group)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif not self.debug then
|
||||||
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToCoalition(self.coalition)
|
||||||
|
else
|
||||||
|
local m = MESSAGE:New(Message,Duration,"Autolase"):ToAll()
|
||||||
|
end
|
||||||
|
if self.debug then self:I(Message) end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User) Send messages via SRS.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string Message The (short!) message to be sent, e.g. "Lasing target!"
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
-- @usage Step 1 - set up the radio basics **once** with
|
||||||
|
-- my_autolase:SetUsingSRS(true,"C:\\path\\SRS-Folder",251,radio.modulation.AM)
|
||||||
|
-- Step 2 - send a message, e.g.
|
||||||
|
-- function my_autolase:OnAfterLasing(From, Event, To, LaserSpot)
|
||||||
|
-- my_autolase:NotifyPilotsWithSRS("Reaper lasing new target!")
|
||||||
|
-- end
|
||||||
|
function AUTOLASE:NotifyPilotsWithSRS(Message)
|
||||||
|
if self.useSRS then
|
||||||
|
-- Create a SOUNDTEXT object.
|
||||||
|
if self.debug then
|
||||||
|
BASE:TraceOn()
|
||||||
|
BASE:TraceClass("SOUNDTEXT")
|
||||||
|
BASE:TraceClass("MSRS")
|
||||||
|
end
|
||||||
|
local path = self.SRSPath or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
|
local freq = self.SRSFreq or 271
|
||||||
|
local mod = self.SRSMod or radio.modulation.AM
|
||||||
|
local text=SOUNDTEXT:New(Message)
|
||||||
|
-- MOOSE SRS
|
||||||
|
local msrs=MSRS:New(path, freq, mod)
|
||||||
|
-- Text-to speech with default voice after 2 seconds.
|
||||||
|
msrs:PlaySoundText(text, 2)
|
||||||
|
end
|
||||||
|
if self.debug then self:I(Message) end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to check if a unit is already lased.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string unitname Name of the unit to check
|
||||||
|
-- @return #boolean outcome True or false
|
||||||
|
function AUTOLASE:CheckIsLased(unitname)
|
||||||
|
local outcome = false
|
||||||
|
for _,_laserspot in pairs(self.CurrentLasing) do
|
||||||
|
local spot = _laserspot -- #AUTOLASE.LaserSpot
|
||||||
|
if spot.unitname == unitname then
|
||||||
|
outcome = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return outcome
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to check if a unit can be lased.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param Wrapper.Unit#UNIT Recce The Recce #UNIT
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The lased #UNIT
|
||||||
|
-- @return #boolean outcome True or false
|
||||||
|
function AUTOLASE:CanLase(Recce,Unit)
|
||||||
|
local canlase = false
|
||||||
|
-- cooldown?
|
||||||
|
local name = Recce:GetName()
|
||||||
|
local cooldown = self.RecceUnits[name].cooldown and self.forcecooldown
|
||||||
|
if cooldown then
|
||||||
|
local Tdiff = timer.getAbsTime() - self.RecceUnits[name].timestamp
|
||||||
|
if Tdiff < self.cooldowntime then
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
self.RecceUnits[name].cooldown = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- calculate LOS
|
||||||
|
local reccecoord = Recce:GetCoordinate()
|
||||||
|
local unitcoord = Unit:GetCoordinate()
|
||||||
|
local islos = reccecoord:IsLOS(unitcoord,2.5)
|
||||||
|
-- calculate distance
|
||||||
|
local distance = math.floor(reccecoord:Get3DDistance(unitcoord))
|
||||||
|
local lasedistance = self:GetLosFromUnit(Recce)
|
||||||
|
if distance <= lasedistance and islos then
|
||||||
|
canlase = true
|
||||||
|
end
|
||||||
|
return canlase
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- FSM Functions
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- (Internal) FSM Function for monitoring
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeMonitor(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
-- Check if group has detected any units.
|
||||||
|
self:UpdateIntel()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function for monitoring
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onafterMonitor(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
|
||||||
|
-- Housekeeping
|
||||||
|
local countlases = self:CleanCurrentLasing()
|
||||||
|
|
||||||
|
self:SetPilotMenu()
|
||||||
|
|
||||||
|
local detecteditems = self.Contacts or {} -- #table of Ops.Intelligence#INTEL.Contact
|
||||||
|
local groupsbythreat = {}
|
||||||
|
local report = REPORT:New("Detections")
|
||||||
|
local lines = 0
|
||||||
|
for _,_contact in pairs(detecteditems) do
|
||||||
|
local contact = _contact -- Ops.Intelligence#INTEL.Contact
|
||||||
|
local grp = contact.group
|
||||||
|
local coord = contact.position
|
||||||
|
local reccename = contact.recce
|
||||||
|
local reccegrp = UNIT:FindByName(reccename)
|
||||||
|
local reccecoord = reccegrp:GetCoordinate()
|
||||||
|
local distance = math.floor(reccecoord:Get3DDistance(coord))
|
||||||
|
local text = string.format("%s of %s | Distance %d km | Threatlevel %d",contact.attribute, contact.groupname, math.floor(distance/1000), contact.threatlevel)
|
||||||
|
report:Add(text)
|
||||||
|
self:T(text)
|
||||||
|
if self.debug then self:I(text) end
|
||||||
|
lines = lines + 1
|
||||||
|
-- sort out groups beyond sight
|
||||||
|
local lasedistance = self:GetLosFromUnit(reccegrp)
|
||||||
|
if grp:IsGround() and lasedistance >= distance then
|
||||||
|
table.insert(groupsbythreat,{contact.group,contact.threatlevel})
|
||||||
|
self.RecceNames[contact.groupname] = contact.recce
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.GroupsByThreat = groupsbythreat
|
||||||
|
|
||||||
|
if self.verbose > 2 and lines > 0 then
|
||||||
|
local m=MESSAGE:New(report:Text(),self.reporttimeshort,"Autolase"):ToAll()
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(self.GroupsByThreat, function(a,b)
|
||||||
|
local aNum = a[2] -- Coin value of a
|
||||||
|
local bNum = b[2] -- Coin value of b
|
||||||
|
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- build table of Units
|
||||||
|
local unitsbythreat = {}
|
||||||
|
for _,_entry in pairs(self.GroupsByThreat) do
|
||||||
|
local group = _entry[1] -- Wrapper.Group#GROUP
|
||||||
|
if group and group:IsAlive() then
|
||||||
|
local units = group:GetUnits()
|
||||||
|
local reccename = self.RecceNames[group:GetName()]
|
||||||
|
for _,_unit in pairs(units) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
local threat = unit:GetThreatLevel()
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
if threat > 0 then
|
||||||
|
local unitname = unit:GetName()
|
||||||
|
table.insert(unitsbythreat,{unit,threat})
|
||||||
|
self.RecceUnitNames[unitname] = reccename
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.UnitsByThreat = unitsbythreat
|
||||||
|
|
||||||
|
table.sort(self.UnitsByThreat, function(a,b)
|
||||||
|
local aNum = a[2] -- Coin value of a
|
||||||
|
local bNum = b[2] -- Coin value of b
|
||||||
|
return aNum > bNum -- Return their comparisons, < for ascending, > for descending
|
||||||
|
end)
|
||||||
|
|
||||||
|
local unitreport = REPORT:New("Detected Units")
|
||||||
|
|
||||||
|
local lines = 0
|
||||||
|
for _,_entry in pairs(self.UnitsByThreat) do
|
||||||
|
local threat = _entry[2]
|
||||||
|
local unit = _entry[1]
|
||||||
|
local unitname = unit:GetName()
|
||||||
|
local text = string.format("Unit %s | Threatlevel %d | Detected by %s",unitname,threat,self.RecceUnitNames[unitname])
|
||||||
|
unitreport:Add(text)
|
||||||
|
lines = lines + 1
|
||||||
|
self:T(text)
|
||||||
|
if self.debug then self:I(text) end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.verbose > 2 and lines > 0 then
|
||||||
|
local m=MESSAGE:New(unitreport:Text(),self.reporttimeshort,"Autolase"):ToAll()
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,_detectingunit in pairs(self.RecceUnits) do
|
||||||
|
|
||||||
|
local reccename = _detectingunit.name
|
||||||
|
local recce = _detectingunit.unit
|
||||||
|
local reccecount = self.targetsperrecce[reccename] or 0
|
||||||
|
local targets = 0
|
||||||
|
for _,_entry in pairs(self.UnitsByThreat) do
|
||||||
|
local unit = _entry[1] -- Wrapper.Unit#UNIT
|
||||||
|
local unitname = unit:GetName()
|
||||||
|
local canlase = self:CanLase(recce,unit)
|
||||||
|
if targets+reccecount < self.maxlasing and not self:CheckIsLased(unitname) and unit:IsAlive() and canlase then
|
||||||
|
targets = targets + 1
|
||||||
|
local code = self:GetLaserCode(reccename)
|
||||||
|
local spot = SPOT:New(recce)
|
||||||
|
spot:LaseOn(unit,code,self.LaseDuration)
|
||||||
|
local locationstring = unit:GetCoordinate():ToStringLLDDM()
|
||||||
|
local laserspot = { -- #AUTOLASE.LaserSpot
|
||||||
|
laserspot = spot,
|
||||||
|
lasedunit = unit,
|
||||||
|
lasingunit = recce,
|
||||||
|
lasercode = code,
|
||||||
|
location = locationstring,
|
||||||
|
timestamp = timer.getAbsTime(),
|
||||||
|
unitname = unitname,
|
||||||
|
reccename = reccename,
|
||||||
|
unittype = unit:GetTypeName(),
|
||||||
|
}
|
||||||
|
if self.smoketargets then
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
coord:Smoke(self.smokecolor)
|
||||||
|
end
|
||||||
|
self.lasingindex = self.lasingindex + 1
|
||||||
|
self.CurrentLasing[self.lasingindex] = laserspot
|
||||||
|
self:__Lasing(2,laserspot)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self:__Monitor(-30)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeRecceKIA
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string RecceName The lost Recce
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeRecceKIA(From,Event,To,RecceName)
|
||||||
|
self:T({From, Event, To, RecceName})
|
||||||
|
if self.notifypilots or self.debug then
|
||||||
|
local text = string.format("Recce %s KIA!",RecceName)
|
||||||
|
self:NotifyPilots(text,self.reporttimeshort)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeTargetDestroyed
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The destroyed unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeTargetDestroyed(From,Event,To,UnitName,RecceName)
|
||||||
|
self:T({From, Event, To, UnitName, RecceName})
|
||||||
|
if self.notifypilots or self.debug then
|
||||||
|
local text = string.format("Unit %s destroyed! Good job!",UnitName)
|
||||||
|
self:NotifyPilots(text,self.reporttimeshort)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeTargetLost
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The lost unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeTargetLost(From,Event,To,UnitName,RecceName)
|
||||||
|
self:T({From, Event, To, UnitName,RecceName})
|
||||||
|
if self.notifypilots or self.debug then
|
||||||
|
local text = string.format("%s lost sight of unit %s.",RecceName,UnitName)
|
||||||
|
self:NotifyPilots(text,self.reporttimeshort)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeLaserTimeout
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param #string UnitName The lost unit\'s name
|
||||||
|
-- @param #string RecceName The Recce name lasing
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeLaserTimeout(From,Event,To,UnitName,RecceName)
|
||||||
|
self:T({From, Event, To, UnitName,RecceName})
|
||||||
|
if self.notifypilots or self.debug then
|
||||||
|
local text = string.format("%s laser timeout on unit %s.",RecceName,UnitName)
|
||||||
|
self:NotifyPilots(text,self.reporttimeshort)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeLasing
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @param Functional.Autolase#AUTOLASE.LaserSpot LaserSpot The LaserSpot data table
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeLasing(From,Event,To,LaserSpot)
|
||||||
|
self:T({From, Event, To, LaserSpot.unittype})
|
||||||
|
if self.notifypilots or self.debug then
|
||||||
|
local laserspot = LaserSpot -- #AUTOLASE.LaserSpot
|
||||||
|
local text = string.format("%s is lasing %s code %d\nat %s",laserspot.reccename,laserspot.unittype,laserspot.lasercode,laserspot.location)
|
||||||
|
self:NotifyPilots(text,self.reporttimeshort+5)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) FSM Function onbeforeCancel
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #string From The from state
|
||||||
|
-- @param #string Event The event
|
||||||
|
-- @param #string To The to state
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:onbeforeCancel(From,Event,To)
|
||||||
|
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
||||||
|
self:__Stop(2)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
-- End Functional.Autolase.lua
|
||||||
|
-------------------------------------------------------------------
|
||||||
@ -715,20 +715,21 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
|
|
||||||
local UnitHit = EventData.TgtUnit
|
local UnitHit = EventData.TgtUnit
|
||||||
|
|
||||||
|
if UnitHit.ClassName ~= "SCENERY" then
|
||||||
-- Check if unit is inside the capture zone and that it is of the defending coalition.
|
-- Check if unit is inside the capture zone and that it is of the defending coalition.
|
||||||
if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.Coalition then
|
if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.Coalition then
|
||||||
|
|
||||||
-- Update last hit time.
|
-- Update last hit time.
|
||||||
self.HitTimeLast=timer.getTime()
|
self.HitTimeLast=timer.getTime()
|
||||||
|
|
||||||
-- Only trigger attacked event if not already in state "Attacked".
|
-- Only trigger attacked event if not already in state "Attacked".
|
||||||
if self:GetState()~="Attacked" then
|
if self:GetState()~="Attacked" then
|
||||||
self:F2("Hit ==> Attack")
|
self:F2("Hit ==> Attack")
|
||||||
self:Attack()
|
self:Attack()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -70,6 +70,7 @@ __Moose.Include( 'Scripts/Moose/Functional/Warehouse.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Functional/Autolase.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' )
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72)) (CVN-72) [Super Carrier Module]
|
-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72)) (CVN-72) [Super Carrier Module]
|
||||||
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
|
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
|
||||||
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
|
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
|
||||||
|
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59)) (CV-59) [Heatblur Carrier Module]
|
||||||
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
|
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
|
||||||
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**]
|
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**]
|
||||||
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**]
|
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**]
|
||||||
@ -1295,6 +1296,7 @@ AIRBOSS.AircraftCarrier={
|
|||||||
-- @field #string WASHINGTON USS George Washington (CVN-73) [Super Carrier Module]
|
-- @field #string WASHINGTON USS George Washington (CVN-73) [Super Carrier Module]
|
||||||
-- @field #string STENNIS USS John C. Stennis (CVN-74)
|
-- @field #string STENNIS USS John C. Stennis (CVN-74)
|
||||||
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
|
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
|
||||||
|
-- @field #string FORRESTAL USS Forrestal (CV-59) [Heatblur Carrier Module]
|
||||||
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
|
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
|
||||||
-- @field #string TARAWA USS Tarawa (LHA-1)
|
-- @field #string TARAWA USS Tarawa (LHA-1)
|
||||||
-- @field #string AMERICA USS America (LHA-6)
|
-- @field #string AMERICA USS America (LHA-6)
|
||||||
@ -1306,6 +1308,7 @@ AIRBOSS.CarrierType={
|
|||||||
WASHINGTON="CVN_73",
|
WASHINGTON="CVN_73",
|
||||||
TRUMAN="CVN_75",
|
TRUMAN="CVN_75",
|
||||||
STENNIS="Stennis",
|
STENNIS="Stennis",
|
||||||
|
FORRESTAL="Forrestal",
|
||||||
VINSON="VINSON",
|
VINSON="VINSON",
|
||||||
TARAWA="LHA_Tarawa",
|
TARAWA="LHA_Tarawa",
|
||||||
AMERICA="USS America LHA-6",
|
AMERICA="USS America LHA-6",
|
||||||
@ -1723,7 +1726,7 @@ AIRBOSS.MenuF10Root=nil
|
|||||||
|
|
||||||
--- Airboss class version.
|
--- Airboss class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRBOSS.version="1.1.6"
|
AIRBOSS.version="1.2.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -1974,6 +1977,8 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
self:_InitNimitz()
|
self:_InitNimitz()
|
||||||
elseif self.carriertype==AIRBOSS.CarrierType.TRUMAN then
|
elseif self.carriertype==AIRBOSS.CarrierType.TRUMAN then
|
||||||
self:_InitNimitz()
|
self:_InitNimitz()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.FORRESTAL then
|
||||||
|
self:_InitForrestal()
|
||||||
elseif self.carriertype==AIRBOSS.CarrierType.VINSON then
|
elseif self.carriertype==AIRBOSS.CarrierType.VINSON then
|
||||||
-- TODO: Carl Vinson parameters.
|
-- TODO: Carl Vinson parameters.
|
||||||
self:_InitStennis()
|
self:_InitStennis()
|
||||||
@ -2041,7 +2046,7 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
local stern=self:_GetSternCoord()
|
local stern=self:_GetSternCoord()
|
||||||
|
|
||||||
-- Bow pos.
|
-- Bow pos.
|
||||||
local bow=stern:Translate(self.carrierparam.totlength, hdg)
|
local bow=stern:Translate(self.carrierparam.totlength, hdg, true)
|
||||||
|
|
||||||
-- End of rwy.
|
-- End of rwy.
|
||||||
local rwy=stern:Translate(self.carrierparam.rwylength, FB, true)
|
local rwy=stern:Translate(self.carrierparam.rwylength, FB, true)
|
||||||
@ -2059,31 +2064,31 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
bow:FlareYellow()
|
bow:FlareYellow()
|
||||||
|
|
||||||
-- Runway half width = 10 m.
|
-- Runway half width = 10 m.
|
||||||
local r1=stern:Translate(self.carrierparam.rwywidth*0.5, FB+90)
|
local r1=stern:Translate(self.carrierparam.rwywidth*0.5, FB+90, true)
|
||||||
local r2=stern:Translate(self.carrierparam.rwywidth*0.5, FB-90)
|
local r2=stern:Translate(self.carrierparam.rwywidth*0.5, FB-90, true)
|
||||||
r1:FlareWhite()
|
--r1:FlareWhite()
|
||||||
r2:FlareWhite()
|
--r2:FlareWhite()
|
||||||
|
|
||||||
-- End of runway.
|
-- End of runway.
|
||||||
rwy:FlareRed()
|
rwy:FlareRed()
|
||||||
|
|
||||||
-- Right 30 meters from stern.
|
-- Right 30 meters from stern.
|
||||||
local cR=stern:Translate(self.carrierparam.totwidthstarboard, hdg+90)
|
local cR=stern:Translate(self.carrierparam.totwidthstarboard, hdg+90, true)
|
||||||
cR:FlareYellow()
|
--cR:FlareYellow()
|
||||||
|
|
||||||
-- Left 40 meters from stern.
|
-- Left 40 meters from stern.
|
||||||
local cL=stern:Translate(self.carrierparam.totwidthport, hdg-90)
|
local cL=stern:Translate(self.carrierparam.totwidthport, hdg-90, true)
|
||||||
cL:FlareYellow()
|
--cL:FlareYellow()
|
||||||
|
|
||||||
|
|
||||||
-- Carrier specific.
|
-- Carrier specific.
|
||||||
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.JCARLOS then
|
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
-- Flare wires.
|
-- Flare wires.
|
||||||
local w1=stern:Translate(self.carrierparam.wire1, FB)
|
local w1=stern:Translate(self.carrierparam.wire1, FB, true)
|
||||||
local w2=stern:Translate(self.carrierparam.wire2, FB)
|
local w2=stern:Translate(self.carrierparam.wire2, FB, true)
|
||||||
local w3=stern:Translate(self.carrierparam.wire3, FB)
|
local w3=stern:Translate(self.carrierparam.wire3, FB, true)
|
||||||
local w4=stern:Translate(self.carrierparam.wire4, FB)
|
local w4=stern:Translate(self.carrierparam.wire4, FB, true)
|
||||||
w1:FlareWhite()
|
w1:FlareWhite()
|
||||||
w2:FlareYellow()
|
w2:FlareYellow()
|
||||||
w3:FlareWhite()
|
w3:FlareWhite()
|
||||||
@ -4380,6 +4385,35 @@ function AIRBOSS:_InitNimitz()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Init parameters for Forrestal class super carriers.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
function AIRBOSS:_InitForrestal()
|
||||||
|
|
||||||
|
-- Init Nimitz as default.
|
||||||
|
self:_InitNimitz()
|
||||||
|
|
||||||
|
-- Carrier Parameters.
|
||||||
|
self.carrierparam.sterndist =-135.5
|
||||||
|
self.carrierparam.deckheight = 20 --20.1494 --DCS World OpenBeta\CoreMods\tech\USS_Nimitz\Database\USS_CVN_7X.lua
|
||||||
|
|
||||||
|
-- Total size of the carrier (approx as rectangle).
|
||||||
|
self.carrierparam.totlength=315 -- Wiki says 325 meters overall length.
|
||||||
|
self.carrierparam.totwidthport=45 -- Wiki says 73 meters overall beam.
|
||||||
|
self.carrierparam.totwidthstarboard=35
|
||||||
|
|
||||||
|
-- Landing runway.
|
||||||
|
self.carrierparam.rwyangle = -9.1359 --DCS World OpenBeta\CoreMods\tech\USS_Nimitz\scripts\USS_Nimitz_RunwaysAndRoutes.lua
|
||||||
|
self.carrierparam.rwylength = 212
|
||||||
|
self.carrierparam.rwywidth = 25
|
||||||
|
|
||||||
|
-- Wires.
|
||||||
|
self.carrierparam.wire1 = 42 -- Distance from stern to first wire.
|
||||||
|
self.carrierparam.wire2 = 51.5
|
||||||
|
self.carrierparam.wire3 = 62
|
||||||
|
self.carrierparam.wire4 = 72.5
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Init parameters for LHA-1 Tarawa carrier.
|
--- Init parameters for LHA-1 Tarawa carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
function AIRBOSS:_InitTarawa()
|
function AIRBOSS:_InitTarawa()
|
||||||
@ -10549,6 +10583,9 @@ function AIRBOSS:_GetSternCoord()
|
|||||||
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||||
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
||||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(7, FB+90, true, true)
|
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(7, FB+90, true, true)
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.FORRESTAL then
|
||||||
|
-- Forrestal
|
||||||
|
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(7.5, FB+90, true, true)
|
||||||
else
|
else
|
||||||
-- Nimitz SC: translate 8 meters starboard wrt Final bearing.
|
-- Nimitz SC: translate 8 meters starboard wrt Final bearing.
|
||||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(9.5, FB+90, true, true)
|
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(9.5, FB+90, true, true)
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
-- @module Ops.CSAR
|
-- @module Ops.CSAR
|
||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
-- Date: Sep 2021
|
-- Date: Oct 2021
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@ -97,6 +97,14 @@
|
|||||||
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
|
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
|
||||||
-- -- (added 0.1.9)
|
-- -- (added 0.1.9)
|
||||||
-- self.suppressmessages = false -- switch off all messaging if you want to do your own
|
-- self.suppressmessages = false -- switch off all messaging if you want to do your own
|
||||||
|
-- -- (added 0.1.11)
|
||||||
|
-- self.rescuehoverheight = 20 -- max height for a hovering rescue in meters
|
||||||
|
-- self.rescuehoverdistance = 10 -- max distance for a hovering rescue in meters
|
||||||
|
-- -- (added 0.1.12)
|
||||||
|
-- -- Country codes for spawned pilots
|
||||||
|
-- self.countryblue= country.id.USA
|
||||||
|
-- self.countryred = country.id.RUSSIA
|
||||||
|
-- self.countryneutral = country.id.UN_PEACEKEEPERS
|
||||||
--
|
--
|
||||||
-- ## 2.1 Experimental Features
|
-- ## 2.1 Experimental Features
|
||||||
--
|
--
|
||||||
@ -233,7 +241,7 @@ CSAR.AircraftType["Mi-24V"] = 8
|
|||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="0.1.10r5"
|
CSAR.version="0.1.11r1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@ -362,6 +370,15 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
||||||
self.pilotmustopendoors = false -- switch to true to enable check on open doors
|
self.pilotmustopendoors = false -- switch to true to enable check on open doors
|
||||||
self.suppressmessages = false
|
self.suppressmessages = false
|
||||||
|
|
||||||
|
-- added 0.1.11r1
|
||||||
|
self.rescuehoverheight = 20
|
||||||
|
self.rescuehoverdistance = 10
|
||||||
|
|
||||||
|
-- added 0.1.12
|
||||||
|
self.countryblue= country.id.USA
|
||||||
|
self.countryred = country.id.RUSSIA
|
||||||
|
self.countryneutral = country.id.UN_PEACEKEEPERS
|
||||||
|
|
||||||
-- WARNING - here\'ll be dragons
|
-- WARNING - here\'ll be dragons
|
||||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||||
@ -549,6 +566,7 @@ function CSAR:_SpawnPilotInField(country,point,frequency)
|
|||||||
for i=1,10 do
|
for i=1,10 do
|
||||||
math.random(i,10000)
|
math.random(i,10000)
|
||||||
end
|
end
|
||||||
|
if point:IsSurfaceTypeWater() then point.y = 0 end
|
||||||
local template = self.template
|
local template = self.template
|
||||||
local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99))
|
local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99))
|
||||||
local coalition = self.coalition
|
local coalition = self.coalition
|
||||||
@ -687,11 +705,11 @@ function CSAR:_SpawnCsarAtZone( _zone, _coalition, _description, _randomPoint, _
|
|||||||
|
|
||||||
local _country = 0
|
local _country = 0
|
||||||
if _coalition == coalition.side.BLUE then
|
if _coalition == coalition.side.BLUE then
|
||||||
_country = country.id.USA
|
_country = self.countryblue
|
||||||
elseif _coalition == coalition.side.RED then
|
elseif _coalition == coalition.side.RED then
|
||||||
_country = country.id.RUSSIA
|
_country = self.countryred
|
||||||
else
|
else
|
||||||
_country = country.id.UN_PEACEKEEPERS
|
_country = self.countryneutral
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_AddCsar(_coalition, _country, pos, typename, unitname, _description, freq, _nomessage, _description, forcedesc)
|
self:_AddCsar(_coalition, _country, pos, typename, unitname, _description, freq, _nomessage, _description, forcedesc)
|
||||||
@ -1120,7 +1138,6 @@ end
|
|||||||
function CSAR:_IsLoadingDoorOpen( unit_name )
|
function CSAR:_IsLoadingDoorOpen( unit_name )
|
||||||
self:T(self.lid .. " _IsLoadingDoorOpen")
|
self:T(self.lid .. " _IsLoadingDoorOpen")
|
||||||
return UTILS.IsLoadingDoorOpen(unit_name)
|
return UTILS.IsLoadingDoorOpen(unit_name)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Function to check if heli is close to group.
|
--- (Internal) Function to check if heli is close to group.
|
||||||
@ -1200,15 +1217,16 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG
|
|||||||
end
|
end
|
||||||
|
|
||||||
if _heliUnit:InAir() and _unitsInHelicopter + 1 <= _maxUnits then
|
if _heliUnit:InAir() and _unitsInHelicopter + 1 <= _maxUnits then
|
||||||
|
-- TODO - make variable
|
||||||
if _distance < 8.0 then
|
if _distance < self.rescuehoverdistance then
|
||||||
|
|
||||||
--check height!
|
--check height!
|
||||||
local leaderheight = _woundedLeader:GetHeight()
|
local leaderheight = _woundedLeader:GetHeight()
|
||||||
if leaderheight < 0 then leaderheight = 0 end
|
if leaderheight < 0 then leaderheight = 0 end
|
||||||
local _height = _heliUnit:GetHeight() - leaderheight
|
local _height = _heliUnit:GetHeight() - leaderheight
|
||||||
|
|
||||||
if _height <= 20.0 then
|
-- TODO - make variable
|
||||||
|
if _height <= self.rescuehoverheight then
|
||||||
|
|
||||||
local _time = self.hoverStatus[_lookupKeyHeli]
|
local _time = self.hoverStatus[_lookupKeyHeli]
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
-- @module Ops.CTLD
|
-- @module Ops.CTLD
|
||||||
-- @image OPS_CTLD.jpg
|
-- @image OPS_CTLD.jpg
|
||||||
|
|
||||||
-- Date: Sep 2021
|
-- Date: Oct 2021
|
||||||
|
|
||||||
do
|
do
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
@ -669,6 +669,7 @@ do
|
|||||||
-- my_ctld.cratecountry = country.id.GERMANY -- ID of crates. Will default to country.id.RUSSIA for RED coalition setups.
|
-- my_ctld.cratecountry = country.id.GERMANY -- ID of crates. Will default to country.id.RUSSIA for RED coalition setups.
|
||||||
-- my_ctld.allowcratepickupagain = true -- allow re-pickup crates that were dropped.
|
-- my_ctld.allowcratepickupagain = true -- allow re-pickup crates that were dropped.
|
||||||
-- my_ctld.enableslingload = false -- allow cargos to be slingloaded - might not work for all cargo types
|
-- my_ctld.enableslingload = false -- allow cargos to be slingloaded - might not work for all cargo types
|
||||||
|
-- my_ctld.pilotmustopendoors = false -- -- force opening of doors
|
||||||
--
|
--
|
||||||
-- ## 2.1 User functions
|
-- ## 2.1 User functions
|
||||||
--
|
--
|
||||||
@ -987,7 +988,7 @@ CTLD.UnitTypes = {
|
|||||||
|
|
||||||
--- CTLD class version.
|
--- CTLD class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CTLD.version="0.2.2a4"
|
CTLD.version="0.2.4"
|
||||||
|
|
||||||
--- Instantiate a new CTLD.
|
--- Instantiate a new CTLD.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@ -1131,6 +1132,9 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- country of crates spawned
|
-- country of crates spawned
|
||||||
self.cratecountry = country.id.GERMANY
|
self.cratecountry = country.id.GERMANY
|
||||||
|
|
||||||
|
-- for opening doors
|
||||||
|
self.pilotmustopendoors = false
|
||||||
|
|
||||||
if self.coalition == coalition.side.RED then
|
if self.coalition == coalition.side.RED then
|
||||||
self.cratecountry = country.id.RUSSIA
|
self.cratecountry = country.id.RUSSIA
|
||||||
end
|
end
|
||||||
@ -1436,6 +1440,7 @@ function CTLD:_LoadTroops(Group, Unit, Cargotype)
|
|||||||
-- landed or hovering over load zone?
|
-- landed or hovering over load zone?
|
||||||
local grounded = not self:IsUnitInAir(Unit)
|
local grounded = not self:IsUnitInAir(Unit)
|
||||||
local hoverload = self:CanHoverLoad(Unit)
|
local hoverload = self:CanHoverLoad(Unit)
|
||||||
|
--local dooropen = UTILS.IsLoadingDoorOpen(Unit:GetName()) and self.pilotmustopendoors
|
||||||
-- check if we are in LOAD zone
|
-- check if we are in LOAD zone
|
||||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||||
if not inzone then
|
if not inzone then
|
||||||
@ -1447,6 +1452,9 @@ function CTLD:_LoadTroops(Group, Unit, Cargotype)
|
|||||||
elseif not grounded and not hoverload then
|
elseif not grounded and not hoverload then
|
||||||
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
|
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
|
||||||
if not self.debug then return self end
|
if not self.debug then return self end
|
||||||
|
elseif self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to load troops!", 10, false, Group)
|
||||||
|
if not self.debug then return self end
|
||||||
end
|
end
|
||||||
-- load troops into heli
|
-- load troops into heli
|
||||||
local group = Group -- Wrapper.Group#GROUP
|
local group = Group -- Wrapper.Group#GROUP
|
||||||
@ -1618,6 +1626,10 @@ end
|
|||||||
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
|
self:_SendMessage("You need to land or hover in position to load!", 10, false, Group)
|
||||||
if not self.debug then return self end
|
if not self.debug then return self end
|
||||||
end
|
end
|
||||||
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to extract troops!", 10, false, Group)
|
||||||
|
if not self.debug then return self end
|
||||||
|
end
|
||||||
-- load troops into heli
|
-- load troops into heli
|
||||||
local unit = Unit -- Wrapper.Unit#UNIT
|
local unit = Unit -- Wrapper.Unit#UNIT
|
||||||
local unitname = unit:GetName()
|
local unitname = unit:GetName()
|
||||||
@ -1887,14 +1899,18 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Inject crates and static cargo objects.
|
--- (Internal) Inject crates and static cargo objects.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Core.Zone#ZONE Zone Zone to spawn in.
|
-- @param Core.Zone#ZONE Zone Zone to spawn in.
|
||||||
-- @param #CTLD_CARGO Cargo The cargo type to spawn.
|
-- @param #CTLD_CARGO Cargo The cargo type to spawn.
|
||||||
|
-- @param #boolean RandomCoord Randomize coordinate.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
function CTLD:InjectStatics(Zone, Cargo)
|
function CTLD:InjectStatics(Zone, Cargo, RandomCoord)
|
||||||
self:T(self.lid .. " InjectStatics")
|
self:T(self.lid .. " InjectStatics")
|
||||||
local cratecoord = Zone:GetCoordinate()
|
local cratecoord = Zone:GetCoordinate()
|
||||||
|
if RandomCoord then
|
||||||
|
cratecoord = Zone:GetRandomCoordinate(5,20)
|
||||||
|
end
|
||||||
local surface = cratecoord:GetSurfaceType()
|
local surface = cratecoord:GetSurfaceType()
|
||||||
if surface == land.SurfaceType.WATER then
|
if surface == land.SurfaceType.WATER then
|
||||||
return self
|
return self
|
||||||
@ -1930,6 +1946,19 @@ function CTLD:InjectStatics(Zone, Cargo)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (User) Inject static cargo objects.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param Core.Zone#ZONE Zone Zone to spawn in. Will be a somewhat random coordinate.
|
||||||
|
-- @param #string Template Unit(!) name of the static cargo object to be used as template.
|
||||||
|
-- @param #number Mass Mass of the static in kg.
|
||||||
|
-- @return #CTLD self
|
||||||
|
function CTLD:InjectStaticFromTemplate(Zone, Template, Mass)
|
||||||
|
self:T(self.lid .. " InjectStaticFromTemplate")
|
||||||
|
local cargotype = self:GetStaticsCargoFromTemplate(Template,Mass) -- #CTLD_CARGO
|
||||||
|
self:InjectStatics(Zone,cargotype,true)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Function to find and list nearby crates.
|
--- (Internal) Function to find and list nearby crates.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Wrapper.Group#GROUP Group
|
-- @param Wrapper.Group#GROUP Group
|
||||||
@ -2343,6 +2372,11 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
self:T(self.lid .. " _UnloadTroops")
|
self:T(self.lid .. " _UnloadTroops")
|
||||||
-- check if we are in LOAD zone
|
-- check if we are in LOAD zone
|
||||||
local droppingatbase = false
|
local droppingatbase = false
|
||||||
|
local canunload = true
|
||||||
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to unload troops!", 10, false, Group)
|
||||||
|
if not self.debug then return self end
|
||||||
|
end
|
||||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD)
|
||||||
if not inzone then
|
if not inzone then
|
||||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||||
@ -2961,7 +2995,7 @@ end
|
|||||||
|
|
||||||
--- User function - Add *generic* static-type loadable as cargo. This type will create cargo that needs to be loaded, moved and dropped.
|
--- User function - Add *generic* static-type loadable as cargo. This type will create cargo that needs to be loaded, moved and dropped.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string Name Unique name of this type of cargo as set in the mission editor (not: UNIT name!), e.g. "Ammunition-1".
|
-- @param #string Name Unique name of this type of cargo as set in the mission editor (note: UNIT name!), e.g. "Ammunition-1".
|
||||||
-- @param #number Mass Mass in kg of each static in kg, e.g. 100.
|
-- @param #number Mass Mass in kg of each static in kg, e.g. 100.
|
||||||
-- @param #number Stock Number of groups in stock. Nil for unlimited.
|
-- @param #number Stock Number of groups in stock. Nil for unlimited.
|
||||||
function CTLD:AddStaticsCargo(Name,Mass,Stock)
|
function CTLD:AddStaticsCargo(Name,Mass,Stock)
|
||||||
@ -2975,6 +3009,22 @@ function CTLD:AddStaticsCargo(Name,Mass,Stock)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- User function - Get a *generic* static-type loadable as #CTLD_CARGO object.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string Name Unique Unit(!) name of this type of cargo as set in the mission editor (not: GROUP name!), e.g. "Ammunition-1".
|
||||||
|
-- @param #number Mass Mass in kg of each static in kg, e.g. 100.
|
||||||
|
-- @return #CTLD_CARGO Cargo object
|
||||||
|
function CTLD:GetStaticsCargoFromTemplate(Name,Mass)
|
||||||
|
self:T(self.lid .. " GetStaticsCargoFromTemplate")
|
||||||
|
self.CargoCounter = self.CargoCounter + 1
|
||||||
|
local type = CTLD_CARGO.Enum.STATIC
|
||||||
|
local template = STATIC:FindByName(Name,true):GetTypeName()
|
||||||
|
-- Crates are not directly loadable
|
||||||
|
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,1)
|
||||||
|
--table.insert(self.Cargo_Statics,cargo)
|
||||||
|
return cargo
|
||||||
|
end
|
||||||
|
|
||||||
--- User function - Add *generic* repair crates loadable as cargo. This type will create crates that need to be loaded, moved, dropped and built.
|
--- User function - Add *generic* repair crates loadable as cargo. This type will create crates that need to be loaded, moved, dropped and built.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string Name Unique name of this type of cargo. E.g. "Humvee".
|
-- @param #string Name Unique name of this type of cargo. E.g. "Humvee".
|
||||||
@ -3013,7 +3063,7 @@ end
|
|||||||
--- User function - Activate Name #CTLD.CargoZone.Type ZoneType for this CTLD instance.
|
--- User function - Activate Name #CTLD.CargoZone.Type ZoneType for this CTLD instance.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string Name Name of the zone to change in the ME.
|
-- @param #string Name Name of the zone to change in the ME.
|
||||||
-- @param #CTLD.CargoZoneTyp ZoneType Type of zone this belongs to.
|
-- @param #CTLD.CargoZoneType ZoneType Type of zone this belongs to.
|
||||||
-- @param #boolean NewState (Optional) Set to true to activate, false to switch off.
|
-- @param #boolean NewState (Optional) Set to true to activate, false to switch off.
|
||||||
function CTLD:ActivateZone(Name,ZoneType,NewState)
|
function CTLD:ActivateZone(Name,ZoneType,NewState)
|
||||||
self:T(self.lid .. " AddZone")
|
self:T(self.lid .. " AddZone")
|
||||||
@ -3049,7 +3099,7 @@ end
|
|||||||
--- User function - Deactivate Name #CTLD.CargoZoneType ZoneType for this CTLD instance.
|
--- User function - Deactivate Name #CTLD.CargoZoneType ZoneType for this CTLD instance.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string Name Name of the zone to change in the ME.
|
-- @param #string Name Name of the zone to change in the ME.
|
||||||
-- @param #CTLD.CargoZoneTyp ZoneType Type of zone this belongs to.
|
-- @param #CTLD.CargoZoneType ZoneType Type of zone this belongs to.
|
||||||
function CTLD:DeactivateZone(Name,ZoneType)
|
function CTLD:DeactivateZone(Name,ZoneType)
|
||||||
self:T(self.lid .. " AddZone")
|
self:T(self.lid .. " AddZone")
|
||||||
self:ActivateZone(Name,ZoneType,false)
|
self:ActivateZone(Name,ZoneType,false)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,28 +1,28 @@
|
|||||||
--- **Sound** - Radio transmissions.
|
--- **Sound** - Radio transmissions.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Provide radio functionality to broadcast radio transmissions.
|
-- * Provide radio functionality to broadcast radio transmissions.
|
||||||
--
|
--
|
||||||
-- What are radio communications in DCS?
|
-- What are radio communications in DCS?
|
||||||
--
|
--
|
||||||
-- * Radio transmissions consist of **sound files** that are broadcasted on a specific **frequency** (e.g. 115MHz) and **modulation** (e.g. AM),
|
-- * Radio transmissions consist of **sound files** that are broadcasted on a specific **frequency** (e.g. 115MHz) and **modulation** (e.g. AM),
|
||||||
-- * They can be **subtitled** for a specific **duration**, the **power** in Watts of the transmiter's antenna can be set, and the transmission can be **looped**.
|
-- * They can be **subtitled** for a specific **duration**, the **power** in Watts of the transmiter's antenna can be set, and the transmission can be **looped**.
|
||||||
--
|
--
|
||||||
-- How to supply DCS my own Sound Files?
|
-- How to supply DCS my own Sound Files?
|
||||||
--
|
--
|
||||||
-- * Your sound files need to be encoded in **.ogg** or .wav,
|
-- * Your sound files need to be encoded in **.ogg** or .wav,
|
||||||
-- * Your sound files should be **as tiny as possible**. It is suggested you encode in .ogg with low bitrate and sampling settings,
|
-- * Your sound files should be **as tiny as possible**. It is suggested you encode in .ogg with low bitrate and sampling settings,
|
||||||
-- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file),
|
-- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file),
|
||||||
-- * For simplicity sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission.
|
-- * For simplicity sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission.
|
||||||
--
|
--
|
||||||
-- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or by any other @{Wrapper.Positionable#POSITIONABLE}
|
-- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or by any other @{Wrapper.Positionable#POSITIONABLE}
|
||||||
--
|
--
|
||||||
-- * If the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, DCS will set the power of the transmission automatically,
|
-- * If the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, DCS will set the power of the transmission automatically,
|
||||||
-- * If the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped.
|
-- * If the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped.
|
||||||
--
|
--
|
||||||
-- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft,
|
-- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft,
|
||||||
-- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below).
|
-- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below).
|
||||||
-- If an FC3 aircraft is used, it will **hear every communication, whatever the frequency and the modulation** is set to. The same is true for TACAN beacons. If your aircraft isn't compatible,
|
-- If an FC3 aircraft is used, it will **hear every communication, whatever the frequency and the modulation** is set to. The same is true for TACAN beacons. If your aircraft isn't compatible,
|
||||||
@ -37,41 +37,41 @@
|
|||||||
|
|
||||||
|
|
||||||
--- *It's not true I had nothing on, I had the radio on.* -- Marilyn Monroe
|
--- *It's not true I had nothing on, I had the radio on.* -- Marilyn Monroe
|
||||||
--
|
--
|
||||||
-- # RADIO usage
|
-- # RADIO usage
|
||||||
--
|
--
|
||||||
-- There are 3 steps to a successful radio transmission.
|
-- There are 3 steps to a successful radio transmission.
|
||||||
--
|
--
|
||||||
-- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function,
|
-- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function,
|
||||||
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
||||||
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
|
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
|
||||||
--
|
--
|
||||||
-- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE}
|
-- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE}
|
||||||
--
|
--
|
||||||
-- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"),
|
-- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"),
|
||||||
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission.
|
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission.
|
||||||
-- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission.
|
-- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission.
|
||||||
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead...
|
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead...
|
||||||
--
|
--
|
||||||
-- Additional Methods to set relevant parameters if the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}
|
-- Additional Methods to set relevant parameters if the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}
|
||||||
--
|
--
|
||||||
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
||||||
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||||
--
|
--
|
||||||
-- Additional Methods to set relevant parameters if the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}
|
-- Additional Methods to set relevant parameters if the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}
|
||||||
--
|
--
|
||||||
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
||||||
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||||
--
|
--
|
||||||
-- What is this power thing?
|
-- What is this power thing?
|
||||||
--
|
--
|
||||||
-- * If your transmission is sent by a @{Wrapper.Positionable#POSITIONABLE} other than a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, you can set the power of the antenna,
|
-- * If your transmission is sent by a @{Wrapper.Positionable#POSITIONABLE} other than a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, you can set the power of the antenna,
|
||||||
-- * Otherwise, DCS sets it automatically, depending on what's available on your Unit,
|
-- * Otherwise, DCS sets it automatically, depending on what's available on your Unit,
|
||||||
-- * If the player gets **too far** from the transmitter, or if the antenna is **too weak**, the transmission will **fade** and **become noisyer**,
|
-- * If the player gets **too far** from the transmitter, or if the antenna is **too weak**, the transmission will **fade** and **become noisyer**,
|
||||||
-- * This an automated DCS calculation you have no say on,
|
-- * This an automated DCS calculation you have no say on,
|
||||||
-- * For reference, a standard VOR station has a 100 W antenna, a standard AA TACAN has a 120 W antenna, and civilian ATC's antenna usually range between 300 and 500 W,
|
-- * For reference, a standard VOR station has a 100 W antenna, a standard AA TACAN has a 120 W antenna, and civilian ATC's antenna usually range between 300 and 500 W,
|
||||||
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
|
-- * Note that if the transmission has a subtitle, it will be readable, regardless of the quality of the transmission.
|
||||||
--
|
--
|
||||||
-- @type RADIO
|
-- @type RADIO
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{#CONTROLLABLE} that will transmit the radio calls.
|
-- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{#CONTROLLABLE} that will transmit the radio calls.
|
||||||
-- @field #string FileName Name of the sound file played.
|
-- @field #string FileName Name of the sound file played.
|
||||||
@ -105,12 +105,12 @@ function RADIO:New(Positionable)
|
|||||||
-- Inherit base
|
-- Inherit base
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- Core.Radio#RADIO
|
local self = BASE:Inherit( self, BASE:New() ) -- Core.Radio#RADIO
|
||||||
self:F(Positionable)
|
self:F(Positionable)
|
||||||
|
|
||||||
if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid
|
if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid
|
||||||
self.Positionable = Positionable
|
self.Positionable = Positionable
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E({error="The passed positionable is invalid, no RADIO created!", positionable=Positionable})
|
self:E({error="The passed positionable is invalid, no RADIO created!", positionable=Positionable})
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@ -137,19 +137,19 @@ end
|
|||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:SetFileName(FileName)
|
function RADIO:SetFileName(FileName)
|
||||||
self:F2(FileName)
|
self:F2(FileName)
|
||||||
|
|
||||||
if type(FileName) == "string" then
|
if type(FileName) == "string" then
|
||||||
|
|
||||||
if FileName:find(".ogg") or FileName:find(".wav") then
|
if FileName:find(".ogg") or FileName:find(".wav") then
|
||||||
if not FileName:find("l10n/DEFAULT/") then
|
if not FileName:find("l10n/DEFAULT/") then
|
||||||
FileName = "l10n/DEFAULT/" .. FileName
|
FileName = "l10n/DEFAULT/" .. FileName
|
||||||
end
|
end
|
||||||
|
|
||||||
self.FileName = FileName
|
self.FileName = FileName
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E({"File name invalid. Maybe something wrong with the extension?", FileName})
|
self:E({"File name invalid. Maybe something wrong with the extension?", FileName})
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -157,39 +157,39 @@ end
|
|||||||
--- Set the frequency for the radio transmission.
|
--- Set the frequency for the radio transmission.
|
||||||
-- If the transmitting positionable is a unit or group, this also set the command "SetFrequency" with the defined frequency and modulation.
|
-- If the transmitting positionable is a unit or group, this also set the command "SetFrequency" with the defined frequency and modulation.
|
||||||
-- @param #RADIO self
|
-- @param #RADIO self
|
||||||
-- @param #number Frequency Frequency in MHz. Ranges allowed for radio transmissions in DCS : 30-87.995 / 108-173.995 / 225-399.975MHz.
|
-- @param #number Frequency Frequency in MHz.
|
||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:SetFrequency(Frequency)
|
function RADIO:SetFrequency(Frequency)
|
||||||
self:F2(Frequency)
|
self:F2(Frequency)
|
||||||
|
|
||||||
if type(Frequency) == "number" then
|
if type(Frequency) == "number" then
|
||||||
|
|
||||||
-- If frequency is in range
|
-- If frequency is in range
|
||||||
if (Frequency >= 30 and Frequency <= 87.995) or (Frequency >= 108 and Frequency <= 173.995) or (Frequency >= 225 and Frequency <= 399.975) then
|
--if (Frequency >= 30 and Frequency <= 87.995) or (Frequency >= 108 and Frequency <= 173.995) or (Frequency >= 225 and Frequency <= 399.975) then
|
||||||
|
|
||||||
-- Convert frequency from MHz to Hz
|
-- Convert frequency from MHz to Hz
|
||||||
self.Frequency = Frequency * 1000000
|
self.Frequency = Frequency * 1000000
|
||||||
|
|
||||||
-- If the RADIO is attached to a UNIT or a GROUP, we need to send the DCS Command "SetFrequency" to change the UNIT or GROUP frequency
|
-- If the RADIO is attached to a UNIT or a GROUP, we need to send the DCS Command "SetFrequency" to change the UNIT or GROUP frequency
|
||||||
if self.Positionable.ClassName == "UNIT" or self.Positionable.ClassName == "GROUP" then
|
if self.Positionable.ClassName == "UNIT" or self.Positionable.ClassName == "GROUP" then
|
||||||
|
|
||||||
local commandSetFrequency={
|
local commandSetFrequency={
|
||||||
id = "SetFrequency",
|
id = "SetFrequency",
|
||||||
params = {
|
params = {
|
||||||
frequency = self.Frequency,
|
frequency = self.Frequency,
|
||||||
modulation = self.Modulation,
|
modulation = self.Modulation,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self:T2(commandSetFrequency)
|
self:T2(commandSetFrequency)
|
||||||
self.Positionable:SetCommand(commandSetFrequency)
|
self.Positionable:SetCommand(commandSetFrequency)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
--end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E({"Frequency is outside of DCS Frequency ranges (30-80, 108-152, 225-400). Frequency unchanged.", Frequency})
|
self:E({"Frequency is not a number. Frequency unchanged.", Frequency})
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -215,13 +215,13 @@ end
|
|||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:SetPower(Power)
|
function RADIO:SetPower(Power)
|
||||||
self:F2(Power)
|
self:F2(Power)
|
||||||
|
|
||||||
if type(Power) == "number" then
|
if type(Power) == "number" then
|
||||||
self.Power = math.floor(math.abs(Power)) --TODO Find what is the maximum power allowed by DCS and limit power to that
|
self.Power = math.floor(math.abs(Power)) --TODO Find what is the maximum power allowed by DCS and limit power to that
|
||||||
else
|
else
|
||||||
self:E({"Power is invalid. Power unchanged.", self.Power})
|
self:E({"Power is invalid. Power unchanged.", self.Power})
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -249,7 +249,7 @@ end
|
|||||||
-- -- create the broadcaster and attaches it a RADIO
|
-- -- create the broadcaster and attaches it a RADIO
|
||||||
-- local MyUnit = UNIT:FindByName("MyUnit")
|
-- local MyUnit = UNIT:FindByName("MyUnit")
|
||||||
-- local MyUnitRadio = MyUnit:GetRadio()
|
-- local MyUnitRadio = MyUnit:GetRadio()
|
||||||
--
|
--
|
||||||
-- -- add a subtitle for the next transmission, which will be up for 10s
|
-- -- add a subtitle for the next transmission, which will be up for 10s
|
||||||
-- MyUnitRadio:SetSubtitle("My Subtitle, 10)
|
-- MyUnitRadio:SetSubtitle("My Subtitle, 10)
|
||||||
function RADIO:SetSubtitle(Subtitle, SubtitleDuration)
|
function RADIO:SetSubtitle(Subtitle, SubtitleDuration)
|
||||||
@ -264,14 +264,14 @@ function RADIO:SetSubtitle(Subtitle, SubtitleDuration)
|
|||||||
self.SubtitleDuration = SubtitleDuration
|
self.SubtitleDuration = SubtitleDuration
|
||||||
else
|
else
|
||||||
self.SubtitleDuration = 0
|
self.SubtitleDuration = 0
|
||||||
self:E({"SubtitleDuration is invalid. SubtitleDuration reset.", self.SubtitleDuration})
|
self:E({"SubtitleDuration is invalid. SubtitleDuration reset.", self.SubtitleDuration})
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Create a new transmission, that is to say, populate the RADIO with relevant data
|
--- Create a new transmission, that is to say, populate the RADIO with relevant data
|
||||||
-- In this function the data is especially relevant if the broadcaster is anything but a UNIT or a GROUP,
|
-- In this function the data is especially relevant if the broadcaster is anything but a UNIT or a GROUP,
|
||||||
-- but it will work with a UNIT or a GROUP anyway.
|
-- but it will work with a UNIT or a GROUP anyway.
|
||||||
-- Only the #RADIO and the Filename are mandatory
|
-- Only the #RADIO and the Filename are mandatory
|
||||||
-- @param #RADIO self
|
-- @param #RADIO self
|
||||||
-- @param #string FileName Name of the sound file that will be transmitted.
|
-- @param #string FileName Name of the sound file that will be transmitted.
|
||||||
@ -281,20 +281,20 @@ end
|
|||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:NewGenericTransmission(FileName, Frequency, Modulation, Power, Loop)
|
function RADIO:NewGenericTransmission(FileName, Frequency, Modulation, Power, Loop)
|
||||||
self:F({FileName, Frequency, Modulation, Power})
|
self:F({FileName, Frequency, Modulation, Power})
|
||||||
|
|
||||||
self:SetFileName(FileName)
|
self:SetFileName(FileName)
|
||||||
if Frequency then self:SetFrequency(Frequency) end
|
if Frequency then self:SetFrequency(Frequency) end
|
||||||
if Modulation then self:SetModulation(Modulation) end
|
if Modulation then self:SetModulation(Modulation) end
|
||||||
if Power then self:SetPower(Power) end
|
if Power then self:SetPower(Power) end
|
||||||
if Loop then self:SetLoop(Loop) end
|
if Loop then self:SetLoop(Loop) end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Create a new transmission, that is to say, populate the RADIO with relevant data
|
--- Create a new transmission, that is to say, populate the RADIO with relevant data
|
||||||
-- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
|
-- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
|
||||||
-- but it will work for any @{Wrapper.Positionable#POSITIONABLE}.
|
-- but it will work for any @{Wrapper.Positionable#POSITIONABLE}.
|
||||||
-- Only the RADIO and the Filename are mandatory.
|
-- Only the RADIO and the Filename are mandatory.
|
||||||
-- @param #RADIO self
|
-- @param #RADIO self
|
||||||
-- @param #string FileName Name of sound file.
|
-- @param #string FileName Name of sound file.
|
||||||
@ -316,20 +316,20 @@ function RADIO:NewUnitTransmission(FileName, Subtitle, SubtitleDuration, Frequen
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Set frequency.
|
-- Set frequency.
|
||||||
if Frequency then
|
if Frequency then
|
||||||
self:SetFrequency(Frequency)
|
self:SetFrequency(Frequency)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set subtitle.
|
-- Set subtitle.
|
||||||
if Subtitle then
|
if Subtitle then
|
||||||
self:SetSubtitle(Subtitle, SubtitleDuration or 0)
|
self:SetSubtitle(Subtitle, SubtitleDuration or 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set Looping.
|
-- Set Looping.
|
||||||
if Loop then
|
if Loop then
|
||||||
self:SetLoop(Loop)
|
self:SetLoop(Loop)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -346,7 +346,7 @@ end
|
|||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:Broadcast(viatrigger)
|
function RADIO:Broadcast(viatrigger)
|
||||||
self:F({viatrigger=viatrigger})
|
self:F({viatrigger=viatrigger})
|
||||||
|
|
||||||
-- If the POSITIONABLE is actually a UNIT or a GROUP, use the more complicated DCS command system.
|
-- If the POSITIONABLE is actually a UNIT or a GROUP, use the more complicated DCS command system.
|
||||||
if (self.Positionable.ClassName=="UNIT" or self.Positionable.ClassName=="GROUP") and (not viatrigger) then
|
if (self.Positionable.ClassName=="UNIT" or self.Positionable.ClassName=="GROUP") and (not viatrigger) then
|
||||||
self:T("Broadcasting from a UNIT or a GROUP")
|
self:T("Broadcasting from a UNIT or a GROUP")
|
||||||
@ -359,7 +359,7 @@ function RADIO:Broadcast(viatrigger)
|
|||||||
subtitle = self.Subtitle,
|
subtitle = self.Subtitle,
|
||||||
loop = self.Loop,
|
loop = self.Loop,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
self:T3(commandTransmitMessage)
|
self:T3(commandTransmitMessage)
|
||||||
self.Positionable:SetCommand(commandTransmitMessage)
|
self.Positionable:SetCommand(commandTransmitMessage)
|
||||||
else
|
else
|
||||||
@ -368,7 +368,7 @@ function RADIO:Broadcast(viatrigger)
|
|||||||
self:T("Broadcasting from a POSITIONABLE")
|
self:T("Broadcasting from a POSITIONABLE")
|
||||||
trigger.action.radioTransmission(self.FileName, self.Positionable:GetPositionVec3(), self.Modulation, self.Loop, self.Frequency, self.Power, tostring(self.ID))
|
trigger.action.radioTransmission(self.FileName, self.Positionable:GetPositionVec3(), self.Modulation, self.Loop, self.Frequency, self.Power, tostring(self.ID))
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -380,11 +380,11 @@ end
|
|||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:StopBroadcast()
|
function RADIO:StopBroadcast()
|
||||||
self:F()
|
self:F()
|
||||||
-- If the POSITIONABLE is a UNIT or a GROUP, stop the transmission with the DCS "StopTransmission" command
|
-- If the POSITIONABLE is a UNIT or a GROUP, stop the transmission with the DCS "StopTransmission" command
|
||||||
if self.Positionable.ClassName == "UNIT" or self.Positionable.ClassName == "GROUP" then
|
if self.Positionable.ClassName == "UNIT" or self.Positionable.ClassName == "GROUP" then
|
||||||
|
|
||||||
local commandStopTransmission={id="StopTransmission", params={}}
|
local commandStopTransmission={id="StopTransmission", params={}}
|
||||||
|
|
||||||
self.Positionable:SetCommand(commandStopTransmission)
|
self.Positionable:SetCommand(commandStopTransmission)
|
||||||
else
|
else
|
||||||
-- Else, we use the appropriate singleton funciton
|
-- Else, we use the appropriate singleton funciton
|
||||||
|
|||||||
@ -683,6 +683,7 @@ do -- TASK_CARGO_DISPATCHER
|
|||||||
-- If no TaskPrefix is given, then "Transport" will be used as the prefix.
|
-- If no TaskPrefix is given, then "Transport" will be used as the prefix.
|
||||||
-- @param Core.SetCargo#SET_CARGO SetCargo The SetCargo to be transported.
|
-- @param Core.SetCargo#SET_CARGO SetCargo The SetCargo to be transported.
|
||||||
-- @param #string Briefing The briefing of the task transport to be shown to the player.
|
-- @param #string Briefing The briefing of the task transport to be shown to the player.
|
||||||
|
-- @param #boolean Silent If true don't send a message that a new task is available.
|
||||||
-- @return Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT
|
-- @return Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
@ -705,10 +706,12 @@ do -- TASK_CARGO_DISPATCHER
|
|||||||
-- -- Here we set a TransportDeployZone. We use the WorkplaceTask as the reference, and provide a ZONE object.
|
-- -- Here we set a TransportDeployZone. We use the WorkplaceTask as the reference, and provide a ZONE object.
|
||||||
-- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) )
|
-- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) )
|
||||||
--
|
--
|
||||||
function TASK_CARGO_DISPATCHER:AddTransportTask( TaskPrefix, SetCargo, Briefing )
|
function TASK_CARGO_DISPATCHER:AddTransportTask( TaskPrefix, SetCargo, Briefing, Silent )
|
||||||
|
|
||||||
self.TransportCount = self.TransportCount + 1
|
self.TransportCount = self.TransportCount + 1
|
||||||
|
|
||||||
|
local verbose = Silent and true
|
||||||
|
|
||||||
local TaskName = string.format( ( TaskPrefix or "Transport" ) .. ".%03d", self.TransportCount )
|
local TaskName = string.format( ( TaskPrefix or "Transport" ) .. ".%03d", self.TransportCount )
|
||||||
|
|
||||||
self.Transport[TaskName] = {}
|
self.Transport[TaskName] = {}
|
||||||
@ -717,7 +720,7 @@ do -- TASK_CARGO_DISPATCHER
|
|||||||
self.Transport[TaskName].Task = nil
|
self.Transport[TaskName].Task = nil
|
||||||
self.Transport[TaskName].TaskPrefix = TaskPrefix
|
self.Transport[TaskName].TaskPrefix = TaskPrefix
|
||||||
|
|
||||||
self:ManageTasks()
|
self:ManageTasks(verbose)
|
||||||
|
|
||||||
return self.Transport[TaskName] and self.Transport[TaskName].Task
|
return self.Transport[TaskName] and self.Transport[TaskName].Task
|
||||||
end
|
end
|
||||||
@ -785,10 +788,11 @@ do -- TASK_CARGO_DISPATCHER
|
|||||||
|
|
||||||
--- Assigns tasks to the @{Core.Set#SET_GROUP}.
|
--- Assigns tasks to the @{Core.Set#SET_GROUP}.
|
||||||
-- @param #TASK_CARGO_DISPATCHER self
|
-- @param #TASK_CARGO_DISPATCHER self
|
||||||
|
-- @param #boolean Silent Announce new task (nil/false) or not (true).
|
||||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||||
function TASK_CARGO_DISPATCHER:ManageTasks()
|
function TASK_CARGO_DISPATCHER:ManageTasks(Silent)
|
||||||
self:F()
|
self:F()
|
||||||
|
local verbose = Silent and true
|
||||||
local AreaMsg = {}
|
local AreaMsg = {}
|
||||||
local TaskMsg = {}
|
local TaskMsg = {}
|
||||||
local ChangeMsg = {}
|
local ChangeMsg = {}
|
||||||
@ -897,7 +901,7 @@ do -- TASK_CARGO_DISPATCHER
|
|||||||
local TaskText = TaskReport:Text(", ")
|
local TaskText = TaskReport:Text(", ")
|
||||||
|
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
if ( not Mission:IsGroupAssigned(TaskGroup) ) and TaskText ~= "" then
|
if ( not Mission:IsGroupAssigned(TaskGroup) ) and TaskText ~= "" and not verbose then
|
||||||
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1611,7 +1611,7 @@ function UTILS.GetOSTime()
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Shuffle a table accoring to Fisher Yeates algorithm
|
--- Shuffle a table accoring to Fisher Yeates algorithm
|
||||||
--@param #table table to be shuffled
|
--@param #table t Table to be shuffled
|
||||||
--@return #table
|
--@return #table
|
||||||
function UTILS.ShuffleTable(t)
|
function UTILS.ShuffleTable(t)
|
||||||
if t == nil or type(t) ~= "table" then
|
if t == nil or type(t) ~= "table" then
|
||||||
@ -1640,7 +1640,7 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
local type_name = unit:getTypeName()
|
local type_name = unit:getTypeName()
|
||||||
|
|
||||||
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) < 0 then
|
||||||
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
||||||
ret_val = true
|
ret_val = true
|
||||||
end
|
end
|
||||||
@ -1660,6 +1660,21 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
ret_val = true
|
ret_val = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if string.find(type_name, "Hercules") and unit:getDrawArgumentValue(1215) == 1 and unit:getDrawArgumentValue(1216) == 1 then
|
||||||
|
BASE:T(unit_name .. " rear doors are open")
|
||||||
|
ret_val = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if string.find(type_name, "Hercules") and (unit:getDrawArgumentValue(1220) == 1 or unit:getDrawArgumentValue(1221) == 1) then
|
||||||
|
BASE:T(unit_name .. " para doors are open")
|
||||||
|
ret_val = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if string.find(type_name, "Hercules") and unit:getDrawArgumentValue(1217) == 1 then
|
||||||
|
BASE:T(unit_name .. " side door is open")
|
||||||
|
ret_val = true
|
||||||
|
end
|
||||||
|
|
||||||
if ret_val == false then
|
if ret_val == false then
|
||||||
BASE:T(unit_name .. " all doors are closed")
|
BASE:T(unit_name .. " all doors are closed")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1211,7 +1211,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
||||||
|
|
||||||
-- Get the aircraft size, i.e. it's longest side of x,z.
|
-- Get the aircraft size, i.e. it's longest side of x,z.
|
||||||
local aircraft = nil
|
local aircraft = nil -- fix local problem below
|
||||||
local _aircraftsize, ax,ay,az
|
local _aircraftsize, ax,ay,az
|
||||||
if group and group.ClassName == "GROUP" then
|
if group and group.ClassName == "GROUP" then
|
||||||
aircraft=group:GetUnit(1)
|
aircraft=group:GetUnit(1)
|
||||||
|
|||||||
@ -2573,8 +2573,10 @@ end
|
|||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandInvisible(switch)
|
function GROUP:SetCommandInvisible(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
local switch = switch or false
|
if switch==nil then
|
||||||
local SetInvisible = {id = 'SetInvisible', params = {value = true}}
|
switch=false
|
||||||
|
end
|
||||||
|
local SetInvisible = {id = 'SetInvisible', params = {value = switch}}
|
||||||
self:SetCommand(SetInvisible)
|
self:SetCommand(SetInvisible)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -2585,9 +2587,11 @@ end
|
|||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandImmortal(switch)
|
function GROUP:SetCommandImmortal(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
local switch = switch or false
|
if switch==nil then
|
||||||
local SetInvisible = {id = 'SetImmortal', params = {value = true}}
|
switch=false
|
||||||
self:SetCommand(SetInvisible)
|
end
|
||||||
|
local SetImmortal = {id = 'SetImmortal', params = {value = switch}}
|
||||||
|
self:SetCommand(SetImmortal)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -69,6 +69,7 @@ Functional/Warehouse.lua
|
|||||||
Functional/Fox.lua
|
Functional/Fox.lua
|
||||||
Functional/Mantis.lua
|
Functional/Mantis.lua
|
||||||
Functional/Shorad.lua
|
Functional/Shorad.lua
|
||||||
|
Functional/Autolase.lua
|
||||||
|
|
||||||
Ops/Airboss.lua
|
Ops/Airboss.lua
|
||||||
Ops/RecoveryTanker.lua
|
Ops/RecoveryTanker.lua
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user