Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank 2025-01-02 20:49:06 +01:00
commit eeca95c77f
20 changed files with 649 additions and 190 deletions

View File

@ -110,7 +110,7 @@ do -- COORDINATE
--
-- ## 4.4) Get the North correction of the current location.
--
-- * @{#COORDINATE.GetNorthCorrection}(): Obtains the north correction at the current 3D point.
-- * @{#COORDINATE.GetNorthCorrectionRadians}(): Obtains the north correction at the current 3D point.
--
-- ## 4.5) Point Randomization
--
@ -968,8 +968,10 @@ do -- COORDINATE
-- @return DCS#Distance Distance The distance in meters.
function COORDINATE:Get2DDistance(TargetCoordinate)
if not TargetCoordinate then return 1000000 end
local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
local norm=UTILS.VecNorm(a)
--local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
local a = self:GetVec2()
local b = TargetCoordinate:GetVec2()
local norm=UTILS.VecDist2D(a,b)
return norm
end
@ -1329,13 +1331,16 @@ do -- COORDINATE
-- @param Core.Settings#SETTINGS Settings
-- @param #string Language (Optional) Language "en" or "ru"
-- @param #boolean MagVar If true, also state angle in magnetic
-- @param #number Precision Rounding precision, defaults to 0
-- @return #string The BR Text
function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language, MagVar )
function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language, MagVar, Precision )
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
Precision = Precision or 0
local BearingText = self:GetBearingText( AngleRadians, 0, Settings, MagVar )
local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 )
local DistanceText = self:GetDistanceText( Distance, Settings, Language, Precision )
local BRText = BearingText .. DistanceText
@ -1957,9 +1962,18 @@ do -- COORDINATE
--- Smokes the point in a color.
-- @param #COORDINATE self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
function COORDINATE:Smoke( SmokeColor )
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
function COORDINATE:Smoke( SmokeColor, name )
self:F2( { SmokeColor } )
trigger.action.smoke( self:GetVec3(), SmokeColor )
self.firename = name or "Smoke-"..math.random(1,100000)
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
end
--- Stops smoking the point in a color.
-- @param #COORDINATE self
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
function COORDINATE:StopSmoke( name )
self:StopBigSmokeAndFire( name )
end
--- Smoke the COORDINATE Green.
@ -2900,12 +2914,13 @@ do -- COORDINATE
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
-- @param #boolean MagVar If true, also get angle in MagVar for BR/BRA
-- @param #number Precision Rounding precision, currently full km as default (=0)
-- @return #string The BR text.
function COORDINATE:ToStringBR( FromCoordinate, Settings, MagVar )
function COORDINATE:ToStringBR( FromCoordinate, Settings, MagVar, Precision )
local DirectionVec3 = FromCoordinate:GetDirectionVec3( self )
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
local Distance = self:Get2DDistance( FromCoordinate )
return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar )
return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar, Precision )
end
--- Return a BRA string from a COORDINATE to the COORDINATE.
@ -3313,9 +3328,8 @@ do -- COORDINATE
-- @param #COORDINATE self
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable to retrieve the settings from, otherwise the default settings will be chosen.
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
-- @param Tasking.Task#TASK Task The task for which coordinates need to be calculated.
-- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToString( Controllable, Settings, Task )
function COORDINATE:ToString( Controllable, Settings )
-- self:E( { Controllable = Controllable and Controllable:GetName() } )
@ -3323,6 +3337,7 @@ do -- COORDINATE
local ModeA2A = nil
--[[
if Task then
if Task:IsInstanceOf( TASK_A2A ) then
ModeA2A = true
@ -3339,7 +3354,7 @@ do -- COORDINATE
end
end
end
--]]
if ModeA2A == nil then
local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false

View File

