mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-22 16:05:25 +00:00
Weapon
This commit is contained in:
@@ -679,10 +679,11 @@ do -- Weapon
|
|||||||
|
|
||||||
--- Weapon.Category enum that stores weapon categories.
|
--- Weapon.Category enum that stores weapon categories.
|
||||||
-- @type Weapon.Category
|
-- @type Weapon.Category
|
||||||
-- @field SHELL
|
-- @field #number SHELL Shell.
|
||||||
-- @field MISSILE
|
-- @field #number MISSILE Missile
|
||||||
-- @field ROCKET
|
-- @field #number ROCKET Rocket.
|
||||||
-- @field BOMB
|
-- @field #number BOMB Bomb.
|
||||||
|
-- @field #number TORPEDO Torpedo.
|
||||||
|
|
||||||
|
|
||||||
--- Weapon.GuidanceType enum that stores guidance methods. Available only for guided weapon (Weapon.Category.MISSILE and some Weapon.Category.BOMB).
|
--- Weapon.GuidanceType enum that stores guidance methods. Available only for guided weapon (Weapon.Category.MISSILE and some Weapon.Category.BOMB).
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ FOX = {
|
|||||||
|
|
||||||
--- Missile data table.
|
--- Missile data table.
|
||||||
-- @type FOX.MissileData
|
-- @type FOX.MissileData
|
||||||
-- @field Wrapper.Unit#UNIT weapon Missile weapon unit.
|
-- @field DCS#Weapon weapon Missile weapon object.
|
||||||
-- @field #boolean active If true the missile is active.
|
-- @field #boolean active If true the missile is active.
|
||||||
-- @field #string missileType Type of missile.
|
-- @field #string missileType Type of missile.
|
||||||
-- @field #string missileName Name of missile.
|
-- @field #string missileName Name of missile.
|
||||||
@@ -196,7 +196,7 @@ FOX.MenuF10Root=nil
|
|||||||
|
|
||||||
--- FOX class version.
|
--- FOX class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FOX.version="0.6.1"
|
FOX.version="0.7.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -762,91 +762,12 @@ function FOX:_IsProtected(targetunit)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Missle launch event.
|
--- Missle launch event.
|
||||||
-- @param #FOX self
|
-- @param #FOX self
|
||||||
-- @param #string From From state.
|
-- @param Wrapper.Weapon#WEAPON weapon Weapon object.
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #FOX.MissileData missile Fired missile
|
-- @param #FOX.MissileData missile Fired missile
|
||||||
function FOX:onafterMissileLaunch(From, Event, To, missile)
|
function FOX:_FuncTrack(weapon, missile)
|
||||||
|
|
||||||
-- Tracking info and init of last bomb position.
|
|
||||||
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
|
||||||
self:I(FOX.lid..text)
|
|
||||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
|
||||||
|
|
||||||
-- Loop over players.
|
|
||||||
for _,_player in pairs(self.players) do
|
|
||||||
local player=_player --#FOX.PlayerData
|
|
||||||
|
|
||||||
-- Player position.
|
|
||||||
local playerUnit=player.unit
|
|
||||||
|
|
||||||
-- Check that player is alive and of the opposite coalition.
|
|
||||||
if playerUnit and playerUnit:IsAlive() and player.coalition~=missile.shooterCoalition then
|
|
||||||
|
|
||||||
-- Player missile distance.
|
|
||||||
local distance=playerUnit:GetCoordinate():Get3DDistance(missile.shotCoord)
|
|
||||||
|
|
||||||
-- Player bearing to missile.
|
|
||||||
local bearing=playerUnit:GetCoordinate():HeadingTo(missile.shotCoord)
|
|
||||||
|
|
||||||
-- Alert that missile has been launched.
|
|
||||||
if player.launchalert then
|
|
||||||
|
|
||||||
-- Alert directly targeted players or players that are within missile max range.
|
|
||||||
if (missile.targetPlayer and player.unitname==missile.targetPlayer.unitname) or (distance<missile.missileRange) then
|
|
||||||
|
|
||||||
-- Inform player.
|
|
||||||
local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing)
|
|
||||||
|
|
||||||
-- Say notching headings.
|
|
||||||
self:ScheduleOnce(5, FOX._SayNotchingHeadings, self, player, missile.weapon)
|
|
||||||
|
|
||||||
--TODO: ALERT or INFO depending on whether this is a direct target.
|
|
||||||
--TODO: lauchalertall option.
|
|
||||||
MESSAGE:New(text, 5, "ALERT"):ToClient(player.client)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mark coordinate.
|
|
||||||
if player.marklaunch then
|
|
||||||
local text=string.format("Missile launch coordinates:\n%s\n%s", missile.shotCoord:ToStringLLDMS(), missile.shotCoord:ToStringBULLS(player.coalition))
|
|
||||||
missile.shotCoord:MarkToGroup(text, player.group)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Init missile position.
|
|
||||||
local _lastBombPos = {x=0,y=0,z=0}
|
|
||||||
|
|
||||||
-- Missile coordinate.
|
|
||||||
local missileCoord = nil --Core.Point#COORDINATE
|
|
||||||
|
|
||||||
-- Target unit of the missile.
|
|
||||||
local target=nil --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
--- Function monitoring the position of a bomb until impact.
|
|
||||||
local function trackMissile(_ordnance)
|
|
||||||
|
|
||||||
-- When the pcall returns a failure the weapon has hit.
|
|
||||||
local _status,_bombPos = pcall(
|
|
||||||
function()
|
|
||||||
return _ordnance:getPoint()
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Check if status is not nil. If so, we have a valid point.
|
|
||||||
if _status then
|
|
||||||
|
|
||||||
----------------------------------------------
|
|
||||||
-- Still in the air. Remember this position --
|
|
||||||
----------------------------------------------
|
|
||||||
|
|
||||||
-- Missile position.
|
|
||||||
_lastBombPos = {x=_bombPos.x, y=_bombPos.y, z=_bombPos.z}
|
|
||||||
|
|
||||||
-- Missile coordinate.
|
-- Missile coordinate.
|
||||||
missileCoord=COORDINATE:NewFromVec3(_lastBombPos)
|
missileCoord=COORDINATE:NewFromVec3(_lastBombPos)
|
||||||
@@ -1076,15 +997,15 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
|||||||
self:T(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName))
|
self:T(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName))
|
||||||
return timer.getTime()+0.1
|
return timer.getTime()+0.1
|
||||||
|
|
||||||
-- No target ==> terminate timer.
|
|
||||||
--return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
end
|
||||||
|
|
||||||
-------------------------------------
|
--- Callback function on impact or destroy otherwise.
|
||||||
-- Missile does not exist any more --
|
-- @param #FOX self
|
||||||
-------------------------------------
|
-- @param Wrapper.Weapon#WEAPON weapon Weapon object.
|
||||||
|
-- @param #FOX.MissileData missile Fired missile
|
||||||
|
function FOX:_FuncImpact(weapon, missile)
|
||||||
|
|
||||||
if target then
|
if target then
|
||||||
|
|
||||||
@@ -1109,13 +1030,78 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
|||||||
self:T(FOX.lid..string.format("Terminating missile track timer."))
|
self:T(FOX.lid..string.format("Terminating missile track timer."))
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
end -- _status check
|
end
|
||||||
|
|
||||||
|
--- Missle launch event.
|
||||||
|
-- @param #FOX self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #FOX.MissileData missile Fired missile
|
||||||
|
function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||||
|
|
||||||
|
-- Tracking info and init of last bomb position.
|
||||||
|
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
||||||
|
self:I(FOX.lid..text)
|
||||||
|
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||||
|
|
||||||
|
-- Loop over players.
|
||||||
|
for _,_player in pairs(self.players) do
|
||||||
|
local player=_player --#FOX.PlayerData
|
||||||
|
|
||||||
|
-- Player position.
|
||||||
|
local playerUnit=player.unit
|
||||||
|
|
||||||
|
-- Check that player is alive and of the opposite coalition.
|
||||||
|
if playerUnit and playerUnit:IsAlive() and player.coalition~=missile.shooterCoalition then
|
||||||
|
|
||||||
|
-- Player missile distance.
|
||||||
|
local distance=playerUnit:GetCoordinate():Get3DDistance(missile.shotCoord)
|
||||||
|
|
||||||
|
-- Player bearing to missile.
|
||||||
|
local bearing=playerUnit:GetCoordinate():HeadingTo(missile.shotCoord)
|
||||||
|
|
||||||
|
-- Alert that missile has been launched.
|
||||||
|
if player.launchalert then
|
||||||
|
|
||||||
|
-- Alert directly targeted players or players that are within missile max range.
|
||||||
|
if (missile.targetPlayer and player.unitname==missile.targetPlayer.unitname) or (distance<missile.missileRange) then
|
||||||
|
|
||||||
|
-- Inform player.
|
||||||
|
local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing)
|
||||||
|
|
||||||
|
-- Say notching headings.
|
||||||
|
self:ScheduleOnce(5, FOX._SayNotchingHeadings, self, player, missile.weapon)
|
||||||
|
|
||||||
|
--TODO: ALERT or INFO depending on whether this is a direct target.
|
||||||
|
--TODO: lauchalertall option.
|
||||||
|
MESSAGE:New(text, 5, "ALERT"):ToClient(player.client)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mark coordinate.
|
||||||
|
if player.marklaunch then
|
||||||
|
local text=string.format("Missile launch coordinates:\n%s\n%s", missile.shotCoord:ToStringLLDMS(), missile.shotCoord:ToStringBULLS(player.coalition))
|
||||||
|
missile.shotCoord:MarkToGroup(text, player.group)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local weapon=WEAPON:New(missile.weapon)
|
||||||
|
|
||||||
|
weapon:SetFuncTrack(FuncTrack)
|
||||||
|
|
||||||
|
weapon:SetFuncImpact(FuncImpact)
|
||||||
|
|
||||||
|
|
||||||
end -- end function trackBomb
|
|
||||||
|
|
||||||
-- Weapon is not yet "alife" just yet. Start timer with a little delay.
|
-- Weapon is not yet "alife" just yet. Start timer with a little delay.
|
||||||
self:T(FOX.lid..string.format("Tracking of missile starts in 0.0001 seconds."))
|
self:T(FOX.lid..string.format("Tracking of missile starts in 0.0001 seconds."))
|
||||||
timer.scheduleFunction(trackMissile, missile.weapon, timer.getTime()+0.0001)
|
--timer.scheduleFunction(trackMissile, missile.weapon, timer.getTime()+0.0001)
|
||||||
|
weapon:StartTrack(0.0001)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -406,9 +406,11 @@ RANGE.TargetType = {
|
|||||||
-- @field #boolean messages Display info messages.
|
-- @field #boolean messages Display info messages.
|
||||||
-- @field Wrapper.Client#CLIENT client Client object of player.
|
-- @field Wrapper.Client#CLIENT client Client object of player.
|
||||||
-- @field #string unitname Name of player aircraft unit.
|
-- @field #string unitname Name of player aircraft unit.
|
||||||
|
-- @field Wrapper.Unit#UNIT unit Player unit.
|
||||||
-- @field #string playername Name of player.
|
-- @field #string playername Name of player.
|
||||||
-- @field #string airframe Aircraft type name.
|
-- @field #string airframe Aircraft type name.
|
||||||
-- @field #boolean inzone If true, player is inside the range zone.
|
-- @field #boolean inzone If true, player is inside the range zone.
|
||||||
|
-- @field #boolean targeton Target on.
|
||||||
|
|
||||||
--- Bomb target data.
|
--- Bomb target data.
|
||||||
-- @type RANGE.BombTarget
|
-- @type RANGE.BombTarget
|
||||||
@@ -1721,6 +1723,7 @@ function RANGE:OnEventBirth( EventData )
|
|||||||
self.PlayerSettings[_playername].messages = true
|
self.PlayerSettings[_playername].messages = true
|
||||||
self.PlayerSettings[_playername].client = CLIENT:FindByName( _unitName, nil, true )
|
self.PlayerSettings[_playername].client = CLIENT:FindByName( _unitName, nil, true )
|
||||||
self.PlayerSettings[_playername].unitname = _unitName
|
self.PlayerSettings[_playername].unitname = _unitName
|
||||||
|
self.PlayerSettings[_playername].unit = _unit
|
||||||
self.PlayerSettings[_playername].playername = _playername
|
self.PlayerSettings[_playername].playername = _playername
|
||||||
self.PlayerSettings[_playername].airframe = EventData.IniUnit:GetTypeName()
|
self.PlayerSettings[_playername].airframe = EventData.IniUnit:GetTypeName()
|
||||||
self.PlayerSettings[_playername].inzone = false
|
self.PlayerSettings[_playername].inzone = false
|
||||||
@@ -1829,108 +1832,14 @@ function RANGE:OnEventHit( EventData )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Range event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
--- Function called on impact of a tracked weapon.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param #table weapon Weapon
|
-- @param Wrapper.Weapon#WEAPON weapon The weapon object.
|
||||||
function RANGE:_TrackWeapon(weapon)
|
-- @param #RANGE.PlayerData playerData Player data table.
|
||||||
|
-- @param #number attackHdg Attack heading.
|
||||||
end
|
-- @param #number attackAlt Attack altitude.
|
||||||
|
-- @param #number attackVel Attack velocity.
|
||||||
--- Range event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
function RANGE:_OnImpact(weapon, playerData, attackHdg, attackAlt, attackVel)
|
||||||
-- @param #RANGE self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
|
||||||
function RANGE:OnEventShot( EventData )
|
|
||||||
self:F( { eventshot = EventData } )
|
|
||||||
|
|
||||||
-- Nil checks.
|
|
||||||
if EventData.Weapon == nil or EventData.IniDCSUnit == nil or EventData.IniPlayerName == nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Weapon data.
|
|
||||||
local _weapon = EventData.Weapon:getTypeName() -- should be the same as Event.WeaponTypeName
|
|
||||||
local _weaponStrArray = UTILS.Split( _weapon, "%." )
|
|
||||||
local _weaponName = _weaponStrArray[#_weaponStrArray]
|
|
||||||
|
|
||||||
-- Weapon descriptor.
|
|
||||||
local desc = EventData.Weapon:getDesc()
|
|
||||||
|
|
||||||
-- Weapon category: 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X)
|
|
||||||
local weaponcategory = desc.category
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Range " .. self.rangename )
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Ini unit = " .. EventData.IniUnitName )
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Ini group = " .. EventData.IniGroupName )
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Weapon type = " .. _weapon )
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Weapon name = " .. _weaponName )
|
|
||||||
self:T( self.lid .. "EVENT SHOT: Weapon cate = " .. weaponcategory )
|
|
||||||
|
|
||||||
-- Tracking conditions for bombs, rockets and missiles.
|
|
||||||
local _bombs = weaponcategory == Weapon.Category.BOMB -- string.match(_weapon, "weapons.bombs")
|
|
||||||
local _rockets = weaponcategory == Weapon.Category.ROCKET -- string.match(_weapon, "weapons.nurs")
|
|
||||||
local _missiles = weaponcategory == Weapon.Category.MISSILE -- string.match(_weapon, "weapons.missiles") or _viggen
|
|
||||||
|
|
||||||
-- Check if any condition applies here.
|
|
||||||
local _track = (_bombs and self.trackbombs) or (_rockets and self.trackrockets) or (_missiles and self.trackmissiles)
|
|
||||||
|
|
||||||
-- Get unit name.
|
|
||||||
local _unitName = EventData.IniUnitName
|
|
||||||
|
|
||||||
-- Get player unit and name.
|
|
||||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
|
||||||
|
|
||||||
-- Attack parameters.
|
|
||||||
local attackHdg=_unit:GetHeading()
|
|
||||||
local attackAlt=_unit:GetHeight()
|
|
||||||
local attackVel=_unit:GetVelocityKNOTS()
|
|
||||||
|
|
||||||
-- Set this to larger value than the threshold.
|
|
||||||
local dPR = self.BombtrackThreshold * 2
|
|
||||||
|
|
||||||
-- Distance player to range.
|
|
||||||
if _unit and _playername then
|
|
||||||
dPR = _unit:GetCoordinate():Get2DDistance( self.location )
|
|
||||||
self:T( self.lid .. string.format( "Range %s, player %s, player-range distance = %d km.", self.rangename, _playername, dPR / 1000 ) )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons.
|
|
||||||
if _track and dPR <= self.BombtrackThreshold and _unit and _playername then
|
|
||||||
|
|
||||||
-- Player data.
|
|
||||||
local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData
|
|
||||||
|
|
||||||
-- Tracking info and init of last bomb position.
|
|
||||||
self:T( self.lid .. string.format( "RANGE %s: Tracking %s - %s.", self.rangename, _weapon, EventData.weapon:getName() ) )
|
|
||||||
|
|
||||||
-- Init bomb position.
|
|
||||||
local _lastBombPos = { x = 0, y = 0, z = 0 } -- DCS#Vec3
|
|
||||||
|
|
||||||
-- Function monitoring the position of a bomb until impact.
|
|
||||||
local function trackBomb( _ordnance )
|
|
||||||
|
|
||||||
-- When the pcall returns a failure the weapon has hit.
|
|
||||||
local _status, _bombPos = pcall( function()
|
|
||||||
return _ordnance:getPoint()
|
|
||||||
end )
|
|
||||||
|
|
||||||
self:T2( self.lid .. string.format( "Range %s: Bomb still in air: %s", self.rangename, tostring( _status ) ) )
|
|
||||||
if _status then
|
|
||||||
|
|
||||||
----------------------------
|
|
||||||
-- Weapon is still in air --
|
|
||||||
----------------------------
|
|
||||||
|
|
||||||
-- Remember this position.
|
|
||||||
_lastBombPos = { x = _bombPos.x, y = _bombPos.y, z = _bombPos.z }
|
|
||||||
|
|
||||||
-- Check again in ~0.005 seconds ==> 200 checks per second.
|
|
||||||
return timer.getTime() + self.dtBombtrack
|
|
||||||
else
|
|
||||||
|
|
||||||
-----------------------------
|
|
||||||
-- Bomb did hit the ground --
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
-- Get closet target to last position.
|
-- Get closet target to last position.
|
||||||
local _closetTarget = nil -- #RANGE.BombTarget
|
local _closetTarget = nil -- #RANGE.BombTarget
|
||||||
@@ -1939,18 +1848,18 @@ function RANGE:OnEventShot( EventData )
|
|||||||
local _hitquality = "POOR"
|
local _hitquality = "POOR"
|
||||||
|
|
||||||
-- Get callsign.
|
-- Get callsign.
|
||||||
local _callsign = self:_myname( _unitName )
|
local _callsign = self:_myname( playerData.unitname )
|
||||||
|
|
||||||
|
local _playername=playerData.playername
|
||||||
|
|
||||||
|
local _unit=playerData.unit
|
||||||
|
|
||||||
-- Coordinate of impact point.
|
-- Coordinate of impact point.
|
||||||
local impactcoord = COORDINATE:NewFromVec3( _lastBombPos )
|
local impactcoord = weapon:GetImpactCoordinate()
|
||||||
|
|
||||||
-- Check if impact happened in range zone.
|
-- Check if impact happened in range zone.
|
||||||
local insidezone = self.rangezone:IsCoordinateInZone( impactcoord )
|
local insidezone = self.rangezone:IsCoordinateInZone( impactcoord )
|
||||||
|
|
||||||
-- Impact point of bomb.
|
|
||||||
if self.Debug then
|
|
||||||
impactcoord:MarkToAll( "Bomb impact point" )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Smoke impact point of bomb.
|
-- Smoke impact point of bomb.
|
||||||
if playerData.smokebombimpact and insidezone then
|
if playerData.smokebombimpact and insidezone then
|
||||||
@@ -2009,7 +1918,7 @@ function RANGE:OnEventShot( EventData )
|
|||||||
result.name = _closetTarget.name or "unknown"
|
result.name = _closetTarget.name or "unknown"
|
||||||
result.distance = _distance
|
result.distance = _distance
|
||||||
result.radial = _closeCoord:HeadingTo( impactcoord )
|
result.radial = _closeCoord:HeadingTo( impactcoord )
|
||||||
result.weapon = _weaponName or "unknown"
|
result.weapon = weapon:GetTypeName() or "unknown"
|
||||||
result.quality = _hitquality
|
result.quality = _hitquality
|
||||||
result.player = playerData.playername
|
result.player = playerData.playername
|
||||||
result.time = timer.getAbsTime()
|
result.time = timer.getAbsTime()
|
||||||
@@ -2059,15 +1968,62 @@ function RANGE:OnEventShot( EventData )
|
|||||||
self:T( self.lid .. string.format( "Range %s, player %s: Terminating bomb track timer.", self.rangename, _playername ) )
|
self:T( self.lid .. string.format( "Range %s, player %s: Terminating bomb track timer.", self.rangename, _playername ) )
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
end -- _status check
|
end
|
||||||
|
|
||||||
end -- end function trackBomb
|
--- Range event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
||||||
|
-- @param #RANGE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function RANGE:OnEventShot( EventData )
|
||||||
|
self:F( { eventshot = EventData } )
|
||||||
|
|
||||||
-- Weapon is not yet "alife" just yet. Start timer in one second.
|
-- Nil checks.
|
||||||
|
if EventData.Weapon == nil or EventData.IniDCSUnit == nil or EventData.IniPlayerName == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create weapon object.
|
||||||
|
local weapon=WEAPON:New(EventData.weapon)
|
||||||
|
|
||||||
|
-- Check if any condition applies here.
|
||||||
|
local _track = (weapon:IsBomb() and self.trackbombs) or (weapon:IsRocket() and self.trackrockets) or (weapon:IsMissile() and self.trackmissiles)
|
||||||
|
|
||||||
|
-- Get unit name.
|
||||||
|
local _unitName = EventData.IniUnitName
|
||||||
|
|
||||||
|
-- Get player unit and name.
|
||||||
|
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
||||||
|
|
||||||
|
-- Set this to larger value than the threshold.
|
||||||
|
local dPR = self.BombtrackThreshold * 2
|
||||||
|
|
||||||
|
-- Distance player to range.
|
||||||
|
if _unit and _playername then
|
||||||
|
dPR = _unit:GetCoordinate():Get2DDistance( self.location )
|
||||||
|
self:T( self.lid .. string.format( "Range %s, player %s, player-range distance = %d km.", self.rangename, _playername, dPR / 1000 ) )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons.
|
||||||
|
if _track and dPR <= self.BombtrackThreshold and _unit and _playername then
|
||||||
|
|
||||||
|
-- Player data.
|
||||||
|
local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData
|
||||||
|
|
||||||
|
-- Attack parameters.
|
||||||
|
local attackHdg=_unit:GetHeading()
|
||||||
|
local attackAlt=_unit:GetHeight()
|
||||||
|
local attackVel=_unit:GetVelocityKNOTS()
|
||||||
|
|
||||||
|
-- Tracking info and init of last bomb position.
|
||||||
|
self:T( self.lid .. string.format( "RANGE %s: Tracking %s - %s.", self.rangename, weapon:GetTypeName(), weapon:GetName()))
|
||||||
|
|
||||||
|
-- Set callback function on impact.
|
||||||
|
weapon:SetFuncImpact(RANGE._OnImpact, self, playerData, attackHdg, attackAlt, attackVel)
|
||||||
|
|
||||||
|
-- Weapon is not yet "alife" just yet. Start timer in 0.1 seconds.
|
||||||
self:T( self.lid .. string.format( "Range %s, player %s: Tracking of weapon starts in 0.1 seconds.", self.rangename, _playername ) )
|
self:T( self.lid .. string.format( "Range %s, player %s: Tracking of weapon starts in 0.1 seconds.", self.rangename, _playername ) )
|
||||||
timer.scheduleFunction( trackBomb, EventData.weapon, timer.getTime() + 0.1 )
|
weapon:StartTrack(0.1)
|
||||||
|
|
||||||
end -- if _track (string.match) and player-range distance < threshold.
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
--- **Wrapper** - Weapon.
|
--- **Wrapper** - Weapon functions.
|
||||||
--
|
--
|
||||||
-- ## Main Features:
|
-- ## Main Features:
|
||||||
--
|
--
|
||||||
-- * Convenient access to all DCS API functions
|
-- * Convenient access to DCS API functions
|
||||||
-- * Track weapon and get impact position
|
-- * Track weapon and get impact position
|
||||||
-- * Get launcher and target of weapon
|
-- * Get launcher and target of weapon
|
||||||
|
-- * Define callback function when weapon impacts
|
||||||
-- * Destroy weapon before impact
|
-- * Destroy weapon before impact
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
@@ -28,13 +29,30 @@
|
|||||||
-- @field #number verbose Verbosity level.
|
-- @field #number verbose Verbosity level.
|
||||||
-- @field #string lid Class id string for output to DCS log file.
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
-- @field DCS#Weapon weapon The DCS weapon object.
|
-- @field DCS#Weapon weapon The DCS weapon object.
|
||||||
|
-- @field #string name Name of the weapon object.
|
||||||
|
-- @field #string typeName Type name of the weapon.
|
||||||
|
-- @field #number category Weapon category 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X).
|
||||||
|
-- @field #number coalition Coalition ID.
|
||||||
|
-- @field #number country Country ID.
|
||||||
|
-- @field DCS#Desc desc Descriptor table.
|
||||||
|
-- @field DCS#Unit launcher Launcher DCS unit.
|
||||||
|
-- @field Wrapper.Unit#UNIT launcherUnit Launcher Unit.
|
||||||
|
-- @field #string launcherName Name of launcher unit.
|
||||||
|
-- @field #number dtTrack Time step in seconds for tracking scheduler.
|
||||||
-- @field #function impactFunc Callback function for weapon impact.
|
-- @field #function impactFunc Callback function for weapon impact.
|
||||||
-- @field #table impactArg Optional arguments for the impact callback function.
|
-- @field #table impactArg Optional arguments for the impact callback function.
|
||||||
|
-- @field #function trackFunc Callback function when weapon is tracked and alive.
|
||||||
|
-- @field #table trackArg Optional arguments for the track callback function.
|
||||||
-- @field DCS#Vec3 vec3 Last known 3D position vector of the tracked weapon.
|
-- @field DCS#Vec3 vec3 Last known 3D position vector of the tracked weapon.
|
||||||
-- @field DCS#Position3 pos3 Last known 3D position and direction vector of the tracked weapon.
|
-- @field DCS#Position3 pos3 Last known 3D position and direction vector of the tracked weapon.
|
||||||
|
-- @field DCS#Vec3 impactVec3 Impact 3D vector.
|
||||||
|
-- @field Core.Point#COORDINATE impactCoord Impact coordinate.
|
||||||
|
-- @field #number trackScheduleID Tracking scheduler ID. Can be used to remove/destroy the scheduler function.
|
||||||
|
-- @field #boolean tracking If `true`, scheduler will keep tracking. Otherwise, function will return nil and stop tracking.
|
||||||
|
-- @field #boolean markImpact If `true`, the impact point is marked on the F10 map. Requires tracking to be started.
|
||||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||||
|
|
||||||
--- *Before this time tomorrow I shall have gained a peerage, or Westminster Abbey.* -- Horatio Nelson
|
--- *In the long run, the sharpest weapon of all is a kind and gentle spirit.* -- Anne Frank
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -48,6 +66,26 @@
|
|||||||
-- **Note** that this wrapper class is different from most others as weapon objects cannot be found with a DCS API function like `getByName()`.
|
-- **Note** that this wrapper class is different from most others as weapon objects cannot be found with a DCS API function like `getByName()`.
|
||||||
-- They can only be found in DCS events like the "Shot" event, where the weapon object is contained in the event data.
|
-- They can only be found in DCS events like the "Shot" event, where the weapon object is contained in the event data.
|
||||||
--
|
--
|
||||||
|
-- # Tracking
|
||||||
|
--
|
||||||
|
-- The status of the weapon can be tracked with the @{#WEAPON.StartTrack}() function. This function will try to determin the position of the weapon in (normally) relatively
|
||||||
|
-- small time steps. The time step can be set via the @{#WEAPON.SetTimeStepTrack} function and is by default set to 0.01 secons.
|
||||||
|
--
|
||||||
|
-- Once the position cannot be retrieved any more, the weapon has impacted (or was destroyed otherwise) and the last known position is safed as the impact point.
|
||||||
|
-- The impact point can be accessed with the @{#WEAPON.GetImpactVec3} or @{#WEAPON.GetImpactCoordinate} functions.
|
||||||
|
--
|
||||||
|
-- ## Callback functions
|
||||||
|
--
|
||||||
|
-- It is possible to define functions that are called during the tracking of the weapon and upon impact.
|
||||||
|
--
|
||||||
|
-- ### Callback on Impact
|
||||||
|
--
|
||||||
|
-- The function called on impact can be set with @{#WEAPON.SetFuncImpact}
|
||||||
|
--
|
||||||
|
-- ### Callback when Tracking
|
||||||
|
--
|
||||||
|
-- The function called each time the weapon status is tracked can be set with @{#WEAPON.SetFuncTrack}
|
||||||
|
--
|
||||||
-- # Dependencies
|
-- # Dependencies
|
||||||
--
|
--
|
||||||
-- This class is used (at least) in the MOOSE classes:
|
-- This class is used (at least) in the MOOSE classes:
|
||||||
@@ -62,27 +100,6 @@ WEAPON = {
|
|||||||
verbose = 0,
|
verbose = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Target data.
|
|
||||||
-- @type WEAPON.Target
|
|
||||||
-- @field #number uid Unique ID of the phase.
|
|
||||||
-- @field #string name Name of the phase.
|
|
||||||
-- @field Core.Condition#CONDITION conditionOver Conditions when the phase is over.
|
|
||||||
-- @field #string status Phase status.
|
|
||||||
-- @field #number Tstart Abs. mission time when the phase was started.
|
|
||||||
-- @field #number nActive Number of times the phase was active.
|
|
||||||
-- @field #number duration Duration in seconds how long the phase should be active after it started.
|
|
||||||
-- @field #WEAPON.Branch branch The branch this phase belongs to.
|
|
||||||
|
|
||||||
--- Operation phase.
|
|
||||||
-- @type WEAPON.PhaseStatus
|
|
||||||
-- @field #string PLANNED Planned.
|
|
||||||
-- @field #string ACTIVE Active phase.
|
|
||||||
-- @field #string OVER Phase is over.
|
|
||||||
WEAPON.PhaseStatus={
|
|
||||||
PLANNED="Planned",
|
|
||||||
ACTIVE="Active",
|
|
||||||
OVER="Over",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- WEAPON class version.
|
--- WEAPON class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
@@ -115,27 +132,42 @@ function WEAPON:New(WeaponObject)
|
|||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
local self=BASE:Inherit(self, POSITIONABLE:New("Weapon")) -- #WEAPON
|
local self=BASE:Inherit(self, POSITIONABLE:New("Weapon")) -- #WEAPON
|
||||||
|
|
||||||
|
-- Set DCS weapon object.
|
||||||
self.weapon=WeaponObject
|
self.weapon=WeaponObject
|
||||||
|
|
||||||
|
-- Descriptors containing a lot of info.
|
||||||
self.desc=WeaponObject:getDesc()
|
self.desc=WeaponObject:getDesc()
|
||||||
|
|
||||||
self.category=WeaponObject:getCategory()
|
-- This gives the object category which is always Object.Category.WEAPON!
|
||||||
|
--self.category=WeaponObject:getCategory()
|
||||||
|
|
||||||
|
-- Weapon category: 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X)
|
||||||
|
self.category = self.desc.category
|
||||||
|
|
||||||
|
if self:IsMissile() and self.desc.missileCategory then
|
||||||
|
self.categoryMissile=self.desc.missileCategory
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get type name.
|
||||||
self.typeName=WeaponObject:getTypeName()
|
self.typeName=WeaponObject:getTypeName()
|
||||||
|
|
||||||
|
-- Get name of object. Usually a number like "1234567".
|
||||||
self.name=WeaponObject:getName()
|
self.name=WeaponObject:getName()
|
||||||
|
|
||||||
|
-- Get coaliton of weapon.
|
||||||
self.coalition=WeaponObject:getCoalition()
|
self.coalition=WeaponObject:getCoalition()
|
||||||
|
|
||||||
|
-- Get country of weapon.
|
||||||
self.country=WeaponObject:getCountry()
|
self.country=WeaponObject:getCountry()
|
||||||
|
|
||||||
-- Get DCS unit of the launcher.
|
-- Get DCS unit of the launcher.
|
||||||
local launcher=WeaponObject:getLauncher()
|
self.launcher=WeaponObject:getLauncher()
|
||||||
|
|
||||||
|
-- Get launcher of weapon.
|
||||||
self.launcherName="Unknown Launcher"
|
self.launcherName="Unknown Launcher"
|
||||||
if launcher then
|
if self.launcher then
|
||||||
self.launcherName=launcher:getName()
|
self.launcherName=self.launcher:getName()
|
||||||
self.launcher=UNIT:Find(launcher)
|
self.launcherUnit=UNIT:Find(self.launcher)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set log ID.
|
-- Set log ID.
|
||||||
@@ -172,33 +204,108 @@ end
|
|||||||
-- @param #number TimeStep Time step in seconds when the position is updated. Default 0.01 sec ==> 100 evaluations per second.
|
-- @param #number TimeStep Time step in seconds when the position is updated. Default 0.01 sec ==> 100 evaluations per second.
|
||||||
-- @return #WEAPON self
|
-- @return #WEAPON self
|
||||||
function WEAPON:SetTimeStepTrack(TimeStep)
|
function WEAPON:SetTimeStepTrack(TimeStep)
|
||||||
self.dtTrackPos=TimeStep or 0.01
|
self.dtTrack=TimeStep or 0.01
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Mark impact point on the F10 map. This requires that the tracking has been started.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #boolean Switch If `true` or nil, impact is marked.
|
||||||
|
-- @return #WEAPON self
|
||||||
|
function WEAPON:SetMarkImpact(Switch)
|
||||||
|
|
||||||
|
if Switch==false then
|
||||||
|
self.markImpact=false
|
||||||
|
else
|
||||||
|
self.markImpact=true
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set callback function when weapon is tracked and still alive. The first argument will be the WEAPON object.
|
||||||
|
-- Note that this can be called many times per second. So be careful for performance reasons.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #function FuncTrack Function called during tracking.
|
||||||
|
-- @param ... Optional function arguments.
|
||||||
|
-- @return #WEAPON self
|
||||||
|
function WEAPON:SetFuncTrack(FuncTrack, ...)
|
||||||
|
self.trackFunc=FuncTrack
|
||||||
|
self.trackArg=arg or {}
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set callback function when weapon impacted or was destroyed otherwise, *i.e.* cannot be tracked any more.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #function FuncImpact Function called once the weapon impacted.
|
||||||
|
-- @param ... Optional function arguments.
|
||||||
|
-- @return #WEAPON self
|
||||||
|
--
|
||||||
|
-- @usage
|
||||||
|
-- -- Function called on impact.
|
||||||
|
-- local function OnImpact(Weapon)
|
||||||
|
-- Weapon:GetImpactCoordinate():MarkToAll("Impact Coordinate of weapon")
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- -- Set which function to call.
|
||||||
|
-- myweapon:SetFuncImpact(OnImpact)
|
||||||
|
--
|
||||||
|
-- -- Start tracking.
|
||||||
|
-- myweapon:Track()
|
||||||
|
--
|
||||||
|
function WEAPON:SetFuncImpact(FuncImpact, ...)
|
||||||
|
self.impactFunc=FuncImpact
|
||||||
|
self.impactArg=arg or {}
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the unit that launched the weapon.
|
--- Get the unit that launched the weapon.
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @return Wrapper.Unit#UNIT Laucher
|
-- @return Wrapper.Unit#UNIT Laucher unit.
|
||||||
function WEAPON:GetLauncher()
|
function WEAPON:GetLauncher()
|
||||||
return self.launcherUnit
|
return self.launcherUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the target, which the weapon is guiding to.
|
--- Get the target, which the weapon is guiding to.
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @return Wrapper.Unit#UNIT Laucher
|
-- @return Wrapper.Object#OBJECT The target object, which can be a UNIT or STATIC object.
|
||||||
function WEAPON:GetTarget()
|
function WEAPON:GetTarget()
|
||||||
|
|
||||||
local target=nil
|
local target=nil --Wrapper.Object#OBJECT
|
||||||
|
|
||||||
if self.weapon then
|
if self.weapon then
|
||||||
|
|
||||||
-- Get the DCS target object, which can be a Unit, Weapon, Static, Scenery, Airbase.
|
-- Get the DCS target object, which can be a Unit, Weapon, Static, Scenery, Airbase.
|
||||||
local object=self.weapon:getTarget()
|
local object=self.weapon:getTarget()
|
||||||
|
|
||||||
DCStarget:getCategory()
|
if object then
|
||||||
|
|
||||||
target=UNIT:Find(DCStarget)
|
-- Get object category.
|
||||||
|
local category=object:getCategory()
|
||||||
|
|
||||||
|
-- Get object name.
|
||||||
|
local name=object:getName()
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:I(self.lid..string.format("Got Target Object %s, category=%d", name, category))
|
||||||
|
|
||||||
|
|
||||||
|
if category==Object.Category.UNIT then
|
||||||
|
|
||||||
|
target=UNIT:Find(object)
|
||||||
|
|
||||||
|
elseif category==Object.Category.STATIC then
|
||||||
|
|
||||||
|
target=STATIC:Find(object)
|
||||||
|
|
||||||
|
elseif category==Object.Category.SCENERY then
|
||||||
|
self:E(self.lid..string.format("ERROR: Scenery target not implemented yet!"))
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("ERROR: Object category=%d is not implemented yet!", category))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -265,7 +372,7 @@ end
|
|||||||
--- Get country.
|
--- Get country.
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @return #number Country ID.
|
-- @return #number Country ID.
|
||||||
function WEAPON:GetCoalition()
|
function WEAPON:GetCountry()
|
||||||
return self.country
|
return self.country
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -277,13 +384,19 @@ function WEAPON:GetDCSObject()
|
|||||||
return self.weapon
|
return self.weapon
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the impact position. Note that this might not exist if the weapon has not impacted yet!
|
--- Get the impact position vector. Note that this might not exist if the weapon has not impacted yet!
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @return DCS#Vec3 Impact position vector (if any).
|
-- @return DCS#Vec3 Impact position vector (if any).
|
||||||
function WEAPON:GetImpactVec3()
|
function WEAPON:GetImpactVec3()
|
||||||
return self.impactVec3
|
return self.impactVec3
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the impact coordinate. Note that this might not exist if the weapon has not impacted yet!
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return Core.Point#COORDINATE Impact coordinate (if any).
|
||||||
|
function WEAPON:GetImpactCoordinate()
|
||||||
|
return self.impactCoord
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if weapon is in the air. Obviously not really useful for torpedos. Well, then again, this is DCS...
|
--- Check if weapon is in the air. Obviously not really useful for torpedos. Well, then again, this is DCS...
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
@@ -309,6 +422,41 @@ function WEAPON:IsExist()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if weapon is a bomb.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #boolean If `true`, is a bomb.
|
||||||
|
function WEAPON:IsBomb()
|
||||||
|
return self.category==Weapon.Category.BOMB
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if weapon is a missile.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #boolean If `true`, is a missile.
|
||||||
|
function WEAPON:IsMissile()
|
||||||
|
return self.category==Weapon.Category.MISSILE
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if weapon is a rocket.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #boolean If `true`, is a missile.
|
||||||
|
function WEAPON:IsRocket()
|
||||||
|
return self.category==Weapon.Category.ROCKET
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if weapon is a shell.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #boolean If `true`, is a shell.
|
||||||
|
function WEAPON:IsShell()
|
||||||
|
return self.category==Weapon.Category.SHELL
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if weapon is a torpedo.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @return #boolean If `true`, is a torpedo.
|
||||||
|
function WEAPON:IsTorpedo()
|
||||||
|
return self.category==Weapon.Category.TORPEDO
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Destroy the weapon object.
|
--- Destroy the weapon object.
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
@@ -320,6 +468,7 @@ function WEAPON:Destroy(Delay)
|
|||||||
self:ScheduleOnce(Delay, WEAPON.Destroy, self, 0)
|
self:ScheduleOnce(Delay, WEAPON.Destroy, self, 0)
|
||||||
else
|
else
|
||||||
if self.weapon then
|
if self.weapon then
|
||||||
|
self:T(self.lid.."Destroying Weapon NOW!")
|
||||||
self.weapon:destroy()
|
self.weapon:destroy()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -327,34 +476,45 @@ function WEAPON:Destroy(Delay)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Start tracking the position of the weapon until it impacts.
|
--- Start tracking the weapon until it impacts or is destroyed otherwise.
|
||||||
-- The position of the weapon is monitored in small time steps. Once the position cannot be determined anymore, the monitoring is stopped and the last known position is
|
-- The position of the weapon is monitored in small time steps. Once the position cannot be determined anymore, the monitoring is stopped and the last known position is
|
||||||
-- the (approximate) impact point. Of course, the smaller the time step, the better the position can be determined. However, this can hit the performance as many
|
-- the (approximate) impact point. Of course, the smaller the time step, the better the position can be determined. However, this can hit the performance as many
|
||||||
-- calculations per second need to be carried out.
|
-- calculations per second need to be carried out.
|
||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @param #function FuncImpact Function called when weapon has impacted. First argument is the impact coordinate Core.Point#COORDINATE.
|
-- @param #number Delay Delay in seconds before the tracking starts. Default 0.001 sec. This is also the minimum.
|
||||||
-- @param ... Optional arguments passed to the impact function after the impact coordinate.
|
|
||||||
-- @return #WEAPON self
|
-- @return #WEAPON self
|
||||||
--
|
function WEAPON:StartTrack(Delay)
|
||||||
-- @usage
|
|
||||||
-- -- Function called on impact.
|
Delay=math.max(Delay or 0.001, 0.001)
|
||||||
-- local function impactfunc(Coordinate, Weapon)
|
|
||||||
-- Coordinate:MarkToAll("Impact Coordinate of weapon")
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- myweapon:Track(impactfunc)
|
|
||||||
--
|
|
||||||
function WEAPON:TrackPosition(FuncImpact, ...)
|
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Tracking weapon"))
|
self:T(self.lid..string.format("Start tracking weapon in %.4f sec", Delay))
|
||||||
|
|
||||||
-- Callback function on impact.
|
|
||||||
self.impactFunc=FuncImpact
|
|
||||||
self.impactArg=arg or {}
|
|
||||||
|
|
||||||
-- Weapon is not yet "alife" just yet. Start timer in 0.001 seconds.
|
-- Weapon is not yet "alife" just yet. Start timer in 0.001 seconds.
|
||||||
timer.scheduleFunction(WEAPON._TrackPosition, self, timer.getTime() + 0.001)
|
self.trackScheduleID=timer.scheduleFunction(WEAPON._TrackWeapon, self, timer.getTime() + Delay)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Stop tracking the weapon by removing the scheduler function.
|
||||||
|
-- @param #WEAPON self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds before the tracking is stopped.
|
||||||
|
-- @return #WEAPON self
|
||||||
|
function WEAPON:StopTrack(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
-- Delayed call.
|
||||||
|
self:ScheduleOnce(Delay, WEAPON.StopTrack, self, 0)
|
||||||
|
else
|
||||||
|
|
||||||
|
if self.trackScheduleID then
|
||||||
|
|
||||||
|
timer.removeFunction(self.trackScheduleID)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -367,12 +527,12 @@ end
|
|||||||
-- @param #WEAPON self
|
-- @param #WEAPON self
|
||||||
-- @param DCS#Time time Time in seconds.
|
-- @param DCS#Time time Time in seconds.
|
||||||
-- @return #number Time when called next or nil if not called again.
|
-- @return #number Time when called next or nil if not called again.
|
||||||
function WEAPON:_TrackPosition(time)
|
function WEAPON:_TrackWeapon(time)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
--self:I(string.format("Tracking at T=%.5f", time))
|
self:T3(self.lid..string.format("Tracking at T=%.5f", time))
|
||||||
|
|
||||||
-- When the pcall returns a failure the weapon has hit.
|
-- Protected call to get the weapon position. If the position cannot be determined any more, the weapon has impacted and status is nil.
|
||||||
local status, pos3= pcall(
|
local status, pos3= pcall(
|
||||||
function()
|
function()
|
||||||
local point=self.weapon:getPosition()
|
local point=self.weapon:getPosition()
|
||||||
@@ -392,6 +552,14 @@ function WEAPON:_TrackPosition(time)
|
|||||||
-- Update last known vec3.
|
-- Update last known vec3.
|
||||||
self.vec3 = self.pos3.p
|
self.vec3 = self.pos3.p
|
||||||
|
|
||||||
|
-- Keep on tracking by returning the next time below.
|
||||||
|
self.tracking=true
|
||||||
|
|
||||||
|
-- Callback function.
|
||||||
|
if self.trackFunc then
|
||||||
|
self.trackFunc(self, unpack(self.trackArg or {}))
|
||||||
|
end
|
||||||
|
|
||||||
if self.verbose>=5 then
|
if self.verbose>=5 then
|
||||||
|
|
||||||
local vec2={x=self.vec3.x, y=self.vec3.z}
|
local vec2={x=self.vec3.x, y=self.vec3.z}
|
||||||
@@ -413,16 +581,14 @@ function WEAPON:_TrackPosition(time)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check again in ~0.01 seconds ==> 100 checks per second.
|
|
||||||
return time+(self.dtTrackPos or 0.01)
|
|
||||||
else
|
else
|
||||||
|
|
||||||
---------------------------
|
---------------------------
|
||||||
-- Weapon does NOT exist --
|
-- Weapon does NOT exist --
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
-- Get intercept point from position (p) and direction (x) in 20 meters.
|
-- Get intercept point from position (p) and direction (x) in 50 meters.
|
||||||
local ip = land.getIP(self.pos3.p, self.pos3.x, 20) --DCS#Vec3
|
local ip = self:_GetIP(50)
|
||||||
|
|
||||||
if ip then
|
if ip then
|
||||||
env.info("FF Got intercept point!")
|
env.info("FF Got intercept point!")
|
||||||
@@ -441,22 +607,37 @@ function WEAPON:_TrackPosition(time)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set impact vec3.
|
-- Safe impact vec3.
|
||||||
self.impactVec3=ip or self.vec3
|
self.impactVec3=ip or self.vec3
|
||||||
|
|
||||||
-- Set impact coordinate.
|
-- Safe impact coordinate.
|
||||||
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
self.impactCoord=COORDINATE:NewFromVec3(self.vec3)
|
||||||
|
|
||||||
--self.impactCoord:MarkToAll("Impact point")
|
-- Mark impact point on F10 map.
|
||||||
|
if self.markImpact then
|
||||||
|
self.impactCoord:MarkToAll(string.format("Impact point of weapon %s\ntype=%s\nlauncher=%s", self.name, self.typeName, self.launcherName))
|
||||||
|
end
|
||||||
|
|
||||||
-- Call callback function.
|
-- Call callback function.
|
||||||
if self.impactFunc then
|
if self.impactFunc then
|
||||||
self.impactFunc(self.impactCoord, self, self.impactArg)
|
self.impactFunc(self, unpack(self.impactArg or {}))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stop tracking by returning nil below.
|
||||||
|
self.tracking=false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return next time the function is called or nil to stop the scheduler.
|
||||||
|
if self.tracking then
|
||||||
|
if self.dtTrack and self.dtTrack>0.001 then
|
||||||
|
return time+self.dtTrack
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Compute estimated intercept/impact point (IP) based on last known position and direction.
|
--- Compute estimated intercept/impact point (IP) based on last known position and direction.
|
||||||
|
|||||||
Reference in New Issue
Block a user