mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #1077 from FlightControl-Master/FF/Develop
New classes, fixes and improvements.
This commit is contained in:
@@ -238,6 +238,8 @@ AIRBASE.Normandy = {
|
||||
-- * AIRBASE.PersianGulf.Sharjah_Intl
|
||||
-- * AIRBASE.PersianGulf.Shiraz_International_Airport
|
||||
-- * AIRBASE.PersianGulf.Kerman_Airport
|
||||
-- * AIRBASE.PersianGulf.Jiroft_Airport
|
||||
-- * AIRBASE.PersianGulf.Lavan_Island_Airport
|
||||
-- @field PersianGulf
|
||||
AIRBASE.PersianGulf = {
|
||||
["Fujairah_Intl"] = "Fujairah Intl",
|
||||
@@ -259,6 +261,8 @@ AIRBASE.PersianGulf = {
|
||||
["Sharjah_Intl"] = "Sharjah Intl",
|
||||
["Shiraz_International_Airport"] = "Shiraz International Airport",
|
||||
["Kerman_Airport"] = "Kerman Airport",
|
||||
["Jiroft_Airport"] = "Jiroft Airport",
|
||||
["Lavan_Island_Airport"] = "Lavan Island Airport",
|
||||
}
|
||||
|
||||
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
-- * @{#CONTROLLABLE.OptionROEReturnFirePossible}
|
||||
-- * @{#CONTROLLABLE.OptionROEEvadeFirePossible}
|
||||
--
|
||||
-- ## 5.2) Rule on thread:
|
||||
-- ## 5.2) Reaction On Thread:
|
||||
--
|
||||
-- * @{#CONTROLLABLE.OptionROTNoReaction}
|
||||
-- * @{#CONTROLLABLE.OptionROTPassiveDefense}
|
||||
@@ -347,16 +347,26 @@ function CONTROLLABLE:PushTask( DCSTask, WaitTime )
|
||||
local DCSControllable = self:GetDCSObject()
|
||||
|
||||
if DCSControllable then
|
||||
local Controller = self:_GetController()
|
||||
|
||||
local DCSControllableName = self:GetName()
|
||||
|
||||
-- When a controllable SPAWNs, it takes about a second to get the controllable in the simulator. Setting tasks to unspawned controllables provides unexpected results.
|
||||
-- Therefore we schedule the functions to set the mission and options for the Controllable.
|
||||
-- Controller:pushTask( DCSTask )
|
||||
-- Controller:pushTask( DCSTask )
|
||||
|
||||
local function PushTask( Controller, DCSTask )
|
||||
if self and self:IsAlive() then
|
||||
local Controller = self:_GetController()
|
||||
Controller:pushTask( DCSTask )
|
||||
else
|
||||
BASE:E( { DCSControllableName .. " is not alive anymore.", DCSTask = DCSTask } )
|
||||
end
|
||||
end
|
||||
|
||||
if WaitTime then
|
||||
self.TaskScheduler:Schedule( Controller, Controller.pushTask, { DCSTask }, WaitTime )
|
||||
if not WaitTime or WaitTime == 0 then
|
||||
PushTask( self, DCSTask )
|
||||
else
|
||||
Controller:pushTask( DCSTask )
|
||||
self.TaskScheduler:Schedule( self, PushTask, { DCSTask }, WaitTime )
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -367,7 +377,7 @@ end
|
||||
|
||||
--- Clearing the Task Queue and Setting the Task on the queue from the controllable.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #DCS.Task DCSTask DCS Task array.
|
||||
-- @param DCS#Task DCSTask DCS Task array.
|
||||
-- @param #number WaitTime Time in seconds, before the task is set.
|
||||
-- @return Wrapper.Controllable#CONTROLLABLE self
|
||||
function CONTROLLABLE:SetTask( DCSTask, WaitTime )
|
||||
@@ -547,9 +557,9 @@ end
|
||||
|
||||
|
||||
|
||||
--- Executes a command action
|
||||
--- Executes a command action for the CONTROLLABLE.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param DCS#Command DCSCommand
|
||||
-- @param DCS#Command DCSCommand The command to be executed.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:SetCommand( DCSCommand )
|
||||
self:F2( DCSCommand )
|
||||
@@ -637,9 +647,122 @@ function CONTROLLABLE:StartUncontrolled(delay)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Give the CONTROLLABLE the command to activate a beacon. See [DCS_command_activateBeacon](https://wiki.hoggitworld.com/view/DCS_command_activateBeacon) on Hoggit.
|
||||
-- For specific beacons like TACAN use the more convenient @{#BEACON} class.
|
||||
-- Note that a controllable can only have one beacon activated at a time with the execption of ICLS.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param Core.Radio#BEACON.Type Type Beacon type (VOR, DME, TACAN, RSBN, ILS etc).
|
||||
-- @param Core.Radio#BEACON.System System Beacon system (VOR, DME, TACAN, RSBN, ILS etc).
|
||||
-- @param #number Frequency Frequency in Hz the beacon is running on. Use @{#UTILS.TACANToFrequency} to generate a frequency for TACAN beacons.
|
||||
-- @param #number UnitID The ID of the unit the beacon is attached to. Usefull if more units are in one group.
|
||||
-- @param #number Channel Channel the beacon is using. For, e.g. TACAN beacons.
|
||||
-- @param #string ModeChannel The TACAN mode of the beacon, i.e. "X" or "Y".
|
||||
-- @param #boolean AA If true, create and Air-Air beacon. IF nil, automatically set if CONTROLLABLE depending on whether unit is and aircraft or not.
|
||||
-- @param #string Callsign Morse code identification callsign.
|
||||
-- @param #boolean Bearing If true, beacon provides bearing information - if supported by the unit the beacon is attached to.
|
||||
-- @param #number Delay (Optional) Delay in seconds before the beacon is activated.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:CommandActivateBeacon(Type, System, Frequency, UnitID, Channel, ModeChannel, AA, Callsign, Bearing, Delay)
|
||||
|
||||
AA=AA or self:IsAir()
|
||||
UnitID=UnitID or self:GetID()
|
||||
|
||||
-- Command
|
||||
local CommandActivateBeacon= {
|
||||
id = "ActivateBeacon",
|
||||
params = {
|
||||
["type"] = Type,
|
||||
["system"] = System,
|
||||
["frequency"] = Frequency,
|
||||
["unitId"] = UnitID,
|
||||
["channel"] = Channel,
|
||||
["modeChannel"] = ModeChannel,
|
||||
["AA"] = AA,
|
||||
["callsign"] = Callsign,
|
||||
["bearing"] = Bearing,
|
||||
}
|
||||
}
|
||||
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandActivateBeacon, {self, Type, System, Frequency, UnitID, Channel, ModeChannel, AA, Callsign, Bearing}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandActivateBeacon)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Activate ICLS system of the CONTROLLABLE. The controllable should be an aircraft carrier!
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #number Channel ICLS channel.
|
||||
-- @param #number UnitID The ID of the unit the ICLS system is attached to. Useful if more units are in one group.
|
||||
-- @param #string Callsign Morse code identification callsign.
|
||||
-- @param #number Delay (Optional) Delay in seconds before the ICLS is deactivated.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:CommandActivateICLS(Channel, UnitID, Callsign, Delay)
|
||||
self:F()
|
||||
|
||||
-- Command to activate ICLS system.
|
||||
local CommandActivateICLS= {
|
||||
id = "ActivateICLS",
|
||||
params= {
|
||||
["type"] = BEACON.Type.ICLS,
|
||||
["channel"] = Channel,
|
||||
["unitId"] = UnitID,
|
||||
["callsign"] = Callsign,
|
||||
}
|
||||
}
|
||||
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandActivateICLS, {self}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandActivateICLS)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Deactivate the active beacon of the CONTROLLABLE.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #number Delay (Optional) Delay in seconds before the beacon is deactivated.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:CommandDeactivateBeacon(Delay)
|
||||
self:F()
|
||||
|
||||
-- Command to deactivate
|
||||
local CommandDeactivateBeacon={id='DeactivateBeacon', params={}}
|
||||
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandActivateBeacon, {self}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandDeactivateBeacon)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Deactivate the ICLS of the CONTROLLABLE.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #number Delay (Optional) Delay in seconds before the ICLS is deactivated.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:CommandDeactivateICLS(Delay)
|
||||
self:F()
|
||||
|
||||
-- Command to deactivate
|
||||
local CommandDeactivateICLS={id='DeactivateICLS', params={}}
|
||||
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandDeactivateICLS, {self}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandDeactivateICLS)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-- TASKS FOR AIR CONTROLLABLES
|
||||
|
||||
|
||||
--- (AIR) Attack a Controllable.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked.
|
||||
@@ -877,6 +1000,38 @@ function CONTROLLABLE:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
|
||||
return DCSTask
|
||||
end
|
||||
|
||||
--- (AIR) Orbit at a position with at a given altitude and speed. Optionally, a race track pattern can be specified.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param Core.Point#COORDINATE Coord Coordinate at which the CONTROLLABLE orbits.
|
||||
-- @param #number Altitude Altitude in meters of the orbit pattern.
|
||||
-- @param #number Speed Speed [m/s] flying the orbit pattern
|
||||
-- @param Core.Point#COORDINATE CoordRaceTrack (Optional) If this coordinate is specified, the CONTROLLABLE will fly a race-track pattern using this and the initial coordinate.
|
||||
-- @return #CONTROLLABLE self
|
||||
function CONTROLLABLE:TaskOrbit(Coord, Altitude, Speed, CoordRaceTrack)
|
||||
|
||||
local Pattern=AI.Task.OrbitPattern.CIRCLE
|
||||
|
||||
local P1=Coord:GetVec2()
|
||||
local P2=nil
|
||||
if CoordRaceTrack then
|
||||
Pattern=AI.Task.OrbitPattern.RACE_TRACK
|
||||
P2=CoordRaceTrack:GetVec2()
|
||||
end
|
||||
|
||||
local Task = {
|
||||
id = 'Orbit',
|
||||
params = {
|
||||
pattern = Pattern,
|
||||
point = P1,
|
||||
point2 = P2,
|
||||
speed = Speed,
|
||||
altitude = Altitude,
|
||||
}
|
||||
}
|
||||
|
||||
return Task
|
||||
end
|
||||
|
||||
--- (AIR) Orbit at the current position of the first unit of the controllable at a specified alititude.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #number Altitude The altitude [m] to hold the position.
|
||||
@@ -965,11 +1120,7 @@ function CONTROLLABLE:TaskRefueling()
|
||||
-- params = {}
|
||||
-- }
|
||||
|
||||
local DCSTask
|
||||
DCSTask = { id = 'Refueling',
|
||||
params = {
|
||||
},
|
||||
},
|
||||
local DCSTask={id='Refueling', params={}}
|
||||
|
||||
self:T3( { DCSTask } )
|
||||
return DCSTask
|
||||
@@ -2109,7 +2260,7 @@ do -- Route methods
|
||||
FromCoordinate = FromCoordinate or self:GetCoordinate()
|
||||
|
||||
-- Get path and path length on road including the end points (From and To).
|
||||
local PathOnRoad, LengthOnRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, true)
|
||||
local PathOnRoad, LengthOnRoad, GotPath =FromCoordinate:GetPathOnRoad(ToCoordinate, true)
|
||||
|
||||
-- Get the length only(!) on the road.
|
||||
local _,LengthRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, false)
|
||||
@@ -2121,7 +2272,7 @@ do -- Route methods
|
||||
-- Calculate the direct distance between the initial and final points.
|
||||
local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate)
|
||||
|
||||
if PathOnRoad then
|
||||
if GotPath then
|
||||
|
||||
-- Off road part of the rout: Total=OffRoad+OnRoad.
|
||||
LengthOffRoad=LengthOnRoad-LengthRoad
|
||||
@@ -2144,7 +2295,7 @@ do -- Route methods
|
||||
local canroad=false
|
||||
|
||||
-- Check if a valid path on road could be found.
|
||||
if PathOnRoad and LengthDirect > 2000 then -- if the length of the movement is less than 1 km, drive directly.
|
||||
if GotPath and LengthDirect > 2000 then -- if the length of the movement is less than 1 km, drive directly.
|
||||
-- Check whether the road is very long compared to direct path.
|
||||
if LongRoad and Shortcut then
|
||||
|
||||
@@ -3073,6 +3224,3 @@ function CONTROLLABLE:IsAirPlane()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Message APIs
|
||||
@@ -325,7 +325,7 @@ end
|
||||
-- So all event listeners will catch the destroy event of this group for each unit in the group.
|
||||
-- To raise these events, provide the `GenerateEvent` parameter.
|
||||
-- @param #GROUP self
|
||||
-- @param #boolean GenerateEvent true if you want to generate a crash or dead event for each unit.
|
||||
-- @param #boolean GenerateEvent If true, a crash or dead event for each unit is generated. If false, if no event is triggered. If nil, a RemoveUnit event is triggered.
|
||||
-- @usage
|
||||
-- -- Air unit example: destroy the Helicopter and generate a S_EVENT_CRASH for each unit in the Helicopter group.
|
||||
-- Helicopter = GROUP:FindByName( "Helicopter" )
|
||||
@@ -1477,29 +1477,61 @@ end
|
||||
--
|
||||
-- @param Wrapper.Group#GROUP self
|
||||
-- @param #table Template (optional) The template of the Group retrieved with GROUP:GetTemplate(). If the template is not provided, the template will be retrieved of the group itself.
|
||||
-- @param #boolean Reset Reset positons if TRUE.
|
||||
-- @return Wrapper.Group#GROUP self
|
||||
function GROUP:Respawn( Template, Reset )
|
||||
|
||||
if not Template then
|
||||
Template = self:GetTemplate()
|
||||
end
|
||||
-- Given template or get old.
|
||||
Template = Template or self:GetTemplate()
|
||||
|
||||
-- Get correct heading.
|
||||
local function _Heading(course)
|
||||
local h
|
||||
if course<=180 then
|
||||
h=math.rad(course)
|
||||
else
|
||||
h=-math.rad(360-course)
|
||||
end
|
||||
return h
|
||||
end
|
||||
|
||||
-- First check if group is alive.
|
||||
if self:IsAlive() then
|
||||
|
||||
-- Respawn zone.
|
||||
local Zone = self.InitRespawnZone -- Core.Zone#ZONE
|
||||
|
||||
-- Zone position or current group position.
|
||||
local Vec3 = Zone and Zone:GetVec3() or self:GetVec3()
|
||||
|
||||
-- From point of the template.
|
||||
local From = { x = Template.x, y = Template.y }
|
||||
|
||||
-- X, Y
|
||||
Template.x = Vec3.x
|
||||
Template.y = Vec3.z
|
||||
|
||||
--Template.x = nil
|
||||
--Template.y = nil
|
||||
|
||||
-- Debug number of units.
|
||||
self:F( #Template.units )
|
||||
|
||||
-- Reset position etc?
|
||||
if Reset == true then
|
||||
|
||||
-- Loop over units in group.
|
||||
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
||||
local GroupUnit = UnitData -- Wrapper.Unit#UNIT
|
||||
self:F( GroupUnit:GetName() )
|
||||
self:F(GroupUnit:GetName())
|
||||
|
||||
if GroupUnit:IsAlive() then
|
||||
self:F( "Alive" )
|
||||
local GroupUnitVec3 = GroupUnit:GetVec3()
|
||||
self:F("Alive")
|
||||
|
||||
-- Get unit position vector.
|
||||
local GroupUnitVec3 = GroupUnit:GetVec3()
|
||||
|
||||
-- Check if respawn zone is set.
|
||||
if Zone then
|
||||
if self.InitRespawnRandomizePositionZone then
|
||||
GroupUnitVec3 = Zone:GetRandomVec3()
|
||||
@@ -1512,17 +1544,38 @@ function GROUP:Respawn( Template, Reset )
|
||||
end
|
||||
end
|
||||
|
||||
-- Altitude
|
||||
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or GroupUnit:GetHeading()
|
||||
|
||||
-- Unit position. Why not simply take the current positon?
|
||||
if Zone then
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
else
|
||||
Template.units[UnitID].x=GroupUnitVec3.x
|
||||
Template.units[UnitID].y=GroupUnitVec3.z
|
||||
end
|
||||
|
||||
-- Set heading.
|
||||
Template.units[UnitID].heading = _Heading(self.InitRespawnHeading and self.InitRespawnHeading or GroupUnit:GetHeading())
|
||||
Template.units[UnitID].psi = -Template.units[UnitID].heading
|
||||
|
||||
-- Debug.
|
||||
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
else -- Reset=false or nil
|
||||
|
||||
-- Loop over template units.
|
||||
for UnitID, TemplateUnitData in pairs( Template.units ) do
|
||||
|
||||
self:F( "Reset" )
|
||||
|
||||
-- Position from template.
|
||||
local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.y }
|
||||
|
||||
-- Respawn zone position.
|
||||
if Zone then
|
||||
if self.InitRespawnRandomizePositionZone then
|
||||
GroupUnitVec3 = Zone:GetRandomVec3()
|
||||
@@ -1535,23 +1588,36 @@ function GROUP:Respawn( Template, Reset )
|
||||
end
|
||||
end
|
||||
|
||||
-- Set altitude.
|
||||
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
||||
|
||||
-- Unit position.
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
|
||||
-- Heading
|
||||
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading
|
||||
|
||||
-- Debug.
|
||||
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self:Destroy()
|
||||
_DATABASE:Spawn( Template )
|
||||
-- Destroy old group. Dont trigger any dead/crash events since this is a respawn.
|
||||
self:Destroy(false)
|
||||
|
||||
self:T({Template=Template})
|
||||
|
||||
-- Spawn new group.
|
||||
_DATABASE:Spawn(Template)
|
||||
|
||||
-- Reset events.
|
||||
self:ResetEvents()
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1652,6 +1718,7 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
|
||||
-- Destroy old group.
|
||||
self:Destroy(false)
|
||||
|
||||
-- Spawn new group.
|
||||
_DATABASE:Spawn( SpawnTemplate )
|
||||
|
||||
-- Reset events.
|
||||
@@ -1800,8 +1867,8 @@ do -- Route methods
|
||||
--
|
||||
-- @param #GROUP self
|
||||
-- @param Wrapper.Airbase#AIRBASE RTBAirbase (optional) The @{Wrapper.Airbase} to return to. If blank, the controllable will return to the nearest friendly airbase.
|
||||
-- @param #number Speed (optional) The Speed, if no Speed is given, the maximum Speed of the first unit is selected.
|
||||
-- @return #GROUP
|
||||
-- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected.
|
||||
-- @return #GROUP self
|
||||
function GROUP:RouteRTB( RTBAirbase, Speed )
|
||||
self:F( { RTBAirbase:GetName(), Speed } )
|
||||
|
||||
@@ -1811,17 +1878,19 @@ do -- Route methods
|
||||
|
||||
if RTBAirbase then
|
||||
|
||||
-- If speed is not given take 80% of max speed.
|
||||
local Speed=Speed or self:GetSpeedMax()*0.8
|
||||
|
||||
--[[
|
||||
local GroupPoint = self:GetVec2()
|
||||
local GroupVelocity = self:GetUnit(1):GetDesc().speedMax
|
||||
|
||||
local GroupVelocity = self:GetUnit(1):GetDesc().speedMax
|
||||
local PointFrom = {}
|
||||
PointFrom.x = GroupPoint.x
|
||||
PointFrom.y = GroupPoint.y
|
||||
PointFrom.type = "Turning Point"
|
||||
PointFrom.action = "Turning Point"
|
||||
PointFrom.speed = GroupVelocity
|
||||
|
||||
|
||||
|
||||
local PointTo = {}
|
||||
local AirbasePointVec2 = RTBAirbase:GetPointVec2()
|
||||
local AirbaseAirPoint = AirbasePointVec2:WaypointAir(
|
||||
@@ -1832,21 +1901,42 @@ do -- Route methods
|
||||
)
|
||||
|
||||
AirbaseAirPoint["airdromeId"] = RTBAirbase:GetID()
|
||||
AirbaseAirPoint["speed_locked"] = true,
|
||||
AirbaseAirPoint["speed_locked"] = true
|
||||
]]
|
||||
|
||||
-- Curent (from) waypoint.
|
||||
local coord=self:GetCoordinate()
|
||||
local PointFrom=coord:WaypointAirTurningPoint(nil, Speed)
|
||||
|
||||
-- Airbase coordinate.
|
||||
--local PointAirbase=RTBAirbase:GetCoordinate():SetAltitude(coord.y):WaypointAirTurningPoint(nil ,Speed)
|
||||
|
||||
-- Landing waypoint. More general than prev version since it should also work with FAPRS and ships.
|
||||
local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase)
|
||||
|
||||
-- Waypoint table.
|
||||
local Points={PointFrom, PointLanding}
|
||||
--local Points={PointFrom, PointAirbase, PointLanding}
|
||||
|
||||
self:F(AirbaseAirPoint )
|
||||
|
||||
local Points = { PointFrom, AirbaseAirPoint }
|
||||
|
||||
self:T3( Points )
|
||||
-- Debug info.
|
||||
self:T3(Points)
|
||||
|
||||
local Template = self:GetTemplate()
|
||||
Template.route.points = Points
|
||||
self:Respawn( Template )
|
||||
|
||||
--self:Route( Points )
|
||||
-- Get group template.
|
||||
local Template=self:GetTemplate()
|
||||
|
||||
-- Set route points.
|
||||
Template.route.points=Points
|
||||
|
||||
-- Respawn the group.
|
||||
self:Respawn(Template, true)
|
||||
|
||||
-- Route the group or this will not work.
|
||||
self:Route(Points)
|
||||
else
|
||||
|
||||
-- Clear all tasks.
|
||||
self:ClearTasks()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -656,6 +656,14 @@ function POSITIONABLE:GetVelocityMPS()
|
||||
return 0
|
||||
end
|
||||
|
||||
--- Returns the POSITIONABLE velocity in knots.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return #number The velocity in knots.
|
||||
function POSITIONABLE:GetVelocityKNOTS()
|
||||
self:F2( self.PositionableName )
|
||||
return UTILS.MpsToKnots(self:GetVelocityMPS())
|
||||
end
|
||||
|
||||
--- Returns the Angle of Attack of a positionable.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return #number Angle of attack in degrees.
|
||||
@@ -706,8 +714,8 @@ end
|
||||
|
||||
--- Returns the unit's climb or descent angle.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return #number Climb or descent angle in degrees.
|
||||
function POSITIONABLE:GetClimbAnge()
|
||||
-- @return #number Climb or descent angle in degrees. Or 0 if velocity vector norm is zero (or nil). Or nil, if the position of the POSITIONABLE returns nil.
|
||||
function POSITIONABLE:GetClimbAngle()
|
||||
|
||||
-- Get position of the unit.
|
||||
local unitpos = self:GetPosition()
|
||||
@@ -719,10 +727,17 @@ function POSITIONABLE:GetClimbAnge()
|
||||
|
||||
if unitvel and UTILS.VecNorm(unitvel)~=0 then
|
||||
|
||||
return math.asin(unitvel.y/UTILS.VecNorm(unitvel))
|
||||
|
||||
-- Calculate climb angle.
|
||||
local angle=math.asin(unitvel.y/UTILS.VecNorm(unitvel))
|
||||
|
||||
-- Return angle in degrees.
|
||||
return math.deg(angle)
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the pitch angle of a unit.
|
||||
|
||||
@@ -902,29 +902,31 @@ end
|
||||
function UNIT:InAir()
|
||||
self:F2( self.UnitName )
|
||||
|
||||
-- Get DCS unit object.
|
||||
local DCSUnit = self:GetDCSObject() --DCS#Unit
|
||||
|
||||
if DCSUnit then
|
||||
-- Implementation of workaround. The original code is below.
|
||||
-- This to simulate the landing on buildings.
|
||||
|
||||
local UnitInAir = true
|
||||
|
||||
-- Get DCS result of whether unit is in air or not.
|
||||
local UnitInAir = DCSUnit:inAir()
|
||||
|
||||
-- Get unit category.
|
||||
local UnitCategory = DCSUnit:getDesc().category
|
||||
if UnitCategory == Unit.Category.HELICOPTER then
|
||||
|
||||
-- If DCS says that it is in air, check if this is really the case, since we might have landed on a building where inAir()=true but actually is not.
|
||||
-- This is a workaround since DCS currently does not acknoledge that helos land on buildings.
|
||||
-- Note however, that the velocity check will fail if the ground is moving, e.g. on an aircraft carrier!
|
||||
if UnitInAir==true and UnitCategory == Unit.Category.HELICOPTER then
|
||||
local VelocityVec3 = DCSUnit:getVelocity()
|
||||
local Velocity = ( VelocityVec3.x ^ 2 + VelocityVec3.y ^ 2 + VelocityVec3.z ^ 2 ) ^ 0.5 -- in meters / sec
|
||||
local Velocity = UTILS.VecNorm(VelocityVec3)
|
||||
local Coordinate = DCSUnit:getPoint()
|
||||
local LandHeight = land.getHeight( { x = Coordinate.x, y = Coordinate.z } )
|
||||
local Height = Coordinate.y - LandHeight
|
||||
if Velocity < 1 and Height <= 60 then
|
||||
UnitInAir = false
|
||||
end
|
||||
else
|
||||
UnitInAir = DCSUnit:inAir()
|
||||
end
|
||||
|
||||
|
||||
|
||||
self:T3( UnitInAir )
|
||||
return UnitInAir
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user