diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index db54e8dc2..dec6bd64c 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -1271,7 +1271,11 @@ end -- @param #string ClientName Name of the Client. -- @return #number Coalition ID. function DATABASE:GetCoalitionFromClientTemplate( ClientName ) - return self.Templates.ClientsByName[ClientName].CoalitionID + if self.Templates.ClientsByName[ClientName] then + return self.Templates.ClientsByName[ClientName].CoalitionID + end + self:E("ERROR: Template does not exist for client "..tostring(ClientName)) + return nil end --- Get category ID from client name. @@ -1279,7 +1283,11 @@ end -- @param #string ClientName Name of the Client. -- @return #number Category ID. function DATABASE:GetCategoryFromClientTemplate( ClientName ) - return self.Templates.ClientsByName[ClientName].CategoryID + if self.Templates.ClientsByName[ClientName] then + return self.Templates.ClientsByName[ClientName].CategoryID + end + self:E("ERROR: Template does not exist for client "..tostring(ClientName)) + return nil end --- Get country ID from client name. @@ -1287,7 +1295,11 @@ end -- @param #string ClientName Name of the Client. -- @return #number Country ID. function DATABASE:GetCountryFromClientTemplate( ClientName ) - return self.Templates.ClientsByName[ClientName].CountryID + if self.Templates.ClientsByName[ClientName] then + return self.Templates.ClientsByName[ClientName].CountryID + end + self:E("ERROR: Template does not exist for client "..tostring(ClientName)) + return nil end --- Airbase diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 929e368a5..875d71ce8 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -2233,7 +2233,7 @@ do -- COORDINATE -- local MarkGroup = GROUP:FindByName( "AttackGroup" ) -- local MarkID = TargetCoord:MarkToGroup( "This is a target for the attack group", AttackGroup ) -- <<< logic >>> - -- RemoveMark( MarkID ) -- The mark is now removed + -- TargetCoord:RemoveMark( MarkID ) -- The mark is now removed function COORDINATE:RemoveMark( MarkID ) trigger.action.removeMark( MarkID ) end diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 43812c1e1..ca82b1ada 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -4729,8 +4729,11 @@ do -- SET_CLIENT local MClientCoalition = false for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName ) + if ClientCoalitionID==nil and MClient:IsAlive()~=nil then + ClientCoalitionID=MClient:GetCoalition() + end self:T3( { "Coalition:", ClientCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } ) - if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionID then + if self.FilterMeta.Coalitions[CoalitionName] and ClientCoalitionID and self.FilterMeta.Coalitions[CoalitionName] == ClientCoalitionID then MClientCoalition = true end end @@ -4742,8 +4745,11 @@ do -- SET_CLIENT local MClientCategory = false for CategoryID, CategoryName in pairs( self.Filter.Categories ) do local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName ) + if ClientCategoryID==nil and MClient:IsAlive()~=nil then + ClientCategoryID=MClient:GetCategory() + end self:T3( { "Category:", ClientCategoryID, self.FilterMeta.Categories[CategoryName], CategoryName } ) - if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == ClientCategoryID then + if self.FilterMeta.Categories[CategoryName] and ClientCategoryID and self.FilterMeta.Categories[CategoryName] == ClientCategoryID then MClientCategory = true end end @@ -4767,8 +4773,11 @@ do -- SET_CLIENT local MClientCountry = false for CountryID, CountryName in pairs( self.Filter.Countries ) do local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName ) + if ClientCountryID==nil and MClient:IsAlive()~=nil then + ClientCountryID=MClient:GetCountry() + end self:T3( { "Country:", ClientCountryID, country.id[CountryName], CountryName } ) - if country.id[CountryName] and country.id[CountryName] == ClientCountryID then + if country.id[CountryName] and ClientCountryID and country.id[CountryName] == ClientCountryID then MClientCountry = true end end diff --git a/Moose Development/Moose/Core/UserFlag.lua b/Moose Development/Moose/Core/UserFlag.lua index 5ed5d6cd7..1c47e787f 100644 --- a/Moose Development/Moose/Core/UserFlag.lua +++ b/Moose Development/Moose/Core/UserFlag.lua @@ -58,7 +58,7 @@ do -- UserFlag --- Set the userflag to a given Number. -- @param #USERFLAG self - -- @param #number Number The number value to be checked if it is the same as the userflag. + -- @param #number Number The number value to set the flag to. -- @param #number Delay Delay in seconds, before the flag is set. -- @return #USERFLAG The userflag instance. -- @usage @@ -104,4 +104,4 @@ do -- UserFlag end -end \ No newline at end of file +end diff --git a/Moose Development/Moose/Functional/Artillery.lua b/Moose Development/Moose/Functional/Artillery.lua index 7425d3212..c1745cac0 100644 --- a/Moose Development/Moose/Functional/Artillery.lua +++ b/Moose Development/Moose/Functional/Artillery.lua @@ -45,6 +45,7 @@ -- @field #table currentMove Holds the current commanded move, if there is one assigned. -- @field #number Nammo0 Initial amount total ammunition (shells+rockets+missiles) of the whole group. -- @field #number Nshells0 Initial amount of shells of the whole group. +-- @field #number Narty0 Initial amount of artillery shells of the whole group. -- @field #number Nrockets0 Initial amount of rockets of the whole group. -- @field #number Nmissiles0 Initial amount of missiles of the whole group. -- @field #number Nukes0 Initial amount of tactical nukes of the whole group. Default is 0. @@ -415,7 +416,7 @@ -- arty set, battery "Paladin Alpha", rearming place -- -- Setting the rearming group is independent of the position of the mark. Just create one anywhere on the map and type --- arty set, battery "Mortar Bravo", rearming group "Ammo Truck M818" +-- arty set, battery "Mortar Bravo", rearming group "Ammo Truck M939" -- Note that the name of the rearming group has to be given in quotation marks and spelt exactly as the group name defined in the mission editor. -- -- ## Transporting @@ -453,7 +454,7 @@ -- -- Creat a new ARTY object from a Paladin group. -- paladin=ARTY:New(GROUP:FindByName("Blue Paladin")) -- --- -- Define a rearming group. This is a Transport M818 truck. +-- -- Define a rearming group. This is a Transport M939 truck. -- paladin:SetRearmingGroup(GROUP:FindByName("Blue Ammo Truck")) -- -- -- Set the max firing range. A Paladin unit has a range of 20 km. @@ -694,7 +695,7 @@ ARTY.db={ --- Arty script version. -- @field #string version -ARTY.version="1.3.0" +ARTY.version="1.3.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -707,7 +708,7 @@ ARTY.version="1.3.0" -- DONE: Add user defined rearm weapon types. -- DONE: Check if target is in range. Maybe this requires a data base with the ranges of all arty units. -- DONE: Make ARTY move to rearming position. --- DONE: Check that right rearming vehicle is specified. Blue M818, Red Ural-375. Are there more? +-- DONE: Check that right rearming vehicle is specified. Blue M939, Red Ural-375. Are there more? -- DONE: Check if ARTY group is still alive. -- DONE: Handle dead events. -- DONE: Abort firing task if no shooting event occured with 5(?) minutes. Something went wrong then. Min/max range for example. @@ -1532,7 +1533,7 @@ end --- Assign a group, which is responsible for rearming the ARTY group. If the group is too far away from the ARTY group it will be guided towards the ARTY group. -- @param #ARTY self --- @param Wrapper.Group#GROUP group Group that is supposed to rearm the ARTY group. For the blue coalition, this is often a unarmed M818 transport whilst for red an unarmed Ural-375 transport can be used. +-- @param Wrapper.Group#GROUP group Group that is supposed to rearm the ARTY group. For the blue coalition, this is often a unarmed M939 transport whilst for red an unarmed Ural-375 transport can be used. -- @return self function ARTY:SetRearmingGroup(group) self:F({group=group}) @@ -1887,7 +1888,7 @@ function ARTY:onafterStart(Controllable, From, Event, To) MESSAGE:New(text, 5):ToAllIf(self.Debug) -- Get Ammo. - self.Nammo0, self.Nshells0, self.Nrockets0, self.Nmissiles0=self:GetAmmo(self.Debug) + self.Nammo0, self.Nshells0, self.Nrockets0, self.Nmissiles0, self.Narty0=self:GetAmmo(self.Debug) -- Init nuclear explosion parameters if they were not set by user. if self.nukerange==nil then @@ -2093,7 +2094,7 @@ function ARTY:_StatusReport(display) end -- Get Ammo. - local Nammo, Nshells, Nrockets, Nmissiles=self:GetAmmo() + local Nammo, Nshells, Nrockets, Nmissiles, Narty=self:GetAmmo() local Nnukes=self.Nukes local Nillu=self.Nillu local Nsmoke=self.Nsmoke @@ -2106,7 +2107,7 @@ function ARTY:_StatusReport(display) text=text..string.format("Clock = %s\n", Clock) text=text..string.format("FSM state = %s\n", self:GetState()) text=text..string.format("Total ammo count = %d\n", Nammo) - text=text..string.format("Number of shells = %d\n", Nshells) + text=text..string.format("Number of shells = %d\n", Narty) text=text..string.format("Number of rockets = %d\n", Nrockets) text=text..string.format("Number of missiles = %d\n", Nmissiles) text=text..string.format("Number of nukes = %d\n", Nnukes) @@ -2293,7 +2294,7 @@ function ARTY:OnEventShot(EventData) end -- Get current ammo. - local _nammo,_nshells,_nrockets,_nmissiles=self:GetAmmo() + local _nammo,_nshells,_nrockets,_nmissiles,_narty=self:GetAmmo() -- Decrease available nukes because we just fired one. if self.currentTarget.weapontype==ARTY.WeaponType.TacticalNukes then @@ -2323,7 +2324,7 @@ function ARTY:OnEventShot(EventData) -- Weapon type name for current target. local _weapontype=self:_WeaponTypeName(self.currentTarget.weapontype) - self:T(self.lid..string.format("Group %s ammo: total=%d, shells=%d, rockets=%d, missiles=%d", self.groupname, _nammo, _nshells, _nrockets, _nmissiles)) + self:T(self.lid..string.format("Group %s ammo: total=%d, shells=%d, rockets=%d, missiles=%d", self.groupname, _nammo, _narty, _nrockets, _nmissiles)) self:T(self.lid..string.format("Group %s uses weapontype %s for current target.", self.groupname, _weapontype)) -- Default switches for cease fire and relocation. @@ -2771,7 +2772,7 @@ function ARTY:onafterStatus(Controllable, From, Event, To) self:_EventFromTo("onafterStatus", Event, From, To) -- Get ammo. - local nammo, nshells, nrockets, nmissiles=self:GetAmmo() + local nammo, nshells, nrockets, nmissiles, narty=self:GetAmmo() -- We have a cargo group ==> check if group was loaded into a carrier. if self.iscargo and self.cargogroup then @@ -2788,7 +2789,7 @@ function ARTY:onafterStatus(Controllable, From, Event, To) -- FSM state. local fsmstate=self:GetState() - self:T(self.lid..string.format("Status %s, Ammo total=%d: shells=%d [smoke=%d, illu=%d, nukes=%d*%.3f kT], rockets=%d, missiles=%d", fsmstate, nammo, nshells, self.Nsmoke, self.Nillu, self.Nukes, self.nukewarhead/1000000, nrockets, nmissiles)) + self:T(self.lid..string.format("Status %s, Ammo total=%d: shells=%d [smoke=%d, illu=%d, nukes=%d*%.3f kT], rockets=%d, missiles=%d", fsmstate, nammo, narty, self.Nsmoke, self.Nillu, self.Nukes, self.nukewarhead/1000000, nrockets, nmissiles)) if self.Controllable and self.Controllable:IsAlive() then @@ -2871,20 +2872,19 @@ function ARTY:onafterStatus(Controllable, From, Event, To) if self.currentTarget then self:CeaseFire(self.currentTarget) end - - -- Open fire on timed target. - self:OpenFire(_timedTarget) - + + if self:is("CombatReady") then + -- Open fire on timed target. + self:OpenFire(_timedTarget) + end elseif _normalTarget then - - -- Open fire on normal target. - self:OpenFire(_normalTarget) - + + if self:is("CombatReady") then + -- Open fire on normal target. + self:OpenFire(_normalTarget) + end end - -- Get ammo. - --local nammo, nshells, nrockets, nmissiles=self:GetAmmo() - -- Check if we have a target in the queue for which weapons are still available. local gotsome=false if #self.targets>0 then @@ -3045,14 +3045,14 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target) local range=Controllable:GetCoordinate():Get2DDistance(target.coord) -- Get ammo. - local Nammo, Nshells, Nrockets, Nmissiles=self:GetAmmo() - local nfire=Nammo + local Nammo, Nshells, Nrockets, Nmissiles, Narty=self:GetAmmo() + local nfire=Narty local _type="shots" if target.weapontype==ARTY.WeaponType.Auto then - nfire=Nammo + nfire=Narty _type="shots" elseif target.weapontype==ARTY.WeaponType.Cannon then - nfire=Nshells + nfire=Narty _type="shells" elseif target.weapontype==ARTY.WeaponType.TacticalNukes then nfire=self.Nukes @@ -3337,7 +3337,7 @@ function ARTY:_CheckRearmed() self:F2() -- Get current ammo. - local nammo,nshells,nrockets,nmissiles=self:GetAmmo() + local nammo,nshells,nrockets,nmissiles,narty=self:GetAmmo() -- Number of units still alive. local units=self.Controllable:GetUnits() @@ -3603,7 +3603,11 @@ function ARTY:_FireAtCoord(coord, radius, nshells, weapontype) if weapontype==ARTY.WeaponType.TacticalNukes or weapontype==ARTY.WeaponType.IlluminationShells or weapontype==ARTY.WeaponType.SmokeShells then weapontype=ARTY.WeaponType.Cannon end - + + if group:HasTask() then + group:ClearTasks() + end + -- Set ROE to weapon free. group:OptionROEOpenFire() @@ -3614,7 +3618,7 @@ function ARTY:_FireAtCoord(coord, radius, nshells, weapontype) local fire=group:TaskFireAtPoint(vec2, radius, nshells, weapontype) -- Execute task. - group:SetTask(fire) + group:SetTask(fire,1) end --- Set task for attacking a group. @@ -3631,7 +3635,11 @@ function ARTY:_AttackGroup(target) if weapontype==ARTY.WeaponType.TacticalNukes or weapontype==ARTY.WeaponType.IlluminationShells or weapontype==ARTY.WeaponType.SmokeShells then weapontype=ARTY.WeaponType.Cannon end - + + if group:HasTask() then + group:ClearTasks() + end + -- Set ROE to weapon free. group:OptionROEOpenFire() @@ -3642,7 +3650,7 @@ function ARTY:_AttackGroup(target) local fire=group:TaskAttackGroup(targetgroup, weapontype, AI.Task.WeaponExpend.ONE, 1) -- Execute task. - group:SetTask(fire) + group:SetTask(fire,1) end @@ -3915,6 +3923,7 @@ end -- @return #number Number of shells the group has left. -- @return #number Number of rockets the group has left. -- @return #number Number of missiles the group has left. +-- @return #number Number of artillery shells the group has left. function ARTY:GetAmmo(display) self:F3({display=display}) @@ -3928,6 +3937,7 @@ function ARTY:GetAmmo(display) local nshells=0 local nrockets=0 local nmissiles=0 + local nartyshells=0 -- Get all units. local units=self.Controllable:GetUnits() @@ -4030,7 +4040,8 @@ function ARTY:GetAmmo(display) -- Add up all shells. nshells=nshells+Nammo - + local _,_,_,_,_,shells = unit:GetAmmunition() + nartyshells=nartyshells+shells -- Debug info. text=text..string.format("- %d shells of type %s\n", Nammo, _weaponName) @@ -4076,7 +4087,7 @@ function ARTY:GetAmmo(display) -- Total amount of ammunition. nammo=nshells+nrockets+nmissiles - return nammo, nshells, nrockets, nmissiles + return nammo, nshells, nrockets, nmissiles, nartyshells end --- Returns a name of a missile category. @@ -4827,7 +4838,10 @@ function ARTY:_CheckShootingStarted() -- Check if we waited long enough and no shot was fired. --if dt > self.WaitForShotTime and self.Nshots==0 then - if dt > self.WaitForShotTime and (self.Nshots==0 or self.currentTarget.nshells >= self.Nshots) then --https://github.com/FlightControl-Master/MOOSE/issues/1356 + + self:T(string.format("dt = %d WaitTime = %d | shots = %d TargetShells = %d",dt,self.WaitForShotTime,self.Nshots,self.currentTarget.nshells)) + + if (dt > self.WaitForShotTime and self.Nshots==0) or (self.currentTarget.nshells <= self.Nshots) then --https://github.com/FlightControl-Master/MOOSE/issues/1356 -- Debug info. self:T(self.lid..string.format("%s, no shot event after %d seconds. Removing current target %s from list.", self.groupname, self.WaitForShotTime, name)) @@ -4889,7 +4903,7 @@ end function ARTY:_CheckOutOfAmmo(targets) -- Get current ammo. - local _nammo,_nshells,_nrockets,_nmissiles=self:GetAmmo() + local _nammo,_nshells,_nrockets,_nmissiles,_narty=self:GetAmmo() -- Special weapon type requested ==> Check if corresponding ammo is empty. local _partlyoutofammo=false @@ -4901,7 +4915,7 @@ function ARTY:_CheckOutOfAmmo(targets) self:T(self.lid..string.format("Group %s, auto weapon requested for target %s but all ammo is empty.", self.groupname, Target.name)) _partlyoutofammo=true - elseif Target.weapontype==ARTY.WeaponType.Cannon and _nshells==0 then + elseif Target.weapontype==ARTY.WeaponType.Cannon and _narty==0 then self:T(self.lid..string.format("Group %s, cannons requested for target %s but shells empty.", self.groupname, Target.name)) _partlyoutofammo=true @@ -4945,14 +4959,14 @@ end function ARTY:_CheckWeaponTypeAvailable(target) -- Get current ammo of group. - local Nammo, Nshells, Nrockets, Nmissiles=self:GetAmmo() + local Nammo, Nshells, Nrockets, Nmissiles, Narty=self:GetAmmo() -- Check if enough ammo is there for the selected weapon type. local nfire=Nammo if target.weapontype==ARTY.WeaponType.Auto then nfire=Nammo elseif target.weapontype==ARTY.WeaponType.Cannon then - nfire=Nshells + nfire=Narty elseif target.weapontype==ARTY.WeaponType.TacticalNukes then nfire=self.Nukes elseif target.weapontype==ARTY.WeaponType.IlluminationShells then diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 686bede21..7a3253bac 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -7946,10 +7946,12 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) local clients=_DATABASE.CLIENTS for clientname, client in pairs(clients) do local template=_DATABASE:GetGroupTemplateFromUnitName(clientname) - local units=template.units - for i,unit in pairs(units) do - local coord=COORDINATE:New(unit.x, unit.alt, unit.y) - coords[unit.name]=coord + if template then + local units=template.units + for i,unit in pairs(units) do + local coord=COORDINATE:New(unit.x, unit.alt, unit.y) + coords[unit.name]=coord + end end end end diff --git a/Moose Development/Moose/Ops/ATIS.lua b/Moose Development/Moose/Ops/ATIS.lua index e6469713b..2c68b127c 100644 --- a/Moose Development/Moose/Ops/ATIS.lua +++ b/Moose Development/Moose/Ops/ATIS.lua @@ -63,6 +63,8 @@ -- @field #number power Radio power in Watts. Default 100 W. -- @field Sound.RadioQueue#RADIOQUEUE radioqueue Radio queue for broadcasing messages. -- @field #string soundpath Path to sound files. +-- @field #string soundpathAirports Path to airport names sound files. +-- @field #string soundpathNato Path to NATO alphabet sound files. -- @field #string relayunitname Name of the radio relay unit. -- @field #table towerfrequency Table with tower frequencies. -- @field #string activerunway The active runway specified by the user. @@ -315,18 +317,18 @@ -- atis:Start() -- -- This uses a male voice with US accent. It requires SRS to be installed in the `D:\DCS\_SRS\` directory. Note that backslashes need to be escaped or simply use slashes (as in linux). --- --- ### SRS can use multiple frequencies: --- +-- +-- ### SRS can use multiple frequencies: +-- -- atis=ATIS:New("Batumi", {305,103.85}, {radio.modulation.AM,radio.modulation.FM}) -- atis:SetSRS("D:\\DCS\\_SRS\\", "male", "en-US") -- atis:Start() --- +-- -- ### SRS Localization --- +-- -- You can localize the SRS output, all you need is to provide a table of translations and set the `locale` of your instance. You need to provide the translations in your script **before you instantiate your ATIS**. -- The German localization (already provided in the code) e.g. looks like follows: --- +-- -- ATIS.Messages.DE = -- { -- HOURS = "Uhr", @@ -387,13 +389,13 @@ -- FARP = "Farp", -- DELIMITER = "Komma", -- decimal delimiter -- } --- +-- -- Then set up your ATIS and set the locale: --- +-- -- atis=ATIS:New("Batumi", 305, radio.modulation.AM) -- atis:SetSRS("D:\\DCS\\_SRS\\", "female", "de_DE") -- atis:SetLocale("de") -- available locales from source are "en", "de" and "es" --- atis:Start() +-- atis:Start() -- -- ## FARPS -- @@ -1081,12 +1083,24 @@ function ATIS:SetLocale(locale) return self end ---- Set sound files folder within miz file. +--- Set sound files folder within miz file (not your local hard drive!). -- @param #ATIS self --- @param #string path Path for sound files. Default "ATIS Soundfiles/". Mind the slash "/" at the end! +-- @param #string pathMain Path to folder containing main sound files. Default "ATIS Soundfiles/". Mind the slash "/" at the end! +-- @param #string pathAirports Path folder containing the airport names sound files. Default is `"ATIS Soundfiles/"`, *e.g.* `"ATIS Soundfiles/Caucasus/"`. +-- @param #string pathNato Path folder containing the NATO alphabet sound files. Default is "ATIS Soundfiles/NATO Alphabet/". -- @return #ATIS self -function ATIS:SetSoundfilesPath( path ) - self.soundpath = tostring( path or "ATIS Soundfiles/" ) +function ATIS:SetSoundfilesPath( pathMain, pathAirports, pathNato ) + self.soundpath = tostring( pathMain or "ATIS Soundfiles/" ) + if pathAirports==nil then + self.soundpathAirports=self.soundpath..env.mission.theatre.."/" + else + self.soundpathAirports=pathAirports + end + if pathNato==nil then + self.soundpathNato=self.soundpath.."NATO Alphabet/" + else + self.soundpathNato=pathNato + end self:T( self.lid .. string.format( "Setting sound files path to %s", self.soundpath ) ) return self end @@ -1111,23 +1125,23 @@ function ATIS:SetSoundfilesInfoFile( csvfile ) -- Read csv file local data=UTILS.ReadCSV(csvfile) - + if data then for i,sound in pairs(data) do - + -- Get the ATIS.Soundfile local soundfile=getSound(sound.filename..".ogg") --#ATIS.Soundfile - + if soundfile then - + -- Set duration soundfile.duration=tonumber(sound.duration) else self:E(string.format("ERROR: Could not get info for sound file %s", sound.filename)) end - + end else self:E(string.format("ERROR: Could not read sound csv file!")) @@ -1587,13 +1601,13 @@ end function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey) --if PathToSRS or MSRS.path then self.useSRS=true - + local path = PathToSRS or MSRS.path local gender = Gender or MSRS.gender local culture = Culture or MSRS.culture 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) @@ -1958,7 +1972,7 @@ function ATIS:onafterBroadcast( From, Event, To ) -------------------------- --- Sunrise and Sunset --- -------------------------- - + local hours = self.gettext:GetEntry("HOURS",self.locale) local sunrise = coord:GetSunrise() sunrise = UTILS.Split( sunrise, ":" ) @@ -2059,10 +2073,45 @@ function ATIS:onafterBroadcast( From, Event, To ) -- Cloud preset (DCS 2.7) local cloudspreset = clouds.preset or "Nothing" + env.info("FF cloud preset "..cloudspreset) + -- Precepitation: 0=None, 1=Rain, 2=Thunderstorm, 3=Snow, 4=Snowstorm. local precepitation = 0 - if cloudspreset:find( "Preset10" ) then + if cloudspreset:find( "RainyPreset1" ) then + -- Overcast + Rain + clouddens = 9 + if temperature > 5 then + precepitation = 1 -- rain + else + precepitation = 3 -- snow + end + elseif cloudspreset:find( "RainyPreset2" ) then + -- Overcast + Rain + clouddens = 9 + if temperature > 5 then + precepitation = 1 -- rain + else + precepitation = 3 -- snow + end + elseif cloudspreset:find( "RainyPreset3" ) then + -- Overcast + Rain + clouddens = 9 + if temperature > 5 then + precepitation = 1 -- rain + else + precepitation = 3 -- snow + end + env.info("Fprecipt "..precepitation) + elseif cloudspreset:find( "RainyPreset" ) then + -- Overcast + Rain + clouddens = 9 + if temperature > 5 then + precepitation = 1 -- rain + else + precepitation = 3 -- snow + end + elseif cloudspreset:find( "Preset10" ) then -- Scattered 5 clouddens = 4 elseif cloudspreset:find( "Preset11" ) then @@ -2143,38 +2192,8 @@ function ATIS:onafterBroadcast( From, Event, To ) elseif cloudspreset:find( "Preset9" ) then -- Scattered 4 clouddens = 4 - elseif cloudspreset:find( "RainyPreset" ) then - -- Overcast + Rain - clouddens = 9 - if temperature > 5 then - precepitation = 1 -- rain - else - precepitation = 3 -- snow - end - elseif cloudspreset:find( "RainyPreset1" ) then - -- Overcast + Rain - clouddens = 9 - if temperature > 5 then - precepitation = 1 -- rain - else - precepitation = 3 -- snow - end - elseif cloudspreset:find( "RainyPreset2" ) then - -- Overcast + Rain - clouddens = 9 - if temperature > 5 then - precepitation = 1 -- rain - else - precepitation = 3 -- snow - end - elseif cloudspreset:find( "RainyPreset3" ) then - -- Overcast + Rain - clouddens = 9 - if temperature > 5 then - precepitation = 1 -- rain - else - precepitation = 3 -- snow - end + else + self:E(string.format("WARNING! Unknown weather preset: %s", tostring(cloudspreset))) end local CLOUDBASE = string.format( "%d", UTILS.MetersToFeet( cloudbase ) ) @@ -2249,7 +2268,7 @@ function ATIS:onafterBroadcast( From, Event, To ) end if not self.useSRS then --self:I(string.format( "%s/%s.ogg", self.theatre, self.airbasename )) - self.radioqueue:NewTransmission( string.format( "%s/%s.ogg", self.theatre, self.airbasename ), 3.0, self.soundpath, nil, nil, subtitle, self.subduration ) + self.radioqueue:NewTransmission( string.format( "%s.ogg", self.airbasename ), 3.0, self.soundpathAirports, nil, nil, subtitle, self.subduration ) end local alltext = subtitle @@ -2260,7 +2279,7 @@ function ATIS:onafterBroadcast( From, Event, To ) local _INFORMATION = subtitle if not self.useSRS then self:Transmission( self.Sound.Information, 0.5, subtitle ) - self.radioqueue:NewTransmission( string.format( "NATO Alphabet/%s.ogg", NATO ), 0.75, self.soundpath ) + self.radioqueue:NewTransmission( string.format( "%s.ogg", NATO ), 0.75, self.soundpathNato ) end alltext = alltext .. ";\n" .. subtitle @@ -2616,9 +2635,9 @@ function ATIS:onafterBroadcast( From, Event, To ) -- Active runway. local subtitle = "" if runwayLanding then - + local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale) - + subtitle=string.format("%s %s", actrun, runwayLanding) if rwyLandingLeft==true then subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale) @@ -2636,13 +2655,13 @@ function ATIS:onafterBroadcast( From, Event, To ) self:Transmission(self.Sound.Right, 0.2) end end - + end - + if runwayTakeoff then - + local actrun = self.gettext:GetEntry("ACTIVERUN",self.locale) - + subtitle=string.format("%s %s", actrun, runwayTakeoff) if rwyTakeoffLeft==true then subtitle=subtitle.." "..self.gettext:GetEntry("LEFT",self.locale) @@ -2650,7 +2669,7 @@ function ATIS:onafterBroadcast( From, Event, To ) subtitle=subtitle.." "..self.gettext:GetEntry("RIGHT",self.locale) end alltext = alltext .. ";\n" .. subtitle - + if not self.useSRS then self:Transmission(self.Sound.ActiveRunwayDeparture, 1.0, subtitle) self.radioqueue:Number2Transmission(runwayTakeoff) @@ -2660,8 +2679,8 @@ function ATIS:onafterBroadcast( From, Event, To ) self:Transmission(self.Sound.Right, 0.2) end end - - + + end _RUNACT = subtitle alltext = alltext .. ";\n" .. subtitle @@ -2710,14 +2729,14 @@ function ATIS:onafterBroadcast( From, Event, To ) alltext = alltext .. ";\n" .. subtitle end end - + -- Airfield elevation if self.elevation then - + local elev = self.gettext:GetEntry("ELEVATION",self.locale) local meters = self.gettext:GetEntry("METERS",self.locale) local feet = self.gettext:GetEntry("FEET",self.locale) - + local elevation = self.airbase:GetHeight() if not self.metric then elevation = UTILS.MetersToFeet( elevation ) @@ -2875,7 +2894,7 @@ function ATIS:onafterBroadcast( From, Event, To ) if not self.useSRS then self:Transmission( self.Sound.TACANChannel, 1.0, subtitle ) self.radioqueue:Number2Transmission( tostring( self.tacan ), nil, 0.2 ) - self.radioqueue:NewTransmission( "NATO Alphabet/Xray.ogg", 0.75, self.soundpath, nil, 0.2 ) + self.radioqueue:NewTransmission( "Xray.ogg", 0.75, self.soundpathNato, nil, 0.2 ) end alltext = alltext .. ";\n" .. subtitle end @@ -2916,7 +2935,7 @@ function ATIS:onafterBroadcast( From, Event, To ) subtitle = string.format( "%s %s", advtxt, NATO ) if not self.useSRS then self:Transmission( self.Sound.AdviceOnInitial, 0.5, subtitle ) - self.radioqueue:NewTransmission( string.format( "NATO Alphabet/%s.ogg", NATO ), 0.75, self.soundpath ) + self.radioqueue:NewTransmission( string.format( "%s.ogg", NATO ), 0.75, self.soundpathNato ) end alltext = alltext .. ";\n" .. subtitle @@ -2955,8 +2974,8 @@ function ATIS:onafterReport( From, Event, To, Text ) local emes = self.gettext:GetEntry("METERSPER",self.locale) local tacan = self.gettext:GetEntry("TACAN",self.locale) local farp = self.gettext:GetEntry("FARP",self.locale) - - + + local text = string.gsub( text, "SM", statute ) text = string.gsub( text, "°C", degc ) text = string.gsub( text, "°F", degf ) @@ -2966,13 +2985,13 @@ function ATIS:onafterReport( From, Event, To, Text ) text = string.gsub( text, "m/s", emes ) text = string.gsub( text, "TACAN", tacan ) text = string.gsub( text, "FARP", farp ) - + local delimiter = self.gettext:GetEntry("DELIMITER",self.locale) - + if string.lower(self.locale) ~= "en" then text = string.gsub(text,"(%d+)(%.)(%d+)","%1 "..delimiter.." %3") end - + -- Replace ";" by "." local text = string.gsub( text, ";", " . " ) @@ -3171,7 +3190,7 @@ end -- @param #ATIS.Soundfile sound ATIS sound object. -- @param #number interval Interval in seconds after the last transmission finished. -- @param #string subtitle Subtitle of the transmission. --- @param #string path Path to sound file. Default self.soundpath. +-- @param #string path Path to sound file. Default `self.soundpath`. function ATIS:Transmission( sound, interval, subtitle, path ) self.radioqueue:NewTransmission( sound.filename, sound.duration, path or self.soundpath, nil, interval, subtitle, self.subduration ) end diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 3772bedea..2f975920a 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -197,6 +197,45 @@ CALLSIGN={ Cargo=11, Ascot=12, }, + AH64={ + Army_Air = 9, + Apache = 10, + Crow = 11, + Sioux = 12, + Gatling = 13, + Gunslinger = 14, + Hammerhead = 15, + Bootleg = 16, + Palehorse = 17, + Carnivor = 18, + Saber = 19, + }, + Kiowa = { + Anvil = 1, + Azrael = 2, + BamBam = 3, + Blackjack = 4, + Bootleg = 5, + BurninStogie = 6, + Chaos = 7, + CrazyHorse = 8, + Crusader = 9, + Darkhorse = 10, + Eagle = 11, + Lighthorse = 12, + Mustang = 13, + Outcast = 14, + Palehorse = 15, + Pegasus = 16, + Pistol = 17, + Roughneck = 18, + Saber = 19, + Shamus = 20, + Spur = 21, + Stetson = 22, + Wrath = 23, + }, + } --#CALLSIGN --- Utilities static class. @@ -1923,7 +1962,19 @@ function UTILS.GetCallsignName(Callsign) return name end end - + + for name, value in pairs(CALLSIGN.AH64) do + if value==Callsign then + return name + end + end + + for name, value in pairs(CALLSIGN.Kiowa) do + if value==Callsign then + return name + end + end + return "Ghostrider" end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 781c71d48..497d9fb1a 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -445,7 +445,11 @@ function UNIT:IsPlayer() if not group then return false end -- Units of template group. - local units=group:GetTemplate().units + local template = group:GetTemplate() + + if (template == nil) or (template.units == nil ) then return false end + + local units=template.units -- Get numbers. for _,unit in pairs(units) do @@ -789,11 +793,13 @@ end --- Get the number of ammunition and in particular the number of shells, rockets, bombs and missiles a unit currently has. -- @param #UNIT self -- @return #number Total amount of ammo the unit has left. This is the sum of shells, rockets, bombs and missiles. --- @return #number Number of shells left. +-- @return #number Number of shells left. Shells include MG ammunition, AP and HE shells, and artillery shells where applicable. -- @return #number Number of rockets left. -- @return #number Number of bombs left. -- @return #number Number of missiles left. --- @return #number Number of artillery shells left (with explosive mass, included in shells; shells can also be machine gun ammo) +-- @return #number Number of artillery shells left (with explosive mass, included in shells; HE will also be reported as artillery shells for tanks) +-- @return #number Number of tank AP shells left (for tanks, if applicable) +-- @return #number Number of tank HE shells left (for tanks, if applicable) function UNIT:GetAmmunition() -- Init counter. @@ -803,6 +809,8 @@ function UNIT:GetAmmunition() local nmissiles=0 local nbombs=0 local narti=0 + local nAPshells = 0 + local nHEshells = 0 local unit=self @@ -844,6 +852,14 @@ function UNIT:GetAmmunition() narti=narti+Nammo end + if ammotable[w].desc.typeName and string.find(ammotable[w].desc.typeName,"_AP",1,true) then + nAPshells = nAPshells+Nammo + end + + if ammotable[w].desc.typeName and string.find(ammotable[w].desc.typeName,"_HE",1,true) then + nHEshells = nHEshells+Nammo + end + elseif Category==Weapon.Category.ROCKET then -- Add up all rockets. @@ -880,7 +896,55 @@ function UNIT:GetAmmunition() -- Total amount of ammunition. nammo=nshells+nrockets+nmissiles+nbombs - return nammo, nshells, nrockets, nbombs, nmissiles, narti + return nammo, nshells, nrockets, nbombs, nmissiles, narti, nAPshells, nHEshells +end + +--- Checks if a tank still has AP shells. +-- @param #UNIT self +-- @return #boolean HasAPShells +function UNIT:HasAPShells() + local _,_,_,_,_,_,shells = self:GetAmmunition() + if shells > 0 then return true else return false end +end + +--- Get number of AP shells from a tank. +-- @param #UNIT self +-- @return #number Number of AP shells +function UNIT:GetAPShells() + local _,_,_,_,_,_,shells = self:GetAmmunition() + return shells or 0 +end + +--- Get number of HE shells from a tank. +-- @param #UNIT self +-- @return #number Number of HE shells +function UNIT:GetHEShells() + local _,_,_,_,_,_,_,shells = self:GetAmmunition() + return shells or 0 +end + +--- Checks if a tank still has HE shells. +-- @param #UNIT self +-- @return #boolean HasHEShells +function UNIT:HasHEShells() + local _,_,_,_,_,_,_,shells = self:GetAmmunition() + if shells > 0 then return true else return false end +end + +--- Checks if an artillery unit still has artillery shells. +-- @param #UNIT self +-- @return #boolean HasArtiShells +function UNIT:HasArtiShells() + local _,_,_,_,_,shells = self:GetAmmunition() + if shells > 0 then return true else return false end +end + +--- Get number of artillery shells from an artillery unit. +-- @param #UNIT self +-- @return #number Number of artillery shells +function UNIT:GetArtiShells() + local _,_,_,_,_,shells = self:GetAmmunition() + return shells or 0 end --- Returns the unit sensors. @@ -1192,17 +1256,17 @@ function UNIT:GetThreatLevel() if self:IsGround() then local ThreatLevels = { - "Unarmed", - "Infantry", - "Old Tanks & APCs", - "Tanks & IFVs without ATGM", - "Tanks & IFV with ATGM", - "Modern Tanks", - "AAA", - "IR Guided SAMs", - "SR SAMs", - "MR SAMs", - "LR SAMs" + [1] = "Unarmed", + [2] = "Infantry", + [3] = "Old Tanks & APCs", + [4] = "Tanks & IFVs without ATGM", + [5] = "Tanks & IFV with ATGM", + [6] = "Modern Tanks", + [7] = "AAA", + [8] = "IR Guided SAMs", + [9] = "SR SAMs", + [10] = "MR SAMs", + [11] = "LR SAMs" } @@ -1228,17 +1292,17 @@ function UNIT:GetThreatLevel() if self:IsAir() then local ThreatLevels = { - "Unarmed", - "Tanker", - "AWACS", - "Transport Helicopter", - "UAV", - "Bomber", - "Strategic Bomber", - "Attack Helicopter", - "Battleplane", - "Multirole Fighter", - "Fighter" + [1] = "Unarmed", + [2] = "Tanker", + [3] = "AWACS", + [4] = "Transport Helicopter", + [5] = "UAV", + [6] = "Bomber", + [7] = "Strategic Bomber", + [8] = "Attack Helicopter", + [9] = "Battleplane", + [10] = "Multirole Fighter", + [11] = "Fighter" } @@ -1272,17 +1336,17 @@ function UNIT:GetThreatLevel() --["Unarmed ships"] = {"Ships","HeavyArmoredUnits",}, local ThreatLevels = { - "Unarmed ship", - "Light armed ships", - "Corvettes", - "", - "Frigates", - "", - "Cruiser", - "", - "Destroyer", - "", - "Aircraft Carrier" + [1] = "Unarmed ship", + [2] = "Light armed ships", + [3] = "Corvettes", + [4] = "", + [5] = "Frigates", + [6] = "", + [7] = "Cruiser", + [8] = "", + [9] = "Destroyer", + [10] = "", + [11] = "Aircraft Carrier" }