mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-21 21:17:30 +00:00
Rescuehelo 1.0.6
This commit is contained in:
@@ -7,7 +7,9 @@
|
|||||||
-- **Main Features:**
|
-- **Main Features:**
|
||||||
--
|
--
|
||||||
-- * Adaptive update of missile-to-player distance.
|
-- * Adaptive update of missile-to-player distance.
|
||||||
-- * F10 radio menu.
|
-- * Define your own training zones on the map. Player in this zone will be protected.
|
||||||
|
-- * Define launch zones. Only
|
||||||
|
-- * F10 radio menu to adjust settings for each player.
|
||||||
-- * Easy to use.
|
-- * Easy to use.
|
||||||
-- * Handles air-to-air and surface-to-air missiles.
|
-- * Handles air-to-air and surface-to-air missiles.
|
||||||
-- * Alert on missile launch (optional).
|
-- * Alert on missile launch (optional).
|
||||||
@@ -33,6 +35,11 @@
|
|||||||
-- @field Core.Set#SET_GROUP protectedset Set of protected groups.
|
-- @field Core.Set#SET_GROUP protectedset Set of protected groups.
|
||||||
-- @field #number explosionpower Power of explostion when destroying the missile in kg TNT. Default 5 kg TNT.
|
-- @field #number explosionpower Power of explostion when destroying the missile in kg TNT. Default 5 kg TNT.
|
||||||
-- @field #number explosiondist Missile player distance in meters for destroying the missile. Default 100 m.
|
-- @field #number explosiondist Missile player distance in meters for destroying the missile. Default 100 m.
|
||||||
|
-- @field #number dt50 Time step [sec] for missile position updates if distance to target > 50 km. Default 5 sec.
|
||||||
|
-- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec.
|
||||||
|
-- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec.
|
||||||
|
-- @field #number dt01 Time step [sec] for missile position updates if distance to target > 1 km and < 5 km. Default 0.1 sec.
|
||||||
|
-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Fox 2!
|
--- Fox 2!
|
||||||
@@ -43,6 +50,9 @@
|
|||||||
--
|
--
|
||||||
-- # The FOX2 Concept
|
-- # The FOX2 Concept
|
||||||
--
|
--
|
||||||
|
-- As you probably know [Fox](https://en.wikipedia.org/wiki/Fox_(code_word)) is a NATO bevity code for launching air-to-air munition. Therefore, the class name is not 100% accurate as this
|
||||||
|
-- script handles air-to-air and surface-to-air missiles. Furthermore, it handles not only Fox **2**, i.e. IR, missiles but also radar guided missiles.
|
||||||
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #FOX2
|
-- @field #FOX2
|
||||||
@@ -59,6 +69,11 @@ FOX2 = {
|
|||||||
explosionpower = 5,
|
explosionpower = 5,
|
||||||
explosiondist = 100,
|
explosiondist = 100,
|
||||||
destroy = nil,
|
destroy = nil,
|
||||||
|
dt50 = 5,
|
||||||
|
dt10 = 1,
|
||||||
|
dt05 = 0.5,
|
||||||
|
dt01 = 0.1,
|
||||||
|
dt00 = 0.01,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,6 +95,7 @@ FOX2 = {
|
|||||||
|
|
||||||
--- Missile data table.
|
--- Missile data table.
|
||||||
-- @type FOX2.MissileData
|
-- @type FOX2.MissileData
|
||||||
|
-- @field Wrapper.Unit#UNIT weapon Missile weapon unit.
|
||||||
-- @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 #number missileRange Range of missile in meters.
|
-- @field #number missileRange Range of missile in meters.
|
||||||
@@ -102,7 +118,7 @@ FOX2.MenuF10Root=nil
|
|||||||
|
|
||||||
--- FOX2 class version.
|
--- FOX2 class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FOX2.version="0.1.3"
|
FOX2.version="0.1.4"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -133,6 +149,8 @@ function FOX2:New()
|
|||||||
-- From State --> Event --> To State
|
-- From State --> Event --> To State
|
||||||
self:AddTransition("Stopped", "Start", "Running") -- Start FOX2 script.
|
self:AddTransition("Stopped", "Start", "Running") -- Start FOX2 script.
|
||||||
self:AddTransition("*", "Status", "*") -- Start FOX2 script.
|
self:AddTransition("*", "Status", "*") -- Start FOX2 script.
|
||||||
|
self:AddTransition("*", "MissileLaunch", "*") -- Start FOX2 script.
|
||||||
|
self:AddTransition("*", "MissileDestroyed", "*") -- Start FOX2 script.
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
@@ -164,6 +182,44 @@ function FOX2:New()
|
|||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "MissileLaunch".
|
||||||
|
-- @function [parent=#FOX2] MissileLaunch
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||||
|
|
||||||
|
--- Triggers the FSM delayed event "MissileLaunch".
|
||||||
|
-- @function [parent=#FOX2] __MissileLaunch
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #number delay Delay in seconds before the function is called.
|
||||||
|
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||||
|
|
||||||
|
--- On after "MissileLaunch" event user function. Called when a missile was launched.
|
||||||
|
-- @function [parent=#FOX2] OnAfterMissileLaunch
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "MissileDestroyed".
|
||||||
|
-- @function [parent=#FOX2] MissileDestroyed
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #FOX2.MissileData missile Data of the destroyed missile.
|
||||||
|
|
||||||
|
--- Triggers the FSM delayed event "MissileDestroyed".
|
||||||
|
-- @function [parent=#FOX2] __MissileDestroyed
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #number delay Delay in seconds before the function is called.
|
||||||
|
-- @param #FOX2.MissileData missile Data of the destroyed missile.
|
||||||
|
|
||||||
|
--- On after "MissileLaunch" event user function. Called when a missile was launched.
|
||||||
|
-- @function [parent=#FOX2] OnAfterMissileLaunch
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -182,8 +238,10 @@ function FOX2:onafterStart(From, Event, To)
|
|||||||
self:HandleEvent(EVENTS.Birth)
|
self:HandleEvent(EVENTS.Birth)
|
||||||
self:HandleEvent(EVENTS.Shot)
|
self:HandleEvent(EVENTS.Shot)
|
||||||
|
|
||||||
|
if self.Debug then
|
||||||
self:TraceClass(self.ClassName)
|
self:TraceClass(self.ClassName)
|
||||||
self:TraceLevel(2)
|
self:TraceLevel(2)
|
||||||
|
end
|
||||||
|
|
||||||
self:__Status(-1)
|
self:__Status(-1)
|
||||||
end
|
end
|
||||||
@@ -212,21 +270,55 @@ end
|
|||||||
--- Add a training zone. Players in the zone are safe.
|
--- Add a training zone. Players in the zone are safe.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param Core.Zone#ZONE zone Training zone.
|
-- @param Core.Zone#ZONE zone Training zone.
|
||||||
|
-- @return #FOX2 self
|
||||||
function FOX2:AddSafeZone(zone)
|
function FOX2:AddSafeZone(zone)
|
||||||
|
|
||||||
table.insert(self.safezones, zone)
|
table.insert(self.safezones, zone)
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add a launch zone. Only missiles launched within these zones will be tracked.
|
--- Add a launch zone. Only missiles launched within these zones will be tracked.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param Core.Zone#ZONE zone Training zone.
|
-- @param Core.Zone#ZONE zone Training zone.
|
||||||
|
-- @return #FOX2 self
|
||||||
function FOX2:AddLaunchZone(zone)
|
function FOX2:AddLaunchZone(zone)
|
||||||
|
|
||||||
table.insert(self.launchzones, zone)
|
table.insert(self.launchzones, zone)
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set debug mode on/off.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #boolean switch If true debug mode on. If false/nil debug mode off
|
||||||
|
-- @return #FOX2 self
|
||||||
|
function FOX2:SetDebugOnOff(switch)
|
||||||
|
|
||||||
|
if switch==nil then
|
||||||
|
self.Debug=false
|
||||||
|
else
|
||||||
|
self.Debug=switch
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set debug mode on.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @return #FOX2 self
|
||||||
|
function FOX2:SetDebugOn()
|
||||||
|
self:SetDebugOnOff(true)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set debug mode off.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @return #FOX2 self
|
||||||
|
function FOX2:SetDebugOff()
|
||||||
|
self:SetDebugOff(false)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Status Functions
|
-- Status Functions
|
||||||
@@ -264,179 +356,24 @@ function FOX2:_CheckMissileStatus()
|
|||||||
end
|
end
|
||||||
local active=tostring(missile.active)
|
local active=tostring(missile.active)
|
||||||
local mtype=missile.missileType
|
local mtype=missile.missileType
|
||||||
|
local dtype=missile.missileType
|
||||||
local range=UTILS.MetersToNM(missile.missileRange)
|
local range=UTILS.MetersToNM(missile.missileRange)
|
||||||
|
local heading=self:_GetWeapongHeading(missile.weapon)
|
||||||
|
|
||||||
text=text..string.format("\n[%d] %s: active=%s, type=%s, range=%.1f NM, target=%s, player=%s, missilename=%s", i, mtype, active, range, targetname, playername, missile.missileName)
|
text=text..string.format("\n[%d] %s: active=%s, range=%.1f NM, heading=%03d, target=%s, player=%s, missilename=%s", i, mtype, active, range, heading, targetname, playername, missile.missileName)
|
||||||
|
|
||||||
end
|
end
|
||||||
self:T(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
--- Missle
|
||||||
-- Event Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- FOX2 event handler for event birth.
|
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param #string From From state.
|
||||||
function FOX2:OnEventBirth(EventData)
|
-- @param #string Event Event.
|
||||||
self:F3({eventbirth = EventData})
|
-- @param #string To To state.
|
||||||
|
-- @param #FOX2.MissileData missile Fired missile
|
||||||
-- Nil checks.
|
function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||||
if EventData==nil then
|
|
||||||
self:E(self.lid.."ERROR: EventData=nil in event BIRTH!")
|
|
||||||
self:E(EventData)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if EventData.IniUnit==nil then
|
|
||||||
self:E(self.lid.."ERROR: EventData.IniUnit=nil in event BIRTH!")
|
|
||||||
self:E(EventData)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Player unit and name.
|
|
||||||
local _unitName=EventData.IniUnitName
|
|
||||||
local playerunit, playername=self:_GetPlayerUnitAndName(_unitName)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid.."BIRTH: unit = "..tostring(EventData.IniUnitName))
|
|
||||||
self:T(self.lid.."BIRTH: group = "..tostring(EventData.IniGroupName))
|
|
||||||
self:T(self.lid.."BIRTH: player = "..tostring(playername))
|
|
||||||
|
|
||||||
-- Check if player entered.
|
|
||||||
if playerunit and playername then
|
|
||||||
|
|
||||||
local _uid=playerunit:GetID()
|
|
||||||
local _group=playerunit:GetGroup()
|
|
||||||
local _callsign=playerunit:GetCallsign()
|
|
||||||
|
|
||||||
-- Debug output.
|
|
||||||
local text=string.format("Pilot %s, callsign %s entered unit %s of group %s.", playername, _callsign, _unitName, _group:GetName())
|
|
||||||
self:T(self.lid..text)
|
|
||||||
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
|
||||||
|
|
||||||
-- Add Menu commands.
|
|
||||||
self:_AddF10Commands(_unitName)
|
|
||||||
|
|
||||||
-- Player data.
|
|
||||||
local playerData={} --#FOX2.PlayerData
|
|
||||||
|
|
||||||
-- Player unit, client and callsign.
|
|
||||||
playerData.unit = playerunit
|
|
||||||
playerData.unitname = _unitName
|
|
||||||
playerData.group = _group
|
|
||||||
playerData.groupname = _group:GetName()
|
|
||||||
playerData.name = playername
|
|
||||||
playerData.callsign = playerData.unit:GetCallsign()
|
|
||||||
playerData.client = CLIENT:FindByName(_unitName, nil, true)
|
|
||||||
playerData.coalition = _group:GetCoalition()
|
|
||||||
|
|
||||||
playerData.destroy=playerData.destroy or true
|
|
||||||
playerData.launchalert=playerData.launchalert or true
|
|
||||||
playerData.marklaunch=playerData.marklaunch or true
|
|
||||||
|
|
||||||
playerData.defeated=playerData.defeated or 0
|
|
||||||
playerData.dead=playerData.dead or 0
|
|
||||||
|
|
||||||
-- Init player data.
|
|
||||||
self.players[playername]=playerData
|
|
||||||
|
|
||||||
-- Init player grades table if necessary.
|
|
||||||
--self.playerscores[playername]=self.playerscores[playername] or {}
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- FOX2 event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
|
||||||
-- @param #FOX2 self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
|
||||||
function FOX2:OnEventShot(EventData)
|
|
||||||
self:I({eventshot = EventData})
|
|
||||||
|
|
||||||
if EventData.Weapon==nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if EventData.IniDCSUnit==nil then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Weapon data.
|
|
||||||
local _weapon = EventData.WeaponName
|
|
||||||
local _target = EventData.Weapon:getTarget()
|
|
||||||
local _targetName = "unknown"
|
|
||||||
local _targetUnit = nil --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
-- Weapon descriptor.
|
|
||||||
local desc=EventData.Weapon:getDesc()
|
|
||||||
self:E({desc=desc})
|
|
||||||
|
|
||||||
-- Weapon category: 0=Shell, 1=Missile, 2=Rocket, 3=BOMB
|
|
||||||
local weaponcategory=desc.category
|
|
||||||
|
|
||||||
-- Missile category: 1=AAM, 2=SAM, 6=OTHER
|
|
||||||
local missilecategory=desc.missileCategory
|
|
||||||
|
|
||||||
local missilerange=nil
|
|
||||||
if missilecategory then
|
|
||||||
missilerange=desc.rangeMaxAltMax
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:E(FOX2.lid.."EVENT SHOT: FOX2")
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Ini unit = %s", tostring(EventData.IniUnitName)))
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Ini group = %s", tostring(EventData.IniGroupName)))
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Weapon type = %s", tostring(_weapon)))
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Weapon categ = %s", tostring(weaponcategory)))
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Missil categ = %s", tostring(missilecategory)))
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Missil range = %s", tostring(missilerange)))
|
|
||||||
|
|
||||||
|
|
||||||
-- Check if fired in launch zone.
|
|
||||||
if not self:_CheckCoordLaunch(EventData.IniUnit:GetCoordinate()) then
|
|
||||||
self:T(self.lid.."Missile was not fired in launch zone. No tracking!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get the target unit. Note if if _target is not nil, the unit can sometimes not be found!
|
|
||||||
if _target then
|
|
||||||
self:E({target=_target})
|
|
||||||
--_targetName=Unit.getName(_target)
|
|
||||||
--_targetUnit=UNIT:FindByName(_targetName)
|
|
||||||
_targetUnit=UNIT:Find(_target)
|
|
||||||
end
|
|
||||||
self:E(FOX2.lid..string.format("EVENT SHOT: Target name = %s", tostring(_targetName)))
|
|
||||||
|
|
||||||
-- Track missiles of type AAM=1, SAM=2 or OTHER=6
|
|
||||||
local _track = weaponcategory==1 and missilecategory and (missilecategory==1 or missilecategory==2 or missilecategory==6)
|
|
||||||
|
|
||||||
-- Get shooter.
|
|
||||||
--local shooterUnit = EventData.IniUnit
|
|
||||||
-- local shooterName = EventData.IniUnitName
|
|
||||||
-- local shooterCoalition=shooterUnit:GetCoalition()
|
|
||||||
-- local shooterCoord=shooterUnit:GetCoordinate()
|
|
||||||
|
|
||||||
-- Only track missiles
|
|
||||||
if _track then
|
|
||||||
|
|
||||||
local missile={} --#FOX2.MissileData
|
|
||||||
|
|
||||||
missile.active=true
|
|
||||||
missile.missileType=_weapon
|
|
||||||
missile.missileRange=missilerange
|
|
||||||
missile.missileName=EventData.weapon:getName()
|
|
||||||
missile.shooterUnit=EventData.IniUnit
|
|
||||||
missile.shooterGroup=EventData.IniGroup
|
|
||||||
missile.shooterCoalition=EventData.IniUnit:GetCoalition()
|
|
||||||
missile.shooterName=EventData.IniUnitName
|
|
||||||
missile.shotTime=timer.getAbsTime()
|
|
||||||
missile.shotCoord=EventData.IniUnit:GetCoordinate()
|
|
||||||
missile.targetUnit=_targetUnit
|
|
||||||
missile.targetPlayer=self:_GetPlayerFromUnit(missile.targetUnit)
|
|
||||||
|
|
||||||
-- Add missile table.
|
|
||||||
table.insert(self.missiles, missile)
|
|
||||||
|
|
||||||
|
|
||||||
-- Tracking info and init of last bomb position.
|
-- Tracking info and init of last bomb position.
|
||||||
self:I(FOX2.lid..string.format("FOX2: Tracking %s - %s.", missile.missileType, missile.missileName))
|
self:I(FOX2.lid..string.format("FOX2: Tracking %s - %s.", missile.missileType, missile.missileName))
|
||||||
@@ -463,8 +400,11 @@ function FOX2:OnEventShot(EventData)
|
|||||||
-- Alert directly targeted players or players that are within missile max range.
|
-- 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
|
if (missile.targetPlayer and player.unitname==missile.targetPlayer.unitname) or (distance<missile.missileRange) then
|
||||||
|
|
||||||
|
local nr, nl=self:_GetNotchingHeadings(missile.weapon)
|
||||||
|
|
||||||
-- Inform player.
|
-- Inform player.
|
||||||
local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing)
|
local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing)
|
||||||
|
text=text..string.format("\nNotching heading %03d or %03d", nr, nl)
|
||||||
|
|
||||||
--TODO: ALERT or INFO depending on wether this is a direct target.
|
--TODO: ALERT or INFO depending on wether this is a direct target.
|
||||||
--TODO: lauchalertall option.
|
--TODO: lauchalertall option.
|
||||||
@@ -575,7 +515,7 @@ function FOX2:OnEventShot(EventData)
|
|||||||
self:T2(self.lid..string.format("Distance = %.1f m, v=%.1f m/s, bearing=%03d°, eta=%.1f sec", distance, missileVelocity, bearing, eta))
|
self:T2(self.lid..string.format("Distance = %.1f m, v=%.1f m/s, bearing=%03d°, eta=%.1f sec", distance, missileVelocity, bearing, eta))
|
||||||
|
|
||||||
-- If missile is 100 m from target ==> destroy missile if in safe zone.
|
-- If missile is 100 m from target ==> destroy missile if in safe zone.
|
||||||
if distance<self.explosiondist and self:_CheckCoordSafe(targetCoord)then
|
if distance<=self.explosiondist and self:_CheckCoordSafe(targetCoord)then
|
||||||
|
|
||||||
-- Destroy missile.
|
-- Destroy missile.
|
||||||
self:T(self.lid..string.format("Destroying missile at distance %.1f m", distance))
|
self:T(self.lid..string.format("Destroying missile at distance %.1f m", distance))
|
||||||
@@ -584,7 +524,7 @@ function FOX2:OnEventShot(EventData)
|
|||||||
-- Little explosion for the visual effect.
|
-- Little explosion for the visual effect.
|
||||||
missileCoord:Explosion(self.explosionpower)
|
missileCoord:Explosion(self.explosionpower)
|
||||||
|
|
||||||
local text="Destroying missile. You're dead!"
|
local text=string.format("Destroying missile. %s", self:_DeadText())
|
||||||
MESSAGE:New(text, 10):ToGroup(target:GetGroup())
|
MESSAGE:New(text, 10):ToGroup(target:GetGroup())
|
||||||
|
|
||||||
-- Terminate timer.
|
-- Terminate timer.
|
||||||
@@ -595,19 +535,19 @@ function FOX2:OnEventShot(EventData)
|
|||||||
local dt=1.0
|
local dt=1.0
|
||||||
if distance>50000 then
|
if distance>50000 then
|
||||||
-- > 50 km
|
-- > 50 km
|
||||||
dt=5.0
|
dt=self.dt50 --=5.0
|
||||||
elseif distance>10000 then
|
elseif distance>10000 then
|
||||||
-- 10-50 km
|
-- 10-50 km
|
||||||
dt=1.0
|
dt=self.dt10 --=1.0
|
||||||
elseif distance>5000 then
|
elseif distance>5000 then
|
||||||
-- 5-10 km
|
-- 5-10 km
|
||||||
dt=0.5
|
dt=self.dt05 --0.5
|
||||||
elseif distance>1000 then
|
elseif distance>1000 then
|
||||||
-- 1-5 km
|
-- 1-5 km
|
||||||
dt=0.1
|
dt=self.dt01 --0.1
|
||||||
else
|
else
|
||||||
-- < 1 km
|
-- < 1 km
|
||||||
dt=0.01
|
dt=self.dt00 --0.01
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check again in dt seconds.
|
-- Check again in dt seconds.
|
||||||
@@ -651,7 +591,171 @@ function FOX2:OnEventShot(EventData)
|
|||||||
|
|
||||||
-- 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(FOX2.lid..string.format("Tracking of missile starts in 0.1 seconds."))
|
self:T(FOX2.lid..string.format("Tracking of missile starts in 0.1 seconds."))
|
||||||
timer.scheduleFunction(trackMissile, EventData.weapon, timer.getTime()+0.1)
|
timer.scheduleFunction(trackMissile, missile.weapon, timer.getTime()+0.0001)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- FOX2 event handler for event birth.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function FOX2:OnEventBirth(EventData)
|
||||||
|
self:F3({eventbirth = EventData})
|
||||||
|
|
||||||
|
-- Nil checks.
|
||||||
|
if EventData==nil then
|
||||||
|
self:E(self.lid.."ERROR: EventData=nil in event BIRTH!")
|
||||||
|
self:E(EventData)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if EventData.IniUnit==nil then
|
||||||
|
self:E(self.lid.."ERROR: EventData.IniUnit=nil in event BIRTH!")
|
||||||
|
self:E(EventData)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Player unit and name.
|
||||||
|
local _unitName=EventData.IniUnitName
|
||||||
|
local playerunit, playername=self:_GetPlayerUnitAndName(_unitName)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid.."BIRTH: unit = "..tostring(EventData.IniUnitName))
|
||||||
|
self:T(self.lid.."BIRTH: group = "..tostring(EventData.IniGroupName))
|
||||||
|
self:T(self.lid.."BIRTH: player = "..tostring(playername))
|
||||||
|
|
||||||
|
-- Check if player entered.
|
||||||
|
if playerunit and playername then
|
||||||
|
|
||||||
|
local _uid=playerunit:GetID()
|
||||||
|
local _group=playerunit:GetGroup()
|
||||||
|
local _callsign=playerunit:GetCallsign()
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
local text=string.format("Pilot %s, callsign %s entered unit %s of group %s.", playername, _callsign, _unitName, _group:GetName())
|
||||||
|
self:T(self.lid..text)
|
||||||
|
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
|
-- Add Menu commands.
|
||||||
|
--self:_AddF10Commands(_unitName)
|
||||||
|
SCHEDULER:New(nil, self._AddF10Commands, {self,_unitName}, 0.1)
|
||||||
|
|
||||||
|
-- Player data.
|
||||||
|
local playerData={} --#FOX2.PlayerData
|
||||||
|
|
||||||
|
-- Player unit, client and callsign.
|
||||||
|
playerData.unit = playerunit
|
||||||
|
playerData.unitname = _unitName
|
||||||
|
playerData.group = _group
|
||||||
|
playerData.groupname = _group:GetName()
|
||||||
|
playerData.name = playername
|
||||||
|
playerData.callsign = playerData.unit:GetCallsign()
|
||||||
|
playerData.client = CLIENT:FindByName(_unitName, nil, true)
|
||||||
|
playerData.coalition = _group:GetCoalition()
|
||||||
|
|
||||||
|
playerData.destroy=playerData.destroy or true
|
||||||
|
playerData.launchalert=playerData.launchalert or true
|
||||||
|
playerData.marklaunch=playerData.marklaunch or true
|
||||||
|
|
||||||
|
playerData.defeated=playerData.defeated or 0
|
||||||
|
playerData.dead=playerData.dead or 0
|
||||||
|
|
||||||
|
-- Init player data.
|
||||||
|
self.players[playername]=playerData
|
||||||
|
|
||||||
|
-- Init player grades table if necessary.
|
||||||
|
--self.playerscores[playername]=self.playerscores[playername] or {}
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- FOX2 event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function FOX2:OnEventShot(EventData)
|
||||||
|
self:I({eventshot = EventData})
|
||||||
|
|
||||||
|
if EventData.Weapon==nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if EventData.IniDCSUnit==nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Weapon data.
|
||||||
|
local _weapon = EventData.WeaponName
|
||||||
|
local _target = EventData.Weapon:getTarget()
|
||||||
|
local _targetName = "unknown"
|
||||||
|
local _targetUnit = nil --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Weapon descriptor.
|
||||||
|
local desc=EventData.Weapon:getDesc()
|
||||||
|
self:E({desc=desc})
|
||||||
|
|
||||||
|
-- Weapon category: 0=Shell, 1=Missile, 2=Rocket, 3=BOMB
|
||||||
|
local weaponcategory=desc.category
|
||||||
|
|
||||||
|
-- Missile category: 1=AAM, 2=SAM, 6=OTHER
|
||||||
|
local missilecategory=desc.missileCategory
|
||||||
|
|
||||||
|
local missilerange=nil
|
||||||
|
if missilecategory then
|
||||||
|
missilerange=desc.rangeMaxAltMax
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:E(FOX2.lid.."EVENT SHOT: FOX2")
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Ini unit = %s", tostring(EventData.IniUnitName)))
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Ini group = %s", tostring(EventData.IniGroupName)))
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Weapon type = %s", tostring(_weapon)))
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Weapon categ = %s", tostring(weaponcategory)))
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Missil categ = %s", tostring(missilecategory)))
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Missil range = %s", tostring(missilerange)))
|
||||||
|
|
||||||
|
|
||||||
|
-- Check if fired in launch zone.
|
||||||
|
if not self:_CheckCoordLaunch(EventData.IniUnit:GetCoordinate()) then
|
||||||
|
self:T(self.lid.."Missile was not fired in launch zone. No tracking!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get the target unit. Note if if _target is not nil, the unit can sometimes not be found!
|
||||||
|
if _target then
|
||||||
|
self:E({target=_target})
|
||||||
|
--_targetName=Unit.getName(_target)
|
||||||
|
--_targetUnit=UNIT:FindByName(_targetName)
|
||||||
|
_targetUnit=UNIT:Find(_target)
|
||||||
|
end
|
||||||
|
self:E(FOX2.lid..string.format("EVENT SHOT: Target name = %s", tostring(_targetName)))
|
||||||
|
|
||||||
|
-- Track missiles of type AAM=1, SAM=2 or OTHER=6
|
||||||
|
local _track = weaponcategory==1 and missilecategory and (missilecategory==1 or missilecategory==2 or missilecategory==6)
|
||||||
|
|
||||||
|
-- Only track missiles
|
||||||
|
if _track then
|
||||||
|
|
||||||
|
local missile={} --#FOX2.MissileData
|
||||||
|
|
||||||
|
missile.active=true
|
||||||
|
missile.weapon=EventData.weapon
|
||||||
|
missile.missileType=_weapon
|
||||||
|
missile.missileRange=missilerange
|
||||||
|
missile.missileName=EventData.weapon:getName()
|
||||||
|
missile.shooterUnit=EventData.IniUnit
|
||||||
|
missile.shooterGroup=EventData.IniGroup
|
||||||
|
missile.shooterCoalition=EventData.IniUnit:GetCoalition()
|
||||||
|
missile.shooterName=EventData.IniUnitName
|
||||||
|
missile.shotTime=timer.getAbsTime()
|
||||||
|
missile.shotCoord=EventData.IniUnit:GetCoordinate()
|
||||||
|
missile.targetUnit=_targetUnit
|
||||||
|
missile.targetPlayer=self:_GetPlayerFromUnit(missile.targetUnit)
|
||||||
|
|
||||||
|
-- Add missile table.
|
||||||
|
table.insert(self.missiles, missile)
|
||||||
|
|
||||||
|
self:__MissileLaunch(0.1, missile)
|
||||||
|
|
||||||
end --if _track
|
end --if _track
|
||||||
|
|
||||||
@@ -737,6 +841,35 @@ function FOX2:_AddF10Commands(_unitName)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Turn player's launch alert on/off.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #string _unitname Name of the player unit.
|
||||||
|
function FOX2:_MyStatus(_unitname)
|
||||||
|
self:F2(_unitname)
|
||||||
|
|
||||||
|
-- Get player unit and player name.
|
||||||
|
local unit, playername = self:_GetPlayerUnitAndName(_unitname)
|
||||||
|
|
||||||
|
-- Check if we have a player.
|
||||||
|
if unit and playername then
|
||||||
|
|
||||||
|
-- Player data.
|
||||||
|
local playerData=self.players[playername] --#FOX2.PlayerData
|
||||||
|
|
||||||
|
if playerData then
|
||||||
|
|
||||||
|
local text=string.format("Status of player %s:", playerData.name)
|
||||||
|
|
||||||
|
text=text..string.format("Destroy missiles: %s", playerData.destroy)
|
||||||
|
text=text..string.format("Launch alert: %s", playerData.launchalert)
|
||||||
|
text=text..string.format("Me target: %d", self:_GetTargetMissiles(playerData.unit))
|
||||||
|
text=text..string.format("Am I safe? %s", self:_CheckCoordSafe(playerData.unit:GetCoordinate()))
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Turn player's launch alert on/off.
|
--- Turn player's launch alert on/off.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param #string _unitname Name of the player unit.
|
-- @param #string _unitname Name of the player unit.
|
||||||
@@ -808,10 +941,29 @@ end
|
|||||||
-- Misc Functions
|
-- Misc Functions
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Get a random text message in case you die.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @return #string Text in case you die.
|
||||||
|
function FOX2:_DeadText()
|
||||||
|
|
||||||
|
local texts={}
|
||||||
|
texts[1]="You're dead!"
|
||||||
|
texts[2]="Meet your maker!"
|
||||||
|
texts[3]="Time to meet your maker!"
|
||||||
|
texts[4]="Well, I guess that was it!"
|
||||||
|
texts[5]="Bye, bye!"
|
||||||
|
texts[6]="Cheers buddy, was nice knowing you!"
|
||||||
|
|
||||||
|
local r=math.random(#texts)
|
||||||
|
|
||||||
|
return texts[r]
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if a coordinate lies within a safe training zone.
|
--- Check if a coordinate lies within a safe training zone.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
||||||
-- @return #boolean
|
-- @return #boolean True if safe.
|
||||||
function FOX2:_CheckCoordSafe(coord)
|
function FOX2:_CheckCoordSafe(coord)
|
||||||
|
|
||||||
-- No safe zones defined ==> Everything is safe.
|
-- No safe zones defined ==> Everything is safe.
|
||||||
@@ -834,7 +986,7 @@ end
|
|||||||
--- Check if a coordinate lies within a launch zone.
|
--- Check if a coordinate lies within a launch zone.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
||||||
-- @return #boolean
|
-- @return #boolean True if in launch zone.
|
||||||
function FOX2:_CheckCoordLaunch(coord)
|
function FOX2:_CheckCoordLaunch(coord)
|
||||||
|
|
||||||
-- No safe zones defined ==> Everything is safe.
|
-- No safe zones defined ==> Everything is safe.
|
||||||
@@ -854,6 +1006,56 @@ function FOX2:_CheckCoordLaunch(coord)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #DCS.Weapon weapon The weapon.
|
||||||
|
-- @return #number Heading of weapon in degrees or -1.
|
||||||
|
function FOX2:_GetWeapongHeading(weapon)
|
||||||
|
|
||||||
|
if weapon and weapon:isExist() then
|
||||||
|
|
||||||
|
local wp=weapon:getPosition()
|
||||||
|
|
||||||
|
local wph = math.atan2(wp.x.z, wp.x.x)
|
||||||
|
|
||||||
|
if wph < 0 then
|
||||||
|
wph=wph+2*math.pi
|
||||||
|
end
|
||||||
|
|
||||||
|
wph=math.deg(wph)
|
||||||
|
|
||||||
|
return wph
|
||||||
|
end
|
||||||
|
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||||
|
-- @param #FOX2 self
|
||||||
|
-- @param #DCS.Weapon weapon The weapon.
|
||||||
|
-- @return #number Notching heading right, i.e. missile heading +90°
|
||||||
|
-- @return #number Notching heading left, i.e. missile heading -90°.
|
||||||
|
function FOX2:_GetNotchingHeadings(weapon)
|
||||||
|
|
||||||
|
if weapon then
|
||||||
|
|
||||||
|
local hdg=self:_GetWeapongHeading(weapon)
|
||||||
|
|
||||||
|
local hdg1=hdg+90
|
||||||
|
if hdg1>360 then
|
||||||
|
hdg1=hdg1-360
|
||||||
|
end
|
||||||
|
|
||||||
|
local hdg2=hdg-90
|
||||||
|
if hdg2<0 then
|
||||||
|
hdg2=hdg2+360
|
||||||
|
end
|
||||||
|
|
||||||
|
return hdg1, hdg2
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns the player data from a unit name.
|
--- Returns the player data from a unit name.
|
||||||
-- @param #FOX2 self
|
-- @param #FOX2 self
|
||||||
@@ -934,6 +1136,7 @@ function FOX2:_GetPlayerUnitAndName(_unitName)
|
|||||||
return nil,nil
|
return nil,nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ RESCUEHELO.UID=0
|
|||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RESCUEHELO.version="1.0.5"
|
RESCUEHELO.version="1.0.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -776,14 +776,19 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData)
|
|||||||
-- Debug.
|
-- Debug.
|
||||||
local text=string.format("Unit %s crashed or ejected.", unitname)
|
local text=string.format("Unit %s crashed or ejected.", unitname)
|
||||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||||
self:T(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Unit "alive" and in our rescue zone.
|
-- Get coordinate of unit.
|
||||||
if unit:IsAlive() and unit:IsInZone(self.rescuezone) then
|
|
||||||
|
|
||||||
-- Get coordinate of crashed unit.
|
|
||||||
local coord=unit:GetCoordinate()
|
local coord=unit:GetCoordinate()
|
||||||
|
|
||||||
|
if coord and self.rescuezone:IsCoordinateInZone(coord) then
|
||||||
|
|
||||||
|
-- This does not seem to work any more. Is:Alive returns flase on ejection.
|
||||||
|
-- Unit "alive" and in our rescue zone.
|
||||||
|
--if unit:IsAlive() and unit:IsInZone(self.rescuezone) then
|
||||||
|
-- Get coordinate of crashed unit.
|
||||||
|
--local coord=unit:GetCoordinate()
|
||||||
|
|
||||||
-- Debug mark on map.
|
-- Debug mark on map.
|
||||||
if self.Debug then
|
if self.Debug then
|
||||||
coord:MarkToCoalition(self.lid..string.format("Crash site of unit %s.", unitname), self.helo:GetCoalition())
|
coord:MarkToCoalition(self.lid..string.format("Crash site of unit %s.", unitname), self.helo:GetCoalition())
|
||||||
@@ -1091,7 +1096,7 @@ function RESCUEHELO:onafterRescue(From, Event, To, RescueCoord)
|
|||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Helo %s is send to rescue mission.", self.helo:GetName())
|
local text=string.format("Helo %s is send to rescue mission.", self.helo:GetName())
|
||||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||||
self:T(self.lid..text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Waypoint array.
|
-- Waypoint array.
|
||||||
local wp={}
|
local wp={}
|
||||||
|
|||||||
Reference in New Issue
Block a user