@ -494,7 +494,7 @@ do -- SETTINGS
return (self.A2ASystem and self.A2ASystem == "MGRS") or (not self.A2ASystem and _SETTINGS:IsA2A_MGRS())
end
-- @param #SETTINGS self
--- @param #SETTINGS self
-- @param Wrapper.Group#GROUP MenuGroup Group for which to add menus.
-- @param #table RootMenu Root menu table
-- @return #SETTINGS
@ -948,49 +948,49 @@ do -- SETTINGS
return self
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:A2GMenuSystem( MenuGroup, RootMenu, A2GSystem )
self.A2GSystem = A2GSystem
MESSAGE:New( string.format( "Settings: Default A2G coordinate system set to %s for all players!", A2GSystem ), 5 ):ToAll()
self:SetSystemMenu( MenuGroup, RootMenu )
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:A2AMenuSystem( MenuGroup, RootMenu, A2ASystem )
self.A2ASystem = A2ASystem
MESSAGE:New( string.format( "Settings: Default A2A coordinate system set to %s for all players!", A2ASystem ), 5 ):ToAll()
self:SetSystemMenu( MenuGroup, RootMenu )
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuLL_DDM_Accuracy( MenuGroup, RootMenu, LL_Accuracy )
self.LL_Accuracy = LL_Accuracy
MESSAGE:New( string.format( "Settings: Default LL accuracy set to %s for all players!", LL_Accuracy ), 5 ):ToAll()
self:SetSystemMenu( MenuGroup, RootMenu )
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuMGRS_Accuracy( MenuGroup, RootMenu, MGRS_Accuracy )
self.MGRS_Accuracy = MGRS_Accuracy
MESSAGE:New( string.format( "Settings: Default MGRS accuracy set to %s for all players!", MGRS_Accuracy ), 5 ):ToAll()
self:SetSystemMenu( MenuGroup, RootMenu )
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuMWSystem( MenuGroup, RootMenu, MW )
self.Metric = MW
MESSAGE:New( string.format( "Settings: Default measurement format set to %s for all players!", MW and "Metric" or "Imperial" ), 5 ):ToAll()
self:SetSystemMenu( MenuGroup, RootMenu )
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuMessageTimingsSystem( MenuGroup, RootMenu, MessageType, MessageTime )
self:SetMessageTime( MessageType, MessageTime )
MESSAGE:New( string.format( "Settings: Default message time set for %s to %d.", MessageType, MessageTime ), 5 ):ToAll()
end
do
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupA2GSystem( PlayerUnit, PlayerGroup, PlayerName, A2GSystem )
--BASE:E( {PlayerUnit:GetName(), A2GSystem } )
self.A2GSystem = A2GSystem
@ -1001,7 +1001,7 @@ do -- SETTINGS
end
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupA2ASystem( PlayerUnit, PlayerGroup, PlayerName, A2ASystem )
self.A2ASystem = A2ASystem
MESSAGE:New( string.format( "Settings: A2A format set to %s for player %s.", A2ASystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
@ -1011,7 +1011,7 @@ do -- SETTINGS
end
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupLL_DDM_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, LL_Accuracy )
self.LL_Accuracy = LL_Accuracy
MESSAGE:New( string.format( "Settings: LL format accuracy set to %d decimal places for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
@ -1021,7 +1021,7 @@ do -- SETTINGS
end
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupMGRS_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, MGRS_Accuracy )
self.MGRS_Accuracy = MGRS_Accuracy
MESSAGE:New( string.format( "Settings: MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
@ -1031,7 +1031,7 @@ do -- SETTINGS
end
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupMWSystem( PlayerUnit, PlayerGroup, PlayerName, MW )
self.Metric = MW
MESSAGE:New( string.format( "Settings: Measurement format set to %s for player %s.", MW and "Metric" or "Imperial", PlayerName ), 5 ):ToGroup( PlayerGroup )
@ -1041,7 +1041,7 @@ do -- SETTINGS
end
end
-- @param #SETTINGS self
--- @param #SETTINGS self
function SETTINGS:MenuGroupMessageTimingsSystem( PlayerUnit, PlayerGroup, PlayerName, MessageType, MessageTime )
self:SetMessageTime( MessageType, MessageTime )
MESSAGE:New( string.format( "Settings: Default message time set for %s to %d.", MessageType, MessageTime ), 5 ):ToGroup( PlayerGroup )

View File

@ -118,7 +118,7 @@ AUTOLASE = {
--- AUTOLASE class version.
-- @field #string version
AUTOLASE.version = "0.1.25"
AUTOLASE.version = "0.1.26"
-------------------------------------------------------------------
-- Begin Functional.Autolase.lua
@ -757,9 +757,11 @@ function AUTOLASE:ShowStatus(Group,Unit)
end
local code = self:GetLaserCode(unit:GetName())
report:Add(string.format("Recce %s has code %d",name,code))
report:Add("---------------")
end
end
report:Add(string.format("Lasing min threat level %d",self.minthreatlevel))
report:Add("---------------")
local lines = 0
for _ind,_entry in pairs(self.CurrentLasing) do
local entry = _entry -- #AUTOLASE.LaserSpot
@ -779,7 +781,7 @@ function AUTOLASE:ShowStatus(Group,Unit)
if playername then
local settings = _DATABASE:GetPlayerSettings(playername)
if settings then
self:I("Get Settings ok!")
self:T("Get Settings ok!")
if settings:IsA2G_MGRS() then
locationstring = entry.coordinate:ToStringMGRS(settings)
elseif settings:IsA2G_LL_DMS() then
@ -789,12 +791,14 @@ function AUTOLASE:ShowStatus(Group,Unit)
end
end
end
local text = string.format("%s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
local text = string.format("+ %s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
report:Add(text)
report:Add("---------------")
lines = lines + 1
end
if lines == 0 then
report:Add("No targets!")
report:Add("---------------")
end
local reporttime = self.reporttimelong
if lines == 0 then reporttime = self.reporttimeshort end

View File

@ -22,7 +22,7 @@
-- @module Functional.Mantis
-- @image Functional.Mantis.jpg
--
-- Last Update: Sep 2024
-- Last Update: Jan 2025
-------------------------------------------------------------------------
--- **MANTIS** class, extends Core.Base#BASE
@ -663,7 +663,7 @@ do
-- TODO Version
-- @field #string version
self.version="0.8.20"
self.version="0.8.22"
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
--- FSM Functions ---
@ -860,7 +860,7 @@ do
self.AcceptZones = AcceptZones or {}
self.RejectZones = RejectZones or {}
self.ConflictZones = ConflictZones or {}
if #AcceptZones > 0 or #RejectZones > 0 or #ConflictZones > 0 then
if #self.AcceptZones > 0 or #self.RejectZones > 0 or #self.ConflictZones > 0 then
self.usezones = true
end
return self
@ -1287,9 +1287,9 @@ do
-- DEBUG
set = self:_PreFilterHeight(height)
end
local friendlyset -- Core.Set#SET_GROUP
if self.checkforfriendlies == true then
friendlyset = SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp) if grp and grp:InAir() then return true else return false end end):FilterOnce()
--self.friendlyset -- Core.Set#SET_GROUP
if self.checkforfriendlies == true and self.friendlyset == nil then
self.friendlyset = SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp) if grp and grp:InAir() then return true else return false end end):FilterStart()
end
for _,_coord in pairs (set) do
local coord = _coord -- get current coord to check
@ -1305,20 +1305,21 @@ do
zonecheck = self:_CheckCoordinateInZones(coord)
end
if self.verbose and self.debug then
local dectstring = coord:ToStringLLDMS()
local samstring = samcoordinate:ToStringLLDMS()
--local dectstring = coord:ToStringLLDMS()
local samstring = samcoordinate:ToStringMGRS({MGRS_Accuracy=0})
samstring = string.gsub(samstring,"%s","")
local inrange = "false"
if targetdistance <= rad then
inrange = "true"
end
local text = string.format("Checking SAM at %s | Targetdist %d | Rad %d | Inrange %s", samstring, targetdistance, rad, inrange)
local text = string.format("Checking SAM at %s | Tgtdist %.1fkm | Rad %.1fkm | Inrange %s", samstring, targetdistance/1000, rad/1000, inrange)
local m = MESSAGE:New(text,10,"Check"):ToAllIf(self.debug)
self:T(self.lid..text)
end
-- friendlies around?
local nofriendlies = true
if self.checkforfriendlies == true then
local closestfriend, distance = friendlyset:GetClosestGroup(samcoordinate)
local closestfriend, distance = self.friendlyset:GetClosestGroup(samcoordinate)
if closestfriend and distance and distance < rad then
nofriendlies = false
end
@ -1618,7 +1619,7 @@ do
--self:I({grpname,grprange, grpheight})
elseif type == MANTIS.SamType.SHORT then
table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind})
-- self:I({grpname,grprange, grpheight})
--self:I({grpname,grprange, grpheight})
self.ShoradGroupSet:Add(grpname,group)
if self.autoshorad then
self.Shorad.Groupset = self.ShoradGroupSet
@ -1677,9 +1678,9 @@ do
function MANTIS:_CheckLoop(samset,detset,dlink,limit)
self:T(self.lid .. "CheckLoop " .. #detset .. " Coordinates")
local switchedon = 0
local statusreport = REPORT:New("\nMANTIS Status")
local instatusred = 0
local instatusgreen = 0
local activeshorads = 0
local SEADactive = 0
for _,_data in pairs (samset) do
local samcoordinate = _data[2]
@ -1690,7 +1691,10 @@ do
local samgroup = GROUP:FindByName(name)
local IsInZone, Distance = self:_CheckObjectInZone(detset, samcoordinate, radius, height, dlink)
local suppressed = self.SuppressedGroups[name] or false
local activeshorad = self.Shorad.ActiveGroups[name] or false
local activeshorad = false
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
activeshorad = true
end
if IsInZone and not suppressed and not activeshorad then --check any target in zone and not currently managed by SEAD
if samgroup:IsAlive() then
-- switch on SAM
@ -1753,13 +1757,13 @@ do
instatusred=instatusred+1
end
end
statusreport:Add("+-----------------------------+")
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
statusreport:Add(string.format("+ SAM in GREEN State: %2d",instatusgreen))
statusreport:Add("+-----------------------------+")
MESSAGE:New(statusreport:Text(),10,nil,true):ToAll():ToLog()
if self.Shorad then
for _,_name in pairs(self.Shorad.ActiveGroups or {}) do
activeshorads=activeshorads+1
end
end
end
return self
return instatusred, instatusgreen, activeshorads
end
--- [Internal] Check detection function
@ -1777,6 +1781,9 @@ do
if rand > 65 then -- 1/3 of cases
self:_RefreshSAMTable()
end
local instatusred = 0
local instatusgreen = 0
local activeshorads = 0
-- switch SAMs on/off if (n)one of the detected groups is inside their reach
if self.automode then
local samset = self.SAM_Table_Long -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
@ -1784,10 +1791,21 @@ do
local samset = self.SAM_Table_Medium -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
self:_CheckLoop(samset,detset,dlink,self.maxmidrange)
local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
else
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
self:_CheckLoop(samset,detset,dlink,self.maxclassic)
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
end
if self.debug or self.verbose then
local statusreport = REPORT:New("\nMANTIS Status "..self.name)
statusreport:Add("+-----------------------------+")
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
statusreport:Add(string.format("+ SAM in GREEN State: %2d",instatusgreen))
if self.Shorad then
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
end
statusreport:Add("+-----------------------------+")
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
end
return self
end

View File

@ -19,7 +19,7 @@
--
-- ### Authors: **applevangelist**, **FlightControl**
--
-- Last Update: Oct 2024
-- Last Update: Dec 2024
--
-- ===
--
@ -80,6 +80,7 @@ SEAD = {
["AGM_122"] = "AGM_122",
["AGM_84"] = "AGM_84",
["AGM_45"] = "AGM_45",
["AGM_65"] = "AGM_65",
["ALARM"] = "ALARM",
["LD-10"] = "LD-10",
["X_58"] = "X_58",
@ -99,6 +100,7 @@ SEAD = {
-- km and mach
["AGM_88"] = { 150, 3},
["AGM_45"] = { 12, 2},
["AGM_65"] = { 16, 0.9},
["AGM_122"] = { 16.5, 2.3},
["AGM_84"] = { 280, 0.8},
["ALARM"] = { 45, 2},
@ -155,7 +157,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
self:AddTransition("*", "ManageEvasion", "*")
self:AddTransition("*", "CalculateHitZone", "*")
self:I("*** SEAD - Started Version 0.4.8")
self:I("*** SEAD - Started Version 0.4.9")
return self
end
@ -468,6 +470,7 @@ function SEAD:HandleEventShot( EventData )
local SEADWeaponName = EventData.WeaponName or "None" -- return weapon type
if self:_CheckHarms(SEADWeaponName) then
--UTILS.PrintTableToLog(EventData)
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
if not SEADPlane then return self end -- case IniUnit is empty
@ -493,7 +496,7 @@ function SEAD:HandleEventShot( EventData )
if not _target or self.debug then -- AGM-88 or 154 w/o target data
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
self:I("**** Tracking AGM-88/154 with no target data.")
self:T("**** Tracking AGM-88/154 with no target data.")
local pos0 = SEADPlane:GetCoordinate()
local fheight = SEADPlane:GetHeight()
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)

View File

@ -21,7 +21,7 @@
-- @image Functional.Shorad.jpg
--
-- Date: Nov 2021
-- Last Update: Nov 2023
-- Last Update: Jan 2025
-------------------------------------------------------------------------
--- **SHORAD** class, extends Core.Base#BASE
@ -521,7 +521,27 @@ do
-- go through set and find the one(s) to activate
local TDiff = 4
for _,_group in pairs (shoradset) do
if _group:IsAnyInZone(targetzone) then
local groupname = _group:GetName()
if groupname == TargetGroup then
-- Shot at a SHORAD group
if self.UseEmOnOff then
_group:EnableEmission(false)
end
_group:OptionAlarmStateGreen()
self.ActiveGroups[groupname] = nil
local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
--Shoot and Scoot
if self.shootandscoot then
self:__ShootAndScoot(1,_group)
end
elseif _group:IsAnyInZone(targetzone) then
-- shot at a group we protect
local text = string.format("Waking up SHORAD %s", _group:GetName())
self:T(text)
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
@ -529,7 +549,6 @@ do
_group:EnableEmission(true)
end
_group:OptionAlarmStateRed()
local groupname = _group:GetName()
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit

View File

@ -6089,7 +6089,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
terminal=parking[i].TerminalID
end
if self.Debug then
if self.Debug and terminal then
local text=string.format("Spawnplace unit %s terminal %d.", unit.name, terminal)
coord:MarkToAll(text)
env.info(text)
@ -8122,9 +8122,11 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
-- Debug output for occupied spots.
if self.Debug then
local coord=problem.coord --Core.Point#COORDINATE
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
self:I(self.lid..text)
coord:MarkToAll(string.format(text))
if coord then
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
self:I(self.lid..text)
coord:MarkToAll(text)
end
else
self:T(self.lid..string.format("Parking spot %d is occupied or not big enough!", _termid))
end

View File

@ -10,7 +10,7 @@ _SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.ScheduleDispatcher#SCHEDU
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
--- Settings
_SETTINGS = SETTINGS:Set()
_SETTINGS = SETTINGS:Set() -- Core.Settings#SETTINGS
_SETTINGS:SetPlayerMenuOn()
--- Register cargos.

View File

@ -17,7 +17,7 @@
-- ===
--
-- ### Author: **applevangelist**
-- @date Last Update Oct 2024
-- @date Last Update Dec 2024
-- @module Ops.AWACS
-- @image OPS_AWACS.jpg
@ -509,7 +509,7 @@ do
-- @field #AWACS
AWACS = {
ClassName = "AWACS", -- #string
version = "0.2.67", -- #string
version = "0.2.68", -- #string
lid = "", -- #string
coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string
@ -5922,6 +5922,7 @@ function AWACS:onafterStart(From, Event, To)
local AwacsAW = self.AirWing -- Ops.Airwing#AIRWING
local mission = AUFTRAG:NewORBIT_RACETRACK(self.OrbitZone:GetCoordinate(),self.AwacsAngels*1000,self.Speed,self.Heading,self.Leg)
mission:SetMissionRange(self.MaxMissionRange)
mission:SetRequiredAttribute({ GROUP.Attribute.AIR_AWACS }) -- prefered plane type, thanks to Heart8reaker
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
mission:SetTime(nil,timeonstation)
self.CatchAllMissions[#self.CatchAllMissions+1] = mission

View File

@ -1351,7 +1351,7 @@ CTLD.UnitTypeCapabilities = {
--- CTLD class version.
-- @field #string version
CTLD.version="1.1.20"
CTLD.version="1.1.22"
--- Instantiate a new CTLD.
-- @param #CTLD self
@ -2686,27 +2686,6 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
row = 1
startpos:Translate(6,heading,nil,true)
end
--[[
local initialSpacing = IsHerc and 16 or (capabilities.length+2) -- initial spacing of the first crates
local crateSpacing = 4 -- further spacing of remaining crates
local lateralSpacing = 4 -- lateral spacing of crates
local nrSideBySideCrates = 4 -- number of crates that are placed side-by-side
if cratesneeded == 1 then
-- single crate needed spawns straight ahead
cratedistance = initialSpacing
rheading = math.fmod((heading + addon), 360)
else
--if (i - 1) % nrSideBySideCrates == 0 then
cratedistance = i == 1 and initialSpacing or (cratedistance + crateSpacing)
angleOffNose = math.ceil(math.deg(math.atan(lateralSpacing / cratedistance)))
self:I("angleOffNose = "..angleOffNose)
rheading = heading + addon - angleOffNose
--else
-- rheading = heading + addon + angleOffNose
--end
end
--]]
end
--local cratevec2 = cratecoord:GetVec2()
@ -3514,7 +3493,7 @@ function CTLD:_UnloadTroops(Group, Unit)
if IsHerc then offset = self.TroopUnloadDistGroundHerc or 25 end
if IsHook then
offset = self.TroopUnloadDistGroundHook or 15
if self.TroopUnloadDistHoverHook then
if hoverunload and self.TroopUnloadDistHoverHook then
offset = self.TroopUnloadDistHoverHook or 5
end
end
@ -4288,6 +4267,7 @@ function CTLD:AddTroopsCargo(Name,Templates,Type,NoTroops,PerTroopMass,Stock,Sub
-- Troops are directly loadable
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,true,NoTroops,nil,nil,PerTroopMass,Stock, SubCategory)
table.insert(self.Cargo_Troops,cargo)
if SubCategory and self.usesubcats ~= true then self.usesubcats=true end
return self
end
@ -4324,6 +4304,7 @@ function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,Sub
cargo:SetStaticTypeAndShape(Category,TypeName,ShapeName)
end
table.insert(self.Cargo_Crates,cargo)
if SubCategory and self.usesubcats ~= true then self.usesubcats=true end
return self
end
@ -4350,6 +4331,7 @@ function CTLD:AddStaticsCargo(Name,Mass,Stock,SubCategory,DontShowInMenu,Locatio
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,template,type,false,false,1,nil,nil,Mass,Stock,SubCategory,DontShowInMenu,Location)
cargo:SetStaticResourceMap(ResourceMap)
table.insert(self.Cargo_Statics,cargo)
if SubCategory and self.usesubcats ~= true then self.usesubcats=true end
return cargo
end
@ -6127,7 +6109,7 @@ end
local statics = nil
local statics = {}
self:T(self.lid.."Bulding Statics Table for Saving")
self:T(self.lid.."Building Statics Table for Saving")
for _,_cargo in pairs (stcstable) do
local cargo = _cargo -- #CTLD_CARGO
local object = cargo:GetPositionable() -- Wrapper.Static#STATIC
@ -6162,7 +6144,7 @@ end
--local data = "LoadedData = {\n"
local data = "Group,x,y,z,CargoName,CargoTemplates,CargoType,CratesNeeded,CrateMass,Structure\n"
local data = "Group,x,y,z,CargoName,CargoTemplates,CargoType,CratesNeeded,CrateMass,Structure,StaticCategory,StaticType,StaticShape\n"
local n = 0
for _,_grp in pairs(grouptable) do
local group = _grp -- Wrapper.Group#GROUP
@ -6189,6 +6171,7 @@ end
local cgotype = cargo.CargoType
local cgoneed = cargo.CratesNeeded
local cgomass = cargo.PerCrateMass
local scat,stype,sshape = cargo:GetStaticTypeAndShape()
local structure = UTILS.GetCountPerTypeName(group)
local strucdata = ""
for typen,anzahl in pairs (structure) do
@ -6205,8 +6188,8 @@ end
end
local location = group:GetVec3()
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d,%s\n"
,template,location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass,strucdata)
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d,%s,%s,%s,%s\n"
,template,location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass,strucdata,scat,stype,sshape or "none")
data = data .. txt
end
end
@ -6231,8 +6214,9 @@ end
local cgomass = object.PerCrateMass
local crateobj = object.Positionable
local location = crateobj:GetVec3()
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d\n"
,"STATIC",location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass)
local scat,stype,sshape = object:GetStaticTypeAndShape()
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d,'none',%s,%s,%s\n"
,"STATIC",location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass,scat,stype,sshape or "none")
data = data .. txt
end
@ -6361,22 +6345,25 @@ end
for _id,_entry in pairs (loadeddata) do
local dataset = UTILS.Split(_entry,",")
-- 1=Group,2=x,3=y,4=z,5=CargoName,6=CargoTemplates,7=CargoType,8=CratesNeeded,9=CrateMass,10=Structure
-- 1=Group,2=x,3=y,4=z,5=CargoName,6=CargoTemplates,7=CargoType,8=CratesNeeded,9=CrateMass,10=Structure,11=StaticCategory,12=StaticType,13=StaticShape
local groupname = dataset[1]
local vec2 = {}
vec2.x = tonumber(dataset[2])
vec2.y = tonumber(dataset[4])
local cargoname = dataset[5]
local cargotemplates = dataset[6]
local cargotype = dataset[7]
local size = tonumber(dataset[8])
local mass = tonumber(dataset[9])
local StaticCategory = dataset[11]
local StaticType = dataset[12]
local StaticShape = dataset[13]
if type(groupname) == "string" and groupname ~= "STATIC" then
local cargotemplates = dataset[6]
cargotemplates = string.gsub(cargotemplates,"{","")
cargotemplates = string.gsub(cargotemplates,"}","")
cargotemplates = UTILS.Split(cargotemplates,";")
local size = tonumber(dataset[8])
local mass = tonumber(dataset[9])
local structure = nil
if dataset[10] then
if dataset[10] and dataset[10] ~= "none" then
structure = dataset[10]
structure = string.gsub(structure,",","")
end
@ -6384,15 +6371,13 @@ end
local dropzone = ZONE_RADIUS:New("DropZone",vec2,20)
if cargotype == CTLD_CARGO.Enum.VEHICLE or cargotype == CTLD_CARGO.Enum.FOB then
local injectvehicle = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
injectvehicle:SetStaticTypeAndShape(StaticCategory,StaticType,StaticShape)
self:InjectVehicles(dropzone,injectvehicle,self.surfacetypes,self.useprecisecoordloads,structure)
elseif cargotype == CTLD_CARGO.Enum.TROOPS or cargotype == CTLD_CARGO.Enum.ENGINEERS then
local injecttroops = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
self:InjectTroops(dropzone,injecttroops,self.surfacetypes,self.useprecisecoordloads,structure)
end
elseif (type(groupname) == "string" and groupname == "STATIC") or cargotype == CTLD_CARGO.Enum.REPAIR then
local cargotemplates = dataset[6]
local size = tonumber(dataset[8])
local mass = tonumber(dataset[9])
local dropzone = ZONE_RADIUS:New("DropZone",vec2,20)
local injectstatic = nil
if cargotype == CTLD_CARGO.Enum.VEHICLE or cargotype == CTLD_CARGO.Enum.FOB then
@ -6400,8 +6385,10 @@ end
cargotemplates = string.gsub(cargotemplates,"}","")
cargotemplates = UTILS.Split(cargotemplates,";")
injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
injectstatic:SetStaticTypeAndShape(StaticCategory,StaticType,StaticShape)
elseif cargotype == CTLD_CARGO.Enum.STATIC or cargotype == CTLD_CARGO.Enum.REPAIR then
injectstatic = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
injectstatic:SetStaticTypeAndShape(StaticCategory,StaticType,StaticShape)
local map=cargotype:GetStaticResourceMap()
injectstatic:SetStaticResourceMap(map)
end

View File

@ -1314,7 +1314,7 @@ function OPSZONE:EvaluateZone()
if Nblu>0 then
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
if not self:IsAttacked() and self.Tblu>=self.threatlevelCapture then
self:Attacked(coalition.side.BLUE)
end
@ -1366,7 +1366,7 @@ function OPSZONE:EvaluateZone()
if Nred>0 then
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
if not self:IsAttacked() and self.Tred>=self.threatlevelCapture then
-- Red is attacking blue zone.
self:Attacked(coalition.side.RED)
end

View File

@ -80,6 +80,7 @@
-- @field #boolean smokeownposition
-- @field #table SmokeOwn
-- @field #boolean smokeaveragetargetpos
-- @field #boolean reporttostringbullsonly
-- @extends Core.Fsm#FSM
---
@ -105,7 +106,7 @@ PLAYERRECCE = {
ClassName = "PLAYERRECCE",
verbose = true,
lid = nil,
version = "0.1.23",
version = "0.1.24",
ViewZone = {},
ViewZoneVisual = {},
ViewZoneLaser = {},
@ -133,7 +134,8 @@ PLAYERRECCE = {
TargetCache = nil,
smokeownposition = false,
SmokeOwn = {},
smokeaveragetargetpos = false,
smokeaveragetargetpos = true,
reporttostringbullsonly = true,
}
---
@ -236,6 +238,8 @@ function PLAYERRECCE:New(Name, Coalition, PlayerSet)
self.minthreatlevel = 0
self.reporttostringbullsonly = true
self.TForget = 600
self.TargetCache = FIFO:New()
@ -929,7 +933,8 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
if (not oldtarget) or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
-- lost LOS or dead
laser:LaseOff()
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
self:T(self.lid.."Target Life Points: "..target:GetLife() or "none")
if target:IsDead() or target:IsDestroyed() or target:GetDamage() > 79 or target:GetLife() <= 1 then
self:__Shack(-1,client,oldtarget)
--self.LaserTarget[playername] = nil
else
@ -1274,6 +1279,9 @@ self:T(self.lid.."_ReportLaserTargets")
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
if not self.ReferencePoint then
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
if self.reporttostringbullsonly ~= true then
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
end
else
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
end
@ -1317,8 +1325,14 @@ function PLAYERRECCE:_ReportVisualTargets(client,group,playername)
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
if not self.ReferencePoint then
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
if self.reporttostringbullsonly ~= true then
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
end
else
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
if self.reporttostringbullsonly ~= true then
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
end
end
report:Add(string.rep("-",15))
local text = report:Text()
@ -1552,6 +1566,16 @@ function PLAYERRECCE:SetMenuName(Name)
return self
end
--- [User] Set reporting to be BULLS only or BULLS plus playersettings based coordinate.
-- @param #PLAYERRECCE self
-- @param #boolean OnOff
-- @return #PLAYERRECCE self
function PLAYERRECCE:SetReportBullsOnly(OnOff)
self:T(self.lid.."SetReportBullsOnly: "..tostring(OnOff))
self.reporttostringbullsonly = OnOff
return self
end
--- [User] Enable smoking of own position
-- @param #PLAYERRECCE self
-- @return #PLAYERRECCE self

View File

@ -997,6 +997,8 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
-- Init status updates in 10 seconds.
self:__Status(10)
return self
end

View File

@ -963,6 +963,8 @@ function RESCUEHELO:onafterStart(From, Event, To)
-- Init status check
self:__Status(1)
return self
end
--- On after Status event. Checks player status.

View File

@ -318,11 +318,14 @@ MSRS.Voices = {
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- [6] MALE
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- [7] MALE
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- [8] FEMALE
["en_GB_Standard_A"] = 'en-GB-Standard-A', -- [9] FEMALE
["en_GB_Standard_B"] = 'en-GB-Standard-B', -- [10] MALE
["en_GB_Standard_C"] = 'en-GB-Standard-C', -- [11] FEMALE
["en_GB_Standard_D"] = 'en-GB-Standard-D', -- [12] MALE
["en_GB_Standard_F"] = 'en-GB-Standard-F', -- [13] FEMALE
-- 2025 changes
["en_GB_Standard_A"] = 'en-GB-Standard-N', -- [9] FEMALE
["en_GB_Standard_B"] = 'en-GB-Standard-O', -- [10] MALE
["en_GB_Standard_C"] = 'en-GB-Standard-N', -- [11] FEMALE
["en_GB_Standard_D"] = 'en-GB-Standard-O', -- [12] MALE
["en_GB_Standard_F"] = 'en-GB-Standard-N', -- [13] FEMALE
["en_GB_Standard_O"] = 'en-GB-Standard-O', -- [12] MALE
["en_GB_Standard_N"] = 'en-GB-Standard-N', -- [13] FEMALE
["en_US_Standard_A"] = 'en-US-Standard-A', -- [14] MALE
["en_US_Standard_B"] = 'en-US-Standard-B', -- [15] MALE
["en_US_Standard_C"] = 'en-US-Standard-C', -- [16] FEMALE
@ -333,25 +336,36 @@ MSRS.Voices = {
["en_US_Standard_H"] = 'en-US-Standard-H', -- [21] FEMALE
["en_US_Standard_I"] = 'en-US-Standard-I', -- [22] MALE
["en_US_Standard_J"] = 'en-US-Standard-J', -- [23] MALE
["fr_FR_Standard_A"] = "fr-FR-Standard-A", -- Female
["fr_FR_Standard_B"] = "fr-FR-Standard-B", -- Male
["fr_FR_Standard_C"] = "fr-FR-Standard-C", -- Female
["fr_FR_Standard_D"] = "fr-FR-Standard-D", -- Male
["fr_FR_Standard_E"] = "fr-FR-Standard-E", -- Female
["de_DE_Standard_A"] = "de-DE-Standard-A", -- Female
["de_DE_Standard_B"] = "de-DE-Standard-B", -- Male
["de_DE_Standard_C"] = "de-DE-Standard-C", -- Female
["de_DE_Standard_D"] = "de-DE-Standard-D", -- Male
["de_DE_Standard_E"] = "de-DE-Standard-E", -- Male
["de_DE_Standard_F"] = "de-DE-Standard-F", -- Female
["es_ES_Standard_A"] = "es-ES-Standard-A", -- Female
["es_ES_Standard_B"] = "es-ES-Standard-B", -- Male
["es_ES_Standard_C"] = "es-ES-Standard-C", -- Female
["es_ES_Standard_D"] = "es-ES-Standard-D", -- Female
["it_IT_Standard_A"] = "it-IT-Standard-A", -- Female
["it_IT_Standard_B"] = "it-IT-Standard-B", -- Female
["it_IT_Standard_C"] = "it-IT-Standard-C", -- Male
["it_IT_Standard_D"] = "it-IT-Standard-D", -- Male
-- 2025 catalog changes
["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female
["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male
["fr_FR_Standard_C"] = "fr-FR-Standard-F", -- Female
["fr_FR_Standard_D"] = "fr-FR-Standard-G", -- Male
["fr_FR_Standard_E"] = "fr-FR-Standard-F", -- Female
["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male
["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female
-- 2025 catalog changes
["de_DE_Standard_A"] = "de-DE-Standard-G", -- Female
["de_DE_Standard_B"] = "de-DE-Standard-H", -- Male
["de_DE_Standard_C"] = "de-DE-Standard-G", -- Female
["de_DE_Standard_D"] = "de-DE-Standard-H", -- Male
["de_DE_Standard_E"] = "de-DE-Standard-H", -- Male
["de_DE_Standard_F"] = "de-DE-Standard-G", -- Female
["de_DE_Standard_H"] = "de-DE-Standard-H", -- Male
["de_DE_Standard_G"] = "de-DE-Standard-G", -- Female
["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female
["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male
["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female
["es_ES_Standard_D"] = "es-ES-Standard-F", -- Male
["es_ES_Standard_E"] = "es-ES-Standard-E", -- Female
["es_ES_Standard_F"] = "es-ES-Standard-F", -- Male
-- 2025 catalog changes
["it_IT_Standard_A"] = "it-IT-Standard-E", -- Female
["it_IT_Standard_B"] = "it-IT-Standard-E", -- Female
["it_IT_Standard_C"] = "it-IT-Standard-F", -- Male
["it_IT_Standard_D"] = "it-IT-Standard-F", -- Male
["it_IT_Standard_E"] = "it-IT-Standard-E", -- Female
["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male
},
Wavenet = {
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- [1] FEMALE
@ -362,12 +376,15 @@ MSRS.Voices = {
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- [6] MALE
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- [7] MALE
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- [8] FEMALE
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-A', -- [9] FEMALE
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-B', -- [10] MALE
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-C', -- [11] FEMALE
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-D', -- [12] MALE
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-F', -- [13] FEMALE
["en_US_Wavenet_A"] = 'en-US-Wavenet-A', -- [14] MALE
-- 2025 changes
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-N', -- [9] FEMALE
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-O', -- [10] MALE
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-N', -- [11] FEMALE
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-O', -- [12] MALE
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-N', -- [13] FEMALE
["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE
["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE
["en_US_Wavenet_A"] = 'en-US-Wavenet-N', -- [14] MALE
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- [15] MALE
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- [16] FEMALE
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- [17] MALE
@ -377,24 +394,35 @@ MSRS.Voices = {
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- [21] FEMALE
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- [22] MALE
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- [23] MALE
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-A", -- Female
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-B", -- Male
["fr_FR_Wavenet_C"] = "fr-FR-Wavenet-C", -- Female
["fr_FR_Wavenet_D"] = "fr-FR-Wavenet-D", -- Male
["fr_FR_Wavenet_E"] = "fr-FR-Wavenet-E", -- Female
["de_DE_Wavenet_A"] = "de-DE-Wavenet-A", -- Female
["de_DE_Wavenet_B"] = "de-DE-Wavenet-B", -- Male
["de_DE_Wavenet_C"] = "de-DE-Wavenet-C", -- Female
["de_DE_Wavenet_D"] = "de-DE-Wavenet-D", -- Male
["de_DE_Wavenet_E"] = "de-DE-Wavenet-E", -- Male
["de_DE_Wavenet_F"] = "de-DE-Wavenet-F", -- Female
["es_ES_Wavenet_B"] = "es-ES-Wavenet-B", -- Male
["es_ES_Wavenet_C"] = "es-ES-Wavenet-C", -- Female
["es_ES_Wavenet_D"] = "es-ES-Wavenet-D", -- Female
["it_IT_Wavenet_A"] = "it-IT-Wavenet-A", -- Female
["it_IT_Wavenet_B"] = "it-IT-Wavenet-B", -- Female
["it_IT_Wavenet_C"] = "it-IT-Wavenet-C", -- Male
["it_IT_Wavenet_D"] = "it-IT-Wavenet-D", -- Male
-- 2025 catalog changes
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male
["fr_FR_Wavenet_C"] = "fr-FR-Wavenet-F", -- Female
["fr_FR_Wavenet_D"] = "fr-FR-Wavenet-G", -- Male
["fr_FR_Wavenet_E"] = "fr-FR-Wavenet-F", -- Female
["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male
["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female
-- 2025 catalog changes
["de_DE_Wavenet_A"] = "de-DE-Wavenet-G", -- Female
["de_DE_Wavenet_B"] = "de-DE-Wavenet-H", -- Male
["de_DE_Wavenet_C"] = "de-DE-Wavenet-G", -- Female
["de_DE_Wavenet_D"] = "de-DE-Wavenet-H", -- Male
["de_DE_Wavenet_E"] = "de-DE-Wavenet-H", -- Male
["de_DE_Wavenet_F"] = "de-DE-Wavenet-G", -- Female
["de_DE_Wavenet_H"] = "de-DE-Wavenet-H", -- Male
["de_DE_Wavenet_G"] = "de-DE-Wavenet-G", -- Female
["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male
["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female
["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female
["es_ES_Wavenet_E"] = "es-ES-Wavenet-E", -- Male
["es_ES_Wavenet_F"] = "es-ES-Wavenet-F", -- Female
-- 2025 catalog changes
["it_IT_Wavenet_A"] = "it-IT-Wavenet-E", -- Female
["it_IT_Wavenet_B"] = "it-IT-Wavenet-E", -- Female
["it_IT_Wavenet_C"] = "it-IT-Wavenet-F", -- Male
["it_IT_Wavenet_D"] = "it-IT-Wavenet-F", -- Male
["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female
["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male
} ,
},
}
@ -1634,9 +1662,9 @@ function MSRS:_DCSgRPCtts(Text, Frequencies, Gender, Culture, Voice, Volume, Lab
end
for _,freq in pairs(Frequencies) do
self:F("Calling GRPC.tts with the following parameter:")
self:F({ssml=ssml, freq=freq, options=options})
self:F(options.provider[provider])
self:T("Calling GRPC.tts with the following parameter:")
self:T({ssml=ssml, freq=freq, options=options})
self:T(options.provider[provider])
GRPC.tts(ssml, freq*1e6, options)
end

View File

@ -1196,17 +1196,17 @@ ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left_Door = {4,15,46,174}
ENUMS.Storage.weapons.UH1H.M60_MG_Left_Door = {4,15,46,176}
-- Kiowa
ENUMS.Storage.weapons.OH58.FIM92 = {4,4,7,449}
ENUMS.Storage.weapons.OH58.MG_M3P100 = {4,15,46,2608}
ENUMS.Storage.weapons.OH58.MG_M3P200 = {4,15,46,2607}
ENUMS.Storage.weapons.OH58.MG_M3P300 = {4,15,46,2606}
ENUMS.Storage.weapons.OH58.MG_M3P400 = {4,15,46,2605}
ENUMS.Storage.weapons.OH58.MG_M3P500 = {4,15,46,2604}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Blue = {4,5,9,486}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Green = {4,5,9,487}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Red = {4,5,9,485}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Violet = {4,5,9,488}
ENUMS.Storage.weapons.OH58.Smk_Grenade_White = {4,5,9,490}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Yellow = {4,5,9,489}
ENUMS.Storage.weapons.OH58.MG_M3P100 = {4,15,46,2611}
ENUMS.Storage.weapons.OH58.MG_M3P200 = {4,15,46,2610}
ENUMS.Storage.weapons.OH58.MG_M3P300 = {4,15,46,2609}
ENUMS.Storage.weapons.OH58.MG_M3P400 = {4,15,46,2608}
ENUMS.Storage.weapons.OH58.MG_M3P500 = {4,15,46,2607}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Blue = {4,5,9,488}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Green = {4,5,9,489}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Red = {4,5,9,487}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Violet = {4,5,9,490}
ENUMS.Storage.weapons.OH58.Smk_Grenade_White = {4,5,9,492}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Yellow = {4,5,9,491}
-- Apache
ENUMS.Storage.weapons.AH64D.AN_APG78 = {4,15,44,2138}
ENUMS.Storage.weapons.AH64D.Internal_Aux_FuelTank = {1,3,43,1700}

View File

@ -4204,3 +4204,123 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
return ReturnObjects, ADFName
end
--- Converts a Vec2 to a Vec3.
-- @param vec the 2D vector
-- @param y optional new y axis (altitude) value. If omitted it's 0.
function UTILS.Vec2toVec3(vec,y)
if not vec.z then
if vec.alt and not y then
y = vec.alt
elseif not y then
y = 0
end
return {x = vec.x, y = y, z = vec.y}
else
return {x = vec.x, y = vec.y, z = vec.z} -- it was already Vec3, actually.
end
end
--- Get the correction needed for true north in radians
-- @param gPoint The map point vec2 or vec3
-- @return number correction
function UTILS.GetNorthCorrection(gPoint)
local point = UTILS.DeepCopy(gPoint)
if not point.z then --Vec2; convert to Vec3
point.z = point.y
point.y = 0
end
local lat, lon = coord.LOtoLL(point)
local north_posit = coord.LLtoLO(lat + 1, lon)
return math.atan2(north_posit.z - point.z, north_posit.x - point.x)
end
--- Convert time in seconds to a DHMS table `{d = days, h = hours, m = minutes, s = seconds}`
-- @param timeInSec Time in Seconds
-- @return #table Table with DHMS data
function UTILS.GetDHMS(timeInSec)
if timeInSec and type(timeInSec) == 'number' then
local tbl = {d = 0, h = 0, m = 0, s = 0}
if timeInSec > 86400 then
while timeInSec > 86400 do
tbl.d = tbl.d + 1
timeInSec = timeInSec - 86400
end
end
if timeInSec > 3600 then
while timeInSec > 3600 do
tbl.h = tbl.h + 1
timeInSec = timeInSec - 3600
end
end
if timeInSec > 60 then
while timeInSec > 60 do
tbl.m = tbl.m + 1
timeInSec = timeInSec - 60
end
end
tbl.s = timeInSec
return tbl
else
BASE:E("No number handed!")
return
end
end
--- Returns heading-error corrected direction in radians.
-- True-north corrected direction from point along vector vec.
-- @param vec Vec3 Starting point
-- @param point Vec2 Direction
-- @return direction corrected direction from point.
function UTILS.GetDirectionRadians(vec, point)
local dir = math.atan2(vec.z, vec.x)
if point then
dir = dir + UTILS.GetNorthCorrection(point)
end
if dir < 0 then
dir = dir + 2 * math.pi -- put dir in range of 0 to 2*pi
end
return dir
end
--- Raycasting a point in polygon. Code from http://softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm
-- @param point Vec2 or Vec3 to test
-- @param #table poly Polygon Table of Vec2/3 point forming the Polygon
-- @param #number maxalt Altitude limit (optional)
-- @param #boolean outcome
function UTILS.IsPointInPolygon(point, poly, maxalt)
point = UTILS.Vec2toVec3(point)
local px = point.x
local pz = point.z
local cn = 0
local newpoly = UTILS.DeepCopy(poly)
if not maxalt or (point.y <= maxalt) then
local polysize = #newpoly
newpoly[#newpoly + 1] = newpoly[1]
newpoly[1] = UTILS.Vec2toVec3(newpoly[1])
for k = 1, polysize do
newpoly[k+1] = UTILS.Vec2toVec3(newpoly[k+1])
if ((newpoly[k].z <= pz) and (newpoly[k+1].z > pz)) or ((newpoly[k].z > pz) and (newpoly[k+1].z <= pz)) then
local vt = (pz - newpoly[k].z) / (newpoly[k+1].z - newpoly[k].z)
if (px < newpoly[k].x + vt*(newpoly[k+1].x - newpoly[k].x)) then
cn = cn + 1
end
end
end
return cn%2 == 1
else
return false
end
end
--- Vector scalar multiplication.
-- @param vec Vec3 vector to multiply
-- @param #number mult scalar multiplicator
-- @return Vec3 new vector multiplied with the given scalar
function UTILS.ScalarMult(vec, mult)
return {x = vec.x*mult, y = vec.y*mult, z = vec.z*mult}
end

View File

@ -791,6 +791,8 @@ AIRBASE.Sinai = {
-- * AIRBASE.Kola.Vuojarvi
-- * AIRBASE.Kola.Andoya
-- * AIRBASE.Kola.Alakourtti
-- * AIRBASE.Kola.Kittila
-- * AIRBASE.Kola.Bardufoss
--
-- @field Kola
AIRBASE.Kola = {
@ -814,6 +816,8 @@ AIRBASE.Kola = {
["Vuojarvi"] = "Vuojarvi",
["Andoya"] = "Andoya",
["Alakourtti"] = "Alakourtti",
["Kittila"] = "Kittila",
["Bardufoss"] = "Bardufoss",
}
--- Airbases of the Afghanistan map
@ -855,19 +859,19 @@ AIRBASE.Afghanistan = {
--- Airbases of the Iraq map
--
-- * `AIRBASE.Iraq.Baghdad_International_Airport` Baghdad International Airport
-- * `AIRBASE.Iraq.Sulaimaniyah_International_Airport` Sulaimaniyah International Airport
-- * `AIRBASE.Iraq.Al_Sahra_Airport` Al-Sahra Airport
-- * `AIRBASE.Iraq.Erbil_International_Airport` Erbil International Airport
-- * `AIRBASE.Iraq.Al_Taji_Airport` Al-Taji Airport
-- * `AIRBASE.Iraq.Al_Asad_Airbase` Al-Asad Airbase
-- * `AIRBASE.Iraq.Al_Salam_Airbase` Al-Salam Airbase
-- * `AIRBASE.Iraq.Balad_Airbase` Balad Airbase
-- * `AIRBASE.Iraq.Kirkuk_International_Airport` Kirkuk International Airport
-- * `AIRBASE.Iraq.Bashur_Airport` Bashur Airport
-- * `AIRBASE.Iraq.Al_Taquddum_Airport` Al-Taquddum Airport
-- * `AIRBASE.Iraq.Qayyarah_Airfield_West` Qayyarah Airfield West
-- * `AIRBASE.Iraq.K1_Base` K1 Base
-- * AIRBASE.Iraq.Baghdad_International_Airport
-- * AIRBASE.Iraq.Sulaimaniyah_International_Airport
-- * AIRBASE.Iraq.Al_Sahra_Airport
-- * AIRBASE.Iraq.Erbil_International_Airpor
-- * AIRBASE.Iraq.Al_Taji_Airport
-- * AIRBASE.Iraq.Al_Asad_Airbase
-- * AIRBASE.Iraq.Al_Salam_Airbase
-- * AIRBASE.Iraq.Balad_Airbase
-- * AIRBASE.Iraq.Kirkuk_International_Airport
-- * AIRBASE.Iraq.Bashur_Airport
-- * AIRBASE.Iraq.Al_Taquddum_Airport
-- * AIRBASE.Iraq.Qayyarah_Airfield_West
-- * AIRBASE.Iraq.K1_Base
--
-- @field Iraq
AIRBASE.Iraq = {

View File

@ -26,6 +26,7 @@
-- @field #string lid Class id string for output to DCS log file.
-- @field DCS#Warehouse warehouse The DCS warehouse object.
-- @field DCS#Airbase airbase The DCS airbase object.
-- @field Core.Timer#TIMER SaverTimer The TIMER for autosave.
-- @extends Core.Base#BASE
--- *The capitalist cannot store labour-power in warehouses after he has bought it, as he may do with the raw material.* -- Karl Marx
@ -128,6 +129,35 @@
--
-- The currently available weapon items are available in the `ENUMS.Storage.weapons`, e.g. `ENUMS.Storage.weapons.bombs.Mk_82Y`.
--
-- # Persistence
--
-- The contents of the storage can be saved to and read from disk. For this to function, `io` and `lfs` need to be desanitized in `MissionScripting.lua`.
--
-- ## Save once
--
-- ### To save once, e.g. this is sufficient:
--
-- -- Filenames created are the Filename given amended by "_Liquids", "_Aircraft" and "_Weapons" followed by a ".csv". Only Storage NOT set to unlimited will be saved.
-- local Path = "C:\\Users\\UserName\\Saved Games\\DCS\\Missions\\"
-- local Filename = "Batumi"
-- storage:SaveToFile(Path,Filename)
--
-- ### Autosave
--
-- storage:StartAutoSave(Path,Filename,300,true) -- save every 300 secs/5 mins starting in 5 mins, load the existing storage - if any - first if the last parameter is **not** `false`.
--
-- ### Stop Autosave
--
-- storage:StopAutoSave() -- stop the scheduler.
--
-- ### Load back with e.g.
--
-- -- Filenames searched for the Filename given amended by "_Liquids", "_Aircraft" and "_Weapons" followed by a ".csv". Only Storage NOT set to unlimited will be loaded.
-- local Path = "C:\\Users\\UserName\\Saved Games\\DCS\\Missions\\"
-- local Filename = "Batumi"
-- storage:LoadFromFile(Path,Filename)
--
--
-- @field #STORAGE
STORAGE = {
ClassName = "STORAGE",
@ -173,14 +203,14 @@ STORAGE.Type = {
--- STORAGE class version.
-- @field #string version
STORAGE.version="0.0.3"
STORAGE.version="0.1.4"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-- TODO: Persistence
-- DONE: Persistence
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@ -226,7 +256,7 @@ function STORAGE:NewFromStaticCargo(StaticCargoName)
return self
end
--- Create a new STORAGE object from an DCS static cargo object.
--- Create a new STORAGE object from a Wrapper.DynamicCargo#DYNAMICCARGO object.
-- @param #STORAGE self
-- @param #string DynamicCargoName Unit name of the dynamic cargo.
-- @return #STORAGE self
@ -235,7 +265,7 @@ function STORAGE:NewFromDynamicCargo(DynamicCargoName)
-- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New()) -- #STORAGE
self.airbase=Unit.getByName(DynamicCargoName)
self.airbase=Unit.getByName(DynamicCargoName) or StaticObject.getByName(DynamicCargoName)
if Airbase.getWarehouse then
self.warehouse=Warehouse.getCargoAsWarehouse(self.airbase)
@ -266,6 +296,10 @@ end
-- @return #STORAGE self
function STORAGE:SetVerbosity(VerbosityLevel)
self.verbose=VerbosityLevel or 0
if self.verbose > 1 then
BASE:TraceOn()
BASE:TraceClass("STORAGE")
end
return self
end
@ -499,7 +533,7 @@ function STORAGE:IsUnlimited(Type)
end
-- Debug info.
self:I(self.lid..string.format("Type=%s: unlimited=%s (N=%d n=%d)", tostring(Type), tostring(unlimited), N, n))
self:T(self.lid..string.format("Type=%s: unlimited=%s (N=%d n=%d)", tostring(Type), tostring(unlimited), N, n))
end
return unlimited
@ -595,6 +629,201 @@ function STORAGE:GetInventory(Item)
return inventory.aircraft, inventory.liquids, inventory.weapon
end
--- Save the contents of a STORAGE to files in CSV format. Filenames created are the Filename given amended by "_Liquids", "_Aircraft" and "_Weapons" followed by a ".csv". Requires io and lfs to be desanitized to be working.
-- @param #STORAGE self
-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems.
-- @param #string Filename The base name of the files. Existing files will be overwritten.
-- @return #STORAGE self
function STORAGE:SaveToFile(Path,Filename)
if not io then
BASE:E("ERROR: io not desanitized. Can't save the files.")
return false
end
-- Check default path.
if Path==nil and not lfs then
BASE:E("WARNING: lfs not desanitized. File will be saved in DCS installation root directory rather than your given path.")
end
local ac, lq, wp = self:GetInventory()
local DataAircraft = ""
local DataLiquids = ""
local DataWeapons = ""
if #lq > 0 then
DataLiquids = DataLiquids .."Liquids in Storage:\n"
for key,amount in pairs(lq) do
DataLiquids = DataLiquids..tostring(key).."="..tostring(amount).."\n"
end
--self:I(DataLiquids)
UTILS.SaveToFile(Path,Filename.."_Liquids.csv",DataLiquids)
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Saving Liquids to "..tostring(Path).."\\"..tostring(Filename).."_Liquids.csv")
end
end
if UTILS.TableLength(ac) > 0 then
DataAircraft = DataAircraft .."Aircraft in Storage:\n"
for key,amount in pairs(ac) do
DataAircraft = DataAircraft..tostring(key).."="..tostring(amount).."\n"
end
--self:I(DataAircraft)
UTILS.SaveToFile(Path,Filename.."_Aircraft.csv",DataAircraft)
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Saving Aircraft to "..tostring(Path).."\\"..tostring(Filename).."_Aircraft.csv")
end
end
if UTILS.TableLength(wp) > 0 then
DataWeapons = DataWeapons .."Weapons and Materiel in Storage:\n"
for key,amount in pairs(wp) do
DataWeapons = DataWeapons..tostring(key).."="..tostring(amount).."\n"
end
-- Gazelle table keys
for key,amount in pairs(ENUMS.Storage.weapons.Gazelle) do
amount = self:GetItemAmount(ENUMS.Storage.weapons.Gazelle[key])
DataWeapons = DataWeapons.."ENUMS.Storage.weapons.Gazelle."..tostring(key).."="..tostring(amount).."\n"
end
-- CH47
for key,amount in pairs(ENUMS.Storage.weapons.CH47) do
amount = self:GetItemAmount(ENUMS.Storage.weapons.CH47[key])
DataWeapons = DataWeapons.."ENUMS.Storage.weapons.CH47."..tostring(key).."="..tostring(amount).."\n"
end
-- UH1H
for key,amount in pairs(ENUMS.Storage.weapons.UH1H) do
amount = self:GetItemAmount(ENUMS.Storage.weapons.UH1H[key])
DataWeapons = DataWeapons.."ENUMS.Storage.weapons.UH1H."..tostring(key).."="..tostring(amount).."\n"
end
-- OH58D
for key,amount in pairs(ENUMS.Storage.weapons.OH58) do
amount = self:GetItemAmount(ENUMS.Storage.weapons.OH58[key])
DataWeapons = DataWeapons.."ENUMS.Storage.weapons.OH58."..tostring(key).."="..tostring(amount).."\n"
end
-- AH64D
for key,amount in pairs(ENUMS.Storage.weapons.AH64D) do
amount = self:GetItemAmount(ENUMS.Storage.weapons.AH64D[key])
DataWeapons = DataWeapons.."ENUMS.Storage.weapons.AH64D."..tostring(key).."="..tostring(amount).."\n"
end
--self:I(DataAircraft)
UTILS.SaveToFile(Path,Filename.."_Weapons.csv",DataWeapons)
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Saving Weapons to "..tostring(Path).."\\"..tostring(Filename).."_Weapons.csv")
end
end
return self
end
--- Load the contents of a STORAGE from files. Filenames searched for are the Filename given amended by "_Liquids", "_Aircraft" and "_Weapons" followed by a ".csv". Requires io and lfs to be desanitized to be working.
-- @param #STORAGE self
-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems.
-- @param #string Filename The name of the file.
-- @return #STORAGE self
function STORAGE:LoadFromFile(Path,Filename)
if not io then
BASE:E("ERROR: io not desanitized. Can't read the files.")
return false
end
-- Check default path.
if Path==nil and not lfs then
BASE:E("WARNING: lfs not desanitized. File will be read from DCS installation root directory rather than your give path.")
end
--Liquids
if self:IsLimitedLiquids() then
local Ok,Liquids = UTILS.LoadFromFile(Path,Filename.."_Liquids.csv")
if Ok then
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Loading Liquids from "..tostring(Path).."\\"..tostring(Filename).."_Liquids.csv")
end
for _id,_line in pairs(Liquids) do
if string.find(_line,"Storage") == nil then
local tbl=UTILS.Split(_line,"=")
local lqno = tonumber(tbl[1])
local lqam = tonumber(tbl[2])
self:SetLiquid(lqno,lqam)
end
end
else
self:E("File for Liquids could not be found: "..tostring(Path).."\\"..tostring(Filename"_Liquids.csv"))
end
end
--Aircraft
if self:IsLimitedAircraft() then
local Ok,Aircraft = UTILS.LoadFromFile(Path,Filename.."_Aircraft.csv")
if Ok then
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Loading Aircraft from "..tostring(Path).."\\"..tostring(Filename).."_Aircraft.csv")
end
for _id,_line in pairs(Aircraft) do
if string.find(_line,"Storage") == nil then
local tbl=UTILS.Split(_line,"=")
local acname = tbl[1]
local acnumber = tonumber(tbl[2])
self:SetAmount(acname,acnumber)
end
end
else
self:E("File for Aircraft could not be found: "..tostring(Path).."\\"..tostring(Filename"_Aircraft.csv"))
end
end
--Weapons
if self:IsLimitedWeapons() then
local Ok,Weapons = UTILS.LoadFromFile(Path,Filename.."_Weapons.csv")
if Ok then
if self.verbose and self.verbose > 0 then
self:I(self.lid.."Loading _eapons from "..tostring(Path).."\\"..tostring(Filename).."_Weapons.csv")
end
for _id,_line in pairs(Weapons) do
if string.find(_line,"Storage") == nil then
local tbl=UTILS.Split(_line,"=")
local wpname = tbl[1]
local wpnumber = tonumber(tbl[2])
self:SetAmount(wpname,wpnumber)
end
end
else
self:E("File for Weapons could not be found: "..tostring(Path).."\\"..tostring(Filename"_Weapons.csv"))
end
end
return self
end
--- Start a STORAGE autosave process.
-- @param #STORAGE self
-- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems.
-- @param #string Filename The name of the file.
-- @param #number Interval The interval, start after this many seconds and repeat every interval seconds. Defaults to 300.
-- @param #boolean LoadOnce If LoadOnce is true or nil, we try to load saved storage first.
-- @return #STORAGE self
function STORAGE:StartAutoSave(Path,Filename,Interval,LoadOnce)
if LoadOnce ~= false then
self:LoadFromFile(Path,Filename)
end
local interval = Interval or 300
self.SaverTimer = TIMER:New(STORAGE.SaveToFile,self,Path,Filename)
self.SaverTimer:Start(interval,interval)
return self
end
--- Stop a running STORAGE autosave process.
-- @param #STORAGE self
-- @return #STORAGE self
function STORAGE:StopAutoSave()
if self.SaverTimer and self.SaverTimer:IsRunning() then
self.SaverTimer:Stop()
self.SaverTimer = nil
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -127,6 +127,7 @@ function UNIT:Register( UnitName )
local group = unit:getGroup()
if group then
self.GroupName=group:getName()
self.groupId = group:getID()
end
self.DCSUnit = unit
end