Compare commits

..

12 Commits

Author SHA1 Message Date
Applevangelist
41e8ddea8c GROUP - change to GetUnits(n) to make it more robust, now returns first alive unit,actually. Similar changes to GetHeading() 2022-05-07 11:54:33 +02:00
Applevangelist
cc49791997 Fallout fixes 2022-05-06 11:45:11 +02:00
Applevangelist
ba4a8050ba AI Patrol - life check on route 2022-05-06 10:36:39 +02:00
Applevangelist
7c5067a59a UNIT Register - small fix for trains 2022-05-06 08:01:31 +02:00
Applevangelist
69eb920173 AI_CAP - more fallout from the dead units in the API 2022-05-05 17:40:00 +02:00
Applevangelist
07d761941a AI_AIR - restrict AB on RTB 2022-05-05 16:41:32 +02:00
Applevangelist
ca52585759 AI/ZONE - Some fixes for units unreachable 2022-05-05 12:07:56 +02:00
Applevangelist
decc9d09f8 docu update 2022-05-05 11:34:14 +02:00
Applevangelist
466a18447c SRS - adding volume setting and a test on OS and IO available 2022-05-05 08:57:27 +02:00
Frank
27902ee107 Update Range.lua
**RANGE**
- Fixed a couple of bugs
- Added new FSM events for strafing
- Updated docs
2022-05-04 22:36:41 +02:00
Applevangelist
8a8b806362 further event related stuff not working any more 2022-05-04 18:09:56 +02:00
Applevangelist
40bb181c78 Another nil check... 2022-05-04 13:29:40 +02:00
14 changed files with 277 additions and 172 deletions

View File

@@ -589,7 +589,9 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
self:ClearTargetDistance()
--AIGroup:ClearTasks()
AIGroup:OptionProhibitAfterburner(true)
local EngageRoute = {}
--- Calculate the target route point.

View File

@@ -533,6 +533,10 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
DefenderCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
local TargetCoord = AttackSetUnit:GetFirst():GetPointVec3()
if not TargetCoord then
self:Return()
return
end
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )

View File

