mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Spawn improvements
COORDINATE: - Improved GetClosestParkingSpot functions. - Improved ScanObject function. SPAWN: - Improved SpawnAtAirbase function RAT: - Improved spawn function - Added some takeoff type user functions. UTILS: - Added clock vs second functions - Added split function AIRBASE: - Added checkonrunway function - Other improvemetns.
This commit is contained in:
@@ -294,15 +294,18 @@ do -- COORDINATE
|
||||
|
||||
--- Returns if the 2 coordinates are at the same 2D position.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number radius Scan radius in meters.
|
||||
-- @param #number radius (Optional) Scan radius in meters. Default 100 m.
|
||||
-- @param #boolean scanunits (Optional) If true scan for units. Default true.
|
||||
-- @param #boolean scanstatics (Optional) If true scan for static objects. Default true.
|
||||
-- @param #boolean scanscenery (Optional) If true scan for scenery objects. Default false.
|
||||
-- @return True if units were found.
|
||||
-- @return True if statics were found.
|
||||
-- @return True if scenery objects were found.
|
||||
-- @return Unit objects found.
|
||||
-- @return Static objects found.
|
||||
-- @return Scenery objects found.
|
||||
function COORDINATE:ScanObjects(radius)
|
||||
self:T(string.format("Scanning in radius %.1f m.", radius))
|
||||
function COORDINATE:ScanObjects(radius, scanunits, scanstatics, scanscenery)
|
||||
self:F(string.format("Scanning in radius %.1f m.", radius))
|
||||
|
||||
local SphereSearch = {
|
||||
id = world.VolumeType.SPHERE,
|
||||
@@ -312,6 +315,30 @@ do -- COORDINATE
|
||||
}
|
||||
}
|
||||
|
||||
-- Defaults
|
||||
radius=radius or 100
|
||||
if scanunits==nil then
|
||||
scanunits=true
|
||||
end
|
||||
if scanstatics==nil then
|
||||
scanstatics=true
|
||||
end
|
||||
if scanscenery==nil then
|
||||
scanscenery=false
|
||||
end
|
||||
|
||||
--{Object.Category.UNIT, Object.Category.STATIC, Object.Category.SCENERY}
|
||||
local scanobjects={}
|
||||
if scanunits then
|
||||
table.insert(scanobjects, Object.Category.UNIT)
|
||||
end
|
||||
if scanstatics then
|
||||
table.insert(scanobjects, Object.Category.STATIC)
|
||||
end
|
||||
if scanscenery then
|
||||
table.insert(scanobjects, Object.Category.SCENERY)
|
||||
end
|
||||
|
||||
-- Found stuff.
|
||||
local Units = {}
|
||||
local Statics = {}
|
||||
@@ -352,7 +379,7 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
-- Search the world.
|
||||
world.searchObjects({Object.Category.UNIT, Object.Category.STATIC, Object.Category.SCENERY}, SphereSearch, EvaluateZone)
|
||||
world.searchObjects(scanobjects, SphereSearch, EvaluateZone)
|
||||
|
||||
for _,unit in pairs(Units) do
|
||||
self:T(string.format("Scan found unit %s", unit:getName()))
|
||||
@@ -361,7 +388,7 @@ do -- COORDINATE
|
||||
self:T(string.format("Scan found static %s", static:getName()))
|
||||
end
|
||||
for _,scenery in pairs(Scenery) do
|
||||
self:T(string.format("Scan found scenery %s", scenery:getName()))
|
||||
self:T(string.format("Scan found scenery %s", scenery:getTypeName()))
|
||||
end
|
||||
|
||||
return gotunits, gotstatics, gotscenery, Units, Statics, Scenery
|
||||
@@ -1021,22 +1048,28 @@ do -- COORDINATE
|
||||
|
||||
--- Gets the nearest parking spot.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #boolean free (Optional) Only look for free parking spots. By default the closest parking spot is returned regardless of whether it is free or not.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at that airbase.
|
||||
-- @param Wrapper.Airbase#Terminaltype terminaltype Type of the terminal.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at this airbase.
|
||||
-- @param Wrapper.Airbase#Terminaltype terminaltype (Optional) Type of the terminal. Default any execpt valid spawn points on runway.
|
||||
-- @param #boolean free (Optional) If true, returns the closest free spot. If false, returns the closest occupied spot. If nil, returns the closest spot regardless of free or occupied.
|
||||
-- @return Core.Point#COORDINATE Coordinate of the nearest parking spot.
|
||||
-- @return #number Distance to closest parking spot.
|
||||
function COORDINATE:GetClosestParkingSpot(free, airbase, terminaltype)
|
||||
|
||||
-- @return #number Terminal ID.
|
||||
-- @return #number Distance to closest parking spot in meters.
|
||||
function COORDINATE:GetClosestParkingSpot(airbase, terminaltype, free)
|
||||
|
||||
-- Get airbase table.
|
||||
local airbases={}
|
||||
if airbase then
|
||||
table.insert(airbases,airbase)
|
||||
else
|
||||
airbases=AIRBASE:GetAllAirbases()
|
||||
airbases=AIRBASE.GetAllAirbases()
|
||||
end
|
||||
|
||||
-- Init.
|
||||
local _closest=nil --Core.Point#COORDINATE
|
||||
local _termID=nil
|
||||
local _distmin=nil
|
||||
|
||||
-- Loop over all airbases.
|
||||
for _,_airbase in pairs(airbases) do
|
||||
|
||||
local mybase=_airbase --Wrapper.Airbase#AIRBASE
|
||||
@@ -1044,44 +1077,51 @@ do -- COORDINATE
|
||||
|
||||
for _,_spot in pairs(parkingdata) do
|
||||
|
||||
-- Get coordinate if it matches the requirements.
|
||||
local _coord=nil --Core.Point#COORDINATE
|
||||
if (free and _spot.Free) or free==nil then
|
||||
if (terminaltype and _spot.TerminalType==terminaltype) or terminaltype==nil then
|
||||
_coord=_spot.Coordinate
|
||||
end
|
||||
end
|
||||
|
||||
-- Compare distance to closest one found so far.
|
||||
if _coord then
|
||||
-- Check for parameters.
|
||||
if (free==true and _spot.Free==true) or (free==false and _spot.Free==false) or free==nil then
|
||||
|
||||
local _coord=_spot.Coordinate --Core.Point#COORDINATE
|
||||
|
||||
local _dist=self:Get2DDistance(_coord)
|
||||
if _distmin==nil then
|
||||
_closest=_coord
|
||||
_distmin=_dist
|
||||
else
|
||||
local _dist=self:Get2DDistance(_coord)
|
||||
_termID=_spot.TerminalID
|
||||
else
|
||||
if _dist<_distmin then
|
||||
_distmin=_dist
|
||||
_closest=_coord
|
||||
_termID=_spot.TerminalID
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return _closest, _distmin
|
||||
|
||||
return _closest, _termID, _distmin
|
||||
end
|
||||
|
||||
--- Gets the nearest free parking spot.
|
||||
-- @param #COORDINATE self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at that airbase.
|
||||
-- @param Wrapper.Airbase#Terminaltype terminaltype Type of the terminal.
|
||||
-- @param Wrapper.Airbase#Terminaltype terminaltype (Optional) Type of the terminal.
|
||||
-- @return #COORDINATE Coordinate of the nearest free parking spot.
|
||||
-- @return #number Distance to closest free parking spot.
|
||||
-- @return #number Terminal ID.
|
||||
-- @return #number Distance to closest free parking spot in meters.
|
||||
function COORDINATE:GetClosestFreeParkingSpot(airbase, terminaltype)
|
||||
return self:GetClosestParkingSpot(true, airbase, terminaltype)
|
||||
return self:GetClosestParkingSpot(airbase, terminaltype, true)
|
||||
end
|
||||
|
||||
--- Gets the nearest occupied parking spot.
|
||||
-- @param #COORDINATE self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at that airbase.
|
||||
-- @param Wrapper.Airbase#Terminaltype terminaltype (Optional) Type of the terminal.
|
||||
-- @return #COORDINATE Coordinate of the nearest occupied parking spot.
|
||||
-- @return #number Terminal ID.
|
||||
-- @return #number Distance to closest occupied parking spot in meters.
|
||||
function COORDINATE:GetClosestOccupiedParkingSpot(airbase, terminaltype)
|
||||
return self:GetClosestParkingSpot(airbase, terminaltype, false)
|
||||
end
|
||||
|
||||
--- Gets the nearest coordinate to a road.
|
||||
|
||||
@@ -1218,7 +1218,8 @@ end
|
||||
-- @param Wrapper.Airbase#AIRBASE SpawnAirbase The @{Wrapper.Airbase} where to spawn the group.
|
||||
-- @param #SPAWN.Takeoff Takeoff (optional) The location and takeoff method. Default is Hot.
|
||||
-- @param #number TakeoffAltitude (optional) The altitude above the ground.
|
||||
-- @param #number TerminalType (optional) The terminal type the aircraft should be spawned at.
|
||||
-- @param Wrapper.Airbase#AIRBASE.TerminalType TerminalType (optional) The terminal type the aircraft should be spawned at. See @{Wrapper.Airbase#AIRBASE.TerminalType}.
|
||||
-- @param #boolean EmergencyAirSpawn (optional) If true (default), groups are spawned in air if there is no parking spot at the airbase. If false, nothing is spawned if no parking spot is available.
|
||||
-- @return Wrapper.Group#GROUP that was spawned or nil when nothing was spawned.
|
||||
-- @usage
|
||||
-- Spawn_Plane = SPAWN:New( "Plane" )
|
||||
@@ -1239,7 +1240,7 @@ end
|
||||
--
|
||||
-- Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Caucasus.Krymsk ), SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.OpenBig )
|
||||
--
|
||||
function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType ) -- R2.2, R2.4
|
||||
function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType, EmergencyAirSpawn ) -- R2.2, R2.4
|
||||
self:F( { self.SpawnTemplatePrefix, SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType } )
|
||||
|
||||
-- Get position of airbase.
|
||||
@@ -1249,6 +1250,11 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
-- Set take off type. Default is hot.
|
||||
Takeoff = Takeoff or SPAWN.Takeoff.Hot
|
||||
|
||||
-- By default, groups are spawned in air if no parking spot is available.
|
||||
if EmergencyAirSpawn==nil then
|
||||
EmergencyAirSpawn=true
|
||||
end
|
||||
|
||||
if self:_GetSpawnIndex( self.SpawnIndex + 1 ) then
|
||||
|
||||
-- Get group template.
|
||||
@@ -1259,9 +1265,13 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
-- Debug output
|
||||
self:T( { "Current point of ", self.SpawnTemplatePrefix, SpawnAirbase } )
|
||||
|
||||
-- Template group and unit.
|
||||
-- Template group, unit and its attributes.
|
||||
local TemplateGroup = GROUP:FindByName(self.SpawnTemplatePrefix)
|
||||
local ishelo=TemplateGroup:GetUnit(1):HasAttribute("Helicopters")
|
||||
local TemplateUnit=TemplateGroup:GetUnit(1)
|
||||
local ishelo=TemplateUnit:HasAttribute("Helicopters")
|
||||
local isbomber=TemplateUnit:HasAttribute("Bombers")
|
||||
local istransport=TemplateUnit:HasAttribute("Transports")
|
||||
local isfighter=TemplateUnit:HasAttribute("Battleplanes")
|
||||
|
||||
-- First waypoint of the group.
|
||||
local SpawnPoint = SpawnTemplate.route.points[1]
|
||||
@@ -1332,32 +1342,64 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
-- Number of free parking spots at the airbase.
|
||||
if spawnonship or spawnonfarp or spawnonrunway then
|
||||
-- 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()))
|
||||
nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype, spawnonship or spawnonfarp or spawnonrunway)
|
||||
spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype, spawnonship or spawnonfarp or spawnonrunway)
|
||||
else
|
||||
if ishelo and termtype==nil then
|
||||
-- Helo is spawned.
|
||||
-- Try helo spots first.
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly)
|
||||
nfree=#spots
|
||||
if nfree<#SpawnTemplate.units then
|
||||
-- Not enough helo ports. Let's try all terminal types.
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable)
|
||||
if ishelo then
|
||||
if termtype==nil then
|
||||
-- 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))
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterOnly)
|
||||
nfree=#spots
|
||||
if nfree<#SpawnTemplate.units then
|
||||
-- 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))
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.HelicopterUsable)
|
||||
nfree=#spots
|
||||
end
|
||||
else
|
||||
-- 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))
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype)
|
||||
nfree=#spots
|
||||
end
|
||||
else
|
||||
-- Fixed wing aircraft is spawned.
|
||||
if termtype==nil then
|
||||
--TODO: Add some default cases for transport, bombers etc. if no explicit terminal type is provided.
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, termtype)
|
||||
nfree=#spots
|
||||
--TODO: We don't want Bombers to spawn in shelters. But I don't know a good attribute for just fighers.
|
||||
--TODO: Some attributes are "Helicopters", "Bombers", "Transports", "Battleplanes". Need to check it out.
|
||||
if isbomber or istransport then
|
||||
-- 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))
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig)
|
||||
nfree=#spots
|
||||
if nfree<#SpawnTemplate.units then
|
||||
-- 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))
|
||||
spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenMedOrBig)
|
||||
nfree=#spots
|
||||
end
|
||||
else
|
||||
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)
|
||||
nfree=#spots
|
||||
end
|
||||
else
|
||||
-- Terminal type explicitly given.
|
||||
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)
|
||||
nfree=#spots
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get parking data.
|
||||
local parkingdata=SpawnAirbase:GetParkingSpotsTable(termtype)
|
||||
self:T(string.format("Parking at %s, terminal type %s:", SpawnAirbase:GetName(), tostring(termtype)))
|
||||
self:T2(string.format("Parking at %s, terminal type %s:", SpawnAirbase:GetName(), tostring(termtype)))
|
||||
for _,_spot in pairs(parkingdata) do
|
||||
self:T(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))
|
||||
end
|
||||
self:T(string.format("%s at %s: free parking spots = %d - number of units = %d", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), nfree, #SpawnTemplate.units))
|
||||
@@ -1371,7 +1413,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
end
|
||||
|
||||
else
|
||||
if 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()))
|
||||
|
||||
-- Not enough parking spots at the airport ==> Spawn in air.
|
||||
@@ -1388,15 +1430,15 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
PointVec3.x=PointVec3.x+math.random(-500,500)
|
||||
PointVec3.z=PointVec3.z+math.random(-500,500)
|
||||
if ishelo then
|
||||
PointVec3.y=PointVec3:GetLandHeight()+math.random(200,1200)
|
||||
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,5000)
|
||||
PointVec3.y=PointVec3:GetLandHeight()+math.random(500,2500)
|
||||
end
|
||||
|
||||
Takeoff=GROUP.Takeoff.Air
|
||||
else
|
||||
self:E(string.format("WARNING: Group %s has no parking spots at %s ==> Uncontrolled spawning ==> No spawn!", self.SpawnTemplatePrefix, SpawnAirbase:GetName()))
|
||||
self:E(string.format("WARNING: Group %s has no parking spots at %s ==> No emergency air start or uncontrolled spawning ==> No spawn!", self.SpawnTemplatePrefix, SpawnAirbase:GetName()))
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -1475,23 +1517,26 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
|
||||
-- Spawn group.
|
||||
local GroupSpawned = self:SpawnWithIndex( self.SpawnIndex )
|
||||
|
||||
|
||||
-- When spawned in the air, we need to generate a Takeoff Event.
|
||||
if Takeoff == GROUP.Takeoff.Air then
|
||||
for UnitID, UnitSpawned in pairs( GroupSpawned:GetUnits() ) do
|
||||
SCHEDULER:New( nil, BASE.CreateEventTakeoff, { GroupSpawned, timer.getTime(), UnitSpawned:GetDCSObject() } , 1 )
|
||||
end
|
||||
end
|
||||
|
||||
return GroupSpawned
|
||||
|
||||
-- Check if we accidentally spawned on the runway. Needs to be schedules, because group is not immidiately alive.
|
||||
if Takeoff~=SPAWN.Takeoff.Runway and Takeoff~=SPAWN.Takeoff.Air and spawnonairport then
|
||||
SCHEDULER:New(nil, AIRBASE.CheckOnRunWay, {SpawnAirbase, GroupSpawned, 25, true} , 1.0)
|
||||
end
|
||||
|
||||
return GroupSpawned
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Will spawn a group from a Vec3 in 3D space.
|
||||
-- This method is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes.
|
||||
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
|
||||
|
||||
Reference in New Issue
Block a user