mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Ops
- Laser
This commit is contained in:
parent
187093fa5a
commit
277eb2d09f
@ -736,7 +736,66 @@ do -- Airbase
|
||||
|
||||
end -- Airbase
|
||||
|
||||
do -- Spot
|
||||
|
||||
--- [DCS Class Spot](https://wiki.hoggitworld.com/view/DCS_Class_Spot)
|
||||
-- Represents a spot from laser or IR-pointer.
|
||||
-- @type Spot
|
||||
-- @field #Spot.Category Category enum that stores spot categories.
|
||||
|
||||
--- Enum that stores spot categories.
|
||||
-- @type Spot.Category
|
||||
-- @field #string INFRA_RED
|
||||
-- @field #string LASER
|
||||
|
||||
|
||||
--- Creates a laser ray emanating from the given object to a point in 3d space.
|
||||
-- @function [parent=#Spot] createLaser
|
||||
-- @param DCS#Object Source The source object of the laser.
|
||||
-- @param DCS#Vec3 LocalRef An optional 3D offset for the source.
|
||||
-- @param DCS#Vec3 Vec3 Target coordinate where the ray is pointing at.
|
||||
-- @param #number LaserCode Any 4 digit number between 1111 and 1788.
|
||||
-- @return #Spot
|
||||
|
||||
--- Creates an infrared ray emanating from the given object to a point in 3d space. Can be seen with night vision goggles.
|
||||
-- @function [parent=#Spot] createInfraRed
|
||||
-- @param DCS#Object Source Source position of the IR ray.
|
||||
-- @param DCS#Vec3 LocalRef An optional 3D offset for the source.
|
||||
-- @param DCS#Vec3 Vec3 Target coordinate where the ray is pointing at.
|
||||
-- @return #Spot
|
||||
|
||||
--- Returns a vec3 table of the x, y, and z coordinates for the position of the given object in 3D space. Coordinates are dependent on the position of the maps origin.
|
||||
-- @function [parent=#Spot] getPoint
|
||||
-- @param #Spot self
|
||||
-- @return DCS#Vec3 Point in 3D, where the beam is pointing at.
|
||||
|
||||
--- Sets the destination point from which the source of the spot is drawn toward.
|
||||
-- @function [parent=#Spot] setPoint
|
||||
-- @param #Spot self
|
||||
-- @param DCS#Vec3 Vec3 Point in 3D, where the beam is pointing at.
|
||||
|
||||
--- Returns the number that is used to define the laser code for which laser designation can track.
|
||||
-- @function [parent=#Spot] getCode
|
||||
-- @param #Spot self
|
||||
-- @return #number Code The laser code used.
|
||||
|
||||
--- Sets the number that is used to define the laser code for which laser designation can track.
|
||||
-- @function [parent=#Spot] setCode
|
||||
-- @param #Spot self
|
||||
-- @param #number Code The laser code. Default value is 1688.
|
||||
|
||||
--- Destroys the spot.
|
||||
-- @function [parent=#Spot] destroy
|
||||
-- @param #Spot self
|
||||
|
||||
--- Gets the category of the spot (laser or IR).
|
||||
-- @function [parent=#Spot] getCategory
|
||||
-- @param #Spot self
|
||||
-- @return #string Category.
|
||||
|
||||
Spot = {} --#Spot
|
||||
|
||||
end -- Spot
|
||||
|
||||
do -- Controller
|
||||
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||
|
||||
@ -1,21 +1,29 @@
|
||||
--- **Ops** - Enhanced Ground Group.
|
||||
--
|
||||
-- **Main Features:**
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Dynamically add and remove waypoints.
|
||||
-- * Convenient checks when the group enters or leaves a zone.
|
||||
-- * Sophisticated task queueing system.
|
||||
-- * Compatible with AUFTRAG class.
|
||||
-- * Easy change of ROE, alarm state, formation and other settings.
|
||||
-- * Many additional events that the mission designer can hook into.
|
||||
-- * Patrol waypoints *ad infinitum*
|
||||
-- * Easy change of ROE and alarm state, formation and other settings
|
||||
-- * Dynamically add and remove waypoints
|
||||
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||
-- * Convenient checks when the group enters or leaves a zone
|
||||
-- * Detection events for new, known and lost units
|
||||
-- * Simple LASER and IR-pointer setup
|
||||
-- * Compatible with AUFTRAG class
|
||||
-- * Many additional events that the mission designer can hook into
|
||||
--
|
||||
-- **Example Missions:**
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Armygroup).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ==
|
||||
--
|
||||
-- @module Ops.ArmyGroup
|
||||
-- @image OPS_ArmyGroup.png
|
||||
|
||||
@ -46,7 +54,12 @@ ARMYGROUP = {
|
||||
--- Army group element.
|
||||
-- @type ARMYGROUP.Element
|
||||
-- @field #string name Name of the element, i.e. the unit.
|
||||
-- @field Wrapper.Unit#UNIT unit The UNIT object.
|
||||
-- @field #string status The element status.
|
||||
-- @field #string typename Type name.
|
||||
-- @field #number length Length of element in meters.
|
||||
-- @field #number width Width of element in meters.
|
||||
-- @field #number height Height of element in meters.
|
||||
|
||||
--- Army Group version.
|
||||
-- @field #string version
|
||||
@ -85,10 +98,7 @@ function ARMYGROUP:New(Group)
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "FullStop", "Holding") -- Hold position.
|
||||
self:AddTransition("*", "Cruise", "Cruising") -- Cruise along the given route of waypoints.
|
||||
|
||||
self:AddTransition("*", "Rearm", "Rearming") -- Group is send to a coordinate and waits until ammo is refilled.
|
||||
self:AddTransition("Rearming", "Rearmed", "Cruising") -- Group was rearmed.
|
||||
|
||||
|
||||
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
||||
self:AddTransition("OnDetour", "DetourReached", "Cruising") -- Group reached the detour coordinate.
|
||||
|
||||
@ -178,6 +188,8 @@ end
|
||||
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
||||
function ARMYGROUP:AddTaskFireAtPoint(Coordinate, Clock, Radius, Nshots, WeaponType, Prio)
|
||||
|
||||
Coordinate=self:_CoordinateFromObject(Coordinate)
|
||||
|
||||
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
||||
|
||||
local task=self:AddTask(DCStask, Clock, nil, Prio)
|
||||
@ -196,6 +208,8 @@ end
|
||||
-- @return Ops.OpsGroup#OPSGROUP.Task The task table.
|
||||
function ARMYGROUP:AddTaskWaypointFireAtPoint(Coordinate, Waypoint, Radius, Nshots, WeaponType, Prio)
|
||||
|
||||
Coordinate=self:_CoordinateFromObject(Coordinate)
|
||||
|
||||
Waypoint=Waypoint or self:GetWaypointNext()
|
||||
|
||||
local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, Coordinate:GetVec2(), Radius, Nshots, WeaponType)
|
||||
@ -243,13 +257,6 @@ function ARMYGROUP:IsOnDetour()
|
||||
return self:Is("OnDetour")
|
||||
end
|
||||
|
||||
--- Check if the group is currently rearming.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group is rearming.
|
||||
function ARMYGROUP:IsRearming()
|
||||
return self:Is("Rearming")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -286,12 +293,24 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
||||
if self.detectionOn then
|
||||
self:_CheckDetectedUnits()
|
||||
end
|
||||
|
||||
-- Update position etc.
|
||||
self:_UpdatePosition()
|
||||
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
if self:IsRearming() then
|
||||
|
||||
local rearmed=self:_CheckAmmoFull()
|
||||
|
||||
if rearmed then
|
||||
self:Rearmed()
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Update position etc.
|
||||
self:_UpdatePosition()
|
||||
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
|
||||
end
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
@ -303,7 +322,7 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
||||
local alarm=self:GetAlarmstate()
|
||||
local speed=UTILS.MpsToKnots(self.velocity)
|
||||
local speedEx=UTILS.MpsToKnots(self:GetExpectedSpeed())
|
||||
local formation=self.option.Formation
|
||||
local formation=self.option.Formation or "unknown"
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("%s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
|
||||
@ -382,7 +401,11 @@ function ARMYGROUP:onafterSpawned(From, Event, To)
|
||||
end
|
||||
|
||||
-- Update route.
|
||||
self:Cruise(nil, self.option.Formation or self.optionDefault.Formation)
|
||||
if #self.waypoints>1 then
|
||||
self:Cruise(nil, self.option.Formation or self.optionDefault.Formation)
|
||||
else
|
||||
self:FullStop()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -549,6 +572,35 @@ function ARMYGROUP:onafterRearm(From, Event, To, Coordinate, Formation)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Rearming" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterRearming(From, Event, To)
|
||||
|
||||
-- Get current position.
|
||||
local pos=self:GetCoordinate()
|
||||
|
||||
-- Create a new waypoint.
|
||||
local wp=pos:WaypointGround(0)
|
||||
|
||||
-- Create new route consisting of only this position ==> Stop!
|
||||
self:Route({wp})
|
||||
|
||||
end
|
||||
|
||||
--- On after "Rearmed" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterRearmed(From, Event, To)
|
||||
|
||||
self:_CheckGroupDone(1)
|
||||
|
||||
end
|
||||
|
||||
--- On after "DetourReached" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -709,6 +761,8 @@ end
|
||||
-- @return Ops.OpsGroup#OPSGROUP.Waypoint Waypoint table.
|
||||
function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation, Updateroute)
|
||||
|
||||
local coordinate=self:_CoordinateFromObject(Coordinate)
|
||||
|
||||
-- Set waypoint index.
|
||||
local wpnumber=self:GetWaypointIndexAfterID(AfterWaypointWithID)
|
||||
|
||||
@ -721,7 +775,7 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
||||
Speed=Speed or self:GetSpeedCruise()
|
||||
|
||||
-- Create a Naval waypoint.
|
||||
local wp=Coordinate:WaypointGround(UTILS.KnotsToKmph(Speed), Formation)
|
||||
local wp=coordinate:WaypointGround(UTILS.KnotsToKmph(Speed), Formation)
|
||||
|
||||
-- Create waypoint data table.
|
||||
local waypoint=self:_CreateWaypoint(wp)
|
||||
@ -730,9 +784,9 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
||||
self:_AddWaypoint(waypoint, wpnumber)
|
||||
|
||||
-- Get closest point to road.
|
||||
waypoint.roadcoord=Coordinate:GetClosestPointToRoad(false)
|
||||
waypoint.roadcoord=coordinate:GetClosestPointToRoad(false)
|
||||
if waypoint.roadcoord then
|
||||
waypoint.roaddist=Coordinate:Get2DDistance(waypoint.roadcoord)
|
||||
waypoint.roaddist=coordinate:Get2DDistance(waypoint.roadcoord)
|
||||
else
|
||||
waypoint.roaddist=1000*1000 --1000 km.
|
||||
end
|
||||
@ -805,51 +859,61 @@ function ARMYGROUP:_InitGroup()
|
||||
|
||||
for _,_unit in pairs(units) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- TODO: this is wrong when grouping is used!
|
||||
local unittemplate=unit:GetTemplate()
|
||||
|
||||
local element={} --#ARMYGROUP.Element
|
||||
element.name=unit:GetName()
|
||||
element.typename=unit:GetTypeName()
|
||||
element.unit=unit
|
||||
element.status=OPSGROUP.ElementStatus.INUTERO
|
||||
element.unit=unit
|
||||
element.typename=unit:GetTypeName()
|
||||
element.skill=unittemplate.skill or "Unknown"
|
||||
element.ai=true
|
||||
element.category=element.unit:GetUnitCategory()
|
||||
element.categoryname=element.unit:GetCategoryName()
|
||||
element.size, element.length, element.height, element.width=unit:GetObjectSize()
|
||||
element.ammo0=self:GetAmmoUnit(unit, false)
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding element %s: status=%s, skill=%s, category=%s (%d), size: %.1f (L=%.1f H=%.1f W=%.1f)",
|
||||
element.name, element.status, element.skill, element.categoryname, element.category, element.size, element.length, element.height, element.width)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Add element to table.
|
||||
table.insert(self.elements, element)
|
||||
|
||||
self:GetAmmoUnit(unit, false)
|
||||
-- Get Descriptors.
|
||||
self.descriptors=self.descriptors or unit:GetDesc()
|
||||
|
||||
if unit:IsAlive() then
|
||||
-- Set type name.
|
||||
self.actype=self.actype or unit:GetTypeName()
|
||||
|
||||
if unit:IsAlive() then
|
||||
-- Trigger spawned event.
|
||||
self:ElementSpawned(element)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Get first unit. This is used to extract other parameters.
|
||||
local unit=self.group:GetUnit(1)
|
||||
|
||||
if unit then
|
||||
|
||||
self.descriptors=unit:GetDesc()
|
||||
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Debug info.
|
||||
if self.verbose>=1 then
|
||||
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
-- Debug info.
|
||||
if self.verbose>=1 then
|
||||
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -1,18 +1,26 @@
|
||||
--- **Ops** - Auftrag (mission) for Ops.
|
||||
--
|
||||
-- **Main Features:**
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Simplifies defining and executing DCS tasks.
|
||||
-- * Additional useful events.
|
||||
-- * Set mission start/stop times.
|
||||
-- * Set mission priority and urgency (can cancel running missions).
|
||||
-- * Simplifies defining and executing DCS tasks
|
||||
-- * Additional useful events
|
||||
-- * Set mission start/stop times
|
||||
-- * Set mission priority and urgency (can cancel running missions)
|
||||
-- * Specific mission options for ROE, ROT, formation, etc.
|
||||
-- * Interface to FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, WINGCOMMANDER and CHIEF classes.
|
||||
-- * FSM events when a mission is done, successful or failed.
|
||||
--
|
||||
-- * Compatible with FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, WINGCOMMANDER and CHIEF classes
|
||||
-- * FSM events when a mission is done, successful or failed
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Auftrag).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Auftrag
|
||||
-- @image OPS_Auftrag.png
|
||||
|
||||
|
||||
@ -1,16 +1,30 @@
|
||||
--- **Ops** - Enhanced Airborne Group.
|
||||
--
|
||||
-- **Main Features:**
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Monitor flight status of elements and/or the entire group.
|
||||
-- * Monitor fuel and ammo status.
|
||||
-- * Conveniently set radio freqencies, TACAN, ROE etc.
|
||||
-- * Sophisticated task queueing system.
|
||||
-- * Many additional events for each element and the whole group.
|
||||
-- * Monitor flight status of elements and/or the entire group
|
||||
-- * Monitor fuel and ammo status
|
||||
-- * Conveniently set radio freqencies, TACAN, ROE etc
|
||||
-- * Order helos to land at specifc coordinates
|
||||
-- * Dynamically add and remove waypoints
|
||||
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||
-- * Convenient checks when the group enters or leaves a zone
|
||||
-- * Detection events for new, known and lost units
|
||||
-- * Simple LASER and IR-pointer setup
|
||||
-- * Compatible with AUFTRAG class
|
||||
-- * Many additional events that the mission designer can hook into
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Flightgroup).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.FlightGroup
|
||||
-- @image OPS_FlightGroup.png
|
||||
|
||||
@ -186,6 +200,7 @@ FLIGHTGROUP.version="0.6.0"
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: VTOL aircraft.
|
||||
-- TODO: Use new UnitLost event instead of crash/dead.
|
||||
-- TODO: Options EPLRS, Afterburner restrict etc.
|
||||
-- DONE: Add TACAN beacon.
|
||||
@ -2729,6 +2744,7 @@ function FLIGHTGROUP:AddElementByName(unitname)
|
||||
element.ai=true
|
||||
end
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding element %s: status=%s, skill=%s, modex=%s, fuelmass=%.1f (%d), category=%d, categoryname=%s, callsign=%s, ai=%s",
|
||||
element.name, element.status, element.skill, element.modex, element.fuelmass, element.fuelrel*100, element.category, element.categoryname, element.callsign, tostring(element.ai))
|
||||
self:T(self.lid..text)
|
||||
|
||||
@ -1,25 +1,33 @@
|
||||
--- **Ops** - Enhanced Naval Group.
|
||||
--
|
||||
-- **Main Features:**
|
||||
-- ## Main Features:
|
||||
--
|
||||
-- * Dynamically add and remove waypoints.
|
||||
-- * Let the group steam into the wind.
|
||||
-- * Command a full stop.
|
||||
-- * Automatic pathfinding, e.g. around islands.
|
||||
-- * Collision warning, if group is heading towards a land mass.
|
||||
-- * Let a submarine dive and surface.
|
||||
-- * Sophisticated task queueing system.
|
||||
-- * Compatible with AUFTRAG class.
|
||||
-- * Convenient checks when the group enters or leaves a zone.
|
||||
-- * Many additional events that the mission designer can hook into.
|
||||
-- * Let the group steam into the wind
|
||||
-- * Command a full stop
|
||||
-- * Patrol waypoints *ad infinitum*
|
||||
-- * Collision warning, if group is heading towards a land mass
|
||||
-- * Automatic pathfinding, e.g. around islands
|
||||
-- * Let a submarine dive and surface
|
||||
-- * Manage TACAN and ICLS beacons
|
||||
-- * Dynamically add and remove waypoints
|
||||
-- * Sophisticated task queueing system (know when DCS tasks start and end)
|
||||
-- * Convenient checks when the group enters or leaves a zone
|
||||
-- * Detection events for new, known and lost units
|
||||
-- * Simple LASER and IR-pointer setup
|
||||
-- * Compatible with AUFTRAG class
|
||||
-- * Many additional events that the mission designer can hook into
|
||||
--
|
||||
-- **Example Missions:**
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Navygroup)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.NavyGroup
|
||||
-- @image OPS_NavyGroup.png
|
||||
|
||||
@ -655,7 +663,11 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
|
||||
end
|
||||
|
||||
-- Update route.
|
||||
self:Cruise()
|
||||
if #self.waypoints>1 then
|
||||
self:Cruise()
|
||||
else
|
||||
self:FullStop()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1124,10 +1136,10 @@ function NAVYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Depth, Up
|
||||
-- Check if a coordinate was given or at least a positionable.
|
||||
if not Coordinate:IsInstanceOf("COORDINATE") then
|
||||
if Coordinate:IsInstanceOf("POSITIONABLE") or Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE. Trying to get coordinate")
|
||||
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
|
||||
Coordinate=Coordinate:GetCoordinate()
|
||||
else
|
||||
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE!")
|
||||
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
--- **Ops** - Generic group enhancement functions.
|
||||
--- **Ops** - Generic group enhancement.
|
||||
--
|
||||
-- This class is **not** meant to be used itself by the end user.
|
||||
-- This class is **not** meant to be used itself by the end user. It contains common functionalities of derived classes for air, ground and sea.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.OpsGroup
|
||||
-- @image OPS_OpsGroup.png
|
||||
|
||||
@ -83,6 +85,8 @@
|
||||
-- @field #OPSGROUP.Callsign callsign Current callsign settings.
|
||||
-- @field #OPSGROUP.Callsign callsignDefault Default callsign settings.
|
||||
--
|
||||
-- @field #OPSGROUP.Spot spot Laser and IR spot.
|
||||
--
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *A small group of determined and like-minded people can change the course of history.* --- Mahatma Gandhi
|
||||
@ -136,6 +140,17 @@ OPSGROUP = {
|
||||
Ndestroyed = 0,
|
||||
}
|
||||
|
||||
|
||||
--- OPS group element.
|
||||
-- @type OPSGROUP.Element
|
||||
-- @field #string name Name of the element, i.e. the unit.
|
||||
-- @field Wrapper.Unit#UNIT unit The UNIT object.
|
||||
-- @field #string status The element status.
|
||||
-- @field #string typename Type name.
|
||||
-- @field #number length Length of element in meters.
|
||||
-- @field #number width Width of element in meters.
|
||||
-- @field #number height Height of element in meters.
|
||||
|
||||
--- Status of group element.
|
||||
-- @type OPSGROUP.ElementStatus
|
||||
-- @field #string INUTERO Element was not spawned yet or its status is unknown so far.
|
||||
@ -236,7 +251,6 @@ OPSGROUP.TaskType={
|
||||
-- @field #boolean EPLRS data link.
|
||||
-- @field #boolean Disperse Disperse under fire.
|
||||
|
||||
|
||||
--- Weapon range data.
|
||||
-- @type OPSGROUP.WeaponData
|
||||
-- @field #number BitType Type of weapon.
|
||||
@ -244,6 +258,16 @@ OPSGROUP.TaskType={
|
||||
-- @field #number RangeMax Max range in meters.
|
||||
-- @field #number ReloadTime Time to reload in seconds.
|
||||
|
||||
--- Laser and IR spot data.
|
||||
-- @type OPSGROUP.Spot
|
||||
-- @field DCS#Spot Laser Laser spot.
|
||||
-- @field DCS#Spot IR Infra-red spot.
|
||||
-- @field #number Code Laser code.
|
||||
-- @field Wrapper.Positionable#POSITIONABLE Target The target.
|
||||
-- @field Core.Point#COORDINATE Coordinate where the spot is pointing.
|
||||
-- @field #boolean On If true, the laser is on.
|
||||
-- @field Core.Timer#TIMER timer Spot timer.
|
||||
|
||||
--- Ammo data.
|
||||
-- @type OPSGROUP.Ammo
|
||||
-- @field #number Total Total amount of ammo.
|
||||
@ -281,13 +305,14 @@ OPSGROUP.TaskType={
|
||||
|
||||
--- NavyGroup version.
|
||||
-- @field #string version
|
||||
OPSGROUP.version="0.5.0"
|
||||
OPSGROUP.version="0.6.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Implement common functions.
|
||||
-- TODO: Suppression of fire.
|
||||
-- TODO: Add pseudo function.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@ -320,6 +345,12 @@ function OPSGROUP:New(Group)
|
||||
-- Init inzone set.
|
||||
self.inzones=SET_ZONE:New()
|
||||
|
||||
-- Laser.
|
||||
self.spot={}
|
||||
self.spot.On=false
|
||||
self.spot.timer=TIMER:New(OPSGROUP._UpdateLaser, self)
|
||||
self:SetLaser()
|
||||
|
||||
-- Init task counter.
|
||||
self.taskcurrent=0
|
||||
self.taskcounter=0
|
||||
@ -356,6 +387,14 @@ function OPSGROUP:New(Group)
|
||||
self:AddTransition("*", "EnterZone", "*") -- Group entered a certain zone.
|
||||
self:AddTransition("*", "LeaveZone", "*") -- Group leaves a certain zone.
|
||||
|
||||
self:AddTransition("*", "Rearm", "Rearming") -- Group is send to a coordinate and waits until ammo is refilled.
|
||||
self:AddTransition("Rearming", "Rearming", "Rearming") -- Group has arrived at the rearming coodinate and is waiting to be fully rearmed.
|
||||
self:AddTransition("Rearming", "Rearmed", "Cruising") -- Group was rearmed.
|
||||
|
||||
self:AddTransition("*", "LaserOn", "*") -- Turn laser on.
|
||||
self:AddTransition("*", "LaserOff", "*") -- Turn laser off.
|
||||
self:AddTransition("*", "LaserCode", "*") -- Switch laser code.
|
||||
|
||||
self:AddTransition("*", "TaskExecute", "*") -- Group will execute a task.
|
||||
self:AddTransition("*", "TaskPause", "*") -- Pause current task. Not implemented yet!
|
||||
self:AddTransition("*", "TaskCancel", "*") -- Cancel current task.
|
||||
@ -457,6 +496,19 @@ function OPSGROUP:SetDetection(Switch)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set detection on or off.
|
||||
-- If detection is on, detected targets of the group will be evaluated and FSM events triggered.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number Code Laser code. Default 1688.
|
||||
-- @param #boolean IROff If true, then dont switch on the additional IR pointer.
|
||||
-- @param #number UpdateTime Time interval in seconds the beam gets up for moving targets. Default every 0.5 sec.
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:SetLaser(Code, IROff, UpdateTime)
|
||||
self.spot.Code=Code or 1688
|
||||
self.spot.IRoff=IROff
|
||||
return self
|
||||
end
|
||||
|
||||
--- Define a SET of zones that trigger and event if the group enters or leaves any of the zones.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param Core.Set#SET_ZONE CheckZonesSet Set of zones.
|
||||
@ -502,9 +554,9 @@ function OPSGROUP:AddWeaponRange(RangeMin, RangeMax, BitType)
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
--- Get weapon data.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number BitType
|
||||
-- @param #number BitType Type of weapon.
|
||||
-- @return #OPSGROUP.WeaponData Weapon range data.
|
||||
function OPSGROUP:GetWeaponData(BitType)
|
||||
|
||||
@ -518,7 +570,6 @@ function OPSGROUP:GetWeaponData(BitType)
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Get set of detected units.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return Core.Set#SET_UNIT Set of detected units.
|
||||
@ -526,6 +577,41 @@ function OPSGROUP:GetDetectedUnits()
|
||||
return self.detectedunits
|
||||
end
|
||||
|
||||
--- Get highest detected threat. Detection must be turned on. The threat level is a number between 0 and 10, where 0 is the lowest, e.g. unarmed units.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number ThreatLevelMin Only consider threats with level greater or equal to this number. Default 1 (so unarmed units wont be considered).
|
||||
-- @param #number ThreatLevelMax Only consider threats with level smaller or queal to this number. Default 10.
|
||||
-- @return Wrapper.Unit#UNIT Highest threat unit detected by the group or `nil` if no threat is currently detected.
|
||||
-- @return #number Threat level.
|
||||
function OPSGROUP:GetThreat(ThreatLevelMin, ThreatLevelMax)
|
||||
|
||||
ThreatLevelMin=ThreatLevelMin or 1
|
||||
ThreatLevelMax=ThreatLevelMax or 10
|
||||
|
||||
local threat=nil --Wrapper.Unit#UNIT
|
||||
local level=0
|
||||
for _,_unit in pairs(self.detectedunits:GetSet()) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- Get threatlevel of unit.
|
||||
local threatlevel=unit:GetThreatLevel()
|
||||
|
||||
-- Check if withing threasholds.
|
||||
if threatlevel>=ThreatLevelMin and threatlevel<=ThreatLevelMax then
|
||||
|
||||
if threatlevel<level then
|
||||
level=threatlevel
|
||||
threat=unit
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return threat, level
|
||||
end
|
||||
|
||||
|
||||
--- Get MOOSE GROUP object.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return Wrapper.Group#GROUP Moose group object.
|
||||
@ -999,6 +1085,13 @@ function OPSGROUP:HasPassedFinalWaypoint()
|
||||
return self.passedfinalwp
|
||||
end
|
||||
|
||||
--- Check if the group is currently rearming.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #boolean If true, group is rearming.
|
||||
function OPSGROUP:IsRearming()
|
||||
return self:Is("Rearming")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Waypoint Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -1736,7 +1829,6 @@ function OPSGROUP:CountRemainingTasks()
|
||||
Ntot=Ntot+1
|
||||
|
||||
if task.type==OPSGROUP.TaskType.WAYPOINT then
|
||||
--TODO: maybe check that waypoint was not already passed?
|
||||
Nwp=Nwp+1
|
||||
elseif task.type==OPSGROUP.TaskType.SCHEDULED then
|
||||
Nsched=Nsched+1
|
||||
@ -1833,7 +1925,7 @@ function OPSGROUP:GetTaskByID(id, status)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- On after TaskExecute event.
|
||||
--- On after "TaskExecute" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
@ -2868,6 +2960,173 @@ function OPSGROUP:onafterLeaveZone(From, Event, To, Zone)
|
||||
self.inzones:Remove(zonename, true)
|
||||
end
|
||||
|
||||
--- On after "LaserOn" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Target Target Coordinate. Target can also be any POSITIONABLE from which we can obtain its coordinates.
|
||||
function OPSGROUP:onafterLaserOn(From, Event, To, Target)
|
||||
|
||||
-- Assume we got a coordinate.
|
||||
local coord=Target
|
||||
|
||||
-- Check if we have a POSITIONABLE.
|
||||
if Target:IsInstanceOf("POSITIONABLE") then
|
||||
local target=Target --Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
if target:IsAlive() then
|
||||
|
||||
self.spot.Target=Target
|
||||
coord=Target:GetCoordinate()
|
||||
|
||||
else
|
||||
self:E("WARNING: LASER target is not alive!")
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Set coordinate.
|
||||
self.spot.Coordinate=coord
|
||||
|
||||
-- Get the first element alive.
|
||||
local element=self:GetElementAlive()
|
||||
|
||||
if element then
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid.."Switching LASER on")
|
||||
|
||||
|
||||
-- Start timer that calls the update twice per sec.
|
||||
self.spot.timer:Start(nil, 0.5)
|
||||
|
||||
-- Set element.
|
||||
self.spot.element=element
|
||||
|
||||
-- Get DCS unit.
|
||||
local DCSunit=self.spot.element.unit:GetDCSObject()
|
||||
|
||||
-- Vec3.
|
||||
self.spot.vec3=coord:GetVec3()
|
||||
|
||||
-- Height offset.
|
||||
local offsetY=element.height
|
||||
|
||||
-- Create laser and IR beams.
|
||||
self.spot.Laser=Spot.createLaser(DCSunit, {x=0, y=offsetY, z=0}, self.spot.vec3, self.spot.Code or 1688)
|
||||
self.spot.IR=Spot.createInfraRed(DCSunit, {x=0, y=offsetY, z=0}, self.spot.vec3)
|
||||
|
||||
-- Laser is on.
|
||||
self.spot.On=true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- On after "LaserOff" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function OPSGROUP:onafterLaserOff(From, Event, To)
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid.."Switching LASER off")
|
||||
|
||||
-- "Destroy" the laser beam.
|
||||
self.spot.Laser:destroy()
|
||||
self.spot.IR:destroy()
|
||||
|
||||
-- Set to nil.
|
||||
self.spot.Laser=nil
|
||||
self.spot.IR=nil
|
||||
|
||||
-- Laser is off.
|
||||
self.spot.On=false
|
||||
|
||||
end
|
||||
|
||||
--- On after "LaserCode" event. Changes the LASER code.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Code Laser code. Default is 1688.
|
||||
function OPSGROUP:onafterLaserCode(From, Event, To, Code)
|
||||
|
||||
-- Default is 1688.
|
||||
self.spot.Code=Code or 1688
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Setting LASER Code to %d", self.spot.Code))
|
||||
|
||||
if self.spot.On then
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Updating LASER Code to %d", self.spot.Code))
|
||||
|
||||
-- Set LASER code.
|
||||
self.spot.Laser:setCode(self.spot.Code)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Update laser point.
|
||||
-- @param #OPSGROUP self
|
||||
function OPSGROUP:_UpdateLaser()
|
||||
|
||||
-- Firstly, check if laser is on.
|
||||
if self.spot.On then
|
||||
|
||||
---
|
||||
-- LASER is ON
|
||||
--´-
|
||||
|
||||
-- Check if we have a POSITIONABLE to lase.
|
||||
if self.spot.Target then
|
||||
|
||||
---
|
||||
-- Lasing a possibly moving target
|
||||
---
|
||||
|
||||
if self.spot.Target:IsAlive() then
|
||||
|
||||
-- Get current target position.
|
||||
local vec3=self.spot.Target:GetVec3()
|
||||
|
||||
-- Calculate distance
|
||||
local dist=UTILS.VecDist3D(vec3, self.spot.vec3)
|
||||
|
||||
-- Update laser if target moved more than one meter.
|
||||
if dist>1 then
|
||||
|
||||
-- Store current position.
|
||||
self.spot.vec3=vec3
|
||||
|
||||
-- Update beam coordinate.
|
||||
self.spot.Coordinate:UpdateFromVec3(vec3)
|
||||
|
||||
-- Set the new laser target point.
|
||||
self.spot.Laser:setPoint(vec3)
|
||||
self.spot.IR:setPoint(vec3)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Switch laser off.
|
||||
self:T(self.lid.."Target is not alive any more ==> switching LASER off")
|
||||
self:LaserOff()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- On after "ElementDestroyed" event.
|
||||
-- @param #OPSGROUP self
|
||||
@ -2902,9 +3161,22 @@ end
|
||||
-- @param #OPSGROUP.Element Element The flight group element.
|
||||
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||
self:T(self.lid..string.format("Element dead %s", Element.name))
|
||||
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||
|
||||
-- Check if element was lasing and if so, switch to another unit alive to lase.
|
||||
if self.spot.On and self.spot.element.name==Element.name then
|
||||
|
||||
-- Switch laser off.
|
||||
self:LaserOff()
|
||||
|
||||
-- If there is another element alive, switch laser on again.
|
||||
if self:GetNelements()>0 then
|
||||
self:__LaserOn(-1, self.spot.Target or self.spot.Coordinate)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "Dead" event.
|
||||
@ -3172,10 +3444,19 @@ end
|
||||
-- @return #boolean If true, ammo is full.
|
||||
function OPSGROUP:_CheckAmmoFull()
|
||||
|
||||
for _,_ammo in pairs(self.ammo) do
|
||||
-- Get current ammo.
|
||||
local ammo=self:GetAmmoTot()
|
||||
|
||||
for key,value in pairs(self.ammo) do
|
||||
|
||||
if ammo[key]<value then
|
||||
-- At least one type of ammunition is less than when spawned.
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -3469,16 +3750,25 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid)
|
||||
|
||||
-- Remove detour waypoint.
|
||||
opsgroup:RemoveWaypointByID(uid)
|
||||
|
||||
-- Trigger event.
|
||||
opsgroup:DetourReached()
|
||||
|
||||
if waypoint.detour==0 then
|
||||
opsgroup:FullStop()
|
||||
elseif waypoint.detour==1 then
|
||||
opsgroup:Cruise()
|
||||
if opsgroup:IsRearming() then
|
||||
|
||||
-- Trigger Rearming event.
|
||||
opsgroup:Rearming()
|
||||
|
||||
else
|
||||
opsgroup:E("ERROR: waypoint.detour should be 0 or 1")
|
||||
|
||||
-- Trigger DetourReached event.
|
||||
opsgroup:DetourReached()
|
||||
|
||||
if waypoint.detour==0 then
|
||||
opsgroup:FullStop()
|
||||
elseif waypoint.detour==1 then
|
||||
opsgroup:Cruise()
|
||||
else
|
||||
opsgroup:E("ERROR: waypoint.detour should be 0 or 1")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
@ -4510,6 +4800,23 @@ function OPSGROUP:GetElementByName(unitname)
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the first element of a group, which is alive.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #OPSGROUP.Element The element or `#nil` if no element is alive any more.
|
||||
function OPSGROUP:GetElementAlive()
|
||||
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --#OPSGROUP.Element
|
||||
if element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||
if element.unit and element.unit:IsAlive() then
|
||||
return element
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get number of elements alive.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string status (Optional) Only count number, which are in a special status.
|
||||
@ -4813,6 +5120,26 @@ function OPSGROUP:_CheckStuck()
|
||||
|
||||
end
|
||||
|
||||
--- Get coordinate from an object.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param Wrapper.Object#OBJECT Object The object.
|
||||
-- @return Core.Point#COORDINATE The coordinate of the object.
|
||||
function OPSGROUP:_CoordinateFromObject(Object)
|
||||
|
||||
if Object:IsInstanceOf("COORDINATE") then
|
||||
return Object
|
||||
else
|
||||
if Object:IsInstanceOf("POSITIONABLE") or Object:IsInstanceOf("ZONE_BASE") then
|
||||
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
|
||||
return Object:GetCoordinate()
|
||||
else
|
||||
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user