@@ -515,8 +515,8 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
--- Calculate the current route point.
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(

View File

@@ -428,8 +428,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
--- Calculate the current route point.
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
if not CurrentVec2 then -- flight dead at this point
return self
end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(

View File

@@ -460,7 +460,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(

View File

@@ -726,7 +726,8 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
end
if self.Controllable:IsAlive() then
local life = self.Controllable:GetLife() or 0
if self.Controllable:IsAlive() and life > 1 then
-- Determine if the AIControllable is within the PatrolZone.
-- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point.
@@ -743,8 +744,9 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
if self.Controllable:InAir() == false then
self:T( "Not in the air, finding route path within PatrolZone" )
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
if not CurrentVec2 then return end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
@@ -758,8 +760,9 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
else
self:T( "In the air, finding route path within PatrolZone" )
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
if not CurrentVec2 then return end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
@@ -870,9 +873,10 @@ function AI_PATROL_ZONE:onafterRTB()
--- Calculate the current route point.
local CurrentVec2 = self.Controllable:GetVec2()
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
if not CurrentVec2 then return end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(

View File

@@ -892,9 +892,8 @@ do -- COORDINATE
-- @param #COORDINATE TargetCoordinate The target COORDINATE. Can also be a DCS#Vec3.
-- @return DCS#Distance Distance The distance in meters.
function COORDINATE:Get2DDistance(TargetCoordinate)
if not TargetCoordinate then return 1000000 end
local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
local norm=UTILS.VecNorm(a)
return norm
end

View File

@@ -1332,7 +1332,11 @@ do -- SET_GROUP
if Event.IniDCSUnit then
local ObjectName, Object = self:FindInDatabase( Event )
if ObjectName then
if Event.IniDCSGroup:getSize() == 1 then -- Only remove if the last unit of the group was destroyed.
local size = 1
if Event.IniDCSGroup then
size = Event.IniDCSGroup:getSize()
end
if size == 1 then -- Only remove if the last unit of the group was destroyed.
self:Remove( ObjectName )
end
end

View File

@@ -174,6 +174,7 @@ end
-- @param DCS#Vec3 Vec3 The point to test.
-- @return #boolean true if the Vec3 is within the zone.
function ZONE_BASE:IsVec3InZone( Vec3 )
if not Vec3 then return false end
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
return InZone
end
@@ -1156,7 +1157,7 @@ end
-- @return #boolean true if the location is within the zone.
function ZONE_RADIUS:IsVec2InZone( Vec2 )
self:F2( Vec2 )
if not Vec2 then return false end
local ZoneVec2 = self:GetVec2()
if ZoneVec2 then
@@ -1174,7 +1175,7 @@ end
-- @return #boolean true if the point is within the zone.
function ZONE_RADIUS:IsVec3InZone( Vec3 )
self:F2( Vec3 )
if not Vec3 then return false end
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
return InZone
@@ -1965,7 +1966,7 @@ end
-- @return #boolean true if the location is within the zone.
function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 )
if not Vec2 then return false end
local Next
local Prev
local InPolygon = false
@@ -1995,7 +1996,9 @@ end
-- @return #boolean true if the point is within the zone.
function ZONE_POLYGON_BASE:IsVec3InZone( Vec3 )
self:F2( Vec3 )
if not Vec3 then return false end
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
return InZone

View File

@@ -591,7 +591,7 @@ do -- DETECTION_BASE
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Wrapper.Group#GROUP DetectionGroup The Group detecting.
-- @param Wrapper.Group#GROUP Detection The Group detecting.
-- @param #number DetectionTimeStamp Time stamp of detection event.
function DETECTION_BASE:onafterDetection( From, Event, To, Detection, DetectionTimeStamp )
@@ -662,7 +662,7 @@ do -- DETECTION_BASE
local DetectedObjectVec3 = DetectedObject:getPoint()
local DetectedObjectVec2 = { x = DetectedObjectVec3.x, y = DetectedObjectVec3.z }
local DetectionGroupVec3 = Detection:GetVec3()
local DetectionGroupVec3 = Detection:GetVec3() or {x=0,y=0,z=0}
local DetectionGroupVec2 = { x = DetectionGroupVec3.x, y = DetectionGroupVec3.z }
local Distance = ((DetectedObjectVec3.x - DetectionGroupVec3.x) ^ 2 +

View File

@@ -233,6 +233,16 @@
-- The next time you start the mission, these results are also automatically loaded.
--
-- Strafing results are currently **not** saved.
--
-- # FSM Events
--
-- This class creates additional events that can be used by mission designers for custom reactions
--
-- * `EnterRange` when a player enters a range zone. See @{#RANGE.OnAfterEnterRange}
-- * `ExitRange` when a player leaves a range zone. See @{#RANGE.OnAfterExitRange}
-- * `Impact` on impact of a player's weapon on a bombing target. See @{#RANGE.OnAfterImpact}
-- * `RollingIn` when a player rolls in on a strafing target. See @{#RANGE.OnAfterRollingIn}
-- * `StrafeResult` when a player finishes a strafing run. See @{#RANGE.OnAfterStrafeResult}
--
-- # Examples
--
@@ -366,14 +376,6 @@ RANGE.TargetType = {
COORD = "Coordinate"
}
--- Default range variables for RangeBoss/Hypeman tie in.
hypemanStrafeRollIn = "nil"
StrafeAircraftType = "strafeAircraftTypeNotSet"
Straferesult = {}
clientRollingIn = false
clientStrafed = false
invalidStrafe = false
--- Player settings.
-- @type RANGE.PlayerData
-- @field #boolean smokebombimpact Smoke bomb impact points.
@@ -408,6 +410,14 @@ invalidStrafe = false
-- @field #number smokepoints Number of smoke points.
-- @field #number heading Heading of pit.
--- Strafe status for player.
-- @type RANGE.StrafeStatus
-- @field #number hits Number of hits on target.
-- @field #number time Number of times.
-- @field #number ammo Amount of ammo.
-- @field #boolean pastfoulline If `true`, player passed foul line. Invalid pass.
-- @field #RANGE.StrafeTarget zone Strafe target.
--- Bomb target result.
-- @type RANGE.BombResult
-- @field #string name Name of closest target.
@@ -420,6 +430,13 @@ invalidStrafe = false
-- @field #number time Time via timer.getAbsTime() in seconds of impact.
-- @field #string date OS date.
--- Strafe result.
-- @type RANGE.StrafeResult
-- @field #string player Player name.
-- @field #string airframe Aircraft type of player.
-- @field #number time Time via timer.getAbsTime() in seconds of impact.
-- @field #string date OS date.
--- Sound file data.
-- @type RANGE.Soundfile
-- @field #string filename Name of the file
@@ -532,7 +549,7 @@ RANGE.MenuF10Root = nil
--- Range script version.
-- @field #string version
RANGE.version = "2.3.0"
RANGE.version = "2.4.0"
-- TODO list:
-- TODO: Verbosity level for messages.
@@ -583,6 +600,8 @@ function RANGE:New( rangename )
self:AddTransition("Stopped", "Start", "Running") -- Start RANGE script.
self:AddTransition("*", "Status", "*") -- Status of RANGE script.
self:AddTransition("*", "Impact", "*") -- Impact of bomb/rocket/missile.
self:AddTransition("*", "RollingIn", "*") -- Player rolling in on strafe target.
self:AddTransition("*", "StrafeResult", "*") -- Strafe result of player.
self:AddTransition("*", "EnterRange", "*") -- Player enters the range.
self:AddTransition("*", "ExitRange", "*") -- Player leaves the range.
self:AddTransition("*", "Save", "*") -- Save player results.
@@ -640,6 +659,37 @@ function RANGE:New( rangename )
-- @param #RANGE.BombResult result Data of the bombing run.
-- @param #RANGE.PlayerData player Data of player settings etc.
--- Triggers the FSM event "RollingIn".
-- @function [parent=#RANGE] RollingIn
-- @param #RANGE self
-- @param #RANGE.PlayerData player Data of player settings etc.
-- @param #RANGE.StrafeTarget target Strafe target.
--- On after "RollingIn" event user function. Called when a player rolls in to a strafe taret.
-- @function [parent=#RANGE] OnAfterRollingIn
-- @param #RANGE self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #RANGE.PlayerData player Data of player settings etc.
-- @param #RANGE.StrafeTarget target Strafe target.
--- Triggers the FSM event "StrafeResult".
-- @function [parent=#RANGE] StrafeResult
-- @param #RANGE self
-- @param #RANGE.PlayerData player Data of player settings etc.
-- @param #RANGE.StrafeResult result Data of the strafing run.
--- On after "StrafeResult" event user function. Called when a player finished a strafing run.
-- @function [parent=#RANGE] OnAfterStrafeResult
-- @param #RANGE self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #RANGE.PlayerData player Data of player settings etc.
-- @param #RANGE.StrafeResult result Data of the strafing run.
--- Triggers the FSM event "EnterRange".
-- @function [parent=#RANGE] EnterRange
-- @param #RANGE self
@@ -1594,7 +1644,6 @@ function RANGE:OnEventBirth( EventData )
self.strafeStatus[_uid] = nil
-- Add Menu commands after a delay of 0.1 seconds.
-- SCHEDULER:New(nil, self._AddF10Commands, {self,_unitName}, 0.1)
self:ScheduleOnce( 0.1, self._AddF10Commands, self, _unitName )
-- By default, some bomb impact points and do not flare each hit on target.
@@ -1613,7 +1662,6 @@ function RANGE:OnEventBirth( EventData )
-- Start check in zone timer.
if self.planes[_uid] ~= true then
-- SCHEDULER:New(nil, self._CheckInZone, {self, EventData.IniUnitName}, 1, 1)
self.timerCheckZone = TIMER:New( self._CheckInZone, self, EventData.IniUnitName ):Start( 1, 1 )
self.planes[_uid] = true
end
@@ -1647,7 +1695,7 @@ function RANGE:OnEventHit( EventData )
local targetname = EventData.TgtUnitName
-- Current strafe target of player.
local _currentTarget = self.strafeStatus[_unitID]
local _currentTarget = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
-- Player has rolled in on a strafing target.
if _currentTarget and target:IsAlive() then
@@ -1931,74 +1979,6 @@ end
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- FSM Functions
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
function RANGE:_SaveTargetSheet( _playername, result ) -- RangeBoss Specific Function
--- Function that saves data to file
local function _savefile( filename, data )
local f = io.open( filename, "wb" )
if f then
f:write( data )
f:close()
else
env.info( "RANGEBOSS EDIT - could not save target sheet to file" )
-- self:E(self.lid..string.format("ERROR: could not save target sheet to file %s.\nFile may contain invalid characters.", tostring(filename)))
end
end
-- Set path or default.
local path = self.targetpath
if lfs then
path = path or lfs.writedir() .. [[Logs\]]
end
-- Create unused file name.
local filename = nil
for i = 1, 9999 do
-- Create file name
if self.targetprefix then
filename = string.format( "%s_%s-%04d.csv", self.targetprefix, playerData.actype, i )
else
local name = UTILS.ReplaceIllegalCharacters( _playername, "_" )
filename = string.format( "RANGERESULTS-%s_Targetsheet-%s-%04d.csv", self.rangename, name, i )
end
-- Set path.
if path ~= nil then
filename = path .. "\\" .. filename
end
-- Check if file exists.
local _exists = UTILS.FileExists( filename )
if not _exists then
break
end
end
-- Header line
local data = "Name,Target,Distance,Radial,Quality,Rounds Fired,Rounds Hit,Rounds Quality,Attack Heading,Weapon,Airframe,Mission Time,OS Time\n"
-- local result=_result --#RANGE.BombResult
local distance = result.distance
local weapon = result.weapon
local target = result.name
local radial = result.radial
local quality = result.quality
local time = UTILS.SecondsToClock( result.time )
local airframe = result.airframe
local date = "n/a"
local roundsFired = result.roundsFired
local roundsHit = result.roundsHit
local strafeResult = result.roundsQuality
local attackHeading = result.heading
if os then
date = os.date()
end
data = data .. string.format( "%s,%s,%.2f,%03d,%s,%03d,%03d,%s,%03d,%s,%s,%s,%s", _playername, target, distance, radial, quality, roundsFired, roundsHit, strafeResult, attackHeading, weapon, airframe, time, date )
-- Save file.
_savefile( filename, data )
end
--- Check spawn queue and spawn aircraft if necessary.
-- @param #RANGE self
@@ -2299,6 +2279,73 @@ function RANGE:onafterLoad( From, Event, To )
end
end
--- Save target sheet.
-- @param #RANGE self
-- @param #string _playername Player name.
-- @param #RANGE.StrafeResult result Results table.
function RANGE:_SaveTargetSheet( _playername, result ) -- RangeBoss Specific Function
--- Function that saves data to file
local function _savefile( filename, data )
local f = io.open( filename, "wb" )
if f then
f:write( data )
f:close()
else
env.info( "RANGEBOSS EDIT - could not save target sheet to file" )
-- self:E(self.lid..string.format("ERROR: could not save target sheet to file %s.\nFile may contain invalid characters.", tostring(filename)))
end
end
-- Set path or default.
local path = self.targetpath
if lfs then
path = path or lfs.writedir() .. [[Logs\]]
end
-- Create unused file name.
local filename = nil
for i = 1, 9999 do
-- Create file name
if self.targetprefix then
filename = string.format( "%s_%s-%04d.csv", self.targetprefix, result.airframe, i )
else
local name = UTILS.ReplaceIllegalCharacters( _playername, "_" )
filename = string.format( "RANGERESULTS-%s_Targetsheet-%s-%04d.csv", self.rangename, name, i )
end
-- Set path.
if path ~= nil then
filename = path .. "\\" .. filename
end
-- Check if file exists.
local _exists = UTILS.FileExists( filename )
if not _exists then
break
end
end
-- Header line
local data = "Name,Target,Rounds Fired,Rounds Hit,Rounds Quality,Airframe,Mission Time,OS Time\n"
local target = result.name
local airframe = result.airframe
local roundsFired = result.roundsFired
local roundsHit = result.roundsHit
local strafeResult = result.roundsQuality
local time = UTILS.SecondsToClock( result.time )
local date = "n/a"
if os then
date = os.date()
end
data = data .. string.format( "%s,%s,%d,%d,%s,%s,%s,%s", _playername, target, roundsFired, roundsHit, strafeResult, airframe, time, date )
-- Save file.
_savefile( filename, data )
end
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Display Messages
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -2324,7 +2371,7 @@ function RANGE:_DisplayMyStrafePitResults( _unitName )
local _message = string.format( "My Top %d Strafe Pit Results:\n", self.ndisplayresult )
-- Get player results.
local _results = self.strafePlayerResults[_playername]
local _results = self.strafePlayerResults[_playername]
-- Create message.
if _results == nil then
@@ -2344,9 +2391,10 @@ function RANGE:_DisplayMyStrafePitResults( _unitName )
-- Loop over results
for _, _result in pairs( _results ) do
local result=_result --#RANGE.StrafeResult
-- Message text.
_message = _message .. string.format( "\n[%d] Hits %d - %s - %s", _count, _result.hits, _result.zone.name, _result.text )
_message = _message .. string.format( "\n[%d] Hits %d - %s - %s", _count, result.roundsHit, result.name, result.roundsQuality )
-- Best result.
if _bestMsg == "" then
@@ -2835,14 +2883,16 @@ function RANGE:_CheckInZone( _unitName )
local unitheading = 0 -- RangeBoss
if _unit and _playername then
-- Player data.
local playerData=self.PlayerSettings[_playername] -- #RANGE.PlayerData
--- Function to check if unit is in zone and facing in the right direction and is below the max alt.
local function checkme( targetheading, _zone )
local zone = _zone -- Core.Zone#ZONE
-- Heading check.
local unitheading = _unit:GetHeading()
unitheadingStrafe = _unit:GetHeading() -- RangeBoss
local pitheading = targetheading - 180
local deltaheading = unitheading - pitheading
local towardspit = math.abs( deltaheading ) <= 90 or math.abs( deltaheading - 360 ) <= 90
@@ -2867,7 +2917,7 @@ function RANGE:_CheckInZone( _unitName )
local _unitID = _unit:GetID()
-- Currently strafing? (strafeStatus is nil if not)
local _currentStrafeRun = self.strafeStatus[_unitID]
local _currentStrafeRun = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
if _currentStrafeRun then -- player has already registered for a strafing run.
@@ -2879,7 +2929,6 @@ function RANGE:_CheckInZone( _unitName )
-- Check if player is in strafe zone and below max alt.
if unitinzone then
StrafeAircraftType = _unit:GetTypeName() -- RangeBoss
-- Still in zone, keep counting hits. Increase counter.
_currentStrafeRun.time = _currentStrafeRun.time + 1
@@ -2909,8 +2958,10 @@ function RANGE:_CheckInZone( _unitName )
local _ammo = self:_GetAmmo( _unitName )
-- Result.
local _result = self.strafeStatus[_unitID]
local _result = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
local _sound = nil -- #RANGE.Soundfile
--[[ --RangeBoss commented out in order to implement strafe quality based on accuracy percentage, not the number of rounds on target
-- Judge this pass. Text is displayed on summary.
if _result.hits >= _result.zone.goodPass*2 then
@@ -2927,6 +2978,7 @@ function RANGE:_CheckInZone( _unitName )
_sound=RANGE.Sound.RCPoorPass
end
]]
-- Calculate accuracy of run. Number of hits wrt number of rounds fired.
local shots = _result.ammo - _ammo
local accur = 0
@@ -2936,29 +2988,30 @@ function RANGE:_CheckInZone( _unitName )
accur = 100
end
end
if invalidStrafe == true then --
_result.text = "* INVALID - PASSED FOUL LINE *"
-- Results text and sound message.
local resulttext=""
if _result.pastfoulline == true then --
resulttext = "* INVALID - PASSED FOUL LINE *"
_sound = RANGE.Sound.RCPoorPass --
else
if accur >= 90 then
_result.text = "DEADEYE PASS"
resulttext = "DEADEYE PASS"
_sound = RANGE.Sound.RCExcellentPass
elseif accur >= 75 then
_result.text = "EXCELLENT PASS"
resulttext = "EXCELLENT PASS"
_sound = RANGE.Sound.RCExcellentPass
elseif accur >= 50 then
_result.text = "GOOD PASS"
resulttext = "GOOD PASS"
_sound = RANGE.Sound.RCGoodPass
elseif accur >= 25 then
_result.text = "INEFFECTIVE PASS"
resulttext = "INEFFECTIVE PASS"
_sound = RANGE.Sound.RCIneffectivePass
else
_result.text = "POOR PASS"
resulttext = "POOR PASS"
_sound = RANGE.Sound.RCPoorPass
end
end
clientStrafed = true -- RANGEBOSS
-- Message text.
local _text = string.format( "%s, hits on target %s: %d", self:_myname( _unitName ), _result.zone.name, _result.hits )
@@ -2969,45 +3022,27 @@ function RANGE:_CheckInZone( _unitName )
-- Send message.
self:_DisplayMessageToGroup( _unit, _text )
-- RangeBoss Edit for strafe table insert
-- Local results.
local result = {} -- #RANGE.BombResult
result.name = _result.zone.name or "unknown"
result.distance = 0
result.radial = 0
result.weapon = "N/A"
result.quality = "N/A"
result.player = _playernamee
-- Strafe result.
local result = {} -- #RANGE.StrafeResult
result.player=_playername
result.name=_result.zone.name or "unknown"
result.time = timer.getAbsTime()
result.airframe = StrafeAircraftType
result.roundsFired = shots -- RANGEBOSS
result.roundsHit = _result.hits -- RANGEBOSS
result.roundsQuality = _result.text -- RANGEBOSS
result.roundsFired = shots
result.roundsHit = _result.hits
result.roundsQuality = resulttext
result.strafeAccuracy = accur
result.heading = unitheadingStrafe -- RANGEBOSS
Straferesult.name = _result.zone.name or "unknown"
Straferesult.distance = 0
Straferesult.radial = 0
Straferesult.weapon = "N/A"
Straferesult.quality = "N/A"
Straferesult.player = _playername
Straferesult.time = timer.getAbsTime()
Straferesult.airframe = StrafeAircraftType
Straferesult.roundsFired = shots
Straferesult.roundsHit = _result.hits
Straferesult.roundsQuality = _result.text
Straferesult.strafeAccuracy = accur
Straferesult.rangename = self.rangename
result.rangename = self.rangename
result.airframe=playerData.airframe
result.invalid = _result.pastfoulline
-- Griger Results.
self:StrafeResult(playerData, result)
-- Save trap sheet.
if playerData and playerData.targeton and self.targetsheet then
self:_SaveTargetSheet( _playername, result )
end
-- RangeBoss edit for strafe data saved to file
end
-- Voice over.
if self.rangecontrol then
@@ -3028,7 +3063,7 @@ function RANGE:_CheckInZone( _unitName )
-- Save stats so the player can retrieve them.
local _stats = self.strafePlayerResults[_playername] or {}
table.insert( _stats, _result )
table.insert( _stats, result )
self.strafePlayerResults[_playername] = _stats
end
@@ -3038,12 +3073,13 @@ function RANGE:_CheckInZone( _unitName )
-- Check to see if we're in any of the strafing zones (first time).
for _, _targetZone in pairs( self.strafeTargets ) do
local target=_targetZone --#RANGE.StrafeTarget
-- Get the current approach zone and check if player is inside.
local zone = _targetZone.polygon -- Core.Zone#ZONE_POLYGON_BASE
local zone = target.polygon -- Core.Zone#ZONE_POLYGON_BASE
-- Check if unit in zone and facing the right direction.
local unitinzone = checkme( _targetZone.heading, zone )
local unitinzone = checkme( target.heading, zone )
-- Player is inside zone.
if unitinzone then
@@ -3052,19 +3088,20 @@ function RANGE:_CheckInZone( _unitName )
local _ammo = self:_GetAmmo( _unitName )
-- Init strafe status for this player.
self.strafeStatus[_unitID] = { hits = 0, zone = _targetZone, time = 1, ammo = _ammo, pastfoulline = false }
self.strafeStatus[_unitID] = { hits = 0, zone = target, time = 1, ammo = _ammo, pastfoulline = false }
-- Rolling in!
local _msg = string.format( "%s, rolling in on strafe pit %s.", self:_myname( _unitName ), _targetZone.name )
local _msg = string.format( "%s, rolling in on strafe pit %s.", self:_myname( _unitName ), target.name )
if self.rangecontrol then
self.rangecontrol:NewTransmission( RANGE.Sound.RCRollingInOnStrafeTarget.filename, RANGE.Sound.RCRollingInOnStrafeTarget.duration, self.soundpath )
end
clientRollingIn = true -- RANGEBOSS
-- Send message.
self:_DisplayMessageToGroup( _unit, _msg, 10, true )
hypemanStrafeRollIn = _msg -- RANGEBOSS
-- Trigger event that player is rolling in.
self:RollingIn(playerData, target)
-- We found our player. Skip remaining checks.
break

View File

@@ -110,7 +110,11 @@
-- ## Set SRS Port
--
-- Use @{#MSRS.SetPort} to define the SRS port. Defaults to 5002.
--
--
-- ## Set SRS Volume
--
-- Use @{#MSRS.SetVolume} to define the SRS volume. Defaults to 1.0. Allowed values are between 0.0 and 1.0, from silent to loudest.
--
-- @field #MSRS
MSRS = {
ClassName = "MSRS",
@@ -131,7 +135,7 @@ MSRS = {
--- MSRS class version.
-- @field #string version
MSRS.version="0.0.4"
MSRS.version="0.0.5"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -150,8 +154,9 @@ MSRS.version="0.0.4"
-- @param #string PathToSRS Path to the directory, where SRS is located.
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies.
-- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
-- @param #number Volume Volume - 1.0 is max, 0.0 is silence
-- @return #MSRS self
function MSRS:New(PathToSRS, Frequency, Modulation)
function MSRS:New(PathToSRS, Frequency, Modulation, Volume)
-- Defaults.
Frequency =Frequency or 143
@@ -167,6 +172,12 @@ function MSRS:New(PathToSRS, Frequency, Modulation)
self:SetGender()
self:SetCoalition()
self:SetLabel()
self:SetVolume()
self.lid = string.format("%s-%s | ",self.name,self.version)
if not io or not os then
self:E(self.lid.."***** ERROR - io or os NOT desanitized! MSRS will not work!")
end
return self
end
@@ -209,6 +220,24 @@ function MSRS:GetPath()
return self.path
end
--- Set SRS volume.
-- @param #MSRS self
-- @param #number Volume Volume - 1.0 is max, 0.0 is silence
-- @return #MSRS self
function MSRS:SetVolume(Volume)
local volume = Volume or 1
if volume > 1 then volume = 1 elseif volume < 0 then volume = 0 end
self.volume = volume
return self
end
--- Get SRS volume.
-- @param #MSRS self
-- @return #number Volume Volume - 1.0 is max, 0.0 is silence
function MSRS:GetVolume()
return self.volume
end
--- Set label.
-- @param #MSRS self
-- @param #number Label. Default "ROBOT"

View File

@@ -711,11 +711,25 @@ end
-- @return DCS#Unit The DCS Unit.
function GROUP:GetDCSUnit( UnitNumber )
local DCSGroup=self:GetDCSObject()
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local DCSUnitFound=DCSGroup:getUnit( UnitNumber )
return DCSUnitFound
local UnitFound = nil
-- 2.7.1 dead event bug, return the first alive unit instead
local units = DCSGroup:getUnits() or {}
for _,_unit in pairs(units) do
local UnitFound = UNIT:Find(_unit)
if UnitFound and UnitFound:IsAlive() then
return UnitFound
end
end
end
return nil
@@ -1093,19 +1107,21 @@ end
function GROUP:GetHeading()
self:F2(self.GroupName)
self:F2(self.GroupName)
local GroupSize = self:GetSize()
local HeadingAccumulator = 0
local n=0
local Units = self:GetUnits()
if GroupSize then
for i = 1, GroupSize do
local unit=self:GetUnit(i)
for _,unit in pairs(Units) do
if unit and unit:IsAlive() then
HeadingAccumulator = HeadingAccumulator + unit:GetHeading()
n=n+1
end
end
return math.floor(HeadingAccumulator / n)
return math.floor(HeadingAccumulator / n)
end
BASE:E( { "Cannot GetHeading", Group = self, Alive = self:IsAlive() } )
@@ -1160,7 +1176,7 @@ function GROUP:GetFuelAvg()
local TotalFuel = 0
for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
local UnitFuel = Unit:GetFuel()
local UnitFuel = Unit:GetFuel() or 0
self:F( { Fuel = UnitFuel } )
TotalFuel = TotalFuel + UnitFuel
end

View File

@@ -119,7 +119,10 @@ function UNIT:Register( UnitName )
local unit=Unit.getByName(self.UnitName)
if unit then
self.GroupName=unit:getGroup():getName()
local group = unit:getGroup()
if group then
self.GroupName=group:getName()
end
end
-- Set event prio.