RANGE etc

RANGE v2.2.3
- Added relay unit option.

TIMER
- Fixed bug.

Minor other stuff
This commit is contained in:
Frank 2020-09-01 17:30:26 +02:00
parent 848336f8ac
commit 26a935c29c
8 changed files with 431 additions and 371 deletions

View File

@ -561,7 +561,8 @@ do -- COORDINATE
return self
else
--env.info("FF translate with NEW coordinate T="..timer.getTime())
return COORDINATE:New(x, y, z)
local coord=COORDINATE:New(x, y, z)
return coord
end
end
@ -761,7 +762,8 @@ do -- COORDINATE
-- Move the vector to start at the end of A.
vec=UTILS.VecAdd(self, vec)
return self:New(vec.x,vec.y,vec.z)
local coord=COORDINATE:New(vec.x,vec.y,vec.z)
return coord
end
--- Return the 2D distance in meters between the target COORDINATE and the COORDINATE.

View File

@ -38,6 +38,8 @@
--
-- The TIMER class is the little sister of the SCHEDULER class. It does the same thing but is a bit easier to use and has less overhead. It should be sufficient in many cases.
--
-- It provides an easy interface to the DCS [timer.scheduleFunction](https://wiki.hoggitworld.com/view/DCS_func_scheduleFunction).
--
-- # Construction
--
-- A new TIMER is created by the @{#TIMER.New}(*func*, *...*) function
@ -100,6 +102,12 @@ TIMER = {
lid = nil,
}
--- Timer ID.
_TIMERID=0
--- Timer data base.
--_TIMERDB={}
--- TIMER class version.
-- @field #string version
TIMER.version="0.1.0"
@ -124,8 +132,6 @@ function TIMER:New(Function, ...)
-- Inherit BASE.
local self=BASE:Inherit(self, BASE:New()) --#TIMER
self.lid="TIMER | "
-- Function to call.
self.func=Function
@ -136,6 +142,18 @@ function TIMER:New(Function, ...)
-- Number of function calls.
self.ncalls=0
-- Increase counter
_TIMERID=_TIMERID+1
-- Set UID.
self.uid=_TIMERID
-- Log id.
self.lid=string.format("TIMER UID=%d | ", self.uid)
-- Add to DB.
--_TIMERDB[self.uid]=self
return self
end
@ -151,7 +169,7 @@ function TIMER:Start(Tstart, dT, Duration)
local Tnow=timer.getTime()
-- Start time in sec.
self.Tstart=Tstart or Tnow
self.Tstart=Tstart and Tnow+Tstart or Tnow+0.001 -- one millisecond delay if Tstart=nil
-- Set time interval.
self.dT=dT
@ -162,10 +180,10 @@ function TIMER:Start(Tstart, dT, Duration)
end
-- Call DCS timer function.
self.tid=timer.scheduleFunction(TIMER._Function, self, self.Tstart)
self.tid=timer.scheduleFunction(self._Function, self, self.Tstart)
-- Set log id.
self.lid=string.format("TIMER ID=%d | ", self.tid)
self.lid=string.format("TIMER UID=%d/%d | ", self.uid, self.tid)
-- Debug info.
self:T(self.lid..string.format("Starting Timer in %.3f sec, dT=%s, Tstop=%s", self.Tstart-Tnow, tostring(self.dT), tostring(self.Tstop)))
@ -186,8 +204,14 @@ function TIMER:Stop(Delay)
else
if self.tid then
-- Remove timer function.
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
timer.removeFunction(self.tid)
-- Remove DB entry.
--_TIMERDB[self.uid]=nil
end
end

View File

@ -93,6 +93,8 @@
-- @field Core.RadioQueue#RADIOQUEUE instructor Instructor radio queue.
-- @field #number rangecontrolfreq Frequency on which the range control transmitts.
-- @field Core.RadioQueue#RADIOQUEUE rangecontrol Range control radio queue.
-- @field #string rangecontrolrelayname Name of relay unit.
-- @field #string instructorrelayname Name of relay unit.
-- @field #string soundpath Path inside miz file where the sound files are located. Default is "Range Soundfiles/".
-- @extends Core.Fsm#FSM
@ -516,7 +518,7 @@ RANGE.MenuF10Root=nil
--- Range script version.
-- @field #string version
RANGE.version="2.2.2"
RANGE.version="2.2.3"
--TODO list:
--TODO: Verbosity level for messages.
@ -770,6 +772,7 @@ function RANGE:onafterStart()
-- Set location where the messages are transmitted from.
self.rangecontrol:SetSenderCoordinate(self.location)
self.rangecontrol:SetSenderUnitName(self.rangecontrolrelayname)
-- Start range control radio queue.
self.rangecontrol:Start(1, 0.1)
@ -794,6 +797,7 @@ function RANGE:onafterStart()
-- Set location where the messages are transmitted from.
self.instructor:SetSenderCoordinate(self.location)
self.instructor:SetSenderUnitName(self.instructorrelayname)
-- Start instructor radio queue.
self.instructor:Start(1, 0.1)
@ -1067,18 +1071,22 @@ end
--- Enable range control and set frequency.
-- @param #RANGE self
-- @param #number frequency Frequency in MHz. Default 256 MHz.
-- @param #string relayunitname Name of the unit used for transmission.
-- @return #RANGE self
function RANGE:SetRangeControl(frequency)
function RANGE:SetRangeControl(frequency, relayunitname)
self.rangecontrolfreq=frequency or 256
self.rangecontrolrelayname=relayunitname
return self
end
--- Enable instructor radio and set frequency.
-- @param #RANGE self
-- @param #number frequency Frequency in MHz. Default 305 MHz.
-- @param #string relayunitname Name of the unit used for transmission.
-- @return #RANGE self
function RANGE:SetInstructorRadio(frequency)
function RANGE:SetInstructorRadio(frequency, relayunitname)
self.instructorfreq=frequency or 305
self.instructorrelayname=relayunitname
return self
end
@ -1908,8 +1916,35 @@ end
-- @param #string To To state.
function RANGE:onafterStatus(From, Event, To)
local fsmstate=self:GetState()
local text=string.format("Range status: %s", fsmstate)
if self.instructor then
local alive="N/A"
if self.instructorrelayname then
local relay=UNIT:FindByName(self.instructorrelayname)
if relay then
alive=tostring(relay:IsAlive())
end
end
text=text..string.format(", Instructor %.3f MHz (Relay=%s alive=%s)", self.instructorfreq, tostring(self.instructorrelayname), alive)
end
if self.rangecontrol then
local alive="N/A"
if self.rangecontrolrelayname then
local relay=UNIT:FindByName(self.rangecontrolrelayname)
if relay then
alive=tostring(relay:IsAlive())
end
end
text=text..string.format(", Control %.3f MHz (Relay=%s alive=%s)", self.rangecontrolfreq, tostring(self.rangecontrolrelayname), alive)
end
-- Check range status.
self:I(self.id..string.format("Range status: %s", self:GetState()))
self:I(self.id..text)
-- Check player status.
self:_CheckPlayers()

View File

@ -1377,7 +1377,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
runway.endpoint=c2
-- Debug info.
self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
--self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
-- Debug mark
if mark then

View File

@ -951,7 +951,8 @@ function GROUP:GetVec2()
local Unit=self:GetUnit(1)
if Unit then
return Unit:GetVec2()
local vec2=Unit:GetVec2()
return vec2
end
end
@ -965,7 +966,8 @@ function GROUP:GetVec3()
local unit=self:GetUnit(1)
if unit then
return unit:GetVec3()
local vec3=unit:GetVec3()
return vec3
end
self:E("ERROR: Cannot get Vec3 of group "..tostring(self.GroupName))
@ -996,13 +998,11 @@ end
-- @param Wrapper.Group#GROUP self
-- @return Core.Point#COORDINATE The COORDINATE of the GROUP.
function GROUP:GetCoordinate()
self:F2( self.PositionableName )
local FirstUnit = self:GetUnit(1)
if FirstUnit then
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
self:T3(FirstUnitCoordinate)
return FirstUnitCoordinate
end
@ -1176,7 +1176,7 @@ do -- Is Zone methods
--- Check if any unit of a group is inside a @{Zone}.
-- @param #GROUP self
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if at least one unit is inside the zone or false if no unit is inside.
-- @return #boolean Returns `true` if *at least one unit* is inside the zone or `false` if *no* unit is inside.
function GROUP:IsInZone( Zone )
if self:IsAlive() then
@ -1184,7 +1184,10 @@ function GROUP:IsInZone( Zone )
for UnitID, UnitData in pairs(self:GetUnits()) do
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsVec3InZone(Unit:GetVec3()) then
-- Get 2D vector. That's all we need for the zone check.
local vec2=Unit:GetVec2()
if Zone:IsVec2InZone(vec2) then
return true -- At least one unit is in the zone. That is enough.
else
-- This one is not but another could be.

View File

@ -1,5 +1,5 @@
--- **Wrapper** - Markers On the F10 map.
--
--
-- **Main Features:**
--
-- * Convenient handling of markers via multiple user API functions.
@ -8,7 +8,7 @@
-- * Retrieve data such as text and coordinate.
-- * Marker specific FSM events when a marker is added, removed or changed.
-- * Additional FSM events when marker text or position is changed.
--
--
-- ===
--
-- ### Author: **funkyfranky**
@ -36,104 +36,104 @@
-- ![Banner Image](..\Presentations\MARKER\Marker_Main.jpg)
--
-- # The MARKER Class Idea
--
--
-- The MARKER class simplifies creating, updating and removing of markers on the F10 map.
--
--
-- # Create a Marker
--
--
-- -- Create a MARKER object at Batumi with a trivial text.
-- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate()
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield")
--
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
--
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
-- show the marker to everyone, to a speficic coaliton only, or only to a specific group.
--
--
-- ## For Everyone
--
--
-- If the marker should be visible to everyone, you can use the :ToAll() function.
--
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll()
--
--
-- ## For a Coaliton
--
--
-- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function.
--
--
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE)
--
--
-- ### To Blue Coaliton
--
--
-- ### To Red Coalition
--
--
-- This would show the marker only to the Blue coaliton.
--
--
-- ## For a Group
--
--
--
--
-- # Removing a Marker
--
--
--
--
-- # Updating a Marker
--
--
-- The marker text and coordinate can be updated easily as shown below.
--
--
-- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**.
-- *This is a DCS scripting engine limitation.*
--
-- *This is a DCS scripting engine limitation.*
--
-- ## Update Text
--
--
-- If you created a marker "mymarker" as shown above, you can update the dispayed test by
--
--
-- mymarker:UpdateText("I am the new text at Batumi")
--
--
-- The update can also be delayed by, e.g. 90 seconds, using
--
--
-- mymarker:UpdateText("I am the new text at Batumi", 90)
--
--
-- ## Update Coordinate
--
--
-- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by
--
--
-- mymarker:UpdateCoordinate(NewCoordinate)
--
--
-- The update can also be delayed by, e.g. 60 seconds, using
--
--
-- mymarker:UpdateCoordinate(NewCoordinate, 60)
--
--
-- # Retrieve Data
--
--
-- The important data as the displayed text and the coordinate of the marker can be retrieved easily.
--
--
-- ## Text
--
--
-- local text=mymarker:GetText()
-- env.info("Marker Text = " .. text)
--
--
-- ## Coordinate
--
--
-- local Coordinate=mymarker:GetCoordinate()
-- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS())
--
--
--
--
-- # FSM Events
--
--
-- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated.
--
--
-- These events can be captured and used for processing via OnAfter functions as shown below.
--
--
-- ## Added
--
--
-- ## Changed
--
--
-- ## Removed
--
--
-- ## TextUpdate
--
--
-- ## CoordUpdate
--
--
--
--
-- # Examples
--
--
--
--
-- @field #MARKER
MARKER = {
ClassName = "MARKER",
@ -170,29 +170,29 @@ MARKER.version="0.1.0"
--- Create a new MARKER class object.
-- @param #MARKER self
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
-- @param #string Text Text displayed on the mark panel.
-- @param #string Text Text displayed on the mark panel.
-- @return #MARKER self
function MARKER:New(Coordinate, Text)
-- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
self.coordinate=Coordinate
self.text=Text
-- Defaults
self.readonly=false
self.message=""
-- New marker ID. This is not the one of the actual marker.
-- New marker ID. This is not the one of the actual marker.
_MARKERID=_MARKERID+1
self.myid=_MARKERID
-- Log ID.
self.lid=string.format("Marker #%d | ", self.myid)
-- Start State.
self:SetStartState("Invisible")
@ -201,7 +201,7 @@ function MARKER:New(Coordinate, Text)
self:AddTransition("Invisible", "Added", "Visible") -- Marker was added.
self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed.
self:AddTransition("*", "Changed", "*") -- Marker was changed.
self:AddTransition("*", "TextUpdate", "*") -- Text updated.
self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated.
@ -304,8 +304,8 @@ function MARKER:New(Coordinate, Text)
self:HandleEvent(EVENTS.MarkAdded)
self:HandleEvent(EVENTS.MarkRemoved)
self:HandleEvent(EVENTS.MarkChange)
return self
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -318,7 +318,7 @@ end
function MARKER:ReadOnly()
self.readonly=true
return self
end
@ -329,7 +329,7 @@ end
function MARKER:Message(Text)
self.message=Text or ""
return self
end
@ -349,14 +349,14 @@ function MARKER:ToAll(Delay)
self.togroup=nil
self.groupname=nil
self.groupid=nil
-- First remove an existing mark.
if self.shown then
self:Remove()
if self.shown then
self:Remove()
end
self.mid=UTILS.GetMarkID()
-- Call DCS function.
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
@ -377,25 +377,25 @@ function MARKER:ToCoalition(Coalition, Delay)
else
self.coalition=Coalition
self.tocoaliton=true
self.toall=false
self.togroup=false
self.groupname=nil
self.groupid=nil
-- First remove an existing mark.
if self.shown then
self:Remove()
if self.shown then
self:Remove()
end
self.mid=UTILS.GetMarkID()
-- Call DCS function.
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
end
return self
end
@ -440,36 +440,36 @@ function MARKER:ToGroup(Group, Delay)
-- Check if group exists.
if Group and Group:IsAlive()~=nil then
self.groupid=Group:GetID()
if self.groupid then
self.groupname=Group:GetName()
self.togroup=true
self.tocoaliton=nil
self.coalition=nil
self.toall=nil
-- First remove an existing mark.
if self.shown then
self:Remove()
if self.shown then
self:Remove()
end
self.mid=UTILS.GetMarkID()
-- Call DCS function.
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
end
else
--TODO: Warning!
--TODO: Warning!
end
end
return self
end
@ -482,14 +482,14 @@ function MARKER:UpdateText(Text, Delay)
if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text)
else
else
self.text=tostring(Text)
self:Refresh()
self:TextUpdate(tostring(Text))
end
return self
@ -504,14 +504,14 @@ function MARKER:UpdateCoordinate(Coordinate, Delay)
if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate)
else
else
self.coordinate=Coordinate
self:Refresh()
self:CoordUpdate(Coordinate)
end
return self
@ -525,26 +525,26 @@ function MARKER:Refresh(Delay)
if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.Refresh, self)
else
else
if self.toall then
self:ToAll()
elseif self.tocoaliton then
self:ToCoalition(self.coalition)
elseif self.togroup then
local group=GROUP:FindByName(self.groupname)
self:ToGroup(group)
else
self:E(self.lid.."ERROR: unknown To in :Refresh()!")
end
end
return self
@ -564,9 +564,9 @@ function MARKER:Remove(Delay)
-- Call DCS function.
trigger.action.removeMark(self.mid)
end
end
return self
@ -605,7 +605,7 @@ end
--- Check if marker is currently invisible on the F10 map.
-- @param #MARKER self
-- @return
-- @return
function MARKER:IsInvisible()
return self:Is("Invisible")
end
@ -620,17 +620,17 @@ end
function MARKER:OnEventMarkAdded(EventData)
if EventData and EventData.MarkID then
local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then
self.shown=true
self:Added(EventData)
end
end
@ -643,21 +643,21 @@ end
function MARKER:OnEventMarkRemoved(EventData)
if EventData and EventData.MarkID then
local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then
self.shown=false
self:Removed(EventData)
end
end
end
--- Event function when a MARKER changed.
@ -666,17 +666,17 @@ end
function MARKER:OnEventMarkChange(EventData)
if EventData and EventData.MarkID then
local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then
self:Changed(EventData)
self:TextChanged(tostring(EventData.MarkText))
end
end
@ -696,7 +696,7 @@ end
function MARKER:onafterAdded(From, Event, To, EventData)
-- Debug info.
local text=string.format("Captured event MarkAdded for myself:\n")
local text=string.format("Captured event MarkAdded for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -716,7 +716,7 @@ end
function MARKER:onafterRemoved(From, Event, To, EventData)
-- Debug info.
local text=string.format("Captured event MarkRemoved for myself:\n")
local text=string.format("Captured event MarkRemoved for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -736,7 +736,7 @@ end
function MARKER:onafterChanged(From, Event, To, EventData)
-- Debug info.
local text=string.format("Captured event MarkChange for myself:\n")
local text=string.format("Captured event MarkChange for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -768,7 +768,7 @@ end
function MARKER:onafterCoordUpdate(From, Event, To, Coordinate)
self:T(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@ -258,8 +258,7 @@ end
--- Returns if the unit is activated.
-- @param #UNIT self
-- @return #boolean true if Unit is activated.
-- @return #nil The DCS Unit is not existing or alive.
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
function UNIT:IsActive()
self:F2( self.UnitName )
@ -279,9 +278,7 @@ end
-- If the Unit is alive and active, true is returned.
-- If the Unit is alive but not active, false is returned.
-- @param #UNIT self
-- @return #boolean true if Unit is alive and active.
-- @return #boolean false if Unit is alive but not active.
-- @return #nil if the Unit is not existing or is not alive.
-- @return #boolean `true` if Unit is alive and active. `false` if Unit is alive but not active. `nil` if the Unit is not existing or is not alive.
function UNIT:IsAlive()
self:F3( self.UnitName )
@ -300,7 +297,6 @@ end
--- Returns the Unit's callsign - the localized string.
-- @param #UNIT self
-- @return #string The Callsign of the Unit.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetCallsign()
self:F2( self.UnitName )
@ -640,8 +636,7 @@ end
--- Returns the unit sensors.
-- @param #UNIT self
-- @return DCS#Unit.Sensors
-- @return #nil The DCS Unit is not existing or alive.
-- @return DCS#Unit.Sensors Table of sensors.
function UNIT:GetSensors()
self:F2( self.UnitName )
@ -661,7 +656,6 @@ end
--- Returns if the unit has sensors of a certain type.
-- @param #UNIT self
-- @return #boolean returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:HasSensors( ... )
self:F2( arg )
@ -678,7 +672,6 @@ end
--- Returns if the unit is SEADable.
-- @param #UNIT self
-- @return #boolean returns true if the unit is SEADable.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:HasSEAD()
self:F2()
@ -705,7 +698,6 @@ end
-- @param #UNIT self
-- @return #boolean Indicates if at least one of the unit's radar(s) is on.
-- @return DCS#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
-- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetRadar()
self:F2( self.UnitName )