mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
- Added A2G voice overs to some of the basic events during defender flight. More to come, like multiple languages, and also more voice overs concerning some of the more detailed events, like:
- Damage - Firing - Enemy location - Callsigns - Numbers for distance and degrees.
This commit is contained in:
commit
98e2f2c09b
@ -3496,91 +3496,123 @@ do -- AI_A2G_DISPATCHER
|
|||||||
|
|
||||||
local AI_A2G_PATROL = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
local AI_A2G_PATROL = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||||
|
|
||||||
local Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderGroup, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.EngageFloorAltitude, Patrol.EngageCeilingAltitude, Patrol.Zone, Patrol.PatrolFloorAltitude, Patrol.PatrolCeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType )
|
local AI_A2G_Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderGroup, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.EngageFloorAltitude, Patrol.EngageCeilingAltitude, Patrol.Zone, Patrol.PatrolFloorAltitude, Patrol.PatrolCeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType )
|
||||||
Fsm:SetDispatcher( self )
|
AI_A2G_Fsm:SetDispatcher( self )
|
||||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
AI_A2G_Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
AI_A2G_Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||||
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
AI_A2G_Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
||||||
Fsm:SetDisengageRadius( self.DisengageRadius )
|
AI_A2G_Fsm:SetDisengageRadius( self.DisengageRadius )
|
||||||
Fsm:SetTanker( DefenderSquadron.TankerName or self.DefenderDefault.TankerName )
|
AI_A2G_Fsm:SetTanker( DefenderSquadron.TankerName or self.DefenderDefault.TankerName )
|
||||||
Fsm:Start()
|
AI_A2G_Fsm:Start()
|
||||||
|
|
||||||
self:SetDefenderTask( SquadronName, DefenderGroup, DefenseTaskType, Fsm, nil, DefenderGrouping )
|
self:SetDefenderTask( SquadronName, DefenderGroup, DefenseTaskType, AI_A2G_Fsm, nil, DefenderGrouping )
|
||||||
|
|
||||||
function Fsm:onafterTakeoff( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender Birth", Defender:GetName()})
|
self:F({"Defender Takeoff", DefenderGroup:GetName()})
|
||||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
|
|
||||||
if Squadron then
|
if Squadron then
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " airborne." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " airborne.", "Wheels_up.wav", 3, "A2G/", DefenderGroup )
|
||||||
Fsm:Patrol() -- Engage on the TargetSetUnit
|
AI_A2G_Fsm:Patrol() -- Engage on the TargetSetUnit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Fsm:onafterPatrolRoute( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender PatrolRoute", Defender:GetName()})
|
self:F({"Defender PatrolRoute", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterPatrolRoute( self, Defender, From, Event, To )
|
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
if Squadron then
|
if Squadron then
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " patrolling." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " patrolling.", "Patrolling.wav", 3, "A2G/", DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
Dispatcher:ClearDefenderTaskTarget( Defender )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
function Fsm:onafterRTB( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
self:F({"Defender RTB", Defender:GetName()})
|
self:F({"Engage Route", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterRTB( self, Defender, From, Event, To )
|
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
|
|
||||||
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
|
|
||||||
|
if Squadron then
|
||||||
|
local FirstUnit = AttackSetUnit:GetFirst()
|
||||||
|
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
|
|
||||||
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), "Moving_on_to_ground_target.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AI_A2G_Fsm:OnAfterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
|
self:F({"Engage Route", DefenderGroup:GetName()})
|
||||||
|
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||||
|
|
||||||
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
|
local FirstUnit = AttackSetUnit:GetFirst()
|
||||||
|
if FirstUnit then
|
||||||
|
local Coordinate = FirstUnit:GetCoordinate()
|
||||||
|
|
||||||
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " engaging ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), "Engaging_ground_target.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function AI_A2G_Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||||
|
self:F({"Defender RTB", DefenderGroup:GetName()})
|
||||||
|
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " returning." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " returning.", "Returning_to_base.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
|
||||||
Dispatcher:ClearDefenderTaskTarget( Defender )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2G_DISPATCHER self
|
--- @param #AI_A2G_DISPATCHER self
|
||||||
function Fsm:onafterLostControl( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterLostControl( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender LostControl", Defender:GetName()})
|
self:F({"Defender LostControl", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." )
|
||||||
if Defender:IsAboveRunway() then
|
if DefenderGroup:IsAboveRunway() then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2G_DISPATCHER self
|
--- @param #AI_A2G_DISPATCHER self
|
||||||
function Fsm:onafterHome( Defender, From, Event, To, Action )
|
function AI_A2G_Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
||||||
self:F({"Defender Home", Defender:GetName()})
|
self:F({"Defender Home", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing.", "Landing_at_base.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
|
||||||
if Action and Action == "Destroy" then
|
if Action and Action == "Destroy" then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then
|
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
Dispatcher:ResourcePark( Squadron, Defender )
|
Dispatcher:ResourcePark( Squadron, DefenderGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3605,112 +3637,112 @@ do -- AI_A2G_DISPATCHER
|
|||||||
|
|
||||||
local AI_A2G = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
local AI_A2G = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||||
|
|
||||||
local Fsm = AI_A2G[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_A2G_ENGAGE
|
local AI_A2G_Fsm = AI_A2G[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_A2G_ENGAGE
|
||||||
Fsm:SetDispatcher( self )
|
AI_A2G_Fsm:SetDispatcher( self )
|
||||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
AI_A2G_Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
AI_A2G_Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||||
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
AI_A2G_Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
||||||
Fsm:SetDisengageRadius( self.DisengageRadius )
|
AI_A2G_Fsm:SetDisengageRadius( self.DisengageRadius )
|
||||||
Fsm:Start()
|
AI_A2G_Fsm:Start()
|
||||||
|
|
||||||
self:SetDefenderTask( SquadronName, DefenderGroup, DefenseTaskType, Fsm, AttackerDetection, DefenderGrouping )
|
self:SetDefenderTask( SquadronName, DefenderGroup, DefenseTaskType, AI_A2G_Fsm, AttackerDetection, DefenderGrouping )
|
||||||
|
|
||||||
function Fsm:onafterTakeoff( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender Birth", Defender:GetName()})
|
self:F({"Defender Birth", DefenderGroup:GetName()})
|
||||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
local DefenderTarget = Dispatcher:GetDefenderTaskTarget( Defender )
|
local DefenderTarget = Dispatcher:GetDefenderTaskTarget( DefenderGroup )
|
||||||
|
|
||||||
self:F( { DefenderTarget = DefenderTarget } )
|
self:F( { DefenderTarget = DefenderTarget } )
|
||||||
|
|
||||||
if DefenderTarget then
|
if DefenderTarget then
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " airborne. Engaging!" )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " airborne. Engaging!", "Wheels_up.wav", 3, "A2G/", DefenderGroup )
|
||||||
Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
AI_A2G_Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Fsm:onafterEngageRoute( Defender, From, Event, To, AttackSetUnit )
|
function AI_A2G_Fsm:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
self:F({"Engage Route", Defender:GetName()})
|
self:F({"Engage Route", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterEngageRoute( self, Defender, From, Event, To, AttackSetUnit )
|
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
|
|
||||||
if Squadron then
|
if Squadron then
|
||||||
local FirstUnit = AttackSetUnit:GetFirst()
|
local FirstUnit = AttackSetUnit:GetFirst()
|
||||||
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
|
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " on route to ground target at " .. Coordinate:ToStringA2G( Defender ) )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), "Moving_on_to_ground_target.wav", 3, "A2G/", DefenderGroup )
|
||||||
end
|
end
|
||||||
|
self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
end
|
end
|
||||||
|
|
||||||
function Fsm:OnAfterEngage( Defender, From, Event, To, AttackSetUnit )
|
function AI_A2G_Fsm:OnAfterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
self:F({"Engage Route", Defender:GetName()})
|
self:F({"Engage Route", DefenderGroup:GetName()})
|
||||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
local FirstUnit = AttackSetUnit:GetFirst()
|
local FirstUnit = AttackSetUnit:GetFirst()
|
||||||
if FirstUnit then
|
if FirstUnit then
|
||||||
local Coordinate = FirstUnit:GetCoordinate()
|
local Coordinate = FirstUnit:GetCoordinate()
|
||||||
|
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " engaging ground target at " .. Coordinate:ToStringA2G( Defender ) )
|
Dispatcher:MessageToPlayers( Squadron, "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " engaging ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), "Engaging_ground_target.wav", 3, "A2G/", DefenderGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Fsm:onafterRTB( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender RTB", Defender:GetName()})
|
self:F({"Defender RTB", DefenderGroup:GetName()})
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " returning." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " returning.", "Returning_to_base.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
|
||||||
self:GetParent(self).onafterRTB( self, Defender, From, Event, To )
|
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
Dispatcher:ClearDefenderTaskTarget( Defender )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2G_DISPATCHER self
|
--- @param #AI_A2G_DISPATCHER self
|
||||||
function Fsm:onafterLostControl( Defender, From, Event, To )
|
function AI_A2G_Fsm:onafterLostControl( DefenderGroup, From, Event, To )
|
||||||
self:F({"Defender LostControl", Defender:GetName()})
|
self:F({"Defender LostControl", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
--Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." )
|
--Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." )
|
||||||
|
|
||||||
if Defender:IsAboveRunway() then
|
if DefenderGroup:IsAboveRunway() then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2G_DISPATCHER self
|
--- @param #AI_A2G_DISPATCHER self
|
||||||
function Fsm:onafterHome( Defender, From, Event, To, Action )
|
function AI_A2G_Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
||||||
self:F({"Defender Home", Defender:GetName()})
|
self:F({"Defender Home", DefenderGroup:GetName()})
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = Defender:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing." )
|
Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing.", "Landing_at_base.wav", 3, "A2G/", DefenderGroup )
|
||||||
|
|
||||||
if Action and Action == "Destroy" then
|
if Action and Action == "Destroy" then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then
|
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, DefenderGroup )
|
||||||
Defender:Destroy()
|
DefenderGroup:Destroy()
|
||||||
Dispatcher:ResourcePark( Squadron, Defender )
|
Dispatcher:ResourcePark( Squadron, DefenderGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -3289,6 +3289,9 @@ do
|
|||||||
self:Patrol( SquadronName, PatrolTaskType )
|
self:Patrol( SquadronName, PatrolTaskType )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
-- ## Features:
|
-- ## Features:
|
||||||
-- --
|
-- --
|
||||||
-- * Provides the facilities to trigger escorts when players join flight slots.
|
-- * Provides the facilities to trigger escorts when players join flight slots.
|
||||||
|
-- *
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@ -187,6 +187,7 @@ end
|
|||||||
function DATABASE:AddUnit( DCSUnitName )
|
function DATABASE:AddUnit( DCSUnitName )
|
||||||
|
|
||||||
if not self.UNITS[DCSUnitName] then
|
if not self.UNITS[DCSUnitName] then
|
||||||
|
self:I( { "Add UNIT:", DCSUnitName } )
|
||||||
local UnitRegister = UNIT:Register( DCSUnitName )
|
local UnitRegister = UNIT:Register( DCSUnitName )
|
||||||
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
|
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
|
||||||
|
|
||||||
|
|||||||
@ -797,470 +797,4 @@ function BEACON:_TACANToFrequency(TACANChannel, TACANMode)
|
|||||||
return (A + TACANChannel - B) * 1000000
|
return (A + TACANChannel - B) * 1000000
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Manages radio transmissions.
|
|
||||||
--
|
|
||||||
-- @type RADIOQUEUE
|
|
||||||
-- @field #string ClassName Name of the class "RADIOQUEUE".
|
|
||||||
-- @field #string lid ID for dcs.log.
|
|
||||||
-- @field #number frequency The radio frequency in Hz.
|
|
||||||
-- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM.
|
|
||||||
-- @field Core.Scheduler#SCHEDULER scheduler The scheduler.
|
|
||||||
-- @field #string RQid The radio queue scheduler ID.
|
|
||||||
-- @field #table queue The queue of transmissions.
|
|
||||||
-- @field #number Tlast Time (abs) when the last transmission finished.
|
|
||||||
-- @field Core.Point#COORDINATE sendercoord Coordinate from where transmissions are broadcasted.
|
|
||||||
-- @field #number sendername Name of the sending unit or static.
|
|
||||||
-- @field Wrapper.Positionable#POSITIONABLE positionable The positionable to broadcast the message.
|
|
||||||
-- @field #number power Power of radio station in Watts. Default 100 W.
|
|
||||||
-- @field #table numbers Table of number transmission parameters.
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
RADIOQUEUE = {
|
|
||||||
ClassName = "RADIOQUEUE",
|
|
||||||
lid=nil,
|
|
||||||
frequency=nil,
|
|
||||||
modulation=nil,
|
|
||||||
scheduler=nil,
|
|
||||||
RQid=nil,
|
|
||||||
queue={},
|
|
||||||
Tlast=nil,
|
|
||||||
sendercoord=nil,
|
|
||||||
sendername=nil,
|
|
||||||
positionable=nil,
|
|
||||||
power=100,
|
|
||||||
numbers={},
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Radio queue transmission data.
|
|
||||||
-- @type RADIOQUEUE.Transmission
|
|
||||||
-- @field #string filename Name of the file to be transmitted.
|
|
||||||
-- @field #string path Path in miz file where the file is located.
|
|
||||||
-- @field #number duration Duration in seconds.
|
|
||||||
-- @field #number Tstarted Mission time (abs) in seconds when the transmission started.
|
|
||||||
-- @field #boolean isplaying If true, transmission is currently playing.
|
|
||||||
-- @field #number Tplay Mission time (abs) in seconds when the transmission should be played.
|
|
||||||
|
|
||||||
|
|
||||||
--- Create a new RADIOQUEUE object for a given radio frequency/modulation.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #number frequency The radio frequency in MHz.
|
|
||||||
-- @param #number modulation (Optional) The radio modulation. Default radio.modulation.AM.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:New(frequency, modulation)
|
|
||||||
|
|
||||||
-- Inherit base
|
|
||||||
local self=BASE:Inherit(self, BASE:New()) -- Core.Radio#RADIOQUEUE
|
|
||||||
|
|
||||||
self.lid="RADIOQUEUE | "
|
|
||||||
|
|
||||||
if frequency==nil then
|
|
||||||
self:E(self.lid.."ERROR: No frequency specified as first parameter!")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Frequency in Hz.
|
|
||||||
self.frequency=frequency*1000000
|
|
||||||
|
|
||||||
-- Modulation.
|
|
||||||
self.modulation=modulation or radio.modulation.AM
|
|
||||||
|
|
||||||
-- Scheduler
|
|
||||||
self.scheduler=SCHEDULER:New()
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Start the radio queue.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #number delay (Optional) Delay in seconds, before the radio queue is started. Default 1 sec.
|
|
||||||
-- @param #number dt (Optional) Time step in seconds for checking the queue. Default 0.01 sec.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:Start(delay, dt)
|
|
||||||
|
|
||||||
delay=delay or 1
|
|
||||||
|
|
||||||
dt=dt or 0.01
|
|
||||||
|
|
||||||
self:I(self.lid..string.format("Starting RADIOQUEUE in %.1f seconds with interval dt=%.3f seconds.", delay, dt))
|
|
||||||
|
|
||||||
self.RQid=self.scheduler:Schedule(self, self._CheckRadioQueue, {}, delay, dt)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Stop the radio queue. Stop scheduler and delete queue.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:Stop()
|
|
||||||
self:I(self.lid.."Stopping RADIOQUEUE.")
|
|
||||||
self.scheduler:Stop(self.RQid)
|
|
||||||
self.queue={}
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set coordinate from where the transmission is broadcasted.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param Core.Point#COORDINATE coordinate Coordinate of the sender.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:SetSenderCoordinate(coordinate)
|
|
||||||
self.sendercoord=coordinate
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set name of unit or static from which transmissions are made.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #string name Name of the unit or static used for transmissions.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:SetSenderUnitName(name)
|
|
||||||
self.sendername=name
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set parameters of a digit.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #number digit The digit 0-9.
|
|
||||||
-- @param #string filename The name of the sound file.
|
|
||||||
-- @param #number duration The duration of the sound file in seconds.
|
|
||||||
-- @param #string path The directory within the miz file where the sound is located. Default "l10n/DEFAULT/".
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:SetDigit(digit, filename, duration, path)
|
|
||||||
|
|
||||||
local transmission={} --#RADIOQUEUE.Transmission
|
|
||||||
transmission.filename=filename
|
|
||||||
transmission.duration=duration
|
|
||||||
transmission.path=path or "l10n/DEFAULT/"
|
|
||||||
|
|
||||||
-- Convert digit to string in case it is given as a number.
|
|
||||||
if type(digit)=="number" then
|
|
||||||
digit=tostring(digit)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set transmission.
|
|
||||||
self.numbers[digit]=transmission
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a transmission to the radio queue.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #RADIOQUEUE.Transmission transmission The transmission data table.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:AddTransmission(transmission)
|
|
||||||
self:F({transmission=transmission})
|
|
||||||
|
|
||||||
-- Init.
|
|
||||||
transmission.isplaying=false
|
|
||||||
transmission.Tstarted=nil
|
|
||||||
|
|
||||||
-- Add to queue.
|
|
||||||
table.insert(self.queue, transmission)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a transmission to the radio queue.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #string filename Name of the sound file. Usually an ogg or wav file type.
|
|
||||||
-- @param #number duration Duration in seconds the file lasts.
|
|
||||||
-- @param #number path Directory path inside the miz file where the sound file is located. Default "l10n/DEFAULT/".
|
|
||||||
-- @param #number tstart Start time (abs) seconds. Default now.
|
|
||||||
-- @param #number interval Interval in seconds after the last transmission finished.
|
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
|
||||||
function RADIOQUEUE:NewTransmission(filename, duration, path, tstart, interval)
|
|
||||||
|
|
||||||
-- Sanity checks.
|
|
||||||
if not filename then
|
|
||||||
self:E(self.lid.."ERROR: No filename specified.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
if type(filename)~="string" then
|
|
||||||
self:E(self.lid.."ERROR: Filename specified is NOT a string.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if not duration then
|
|
||||||
self:E(self.lid.."ERROR: No duration of transmission specified.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
if type(duration)~="number" then
|
|
||||||
self:E(self.lid.."ERROR: Duration specified is NOT a number.")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local transmission={} --#RADIOQUEUE.Transmission
|
|
||||||
transmission.filename=filename
|
|
||||||
transmission.duration=duration
|
|
||||||
transmission.path=path or "l10n/DEFAULT/"
|
|
||||||
transmission.Tplay=tstart or timer.getAbsTime()
|
|
||||||
|
|
||||||
-- Add transmission to queue.
|
|
||||||
self:AddTransmission(transmission)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Convert a number (as string) into a radio transmission.
|
|
||||||
-- E.g. for board number or headings.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #string number Number string, e.g. "032" or "183".
|
|
||||||
-- @param #number delay Delay before transmission in seconds.
|
|
||||||
-- @param #number interval Interval between the next call.
|
|
||||||
-- @return #number Duration of the call in seconds.
|
|
||||||
function RADIOQUEUE:Number2Transmission(number, delay, interval)
|
|
||||||
|
|
||||||
--- Split string into characters.
|
|
||||||
local function _split(str)
|
|
||||||
local chars={}
|
|
||||||
for i=1,#str do
|
|
||||||
local c=str:sub(i,i)
|
|
||||||
table.insert(chars, c)
|
|
||||||
end
|
|
||||||
return chars
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Split string into characters.
|
|
||||||
local numbers=_split(number)
|
|
||||||
|
|
||||||
local wait=0
|
|
||||||
for i=1,#numbers do
|
|
||||||
|
|
||||||
-- Current number
|
|
||||||
local n=numbers[i]
|
|
||||||
|
|
||||||
-- Radio call.
|
|
||||||
local transmission=UTILS.DeepCopy(self.numbers[n]) --#RADIOQUEUE.Transmission
|
|
||||||
|
|
||||||
transmission.Tplay=timer.getAbsTime()+(delay or 0)
|
|
||||||
|
|
||||||
if interval and i==1 then
|
|
||||||
transmission.interval=interval
|
|
||||||
end
|
|
||||||
|
|
||||||
self:AddTransmission(transmission)
|
|
||||||
|
|
||||||
-- Add up duration of the number.
|
|
||||||
wait=wait+transmission.duration
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Return the total duration of the call.
|
|
||||||
return wait
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Broadcast radio message.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @param #RADIOQUEUE.Transmission transmission The transmission.
|
|
||||||
function RADIOQUEUE:Broadcast(transmission)
|
|
||||||
|
|
||||||
-- Get unit sending the transmission.
|
|
||||||
local sender=self:_GetRadioSender()
|
|
||||||
|
|
||||||
-- Construct file name.
|
|
||||||
local filename=string.format("%s%s", transmission.path, transmission.filename)
|
|
||||||
|
|
||||||
-- Create subtitle for transmission.
|
|
||||||
--local subtitle=self:_RadioSubtitle(radio, call, loud)
|
|
||||||
|
|
||||||
if sender then
|
|
||||||
|
|
||||||
-- Broadcasting from aircraft. Only players tuned in to the right frequency will see the message.
|
|
||||||
self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName()))
|
|
||||||
|
|
||||||
-- Command to set the Frequency for the transmission.
|
|
||||||
local commandFrequency={
|
|
||||||
id="SetFrequency",
|
|
||||||
params={
|
|
||||||
frequency=self.frequency, -- Frequency in Hz.
|
|
||||||
modulation=self.modulation,
|
|
||||||
}}
|
|
||||||
|
|
||||||
-- Command to tranmit the call.
|
|
||||||
local commandTransmit={
|
|
||||||
id = "TransmitMessage",
|
|
||||||
params = {
|
|
||||||
file=filename,
|
|
||||||
duration=transmission.subduration or 5,
|
|
||||||
subtitle=transmission.subtitle or "",
|
|
||||||
loop=false,
|
|
||||||
}}
|
|
||||||
|
|
||||||
-- Set commend for frequency
|
|
||||||
sender:SetCommand(commandFrequency)
|
|
||||||
|
|
||||||
-- Set command for radio transmission.
|
|
||||||
sender:SetCommand(commandTransmit)
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
-- Broadcasting from carrier. No subtitle possible. Need to send messages to players.
|
|
||||||
self:T(self.lid..string.format("Broadcasting from carrier via trigger.action.radioTransmission()."))
|
|
||||||
|
|
||||||
-- Position from where to transmit.
|
|
||||||
local vec3=nil
|
|
||||||
|
|
||||||
-- Try to get positon from sender unit/static.
|
|
||||||
if self.sendername then
|
|
||||||
local coord=self:_GetRadioSenderCoord()
|
|
||||||
if coord then
|
|
||||||
vec3=coord:GetVec3()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Try to get fixed positon.
|
|
||||||
if self.sendercoord and not vec3 then
|
|
||||||
vec3=self.sendercoord:GetVec3()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Transmit via trigger.
|
|
||||||
if vec3 then
|
|
||||||
trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Check radio queue for transmissions to be broadcasted.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
function RADIOQUEUE:_CheckRadioQueue()
|
|
||||||
|
|
||||||
-- Check if queue is empty.
|
|
||||||
if #self.queue==0 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get current abs time.
|
|
||||||
local time=timer.getAbsTime()
|
|
||||||
|
|
||||||
local playing=false
|
|
||||||
local next=nil --#RADIOQUEUE.Transmission
|
|
||||||
local remove=nil
|
|
||||||
for i,_transmission in ipairs(self.queue) do
|
|
||||||
local transmission=_transmission --#RADIOQUEUE.Transmission
|
|
||||||
|
|
||||||
-- Check if transmission time has passed.
|
|
||||||
if time>=transmission.Tplay then
|
|
||||||
|
|
||||||
-- Check if transmission is currently playing.
|
|
||||||
if transmission.isplaying then
|
|
||||||
|
|
||||||
-- Check if transmission is finished.
|
|
||||||
if time>=transmission.Tstarted+transmission.duration then
|
|
||||||
|
|
||||||
-- Transmission over.
|
|
||||||
transmission.isplaying=false
|
|
||||||
|
|
||||||
-- Remove ith element in queue.
|
|
||||||
remove=i
|
|
||||||
|
|
||||||
-- Store time last transmission finished.
|
|
||||||
self.Tlast=time
|
|
||||||
|
|
||||||
else -- still playing
|
|
||||||
|
|
||||||
-- Transmission is still playing.
|
|
||||||
playing=true
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
else -- not playing yet
|
|
||||||
|
|
||||||
local Tlast=self.Tlast
|
|
||||||
|
|
||||||
if transmission.interval==nil then
|
|
||||||
|
|
||||||
-- Not playing ==> this will be next.
|
|
||||||
if next==nil then
|
|
||||||
next=transmission
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
if Tlast==nil or time-Tlast>=transmission.interval then
|
|
||||||
next=transmission
|
|
||||||
else
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- We got a transmission or one with an interval that is not due yet. No need for anything else.
|
|
||||||
if next or Tlast then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
-- Transmission not due yet.
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Found a new transmission.
|
|
||||||
if next~=nil and not playing then
|
|
||||||
self:Broadcast(next)
|
|
||||||
next.isplaying=true
|
|
||||||
next.Tstarted=time
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Remove completed calls from queue.
|
|
||||||
if remove then
|
|
||||||
table.remove(self.queue, remove)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @return Wrapper.Unit#UNIT Sending aircraft unit or nil if was not setup, is not an aircraft or is not alive.
|
|
||||||
function RADIOQUEUE:_GetRadioSender()
|
|
||||||
|
|
||||||
-- Check if we have a sending aircraft.
|
|
||||||
local sender=nil --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
-- Try the general default.
|
|
||||||
if self.sendername then
|
|
||||||
-- First try to find a unit
|
|
||||||
sender=UNIT:FindByName(self.sendername)
|
|
||||||
|
|
||||||
-- Check that sender is alive and an aircraft.
|
|
||||||
if sender and sender:IsAlive() and sender:IsAir() then
|
|
||||||
return sender
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
|
||||||
-- @param #RADIOQUEUE self
|
|
||||||
-- @return Core.Point#COORDINATE Coordinate of the sender unit.
|
|
||||||
function RADIOQUEUE:_GetRadioSenderCoord()
|
|
||||||
|
|
||||||
local vec3=nil
|
|
||||||
|
|
||||||
-- Try the general default.
|
|
||||||
if self.sendername then
|
|
||||||
|
|
||||||
-- First try to find a unit
|
|
||||||
local sender=UNIT:FindByName(self.sendername)
|
|
||||||
|
|
||||||
-- Check that sender is alive and an aircraft.
|
|
||||||
if sender and sender:IsAlive() then
|
|
||||||
return sender:GetCoodinate()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Now try a static.
|
|
||||||
local sender=STATIC:FindByName(self.sendername)
|
|
||||||
|
|
||||||
-- Check that sender is alive and an aircraft.
|
|
||||||
if sender then
|
|
||||||
return sender:GetCoodinate()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|||||||
483
Moose Development/Moose/Core/RadioQueue.lua
Normal file
483
Moose Development/Moose/Core/RadioQueue.lua
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
--- **Core** - Queues Radio Transmissions.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Features:
|
||||||
|
--
|
||||||
|
-- * Managed Radio Transmissions.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Authors: funkyfranky
|
||||||
|
--
|
||||||
|
-- @module Core.RadioQueue
|
||||||
|
-- @image Core_Radio.JPG
|
||||||
|
|
||||||
|
--- Manages radio transmissions.
|
||||||
|
--
|
||||||
|
-- @type RADIOQUEUE
|
||||||
|
-- @field #string ClassName Name of the class "RADIOQUEUE".
|
||||||
|
-- @field #string lid ID for dcs.log.
|
||||||
|
-- @field #number frequency The radio frequency in Hz.
|
||||||
|
-- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM.
|
||||||
|
-- @field Core.Scheduler#SCHEDULER scheduler The scheduler.
|
||||||
|
-- @field #string RQid The radio queue scheduler ID.
|
||||||
|
-- @field #table queue The queue of transmissions.
|
||||||
|
-- @field #number Tlast Time (abs) when the last transmission finished.
|
||||||
|
-- @field Core.Point#COORDINATE sendercoord Coordinate from where transmissions are broadcasted.
|
||||||
|
-- @field #number sendername Name of the sending unit or static.
|
||||||
|
-- @field Wrapper.Positionable#POSITIONABLE positionable The positionable to broadcast the message.
|
||||||
|
-- @field #number power Power of radio station in Watts. Default 100 W.
|
||||||
|
-- @field #table numbers Table of number transmission parameters.
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
|
RADIOQUEUE = {
|
||||||
|
ClassName = "RADIOQUEUE",
|
||||||
|
lid=nil,
|
||||||
|
frequency=nil,
|
||||||
|
modulation=nil,
|
||||||
|
scheduler=nil,
|
||||||
|
RQid=nil,
|
||||||
|
queue={},
|
||||||
|
Tlast=nil,
|
||||||
|
sendercoord=nil,
|
||||||
|
sendername=nil,
|
||||||
|
positionable=nil,
|
||||||
|
power=100,
|
||||||
|
numbers={},
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Radio queue transmission data.
|
||||||
|
-- @type RADIOQUEUE.Transmission
|
||||||
|
-- @field #string filename Name of the file to be transmitted.
|
||||||
|
-- @field #string path Path in miz file where the file is located.
|
||||||
|
-- @field #number duration Duration in seconds.
|
||||||
|
-- @field #number Tstarted Mission time (abs) in seconds when the transmission started.
|
||||||
|
-- @field #boolean isplaying If true, transmission is currently playing.
|
||||||
|
-- @field #number Tplay Mission time (abs) in seconds when the transmission should be played.
|
||||||
|
|
||||||
|
|
||||||
|
--- Create a new RADIOQUEUE object for a given radio frequency/modulation.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #number frequency The radio frequency in MHz.
|
||||||
|
-- @param #number modulation (Optional) The radio modulation. Default radio.modulation.AM.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:New(frequency, modulation)
|
||||||
|
|
||||||
|
-- Inherit base
|
||||||
|
local self=BASE:Inherit(self, BASE:New()) -- #RADIOQUEUE
|
||||||
|
|
||||||
|
self.lid="RADIOQUEUE | "
|
||||||
|
|
||||||
|
if frequency==nil then
|
||||||
|
self:E(self.lid.."ERROR: No frequency specified as first parameter!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Frequency in Hz.
|
||||||
|
self.frequency=frequency*1000000
|
||||||
|
|
||||||
|
-- Modulation.
|
||||||
|
self.modulation=modulation or radio.modulation.AM
|
||||||
|
|
||||||
|
-- Scheduler
|
||||||
|
self.scheduler=SCHEDULER:New()
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Start the radio queue.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #number delay (Optional) Delay in seconds, before the radio queue is started. Default 1 sec.
|
||||||
|
-- @param #number dt (Optional) Time step in seconds for checking the queue. Default 0.01 sec.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:Start(delay, dt)
|
||||||
|
|
||||||
|
delay=delay or 1
|
||||||
|
|
||||||
|
dt=dt or 0.01
|
||||||
|
|
||||||
|
self:I(self.lid..string.format("Starting RADIOQUEUE in %.1f seconds with interval dt=%.3f seconds.", delay, dt))
|
||||||
|
|
||||||
|
self.RQid=self.scheduler:Schedule(self, self._CheckRadioQueue, {}, delay, dt)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stop the radio queue. Stop scheduler and delete queue.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:Stop()
|
||||||
|
self:I(self.lid.."Stopping RADIOQUEUE.")
|
||||||
|
self.scheduler:Stop(self.RQid)
|
||||||
|
self.queue={}
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set coordinate from where the transmission is broadcasted.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param Core.Point#COORDINATE coordinate Coordinate of the sender.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:SetSenderCoordinate(coordinate)
|
||||||
|
self.sendercoord=coordinate
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set name of unit or static from which transmissions are made.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #string name Name of the unit or static used for transmissions.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:SetSenderUnitName(name)
|
||||||
|
self.sendername=name
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set parameters of a digit.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #number digit The digit 0-9.
|
||||||
|
-- @param #string filename The name of the sound file.
|
||||||
|
-- @param #number duration The duration of the sound file in seconds.
|
||||||
|
-- @param #string path The directory within the miz file where the sound is located. Default "l10n/DEFAULT/".
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:SetDigit(digit, filename, duration, path)
|
||||||
|
|
||||||
|
local transmission={} --#RADIOQUEUE.Transmission
|
||||||
|
transmission.filename=filename
|
||||||
|
transmission.duration=duration
|
||||||
|
transmission.path=path or "l10n/DEFAULT/"
|
||||||
|
|
||||||
|
-- Convert digit to string in case it is given as a number.
|
||||||
|
if type(digit)=="number" then
|
||||||
|
digit=tostring(digit)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set transmission.
|
||||||
|
self.numbers[digit]=transmission
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a transmission to the radio queue.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #RADIOQUEUE.Transmission transmission The transmission data table.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:AddTransmission(transmission)
|
||||||
|
self:F({transmission=transmission})
|
||||||
|
|
||||||
|
-- Init.
|
||||||
|
transmission.isplaying=false
|
||||||
|
transmission.Tstarted=nil
|
||||||
|
|
||||||
|
-- Add to queue.
|
||||||
|
table.insert(self.queue, transmission)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a transmission to the radio queue.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #string filename Name of the sound file. Usually an ogg or wav file type.
|
||||||
|
-- @param #number duration Duration in seconds the file lasts.
|
||||||
|
-- @param #number path Directory path inside the miz file where the sound file is located. Default "l10n/DEFAULT/".
|
||||||
|
-- @param #number tstart Start time (abs) seconds. Default now.
|
||||||
|
-- @param #number interval Interval in seconds after the last transmission finished.
|
||||||
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
|
function RADIOQUEUE:NewTransmission(filename, duration, path, tstart, interval)
|
||||||
|
|
||||||
|
-- Sanity checks.
|
||||||
|
if not filename then
|
||||||
|
self:E(self.lid.."ERROR: No filename specified.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if type(filename)~="string" then
|
||||||
|
self:E(self.lid.."ERROR: Filename specified is NOT a string.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if not duration then
|
||||||
|
self:E(self.lid.."ERROR: No duration of transmission specified.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if type(duration)~="number" then
|
||||||
|
self:E(self.lid.."ERROR: Duration specified is NOT a number.")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local transmission={} --#RADIOQUEUE.Transmission
|
||||||
|
transmission.filename=filename
|
||||||
|
transmission.duration=duration
|
||||||
|
transmission.path=path or "l10n/DEFAULT/"
|
||||||
|
transmission.Tplay=tstart or timer.getAbsTime()
|
||||||
|
|
||||||
|
-- Add transmission to queue.
|
||||||
|
self:AddTransmission(transmission)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Convert a number (as string) into a radio transmission.
|
||||||
|
-- E.g. for board number or headings.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #string number Number string, e.g. "032" or "183".
|
||||||
|
-- @param #number delay Delay before transmission in seconds.
|
||||||
|
-- @param #number interval Interval between the next call.
|
||||||
|
-- @return #number Duration of the call in seconds.
|
||||||
|
function RADIOQUEUE:Number2Transmission(number, delay, interval)
|
||||||
|
|
||||||
|
--- Split string into characters.
|
||||||
|
local function _split(str)
|
||||||
|
local chars={}
|
||||||
|
for i=1,#str do
|
||||||
|
local c=str:sub(i,i)
|
||||||
|
table.insert(chars, c)
|
||||||
|
end
|
||||||
|
return chars
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Split string into characters.
|
||||||
|
local numbers=_split(number)
|
||||||
|
|
||||||
|
local wait=0
|
||||||
|
for i=1,#numbers do
|
||||||
|
|
||||||
|
-- Current number
|
||||||
|
local n=numbers[i]
|
||||||
|
|
||||||
|
-- Radio call.
|
||||||
|
local transmission=UTILS.DeepCopy(self.numbers[n]) --#RADIOQUEUE.Transmission
|
||||||
|
|
||||||
|
transmission.Tplay=timer.getAbsTime()+(delay or 0)
|
||||||
|
|
||||||
|
if interval and i==1 then
|
||||||
|
transmission.interval=interval
|
||||||
|
end
|
||||||
|
|
||||||
|
self:AddTransmission(transmission)
|
||||||
|
|
||||||
|
-- Add up duration of the number.
|
||||||
|
wait=wait+transmission.duration
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Return the total duration of the call.
|
||||||
|
return wait
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Broadcast radio message.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @param #RADIOQUEUE.Transmission transmission The transmission.
|
||||||
|
function RADIOQUEUE:Broadcast(transmission)
|
||||||
|
|
||||||
|
-- Get unit sending the transmission.
|
||||||
|
local sender=self:_GetRadioSender()
|
||||||
|
|
||||||
|
-- Construct file name.
|
||||||
|
local filename=string.format("%s%s", transmission.path, transmission.filename)
|
||||||
|
|
||||||
|
-- Create subtitle for transmission.
|
||||||
|
--local subtitle=self:_RadioSubtitle(radio, call, loud)
|
||||||
|
|
||||||
|
if sender then
|
||||||
|
|
||||||
|
-- Broadcasting from aircraft. Only players tuned in to the right frequency will see the message.
|
||||||
|
self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName()))
|
||||||
|
|
||||||
|
-- Command to set the Frequency for the transmission.
|
||||||
|
local commandFrequency={
|
||||||
|
id="SetFrequency",
|
||||||
|
params={
|
||||||
|
frequency=self.frequency, -- Frequency in Hz.
|
||||||
|
modulation=self.modulation,
|
||||||
|
}}
|
||||||
|
|
||||||
|
-- Command to tranmit the call.
|
||||||
|
local commandTransmit={
|
||||||
|
id = "TransmitMessage",
|
||||||
|
params = {
|
||||||
|
file=filename,
|
||||||
|
duration=transmission.subduration or 5,
|
||||||
|
subtitle=transmission.subtitle or "",
|
||||||
|
loop=false,
|
||||||
|
}}
|
||||||
|
|
||||||
|
-- Set commend for frequency
|
||||||
|
sender:SetCommand(commandFrequency)
|
||||||
|
|
||||||
|
-- Set command for radio transmission.
|
||||||
|
sender:SetCommand(commandTransmit)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Broadcasting from carrier. No subtitle possible. Need to send messages to players.
|
||||||
|
self:T(self.lid..string.format("Broadcasting from carrier via trigger.action.radioTransmission()."))
|
||||||
|
|
||||||
|
-- Position from where to transmit.
|
||||||
|
local vec3=nil
|
||||||
|
|
||||||
|
-- Try to get positon from sender unit/static.
|
||||||
|
if self.sendername then
|
||||||
|
local coord=self:_GetRadioSenderCoord()
|
||||||
|
if coord then
|
||||||
|
vec3=coord:GetVec3()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Try to get fixed positon.
|
||||||
|
if self.sendercoord and not vec3 then
|
||||||
|
vec3=self.sendercoord:GetVec3()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Transmit via trigger.
|
||||||
|
if vec3 then
|
||||||
|
self:E("Sending")
|
||||||
|
self:E( { filename = filename, vec3 = vec3, modulation = self.modulation, frequency = self.frequency, power = self.power } )
|
||||||
|
trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check radio queue for transmissions to be broadcasted.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
function RADIOQUEUE:_CheckRadioQueue()
|
||||||
|
|
||||||
|
-- Check if queue is empty.
|
||||||
|
if #self.queue==0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get current abs time.
|
||||||
|
local time=timer.getAbsTime()
|
||||||
|
|
||||||
|
local playing=false
|
||||||
|
local next=nil --#RADIOQUEUE.Transmission
|
||||||
|
local remove=nil
|
||||||
|
for i,_transmission in ipairs(self.queue) do
|
||||||
|
local transmission=_transmission --#RADIOQUEUE.Transmission
|
||||||
|
|
||||||
|
-- Check if transmission time has passed.
|
||||||
|
if time>=transmission.Tplay then
|
||||||
|
|
||||||
|
-- Check if transmission is currently playing.
|
||||||
|
if transmission.isplaying then
|
||||||
|
|
||||||
|
-- Check if transmission is finished.
|
||||||
|
if time>=transmission.Tstarted+transmission.duration then
|
||||||
|
|
||||||
|
-- Transmission over.
|
||||||
|
transmission.isplaying=false
|
||||||
|
|
||||||
|
-- Remove ith element in queue.
|
||||||
|
remove=i
|
||||||
|
|
||||||
|
-- Store time last transmission finished.
|
||||||
|
self.Tlast=time
|
||||||
|
|
||||||
|
else -- still playing
|
||||||
|
|
||||||
|
-- Transmission is still playing.
|
||||||
|
playing=true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- not playing yet
|
||||||
|
|
||||||
|
local Tlast=self.Tlast
|
||||||
|
|
||||||
|
if transmission.interval==nil then
|
||||||
|
|
||||||
|
-- Not playing ==> this will be next.
|
||||||
|
if next==nil then
|
||||||
|
next=transmission
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if Tlast==nil or time-Tlast>=transmission.interval then
|
||||||
|
next=transmission
|
||||||
|
else
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- We got a transmission or one with an interval that is not due yet. No need for anything else.
|
||||||
|
if next or Tlast then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Transmission not due yet.
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Found a new transmission.
|
||||||
|
if next~=nil and not playing then
|
||||||
|
self:Broadcast(next)
|
||||||
|
next.isplaying=true
|
||||||
|
next.Tstarted=time
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove completed calls from queue.
|
||||||
|
if remove then
|
||||||
|
table.remove(self.queue, remove)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @return Wrapper.Unit#UNIT Sending aircraft unit or nil if was not setup, is not an aircraft or is not alive.
|
||||||
|
function RADIOQUEUE:_GetRadioSender()
|
||||||
|
|
||||||
|
-- Check if we have a sending aircraft.
|
||||||
|
local sender=nil --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Try the general default.
|
||||||
|
if self.sendername then
|
||||||
|
-- First try to find a unit
|
||||||
|
sender=UNIT:FindByName(self.sendername)
|
||||||
|
|
||||||
|
-- Check that sender is alive and an aircraft.
|
||||||
|
if sender and sender:IsAlive() and sender:IsAir() then
|
||||||
|
return sender
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
||||||
|
-- @param #RADIOQUEUE self
|
||||||
|
-- @return Core.Point#COORDINATE Coordinate of the sender unit.
|
||||||
|
function RADIOQUEUE:_GetRadioSenderCoord()
|
||||||
|
|
||||||
|
local vec3=nil
|
||||||
|
|
||||||
|
-- Try the general default.
|
||||||
|
if self.sendername then
|
||||||
|
|
||||||
|
-- First try to find a unit
|
||||||
|
local sender=UNIT:FindByName(self.sendername)
|
||||||
|
|
||||||
|
-- Check that sender is alive and an aircraft.
|
||||||
|
if sender and sender:IsAlive() then
|
||||||
|
return sender:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Now try a static.
|
||||||
|
local sender=STATIC:FindByName(self.sendername)
|
||||||
|
|
||||||
|
-- Check that sender is alive and an aircraft.
|
||||||
|
if sender then
|
||||||
|
return sender:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
@ -194,6 +194,19 @@
|
|||||||
-- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds.
|
-- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds.
|
||||||
-- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds.
|
-- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds.
|
||||||
--
|
--
|
||||||
|
-- ## 3.5) **Era** of the battle
|
||||||
|
--
|
||||||
|
-- The threat level metric is scaled according the era of the battle. A target that is AAA, will pose a much greather threat in WWII than on modern warfare.
|
||||||
|
-- Therefore, there are 4 era that are defined within the settings:
|
||||||
|
--
|
||||||
|
-- - **WWII** era: Use for warfare with equipment during the world war II time.
|
||||||
|
-- - **Korea** era: Use for warfare with equipment during the Korea war time.
|
||||||
|
-- - **Cold War** era: Use for warfare with equipment during the cold war time.
|
||||||
|
-- - **Modern** era: Use for warfare with modern equipment in the 2000s.
|
||||||
|
--
|
||||||
|
-- There are different API defined that you can use with the _SETTINGS object to configure your mission script to work in one of the 4 era:
|
||||||
|
-- @{#SETTINGS.SetEraWWII}(), @{#SETTINGS.SetEraKorea}(), @{#SETTINGS.SetEraCold}(), @{#SETTINGS.SetEraModern}()
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @field #SETTINGS
|
-- @field #SETTINGS
|
||||||
@ -202,6 +215,19 @@ SETTINGS = {
|
|||||||
ShowPlayerMenu = true,
|
ShowPlayerMenu = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SETTINGS.__Enum = {}
|
||||||
|
|
||||||
|
--- @type SETTINGS.__Enum.Era
|
||||||
|
-- @field #number WWII
|
||||||
|
-- @field #number Korea
|
||||||
|
-- @field #number Cold
|
||||||
|
-- @field #number Modern
|
||||||
|
SETTINGS.__Enum.Era = {
|
||||||
|
WWII = 1,
|
||||||
|
Korea = 2,
|
||||||
|
Cold = 3,
|
||||||
|
Modern = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
do -- SETTINGS
|
do -- SETTINGS
|
||||||
@ -223,6 +249,7 @@ do -- SETTINGS
|
|||||||
self:SetMessageTime( MESSAGE.Type.Information, 30 )
|
self:SetMessageTime( MESSAGE.Type.Information, 30 )
|
||||||
self:SetMessageTime( MESSAGE.Type.Overview, 60 )
|
self:SetMessageTime( MESSAGE.Type.Overview, 60 )
|
||||||
self:SetMessageTime( MESSAGE.Type.Update, 15 )
|
self:SetMessageTime( MESSAGE.Type.Update, 15 )
|
||||||
|
self:SetEraModern()
|
||||||
return self
|
return self
|
||||||
else
|
else
|
||||||
local Settings = _DATABASE:GetPlayerSettings( PlayerName )
|
local Settings = _DATABASE:GetPlayerSettings( PlayerName )
|
||||||
@ -839,6 +866,47 @@ do -- SETTINGS
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Configures the era of the mission to be WWII.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @return #SETTINGS self
|
||||||
|
function SETTINGS:SetEraWWII()
|
||||||
|
|
||||||
|
self.Era = SETTINGS.__Enum.Era.WWII
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Configures the era of the mission to be Korea.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @return #SETTINGS self
|
||||||
|
function SETTINGS:SetEraKorea()
|
||||||
|
|
||||||
|
self.Era = SETTINGS.__Enum.Era.Korea
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Configures the era of the mission to be Cold war.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @return #SETTINGS self
|
||||||
|
function SETTINGS:SetEraCold()
|
||||||
|
|
||||||
|
self.Era = SETTINGS.__Enum.Era.Cold
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Configures the era of the mission to be Modern war.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @return #SETTINGS self
|
||||||
|
function SETTINGS:SetEraModern()
|
||||||
|
|
||||||
|
self.Era = SETTINGS.__Enum.Era.Modern
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@ __Moose.Include( 'Scripts/Moose/Core/Velocity.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Core/Message.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Message.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Fsm.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Fsm.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Radio.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Radio.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Core/RadioQueue.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
||||||
|
|||||||
@ -254,11 +254,45 @@ do -- DETECTION MANAGER
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the command center to communicate actions to the players.
|
||||||
|
-- @param #DETECTION_MANAGER self
|
||||||
|
-- @return Tasking.CommandCenter#COMMANDCENTER The command center.
|
||||||
|
function DETECTION_MANAGER:GetCommandCenter()
|
||||||
|
|
||||||
|
return self.CC
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the frequency of communication and the mode of communication for voice overs.
|
||||||
|
-- @param #DETECTION_MANAGER self
|
||||||
|
-- @param #number RadioFrequency The frequency of communication.
|
||||||
|
-- @param #number RadioModulation The modulation of communication.
|
||||||
|
-- @param #number RadioPower The power in Watts of communication.
|
||||||
|
function DETECTION_MANAGER:SetRadioFrequency( RadioFrequency, RadioModulation, RadioPower )
|
||||||
|
|
||||||
|
self.RadioFrequency = RadioFrequency
|
||||||
|
self.RadioModulation = RadioModulation or radio.modulation.AM
|
||||||
|
self.RadioPower = RadioPower or 100
|
||||||
|
|
||||||
|
if self.RadioQueue then
|
||||||
|
self.RadioQueue:Stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.RadioQueue = nil
|
||||||
|
|
||||||
|
self.RadioQueue = RADIOQUEUE:New( self.RadioFrequency, self.RadioModulation )
|
||||||
|
self.RadioQueue.power = self.RadioPower
|
||||||
|
self.RadioQueue:Start( 0.5 )
|
||||||
|
end
|
||||||
|
|
||||||
--- Send an information message to the players reporting to the command center.
|
--- Send an information message to the players reporting to the command center.
|
||||||
-- @param #DETECTION_MANAGER self
|
-- @param #DETECTION_MANAGER self
|
||||||
-- @param #string Message The message to be sent.
|
-- @param #string Message The message to be sent.
|
||||||
|
-- @param #string SoundFile The name of the sound file .wav or .ogg.
|
||||||
|
-- @param #number SoundDuration The duration of the sound.
|
||||||
|
-- @param #string SoundPath The path pointing to the folder in the mission file.
|
||||||
|
-- @param Wrapper.Group#GROUP DefenderGroup The defender group sending the message.
|
||||||
-- @return #DETECTION_MANGER self
|
-- @return #DETECTION_MANGER self
|
||||||
function DETECTION_MANAGER:MessageToPlayers( Message )
|
function DETECTION_MANAGER:MessageToPlayers( Message, SoundFile, SoundDuration, SoundPath, DefenderGroup )
|
||||||
|
|
||||||
self:F( { Message = Message } )
|
self:F( { Message = Message } )
|
||||||
|
|
||||||
@ -269,6 +303,17 @@ do -- DETECTION MANAGER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Here we handle the transmission of the voice over.
|
||||||
|
-- If for a certain reason the Defender does not exist, we use the coordinate of the airbase to send the message from.
|
||||||
|
if SoundFile then
|
||||||
|
local RadioQueue = self.RadioQueue -- Core.RadioQueue#RADIOQUEUE
|
||||||
|
local DefenderUnit = DefenderGroup:GetUnit(1)
|
||||||
|
if DefenderUnit and DefenderUnit:IsAlive() then
|
||||||
|
RadioQueue:SetSenderUnitName( DefenderUnit:GetName() )
|
||||||
|
end
|
||||||
|
RadioQueue:NewTransmission( SoundFile, SoundDuration, SoundPath )
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -696,7 +696,9 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Returns the Unit's A2G threat level on a scale from 1 to 10 ...
|
--- Returns the Unit's A2G threat level on a scale from 1 to 10 ...
|
||||||
-- The following threat levels are foreseen:
|
-- Depending on the era and the type of unit, the following threat levels are foreseen:
|
||||||
|
--
|
||||||
|
-- **Modern**:
|
||||||
--
|
--
|
||||||
-- * Threat level 0: Unit is unarmed.
|
-- * Threat level 0: Unit is unarmed.
|
||||||
-- * Threat level 1: Unit is infantry.
|
-- * Threat level 1: Unit is infantry.
|
||||||
@ -709,6 +711,42 @@ end
|
|||||||
-- * Threat level 8: Unit is a Short Range SAM, radar guided.
|
-- * Threat level 8: Unit is a Short Range SAM, radar guided.
|
||||||
-- * Threat level 9: Unit is a Medium Range SAM, radar guided.
|
-- * Threat level 9: Unit is a Medium Range SAM, radar guided.
|
||||||
-- * Threat level 10: Unit is a Long Range SAM, radar guided.
|
-- * Threat level 10: Unit is a Long Range SAM, radar guided.
|
||||||
|
--
|
||||||
|
-- **Cold**:
|
||||||
|
--
|
||||||
|
-- * Threat level 0: Unit is unarmed.
|
||||||
|
-- * Threat level 1: Unit is infantry.
|
||||||
|
-- * Threat level 2: Unit is an infantry vehicle.
|
||||||
|
-- * Threat level 3: Unit is ground artillery.
|
||||||
|
-- * Threat level 4: Unit is a tank.
|
||||||
|
-- * Threat level 5: Unit is a modern tank or ifv with ATGM.
|
||||||
|
-- * Threat level 6: Unit is a AAA.
|
||||||
|
-- * Threat level 7: Unit is a SAM or manpad, IR guided.
|
||||||
|
-- * Threat level 8: Unit is a Short Range SAM, radar guided.
|
||||||
|
-- * Threat level 10: Unit is a Medium Range SAM, radar guided.
|
||||||
|
--
|
||||||
|
-- **Korea**:
|
||||||
|
--
|
||||||
|
-- * Threat level 0: Unit is unarmed.
|
||||||
|
-- * Threat level 1: Unit is infantry.
|
||||||
|
-- * Threat level 2: Unit is an infantry vehicle.
|
||||||
|
-- * Threat level 3: Unit is ground artillery.
|
||||||
|
-- * Threat level 5: Unit is a tank.
|
||||||
|
-- * Threat level 6: Unit is a AAA.
|
||||||
|
-- * Threat level 7: Unit is a SAM or manpad, IR guided.
|
||||||
|
-- * Threat level 10: Unit is a Short Range SAM, radar guided.
|
||||||
|
--
|
||||||
|
-- **WWII**:
|
||||||
|
--
|
||||||
|
-- * Threat level 0: Unit is unarmed.
|
||||||
|
-- * Threat level 1: Unit is infantry.
|
||||||
|
-- * Threat level 2: Unit is an infantry vehicle.
|
||||||
|
-- * Threat level 3: Unit is ground artillery.
|
||||||
|
-- * Threat level 5: Unit is a tank.
|
||||||
|
-- * Threat level 7: Unit is FLAK.
|
||||||
|
-- * Threat level 10: Unit is AAA.
|
||||||
|
--
|
||||||
|
--
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
function UNIT:GetThreatLevel()
|
function UNIT:GetThreatLevel()
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user