Merge branch 'develop' of https://github.com/FlightControl-Master/MOOSE into develop

This commit is contained in:
Van De Velde 2018-06-30 09:37:45 +02:00
commit 5124b842f5
3 changed files with 237 additions and 62 deletions

View File

@ -295,7 +295,9 @@ function SPAWN:New( SpawnTemplatePrefix )
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil -- No grouping self.Grouping = nil -- No grouping.
self.SpawnInitLivery = nil -- No special livery.
self.SpawnInitSkill = nil -- No special skill.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@ -341,7 +343,9 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil self.Grouping = nil -- No grouping.
self.SpawnInitLivery = nil -- No special livery.
self.SpawnInitSkill = nil -- No special skill.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@ -390,7 +394,9 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
self.SpawnUnControlled = false self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name. self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
self.DelayOnOff = false -- No intial delay when spawning the first group. self.DelayOnOff = false -- No intial delay when spawning the first group.
self.Grouping = nil self.Grouping = nil -- No grouping.
self.SpawnInitLivery = nil -- No special livery.
self.SpawnInitSkill = nil -- No special skill.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned. self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else else
@ -488,15 +494,23 @@ function SPAWN:InitHeading( HeadingMin, HeadingMax )
end end
--- Sets the coalition of the spawned group. Note that it might be necessary to also set the country explicitly!
-- @param #SPAWN self
-- @param #DCS.coalition Coaliton Coaliton of the group as number of enumerator, i.e. 0=coaliton.side.NEUTRAL, 1=coaliton.side.RED, 2=coalition.side.BLUE.
-- @return #SPAWN self
function SPAWN:InitCoalition( Coalition ) function SPAWN:InitCoalition( Coalition )
self:F( ) self:F({coalition=Coalition})
self.SpawnInitCoalition = Coalition self.SpawnInitCoalition = Coalition
return self return self
end end
--- Sets the country of the spawn group. Note that the country determins the coalition of the group depending on which country is defined to be on which side for each specific mission!
-- See https://wiki.hoggitworld.com/view/DCS_enum_country for country enumerators.
-- @param #SPAWN self
-- @param #DCS.country Country Country id as number or enumerator, e.g. country.id.RUSSIA=0, county.id.USA=2 etc.
-- @return #SPAWN self
function SPAWN:InitCountry( Country ) function SPAWN:InitCountry( Country )
self:F( ) self:F( )
@ -506,6 +520,10 @@ function SPAWN:InitCountry( Country )
end end
--- Sets category ID of the group.
-- @param #SPAWN self
-- @param #number Category Category id.
-- @return #SPAWN self
function SPAWN:InitCategory( Category ) function SPAWN:InitCategory( Category )
self:F( ) self:F( )
@ -514,6 +532,40 @@ function SPAWN:InitCategory( Category )
return self return self
end end
--- Sets livery of the group.
-- @param #SPAWN self
-- @param #string Livery Livery name. Note that this is not necessarily the same name as displayed in the mission edior.
-- @return #SPAWN self
function SPAWN:InitLivery( Livery )
self:F({livery=Livery} )
self.SpawnInitLivery = Livery
return self
end
--- Sets skill of the group.
-- @param #SPAWN self
-- @param #string Skill Skill, possible values "Average", "Good", "High", "Excellent" or "Random".
-- @return #SPAWN self
function SPAWN:InitSkill( Skill )
self:F({skill=Skill})
if Skill:lower()=="average" then
self.SpawnInitSkill="Average"
elseif Skill:lower()=="good" then
self.SpawnInitSkill="Good"
elseif Skill:lower()=="excellent" then
self.SpawnInitSkill="Excellent"
elseif Skill:lower()=="random" then
self.SpawnInitSkill="Random"
else
self.SpawnInitSkill="High"
end
return self
end
--- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups. --- Randomizes the defined route of the SpawnTemplatePrefix group in the ME. This is very useful to define extra variation of the behaviour of groups.
-- @param #SPAWN self -- @param #SPAWN self
-- @param #number SpawnStartPoint is the waypoint where the randomization begins. -- @param #number SpawnStartPoint is the waypoint where the randomization begins.
@ -1050,13 +1102,40 @@ function SPAWN:SpawnWithIndex( SpawnIndex )
end end
end end
-- Get correct heading.
local function _Heading(course)
local h
if course<=180 then
h=math.rad(course)
else
h=-math.rad(360-course)
end
return h
end
-- If Heading is given, point all the units towards the given Heading. -- If Heading is given, point all the units towards the given Heading.
if self.SpawnInitHeadingMin then if self.SpawnInitHeadingMin then
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].heading = self.SpawnInitHeadingMax and math.random( self.SpawnInitHeadingMin, self.SpawnInitHeadingMax ) or self.SpawnInitHeadingMin SpawnTemplate.units[UnitID].heading = _Heading(self.SpawnInitHeadingMax and math.random( self.SpawnInitHeadingMin, self.SpawnInitHeadingMax ) or self.SpawnInitHeadingMin)
SpawnTemplate.units[UnitID].psi = -SpawnTemplate.units[UnitID].heading
end end
end end
-- Set livery.
if self.SpawnInitLivery then
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].livery_id = self.SpawnInitLivery
end
end
-- Set skill.
if self.SpawnInitSkill then
for UnitID = 1, #SpawnTemplate.units do
SpawnTemplate.units[UnitID].skill = self.SpawnInitSkill
end
end
-- Set country, coaliton and categroy.
SpawnTemplate.CategoryID = self.SpawnInitCategory or SpawnTemplate.CategoryID SpawnTemplate.CategoryID = self.SpawnInitCategory or SpawnTemplate.CategoryID
SpawnTemplate.CountryID = self.SpawnInitCountry or SpawnTemplate.CountryID SpawnTemplate.CountryID = self.SpawnInitCountry or SpawnTemplate.CountryID
SpawnTemplate.CoalitionID = self.SpawnInitCoalition or SpawnTemplate.CoalitionID SpawnTemplate.CoalitionID = self.SpawnInitCoalition or SpawnTemplate.CoalitionID
@ -1272,9 +1351,12 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
local isbomber=TemplateUnit:HasAttribute("Bombers") local isbomber=TemplateUnit:HasAttribute("Bombers")
local istransport=TemplateUnit:HasAttribute("Transports") local istransport=TemplateUnit:HasAttribute("Transports")
local isfighter=TemplateUnit:HasAttribute("Battleplanes") local isfighter=TemplateUnit:HasAttribute("Battleplanes")
-- Number of units in the group. With grouping this can actually differ from the template group size!
local nunits=#SpawnTemplate.units
-- First waypoint of the group. -- First waypoint of the group.
local SpawnPoint = SpawnTemplate.route.points[1] local SpawnPoint = SpawnTemplate.route.points[1]
-- These are only for ships and FARPS. -- These are only for ships and FARPS.
SpawnPoint.linkUnit = nil SpawnPoint.linkUnit = nil
@ -1350,25 +1432,25 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
if spawnonship or spawnonfarp or spawnonrunway then if spawnonship or spawnonfarp or spawnonrunway then
-- These places work procedural and have some kind of build in queue ==> Less effort. -- These places work procedural and have some kind of build in queue ==> Less effort.
self:T(string.format("Group %s is spawned on farp/ship/runway %s.", self.SpawnTemplatePrefix, SpawnAirbase:GetName())) self:T(string.format("Group %s is spawned on farp/ship/runway %s.", self.SpawnTemplatePrefix, SpawnAirbase:GetName()))
nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype, spawnonship or spawnonfarp or spawnonrunway) nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype, true)
spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype, spawnonship or spawnonfarp or spawnonrunway) spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype, true)
else else
if ishelo then if ishelo then
if termtype==nil then if termtype==nil then
-- Helo is spawned. Try exclusive helo spots first. -- Helo is spawned. Try exclusive helo spots first.
self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.HelicopterOnly)) self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.HelicopterOnly))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
if nfree<#SpawnTemplate.units then if nfree<nunits then
-- Not enough helo ports. Let's try also other terminal types. -- Not enough helo ports. Let's try also other terminal types.
self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.HelicopterUsable)) self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.HelicopterUsable))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
-- No terminal type specified. We try all spots except shelters. -- No terminal type specified. We try all spots except shelters.
self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), termtype)) self:T(string.format("Helo group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), termtype))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
@ -1380,23 +1462,23 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
if isbomber or istransport then if isbomber or istransport then
-- First we fill the potentially bigger spots. -- First we fill the potentially bigger spots.
self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.OpenBig)) self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.OpenBig))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
if nfree<#SpawnTemplate.units then if nfree<nunits then
-- Now we try the smaller ones. -- Now we try the smaller ones.
self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.OpenMedOrBig)) self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.OpenMedOrBig))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenMedOrBig, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenMedOrBig, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
self:T(string.format("Fighter group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.FighterAircraft)) self:T(string.format("Fighter group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.FighterAircraft))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.FighterAircraft, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.FighterAircraft, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
-- Terminal type explicitly given. -- Terminal type explicitly given.
self:T(string.format("Plane group %s is at %s using terminal type %s.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), tostring(termtype))) self:T(string.format("Plane group %s is at %s using terminal type %s.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), tostring(termtype)))
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
end end
@ -1409,17 +1491,48 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
self:T2(string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d", self:T2(string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d",
SpawnAirbase:GetName(), _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)) SpawnAirbase:GetName(), _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy))
end end
self:T(string.format("%s at %s: free parking spots = %d - number of units = %d", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), nfree, #SpawnTemplate.units)) self:T(string.format("%s at %s: free parking spots = %d - number of units = %d", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), nfree, nunits))
-- Put parking spots in table. These spots are only used if spawing at an airbase. -- Set this to true if not enough spots are available for emergency air start.
if nfree >= #SpawnTemplate.units or (spawnonrunway and nfree>0) then local _notenough=false
for i=1,#SpawnTemplate.units do -- Need to differentiate some cases again.
table.insert(parkingspots, spots[i].Coordinate) if spawnonship or spawnonfarp or spawnonrunway then
table.insert(parkingindex, spots[i].TerminalID)
-- On free spot required in these cases.
if nfree >=1 then
-- All units get the same spot. DCS takes care of the rest.
for i=1,nunits do
table.insert(parkingspots, spots[1].Coordinate)
table.insert(parkingindex, spots[1].TerminalID)
end
-- This is actually used...
PointVec3=spots[1].Coordinate
else
-- If there is absolutely not spot ==> air start!
_notenough=true
end end
elseif spawnonairport then
if nfree>=nunits then
else for i=1,nunits do
table.insert(parkingspots, spots[i].Coordinate)
table.insert(parkingindex, spots[i].TerminalID)
end
else
-- Not enough spots for the whole group ==> air start!
_notenough=true
end
end
-- Not enough spots ==> Prepare airstart.
if _notenough then
if EmergencyAirSpawn and not self.SpawnUnControlled then if EmergencyAirSpawn and not self.SpawnUnControlled then
self:E(string.format("WARNING: Group %s has no parking spots at %s ==> air start!", self.SpawnTemplatePrefix, SpawnAirbase:GetName())) self:E(string.format("WARNING: Group %s has no parking spots at %s ==> air start!", self.SpawnTemplatePrefix, SpawnAirbase:GetName()))
@ -1449,11 +1562,25 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
return nil return nil
end end
end end
else
-- Air start requested initially ==> Set altitude.
if TakeoffAltitude then
PointVec3.y=TakeoffAltitude
else
if ishelo then
PointVec3.y=PointVec3:GetLandHeight()+math.random(100,1000)
else
-- Randomize position so that multiple AC wont be spawned on top even in air.
PointVec3.y=PointVec3:GetLandHeight()+math.random(500,2500)
end
end
end end
-- Translate the position of the Group Template to the Vec3. -- Translate the position of the Group Template to the Vec3.
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, nunits do
self:T2('Before Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y) self:T2('Before Translation SpawnTemplate.units['..UnitID..'].x = '..SpawnTemplate.units[UnitID].x..', SpawnTemplate.units['..UnitID..'].y = '..SpawnTemplate.units[UnitID].y)
-- Template of the current unit. -- Template of the current unit.

View File

@ -511,7 +511,7 @@ RAT.id="RAT | "
--- RAT version. --- RAT version.
-- @list version -- @list version
RAT.version={ RAT.version={
version = "2.3.0", version = "2.3.1",
print = true, print = true,
} }
@ -5031,6 +5031,9 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
self.SpawnUnControlled=true self.SpawnUnControlled=true
end end
-- Number of units in the group. With grouping this can actually differ from the template group size!
local nunits=#SpawnTemplate.units
-- Array with parking spots coordinates. -- Array with parking spots coordinates.
local parkingspots={} local parkingspots={}
local parkingindex={} local parkingindex={}
@ -5059,26 +5062,26 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
if spawnonship or spawnonfarp or spawnonrunway then if spawnonship or spawnonfarp or spawnonrunway then
-- These places work procedural and have some kind of build in queue ==> Less effort. -- These places work procedural and have some kind of build in queue ==> Less effort.
self:T(RAT.id..string.format("Group %s is spawned on farp/ship/runway %s.", self.alias, departure:GetName())) self:T(RAT.id..string.format("Group %s is spawned on farp/ship/runway %s.", self.alias, departure:GetName()))
nfree=departure:GetFreeParkingSpotsNumber(termtype, spawnonship or spawnonfarp or spawnonrunway) nfree=departure:GetFreeParkingSpotsNumber(termtype, true)
spots=departure:GetFreeParkingSpotsTable(termtype, spawnonship or spawnonfarp or spawnonrunway) spots=departure:GetFreeParkingSpotsTable(termtype, true)
else else
-- Helo is spawned. -- Helo is spawned.
if self.category==RAT.cat.heli then if self.category==RAT.cat.heli then
if termtype==nil then if termtype==nil then
-- Try exclusive helo spots first. -- Try exclusive helo spots first.
self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.HelicopterOnly)) self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.HelicopterOnly))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
if nfree<#SpawnTemplate.units then if nfree<nunits then
-- Not enough helo ports. Let's try also other terminal types. -- Not enough helo ports. Let's try also other terminal types.
self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.HelicopterOnly)) self:T(RAT.id..string.format("Helo group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.HelicopterOnly))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
-- Terminal type specified explicitly. -- Terminal type specified explicitly.
self:T(RAT.id..string.format("Helo group %s is at %s using terminal type %d.", self.alias, departure:GetName(), termtype)) self:T(RAT.id..string.format("Helo group %s is at %s using terminal type %d.", self.alias, departure:GetName(), termtype))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
@ -5092,23 +5095,23 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
if bomber or transport then if bomber or transport then
-- First we fill the potentially bigger spots. -- First we fill the potentially bigger spots.
self:T(RAT.id..string.format("Transport/bomber group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.OpenBig)) self:T(RAT.id..string.format("Transport/bomber group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.OpenBig))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
if nfree<#SpawnTemplate.units then if nfree<nunits then
-- Now we try the smaller ones. -- Now we try the smaller ones.
self:T(RAT.id..string.format("Transport/bomber group %s is at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.OpenMed)) self:T(RAT.id..string.format("Transport/bomber group %s is at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.OpenMed))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenMed, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenMed, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
self:T(RAT.id..string.format("Fighter group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.FighterAircraft)) self:T(RAT.id..string.format("Fighter group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), AIRBASE.TerminalType.FighterAircraft))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.FighterAircraft, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.FighterAircraft, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
else else
-- Terminal type explicitly given. -- Terminal type explicitly given.
self:T(RAT.id..string.format("Plane group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), termtype)) self:T(RAT.id..string.format("Plane group %s is spawned at %s using terminal type %d.", self.alias, departure:GetName(), termtype))
spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe) spots=departure:FindFreeParkingSpotForAircraft(TemplateGroup, termtype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits)
nfree=#spots nfree=#spots
end end
end end
@ -5121,19 +5124,51 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
self:T2(RAT.id..string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d", self:T2(RAT.id..string.format("%s, Termin Index = %3d, Term Type = %03d, Free = %5s, TOAC = %5s, Term ID0 = %3d, Dist2Rwy = %4d",
departure:GetName(), _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy)) departure:GetName(), _spot.TerminalID, _spot.TerminalType,tostring(_spot.Free),tostring(_spot.TOAC),_spot.TerminalID0,_spot.DistToRwy))
end end
self:T(RAT.id..string.format("%s at %s: free parking spots = %d - number of units = %d", self.alias, departure:GetName(), nfree, #SpawnTemplate.units)) self:T(RAT.id..string.format("%s at %s: free parking spots = %d - number of units = %d", self.alias, departure:GetName(), nfree, nunits))
-- Put parking spots in table. These spots are only used if
if nfree >= #SpawnTemplate.units or (spawnonrunway and nfree>0) then -- Set this to true if not enough spots are available for emergency air start.
local _notenough=false
for i=1,#SpawnTemplate.units do
table.insert(parkingspots, spots[i].Coordinate) -- Need to differentiate some cases again.
table.insert(parkingindex, spots[i].TerminalID) if spawnonship or spawnonfarp or spawnonrunway then
-- On free spot required in these cases.
if nfree >=1 then
-- All units get the same spot. DCS takes care of the rest.
for i=1,nunits do
table.insert(parkingspots, spots[1].Coordinate)
table.insert(parkingindex, spots[1].TerminalID)
end
-- This is actually used...
PointVec3=spots[1].Coordinate
else
-- If there is absolutely not spot ==> air start!
_notenough=true
end end
elseif spawnonairport then
if nfree>=nunits then
else for i=1,nunits do
if self.respawn_inair and not self.uncontrolled then table.insert(parkingspots, spots[i].Coordinate)
self:E(RAT.id..string.format("WARNING: RAT group %s has no parking spots at %s ==> air start!", self.alias, departure:GetName())) table.insert(parkingindex, spots[i].TerminalID)
end
else
-- Not enough spots for the whole group ==> air start!
_notenough=true
end
end
-- Not enough spots ==> Prepare airstart.
if _notenough then
if self.respawn_inair and not self.SpawnUnControlled then
self:E(RAT.id..string.format("WARNING: Group %s has no parking spots at %s ==> air start!", self.SpawnTemplatePrefix, departure:GetName()))
-- Not enough parking spots at the airport ==> Spawn in air. -- Not enough parking spots at the airport ==> Spawn in air.
spawnonground=false spawnonground=false
@ -5142,27 +5177,37 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
spawnonrunway=false spawnonrunway=false
-- Set waypoint type/action to turning point. -- Set waypoint type/action to turning point.
waypoints[1].type = GROUPTEMPLATE.Takeoff[GROUP.Takeoff.Air][1] -- type = Turning Point waypoints[1].type = GROUPTEMPLATE.Takeoff[GROUP.Takeoff.Air][1] -- type = Turning Point
waypoints[1].action = GROUPTEMPLATE.Takeoff[GROUP.Takeoff.Air][2] -- action = Turning Point waypoints[1].action = GROUPTEMPLATE.Takeoff[GROUP.Takeoff.Air][2] -- action = Turning Point
-- Adjust and randomize position and altitude of the spawn point. -- Adjust altitude to be 500-1000 m above the airbase.
PointVec3.x=PointVec3.x+math.random(-500,500) PointVec3.x=PointVec3.x+math.random(-500,500)
PointVec3.z=PointVec3.z+math.random(-500,500) PointVec3.z=PointVec3.z+math.random(-500,500)
if self.category==RAT.cat.heli then if self.category==RAT.cat.heli then
PointVec3.y=PointVec3:GetLandHeight()+math.random(100,1000) PointVec3.y=PointVec3:GetLandHeight()+math.random(100,1000)
else else
-- Randomize position so that multiple AC wont be spawned on top even in air.
PointVec3.y=PointVec3:GetLandHeight()+math.random(500,2500) PointVec3.y=PointVec3:GetLandHeight()+math.random(500,2500)
end end
else else
self:E(RAT.id..string.format("WARNING: RAT group %s has no parking spots at %s. Air start deactivated or uncontrolled AC!", self.alias, departure:GetName())) self:E(RAT.id..string.format("WARNING: Group %s has no parking spots at %s ==> No emergency air start or uncontrolled spawning ==> No spawn!", self.SpawnTemplatePrefix, departure:GetName()))
return nil return nil
end end
end end
else
-- Air start requested initially!
--PointVec3.y is already set from first waypoint here!
end end
--- new
-- Translate the position of the Group Template to the Vec3. -- Translate the position of the Group Template to the Vec3.
for UnitID = 1, #SpawnTemplate.units do for UnitID = 1, nunits do
-- Template of the current unit. -- Template of the current unit.
local UnitTemplate = SpawnTemplate.units[UnitID] local UnitTemplate = SpawnTemplate.units[UnitID]

View File

@ -589,8 +589,9 @@ end
-- @param #boolean scanstatics (Optional) Scan for statics as obstacles. Default true. -- @param #boolean scanstatics (Optional) Scan for statics as obstacles. Default true.
-- @param #boolean scanscenery (Optional) Scan for scenery as obstacles. Default false. Can cause problems with e.g. shelters. -- @param #boolean scanscenery (Optional) Scan for scenery as obstacles. Default false. Can cause problems with e.g. shelters.
-- @param #boolean verysafe (Optional) If true, wait until an aircraft has taken off until the parking spot is considered to be free. Defaul false. -- @param #boolean verysafe (Optional) If true, wait until an aircraft has taken off until the parking spot is considered to be free. Defaul false.
-- @param #number nspots (Optional) Number of freeparking spots requested. Default is the number of aircraft in the group.
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID. -- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe) function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots)
-- Init default -- Init default
scanradius=scanradius or 50 scanradius=scanradius or 50
@ -646,11 +647,13 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
-- Get the aircraft size, i.e. it's longest side of x,z. -- Get the aircraft size, i.e. it's longest side of x,z.
local aircraft=group:GetUnit(1) local aircraft=group:GetUnit(1)
local nspots=group:GetSize()
local _aircraftsize, ax,ay,az=_GetObjectSize(aircraft, true) local _aircraftsize, ax,ay,az=_GetObjectSize(aircraft, true)
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
local _nspots=nspots or group:GetSize()
-- Debug info. -- Debug info.
self:E(string.format("Looking for %d parking spot(s) at %s for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", nspots, airport, _aircraftsize, ax, ay, az, tostring(terminaltype))) self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
-- Table of valid spots. -- Table of valid spots.
local validspots={} local validspots={}
@ -743,7 +746,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
self:T(string.format("%s: Parking spot id %d occupied.", airport, _termid)) self:T(string.format("%s: Parking spot id %d occupied.", airport, _termid))
else else
self:E(string.format("%s: Parking spot id %d free.", airport, _termid)) self:E(string.format("%s: Parking spot id %d free.", airport, _termid))
if nvalid<nspots then if nvalid<_nspots then
table.insert(validspots, {Coordinate=_spot, TerminalID=_termid}) table.insert(validspots, {Coordinate=_spot, TerminalID=_termid})
end end
nvalid=nvalid+1 nvalid=nvalid+1
@ -752,7 +755,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
end end
-- We found enough spots. -- We found enough spots.
if nvalid>=nspots then if nvalid>=_nspots then
return validspots return validspots
end end
end end