mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-07-21 14:31:54 +00:00
MISC
FMD: misc FOX v0.3.0 improvements RANGE v2.1.1 fixed bugs SCORING added option to reload csv file WAREHOUSE v0.7.1 added AssedSpawned FMS event.
This commit is contained in:
@@ -145,7 +145,7 @@ function FMD:New()
|
||||
self:AddTransition("*", "Status", "*") -- Start FMD script.
|
||||
|
||||
-- Start FMD.
|
||||
FMD:Start()
|
||||
self:Start()
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -239,28 +239,33 @@ end
|
||||
-- @param Wrapper.Unit#UNIT unit
|
||||
-- @return #FMD.DataPoint Datapoint.
|
||||
function FMD:_GetDataPoint(unit)
|
||||
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
-- Current coordinate.
|
||||
local coord=unit:GetCoordinate()
|
||||
|
||||
local dp={} --#FMD.DataPoint
|
||||
|
||||
dp.a={}
|
||||
dp.Alt=coord.y
|
||||
dp.AoA=unit:GetAoA()
|
||||
dp.Atot=nil
|
||||
dp.P=coord:GetPressure()
|
||||
dp.Pitch=unit:GetPitch()
|
||||
dp.Roll=unit:GetRoll()
|
||||
dp.time=timer.getAbsTime()
|
||||
dp.T=coord:GetTemperature()
|
||||
dp.v=unit:GetVelocityVec3()
|
||||
dp.Vtot=UTILS.VecNorm(dp.v)
|
||||
dp.Yaw=unit:GetYaw()
|
||||
dp.o=unit:GetOrientationX()
|
||||
dp.Hdg=unit:GetHeading()
|
||||
|
||||
return dp
|
||||
-- Current coordinate.
|
||||
local coord=unit:GetCoordinate()
|
||||
|
||||
local dp={} --#FMD.DataPoint
|
||||
|
||||
dp.a={}
|
||||
dp.Alt=coord.y
|
||||
dp.AoA=unit:GetAoA()
|
||||
dp.Atot=nil
|
||||
dp.P=coord:GetPressure()
|
||||
dp.Pitch=unit:GetPitch()
|
||||
dp.Roll=unit:GetRoll()
|
||||
dp.time=timer.getAbsTime()
|
||||
dp.T=coord:GetTemperature()
|
||||
dp.v=unit:GetVelocityVec3()
|
||||
dp.Vtot=UTILS.VecNorm(dp.v)
|
||||
dp.Yaw=unit:GetYaw()
|
||||
dp.o=unit:GetOrientationX()
|
||||
dp.Hdg=unit:GetHeading()
|
||||
|
||||
return dp
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
--- Get data of unit.
|
||||
@@ -292,9 +297,32 @@ function FMD:_Derivative(playerData)
|
||||
dpi.a.z=numderiv(dpm.v.z, dpp.v.z, dt)
|
||||
|
||||
dpi.DPitch=numderiv(dpm.Pitch, dpp.Pitch, dt)
|
||||
dpi.DRoll=numderiv(dpm.Roll, dpp.Roll, dt)
|
||||
--dpi.DRoll=numderiv(dpm.Roll, dpp.Roll, dt)
|
||||
dpi.DYaw=numderiv(dpm.Yaw, dpp.Yaw, dt)
|
||||
|
||||
-- Roll shortcuts.
|
||||
local r1=dpm.Roll
|
||||
local r2=dpp.Roll
|
||||
|
||||
-- Put roll in [0,360)
|
||||
if (r1<0) then
|
||||
r1=r1+360
|
||||
end
|
||||
if (r2<0) then
|
||||
r2=r2+360
|
||||
end
|
||||
|
||||
-- Handle case where 360 deg periodicity strikes.
|
||||
if r1<90 and r2>270 then
|
||||
r1=r1+360
|
||||
end
|
||||
if r1>270 and r2<90 then
|
||||
r2=r2+360
|
||||
end
|
||||
|
||||
--
|
||||
dpi.DRoll=numderiv(r1, r2, dt)
|
||||
|
||||
local ang=UTILS.VecAngle(dpm.o, dpp.o)
|
||||
dpi.omega=numderiv(0, ang, dt)
|
||||
|
||||
@@ -317,12 +345,20 @@ function FMD:_RecordData(playerData)
|
||||
-- Activate recording switch.
|
||||
playerData.recording=true
|
||||
end
|
||||
|
||||
-- Get data point.
|
||||
local dp=self:_GetDataPoint(playerData.unit)
|
||||
|
||||
-- Add data point to player table.
|
||||
table.insert(playerData.data, dp)
|
||||
-- Check if unit is alive.
|
||||
if playerData.unit and playerData.unit:IsAlive() then
|
||||
|
||||
-- Get data point.
|
||||
local dp=self:_GetDataPoint(playerData.unit)
|
||||
|
||||
-- Add data point to player table.
|
||||
table.insert(playerData.data, dp)
|
||||
|
||||
else
|
||||
-- Stop recording if player unit is not alive.
|
||||
self:_StopRecording(playerData.unitname)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -374,7 +410,7 @@ function FMD:_SaveData(playerData)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Header line
|
||||
local data="#Time,Altitude,Temperature,Pressure,Vtot,Vx,Vy,Vz,Atot,ax,ay,az,AoA,Pitch,dPitch/dt,Roll,dRoll/dt,Yaw,dYaw/dt\n"
|
||||
local data="#Time,Altitude,Temperature,Pressure,Vtot,Vx,Vy,Vz,Atot,ax,ay,az,AoA,Pitch,dPitch/dt,Roll,dRoll/dt,Yaw,dYaw/dt,Turn Rate\n"
|
||||
|
||||
local g0=playerData.data[1] --#FMD.DataPoint
|
||||
local T0=g0.time
|
||||
@@ -404,7 +440,11 @@ function FMD:_SaveData(playerData)
|
||||
local l=dp.AoA or 0
|
||||
local m=dp.Pitch or 0
|
||||
local n=dp.DPitch or 0
|
||||
local o=dp.Roll or 0
|
||||
local roll=dp.Roll or 0
|
||||
if roll<0 then
|
||||
roll=roll+360
|
||||
end
|
||||
local o=roll --dp.Roll or 0
|
||||
local p=dp.DRoll or 0
|
||||
local q=dp.Yaw or 0
|
||||
local r=dp.DYaw or 0
|
||||
@@ -510,13 +550,16 @@ function FMD:_AddF10Commands(_unitName)
|
||||
missionCommands.addCommandForGroup(gid, "Delta t=30 s", _timePath, self._SetTimeInterval, self, _unitName, 30.0)
|
||||
missionCommands.addCommandForGroup(gid, "Delta t=60 s", _timePath, self._SetTimeInterval, self, _unitName, 60.0)
|
||||
|
||||
-------------------------------
|
||||
-- F10/F<X> FMD/F1 Rec Duration
|
||||
-------------------------------
|
||||
local _durPath=missionCommands.addSubMenuForGroup(gid, "Rec Duration", _rootPath)
|
||||
-- F10/FMD/F1 Rec Duration/
|
||||
missionCommands.addCommandForGroup(gid, "T=10 s", _timePath, self._SetRecDuration, self, _unitName, 10)
|
||||
missionCommands.addCommandForGroup(gid, "T=30 s", _timePath, self._SetRecDuration, self, _unitName, 30)
|
||||
missionCommands.addCommandForGroup(gid, "T=60 s", _timePath, self._SetRecDuration, self, _unitName, 60)
|
||||
missionCommands.addCommandForGroup(gid, "T=5 min", _timePath, self._SetRecDuration, self, _unitName, 5*60)
|
||||
missionCommands.addCommandForGroup(gid, "T=10 min", _timePath, self._SetRecDuration, self, _unitName, 10*60)
|
||||
missionCommands.addCommandForGroup(gid, "T=10 s", _durPath, self._SetRecDuration, self, _unitName, 10)
|
||||
missionCommands.addCommandForGroup(gid, "T=30 s", _durPath, self._SetRecDuration, self, _unitName, 30)
|
||||
missionCommands.addCommandForGroup(gid, "T=60 s", _durPath, self._SetRecDuration, self, _unitName, 60)
|
||||
missionCommands.addCommandForGroup(gid, "T=5 min", _durPath, self._SetRecDuration, self, _unitName, 5*60)
|
||||
missionCommands.addCommandForGroup(gid, "T=10 min", _durPath, self._SetRecDuration, self, _unitName, 10*60)
|
||||
|
||||
--------------------------------
|
||||
-- F10/F<X> FMD/
|
||||
@@ -536,7 +579,7 @@ end
|
||||
-- @param #FMD self
|
||||
-- @param #string _unitName Name of player unit.
|
||||
-- @param #number rd Recording duration in sec.
|
||||
function FMD:_SetTimeInterval(_unitName, rd)
|
||||
function FMD:_SetRecDuration(_unitName, rd)
|
||||
|
||||
-- Get player unit and name.
|
||||
local _unit, _playername = self:_GetPlayerUnitAndName(_unitName)
|
||||
@@ -610,7 +653,7 @@ function FMD:_StartRecording(_unitName)
|
||||
playerData.SID=playerData.scheduler:Schedule(nil, self._RecordData, {self, playerData}, delay, playerData.dt, 0.0)
|
||||
|
||||
-- Stop scheduler once.
|
||||
playerData.scheduler:ScheduleOnce(playerData.rd+delay, self._StopRecording, {self,_unitName})
|
||||
playerData.scheduler:ScheduleOnce(playerData.rd+delay, self._StopRecording, self,_unitName)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- @module Functional.FOX2
|
||||
-- @image Functional_FOX2.png
|
||||
-- @module Functional.FOX
|
||||
-- @image Functional_FOX.png
|
||||
|
||||
|
||||
--- FOX2 class.
|
||||
-- @type FOX2
|
||||
--- FOX class.
|
||||
-- @type FOX
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||
-- @field #string lid Class id string for output to DCS log file.
|
||||
@@ -40,24 +40,25 @@
|
||||
-- @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.
|
||||
-- @field #boolean
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Fox 2!
|
||||
--- Fox 3!
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- 
|
||||
--
|
||||
-- # The FOX2 Concept
|
||||
-- # The FOX 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.
|
||||
-- As you probably know [Fox](https://en.wikipedia.org/wiki/Fox_(code_word)) is a NATO brevity 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.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #FOX2
|
||||
FOX2 = {
|
||||
ClassName = "FOX2",
|
||||
-- @field #FOX
|
||||
FOX = {
|
||||
ClassName = "FOX",
|
||||
Debug = false,
|
||||
lid = nil,
|
||||
menuadded = {},
|
||||
@@ -78,7 +79,7 @@ FOX2 = {
|
||||
|
||||
|
||||
--- Player data table holding all important parameters of each player.
|
||||
-- @type FOX2.PlayerData
|
||||
-- @type FOX.PlayerData
|
||||
-- @field Wrapper.Unit#UNIT unit Aircraft of the player.
|
||||
-- @field #string unitname Name of the unit.
|
||||
-- @field Wrapper.Client#CLIENT client Client object of player.
|
||||
@@ -92,9 +93,10 @@ FOX2 = {
|
||||
-- @field #boolean marklaunch Mark position of launched missile on F10 map.
|
||||
-- @field #number defeated Number of missiles defeated.
|
||||
-- @field #number dead Number of missiles not defeated.
|
||||
-- @field #boolean inzone Player is inside a protected zone.
|
||||
|
||||
--- Missile data table.
|
||||
-- @type FOX2.MissileData
|
||||
-- @type FOX.MissileData
|
||||
-- @field Wrapper.Unit#UNIT weapon Missile weapon unit.
|
||||
-- @field #boolean active If true the missile is active.
|
||||
-- @field #string missileType Type of missile.
|
||||
@@ -106,132 +108,175 @@ FOX2 = {
|
||||
-- @field #number shotTime Abs mission time in seconds the missile was fired.
|
||||
-- @field Core.Point#COORDINATE shotCoord Coordinate where the missile was fired.
|
||||
-- @field Wrapper.Unit#UNIT targetUnit Unit that was targeted.
|
||||
-- @field #FOX2.PlayerData targetPlayer Player that was targeted or nil.
|
||||
-- @field #FOX.PlayerData targetPlayer Player that was targeted or nil.
|
||||
|
||||
--- Main radio menu on group level.
|
||||
-- @field #table MenuF10 Root menu table on group level.
|
||||
FOX2.MenuF10={}
|
||||
FOX.MenuF10={}
|
||||
|
||||
--- Main radio menu on mission level.
|
||||
-- @field #table MenuF10Root Root menu on mission level.
|
||||
FOX2.MenuF10Root=nil
|
||||
FOX.MenuF10Root=nil
|
||||
|
||||
--- FOX2 class version.
|
||||
--- FOX class version.
|
||||
-- @field #string version
|
||||
FOX2.version="0.1.4"
|
||||
FOX.version="0.3.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO list:
|
||||
-- TODO: safe zones
|
||||
-- TODO: mark shooter on F10
|
||||
-- DONE: safe zones
|
||||
-- DONE: mark shooter on F10
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new FOX2 class object.
|
||||
-- @param #FOX2 self
|
||||
-- @return #FOX2 self.
|
||||
function FOX2:New()
|
||||
--- Create a new FOX class object.
|
||||
-- @param #FOX self
|
||||
-- @return #FOX self.
|
||||
function FOX:New()
|
||||
|
||||
self.lid="FOX2 | "
|
||||
self.lid="FOX | "
|
||||
|
||||
-- Inherit everthing from FSM class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #FOX2
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #FOX
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FOX2 script.
|
||||
self:AddTransition("*", "Status", "*") -- Start FOX2 script.
|
||||
self:AddTransition("*", "MissileLaunch", "*") -- Start FOX2 script.
|
||||
self:AddTransition("*", "MissileDestroyed", "*") -- Start FOX2 script.
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FOX script.
|
||||
self:AddTransition("*", "Status", "*") -- Status update.
|
||||
self:AddTransition("*", "MissileLaunch", "*") -- Missile was launched.
|
||||
self:AddTransition("*", "MissileDestroyed", "*") -- Missile was destroyed before impact.
|
||||
self:AddTransition("*", "EnterSafeZone", "*") -- Player enters a safe zone.
|
||||
self:AddTransition("*", "ExitSafeZone", "*") -- Player exists a safe zone.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the FOX2. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FOX2] Start
|
||||
-- @param #FOX2 self
|
||||
--- Triggers the FSM event "Start". Starts the FOX. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FOX] Start
|
||||
-- @param #FOX self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the FOX2. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FOX2] __Start
|
||||
-- @param #FOX2 self
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the FOX. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FOX] __Start
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the FOX2 and all its event handlers.
|
||||
-- @param #FOX2 self
|
||||
--- Triggers the FSM event "Stop". Stops the FOX and all its event handlers.
|
||||
-- @param #FOX self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the FOX2 and all its event handlers.
|
||||
-- @function [parent=#FOX2] __Stop
|
||||
-- @param #FOX2 self
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the FOX and all its event handlers.
|
||||
-- @function [parent=#FOX] __Stop
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Status".
|
||||
-- @function [parent=#FOX2] Status
|
||||
-- @param #FOX2 self
|
||||
-- @function [parent=#FOX] Status
|
||||
-- @param #FOX self
|
||||
|
||||
--- Triggers the FSM event "Status" after a delay.
|
||||
-- @function [parent=#FOX2] __Status
|
||||
-- @param #FOX2 self
|
||||
-- @function [parent=#FOX] __Status
|
||||
-- @param #FOX self
|
||||
-- @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.
|
||||
-- @function [parent=#FOX] MissileLaunch
|
||||
-- @param #FOX self
|
||||
-- @param #FOX.MissileData missile Data of the fired missile.
|
||||
|
||||
--- Triggers the FSM delayed event "MissileLaunch".
|
||||
-- @function [parent=#FOX2] __MissileLaunch
|
||||
-- @param #FOX2 self
|
||||
-- @function [parent=#FOX] __MissileLaunch
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds before the function is called.
|
||||
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||
-- @param #FOX.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
|
||||
-- @function [parent=#FOX] OnAfterMissileLaunch
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||
-- @param #FOX.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.
|
||||
-- @function [parent=#FOX] MissileDestroyed
|
||||
-- @param #FOX self
|
||||
-- @param #FOX.MissileData missile Data of the destroyed missile.
|
||||
|
||||
--- Triggers the FSM delayed event "MissileDestroyed".
|
||||
-- @function [parent=#FOX2] __MissileDestroyed
|
||||
-- @param #FOX2 self
|
||||
-- @function [parent=#FOX] __MissileDestroyed
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds before the function is called.
|
||||
-- @param #FOX2.MissileData missile Data of the destroyed missile.
|
||||
-- @param #FOX.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
|
||||
--- On after "MissileDestroyed" event user function. Called when a missile was destroyed.
|
||||
-- @function [parent=#FOX] OnAfterMissileDestroyed
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #FOX2.MissileData missile Data of the fired missile.
|
||||
-- @param #FOX.MissileData missile Data of the destroyed missile.
|
||||
|
||||
|
||||
--- Triggers the FSM event "EnterSafeZone".
|
||||
-- @function [parent=#FOX] EnterSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
--- Triggers the FSM delayed event "EnterSafeZone".
|
||||
-- @function [parent=#FOX] __EnterSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds before the function is called.
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
--- On after "EnterSafeZone" event user function. Called when a player enters a safe zone.
|
||||
-- @function [parent=#FOX] OnAfterEnterSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
|
||||
--- Triggers the FSM event "ExitSafeZone".
|
||||
-- @function [parent=#FOX] ExitSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
--- Triggers the FSM delayed event "ExitSafeZone".
|
||||
-- @function [parent=#FOX] __ExitSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #number delay Delay in seconds before the function is called.
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
--- On after "ExitSafeZone" event user function. Called when a player exists a safe zone.
|
||||
-- @function [parent=#FOX] OnAfterExitSafeZone
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #FOX.PlayerData player Player data.
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- On after Start event. Starts the missile trainer and adds event handlers.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FOX2:onafterStart(From, Event, To)
|
||||
function FOX:onafterStart(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Starting FOX2 Missile Trainer %s", FOX2.version)
|
||||
local text=string.format("Starting FOX Missile Trainer %s", FOX.version)
|
||||
env.info(text)
|
||||
|
||||
-- Handle events:
|
||||
@@ -247,14 +292,14 @@ function FOX2:onafterStart(From, Event, To)
|
||||
end
|
||||
|
||||
--- On after Stop event. Stops the missile trainer and unhandles events.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FOX2:onafterStop(From, Event, To)
|
||||
function FOX:onafterStop(From, Event, To)
|
||||
|
||||
-- Short info.
|
||||
local text=string.format("Stopping FOX2 Missile Trainer v0.0.1")
|
||||
local text=string.format("Stopping FOX Missile Trainer %s", FOX.version)
|
||||
env.info(text)
|
||||
|
||||
-- Handle events:
|
||||
@@ -268,10 +313,10 @@ end
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a training zone. Players in the zone are safe.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param Core.Zone#ZONE zone Training zone.
|
||||
-- @return #FOX2 self
|
||||
function FOX2:AddSafeZone(zone)
|
||||
-- @return #FOX self
|
||||
function FOX:AddSafeZone(zone)
|
||||
|
||||
table.insert(self.safezones, zone)
|
||||
|
||||
@@ -279,10 +324,10 @@ function FOX2:AddSafeZone(zone)
|
||||
end
|
||||
|
||||
--- Add a launch zone. Only missiles launched within these zones will be tracked.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param Core.Zone#ZONE zone Training zone.
|
||||
-- @return #FOX2 self
|
||||
function FOX2:AddLaunchZone(zone)
|
||||
-- @return #FOX self
|
||||
function FOX:AddLaunchZone(zone)
|
||||
|
||||
table.insert(self.launchzones, zone)
|
||||
|
||||
@@ -290,10 +335,10 @@ function FOX2:AddLaunchZone(zone)
|
||||
end
|
||||
|
||||
--- Set debug mode on/off.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #boolean switch If true debug mode on. If false/nil debug mode off
|
||||
-- @return #FOX2 self
|
||||
function FOX2:SetDebugOnOff(switch)
|
||||
-- @return #FOX self
|
||||
function FOX:SetDebugOnOff(switch)
|
||||
|
||||
if switch==nil then
|
||||
self.Debug=false
|
||||
@@ -305,17 +350,17 @@ function FOX2:SetDebugOnOff(switch)
|
||||
end
|
||||
|
||||
--- Set debug mode on.
|
||||
-- @param #FOX2 self
|
||||
-- @return #FOX2 self
|
||||
function FOX2:SetDebugOn()
|
||||
-- @param #FOX self
|
||||
-- @return #FOX self
|
||||
function FOX:SetDebugOn()
|
||||
self:SetDebugOnOff(true)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set debug mode off.
|
||||
-- @param #FOX2 self
|
||||
-- @return #FOX2 self
|
||||
function FOX2:SetDebugOff()
|
||||
-- @param #FOX self
|
||||
-- @return #FOX self
|
||||
function FOX:SetDebugOff()
|
||||
self:SetDebugOff(false)
|
||||
return self
|
||||
end
|
||||
@@ -325,26 +370,77 @@ end
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Check spawn queue and spawn aircraft if necessary.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FOX2:onafterStatus(From, Event, To)
|
||||
function FOX:onafterStatus(From, Event, To)
|
||||
|
||||
self:I(self.lid..string.format("Missile trainer status: %s", self:GetState()))
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
self:I(self.lid..string.format("Missile trainer status: %s", fsmstate))
|
||||
|
||||
self:_CheckMissileStatus()
|
||||
|
||||
self:__Status(-30)
|
||||
if fsmstate=="Running" then
|
||||
self:__Status(-10)
|
||||
end
|
||||
end
|
||||
|
||||
--- Check status of players.
|
||||
-- @param #FOX self
|
||||
-- @param #string _unitName Name of player unit.
|
||||
function FOX:_CheckPlayers()
|
||||
|
||||
for playername,_playersettings in pairs(self.players) do
|
||||
local playersettings=_playersettings --#FOX.PlayerData
|
||||
|
||||
local unitname=playersettings.unitname
|
||||
local unit=UNIT:FindByName(unitname)
|
||||
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
local coord=unit:GetCoordinate()
|
||||
|
||||
local issafe=self:_CheckCoordSafe(coord)
|
||||
|
||||
|
||||
if issafe then
|
||||
|
||||
-----------------------------
|
||||
-- Player INSIDE Safe Zone --
|
||||
-----------------------------
|
||||
|
||||
if not playersettings.inzone then
|
||||
self:EnterSafeZone(playersettings)
|
||||
playersettings.inzone=true
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
------------------------------
|
||||
-- Player OUTSIDE Safe Zone --
|
||||
------------------------------
|
||||
|
||||
if playersettings.inzone==true then
|
||||
self:ExitSafeZone(playersettings)
|
||||
playersettings.inzone=false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Missile status
|
||||
-- @param #FOX2 self
|
||||
function FOX2:_CheckMissileStatus()
|
||||
-- @param #FOX self
|
||||
function FOX:_CheckMissileStatus()
|
||||
|
||||
local text="Missiles:"
|
||||
for i,_missile in pairs(self.missiles) do
|
||||
local missile=_missile --#FOX2.MissileData
|
||||
local missile=_missile --#FOX.MissileData
|
||||
|
||||
local targetname="unkown"
|
||||
if missile.targetUnit then
|
||||
@@ -368,19 +464,19 @@ function FOX2:_CheckMissileStatus()
|
||||
end
|
||||
|
||||
--- Missle launch.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #FOX2.MissileData missile Fired missile
|
||||
function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||
-- @param #FOX.MissileData missile Fired missile
|
||||
function FOX:onafterMissileLaunch(From, Event, To, missile)
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
self:I(FOX2.lid..string.format("FOX2: Tracking %s - %s.", missile.missileType, missile.missileName))
|
||||
self:I(FOX.lid..string.format("FOX: Tracking %s - %s.", missile.missileType, missile.missileName))
|
||||
|
||||
-- Loop over players.
|
||||
for _,_player in pairs(self.players) do
|
||||
local player=_player --#FOX2.PlayerData
|
||||
local player=_player --#FOX.PlayerData
|
||||
|
||||
-- Player position.
|
||||
local playerUnit=player.unit
|
||||
@@ -406,7 +502,7 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||
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 whether this is a direct target.
|
||||
--TODO: lauchalertall option.
|
||||
MESSAGE:New(text, 5, "ALERT"):ToClient(player.client)
|
||||
|
||||
@@ -482,7 +578,7 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||
|
||||
-- Loop over players.
|
||||
for _,_player in pairs(self.players) do
|
||||
local player=_player --#FOX2.PlayerData
|
||||
local player=_player --#FOX.PlayerData
|
||||
|
||||
-- Check that player was not the one who launched the missile.
|
||||
if player.unitname~=missile.shooterName then
|
||||
@@ -588,7 +684,7 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||
missile.active=false
|
||||
|
||||
--Terminate the timer.
|
||||
self:T(FOX2.lid..string.format("Terminating missile track timer."))
|
||||
self:T(FOX.lid..string.format("Terminating missile track timer."))
|
||||
return nil
|
||||
|
||||
end -- _status check
|
||||
@@ -596,7 +692,7 @@ function FOX2:onafterMissileLaunch(From, Event, To, missile)
|
||||
end -- end function trackBomb
|
||||
|
||||
-- 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(FOX.lid..string.format("Tracking of missile starts in 0.1 seconds."))
|
||||
timer.scheduleFunction(trackMissile, missile.weapon, timer.getTime()+0.0001)
|
||||
|
||||
end
|
||||
@@ -605,10 +701,10 @@ end
|
||||
-- Event Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- FOX2 event handler for event birth.
|
||||
-- @param #FOX2 self
|
||||
--- FOX event handler for event birth.
|
||||
-- @param #FOX self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function FOX2:OnEventBirth(EventData)
|
||||
function FOX:OnEventBirth(EventData)
|
||||
self:F3({eventbirth = EventData})
|
||||
|
||||
-- Nil checks.
|
||||
@@ -649,7 +745,7 @@ function FOX2:OnEventBirth(EventData)
|
||||
SCHEDULER:New(nil, self._AddF10Commands, {self,_unitName}, 0.1)
|
||||
|
||||
-- Player data.
|
||||
local playerData={} --#FOX2.PlayerData
|
||||
local playerData={} --#FOX.PlayerData
|
||||
|
||||
-- Player unit, client and callsign.
|
||||
playerData.unit = playerunit
|
||||
@@ -677,10 +773,10 @@ function FOX2:OnEventBirth(EventData)
|
||||
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
|
||||
--- FOX event handler for event shot (when a unit releases a rocket or bomb (but not a fast firing gun).
|
||||
-- @param #FOX self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function FOX2:OnEventShot(EventData)
|
||||
function FOX:OnEventShot(EventData)
|
||||
self:I({eventshot = EventData})
|
||||
|
||||
if EventData.Weapon==nil then
|
||||
@@ -712,13 +808,13 @@ function FOX2:OnEventShot(EventData)
|
||||
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)))
|
||||
self:E(FOX.lid.."EVENT SHOT: FOX")
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Ini unit = %s", tostring(EventData.IniUnitName)))
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Ini group = %s", tostring(EventData.IniGroupName)))
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Weapon type = %s", tostring(_weapon)))
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Weapon categ = %s", tostring(weaponcategory)))
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Missil categ = %s", tostring(missilecategory)))
|
||||
self:E(FOX.lid..string.format("EVENT SHOT: Missil range = %s", tostring(missilerange)))
|
||||
|
||||
|
||||
-- Check if fired in launch zone.
|
||||
@@ -734,7 +830,7 @@ function FOX2:OnEventShot(EventData)
|
||||
--_targetUnit=UNIT:FindByName(_targetName)
|
||||
_targetUnit=UNIT:Find(_target)
|
||||
end
|
||||
self:E(FOX2.lid..string.format("EVENT SHOT: Target name = %s", tostring(_targetName)))
|
||||
self:E(FOX.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)
|
||||
@@ -742,7 +838,7 @@ function FOX2:OnEventShot(EventData)
|
||||
-- Only track missiles
|
||||
if _track then
|
||||
|
||||
local missile={} --#FOX2.MissileData
|
||||
local missile={} --#FOX.MissileData
|
||||
|
||||
missile.active=true
|
||||
missile.weapon=EventData.weapon
|
||||
@@ -758,10 +854,15 @@ function FOX2:OnEventShot(EventData)
|
||||
missile.targetUnit=_targetUnit
|
||||
missile.targetPlayer=self:_GetPlayerFromUnit(missile.targetUnit)
|
||||
|
||||
-- Add missile table.
|
||||
table.insert(self.missiles, missile)
|
||||
-- TODO: or in protected set!
|
||||
if missile.targetPlayer then
|
||||
|
||||
self:__MissileLaunch(0.1, missile)
|
||||
-- Add missile table.
|
||||
table.insert(self.missiles, missile)
|
||||
|
||||
self:__MissileLaunch(0.1, missile)
|
||||
|
||||
end
|
||||
|
||||
end --if _track
|
||||
|
||||
@@ -773,9 +874,9 @@ end
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add menu commands for player.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string _unitName Name of player unit.
|
||||
function FOX2:_AddF10Commands(_unitName)
|
||||
function FOX:_AddF10Commands(_unitName)
|
||||
self:F(_unitName)
|
||||
|
||||
-- Get player unit and name.
|
||||
@@ -797,40 +898,40 @@ function FOX2:_AddF10Commands(_unitName)
|
||||
|
||||
-- Set menu root path.
|
||||
local _rootPath=nil
|
||||
if FOX2.MenuF10Root then
|
||||
if FOX.MenuF10Root then
|
||||
------------------------
|
||||
-- MISSON LEVEL MENUE --
|
||||
------------------------
|
||||
|
||||
-- F10/FOX2/...
|
||||
_rootPath=FOX2.MenuF10Root
|
||||
-- F10/FOX/...
|
||||
_rootPath=FOX.MenuF10Root
|
||||
|
||||
else
|
||||
------------------------
|
||||
-- GROUP LEVEL MENUES --
|
||||
------------------------
|
||||
|
||||
-- Main F10 menu: F10/FOX2/
|
||||
if FOX2.MenuF10[gid]==nil then
|
||||
FOX2.MenuF10[gid]=missionCommands.addSubMenuForGroup(gid, "FOX2")
|
||||
-- Main F10 menu: F10/FOX/
|
||||
if FOX.MenuF10[gid]==nil then
|
||||
FOX.MenuF10[gid]=missionCommands.addSubMenuForGroup(gid, "FOX")
|
||||
end
|
||||
|
||||
-- F10/FOX2/...
|
||||
_rootPath=FOX2.MenuF10[gid]
|
||||
-- F10/FOX/...
|
||||
_rootPath=FOX.MenuF10[gid]
|
||||
|
||||
end
|
||||
|
||||
|
||||
--------------------------------
|
||||
-- F10/F<X> FOX2/F1 Help
|
||||
-- F10/F<X> FOX/F1 Help
|
||||
--------------------------------
|
||||
local _helpPath=missionCommands.addSubMenuForGroup(gid, "Help", _rootPath)
|
||||
-- F10/FOX2/F1 Help/
|
||||
-- F10/FOX/F1 Help/
|
||||
--missionCommands.addCommandForGroup(gid, "Subtitles On/Off", _helpPath, self._SubtitlesOnOff, self, _unitName) -- F7
|
||||
--missionCommands.addCommandForGroup(gid, "Trapsheet On/Off", _helpPath, self._TrapsheetOnOff, self, _unitName) -- F8
|
||||
|
||||
-------------------------
|
||||
-- F10/F<X> FOX2/
|
||||
-- F10/F<X> FOX/
|
||||
-------------------------
|
||||
|
||||
missionCommands.addCommandForGroup(gid, "Launch Alerts On/Off", _rootPath, self._ToggleLaunchAlert, self, _unitName) -- F2
|
||||
@@ -848,9 +949,9 @@ end
|
||||
|
||||
|
||||
--- Turn player's launch alert on/off.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string _unitname Name of the player unit.
|
||||
function FOX2:_MyStatus(_unitname)
|
||||
function FOX:_MyStatus(_unitname)
|
||||
self:F2(_unitname)
|
||||
|
||||
-- Get player unit and player name.
|
||||
@@ -860,7 +961,7 @@ function FOX2:_MyStatus(_unitname)
|
||||
if unit and playername then
|
||||
|
||||
-- Player data.
|
||||
local playerData=self.players[playername] --#FOX2.PlayerData
|
||||
local playerData=self.players[playername] --#FOX.PlayerData
|
||||
|
||||
if playerData then
|
||||
|
||||
@@ -877,9 +978,9 @@ end
|
||||
|
||||
|
||||
--- Turn player's launch alert on/off.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string _unitname Name of the player unit.
|
||||
function FOX2:_ToggleLaunchAlert(_unitname)
|
||||
function FOX:_ToggleLaunchAlert(_unitname)
|
||||
self:F2(_unitname)
|
||||
|
||||
-- Get player unit and player name.
|
||||
@@ -889,7 +990,7 @@ function FOX2:_ToggleLaunchAlert(_unitname)
|
||||
if unit and playername then
|
||||
|
||||
-- Player data.
|
||||
local playerData=self.players[playername] --#FOX2.PlayerData
|
||||
local playerData=self.players[playername] --#FOX.PlayerData
|
||||
|
||||
if playerData then
|
||||
|
||||
@@ -910,9 +1011,9 @@ function FOX2:_ToggleLaunchAlert(_unitname)
|
||||
end
|
||||
|
||||
--- Turn player's
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string _unitname Name of the player unit.
|
||||
function FOX2:_ToggleDestroyMissiles(_unitname)
|
||||
function FOX:_ToggleDestroyMissiles(_unitname)
|
||||
self:F2(_unitname)
|
||||
|
||||
-- Get player unit and player name.
|
||||
@@ -922,7 +1023,7 @@ function FOX2:_ToggleDestroyMissiles(_unitname)
|
||||
if unit and playername then
|
||||
|
||||
-- Player data.
|
||||
local playerData=self.players[playername] --#FOX2.PlayerData
|
||||
local playerData=self.players[playername] --#FOX.PlayerData
|
||||
|
||||
if playerData then
|
||||
|
||||
@@ -948,9 +1049,9 @@ end
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Get a random text message in case you die.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @return #string Text in case you die.
|
||||
function FOX2:_DeadText()
|
||||
function FOX:_DeadText()
|
||||
|
||||
local texts={}
|
||||
texts[1]="You're dead!"
|
||||
@@ -967,10 +1068,10 @@ end
|
||||
|
||||
|
||||
--- Check if a coordinate lies within a safe training zone.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
||||
-- @return #boolean True if safe.
|
||||
function FOX2:_CheckCoordSafe(coord)
|
||||
function FOX:_CheckCoordSafe(coord)
|
||||
|
||||
-- No safe zones defined ==> Everything is safe.
|
||||
if #self.safezones==0 then
|
||||
@@ -990,10 +1091,10 @@ function FOX2:_CheckCoordSafe(coord)
|
||||
end
|
||||
|
||||
--- Check if a coordinate lies within a launch zone.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param Core.Point#COORDINATE coord Coordinate to check.
|
||||
-- @return #boolean True if in launch zone.
|
||||
function FOX2:_CheckCoordLaunch(coord)
|
||||
function FOX:_CheckCoordLaunch(coord)
|
||||
|
||||
-- No safe zones defined ==> Everything is safe.
|
||||
if #self.launchzones==0 then
|
||||
@@ -1013,10 +1114,10 @@ function FOX2:_CheckCoordLaunch(coord)
|
||||
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.
|
||||
-- @param #FOX self
|
||||
-- @param DCS#Weapon weapon The weapon.
|
||||
-- @return #number Heading of weapon in degrees or -1.
|
||||
function FOX2:_GetWeapongHeading(weapon)
|
||||
function FOX:_GetWeapongHeading(weapon)
|
||||
|
||||
if weapon and weapon:isExist() then
|
||||
|
||||
@@ -1037,11 +1138,11 @@ function FOX2:_GetWeapongHeading(weapon)
|
||||
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.
|
||||
-- @param #FOX 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)
|
||||
function FOX:_GetNotchingHeadings(weapon)
|
||||
|
||||
if weapon then
|
||||
|
||||
@@ -1064,13 +1165,13 @@ function FOX2:_GetNotchingHeadings(weapon)
|
||||
end
|
||||
|
||||
--- Returns the player data from a unit name.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param #string unitName Name of the unit.
|
||||
-- @return #FOX2.PlayerData Player data.
|
||||
function FOX2:_GetPlayerFromUnitname(unitName)
|
||||
-- @return #FOX.PlayerData Player data.
|
||||
function FOX:_GetPlayerFromUnitname(unitName)
|
||||
|
||||
for _,_player in pairs(self.players) do
|
||||
local player=_player --#FOX2.PlayerData
|
||||
local player=_player --#FOX.PlayerData
|
||||
|
||||
if player.unitname==unitName then
|
||||
return player
|
||||
@@ -1081,10 +1182,10 @@ function FOX2:_GetPlayerFromUnitname(unitName)
|
||||
end
|
||||
|
||||
--- Retruns the player data from a unit.
|
||||
-- @param #FOX2 self
|
||||
-- @param #FOX self
|
||||
-- @param Wrapper.Unit#UNIT unit
|
||||
-- @return #FOX2.PlayerData Player data.
|
||||
function FOX2:_GetPlayerFromUnit(unit)
|
||||
-- @return #FOX.PlayerData Player data.
|
||||
function FOX:_GetPlayerFromUnit(unit)
|
||||
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
@@ -1092,7 +1193,7 @@ function FOX2:_GetPlayerFromUnit(unit)
|
||||
local unitname=unit:GetName()
|
||||
|
||||
for _,_player in pairs(self.players) do
|
||||
local player=_player --#FOX2.PlayerData
|
||||
local player=_player --#FOX.PlayerData
|
||||
|
||||
if player.unitname==unitname then
|
||||
return player
|
||||
@@ -1105,11 +1206,11 @@ function FOX2:_GetPlayerFromUnit(unit)
|
||||
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 #FOX self
|
||||
-- @param #string _unitName Name of the player unit.
|
||||
-- @return Wrapper.Unit#UNIT Unit of player or nil.
|
||||
-- @return #string Name of the player or nil.
|
||||
function FOX2:_GetPlayerUnitAndName(_unitName)
|
||||
function FOX:_GetPlayerUnitAndName(_unitName)
|
||||
self:F2(_unitName)
|
||||
|
||||
if _unitName ~= nil then
|
||||
|
||||
@@ -340,7 +340,7 @@ RANGE.MenuF10Root=nil
|
||||
|
||||
--- Range script version.
|
||||
-- @field #string version
|
||||
RANGE.version="2.1.0"
|
||||
RANGE.version="2.1.1"
|
||||
|
||||
--TODO list:
|
||||
--TODO: Verbosity level for messages.
|
||||
@@ -532,7 +532,7 @@ function RANGE:onafterStart()
|
||||
end
|
||||
|
||||
if self.location==nil then
|
||||
local text=string.format("ERROR! No range location found. Number of strafe targets = %d. Number of bomb targets = %d.", self.rangename, self.nstrafetargets, self.nbombtargets)
|
||||
local text=string.format("ERROR! No range location found. Number of strafe targets = %d. Number of bomb targets = %d.", self.nstrafetargets, self.nbombtargets)
|
||||
self:E(self.id..text)
|
||||
return
|
||||
end
|
||||
@@ -1095,7 +1095,7 @@ function RANGE:AddBombingTargetUnit(unit, goodhitrange, randommove)
|
||||
|
||||
local target={} --#RANGE.BombTarget
|
||||
target.name=name
|
||||
target.target=target
|
||||
target.target=unit
|
||||
target.goodhitrange=goodhitrange
|
||||
target.move=randommove
|
||||
target.speed=speed
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
--
|
||||
-- When a player commits too much damage to friendlies, his penalty score will reach a certain level.
|
||||
-- Use the method @{#SCORING.SetFratricide}() to define the level when a player gets kicked.
|
||||
-- By default, the fratricide level is the default penalty mutiplier * 2 for the penalty score.
|
||||
-- By default, the fratricide level is the default penalty multiplier * 2 for the penalty score.
|
||||
--
|
||||
-- # Penalty score when a player changes the coalition.
|
||||
--
|
||||
@@ -227,10 +227,12 @@ SCORING = {
|
||||
ClassName = "SCORING",
|
||||
ClassID = 0,
|
||||
Players = {},
|
||||
CSVdata = {},
|
||||
}
|
||||
|
||||
local _SCORINGCoalition =
|
||||
{
|
||||
[0] = "Neutral",
|
||||
[1] = "Red",
|
||||
[2] = "Blue",
|
||||
}
|
||||
@@ -247,13 +249,15 @@ local _SCORINGCategory =
|
||||
--- Creates a new SCORING object to administer the scoring achieved by players.
|
||||
-- @param #SCORING self
|
||||
-- @param #string GameName The name of the game. This name is also logged in the CSV score file.
|
||||
-- @param #string FileName (Optional) Name of the CSV file for saving results. If the file exists, player scores are read.
|
||||
-- @param #boolean MenuOff (Optional) Done create player menus.
|
||||
-- @return #SCORING self
|
||||
-- @usage
|
||||
--
|
||||
-- -- Define a new scoring object for the mission Gori Valley.
|
||||
-- ScoringObject = SCORING:New( "Gori Valley" )
|
||||
--
|
||||
function SCORING:New( GameName )
|
||||
function SCORING:New( GameName, FileName, MenuOff )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SCORING
|
||||
@@ -264,6 +268,10 @@ function SCORING:New( GameName )
|
||||
error( "A game name must be given to register the scoring results" )
|
||||
end
|
||||
|
||||
if FileName then
|
||||
self.FileName = FileName
|
||||
end
|
||||
|
||||
|
||||
-- Additional Object scores
|
||||
self.ScoringObjects = {}
|
||||
@@ -290,6 +298,9 @@ function SCORING:New( GameName )
|
||||
|
||||
self:SetDisplayMessagePrefix()
|
||||
|
||||
-- No player menus.
|
||||
self.MenuOff=MenuOff
|
||||
|
||||
-- Event handlers
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
@@ -312,7 +323,7 @@ function SCORING:New( GameName )
|
||||
|
||||
|
||||
-- Create the CSV file.
|
||||
self:OpenCSV( GameName )
|
||||
self:OpenCSV( GameName, FileName )
|
||||
|
||||
return self
|
||||
|
||||
@@ -600,11 +611,13 @@ end
|
||||
-- @param #SCORING self
|
||||
-- @return #SCORING
|
||||
function SCORING:SetScoringMenu( ScoringGroup )
|
||||
if not self.MenuOff then
|
||||
local Menu = MENU_GROUP:New( ScoringGroup, 'Scoring and Statistics' )
|
||||
local ReportGroupSummary = MENU_GROUP_COMMAND:New( ScoringGroup, 'Summary report players in group', Menu, SCORING.ReportScoreGroupSummary, self, ScoringGroup )
|
||||
local ReportGroupDetailed = MENU_GROUP_COMMAND:New( ScoringGroup, 'Detailed report players in group', Menu, SCORING.ReportScoreGroupDetailed, self, ScoringGroup )
|
||||
local ReportToAllSummary = MENU_GROUP_COMMAND:New( ScoringGroup, 'Summary report all players', Menu, SCORING.ReportScoreAllSummary, self, ScoringGroup )
|
||||
self:SetState( ScoringGroup, "ScoringMenu", Menu )
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1758,47 +1771,49 @@ function SCORING:ReportScoreAllSummary( PlayerGroup )
|
||||
|
||||
end
|
||||
|
||||
|
||||
function SCORING:SecondsToClock(sSeconds)
|
||||
local nSeconds = sSeconds
|
||||
if nSeconds == 0 then
|
||||
--return nil;
|
||||
return "00:00:00";
|
||||
else
|
||||
nHours = string.format("%02.f", math.floor(nSeconds/3600));
|
||||
nMins = string.format("%02.f", math.floor(nSeconds/60 - (nHours*60)));
|
||||
nSecs = string.format("%02.f", math.floor(nSeconds - nHours*3600 - nMins *60));
|
||||
return nHours..":"..nMins..":"..nSecs
|
||||
end
|
||||
end
|
||||
|
||||
--- Opens a score CSV file to log the scores.
|
||||
-- @param #SCORING self
|
||||
-- @param #string ScoringCSV
|
||||
-- @param #string FileName Name of the csv file.
|
||||
-- @return #SCORING self
|
||||
-- @usage
|
||||
-- -- Open a new CSV file to log the scores of the game Gori Valley. Let the name of the CSV file begin with "Player Scores".
|
||||
-- ScoringObject = SCORING:New( "Gori Valley" )
|
||||
-- ScoringObject:OpenCSV( "Player Scores" )
|
||||
function SCORING:OpenCSV( ScoringCSV )
|
||||
function SCORING:OpenCSV( ScoringCSV, FileName )
|
||||
self:F( ScoringCSV )
|
||||
|
||||
if lfs and io and os then
|
||||
|
||||
if ScoringCSV then
|
||||
self.ScoringCSV = ScoringCSV
|
||||
local fdir = lfs.writedir() .. [[Logs\]] .. self.ScoringCSV .. " " .. os.date( "%Y-%m-%d %H-%M-%S" ) .. ".csv"
|
||||
|
||||
self.CSVFile, self.err = io.open( fdir, "w+" )
|
||||
if not self.CSVFile then
|
||||
error( "Error: Cannot open CSV file in " .. lfs.writedir() )
|
||||
|
||||
-- File name.
|
||||
local fdir = lfs.writedir() .. [[Logs\]] .. ScoringCSV .. " " .. os.date( "%Y-%m-%d %H-%M-%S" ) .. ".csv"
|
||||
|
||||
if FileName then
|
||||
fdir=lfs.writedir() .. [[Logs\]] .. FileName
|
||||
end
|
||||
|
||||
if UTILS.FileExists(fdir) then
|
||||
self:LoadCSV(fdir)
|
||||
self.CSVFile, self.err = io.open( fdir, "a+" )
|
||||
if not self.CSVFile then
|
||||
error( "Error: Cannot open CSV file in " .. lfs.writedir() )
|
||||
end
|
||||
|
||||
else
|
||||
self.CSVFile, self.err = io.open( fdir, "w+" )
|
||||
if not self.CSVFile then
|
||||
error( "Error: Cannot open CSV file in " .. lfs.writedir() )
|
||||
end
|
||||
self.CSVFile:write( '"GameName","RunTime","Time","PlayerName","TargetPlayerName","ScoreType","PlayerUnitCoaltion","PlayerUnitCategory","PlayerUnitType","PlayerUnitName","TargetUnitCoalition","TargetUnitCategory","TargetUnitType","TargetUnitName","Times","Score"\n' )
|
||||
end
|
||||
|
||||
self.CSVFile:write( '"GameName","RunTime","Time","PlayerName","TargetPlayerName","ScoreType","PlayerUnitCoaltion","PlayerUnitCategory","PlayerUnitType","PlayerUnitName","TargetUnitCoalition","TargetUnitCategory","TargetUnitType","TargetUnitName","Times","Score"\n' )
|
||||
|
||||
self.RunTime = os.date("%y-%m-%d_%H-%M-%S")
|
||||
else
|
||||
error( "A string containing the CSV file name must be given." )
|
||||
end
|
||||
|
||||
else
|
||||
self:F( "The MissionScripting.lua file has not been changed to allow lfs, io and os modules to be used..." )
|
||||
end
|
||||
@@ -1806,6 +1821,101 @@ function SCORING:OpenCSV( ScoringCSV )
|
||||
end
|
||||
|
||||
|
||||
--- Load player data from file.
|
||||
-- @param #SCORING self
|
||||
-- @param #string filename File name containing player scoring data.
|
||||
function SCORING:LoadCSV(filename)
|
||||
|
||||
--- Function that load data from a file.
|
||||
local function _loadfile(filename)
|
||||
local f=io.open(filename, "rb")
|
||||
if f then
|
||||
local data=f:read("*all")
|
||||
f:close()
|
||||
return data
|
||||
else
|
||||
self:E(self.id..string.format("ERROR: Could not load player results from file %s", tostring(filename)))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Info message.
|
||||
local text=string.format("Loading player scoring from file %s", filename)
|
||||
self:I(text)
|
||||
|
||||
-- Load asset data from file.
|
||||
local data=_loadfile(filename)
|
||||
|
||||
if data then
|
||||
|
||||
-- Split by line break.
|
||||
local results=UTILS.Split(data,"\n")
|
||||
|
||||
-- Remove first header line.
|
||||
table.remove(results, 1)
|
||||
|
||||
-- Init player scores table.
|
||||
self.CSVdata=self.CSVdata or {}
|
||||
|
||||
-- Loop over all lines.
|
||||
for _,_result in pairs(results) do
|
||||
|
||||
-- Parameters are separated by commata.
|
||||
local resultdata=UTILS.Split(_result, ",")
|
||||
|
||||
-- Grade table
|
||||
local result={}
|
||||
|
||||
--'"GameName","RunTime","Time","PlayerName","TargetPlayerName","ScoreType","PlayerUnitCoaltion","PlayerUnitCategory","PlayerUnitType","PlayerUnitName","TargetUnitCoalition",
|
||||
-- "TargetUnitCategory","TargetUnitType","TargetUnitName","Times","Score"\n'
|
||||
|
||||
local PlayerName=tostring(resultdata[4])
|
||||
|
||||
-- Results data.
|
||||
result.GameName=tostring(resultdata[1])
|
||||
result.RunTime=tostring(resultdata[2])
|
||||
result.Time=tonumber(resultdata[3])
|
||||
result.PlayerName=tostring(resultdata[4])
|
||||
result.TargetPlayerName=tostring(resultdata[5])
|
||||
result.ScoreType=tostring(resultdata[6])
|
||||
result.PlayerUnitCoaltion=tostring(resultdata[7])
|
||||
result.PlayerUnitCategory=tostring(resultdata[8])
|
||||
result.PlayerUnitType=tostring(resultdata[9])
|
||||
result.PlayerUnitName=tostring(resultdata[10])
|
||||
result.TargetUnitCoalition=tostring(resultdata[11])
|
||||
result.TargetUnitCategory=tostring(resultdata[12])
|
||||
result.TargetUnitType=tostring(resultdata[13])
|
||||
result.TargetUnitName=tostring(resultdata[14])
|
||||
result.Times=tonumber(resultdata[15])
|
||||
result.Score=tonumber(resultdata[16])
|
||||
|
||||
self:E(result.Score)
|
||||
|
||||
-- Create player array if necessary.
|
||||
self.CSVdata[result.PlayerName]=self.CSVdata[result.PlayerName] or {}
|
||||
|
||||
if self.Players[PlayerName] == nil then -- I believe this is the place where a Player gets a life in a mission when he enters a unit ...
|
||||
self.Players[PlayerName] = {}
|
||||
self.Players[PlayerName].Hit = {}
|
||||
self.Players[PlayerName].Destroy = {}
|
||||
self.Players[PlayerName].Goals = {}
|
||||
self.Players[PlayerName].Mission = {}
|
||||
self.Players[PlayerName].HitPlayers = {}
|
||||
self.Players[PlayerName].Score = 0
|
||||
self.Players[PlayerName].Penalty = 0
|
||||
self.Players[PlayerName].PenaltyCoalition = 0
|
||||
self.Players[PlayerName].PenaltyWarning = 0
|
||||
end
|
||||
|
||||
--self.Players[PlayerName].Score=self.Players[PlayerName].Score+result.Score
|
||||
|
||||
-- Add result to table.
|
||||
table.insert(self.CSVdata[result.PlayerName], result)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Registers a score for a player.
|
||||
-- @param #SCORING self
|
||||
-- @param #string PlayerName The name of the player.
|
||||
@@ -1823,11 +1933,17 @@ end
|
||||
-- @param #string TargetUnitType The type of the target unit.
|
||||
-- @return #SCORING self
|
||||
function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes, ScoreAmount, PlayerUnitName, PlayerUnitCoalition, PlayerUnitCategory, PlayerUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
|
||||
--write statistic information to file
|
||||
local ScoreTime = self:SecondsToClock( timer.getTime() )
|
||||
--local ScoreTime = self:SecondsToClock( timer.getTime() )
|
||||
local ScoreTime = UTILS.SecondsToClock(timer.getAbsTime())
|
||||
|
||||
-- Player name
|
||||
PlayerName = PlayerName:gsub( '"', '_' )
|
||||
|
||||
TargetPlayerName = TargetPlayerName or ""
|
||||
-- Target NAme
|
||||
TargetPlayerName = TargetPlayerName or "n/a"
|
||||
|
||||
TargetPlayerName = TargetPlayerName:gsub( '"', '_' )
|
||||
|
||||
if PlayerUnitName and PlayerUnitName ~= '' then
|
||||
@@ -1847,22 +1963,22 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
|
||||
PlayerUnitType = PlayerUnit:getTypeName()
|
||||
end
|
||||
else
|
||||
PlayerUnitName = ''
|
||||
PlayerUnitCategory = ''
|
||||
PlayerUnitCoalition = ''
|
||||
PlayerUnitType = ''
|
||||
PlayerUnitName = 'n/a'
|
||||
PlayerUnitCategory = 'n/a'
|
||||
PlayerUnitCoalition = 'n/a'
|
||||
PlayerUnitType = 'n/a'
|
||||
end
|
||||
else
|
||||
PlayerUnitName = ''
|
||||
PlayerUnitCategory = ''
|
||||
PlayerUnitCoalition = ''
|
||||
PlayerUnitType = ''
|
||||
PlayerUnitName = 'n/a'
|
||||
PlayerUnitCategory = 'n/a'
|
||||
PlayerUnitCoalition = 'n/a'
|
||||
PlayerUnitType = 'n/a'
|
||||
end
|
||||
|
||||
TargetUnitCoalition = TargetUnitCoalition or ""
|
||||
TargetUnitCategory = TargetUnitCategory or ""
|
||||
TargetUnitType = TargetUnitType or ""
|
||||
TargetUnitName = TargetUnitName or ""
|
||||
TargetUnitCoalition = TargetUnitCoalition or "n/a"
|
||||
TargetUnitCategory = TargetUnitCategory or "n/a"
|
||||
TargetUnitType = TargetUnitType or "n/a"
|
||||
TargetUnitName = TargetUnitName or "n/a"
|
||||
|
||||
if lfs and io and os then
|
||||
self.CSVFile:write(
|
||||
@@ -1881,14 +1997,15 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
|
||||
'"' .. TargetUnitType .. '"' .. ',' ..
|
||||
'"' .. TargetUnitName .. '"' .. ',' ..
|
||||
'' .. ScoreTimes .. '' .. ',' ..
|
||||
'' .. ScoreAmount
|
||||
'' .. ScoreAmount
|
||||
)
|
||||
|
||||
self.CSVFile:write( "\n" )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Close csv file.
|
||||
-- @param #SCORING self
|
||||
function SCORING:CloseCSV()
|
||||
if lfs and io and os then
|
||||
self.CSVFile:close()
|
||||
|
||||
@@ -1733,7 +1733,7 @@ _WAREHOUSEDB = {
|
||||
|
||||
--- Warehouse class version.
|
||||
-- @field #string version
|
||||
WAREHOUSE.version="0.7.0"
|
||||
WAREHOUSE.version="0.7.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO: Warehouse todo list.
|
||||
@@ -1876,6 +1876,7 @@ function WAREHOUSE:New(warehouse, alias)
|
||||
self:AddTransition("Running", "Request", "*") -- Process a request. Only in running mode.
|
||||
self:AddTransition("Attacked", "Request", "*") -- Process a request. Only in running mode.
|
||||
self:AddTransition("*", "Unloaded", "*") -- Cargo has been unloaded from the carrier (unused ==> unnecessary?).
|
||||
self:AddTransition("*", "AssetSpawned", "*") -- Asset has been spawned into the world.
|
||||
self:AddTransition("*", "Arrived", "*") -- Cargo or transport group has arrived.
|
||||
self:AddTransition("*", "Delivered", "*") -- All cargo groups of a request have been delivered to the requesting warehouse.
|
||||
self:AddTransition("Running", "SelfRequest", "*") -- Request to warehouse itself. Requested assets are only spawned but not delivered anywhere.
|
||||
@@ -2301,6 +2302,29 @@ function WAREHOUSE:New(warehouse, alias)
|
||||
-- @param #string To To state.
|
||||
|
||||
|
||||
--- Triggers the FSM event "AssetSpawned" when the warehouse has spawned an asset.
|
||||
-- @function [parent=#WAREHOUSE] AssetSpawned
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param Wrapper.Group#GROUP group the group that was spawned.
|
||||
-- @param #WAREHOUSE.Assetitem asset The asset that was spawned.
|
||||
|
||||
--- Triggers the FSM event "AssetSpawned" with a delay when the warehouse has spawned an asset.
|
||||
-- @function [parent=#WAREHOUSE] __AssetSpawned
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Wrapper.Group#GROUP group the group that was spawned.
|
||||
-- @param #WAREHOUSE.Assetitem asset The asset that was spawned.
|
||||
|
||||
--- On after "AssetSpawned" event user function. Called when the warehouse has spawned an asset.
|
||||
-- @function [parent=#WAREHOUSE] OnAfterAssetSpawned
|
||||
-- @param #WAREHOUSE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Group#GROUP group the group that was spawned.
|
||||
-- @param #WAREHOUSE.Assetitem asset The asset that was spawned.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Save" when the warehouse assets are saved to file on disk.
|
||||
-- @function [parent=#WAREHOUSE] Save
|
||||
-- @param #WAREHOUSE self
|
||||
@@ -4259,6 +4283,9 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
|
||||
|
||||
-- Add transport assets.
|
||||
table.insert(_transportassets,_assetitem)
|
||||
|
||||
-- Asset spawned FSM function.
|
||||
self:__AssetSpawned(1, spawngroup, _assetitem)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5195,6 +5222,9 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
|
||||
if _group then
|
||||
_groupset:AddGroup(_group)
|
||||
table.insert(_assets, _assetitem)
|
||||
|
||||
-- Call FSM function.
|
||||
self:__AssetSpawned(1,_group,_assetitem)
|
||||
else
|
||||
self:E(self.wid.."ERROR: Cargo asset could not be spawned!")
|
||||
end
|
||||
|
||||
@@ -8320,7 +8320,6 @@ end
|
||||
--- Airboss event handler for event that a unit takes off.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
--function AIRBOSS:OnEventPlayerLeaveUnit(EventData)
|
||||
function AIRBOSS:OnEventTakeoff(EventData)
|
||||
self:F3({eventtakeoff=EventData})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user