mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'FF/Ops' into FF/OpsDev
This commit is contained in:
@@ -1344,8 +1344,16 @@ function DATABASE:_RegisterAirbase(airbase)
|
|||||||
-- Unique ID.
|
-- Unique ID.
|
||||||
local airbaseUID=airbase:GetID(true)
|
local airbaseUID=airbase:GetID(true)
|
||||||
|
|
||||||
|
local typename = airbase:GetTypeName()
|
||||||
|
|
||||||
|
local category = airbase.category
|
||||||
|
|
||||||
|
if category == Airbase.Category.SHIP and typename == "FARP_SINGLE_01" then
|
||||||
|
category = Airbase.Category.HELIPAD
|
||||||
|
end
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
local text=string.format("Register %s: %s (UID=%d), Runways=%d, Parking=%d [", AIRBASE.CategoryName[airbase.category], tostring(DCSAirbaseName), airbaseUID, #airbase.runways, airbase.NparkingTotal)
|
local text=string.format("Register %s: %s (UID=%d), Runways=%d, Parking=%d [", AIRBASE.CategoryName[category], tostring(DCSAirbaseName), airbaseUID, #airbase.runways, airbase.NparkingTotal)
|
||||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then
|
if airbase.NparkingTerminal and airbase.NparkingTerminal[terminalType] then
|
||||||
text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType])
|
text=text..string.format("%d=%d ", terminalType, airbase.NparkingTerminal[terminalType])
|
||||||
|
|||||||
@@ -459,14 +459,14 @@ end
|
|||||||
|
|
||||||
_MESSAGESRS = {}
|
_MESSAGESRS = {}
|
||||||
|
|
||||||
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions.
|
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #string PathToSRS Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone".
|
-- @param #string PathToSRS (optional) Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" or your configuration file setting.
|
||||||
-- @param #number Port Port number of SRS, defaults to 5002.
|
-- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting.
|
||||||
-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google.
|
-- @param #string PathToCredentials (optional) Path to credentials file for Google.
|
||||||
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
||||||
-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations.
|
-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations.
|
||||||
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "female".
|
-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "female" or your configuration file setting.
|
||||||
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB"
|
-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB" or your configuration file setting.
|
||||||
-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server!
|
-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server!
|
||||||
-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL.
|
-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL.
|
||||||
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
||||||
@@ -480,42 +480,51 @@ _MESSAGESRS = {}
|
|||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||||
--
|
--
|
||||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
||||||
_MESSAGESRS.MSRS = MSRS:New(PathToSRS,Frequency or 243,Modulation or radio.modulation.AM,Volume)
|
|
||||||
|
|
||||||
_MESSAGESRS.frequency = Frequency
|
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
_MESSAGESRS.modulation = Modulation or radio.modulation.AM
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetCoalition(Coalition or coalition.side.NEUTRAL)
|
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
|
||||||
_MESSAGESRS.coalition = Coalition or coalition.side.NEUTRAL
|
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
|
||||||
|
|
||||||
|
_MESSAGESRS.MSRS = MSRS:New(_MESSAGESRS.PathToSRS,_MESSAGESRS.frequency, _MESSAGESRS.modulation)
|
||||||
|
|
||||||
|
_MESSAGESRS.coalition = Coalition or MSRS.coalition or coalition.side.NEUTRAL
|
||||||
|
_MESSAGESRS.MSRS:SetCoalition(_MESSAGESRS.coalition)
|
||||||
|
|
||||||
_MESSAGESRS.coordinate = Coordinate
|
_MESSAGESRS.coordinate = Coordinate
|
||||||
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
|
||||||
|
|
||||||
|
if Coordinate then
|
||||||
|
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
||||||
|
end
|
||||||
|
|
||||||
|
_MESSAGESRS.Culture = Culture or MSRS.culture or "en-GB"
|
||||||
_MESSAGESRS.MSRS:SetCulture(Culture)
|
_MESSAGESRS.MSRS:SetCulture(Culture)
|
||||||
_MESSAGESRS.Culture = Culture or "en-GB"
|
|
||||||
|
|
||||||
|
_MESSAGESRS.Gender = Gender or MSRS.gender or "female"
|
||||||
_MESSAGESRS.MSRS:SetGender(Gender)
|
_MESSAGESRS.MSRS:SetGender(Gender)
|
||||||
_MESSAGESRS.Gender = Gender or "female"
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
if PathToCredentials then
|
||||||
|
_MESSAGESRS.MSRS:SetProviderOptionsGoogle(PathToCredentials)
|
||||||
|
_MESSAGESRS.MSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
|
||||||
|
_MESSAGESRS.label = Label or MSRS.Label or "MESSAGE"
|
||||||
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
||||||
_MESSAGESRS.label = Label or "MESSAGE"
|
|
||||||
|
|
||||||
|
_MESSAGESRS.port = Port or MSRS.port or 5002
|
||||||
_MESSAGESRS.MSRS:SetPort(Port or 5002)
|
_MESSAGESRS.MSRS:SetPort(Port or 5002)
|
||||||
_MESSAGESRS.port = Port or 5002
|
|
||||||
|
|
||||||
_MESSAGESRS.volume = Volume or 1
|
_MESSAGESRS.volume = Volume or MSRS.volume or 1
|
||||||
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
|
_MESSAGESRS.MSRS:SetVolume(_MESSAGESRS.volume)
|
||||||
|
|
||||||
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
||||||
|
|
||||||
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
|
_MESSAGESRS.voice = Voice or MSRS.voice --or MSRS.Voices.Microsoft.Hedda
|
||||||
|
|
||||||
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
|
_MESSAGESRS.SRSQ = MSRSQUEUE:New(_MESSAGESRS.label)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a message via SRS.
|
--- Sends a message via SRS. `ToSRS()` will try to use as many attributes configured with @{Core.Message#MESSAGE.SetMSRS}() and @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||||
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting.
|
||||||
@@ -543,7 +552,7 @@ function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volum
|
|||||||
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
|
_MESSAGESRS.MSRS:SetCoordinate(coordinate)
|
||||||
end
|
end
|
||||||
local category = string.gsub(self.MessageCategory,":","")
|
local category = string.gsub(self.MessageCategory,":","")
|
||||||
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
|
_MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,0.5,1,nil,nil,nil,frequency or _MESSAGESRS.frequency,modulation or _MESSAGESRS.modulation, gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,nil,volume or _MESSAGESRS.volume,category,coordinate or _MESSAGESRS.coordinate)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1578,7 +1578,7 @@ do
|
|||||||
function SET_GROUP:AddInDatabase( Event )
|
function SET_GROUP:AddInDatabase( Event )
|
||||||
self:F3( { Event } )
|
self:F3( { Event } )
|
||||||
|
|
||||||
if Event.IniObjectCategory == 1 then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
if not self.Database[Event.IniDCSGroupName] then
|
if not self.Database[Event.IniDCSGroupName] then
|
||||||
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
||||||
self:T3( self.Database[Event.IniDCSGroupName] )
|
self:T3( self.Database[Event.IniDCSGroupName] )
|
||||||
@@ -2641,7 +2641,7 @@ do -- SET_UNIT
|
|||||||
function SET_UNIT:AddInDatabase( Event )
|
function SET_UNIT:AddInDatabase( Event )
|
||||||
self:F3( { Event } )
|
self:F3( { Event } )
|
||||||
|
|
||||||
if Event.IniObjectCategory == 1 then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
if not self.Database[Event.IniDCSUnitName] then
|
if not self.Database[Event.IniDCSUnitName] then
|
||||||
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
|
self.Database[Event.IniDCSUnitName] = UNIT:Register( Event.IniDCSUnitName )
|
||||||
self:T3( self.Database[Event.IniDCSUnitName] )
|
self:T3( self.Database[Event.IniDCSUnitName] )
|
||||||
@@ -4518,7 +4518,7 @@ do -- SET_CLIENT
|
|||||||
function SET_CLIENT:_EventPlayerEnterUnit(Event)
|
function SET_CLIENT:_EventPlayerEnterUnit(Event)
|
||||||
self:I( "_EventPlayerEnterUnit" )
|
self:I( "_EventPlayerEnterUnit" )
|
||||||
if Event.IniDCSUnit then
|
if Event.IniDCSUnit then
|
||||||
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
|
if Event.IniObjectCategory == Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround() then
|
||||||
-- CA Slot entered
|
-- CA Slot entered
|
||||||
local ObjectName, Object = self:AddInDatabase( Event )
|
local ObjectName, Object = self:AddInDatabase( Event )
|
||||||
self:I( ObjectName, UTILS.PrintTableToLog(Object) )
|
self:I( ObjectName, UTILS.PrintTableToLog(Object) )
|
||||||
@@ -4537,7 +4537,7 @@ do -- SET_CLIENT
|
|||||||
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
|
function SET_CLIENT:_EventPlayerLeaveUnit(Event)
|
||||||
self:I( "_EventPlayerLeaveUnit" )
|
self:I( "_EventPlayerLeaveUnit" )
|
||||||
if Event.IniDCSUnit then
|
if Event.IniDCSUnit then
|
||||||
if Event.IniObjectCategory == 1 and Event.IniGroup and Event.IniGroup:IsGround() then
|
if Event.IniObjectCategory == Object.Category.UNIT and Event.IniGroup and Event.IniGroup:IsGround() then
|
||||||
-- CA Slot left
|
-- CA Slot left
|
||||||
local ObjectName, Object = self:FindInDatabase( Event )
|
local ObjectName, Object = self:FindInDatabase( Event )
|
||||||
if ObjectName then
|
if ObjectName then
|
||||||
@@ -7837,6 +7837,29 @@ do -- SET_OPSGROUP
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles the OnBirth event for the Set.
|
||||||
|
-- @param #SET_OPSGROUP self
|
||||||
|
-- @param Core.Event#EVENTDATA Event Event data.
|
||||||
|
function SET_OPSGROUP:_EventOnBirth( Event )
|
||||||
|
self:F3( { Event } )
|
||||||
|
|
||||||
|
if Event.IniDCSUnit and Event.IniDCSGroup then
|
||||||
|
local DCSgroup=Event.IniDCSGroup --DCS#Group
|
||||||
|
|
||||||
|
if DCSgroup:getInitialSize() == DCSgroup:getSize() then -- This seems to be not a good check as even for the first birth event, getSize returns the total number of units in the group.
|
||||||
|
|
||||||
|
local groupname, group = self:AddInDatabase( Event )
|
||||||
|
|
||||||
|
if group and group:CountAliveUnits()==DCSgroup:getInitialSize() then
|
||||||
|
if group and self:IsIncludeObject( group ) then
|
||||||
|
self:Add( groupname, group )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Handles the OnDead or OnCrash event for alive groups set.
|
--- Handles the OnDead or OnCrash event for alive groups set.
|
||||||
-- Note: The GROUP object in the SET_OPSGROUP collection will only be removed if the last unit is destroyed of the GROUP.
|
-- Note: The GROUP object in the SET_OPSGROUP collection will only be removed if the last unit is destroyed of the GROUP.
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
@@ -7857,12 +7880,12 @@ do -- SET_OPSGROUP
|
|||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA Event Event data.
|
||||||
-- @return #string The name of the GROUP
|
-- @return #string The name of the GROUP.
|
||||||
-- @return #table The GROUP
|
-- @return Wrapper.Group#GROUP The GROUP object.
|
||||||
function SET_OPSGROUP:AddInDatabase( Event )
|
function SET_OPSGROUP:AddInDatabase( Event )
|
||||||
|
|
||||||
if Event.IniObjectCategory==1 then
|
if Event.IniObjectCategory==Object.Category.UNIT then
|
||||||
|
|
||||||
if not self.Database[Event.IniDCSGroupName] then
|
if not self.Database[Event.IniDCSGroupName] then
|
||||||
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
self.Database[Event.IniDCSGroupName] = GROUP:Register( Event.IniDCSGroupName )
|
||||||
@@ -7877,8 +7900,8 @@ do -- SET_OPSGROUP
|
|||||||
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @param Core.Event#EVENTDATA Event Event data table.
|
-- @param Core.Event#EVENTDATA Event Event data table.
|
||||||
-- @return #string The name of the GROUP
|
-- @return #string The name of the GROUP.
|
||||||
-- @return #table The GROUP
|
-- @return Wrapper.Group#GROUP The GROUP object.
|
||||||
function SET_OPSGROUP:FindInDatabase(Event)
|
function SET_OPSGROUP:FindInDatabase(Event)
|
||||||
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
return Event.IniDCSGroupName, self.Database[Event.IniDCSGroupName]
|
||||||
end
|
end
|
||||||
@@ -8197,7 +8220,7 @@ do -- SET_SCENERY
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Get a table of alive objects.
|
--- Get a table of alive objects.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_SCENERY self
|
||||||
-- @return #table Table of alive objects
|
-- @return #table Table of alive objects
|
||||||
-- @return Core.Set#SET_SCENERY SET of alive objects
|
-- @return Core.Set#SET_SCENERY SET of alive objects
|
||||||
function SET_SCENERY:GetAliveSet()
|
function SET_SCENERY:GetAliveSet()
|
||||||
|
|||||||
@@ -1458,6 +1458,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
else
|
else
|
||||||
|
|
||||||
local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate
|
local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate
|
||||||
|
local SpawnZone = self.SpawnGroups[self.SpawnIndex].SpawnZone
|
||||||
self:T( SpawnTemplate.name )
|
self:T( SpawnTemplate.name )
|
||||||
|
|
||||||
if SpawnTemplate then
|
if SpawnTemplate then
|
||||||
@@ -1483,6 +1484,23 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
if self.SpawnRandomizeUnits then
|
if self.SpawnRandomizeUnits then
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
local RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
||||||
|
if (SpawnZone) then
|
||||||
|
local inZone = SpawnZone:IsVec2InZone(RandomVec2)
|
||||||
|
local numTries = 1
|
||||||
|
while (not inZone) and (numTries < 20) do
|
||||||
|
if not inZone then
|
||||||
|
RandomVec2 = PointVec3:GetRandomVec2InRadius( self.SpawnOuterRadius, self.SpawnInnerRadius )
|
||||||
|
numTries = numTries + 1
|
||||||
|
inZone = SpawnZone:IsVec2InZone(RandomVec2)
|
||||||
|
self:I("Retrying " .. numTries .. "spawn " .. SpawnTemplate.name .. " in Zone " .. SpawnZone:GetName() .. "!")
|
||||||
|
self:I(SpawnZone)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if (not inZone) then
|
||||||
|
self:I("Could not place unit within zone and within radius!")
|
||||||
|
RandomVec2 = SpawnZone:GetRandomVec2()
|
||||||
|
end
|
||||||
|
end
|
||||||
SpawnTemplate.units[UnitID].x = RandomVec2.x
|
SpawnTemplate.units[UnitID].x = RandomVec2.x
|
||||||
SpawnTemplate.units[UnitID].y = RandomVec2.y
|
SpawnTemplate.units[UnitID].y = RandomVec2.y
|
||||||
self:T( 'SpawnTemplate.units[' .. UnitID .. '].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. SpawnTemplate.units[UnitID].y )
|
self:T( 'SpawnTemplate.units[' .. UnitID .. '].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units[' .. UnitID .. '].y = ' .. SpawnTemplate.units[UnitID].y )
|
||||||
@@ -1534,12 +1552,14 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
|
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
|
||||||
if UnitID > 1 then -- don't rotate position of unit #1
|
if not self.SpawnRandomizeUnits then
|
||||||
local unitXOff = SpawnTemplate.units[UnitID].x - pivotX -- rotate position offset around unit #1
|
if UnitID > 1 then -- don't rotate position of unit #1
|
||||||
local unitYOff = SpawnTemplate.units[UnitID].y - pivotY
|
local unitXOff = SpawnTemplate.units[UnitID].x - pivotX -- rotate position offset around unit #1
|
||||||
|
local unitYOff = SpawnTemplate.units[UnitID].y - pivotY
|
||||||
|
|
||||||
SpawnTemplate.units[UnitID].x = pivotX + (unitXOff * cosHeading) - (unitYOff * sinHeading)
|
SpawnTemplate.units[UnitID].x = pivotX + (unitXOff * cosHeading) - (unitYOff * sinHeading)
|
||||||
SpawnTemplate.units[UnitID].y = pivotY + (unitYOff * cosHeading) + (unitXOff * sinHeading)
|
SpawnTemplate.units[UnitID].y = pivotY + (unitYOff * cosHeading) + (unitXOff * sinHeading)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- adjust heading of all units, including unit #1
|
-- adjust heading of all units, including unit #1
|
||||||
@@ -3591,6 +3611,7 @@ function SPAWN:_RandomizeZones( SpawnIndex )
|
|||||||
self:T( { SpawnVec2 = SpawnVec2 } )
|
self:T( { SpawnVec2 = SpawnVec2 } )
|
||||||
|
|
||||||
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
|
local SpawnTemplate = self.SpawnGroups[SpawnIndex].SpawnTemplate
|
||||||
|
self.SpawnGroups[SpawnIndex].SpawnZone = SpawnZone
|
||||||
|
|
||||||
self:T( { Route = SpawnTemplate.route } )
|
self:T( { Route = SpawnTemplate.route } )
|
||||||
|
|
||||||
|
|||||||
@@ -574,7 +574,7 @@ function AICSAR:SetSRSTTSRadio(OnOff,Path,Frequency,Modulation,Port,Voice,Cultur
|
|||||||
self.SRSModulation = Modulation or radio.modulation.AM
|
self.SRSModulation = Modulation or radio.modulation.AM
|
||||||
self.SRSPort = Port or 5002
|
self.SRSPort = Port or 5002
|
||||||
if OnOff then
|
if OnOff then
|
||||||
self.SRS = MSRS:New(Path,Frequency,Modulation,1)
|
self.SRS = MSRS:New(Path,Frequency,Modulation)
|
||||||
self.SRS:SetPort(self.SRSPort)
|
self.SRS:SetPort(self.SRSPort)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
self.SRS:SetLabel("ACSR")
|
self.SRS:SetLabel("ACSR")
|
||||||
@@ -600,7 +600,7 @@ end
|
|||||||
function AICSAR:SetPilotTTSVoice(Voice,Culture,Gender)
|
function AICSAR:SetPilotTTSVoice(Voice,Culture,Gender)
|
||||||
self:T(self.lid .. "SetPilotTTSVoice")
|
self:T(self.lid .. "SetPilotTTSVoice")
|
||||||
self.SRSPilotVoice = true
|
self.SRSPilotVoice = true
|
||||||
self.SRSPilot = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation,1)
|
self.SRSPilot = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation)
|
||||||
self.SRSPilot:SetCoalition(self.coalition)
|
self.SRSPilot:SetCoalition(self.coalition)
|
||||||
self.SRSPilot:SetVoice(Voice)
|
self.SRSPilot:SetVoice(Voice)
|
||||||
self.SRSPilot:SetCulture(Culture or "en-US")
|
self.SRSPilot:SetCulture(Culture or "en-US")
|
||||||
@@ -624,7 +624,7 @@ end
|
|||||||
function AICSAR:SetOperatorTTSVoice(Voice,Culture,Gender)
|
function AICSAR:SetOperatorTTSVoice(Voice,Culture,Gender)
|
||||||
self:T(self.lid .. "SetOperatorTTSVoice")
|
self:T(self.lid .. "SetOperatorTTSVoice")
|
||||||
self.SRSOperatorVoice = true
|
self.SRSOperatorVoice = true
|
||||||
self.SRSOperator = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation,1)
|
self.SRSOperator = MSRS:New(self.SRSPath,self.SRSFrequency,self.SRSModulation)
|
||||||
self.SRSOperator:SetCoalition(self.coalition)
|
self.SRSOperator:SetCoalition(self.coalition)
|
||||||
self.SRSOperator:SetVoice(Voice)
|
self.SRSOperator:SetVoice(Voice)
|
||||||
self.SRSOperator:SetCulture(Culture or "en-GB")
|
self.SRSOperator:SetCulture(Culture or "en-GB")
|
||||||
|
|||||||
@@ -462,7 +462,7 @@ function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Cultu
|
|||||||
self.Volume = Volume or 1.0
|
self.Volume = Volume or 1.0
|
||||||
self.Label = Label
|
self.Label = Label
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS = MSRS:New(self.SRSPath,self.SRSFreq,self.SRSMod,self.Volume)
|
self.SRS = MSRS:New(self.SRSPath,self.SRSFreq,self.SRSMod)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
@@ -470,6 +470,7 @@ function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Cultu
|
|||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVoice(self.Voice)
|
||||||
self.SRS:SetCoalition(self.coalition)
|
self.SRS:SetCoalition(self.coalition)
|
||||||
|
self.SRS:SetVolume(Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
self.SRS:SetGoogle(self.PathToGoogleKey)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1211,16 +1211,18 @@ function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume,
|
|||||||
|
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
|
|
||||||
self.controlmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 256, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.controlmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 256, Modulation or radio.modulation.AM)
|
||||||
self.controlmsrs:SetPort(Port or MSRS.port)
|
self.controlmsrs:SetPort(Port or MSRS.port)
|
||||||
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.controlmsrs:SetLabel("RANGEC")
|
self.controlmsrs:SetLabel("RANGEC")
|
||||||
|
self.controlmsrs:SetVolume(Volume or 1.0)
|
||||||
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
||||||
|
|
||||||
self.instructmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 305, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.instructmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 305, Modulation or radio.modulation.AM)
|
||||||
self.instructmsrs:SetPort(Port or MSRS.port)
|
self.instructmsrs:SetPort(Port or MSRS.port)
|
||||||
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.instructmsrs:SetLabel("RANGEI")
|
self.instructmsrs:SetLabel("RANGEI")
|
||||||
|
self.instructmsrs:SetVolume(Volume or 1.0)
|
||||||
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
||||||
|
|
||||||
if PathToGoogleKey then
|
if PathToGoogleKey then
|
||||||
|
|||||||
@@ -276,9 +276,15 @@ function SCORING:New( GameName )
|
|||||||
self:SetMessagesZone( true )
|
self:SetMessagesZone( true )
|
||||||
|
|
||||||
-- Scales
|
-- Scales
|
||||||
|
|
||||||
self:SetScaleDestroyScore( 10 )
|
self:SetScaleDestroyScore( 10 )
|
||||||
self:SetScaleDestroyPenalty( 30 )
|
self:SetScaleDestroyPenalty( 30 )
|
||||||
|
|
||||||
|
-- Hitting a target multiple times before destoying it should not result in a higger score
|
||||||
|
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
||||||
|
-- Making this configurable to anyone can enable this anyway if they want
|
||||||
|
self:SetScoreIncrementOnHit(0)
|
||||||
|
|
||||||
-- Default fratricide penalty level (maximum penalty that can be assigned to a player before he gets kicked).
|
-- Default fratricide penalty level (maximum penalty that can be assigned to a player before he gets kicked).
|
||||||
self:SetFratricide( self.ScaleDestroyPenalty * 3 )
|
self:SetFratricide( self.ScaleDestroyPenalty * 3 )
|
||||||
self.penaltyonfratricide = true
|
self.penaltyonfratricide = true
|
||||||
@@ -467,6 +473,16 @@ function SCORING:SetMessagesHit( OnOff )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Configure to increment score after a target has been hit.
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #number score amount of point to inclement score on each hit
|
||||||
|
-- @return #SCORING
|
||||||
|
function SCORING:SetScoreIncrementOnHit( score )
|
||||||
|
|
||||||
|
self.ScoreIncrementOnHit = score
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- If to send messages after a target has been hit.
|
--- If to send messages after a target has been hit.
|
||||||
-- @param #SCORING self
|
-- @param #SCORING self
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
@@ -885,6 +901,7 @@ function SCORING:OnEventBirth( Event )
|
|||||||
Event.IniUnit.BirthTime = timer.getTime()
|
Event.IniUnit.BirthTime = timer.getTime()
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
self:_AddPlayerFromUnit( Event.IniUnit )
|
self:_AddPlayerFromUnit( Event.IniUnit )
|
||||||
|
self.Players[PlayerName].PlayerKills = 0
|
||||||
self:SetScoringMenu( Event.IniGroup )
|
self:SetScoringMenu( Event.IniGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1015,7 +1032,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||||
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
||||||
if PlayerHit.UNIT.ThreatType == nil then
|
if PlayerHit.UNIT.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||||
-- if this fails for some reason, set a good default value
|
-- if this fails for some reason, set a good default value
|
||||||
if PlayerHit.ThreatType == nil then
|
if PlayerHit.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel = 1
|
PlayerHit.ThreatLevel = 1
|
||||||
@@ -1060,10 +1077,8 @@ function SCORING:_EventOnHit( Event )
|
|||||||
end
|
end
|
||||||
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
else
|
else
|
||||||
-- Hitting a target multiple times before destoying it should not result in a higger score
|
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||||
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||||
-- Player.Score = Player.Score + 1
|
|
||||||
-- PlayerHit.Score = PlayerHit.Score + 1
|
|
||||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||||
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
||||||
@@ -1128,7 +1143,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||||
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
-- After an instant kill we can't compute the thread level anymore. To fix this we compute at OnEventBirth
|
||||||
if PlayerHit.UNIT.ThreatType == nil then
|
if PlayerHit.UNIT.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||||
-- if this fails for some reason, set a good default value
|
-- if this fails for some reason, set a good default value
|
||||||
if PlayerHit.ThreatType == nil then
|
if PlayerHit.ThreatType == nil then
|
||||||
PlayerHit.ThreatLevel = 1
|
PlayerHit.ThreatLevel = 1
|
||||||
@@ -1163,10 +1178,8 @@ function SCORING:_EventOnHit( Event )
|
|||||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
else
|
else
|
||||||
-- Hitting a target multiple times before destoying it should not result in a higger score
|
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||||
-- Multiple hits is typically a results of bombs/missles missing their target but still inflict some spash damage
|
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||||
-- Player.Score = Player.Score + 1
|
|
||||||
-- PlayerHit.Score = PlayerHit.Score + 1
|
|
||||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||||
@@ -1274,13 +1287,18 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
TargetDestroy.Penalty = TargetDestroy.Penalty + ThreatPenalty
|
TargetDestroy.Penalty = TargetDestroy.Penalty + ThreatPenalty
|
||||||
TargetDestroy.PenaltyDestroy = TargetDestroy.PenaltyDestroy + 1
|
TargetDestroy.PenaltyDestroy = TargetDestroy.PenaltyDestroy + 1
|
||||||
|
|
||||||
|
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty)
|
||||||
|
|
||||||
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, true)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
||||||
else
|
else
|
||||||
|
self:OnKillPvE(Player, TargetUnitName, true, TargetThreatLevel, Player.ThreatLevel, ThreatPenalty)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed friendly target " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
"Penalty: -" .. ThreatPenalty .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
@@ -1303,12 +1321,19 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
|||||||
TargetDestroy.Score = TargetDestroy.Score + ThreatScore
|
TargetDestroy.Score = TargetDestroy.Score + ThreatScore
|
||||||
TargetDestroy.ScoreDestroy = TargetDestroy.ScoreDestroy + 1
|
TargetDestroy.ScoreDestroy = TargetDestroy.ScoreDestroy + 1
|
||||||
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
if Player.HitPlayers[TargetPlayerName] then -- A player destroyed another player
|
||||||
|
if Player.PlayerKills ~= nil then
|
||||||
|
Player.PlayerKills = Player.PlayerKills + 1
|
||||||
|
else
|
||||||
|
Player.PlayerKills = 1
|
||||||
|
end
|
||||||
|
self:OnKillPvP(Player, TargetPlayerName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy player '" .. TargetPlayerName .. "' " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesDestroy() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesDestroy() and self:IfMessagesToCoalition() )
|
||||||
else
|
else
|
||||||
|
self:OnKillPvE(Player, TargetUnitName, false, TargetThreatLevel, Player.ThreatLevel, ThreatScore)
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' destroyed enemy " .. TargetUnitCategory .. " ( " .. ThreatTypeTarget .. " ) " ..
|
||||||
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
"Score: +" .. ThreatScore .. " = " .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Information )
|
MESSAGE.Type.Information )
|
||||||
@@ -1907,3 +1932,26 @@ function SCORING:SwitchAutoSave(OnOff)
|
|||||||
self.AutoSave = OnOff
|
self.AutoSave = OnOff
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles the event when one player kill another player
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #PLAYER Player the ataching player
|
||||||
|
-- @param #string TargetPlayerName the name of the killed player
|
||||||
|
-- @param #bool IsTeamKill true if this kill was a team kill
|
||||||
|
-- @param #number TargetThreatLevel Thread level of the target
|
||||||
|
-- @param #number PlayerThreatLevelThread level of the player
|
||||||
|
-- @param #number Score The score based on both threat levels
|
||||||
|
function SCORING:OnKillPvP(Player, TargetPlayerName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score)
|
||||||
|
|
||||||
|
end
|
||||||
|
--- Handles the event when one player kill another player
|
||||||
|
-- @param #SCORING self
|
||||||
|
-- @param #PLAYER Player the ataching player
|
||||||
|
-- @param #string TargetUnitName the name of the killed unit
|
||||||
|
-- @param #bool IsTeamKill true if this kill was a team kill
|
||||||
|
-- @param #number TargetThreatLevel Thread level of the target
|
||||||
|
-- @param #number PlayerThreatLevelThread level of the player
|
||||||
|
-- @param #number Score The score based on both threat levels
|
||||||
|
function SCORING:OnKillPvE(Player, TargetUnitName, IsTeamKill, TargetThreatLevel, PlayerThreatLevel, Score)
|
||||||
|
|
||||||
|
end
|
||||||
@@ -42,6 +42,7 @@
|
|||||||
-- @field #number CaptureUnits
|
-- @field #number CaptureUnits
|
||||||
-- @field #number CaptureThreatlevel
|
-- @field #number CaptureThreatlevel
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
--- *If you see what is right and fail to act on it, you lack courage* --- Confucius
|
--- *If you see what is right and fail to act on it, you lack courage* --- Confucius
|
||||||
@@ -175,7 +176,7 @@ STRATEGO = {
|
|||||||
debug = false,
|
debug = false,
|
||||||
drawzone = false,
|
drawzone = false,
|
||||||
markzone = false,
|
markzone = false,
|
||||||
version = "0.2.1",
|
version = "0.2.3",
|
||||||
portweight = 3,
|
portweight = 3,
|
||||||
POIweight = 1,
|
POIweight = 1,
|
||||||
maxrunways = 3,
|
maxrunways = 3,
|
||||||
@@ -244,8 +245,8 @@ STRATEGO.Type = {
|
|||||||
-- @param #number MaxDist Maximum distance of a single route in kilometers, defaults to 150.
|
-- @param #number MaxDist Maximum distance of a single route in kilometers, defaults to 150.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:New(Name,Coalition,MaxDist)
|
function STRATEGO:New(Name,Coalition,MaxDist)
|
||||||
-- Inherit everything from BASE class.
|
-- Inherit everything from FSM class.
|
||||||
local self = BASE:Inherit(self, BASE:New()) -- #STRATEGO
|
local self = BASE:Inherit(self, FSM:New()) -- #STRATEGO
|
||||||
|
|
||||||
self.coalition = Coalition
|
self.coalition = Coalition
|
||||||
self.coalitiontext = UTILS.GetCoalitionName(Coalition)
|
self.coalitiontext = UTILS.GetCoalitionName(Coalition)
|
||||||
@@ -268,13 +269,55 @@ function STRATEGO:New(Name,Coalition,MaxDist)
|
|||||||
[4] = {1,0.65,0}, -- orange
|
[4] = {1,0.65,0}, -- orange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Stopped")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Update", "*") -- Start FSM.
|
||||||
|
self:AddTransition("*", "NodeEvent", "*") -- Start FSM.
|
||||||
|
self:AddTransition("Running", "Stop", "Stopped") -- Start FSM.
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
--- Pseudo Functions ---
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start". Starts the STRATEGO. Initializes parameters and starts event handlers.
|
||||||
|
-- @function [parent=#STRATEGO] Start
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start" after a delay. Starts the STRATEGO. Initializes parameters and starts event handlers.
|
||||||
|
-- @function [parent=#STRATEGO] __Start
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop". Stops the STRATEGO and all its event handlers.
|
||||||
|
-- @function [parent=#STRATEGO] Stop
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop" after a delay. Stops the STRATEGO and all its event handlers.
|
||||||
|
-- @function [parent=#STRATEGO] __Stop
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- FSM Function OnAfterNodeEvent. A node changed coalition.
|
||||||
|
-- @function [parent=#STRATEGO] OnAfterNodeEvent
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Ops.OpsZone#OPSZONE OpsZone The OpsZone triggering the event.
|
||||||
|
-- @param #number Coalition The coalition of the new owner.
|
||||||
|
-- @return #STRATEGO self
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [USER] Do initial setup and get ready.
|
--- [INTERNAL] FSM function for initial setup and getting ready.
|
||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:Start()
|
function STRATEGO:onafterStart(From,Event,To)
|
||||||
self:T(self.lid.."Start")
|
self:T(self.lid.."Start")
|
||||||
self:AnalyseBases()
|
self:AnalyseBases()
|
||||||
self:AnalysePOIs(self.ports,self.portweight,"PORT")
|
self:AnalysePOIs(self.ports,self.portweight,"PORT")
|
||||||
@@ -282,12 +325,27 @@ function STRATEGO:Start()
|
|||||||
|
|
||||||
for i=self.maxrunways,1,-1 do
|
for i=self.maxrunways,1,-1 do
|
||||||
self:AnalyseRoutes(i,i*self.routefactor,self.colors[(i%3)+1],i)
|
self:AnalyseRoutes(i,i*self.routefactor,self.colors[(i%3)+1],i)
|
||||||
--self:AnalyseRoutes(2,2*self.routefactor,self.colors[2],2)
|
|
||||||
--self:AnalyseRoutes(1,1*self.routefactor,self.colors[3],3)
|
|
||||||
end
|
end
|
||||||
self:AnalyseUnconnected(self.colors[4])
|
self:AnalyseUnconnected(self.colors[4])
|
||||||
|
|
||||||
self:I(self.lid.."Advisory ready.")
|
self:I(self.lid.."Advisory ready.")
|
||||||
|
|
||||||
|
self:__Update(180)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Update knot association
|
||||||
|
-- @param #STRATEGO self
|
||||||
|
-- @return #STRATEGO self
|
||||||
|
function STRATEGO:onafterUpdate(From,Event,To)
|
||||||
|
self:T(self.lid.."Update")
|
||||||
|
|
||||||
|
self:UpdateNodeCoalitions()
|
||||||
|
|
||||||
|
if self:GetState() == "Running" then
|
||||||
|
self:__Update(180)
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -308,6 +366,7 @@ end
|
|||||||
-- @param #boolean DrawZones If true, draw the OpsZones on the F10 map.
|
-- @param #boolean DrawZones If true, draw the OpsZones on the F10 map.
|
||||||
-- @param #boolean MarkZones if true, mark the OpsZones on the F10 map (with further information).
|
-- @param #boolean MarkZones if true, mark the OpsZones on the F10 map (with further information).
|
||||||
function STRATEGO:SetDebug(Debug,DrawZones,MarkZones)
|
function STRATEGO:SetDebug(Debug,DrawZones,MarkZones)
|
||||||
|
self:T(self.lid.."SetDebug")
|
||||||
self.debug = Debug
|
self.debug = Debug
|
||||||
self.drawzone = DrawZones
|
self.drawzone = DrawZones
|
||||||
self.markzone = MarkZones
|
self.markzone = MarkZones
|
||||||
@@ -322,6 +381,7 @@ end
|
|||||||
-- @param #number RouteFactor Defines which weight each route between two defined nodes gets: Weight * RouteFactor.
|
-- @param #number RouteFactor Defines which weight each route between two defined nodes gets: Weight * RouteFactor.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:SetWeights(MaxRunways,PortWeight,POIWeight,RouteFactor)
|
function STRATEGO:SetWeights(MaxRunways,PortWeight,POIWeight,RouteFactor)
|
||||||
|
self:T(self.lid.."SetWeights")
|
||||||
self.portweight = PortWeight or 3
|
self.portweight = PortWeight or 3
|
||||||
self.POIweight = POIWeight or 1
|
self.POIweight = POIWeight or 1
|
||||||
self.maxrunways = MaxRunways or 3
|
self.maxrunways = MaxRunways or 3
|
||||||
@@ -334,6 +394,7 @@ end
|
|||||||
-- @param #number NeutralBenefit Pointsm defaults to 100.
|
-- @param #number NeutralBenefit Pointsm defaults to 100.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:SetNeutralBenefit(NeutralBenefit)
|
function STRATEGO:SetNeutralBenefit(NeutralBenefit)
|
||||||
|
self:T(self.lid.."SetNeutralBenefit")
|
||||||
self.NeutralBenefit = NeutralBenefit or 100
|
self.NeutralBenefit = NeutralBenefit or 100
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -344,6 +405,7 @@ end
|
|||||||
-- @param #number CaptureThreatlevel Threat level needed, can be 0..10, defaults to one.
|
-- @param #number CaptureThreatlevel Threat level needed, can be 0..10, defaults to one.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:SetCaptureOptions(CaptureUnits,CaptureThreatlevel)
|
function STRATEGO:SetCaptureOptions(CaptureUnits,CaptureThreatlevel)
|
||||||
|
self:T(self.lid.."SetCaptureOptions")
|
||||||
self.CaptureUnits = CaptureUnits or 3
|
self.CaptureUnits = CaptureUnits or 3
|
||||||
self.CaptureThreatlevel = CaptureThreatlevel or 1
|
self.CaptureThreatlevel = CaptureThreatlevel or 1
|
||||||
return self
|
return self
|
||||||
@@ -369,6 +431,9 @@ function STRATEGO:AnalyseBases()
|
|||||||
local numrwys = #runways
|
local numrwys = #runways
|
||||||
if numrwys >= 1 then numrwys = numrwys * 0.5 end
|
if numrwys >= 1 then numrwys = numrwys * 0.5 end
|
||||||
local abzone = ab:GetZone()
|
local abzone = ab:GetZone()
|
||||||
|
if not abzone then
|
||||||
|
abzone = ZONE_RADIUS:New(abname,ab:GetVec2(),500)
|
||||||
|
end
|
||||||
local coa = ab:GetCoalition() + 1
|
local coa = ab:GetCoalition() + 1
|
||||||
local abtype = "AIRBASE"
|
local abtype = "AIRBASE"
|
||||||
if ab:IsShip() then
|
if ab:IsShip() then
|
||||||
@@ -379,7 +444,7 @@ function STRATEGO:AnalyseBases()
|
|||||||
numrwys = 1
|
numrwys = 1
|
||||||
abtype = "FARP"
|
abtype = "FARP"
|
||||||
end
|
end
|
||||||
local coord = abzone:GetCoordinate()
|
local coord = ab:GetCoordinate()
|
||||||
if debug then
|
if debug then
|
||||||
abzone:DrawZone(-1,colors[coa],1,colors[coa],0.3,1)
|
abzone:DrawZone(-1,colors[coa],1,colors[coa],0.3,1)
|
||||||
coord:TextToAll(tostring(numrwys),-1,{0,0,0},1,colors[coa],0.3,20)
|
coord:TextToAll(tostring(numrwys),-1,{0,0,0},1,colors[coa],0.3,20)
|
||||||
@@ -394,6 +459,7 @@ function STRATEGO:AnalyseBases()
|
|||||||
zone = abzone,
|
zone = abzone,
|
||||||
coord = coord,
|
coord = coord,
|
||||||
type = abtype,
|
type = abtype,
|
||||||
|
opszone = opszone,
|
||||||
}
|
}
|
||||||
airbasetable[abname] = tbl
|
airbasetable[abname] = tbl
|
||||||
nonconnectedab[abname] = true
|
nonconnectedab[abname] = true
|
||||||
@@ -437,6 +503,15 @@ function STRATEGO:GetNewOpsZone(Zone,Coalition)
|
|||||||
opszone:SetDrawZone(self.drawzone)
|
opszone:SetDrawZone(self.drawzone)
|
||||||
opszone:SetMarkZone(self.markzone)
|
opszone:SetMarkZone(self.markzone)
|
||||||
opszone:Start()
|
opszone:Start()
|
||||||
|
|
||||||
|
local function Captured(opszone,coalition)
|
||||||
|
self:__NodeEvent(1,opszone,coalition)
|
||||||
|
end
|
||||||
|
|
||||||
|
function opszone:OnBeforeCaptured(From,Event,To,Coalition)
|
||||||
|
Captured(opszone,Coalition)
|
||||||
|
end
|
||||||
|
|
||||||
return opszone
|
return opszone
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -494,13 +569,14 @@ end
|
|||||||
|
|
||||||
--- [USER] Manually add a route, for e.g. Island hopping or to connect isolated networks. Use **after** STRATEGO has been started!
|
--- [USER] Manually add a route, for e.g. Island hopping or to connect isolated networks. Use **after** STRATEGO has been started!
|
||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @param #string Startpoint
|
-- @param #string Startpoint Starting Point, e.g. AIRBASE.Syria.Hatay
|
||||||
-- @param #string Endpoint
|
-- @param #string Endpoint End Point, e.g. AIRBASE.Syria.H4
|
||||||
-- @param #table Color (Optional) RGB color table {r, g, b}, e.g. {1,0,0} for red. Defaults to lila.
|
-- @param #table Color (Optional) RGB color table {r, g, b}, e.g. {1,0,0} for red. Defaults to lila.
|
||||||
-- @param #number LineType (Optional) Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 5.
|
-- @param #number Linetype (Optional) Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 5.
|
||||||
-- @param #boolean Draw (Optional) If true, draw route on the F10 map. Defaukt false.
|
-- @param #boolean Draw (Optional) If true, draw route on the F10 map. Defaukt false.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:AddRoutesManually(Startpoint,Endpoint,Color,Linetype,Draw)
|
function STRATEGO:AddRoutesManually(Startpoint,Endpoint,Color,Linetype,Draw)
|
||||||
|
self:T(self.lid.."AddRoutesManually")
|
||||||
local fromto,tofrom = self:GetToFrom(Startpoint,Endpoint)
|
local fromto,tofrom = self:GetToFrom(Startpoint,Endpoint)
|
||||||
local startcoordinate = self.airbasetable[Startpoint].coord
|
local startcoordinate = self.airbasetable[Startpoint].coord
|
||||||
local targetcoordinate = self.airbasetable[Endpoint].coord
|
local targetcoordinate = self.airbasetable[Endpoint].coord
|
||||||
@@ -630,7 +706,7 @@ end
|
|||||||
-- @return #table Table of nodes.
|
-- @return #table Table of nodes.
|
||||||
-- @return #number Weight The consolidated weight associated with the nodes.
|
-- @return #number Weight The consolidated weight associated with the nodes.
|
||||||
function STRATEGO:GetHighestWeightNodes()
|
function STRATEGO:GetHighestWeightNodes()
|
||||||
self:T(self.lid.."GetHighestWeightBases")
|
self:T(self.lid.."GetHighestWeightNodes")
|
||||||
local weight = 0
|
local weight = 0
|
||||||
local airbases = {}
|
local airbases = {}
|
||||||
for _name,_data in pairs(self.airbasetable) do
|
for _name,_data in pairs(self.airbasetable) do
|
||||||
@@ -648,7 +724,7 @@ end
|
|||||||
-- @return #table Table of nodes.
|
-- @return #table Table of nodes.
|
||||||
-- @return #number Weight The consolidated weight associated with the nodes.
|
-- @return #number Weight The consolidated weight associated with the nodes.
|
||||||
function STRATEGO:GetNextHighestWeightNodes(Weight)
|
function STRATEGO:GetNextHighestWeightNodes(Weight)
|
||||||
self:T(self.lid.."GetNextHighestWeightBases")
|
self:T(self.lid.."GetNextHighestWeightNodes")
|
||||||
local weight = 0
|
local weight = 0
|
||||||
local airbases = {}
|
local airbases = {}
|
||||||
for _name,_data in pairs(self.airbasetable) do
|
for _name,_data in pairs(self.airbasetable) do
|
||||||
@@ -666,6 +742,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #number Weight The weight or 0 if not found.
|
-- @return #number Weight The weight or 0 if not found.
|
||||||
function STRATEGO:GetNodeWeight(Name)
|
function STRATEGO:GetNodeWeight(Name)
|
||||||
|
self:T(self.lid.."GetNodeWeight")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].weight or 0
|
return self.airbasetable[Name].weight or 0
|
||||||
else
|
else
|
||||||
@@ -678,6 +755,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #number Weight The base weight or 0 if not found.
|
-- @return #number Weight The base weight or 0 if not found.
|
||||||
function STRATEGO:GetNodeBaseWeight(Name)
|
function STRATEGO:GetNodeBaseWeight(Name)
|
||||||
|
self:T(self.lid.."GetNodeBaseWeight")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].baseweight or 0
|
return self.airbasetable[Name].baseweight or 0
|
||||||
else
|
else
|
||||||
@@ -690,6 +768,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #number Coalition The coalition.
|
-- @return #number Coalition The coalition.
|
||||||
function STRATEGO:GetNodeCoalition(Name)
|
function STRATEGO:GetNodeCoalition(Name)
|
||||||
|
self:T(self.lid.."GetNodeCoalition")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].coalition or coalition.side.NEUTRAL
|
return self.airbasetable[Name].coalition or coalition.side.NEUTRAL
|
||||||
else
|
else
|
||||||
@@ -702,6 +781,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #string Type Type of the node, e.g. STRATEGO.Type.AIRBASE or nil if not found.
|
-- @return #string Type Type of the node, e.g. STRATEGO.Type.AIRBASE or nil if not found.
|
||||||
function STRATEGO:GetNodeType(Name)
|
function STRATEGO:GetNodeType(Name)
|
||||||
|
self:T(self.lid.."GetNodeType")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type
|
return self.airbasetable[Name].type
|
||||||
else
|
else
|
||||||
@@ -714,6 +794,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return Core.Zone#ZONE Zone The Zone of the node or nil if not found.
|
-- @return Core.Zone#ZONE Zone The Zone of the node or nil if not found.
|
||||||
function STRATEGO:GetNodeZone(Name)
|
function STRATEGO:GetNodeZone(Name)
|
||||||
|
self:T(self.lid.."GetNodeZone")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].zone
|
return self.airbasetable[Name].zone
|
||||||
else
|
else
|
||||||
@@ -726,6 +807,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return Ops.OpsZone#OPSZONE OpsZone The OpsZone of the node or nil if not found.
|
-- @return Ops.OpsZone#OPSZONE OpsZone The OpsZone of the node or nil if not found.
|
||||||
function STRATEGO:GetNodeOpsZone(Name)
|
function STRATEGO:GetNodeOpsZone(Name)
|
||||||
|
self:T(self.lid.."GetNodeOpsZone")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].opszone
|
return self.airbasetable[Name].opszone
|
||||||
else
|
else
|
||||||
@@ -738,6 +820,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return Core.Point#COORDINATE Coordinate The Coordinate of the node or nil if not found.
|
-- @return Core.Point#COORDINATE Coordinate The Coordinate of the node or nil if not found.
|
||||||
function STRATEGO:GetNodeCoordinate(Name)
|
function STRATEGO:GetNodeCoordinate(Name)
|
||||||
|
self:T(self.lid.."GetNodeCoordinate")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].coord
|
return self.airbasetable[Name].coord
|
||||||
else
|
else
|
||||||
@@ -750,6 +833,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function STRATEGO:IsAirbase(Name)
|
function STRATEGO:IsAirbase(Name)
|
||||||
|
self:T(self.lid.."IsAirbase")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type == STRATEGO.Type.AIRBASE
|
return self.airbasetable[Name].type == STRATEGO.Type.AIRBASE
|
||||||
else
|
else
|
||||||
@@ -762,6 +846,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function STRATEGO:IsPort(Name)
|
function STRATEGO:IsPort(Name)
|
||||||
|
self:T(self.lid.."IsPort")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type == STRATEGO.Type.PORT
|
return self.airbasetable[Name].type == STRATEGO.Type.PORT
|
||||||
else
|
else
|
||||||
@@ -774,6 +859,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function STRATEGO:IsPOI(Name)
|
function STRATEGO:IsPOI(Name)
|
||||||
|
self:T(self.lid.."IsPOI")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type == STRATEGO.Type.POI
|
return self.airbasetable[Name].type == STRATEGO.Type.POI
|
||||||
else
|
else
|
||||||
@@ -786,6 +872,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function STRATEGO:IsFARP(Name)
|
function STRATEGO:IsFARP(Name)
|
||||||
|
self:T(self.lid.."IsFARP")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type == STRATEGO.Type.FARP
|
return self.airbasetable[Name].type == STRATEGO.Type.FARP
|
||||||
else
|
else
|
||||||
@@ -798,6 +885,7 @@ end
|
|||||||
-- @param #string Name.
|
-- @param #string Name.
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function STRATEGO:IsShip(Name)
|
function STRATEGO:IsShip(Name)
|
||||||
|
self:T(self.lid.."IsShip")
|
||||||
if Name and self.airbasetable[Name] then
|
if Name and self.airbasetable[Name] then
|
||||||
return self.airbasetable[Name].type == STRATEGO.Type.SHIP
|
return self.airbasetable[Name].type == STRATEGO.Type.SHIP
|
||||||
else
|
else
|
||||||
@@ -880,6 +968,7 @@ end
|
|||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #table of #STRATEGO.Target data points
|
-- @return #table of #STRATEGO.Target data points
|
||||||
function STRATEGO:FindStrategicTargets()
|
function STRATEGO:FindStrategicTargets()
|
||||||
|
self:T(self.lid.."FindStrategicTargets")
|
||||||
local targets = {}
|
local targets = {}
|
||||||
for _,_data in pairs(self.airbasetable) do
|
for _,_data in pairs(self.airbasetable) do
|
||||||
local data = _data -- #STRATEGO.Data
|
local data = _data -- #STRATEGO.Data
|
||||||
@@ -923,6 +1012,7 @@ end
|
|||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #table of #STRATEGO.Target data points
|
-- @return #table of #STRATEGO.Target data points
|
||||||
function STRATEGO:FindConsolidationTargets()
|
function STRATEGO:FindConsolidationTargets()
|
||||||
|
self:T(self.lid.."FindConsolidationTargets")
|
||||||
local targets = {}
|
local targets = {}
|
||||||
for _,_data in pairs(self.airbasetable) do
|
for _,_data in pairs(self.airbasetable) do
|
||||||
local data = _data -- #STRATEGO.Data
|
local data = _data -- #STRATEGO.Data
|
||||||
@@ -971,6 +1061,7 @@ end
|
|||||||
-- @param #boolean Friends (optional) If true, find only friendly or neutral neighbors.
|
-- @param #boolean Friends (optional) If true, find only friendly or neutral neighbors.
|
||||||
-- @return #table Neighbors Table of #STRATEGO.DistData entries indexed by neighbor node names.
|
-- @return #table Neighbors Table of #STRATEGO.DistData entries indexed by neighbor node names.
|
||||||
function STRATEGO:FindNeighborNodes(Name,Enemies,Friends)
|
function STRATEGO:FindNeighborNodes(Name,Enemies,Friends)
|
||||||
|
self:T(self.lid.."FindNeighborNodes")
|
||||||
local neighbors = {}
|
local neighbors = {}
|
||||||
local name = string.gsub(Name,"[%p%s]",".")
|
local name = string.gsub(Name,"[%p%s]",".")
|
||||||
for _route,_data in pairs(self.disttable) do
|
for _route,_data in pairs(self.disttable) do
|
||||||
@@ -1002,10 +1093,13 @@ end
|
|||||||
-- @param #string End The name of the end node.
|
-- @param #string End The name of the end node.
|
||||||
-- @param #number Hops Max iterations to find a route.
|
-- @param #number Hops Max iterations to find a route.
|
||||||
-- @param #boolean Draw If true, draw the route on the map.
|
-- @param #boolean Draw If true, draw the route on the map.
|
||||||
|
-- @param #table Color (Optional) RGB color table {r, g, b}, e.g. {1,0,0} for red. Defaults to black.
|
||||||
|
-- @param #number LineType (Optional) Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 6.
|
||||||
-- @return #table Route Table of #string name entries of the route
|
-- @return #table Route Table of #string name entries of the route
|
||||||
-- @return #boolean Complete If true, the route was found end-to-end.
|
-- @return #boolean Complete If true, the route was found end-to-end.
|
||||||
function STRATEGO:FindRoute(Start,End,Hops,Draw)
|
function STRATEGO:FindRoute(Start,End,Hops,Draw,Color,LineType)
|
||||||
self:I({Start,End,Hops})
|
self:T(self.lid.."FindRoute")
|
||||||
|
--self:I({Start,End,Hops})
|
||||||
--local bases = UTILS.DeepCopy(self.airbasetable)
|
--local bases = UTILS.DeepCopy(self.airbasetable)
|
||||||
local Route = {}
|
local Route = {}
|
||||||
local hops = Hops or 4
|
local hops = Hops or 4
|
||||||
@@ -1046,7 +1140,9 @@ function STRATEGO:FindRoute(Start,End,Hops,Draw)
|
|||||||
local p2=Route[i+1]
|
local p2=Route[i+1]
|
||||||
local c1 = self.airbasetable[p1].coord -- Core.Point#COORDINATE
|
local c1 = self.airbasetable[p1].coord -- Core.Point#COORDINATE
|
||||||
local c2 = self.airbasetable[p2].coord -- Core.Point#COORDINATE
|
local c2 = self.airbasetable[p2].coord -- Core.Point#COORDINATE
|
||||||
c1:LineToAll(c2,-1,{0,0,0},1,6)
|
local line = LineType or 6
|
||||||
|
local color = Color or {0,0,0}
|
||||||
|
c1:LineToAll(c2,-1,color,1,line)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1076,7 +1172,7 @@ function STRATEGO:FindRoute(Start,End,Hops,Draw)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if self.debug or Draw then DrawRoute(Route) end
|
if (self.debug or Draw) then DrawRoute(Route) end
|
||||||
return Route, routecomplete
|
return Route, routecomplete
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1085,6 +1181,7 @@ end
|
|||||||
-- @param #number Number of points to add.
|
-- @param #number Number of points to add.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:AddBudget(Number)
|
function STRATEGO:AddBudget(Number)
|
||||||
|
self:T(self.lid.."AddBudget")
|
||||||
self.Budget = self.Budget + Number
|
self.Budget = self.Budget + Number
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1094,6 +1191,7 @@ end
|
|||||||
-- @param #number Number of points to subtract.
|
-- @param #number Number of points to subtract.
|
||||||
-- @return #STRATEGO self
|
-- @return #STRATEGO self
|
||||||
function STRATEGO:SubtractBudget(Number)
|
function STRATEGO:SubtractBudget(Number)
|
||||||
|
self:T(self.lid.."SubtractBudget")
|
||||||
self.Budget = self.Budget - Number
|
self.Budget = self.Budget - Number
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1102,6 +1200,7 @@ end
|
|||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #number budget
|
-- @return #number budget
|
||||||
function STRATEGO:GetBudget()
|
function STRATEGO:GetBudget()
|
||||||
|
self:T(self.lid.."GetBudget")
|
||||||
return self.Budget
|
return self.Budget
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1109,6 +1208,7 @@ end
|
|||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #table Target Table with #STRATEGO.Target data or nil if none found.
|
-- @return #table Target Table with #STRATEGO.Target data or nil if none found.
|
||||||
function STRATEGO:FindAffordableStrategicTarget()
|
function STRATEGO:FindAffordableStrategicTarget()
|
||||||
|
self:T(self.lid.."FindAffordableStrategicTarget")
|
||||||
local targets = self:FindStrategicTargets() -- #table of #STRATEGO.Target
|
local targets = self:FindStrategicTargets() -- #table of #STRATEGO.Target
|
||||||
local budget = self.Budget
|
local budget = self.Budget
|
||||||
--local leftover = self.Budget
|
--local leftover = self.Budget
|
||||||
@@ -1140,6 +1240,7 @@ end
|
|||||||
-- @param #STRATEGO self
|
-- @param #STRATEGO self
|
||||||
-- @return #table Target Table with #STRATEGO.Target data or nil if none found.
|
-- @return #table Target Table with #STRATEGO.Target data or nil if none found.
|
||||||
function STRATEGO:FindAffordableConsolidationTarget()
|
function STRATEGO:FindAffordableConsolidationTarget()
|
||||||
|
self:T(self.lid.."FindAffordableConsolidationTarget")
|
||||||
local targets = self:FindConsolidationTargets() -- #table of #STRATEGO.Target
|
local targets = self:FindConsolidationTargets() -- #table of #STRATEGO.Target
|
||||||
local budget = self.Budget
|
local budget = self.Budget
|
||||||
--local leftover = self.Budget
|
--local leftover = self.Budget
|
||||||
|
|||||||
@@ -1526,7 +1526,7 @@ function ATIS:MarkRunways( markall )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.
|
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.`SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #string PathToSRS Path to SRS directory (only necessary if SRS exe backend is used).
|
-- @param #string PathToSRS Path to SRS directory (only necessary if SRS exe backend is used).
|
||||||
-- @param #string Gender Gender: "male" or "female" (default).
|
-- @param #string Gender Gender: "male" or "female" (default).
|
||||||
@@ -1536,24 +1536,52 @@ end
|
|||||||
-- @param #string GoogleKey Path to Google JSON-Key (SRS exe backend) or Google API key (DCS-gRPC backend).
|
-- @param #string GoogleKey Path to Google JSON-Key (SRS exe backend) or Google API key (DCS-gRPC backend).
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
||||||
if PathToSRS or MSRS.path then
|
--if PathToSRS or MSRS.path then
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
|
||||||
self.msrs:SetGender(Gender)
|
local path = PathToSRS or MSRS.path
|
||||||
self.msrs:SetCulture(Culture)
|
local gender = Gender or MSRS.gender
|
||||||
self.msrs:SetVoice(Voice)
|
local culture = Culture or MSRS.culture
|
||||||
self.msrs:SetPort(Port)
|
local voice = Voice or MSRS.voice
|
||||||
|
local port = Port or MSRS.port or 5002
|
||||||
|
|
||||||
|
self.msrs=MSRS:New(path, self.frequency, self.modulation)
|
||||||
|
self.msrs:SetGender(gender)
|
||||||
|
self.msrs:SetCulture(culture)
|
||||||
|
self.msrs:SetPort(port)
|
||||||
self.msrs:SetCoalition(self:GetCoalition())
|
self.msrs:SetCoalition(self:GetCoalition())
|
||||||
self.msrs:SetLabel("ATIS")
|
self.msrs:SetLabel("ATIS")
|
||||||
self.msrs:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrs:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not GoogleKey) and self.msrs:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
end
|
||||||
|
self.msrs:SetVoice(voice)
|
||||||
self.msrs:SetCoordinate(self.airbase:GetCoordinate())
|
self.msrs:SetCoordinate(self.airbase:GetCoordinate())
|
||||||
self.msrsQ = MSRSQUEUE:New("ATIS")
|
self.msrsQ = MSRSQUEUE:New("ATIS")
|
||||||
self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
if self.dTQueueCheck<=10 then
|
if self.dTQueueCheck<=10 then
|
||||||
self:SetQueueUpdateTime(90)
|
self:SetQueueUpdateTime(90)
|
||||||
end
|
end
|
||||||
|
--else
|
||||||
|
--self:E(self.lid..string.format("ERROR: No SRS path specified!"))
|
||||||
|
--end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set an alternative provider to the one set in your MSRS configuration file.
|
||||||
|
-- @param #ATIS self
|
||||||
|
-- @param #string Provider The provider to use. Known providers are: `MSRS.Provider.WINDOWS` and `MSRS.Provider.GOOGLE`
|
||||||
|
-- @return #ATIS self
|
||||||
|
function ATIS:SetSRSProvider(Provider)
|
||||||
|
self:T(self.lid.."SetSRSProvider")
|
||||||
|
if self.msrs then
|
||||||
|
self.msrs:SetProvider(Provider)
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: No SRS path specified!"))
|
MESSAGE:New(self.lid.."Set up SRS first before trying to change the provider!",30,"ATIS"):ToAll():ToLog()
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -3072,6 +3072,7 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
|||||||
self.SRS:SetPort(Port or 5002)
|
self.SRS:SetPort(Port or 5002)
|
||||||
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
|
self.SRS:SetLabel(self.AirbossRadio.alias or "AIRBOSS")
|
||||||
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
|
self.SRS:SetCoordinate(self.carrier:GetCoordinate())
|
||||||
|
self.SRS:SetVolume(Volume)
|
||||||
--self.SRS:SetModulations(Modulations)
|
--self.SRS:SetModulations(Modulations)
|
||||||
if GoogleCreds then
|
if GoogleCreds then
|
||||||
self.SRS:SetGoogle(GoogleCreds)
|
self.SRS:SetGoogle(GoogleCreds)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **applevangelist**
|
-- ### Author: **applevangelist**
|
||||||
-- @date Last Update Nov 2023
|
-- @date Last Update Jan 2024
|
||||||
-- @module Ops.AWACS
|
-- @module Ops.AWACS
|
||||||
-- @image OPS_AWACS.jpg
|
-- @image OPS_AWACS.jpg
|
||||||
|
|
||||||
@@ -507,7 +507,7 @@ do
|
|||||||
-- @field #AWACS
|
-- @field #AWACS
|
||||||
AWACS = {
|
AWACS = {
|
||||||
ClassName = "AWACS", -- #string
|
ClassName = "AWACS", -- #string
|
||||||
version = "0.2.59", -- #string
|
version = "0.2.61", -- #string
|
||||||
lid = "", -- #string
|
lid = "", -- #string
|
||||||
coalition = coalition.side.BLUE, -- #number
|
coalition = coalition.side.BLUE, -- #number
|
||||||
coalitiontxt = "blue", -- #string
|
coalitiontxt = "blue", -- #string
|
||||||
@@ -1405,15 +1405,18 @@ function AWACS:SetTacticalRadios(BaseFreq,Increase,Modulation,Interval,Number)
|
|||||||
self.TacticalFrequencies[freq] = freq
|
self.TacticalFrequencies[freq] = freq
|
||||||
end
|
end
|
||||||
if self.AwacsSRS then
|
if self.AwacsSRS then
|
||||||
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation,self.Volume)
|
self.TacticalSRS = MSRS:New(self.PathToSRS,self.TacticalBaseFreq,self.TacticalModulation)
|
||||||
self.TacticalSRS:SetCoalition(self.coalition)
|
self.TacticalSRS:SetCoalition(self.coalition)
|
||||||
self.TacticalSRS:SetGender(self.Gender)
|
self.TacticalSRS:SetGender(self.Gender)
|
||||||
self.TacticalSRS:SetCulture(self.Culture)
|
self.TacticalSRS:SetCulture(self.Culture)
|
||||||
self.TacticalSRS:SetVoice(self.Voice)
|
self.TacticalSRS:SetVoice(self.Voice)
|
||||||
self.TacticalSRS:SetPort(self.Port)
|
self.TacticalSRS:SetPort(self.Port)
|
||||||
self.TacticalSRS:SetLabel("AWACS")
|
self.TacticalSRS:SetLabel("AWACS")
|
||||||
|
self.TacticalSRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.TacticalSRS:SetGoogle(self.PathToGoogleKey)
|
--self.TacticalSRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.TacticalSRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.TacticalSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS")
|
self.TacticalSRSQ = MSRSQUEUE:New("Tactical AWACS")
|
||||||
end
|
end
|
||||||
@@ -2069,7 +2072,7 @@ function AWACS:AddGroupToDetection(Group)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details
|
--- [User] Set AWACS SRS TTS details - see @{Sound.SRS} for details. `SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
-- @param #string Gender Defaults to "male"
|
-- @param #string Gender Defaults to "male"
|
||||||
@@ -2078,29 +2081,39 @@ end
|
|||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here.
|
||||||
|
-- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here.
|
||||||
-- @return #AWACS self
|
-- @return #AWACS self
|
||||||
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
function AWACS:SetSRS(PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
self.Gender = Gender or "male"
|
self.Gender = Gender or MSRS.gender or "male"
|
||||||
self.Culture = Culture or "en-US"
|
self.Culture = Culture or MSRS.culture or "en-US"
|
||||||
self.Port = Port or 5002
|
self.Port = Port or MSRS.port or 5002
|
||||||
self.Voice = Voice
|
self.Voice = Voice or MSRS.voice
|
||||||
self.PathToGoogleKey = PathToGoogleKey
|
self.PathToGoogleKey = PathToGoogleKey
|
||||||
|
self.AccessKey = AccessKey
|
||||||
self.Volume = Volume or 1.0
|
self.Volume = Volume or 1.0
|
||||||
|
|
||||||
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation,self.Volume)
|
self.AwacsSRS = MSRS:New(self.PathToSRS,self.MultiFrequency,self.MultiModulation)
|
||||||
self.AwacsSRS:SetCoalition(self.coalition)
|
self.AwacsSRS:SetCoalition(self.coalition)
|
||||||
self.AwacsSRS:SetGender(self.Gender)
|
self.AwacsSRS:SetGender(self.Gender)
|
||||||
self.AwacsSRS:SetCulture(self.Culture)
|
self.AwacsSRS:SetCulture(self.Culture)
|
||||||
self.AwacsSRS:SetVoice(self.Voice)
|
|
||||||
self.AwacsSRS:SetPort(self.Port)
|
self.AwacsSRS:SetPort(self.Port)
|
||||||
self.AwacsSRS:SetLabel("AWACS")
|
self.AwacsSRS:SetLabel("AWACS")
|
||||||
|
self.AwacsSRS:SetVolume(Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.AwacsSRS:SetGoogle(self.PathToGoogleKey)
|
--self.AwacsSRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.AwacsSRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.AwacsSRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.AwacsSRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
self.AccessKey = AccessKey or MSRS.poptions.gcloud.key
|
||||||
|
end
|
||||||
|
self.AwacsSRS:SetVoice(self.Voice)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2935,7 +2948,7 @@ function AWACS:_Picture(Group,IsGeneral)
|
|||||||
if not self.intel then
|
if not self.intel then
|
||||||
-- no intel yet!
|
-- no intel yet!
|
||||||
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
|
local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
|
||||||
text = string.format(picclean,self.callsigntxt, gcallsign)
|
text = string.format(picclean,gcallsign,self.callsigntxt)
|
||||||
textScreen = text
|
textScreen = text
|
||||||
|
|
||||||
self:_NewRadioEntry(text,text,GID,false,true,true,false)
|
self:_NewRadioEntry(text,text,GID,false,true,true,false)
|
||||||
@@ -3663,7 +3676,7 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
|
|||||||
CAPVoice = self.CapVoices[math.floor(math.random(1,10))]
|
CAPVoice = self.CapVoices[math.floor(math.random(1,10))]
|
||||||
end
|
end
|
||||||
|
|
||||||
FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT")
|
FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT",1)
|
||||||
|
|
||||||
local checkai = self.gettext:GetEntry("CHECKINAI",self.locale)
|
local checkai = self.gettext:GetEntry("CHECKINAI",self.locale)
|
||||||
text = string.format(checkai,self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
|
text = string.format(checkai,self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
|
||||||
@@ -6595,7 +6608,7 @@ function AWACS:onafterCheckTacticalQueue(From,Event,To)
|
|||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
gtext = string.format("<speak><prosody rate='medium'>%s</prosody></speak>",gtext)
|
gtext = string.format("<speak><prosody rate='medium'>%s</prosody></speak>",gtext)
|
||||||
end
|
end
|
||||||
self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation,nil,nil,nil,nil,nil)
|
self.TacticalSRSQ:NewTransmission(gtext,nil,self.TacticalSRS,nil,0.5,nil,nil,nil,frequency,self.TacticalModulation)
|
||||||
|
|
||||||
self:T(RadioEntry.TextTTS)
|
self:T(RadioEntry.TextTTS)
|
||||||
|
|
||||||
|
|||||||
@@ -453,9 +453,12 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
|
|||||||
self.msrsqueue=MSRSQUEUE:New(self.alias)
|
self.msrsqueue=MSRSQUEUE:New(self.alias)
|
||||||
|
|
||||||
-- SRS for Tower.
|
-- SRS for Tower.
|
||||||
self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation)
|
self.msrsTower=MSRS:New(path, Frequency, Modulation)
|
||||||
self.msrsTower:SetPort(self.Port)
|
self.msrsTower:SetPort(port)
|
||||||
self.msrsTower:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrsTower:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrsTower:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
||||||
if GoogleKey then
|
if GoogleKey then
|
||||||
self.msrsTower:SetGoogle(GoogleKey)
|
self.msrsTower:SetGoogle(GoogleKey)
|
||||||
@@ -465,7 +468,10 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
|
|||||||
-- SRS for Pilot.
|
-- SRS for Pilot.
|
||||||
self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation)
|
self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation)
|
||||||
self.msrsPilot:SetPort(self.Port)
|
self.msrsPilot:SetPort(self.Port)
|
||||||
self.msrsPilot:SetGoogle(GoogleKey)
|
if GoogleKey then
|
||||||
|
self.msrsPilot:SetProviderOptionsGoogle(GoogleKey,GoogleKey)
|
||||||
|
self.msrsPilot:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
self.msrsTower:SetCoordinate(self:GetCoordinate())
|
||||||
if GoogleKey then
|
if GoogleKey then
|
||||||
self.msrsPilot:SetGoogle(GoogleKey)
|
self.msrsPilot:SetGoogle(GoogleKey)
|
||||||
@@ -688,12 +694,11 @@ end
|
|||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`. See [Google Voices](https://cloud.google.com/text-to-speech/docs/voices).
|
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`. See [Google Voices](https://cloud.google.com/text-to-speech/docs/voices).
|
||||||
-- @param #number Volume Volume. Default 1.0.
|
-- @param #number Volume Volume. Default 1.0.
|
||||||
-- @param #string Label Name under which SRS transmits. Default `self.alias`.
|
-- @param #string Label Name under which SRS transmits. Default `self.alias`.
|
||||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
|
||||||
-- @return #FLIGHTCONTROL self
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label)
|
||||||
|
|
||||||
if self.msrsTower then
|
if self.msrsTower then
|
||||||
self:_SetSRSOptions(self.msrsTower, Gender or "female", Culture or "en-GB", Voice, Volume, Label or self.alias, PathToGoogleCredentials)
|
self:_SetSRSOptions(self.msrsTower, Gender or "female", Culture or "en-GB", Voice, Volume, Label or self.alias)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -706,12 +711,11 @@ end
|
|||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||||
-- @param #number Volume Volume. Default 1.0.
|
-- @param #number Volume Volume. Default 1.0.
|
||||||
-- @param #string Label Name under which SRS transmits. Default "Pilot".
|
-- @param #string Label Name under which SRS transmits. Default "Pilot".
|
||||||
-- @param #string PathToGoogleCredentials Path to google credentials json file.
|
|
||||||
-- @return #FLIGHTCONTROL self
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
|
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label)
|
||||||
|
|
||||||
if self.msrsPilot then
|
if self.msrsPilot then
|
||||||
self:_SetSRSOptions(self.msrsPilot, Gender or "male", Culture or "en-US", Voice, Volume, Label or "Pilot", PathToGoogleCredentials)
|
self:_SetSRSOptions(self.msrsPilot, Gender or "male", Culture or "en-US", Voice, Volume, Label or "Pilot")
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -949,7 +953,7 @@ end
|
|||||||
|
|
||||||
--- Set ATIS.
|
--- Set ATIS.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param Ops.ATIS#ATIS ATIS ATIS.
|
-- @param Ops.ATIS#ATIS Atis ATIS.
|
||||||
-- @return #FLIGHTCONTROL self
|
-- @return #FLIGHTCONTROL self
|
||||||
function FLIGHTCONTROL:SetATIS(Atis)
|
function FLIGHTCONTROL:SetATIS(Atis)
|
||||||
self.atis=Atis
|
self.atis=Atis
|
||||||
|
|||||||
@@ -3257,11 +3257,20 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand)
|
|||||||
local TaskFinal = self.group:TaskFunction("FLIGHTGROUP._OnFinal", self)
|
local TaskFinal = self.group:TaskFunction("FLIGHTGROUP._OnFinal", self)
|
||||||
|
|
||||||
-- Final approach waypoint.
|
-- Final approach waypoint.
|
||||||
local papp=airbase:GetCoordinate():Translate(x1, runway.heading-180):SetAltitude(h1)
|
local rheading
|
||||||
|
if runway then
|
||||||
|
rheading = runway.heading-180
|
||||||
|
else
|
||||||
|
-- AB HeloBase w/o runway eg Naqoura
|
||||||
|
local wind = airbase:GetCoordinate():GetWind()
|
||||||
|
rheading = -wind
|
||||||
|
end
|
||||||
|
|
||||||
|
local papp=airbase:GetCoordinate():Translate(x1, rheading):SetAltitude(h1)
|
||||||
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {TaskFinal}, "Final Approach")
|
wp[#wp+1]=papp:WaypointAirTurningPoint("BARO", UTILS.KnotsToKmph(SpeedLand), {TaskFinal}, "Final Approach")
|
||||||
|
|
||||||
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
-- Okay, it looks like it's best to specify the coordinates not at the airbase but a bit away. This causes a more direct landing approach.
|
||||||
local pland=airbase:GetCoordinate():Translate(x2, runway.heading-180):SetAltitude(h2)
|
local pland=airbase:GetCoordinate():Translate(x2, rheading):SetAltitude(h2)
|
||||||
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
|
wp[#wp+1]=pland:WaypointAirLanding(UTILS.KnotsToKmph(SpeedLand), airbase, {}, "Landing")
|
||||||
|
|
||||||
elseif airbase:IsShip() or airbase:IsHelipad() then
|
elseif airbase:IsShip() or airbase:IsHelipad() then
|
||||||
|
|||||||
@@ -2265,7 +2265,7 @@ function LEGION:RecruitAssetsForMission(Mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight))
|
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight or 0))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -2745,7 +2745,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Now we have a long list with assets.
|
-- Now we have a long list with assets.
|
||||||
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false)
|
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight)
|
||||||
|
|
||||||
|
|
||||||
-- Get payloads for air assets.
|
-- Get payloads for air assets.
|
||||||
@@ -2770,7 +2770,7 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Now find the best asset for the given payloads.
|
-- Now find the best asset for the given payloads.
|
||||||
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, true)
|
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, true, TotalWeight)
|
||||||
|
|
||||||
-- Number of assets. At most NreqMax.
|
-- Number of assets. At most NreqMax.
|
||||||
local Nassets=math.min(#Assets, NreqMax)
|
local Nassets=math.min(#Assets, NreqMax)
|
||||||
@@ -3114,8 +3114,9 @@ end
|
|||||||
-- @param #string MissionType Mission type for which the best assets are desired.
|
-- @param #string MissionType Mission type for which the best assets are desired.
|
||||||
-- @param DCS#Vec2 TargetVec2 Target 2D vector.
|
-- @param DCS#Vec2 TargetVec2 Target 2D vector.
|
||||||
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
||||||
|
-- @param #number TotalWeight The total weight of the cargo to be transported, if applicable.
|
||||||
-- @return #number Mission score.
|
-- @return #number Mission score.
|
||||||
function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload)
|
function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
-- Mission score.
|
-- Mission score.
|
||||||
local score=0
|
local score=0
|
||||||
@@ -3209,8 +3210,18 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
|
|||||||
|
|
||||||
-- TRANSPORT specific.
|
-- TRANSPORT specific.
|
||||||
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
||||||
-- Add 1 score point for each 10 kg of cargo bay.
|
if TotalWeight then
|
||||||
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
-- Add 1 score point for each 10 kg of cargo bay capacity up to the total cargo weight,
|
||||||
|
-- and then subtract 1 score point for each excess 10kg of cargo bay capacity.
|
||||||
|
if asset.cargobaymax < TotalWeight then
|
||||||
|
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
||||||
|
else
|
||||||
|
score=score+UTILS.Round(TotalWeight/10, 0)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Add 1 score point for each 10 kg of cargo bay.
|
||||||
|
score=score+UTILS.Round(asset.cargobaymax/10, 0)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
-- TODO: This could be vastly improved. Need to gather ideas during testing.
|
||||||
@@ -3231,14 +3242,15 @@ end
|
|||||||
-- @param #string MissionType Mission type.
|
-- @param #string MissionType Mission type.
|
||||||
-- @param DCS#Vec2 TargetVec2 Target position as 2D vector.
|
-- @param DCS#Vec2 TargetVec2 Target position as 2D vector.
|
||||||
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
-- @param #boolean IncludePayload If `true`, include the payload in the calulation if the asset has one attached.
|
||||||
function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, IncludePayload)
|
-- @param #number TotalWeight The total weight of the cargo to be transported, if applicable.
|
||||||
|
function LEGION._OptimizeAssetSelection(assets, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
-- Calculate the mission score of all assets.
|
-- Calculate the mission score of all assets.
|
||||||
for _,_asset in pairs(assets) do
|
for _,_asset in pairs(assets) do
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
-- Calculate the asset score.
|
-- Calculate the asset score.
|
||||||
asset.score=LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload)
|
asset.score=LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, IncludePayload, TotalWeight)
|
||||||
|
|
||||||
if IncludePayload then
|
if IncludePayload then
|
||||||
|
|
||||||
|
|||||||
@@ -2322,14 +2322,17 @@ end
|
|||||||
-- @return #OPSGROUP self
|
-- @return #OPSGROUP self
|
||||||
function OPSGROUP:SetSRS(PathToSRS, Gender, Culture, Voice, Port, PathToGoogleKey, Label, Volume)
|
function OPSGROUP:SetSRS(PathToSRS, Gender, Culture, Voice, Port, PathToGoogleKey, Label, Volume)
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency, self.modulation)
|
local path = PathToSRS or MSRS.path
|
||||||
|
local port = Port or MSRS.port
|
||||||
|
self.msrs=MSRS:New(path, self.frequency, self.modulation)
|
||||||
self.msrs:SetGender(Gender)
|
self.msrs:SetGender(Gender)
|
||||||
self.msrs:SetCulture(Culture)
|
self.msrs:SetCulture(Culture)
|
||||||
self.msrs:SetVoice(Voice)
|
self.msrs:SetVoice(Voice)
|
||||||
self.msrs:SetPort(Port)
|
self.msrs:SetPort(port)
|
||||||
self.msrs:SetLabel(Label)
|
self.msrs:SetLabel(Label)
|
||||||
if PathToGoogleKey then
|
if PathToGoogleKey then
|
||||||
self.msrs:SetGoogle(PathToGoogleKey)
|
self.msrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
|
self.msrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
self.msrs:SetCoalition(self:GetCoalition())
|
self.msrs:SetCoalition(self:GetCoalition())
|
||||||
self.msrs:SetVolume(Volume)
|
self.msrs:SetVolume(Volume)
|
||||||
|
|||||||
@@ -605,6 +605,16 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActi
|
|||||||
self:AddCargoGroups(group, TransportZoneCombo, DisembarkActivation)
|
self:AddCargoGroups(group, TransportZoneCombo, DisembarkActivation)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Use FSM function to keep the SET up-to-date. Note that it overwrites the user FMS function, which cannot be used any more now.
|
||||||
|
local groupset=GroupSet --Core.Set#SET_OPSGROUP
|
||||||
|
function groupset.OnAfterAdded(groupset, From, Event, To, ObjectName, Object)
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Adding Cargo Group %s", tostring(ObjectName)))
|
||||||
|
self:AddCargoGroups(Object, TransportZoneCombo, DisembarkActivation, DisembarkZone, DisembarkCarriers)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
|
|||||||
@@ -1508,15 +1508,22 @@ function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,V
|
|||||||
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
||||||
self.BCModulation = self.Modulation
|
self.BCModulation = self.Modulation
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume)
|
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation)
|
||||||
self.SRS:SetCoalition(self.Coalition)
|
self.SRS:SetCoalition(self.Coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
self.SRS:SetCulture(self.Culture)
|
self.SRS:SetCulture(self.Culture)
|
||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVoice(self.Voice)
|
||||||
|
self.SRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.PathToGoogleKey)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.AwacsSRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
end
|
end
|
||||||
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
||||||
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
-- @module Ops.PlayerTask
|
-- @module Ops.PlayerTask
|
||||||
-- @image OPS_PlayerTask.jpg
|
-- @image OPS_PlayerTask.jpg
|
||||||
-- @date Last Update Oct 2023
|
-- @date Last Update Jan 2024
|
||||||
|
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -1552,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
|
|||||||
|
|
||||||
--- PLAYERTASK class version.
|
--- PLAYERTASK class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PLAYERTASKCONTROLLER.version="0.1.63"
|
PLAYERTASKCONTROLLER.version="0.1.64"
|
||||||
|
|
||||||
--- Create and run a new TASKCONTROLLER instance.
|
--- Create and run a new TASKCONTROLLER instance.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
@@ -3993,7 +3993,7 @@ function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Set SRS TTS details - see @{Sound.SRS} for details
|
--- [User] Set SRS TTS details - see @{Sound.SRS} for details.`SetSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #PLAYERTASKCONTROLLER self
|
-- @param #PLAYERTASKCONTROLLER self
|
||||||
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
|
-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
|
||||||
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
|
-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
|
||||||
@@ -4004,17 +4004,19 @@ end
|
|||||||
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS#SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS; if you use a config file for MSRS, hand in nil here.
|
||||||
|
-- @param #string AccessKey (Optional) Your Google API access key. This is necessary if DCS-gRPC is used as backend; if you use a config file for MSRS, hand in nil here.
|
||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate from which the controller radio is sending
|
-- @param Core.Point#COORDINATE Coordinate Coordinate from which the controller radio is sending
|
||||||
-- @return #PLAYERTASKCONTROLLER self
|
-- @return #PLAYERTASKCONTROLLER self
|
||||||
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Coordinate)
|
function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,AccessKey,Coordinate)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
||||||
self.Gender = Gender or "male" --
|
self.Gender = Gender or MSRS.gender or "male" --
|
||||||
self.Culture = Culture or "en-US" --
|
self.Culture = Culture or MSRS.culture or "en-US" --
|
||||||
self.Port = Port or 5002 --
|
self.Port = Port or MSRS.port or 5002 --
|
||||||
self.Voice = Voice --
|
self.Voice = Voice or MSRS.voice
|
||||||
self.PathToGoogleKey = PathToGoogleKey --
|
self.PathToGoogleKey = PathToGoogleKey --
|
||||||
|
self.AccessKey = AccessKey
|
||||||
self.Volume = Volume or 1.0 --
|
self.Volume = Volume or 1.0 --
|
||||||
self.UseSRS = true
|
self.UseSRS = true
|
||||||
self.Frequency = Frequency or {127,251} --
|
self.Frequency = Frequency or {127,251} --
|
||||||
@@ -4022,19 +4024,28 @@ function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Cultu
|
|||||||
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
|
||||||
self.BCModulation = self.Modulation
|
self.BCModulation = self.Modulation
|
||||||
-- set up SRS
|
-- set up SRS
|
||||||
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume)
|
self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation)
|
||||||
self.SRS:SetCoalition(self.Coalition)
|
self.SRS:SetCoalition(self.Coalition)
|
||||||
self.SRS:SetLabel(self.MenuName or self.Name)
|
self.SRS:SetLabel(self.MenuName or self.Name)
|
||||||
self.SRS:SetGender(self.Gender)
|
self.SRS:SetGender(self.Gender)
|
||||||
self.SRS:SetCulture(self.Culture)
|
self.SRS:SetCulture(self.Culture)
|
||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVoice(self.Voice)
|
self.SRS:SetVolume(self.Volume)
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetGoogle(self.PathToGoogleKey)
|
--self.SRS:SetGoogle(self.PathToGoogleKey)
|
||||||
|
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.AccessKey)
|
||||||
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
end
|
||||||
|
-- Pre-configured Google?
|
||||||
|
if (not PathToGoogleKey) and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
|
self.PathToGoogleKey = MSRS.poptions.gcloud.credentials
|
||||||
|
self.Voice = Voice or MSRS.poptions.gcloud.voice
|
||||||
|
self.AccessKey = AccessKey or MSRS.poptions.gcloud.key
|
||||||
end
|
end
|
||||||
if Coordinate then
|
if Coordinate then
|
||||||
self.SRS:SetCoordinate(Coordinate)
|
self.SRS:SetCoordinate(Coordinate)
|
||||||
end
|
end
|
||||||
|
self.SRS:SetVoice(self.Voice)
|
||||||
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
|
||||||
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
self.SRSQueue:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers)
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -183,8 +183,10 @@ end
|
|||||||
-- @param #number Port SRS port. Default 5002.
|
-- @param #number Port SRS port. Default 5002.
|
||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
function RADIOQUEUE:SetSRS(PathToSRS, Port)
|
function RADIOQUEUE:SetSRS(PathToSRS, Port)
|
||||||
self.msrs=MSRS:New(PathToSRS, self.frequency/1000000, self.modulation)
|
local path = PathToSRS or MSRS.path
|
||||||
self.msrs:SetPort(Port)
|
local port = Port or MSRS.port
|
||||||
|
self.msrs=MSRS:New(path, self.frequency/1000000, self.modulation)
|
||||||
|
self.msrs:SetPort(port)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -272,6 +272,13 @@ MSRS.Voices = {
|
|||||||
["Zira"] = "Microsoft Zira Desktop", -- en-US
|
["Zira"] = "Microsoft Zira Desktop", -- en-US
|
||||||
["Hortense"] = "Microsoft Hortense Desktop", --fr-FR
|
["Hortense"] = "Microsoft Hortense Desktop", --fr-FR
|
||||||
},
|
},
|
||||||
|
MicrosoftGRPC = {
|
||||||
|
["Hedda"] = "Hedda", -- de-DE
|
||||||
|
["Hazel"] = "Hazel", -- en-GB
|
||||||
|
["David"] = "David", -- en-US
|
||||||
|
["Zira"] = "Zira", -- en-US
|
||||||
|
["Hortense"] = "Hortense", --fr-FR
|
||||||
|
},
|
||||||
Google = {
|
Google = {
|
||||||
Standard = {
|
Standard = {
|
||||||
["en_AU_Standard_A"] = 'en-AU-Standard-A', -- [1] FEMALE
|
["en_AU_Standard_A"] = 'en-AU-Standard-A', -- [1] FEMALE
|
||||||
@@ -516,8 +523,20 @@ end
|
|||||||
-- @return #MSRS self
|
-- @return #MSRS self
|
||||||
function MSRS:SetBackend(Backend)
|
function MSRS:SetBackend(Backend)
|
||||||
self:F( {Backend=Backend} )
|
self:F( {Backend=Backend} )
|
||||||
self.backend=Backend or MSRS.Backend.SRSEXE
|
Backend = Backend or MSRS.Backend.SRSEXE -- avoid nil
|
||||||
|
local function Checker(back)
|
||||||
|
local ok = false
|
||||||
|
for _,_backend in pairs(MSRS.Backend) do
|
||||||
|
if tostring(back) == _backend then ok = true end
|
||||||
|
end
|
||||||
|
return ok
|
||||||
|
end
|
||||||
|
|
||||||
|
if Checker(Backend) then
|
||||||
|
self.backend=Backend
|
||||||
|
else
|
||||||
|
MESSAGE:New("ERROR: Backend "..tostring(Backend).." is not supported!",30,"MSRS",true):ToLog():ToAll()
|
||||||
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -906,12 +925,16 @@ end
|
|||||||
-- @param #string Provider
|
-- @param #string Provider
|
||||||
-- @return #MSRS self
|
-- @return #MSRS self
|
||||||
function MSRS:SetProvider(Provider)
|
function MSRS:SetProvider(Provider)
|
||||||
self:F( {Provider=Provider} )
|
BASE:F( {Provider=Provider} )
|
||||||
self.provider = Provider or MSRS.Provider.WINDOWS
|
if self then
|
||||||
return self
|
self.provider = Provider or MSRS.Provider.WINDOWS
|
||||||
|
return self
|
||||||
|
else
|
||||||
|
MSRS.provider = Provider or MSRS.Provider.WINDOWS
|
||||||
|
end
|
||||||
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get provider.
|
--- Get provider.
|
||||||
-- @param #MSRS self
|
-- @param #MSRS self
|
||||||
-- @return #MSRS self
|
-- @return #MSRS self
|
||||||
@@ -928,7 +951,7 @@ end
|
|||||||
-- @param #string Region Region to use.
|
-- @param #string Region Region to use.
|
||||||
-- @return #MSRS.ProviderOptions Provider optionas table.
|
-- @return #MSRS.ProviderOptions Provider optionas table.
|
||||||
function MSRS:SetProviderOptions(Provider, CredentialsFile, AccessKey, SecretKey, Region)
|
function MSRS:SetProviderOptions(Provider, CredentialsFile, AccessKey, SecretKey, Region)
|
||||||
self:F( {Provider, CredentialsFile, AccessKey, SecretKey, Region} )
|
BASE:F( {Provider, CredentialsFile, AccessKey, SecretKey, Region} )
|
||||||
local option=MSRS._CreateProviderOptions(Provider, CredentialsFile, AccessKey, SecretKey, Region)
|
local option=MSRS._CreateProviderOptions(Provider, CredentialsFile, AccessKey, SecretKey, Region)
|
||||||
|
|
||||||
if self then
|
if self then
|
||||||
@@ -1184,7 +1207,7 @@ end
|
|||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate.
|
||||||
-- @return #MSRS self
|
-- @return #MSRS self
|
||||||
function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
|
function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
|
||||||
self:F( {Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate} )
|
self:T({Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate} )
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay>0 then
|
||||||
self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
|
self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate)
|
||||||
@@ -1205,6 +1228,7 @@ function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture
|
|||||||
self:_ExecCommand(command)
|
self:_ExecCommand(command)
|
||||||
|
|
||||||
elseif self.backend==MSRS.Backend.GRPC then
|
elseif self.backend==MSRS.Backend.GRPC then
|
||||||
|
--BASE:I("MSRS.Backend.GRPC")
|
||||||
|
|
||||||
self:_DCSgRPCtts(Text, Frequencies, Gender, Culture, Voice, Volume, Label, Coordinate)
|
self:_DCSgRPCtts(Text, Frequencies, Gender, Culture, Voice, Volume, Label, Coordinate)
|
||||||
|
|
||||||
@@ -1593,7 +1617,7 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Moose MSRS default Config
|
-- -- Moose MSRS default Config
|
||||||
-- MSRS_Config = {
|
-- MSRS_Config = {
|
||||||
-- Path = C:\\Program Files\\DCS-SimpleRadio-Standalone, -- Path to SRS install directory.
|
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- Path to SRS install directory.
|
||||||
-- Port = 5002, -- Port of SRS server. Default 5002.
|
-- Port = 5002, -- Port of SRS server. Default 5002.
|
||||||
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
|
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
|
||||||
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
|
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
|
||||||
@@ -1606,7 +1630,6 @@ end
|
|||||||
-- Voice = "Microsoft Hazel Desktop", -- Voice that is used if no explicit provider voice is specified.
|
-- Voice = "Microsoft Hazel Desktop", -- Voice that is used if no explicit provider voice is specified.
|
||||||
-- Label = "MSRS",
|
-- Label = "MSRS",
|
||||||
-- Provider = "win", --Provider for generating TTS (win, gcloud, azure, aws).
|
-- Provider = "win", --Provider for generating TTS (win, gcloud, azure, aws).
|
||||||
--
|
|
||||||
-- -- Windows
|
-- -- Windows
|
||||||
-- win = {
|
-- win = {
|
||||||
-- voice = "Microsoft Hazel Desktop",
|
-- voice = "Microsoft Hazel Desktop",
|
||||||
@@ -1632,7 +1655,7 @@ end
|
|||||||
-- },
|
-- },
|
||||||
-- }
|
-- }
|
||||||
--
|
--
|
||||||
-- 3) The config file is automatically loaded when Moose starts. YOu can also load the config into the MSRS raw class manually before you do anything else:
|
-- 3) The config file is automatically loaded when Moose starts. You can also load the config into the MSRS raw class manually before you do anything else:
|
||||||
--
|
--
|
||||||
-- MSRS.LoadConfigFile() -- Note the "." here
|
-- MSRS.LoadConfigFile() -- Note the "." here
|
||||||
--
|
--
|
||||||
@@ -1648,8 +1671,7 @@ end
|
|||||||
-- 4) Use the config in your code like so, variable names are basically the same as in the config file, but all lower case, examples:
|
-- 4) Use the config in your code like so, variable names are basically the same as in the config file, but all lower case, examples:
|
||||||
--
|
--
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS(MSRS.path,nil,MSRS.google,243,radio.modulation.AM,nil,nil,
|
-- MESSAGE.SetMSRS(MSRS.path,MSRS.port,nil,127,rado.modulation.FM,nil,nil,nil,nil,nil,"TALK")
|
||||||
-- MSRS.Voices.Google.Standard.de_DE_Standard_B,coalition.side.BLUE)
|
|
||||||
--
|
--
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
--
|
--
|
||||||
@@ -1831,7 +1853,7 @@ end
|
|||||||
-- @param #MSRSQUEUE self
|
-- @param #MSRSQUEUE self
|
||||||
-- @return #MSRSQUEUE self The MSRSQUEUE object.
|
-- @return #MSRSQUEUE self The MSRSQUEUE object.
|
||||||
function MSRSQUEUE:Clear()
|
function MSRSQUEUE:Clear()
|
||||||
self:I(self.lid.."Clearing MSRSQUEUE")
|
self:T(self.lid.."Clearing MSRSQUEUE")
|
||||||
self.queue={}
|
self.queue={}
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1842,7 +1864,6 @@ end
|
|||||||
-- @param #MSRSQUEUE.Transmission transmission The transmission data table.
|
-- @param #MSRSQUEUE.Transmission transmission The transmission data table.
|
||||||
-- @return #MSRSQUEUE self
|
-- @return #MSRSQUEUE self
|
||||||
function MSRSQUEUE:AddTransmission(transmission)
|
function MSRSQUEUE:AddTransmission(transmission)
|
||||||
|
|
||||||
-- Init.
|
-- Init.
|
||||||
transmission.isplaying=false
|
transmission.isplaying=false
|
||||||
transmission.Tstarted=nil
|
transmission.Tstarted=nil
|
||||||
@@ -1921,20 +1942,20 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr
|
|||||||
transmission.Tplay=tstart or timer.getAbsTime()
|
transmission.Tplay=tstart or timer.getAbsTime()
|
||||||
transmission.subtitle=subtitle
|
transmission.subtitle=subtitle
|
||||||
transmission.interval=interval or 0
|
transmission.interval=interval or 0
|
||||||
transmission.frequency=frequency
|
transmission.frequency=frequency or msrs.frequencies
|
||||||
transmission.modulation=modulation
|
transmission.modulation=modulation or msrs.modulations
|
||||||
transmission.subgroups=subgroups
|
transmission.subgroups=subgroups
|
||||||
if transmission.subtitle then
|
if transmission.subtitle then
|
||||||
transmission.subduration=subduration or transmission.duration
|
transmission.subduration=subduration or transmission.duration
|
||||||
else
|
else
|
||||||
transmission.subduration=0 --nil
|
transmission.subduration=0 --nil
|
||||||
end
|
end
|
||||||
transmission.gender = gender
|
transmission.gender = gender or msrs.gender
|
||||||
transmission.culture = culture
|
transmission.culture = culture or msrs.culture
|
||||||
transmission.voice = voice
|
transmission.voice = voice or msrs.voice
|
||||||
transmission.volume = volume
|
transmission.volume = volume or msrs.volume
|
||||||
transmission.label = label
|
transmission.label = label or msrs.Label
|
||||||
transmission.coordinate = coordinate
|
transmission.coordinate = coordinate or msrs.coordinate
|
||||||
|
|
||||||
-- Add transmission to queue.
|
-- Add transmission to queue.
|
||||||
self:AddTransmission(transmission)
|
self:AddTransmission(transmission)
|
||||||
@@ -1946,6 +1967,7 @@ end
|
|||||||
-- @param #MSRSQUEUE self
|
-- @param #MSRSQUEUE self
|
||||||
-- @param #MSRSQUEUE.Transmission transmission The transmission.
|
-- @param #MSRSQUEUE.Transmission transmission The transmission.
|
||||||
function MSRSQUEUE:Broadcast(transmission)
|
function MSRSQUEUE:Broadcast(transmission)
|
||||||
|
self:T(self.lid.."Broadcast")
|
||||||
|
|
||||||
if transmission.frequency then
|
if transmission.frequency then
|
||||||
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label, transmission.coordinate)
|
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label, transmission.coordinate)
|
||||||
|
|||||||
@@ -691,7 +691,15 @@ function GROUP:GetUnits()
|
|||||||
local DCSUnits = DCSGroup:getUnits() or {}
|
local DCSUnits = DCSGroup:getUnits() or {}
|
||||||
local Units = {}
|
local Units = {}
|
||||||
for Index, UnitData in pairs( DCSUnits ) do
|
for Index, UnitData in pairs( DCSUnits ) do
|
||||||
Units[#Units+1] = UNIT:Find( UnitData )
|
|
||||||
|
local unit=UNIT:Find( UnitData )
|
||||||
|
if unit then
|
||||||
|
Units[#Units+1] = UNIT:Find( UnitData )
|
||||||
|
else
|
||||||
|
local UnitName=UnitData:getName()
|
||||||
|
unit=_DATABASE:AddUnit(UnitName)
|
||||||
|
Units[#Units+1]=unit
|
||||||
|
end
|
||||||
end
|
end
|
||||||
self:T3( Units )
|
self:T3( Units )
|
||||||
return Units
|
return Units
|
||||||
|
|||||||
@@ -5,37 +5,41 @@
|
|||||||
-- This method is used by Moose developers and not mission builders.
|
-- This method is used by Moose developers and not mission builders.
|
||||||
ModuleLoader = 'Scripts/Moose/Modules.lua'
|
ModuleLoader = 'Scripts/Moose/Modules.lua'
|
||||||
|
|
||||||
local f=io.open(ModuleLoader,"r")
|
if io then
|
||||||
if f~=nil then
|
local f=io.open(ModuleLoader,"r")
|
||||||
io.close(f)
|
if f~=nil then
|
||||||
|
io.close(f)
|
||||||
|
|
||||||
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
|
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
|
||||||
|
|
||||||
local base = _G
|
local base = _G
|
||||||
|
|
||||||
__Moose = {}
|
__Moose = {}
|
||||||
|
|
||||||
__Moose.Include = function( IncludeFile )
|
__Moose.Include = function( IncludeFile )
|
||||||
if not __Moose.Includes[ IncludeFile ] then
|
if not __Moose.Includes[ IncludeFile ] then
|
||||||
__Moose.Includes[IncludeFile] = IncludeFile
|
__Moose.Includes[IncludeFile] = IncludeFile
|
||||||
local f = assert( base.loadfile( IncludeFile ) )
|
local f = assert( base.loadfile( IncludeFile ) )
|
||||||
if f == nil then
|
if f == nil then
|
||||||
error ("Moose: Could not load Moose file " .. IncludeFile )
|
error ("Moose: Could not load Moose file " .. IncludeFile )
|
||||||
else
|
else
|
||||||
env.info( "Moose: " .. IncludeFile .. " dynamically loaded." )
|
env.info( "Moose: " .. IncludeFile .. " dynamically loaded." )
|
||||||
return f()
|
return f()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
__Moose.Includes = {}
|
||||||
|
|
||||||
|
__Moose.Include( 'Scripts/Moose/Modules.lua' )
|
||||||
|
BASE:TraceOnOff( true )
|
||||||
|
env.info( '*** MOOSE INCLUDE END *** ' )
|
||||||
|
|
||||||
|
-- Skip the static part of this file completly
|
||||||
|
do return end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
__Moose.Includes = {}
|
env.info( '*** MOOSE DYNAMIC INCLUDE NOT POSSIBLE (Desanitize io to use it) *** ' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Modules.lua' )
|
|
||||||
BASE:TraceOnOff( true )
|
|
||||||
env.info( '*** MOOSE INCLUDE END *** ' )
|
|
||||||
|
|
||||||
-- Skip the static part of this file completly
|
|
||||||
do return end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Individual Moose files are not found. Use the static code below.
|
-- Individual Moose files are not found. Use the static code below.
|
||||||
|
|||||||
Reference in New Issue
Block a user