Merge pull request #986 from FlightControl-Master/FF/Develop

WAREHOUSE v0.5.1
This commit is contained in:
Frank 2018-09-18 17:01:01 +02:00 committed by GitHub
commit f655e7e652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 7184 additions and 971 deletions

View File

@ -239,7 +239,6 @@ function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
-- Aircraft was sent to this airbase to pickup troops. Initiate loadling. -- Aircraft was sent to this airbase to pickup troops. Initiate loadling.
if self.RoutePickup == true then if self.RoutePickup == true then
env.info("FF load airplane "..Airplane:GetName())
self:Load( self.PickupZone ) self:Load( self.PickupZone )
end end
@ -265,15 +264,15 @@ end
-- @param Core.Zone#ZONE_AIRBASE PickupZone -- @param Core.Zone#ZONE_AIRBASE PickupZone
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, PickupZone ) function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, PickupZone )
if Airplane and Airplane:IsAlive()~=nil then if Airplane and Airplane:IsAlive() then
env.info("FF onafterpick aircraft alive") --env.info("FF onafterpick aircraft alive")
self.PickupZone = PickupZone self.PickupZone = PickupZone
-- Get closest airbase of current position. -- Get closest airbase of current position.
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase() local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
env.info("FF onafterpickup closest airbase "..ClosestAirbase:GetName()) --env.info("FF onafterpickup closest airbase "..ClosestAirbase:GetName())
-- Two cases. Aircraft spawned in air or at an airbase. -- Two cases. Aircraft spawned in air or at an airbase.
if Airplane:InAir() then if Airplane:InAir() then
@ -282,15 +281,16 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate,
self.Airbase=ClosestAirbase self.Airbase=ClosestAirbase
end end
-- Set pickup airbase.
local Airbase = PickupZone:GetAirbase() local Airbase = PickupZone:GetAirbase()
-- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase. -- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase.
local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate()) local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
env.info("Distance closest to pickup airbase = "..Dist) --env.info("Distance closest to pickup airbase = "..Dist)
if Airplane:InAir() or Dist>500 then if Airplane:InAir() or Dist>500 then
env.info("FF onafterpickup routing to airbase "..ClosestAirbase:GetName()) --env.info("FF onafterpickup routing to airbase "..ClosestAirbase:GetName())
-- Route aircraft to pickup airbase. -- Route aircraft to pickup airbase.
self:Route( Airplane, Airbase, Speed ) self:Route( Airplane, Airbase, Speed )
@ -302,7 +302,7 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate,
self.RoutePickup = true self.RoutePickup = true
else else
env.info("FF onafterpick calling landed") --env.info("FF onafterpick calling landed")
-- We are already at the right airbase ==> Landed ==> triggers loading of troops. Is usually called at engine shutdown event. -- We are already at the right airbase ==> Landed ==> triggers loading of troops. Is usually called at engine shutdown event.
self.RoutePickup=true self.RoutePickup=true
@ -312,7 +312,7 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate,
self:GetParent( self, AI_CARGO_AIRPLANE ).onafterPickup( self, Airplane, From, Event, To, Coordinate, Speed, PickupZone ) self:GetParent( self, AI_CARGO_AIRPLANE ).onafterPickup( self, Airplane, From, Event, To, Coordinate, Speed, PickupZone )
else else
env.info("FF onafterpick aircraft not alive") --env.info("FF onafterpick aircraft not alive")
end end
@ -396,7 +396,7 @@ end
-- @param #boolean Uncontrolled If true, spawn group in uncontrolled state. -- @param #boolean Uncontrolled If true, spawn group in uncontrolled state.
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Uncontrolled ) function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Uncontrolled )
if Airplane and Airplane:IsAlive()~=nil then if Airplane and Airplane:IsAlive() then
-- Set takeoff type. -- Set takeoff type.
local Takeoff = SPAWN.Takeoff.Cold local Takeoff = SPAWN.Takeoff.Cold

View File

@ -471,9 +471,9 @@ end
-- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart() -- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone ) -- AICargoDispatcher = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo, SetDeployZone )
-- --
function AI_CARGO_DISPATCHER:NewWithZones( SetCarriers, SetCargos, PickupZoneSet, DeployZoneSet ) function AI_CARGO_DISPATCHER:NewWithZones( SetCarrier, SetCargo, PickupZoneSet, DeployZoneSet )
local self = AI_CARGO_DISPATCHER:New( SetCarriers, SetCargos ) -- #AI_CARGO_DISPATCHER local self = AI_CARGO_DISPATCHER:New( SetCarrier, SetCargo ) -- #AI_CARGO_DISPATCHER
self.PickupZoneSet = PickupZoneSet self.PickupZoneSet = PickupZoneSet
self.DeployZoneSet = DeployZoneSet self.DeployZoneSet = DeployZoneSet

View File

@ -109,14 +109,14 @@ AI_CARGO_DISPATCHER_APC = {
-- APCSet = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart() -- APCSet = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
-- CargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart() -- CargoSet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
-- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart() -- DeployZoneSet = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
-- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( APCSet, SCargoSet, nil, DeployZoneSet, 500 ) -- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( APCSet, CargoSet, nil, DeployZoneSet, 500 )
-- --
function AI_CARGO_DISPATCHER_APC:New( APCSet, CargoSet, PickupZoneSet, DeployZoneSet, CombatRadius ) function AI_CARGO_DISPATCHER_APC:New( APCSet, CargoSet, PickupZoneSet, DeployZoneSet, CombatRadius )
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( APCSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_APC local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:NewWithZones( APCSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_APC
self:SetDeploySpeed( 70, 120 ) self:SetDeploySpeed( 120, 70 )
self:SetPickupSpeed( 70, 120 ) self:SetPickupSpeed( 120, 70 )
self:SetPickupRadius( 0, 0 ) self:SetPickupRadius( 0, 0 )
self:SetDeployRadius( 0, 0 ) self:SetDeployRadius( 0, 0 )

View File

@ -650,7 +650,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
local FollowSet = FollowGroupSet:GetSet() local FollowSet = FollowGroupSet:GetSet()
local i = 0 local i = 1 --FF i=0 caused first unit to have no XSpace! Probably needs further adjustments. This is just a quick work around.
for FollowID, FollowGroup in pairs( FollowSet ) do for FollowID, FollowGroup in pairs( FollowSet ) do

View File

@ -664,11 +664,12 @@ do -- CARGO_GROUP
CargoCoordinate = Cargo.CargoObject:GetCoordinate() CargoCoordinate = Cargo.CargoObject:GetCoordinate()
end end
-- if CargoCoordinate then -- FF check if coordinate could be obtained. This was commented out for some (unknown) reason. But the check seems valid!
if CargoCoordinate then
Distance = Coordinate:Get2DDistance( CargoCoordinate ) Distance = Coordinate:Get2DDistance( CargoCoordinate )
-- else else
-- return false return false
-- end end
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } ) self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
if Distance <= self.LoadRadius then if Distance <= self.LoadRadius then

View File

@ -538,8 +538,8 @@ end
-- SpawnCountryID, SpawnCategoryID -- SpawnCountryID, SpawnCategoryID
-- This method is used by the SPAWN class. -- This method is used by the SPAWN class.
-- @param #DATABASE self -- @param #DATABASE self
-- @param #table SpawnTemplate -- @param #table SpawnTemplate Template of the group to spawn.
-- @return #DATABASE self -- @return Wrapper.Group#GROUP Spawned group.
function DATABASE:Spawn( SpawnTemplate ) function DATABASE:Spawn( SpawnTemplate )
self:F( SpawnTemplate.name ) self:F( SpawnTemplate.name )

View File

@ -260,6 +260,10 @@ EVENTS = {
-- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target. -- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target.
-- @field #string TgtTypeName (UNIT) The type name of the target. -- @field #string TgtTypeName (UNIT) The type name of the target.
-- --
-- @field DCS#Airbase place The @{DCS#Airbase}
-- @field Wrapper.Airbase#AIRBASE Place The MOOSE airbase object.
-- @field #string PlaceName The name of the airbase.
--
-- @field weapon The weapon used during the event. -- @field weapon The weapon used during the event.
-- @field Weapon -- @field Weapon
-- @field WeaponName -- @field WeaponName
@ -941,6 +945,12 @@ function EVENT:onEvent( Event )
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget() --Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
end end
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
if Event.place then
Event.Place=AIRBASE:Find(Event.place)
Event.PlaceName=Event.Place:GetName()
end
-- @FC: something like this should be added. -- @FC: something like this should be added.
--[[ --[[
if Event.idx then if Event.idx then
@ -968,7 +978,7 @@ function EVENT:onEvent( Event )
local PriorityEnd = PriorityOrder == -1 and 1 or 5 local PriorityEnd = PriorityOrder == -1 and 1 or 5
if Event.IniObjectCategory ~= Object.Category.STATIC then if Event.IniObjectCategory ~= Object.Category.STATIC then
self:E( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } ) self:T( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end end
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do

View File

@ -295,7 +295,8 @@ end
--- Sends a MESSAGE to a Coalition if the given Condition is true. --- Sends a MESSAGE to a Coalition if the given Condition is true.
-- @param #MESSAGE self -- @param #MESSAGE self
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}. -- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
-- @return #MESSAGE -- @param #boolean Condition Sends the message only if the condition is true.
-- @return #MESSAGE self
function MESSAGE:ToCoalitionIf( CoalitionSide, Condition ) function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
self:F( CoalitionSide ) self:F( CoalitionSide )

View File

@ -397,7 +397,7 @@ do -- COORDINATE
local gotunits=false local gotunits=false
local gotscenery=false local gotscenery=false
local function EvaluateZone( ZoneObject ) local function EvaluateZone(ZoneObject)
if ZoneObject then if ZoneObject then
@ -408,7 +408,7 @@ do -- COORDINATE
--if (ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive()) then --if (ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive()) then
if (ObjectCategory == Object.Category.UNIT and ZoneObject:isExist()) then if (ObjectCategory == Object.Category.UNIT and ZoneObject:isExist()) then
table.insert(Units, ZoneObject) table.insert(Units, UNIT:Find(ZoneObject))
gotunits=true gotunits=true
elseif (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then elseif (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
@ -432,7 +432,7 @@ do -- COORDINATE
world.searchObjects(scanobjects, SphereSearch, EvaluateZone) world.searchObjects(scanobjects, SphereSearch, EvaluateZone)
for _,unit in pairs(Units) do for _,unit in pairs(Units) do
self:T(string.format("Scan found unit %s", unit:getName())) self:T(string.format("Scan found unit %s", unit:GetName()))
end end
for _,static in pairs(Statics) do for _,static in pairs(Statics) do
self:T(string.format("Scan found static %s", static:getName())) self:T(string.format("Scan found static %s", static:getName()))
@ -729,6 +729,20 @@ do -- COORDINATE
return nil return nil
end end
--- Returns the heading from this to another coordinate.
-- @param #COORDINATE self
-- @param #COORDINATE ToCoordinate
-- @return #number Heading in degrees.
function COORDINATE:HeadingTo(ToCoordinate)
local dz=ToCoordinate.z-self.z
local dx=ToCoordinate.x-self.x
local heading=math.deg(math.atan2(dz, dx))
if heading < 0 then
heading = 360 + heading
end
return heading
end
--- Returns the wind direction (from) and strength. --- Returns the wind direction (from) and strength.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param height (Optional) parameter specifying the height ASL. The minimum height will be always be the land height since the wind is zero below the ground. -- @param height (Optional) parameter specifying the height ASL. The minimum height will be always be the land height since the wind is zero below the ground.
@ -949,21 +963,53 @@ do -- COORDINATE
-- @param #COORDINATE.WaypointAction Action The route point action. -- @param #COORDINATE.WaypointAction Action The route point action.
-- @param DCS#Speed Speed Airspeed in km/h. Default is 500 km/h. -- @param DCS#Speed Speed Airspeed in km/h. Default is 500 km/h.
-- @param #boolean SpeedLocked true means the speed is locked. -- @param #boolean SpeedLocked true means the speed is locked.
-- @param Wrapper.Airbase#AIRBASE airbase The airbase for takeoff and landing points.
-- @param #table DCSTasks A table of @{DCS#Task} items which are executed at the waypoint.
-- @param #string description A text description of the waypoint, which will be shown on the F10 map.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAir( AltType, Type, Action, Speed, SpeedLocked ) function COORDINATE:WaypointAir( AltType, Type, Action, Speed, SpeedLocked, airbase, DCSTasks, description )
self:F2( { AltType, Type, Action, Speed, SpeedLocked } ) self:F2( { AltType, Type, Action, Speed, SpeedLocked } )
-- Defaults
AltType=AltType or "RADIO"
if SpeedLocked==nil then
SpeedLocked=true
end
Speed=Speed or 500
-- Waypoint array.
local RoutePoint = {} local RoutePoint = {}
-- Coordinates.
RoutePoint.x = self.x RoutePoint.x = self.x
RoutePoint.y = self.z RoutePoint.y = self.z
-- Altitude.
RoutePoint.alt = self.y RoutePoint.alt = self.y
RoutePoint.alt_type = AltType or "RADIO" RoutePoint.alt_type = AltType
-- Waypoint type.
RoutePoint.type = Type or nil RoutePoint.type = Type or nil
RoutePoint.action = Action or nil RoutePoint.action = Action or nil
-- Set speed/ETA.
RoutePoint.speed = Speed/3.6
RoutePoint.speed_locked = SpeedLocked
RoutePoint.ETA=nil
RoutePoint.ETA_locked = false
-- Waypoint description.
RoutePoint.name=description
-- Airbase parameters for takeoff and landing points.
if airbase then
local AirbaseID = airbase:GetID()
local AirbaseCategory = airbase:GetDesc().category
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
RoutePoint.linkUnit = AirbaseID
RoutePoint.helipadId = AirbaseID
elseif AirbaseCategory == Airbase.Category.AIRDROME then
RoutePoint.airdromeId = AirbaseID
else
self:T("ERROR: Unknown airbase category in COORDINATE:WaypointAir()!")
end
end
RoutePoint.speed = ( Speed and Speed / 3.6 ) or ( 500 / 3.6 )
RoutePoint.speed_locked = true
-- ["task"] = -- ["task"] =
-- { -- {
@ -976,13 +1022,13 @@ do -- COORDINATE
-- }, -- end of ["params"] -- }, -- end of ["params"]
-- }, -- end of ["task"] -- }, -- end of ["task"]
-- Waypoint tasks.
RoutePoint.task = {} RoutePoint.task = {}
RoutePoint.task.id = "ComboTask" RoutePoint.task.id = "ComboTask"
RoutePoint.task.params = {} RoutePoint.task.params = {}
RoutePoint.task.params.tasks = {} RoutePoint.task.params.tasks = DCSTasks or {}
self:T({RoutePoint=RoutePoint})
return RoutePoint return RoutePoint
end end
@ -991,9 +1037,11 @@ do -- COORDINATE
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
-- @param DCS#Speed Speed Airspeed in km/h. -- @param DCS#Speed Speed Airspeed in km/h.
-- @param #table DCSTasks (Optional) A table of @{DCS#Task} items which are executed at the waypoint.
-- @param #string description (Optional) A text description of the waypoint, which will be shown on the F10 map.
-- @return #table The route point. -- @return #table The route point.
function COORDINATE:WaypointAirTurningPoint( AltType, Speed ) function COORDINATE:WaypointAirTurningPoint( AltType, Speed, DCSTasks, description )
return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed ) return self:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true, nil, DCSTasks, description )
end end
@ -1098,11 +1146,14 @@ do -- COORDINATE
--- Gets the nearest airbase with respect to the current coordinates. --- Gets the nearest airbase with respect to the current coordinates.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number AirbaseCategory Category of the airbase. -- @param #number Category (Optional) Category of the airbase. Enumerator of @{Wrapper.Airbase#AIRBASE.Category}.
-- @param #number Coalition (Optional) Coalition of the airbase.
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
-- @return #number Distance to the closest airbase in meters. -- @return #number Distance to the closest airbase in meters.
function COORDINATE:GetClosestAirbase(AirbaseCategory) function COORDINATE:GetClosestAirbase(Category, Coalition)
local airbases=AIRBASE.GetAllAirbases()
-- Get all airbases of the map.
local airbases=AIRBASE.GetAllAirbases(Coalition)
local closest=nil local closest=nil
local distmin=nil local distmin=nil
@ -1110,7 +1161,7 @@ do -- COORDINATE
for _,_airbase in pairs(airbases) do for _,_airbase in pairs(airbases) do
local airbase=_airbase --Wrapper.Airbase#AIRBASE local airbase=_airbase --Wrapper.Airbase#AIRBASE
local category=airbase:GetDesc().category local category=airbase:GetDesc().category
if AirbaseCategory and AirbaseCategory==category or AirbaseCategory==nil then if Category and Category==category or Category==nil then
local dist=self:Get2DDistance(airbase:GetCoordinate()) local dist=self:Get2DDistance(airbase:GetCoordinate())
if closest==nil then if closest==nil then
distmin=dist distmin=dist
@ -1205,11 +1256,16 @@ do -- COORDINATE
return self:GetClosestParkingSpot(airbase, terminaltype, false) return self:GetClosestParkingSpot(airbase, terminaltype, false)
end end
--- Gets the nearest coordinate to a road. --- Gets the nearest coordinate to a road (or railroad).
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #boolean Railroad (Optional) If true, closest point to railroad is returned rather than closest point to conventional road. Default false.
-- @return #COORDINATE Coordinate of the nearest road. -- @return #COORDINATE Coordinate of the nearest road.
function COORDINATE:GetClosestPointToRoad() function COORDINATE:GetClosestPointToRoad(Railroad)
local x,y = land.getClosestPointOnRoads("roads", self.x, self.z) local roadtype="roads"
if Railroad==true then
roadtype="railroads"
end
local x,y = land.getClosestPointOnRoads(roadtype, self.x, self.z)
local vec2={ x = x, y = y } local vec2={ x = x, y = y }
return COORDINATE:NewFromVec2(vec2) return COORDINATE:NewFromVec2(vec2)
end end
@ -1222,9 +1278,12 @@ do -- COORDINATE
-- @param #COORDINATE ToCoord Coordinate of destination. -- @param #COORDINATE ToCoord Coordinate of destination.
-- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path. -- @param #boolean IncludeEndpoints (Optional) Include the coordinate itself and the ToCoordinate in the path.
-- @param #boolean Railroad (Optional) If true, path on railroad is returned. Default false. -- @param #boolean Railroad (Optional) If true, path on railroad is returned. Default false.
-- @param #boolean MarkPath (Optional) If true, place markers on F10 map along the path.
-- @param #boolean SmokePath (Optional) If true, put (green) smoke along the
-- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints. -- @return #table Table of coordinates on road. If no path on road can be found, nil is returned or just the endpoints.
-- @return #number The length of the total path. -- @return #number Tonal length of path.
function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints, Railroad) -- @return #boolean If true a valid path on road/rail was found. If false, only the direct way is possible.
function COORDINATE:GetPathOnRoad(ToCoord, IncludeEndpoints, Railroad, MarkPath, SmokePath)
-- Set road type. -- Set road type.
local RoadType="roads" local RoadType="roads"
@ -1244,17 +1303,42 @@ do -- COORDINATE
Path[1]=self Path[1]=self
end end
-- Assume we could get a valid path.
local GotPath=true
-- Check that DCS routine actually returned a path. There are situations where this is not the case. -- Check that DCS routine actually returned a path. There are situations where this is not the case.
if path then if path then
-- Include all points on road. -- Include all points on road.
for _,_vec2 in ipairs(path) do for _i,_vec2 in ipairs(path) do
Path[#Path+1]=COORDINATE:NewFromVec2(_vec2)
--COORDINATE:NewFromVec2(_vec2):SmokeGreen() local coord=COORDINATE:NewFromVec2(_vec2)
Path[#Path+1]=coord
if MarkPath then
coord:MarkToAll(string.format("Path segment %d.", _i))
end
if SmokePath then
coord:SmokeGreen()
end
end
-- Mark/smoke endpoints
if IncludeEndpoints then
if MarkPath then
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Initinal Point")
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Final Point")
end
if SmokePath then
COORDINATE:NewFromVec2(path[1]):SmokeBlue()
COORDINATE:NewFromVec2(path[#path]):SmokeBlue()
end
end end
else else
self:E("Path is nil. No valid path on road could be found.") self:E("Path is nil. No valid path on road could be found.")
GotPath=false
end end
-- Include end point, which might not be on road. -- Include end point, which might not be on road.
@ -1272,7 +1356,7 @@ do -- COORDINATE
return nil,nil return nil,nil
end end
return Path, Way return Path, Way, GotPath
end end
--- Gets the surface type at the coordinate. --- Gets the surface type at the coordinate.
@ -1429,7 +1513,7 @@ do -- COORDINATE
--- Flares the point in a color. --- Flares the point in a color.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param Utilities.Utils#FLARECOLOR FlareColor -- @param Utilities.Utils#FLARECOLOR FlareColor
-- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth Azimuth (optional) The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:Flare( FlareColor, Azimuth ) function COORDINATE:Flare( FlareColor, Azimuth )
self:F2( { FlareColor } ) self:F2( { FlareColor } )
trigger.action.signalFlare( self:GetVec3(), FlareColor, Azimuth and Azimuth or 0 ) trigger.action.signalFlare( self:GetVec3(), FlareColor, Azimuth and Azimuth or 0 )
@ -1437,7 +1521,7 @@ do -- COORDINATE
--- Flare the COORDINATE White. --- Flare the COORDINATE White.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth Azimuth (optional) The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareWhite( Azimuth ) function COORDINATE:FlareWhite( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.White, Azimuth ) self:Flare( FLARECOLOR.White, Azimuth )
@ -1445,7 +1529,7 @@ do -- COORDINATE
--- Flare the COORDINATE Yellow. --- Flare the COORDINATE Yellow.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth Azimuth (optional) The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareYellow( Azimuth ) function COORDINATE:FlareYellow( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.Yellow, Azimuth ) self:Flare( FLARECOLOR.Yellow, Azimuth )
@ -1453,7 +1537,7 @@ do -- COORDINATE
--- Flare the COORDINATE Green. --- Flare the COORDINATE Green.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param DCS#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. -- @param DCS#Azimuth Azimuth (optional) The azimuth of the flare direction. The default azimuth is 0.
function COORDINATE:FlareGreen( Azimuth ) function COORDINATE:FlareGreen( Azimuth )
self:F2( Azimuth ) self:F2( Azimuth )
self:Flare( FLARECOLOR.Green, Azimuth ) self:Flare( FLARECOLOR.Green, Azimuth )

View File

@ -496,7 +496,7 @@ end
--- Sets the coalition of the spawned group. Note that it might be necessary to also set the country explicitly! --- Sets the coalition of the spawned group. Note that it might be necessary to also set the country explicitly!
-- @param #SPAWN self -- @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. -- @param DCS#coalition.side Coalition Coalition of the group as number of enumerator, i.e. 0=coaliton.side.NEUTRAL, 1=coaliton.side.RED, 2=coalition.side.BLUE.
-- @return #SPAWN self -- @return #SPAWN self
function SPAWN:InitCoalition( Coalition ) function SPAWN:InitCoalition( Coalition )
self:F({coalition=Coalition}) self:F({coalition=Coalition})
@ -1301,6 +1301,7 @@ end
-- @param #number TakeoffAltitude (optional) The altitude above the ground. -- @param #number TakeoffAltitude (optional) The altitude above the ground.
-- @param Wrapper.Airbase#AIRBASE.TerminalType TerminalType (optional) The terminal type the aircraft should be spawned at. See @{Wrapper.Airbase#AIRBASE.TerminalType}. -- @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. -- @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.
-- @param #table Parkingdata (optional) Table holding the coordinates and terminal ids for all units of the group. Spawning will be forced to happen at exactily these spots!
-- @return Wrapper.Group#GROUP that was spawned or nil when nothing was spawned. -- @return Wrapper.Group#GROUP that was spawned or nil when nothing was spawned.
-- @usage -- @usage
-- Spawn_Plane = SPAWN:New( "Plane" ) -- Spawn_Plane = SPAWN:New( "Plane" )
@ -1321,7 +1322,7 @@ end
-- --
-- Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Caucasus.Krymsk ), SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.OpenBig ) -- Spawn_Plane:SpawnAtAirbase( AIRBASE:FindByName( AIRBASE.Caucasus.Krymsk ), SPAWN.Takeoff.Cold, nil, AIRBASE.TerminalType.OpenBig )
-- --
function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType, EmergencyAirSpawn ) -- R2.2, R2.4 function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType, EmergencyAirSpawn, Parkingdata ) -- R2.2, R2.4
self:F( { self.SpawnTemplatePrefix, SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType } ) self:F( { self.SpawnTemplatePrefix, SpawnAirbase, Takeoff, TakeoffAltitude, TerminalType } )
-- Get position of airbase. -- Get position of airbase.
@ -1436,6 +1437,10 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
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, true) nfree=SpawnAirbase:GetFreeParkingSpotsNumber(termtype, true)
spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype, true) spots=SpawnAirbase:GetFreeParkingSpotsTable(termtype, true)
elseif Parkingdata~=nil then
-- Parking data explicitly set by user as input parameter.
nfree=#Parkingdata
spots=Parkingdata
else else
if ishelo then if ishelo then
if termtype==nil then if termtype==nil then
@ -1513,7 +1518,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
PointVec3=spots[1].Coordinate PointVec3=spots[1].Coordinate
else else
-- If there is absolutely not spot ==> air start! -- If there is absolutely no spot ==> air start!
_notenough=true _notenough=true
end end
@ -1617,6 +1622,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
SpawnTemplate.units[UnitID].y = parkingspots[UnitID].z SpawnTemplate.units[UnitID].y = parkingspots[UnitID].z
SpawnTemplate.units[UnitID].alt = parkingspots[UnitID].y SpawnTemplate.units[UnitID].alt = parkingspots[UnitID].y
--parkingspots[UnitID]:MarkToAll(string.format("Group %s spawning at airbase %s on parking spot id %d", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), parkingindex[UnitID]))
end end
else else

View File

@ -189,11 +189,8 @@ function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
end end
--- Creates the original @{Static} at a POINT_VEC2. --- Respawns the original @{Static}.
-- @param #SPAWNSTATIC self -- @param #SPAWNSTATIC self
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
-- @param #string (optional) The name of the new static.
-- @return #SPAWNSTATIC -- @return #SPAWNSTATIC
function SPAWNSTATIC:ReSpawn() function SPAWNSTATIC:ReSpawn()
@ -202,7 +199,6 @@ function SPAWNSTATIC:ReSpawn()
if StaticTemplate then if StaticTemplate then
local StaticUnitTemplate = StaticTemplate.units[1] local StaticUnitTemplate = StaticTemplate.units[1]
StaticTemplate.route = nil StaticTemplate.route = nil
StaticTemplate.groupId = nil StaticTemplate.groupId = nil

View File

@ -317,7 +317,8 @@ end
--- Set the randomization probability of a zone to be selected. --- Set the randomization probability of a zone to be selected.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. -- @param #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
-- @return #ZONE_BASE self
function ZONE_BASE:SetZoneProbability( ZoneProbability ) function ZONE_BASE:SetZoneProbability( ZoneProbability )
self:F( { self:GetName(), ZoneProbability = ZoneProbability } ) self:F( { self:GetName(), ZoneProbability = ZoneProbability } )
@ -934,7 +935,7 @@ end
function ZONE_RADIUS:GetRandomCoordinate( inner, outer ) function ZONE_RADIUS:GetRandomCoordinate( inner, outer )
self:F( self.ZoneName, inner, outer ) self:F( self.ZoneName, inner, outer )
local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2() ) local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2(inner, outer) )
self:T3( { Coordinate = Coordinate } ) self:T3( { Coordinate = Coordinate } )
@ -1079,6 +1080,7 @@ function ZONE_UNIT:GetVec2()
local ZoneVec2 = self.ZoneUNIT:GetVec2() local ZoneVec2 = self.ZoneUNIT:GetVec2()
if ZoneVec2 then if ZoneVec2 then
local heading
if self.relative_to_unit then if self.relative_to_unit then
heading = ( self.ZoneUNIT:GetHeading() or 0.0 ) * math.pi / 180.0 heading = ( self.ZoneUNIT:GetHeading() or 0.0 ) * math.pi / 180.0
else else
@ -1118,7 +1120,8 @@ function ZONE_UNIT:GetRandomVec2()
self:F( self.ZoneName ) self:F( self.ZoneName )
local RandomVec2 = {} local RandomVec2 = {}
local Vec2 = self.ZoneUNIT:GetVec2() --local Vec2 = self.ZoneUNIT:GetVec2() -- FF: This does not take care of the new offset feature!
local Vec2 = self:GetVec2()
if not Vec2 then if not Vec2 then
Vec2 = self.LastVec2 Vec2 = self.LastVec2
@ -1609,16 +1612,16 @@ do -- ZONE_AIRBASE
--- Constructor to create a ZONE_AIRBASE instance, taking the zone name, a zone @{Wrapper.Airbase#AIRBASE} and a radius. --- Constructor to create a ZONE_AIRBASE instance, taking the zone name, a zone @{Wrapper.Airbase#AIRBASE} and a radius.
-- @param #ZONE_AIRBASE self -- @param #ZONE_AIRBASE self
-- @param #string ZoneName Name of the zone. -- @param #string AirbaseName Name of the airbase.
-- @param Wrapper.Airbase#AIRBASE ZoneAirbase The @{Wrapper.Airbase} as the center of the zone. -- @param DCS#Distance Radius (Optional)The radius of the zone in meters. Default 4000 meters.
-- @param DCS#Distance Radius The radius of the zone.
-- @return #ZONE_AIRBASE self -- @return #ZONE_AIRBASE self
function ZONE_AIRBASE:New( AirbaseName ) function ZONE_AIRBASE:New( AirbaseName, Radius )
Radius=Radius or 4000
local Airbase = AIRBASE:FindByName( AirbaseName ) local Airbase = AIRBASE:FindByName( AirbaseName )
local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), 4000 ) ) local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), Radius ) )
self._.ZoneAirbase = Airbase self._.ZoneAirbase = Airbase
self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2() self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2()

View File

@ -208,9 +208,6 @@ do -- country
-- @type country -- @type country
-- @field #country.id id -- @field #country.id id
--- [DCS Enum country](https://wiki.hoggitworld.com/view/DCS_enum_country)
-- @field #country
country = {}
--- [DCS enumerator country](https://wiki.hoggitworld.com/view/DCS_enum_country) --- [DCS enumerator country](https://wiki.hoggitworld.com/view/DCS_enum_country)
-- @type country.id -- @type country.id
@ -289,6 +286,8 @@ do -- country
-- @field OMAN -- @field OMAN
-- @field UNITED_ARAB_EMIRATES -- @field UNITED_ARAB_EMIRATES
country = {} --#country
end -- country end -- country

View File

@ -549,7 +549,7 @@ RAT.id="RAT | "
--- RAT version. --- RAT version.
-- @list version -- @list version
RAT.version={ RAT.version={
version = "2.3.3", version = "2.3.4",
print = true, print = true,
} }
@ -2064,8 +2064,9 @@ end
-- @param #table _waypoint First waypoint to be used (for continue journey, commute, etc). -- @param #table _waypoint First waypoint to be used (for continue journey, commute, etc).
-- @param Core.Point#COORDINATE _lastpos (Optional) Position where the aircraft will be spawned. -- @param Core.Point#COORDINATE _lastpos (Optional) Position where the aircraft will be spawned.
-- @param #number _nrespawn Number of already performed respawn attempts (e.g. spawning on runway bug). -- @param #number _nrespawn Number of already performed respawn attempts (e.g. spawning on runway bug).
-- @param #table parkingdata Explicitly specify the parking spots when spawning at an airport.
-- @return #number Spawn index. -- @return #number Spawn index.
function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _livery, _waypoint, _lastpos, _nrespawn) function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _livery, _waypoint, _lastpos, _nrespawn, parkingdata)
self:F({rat=RAT.id, departure=_departure, destination=_destination, takeoff=_takeoff, landing=_landing, livery=_livery, waypoint=_waypoint, lastpos=_lastpos, nrespawn=_nrespawn}) self:F({rat=RAT.id, departure=_departure, destination=_destination, takeoff=_takeoff, landing=_landing, livery=_livery, waypoint=_waypoint, lastpos=_lastpos, nrespawn=_nrespawn})
-- Set takeoff type. -- Set takeoff type.
@ -2115,7 +2116,7 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
end end
-- Modify the spawn template to follow the flight plan. -- Modify the spawn template to follow the flight plan.
local successful=self:_ModifySpawnTemplate(waypoints, livery, _lastpos, departure, takeoff) local successful=self:_ModifySpawnTemplate(waypoints, livery, _lastpos, departure, takeoff, parkingdata)
if not successful then if not successful then
return nil return nil
end end
@ -2458,7 +2459,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
local VxCruiseMin = math.min(VxCruiseMax*0.70, 166) local VxCruiseMin = math.min(VxCruiseMax*0.70, 166)
-- Cruise speed (randomized). Expectation value at midpoint between min and max. -- Cruise speed (randomized). Expectation value at midpoint between min and max.
local VxCruise = self:_Random_Gaussian((VxCruiseMax-VxCruiseMin)/2+VxCruiseMin, (VxCruiseMax-VxCruiseMax)/4, VxCruiseMin, VxCruiseMax) local VxCruise = UTILS.RandomGaussian((VxCruiseMax-VxCruiseMin)/2+VxCruiseMin, (VxCruiseMax-VxCruiseMax)/4, VxCruiseMin, VxCruiseMax)
-- Climb speed 90% ov Vmax but max 720 km/h. -- Climb speed 90% ov Vmax but max 720 km/h.
local VxClimb = math.min(self.aircraft.Vmax*0.90, 200) local VxClimb = math.min(self.aircraft.Vmax*0.90, 200)
@ -2816,7 +2817,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
end end
-- Set cruise altitude. Selected from Gaussian distribution but limited to FLmin and FLmax. -- Set cruise altitude. Selected from Gaussian distribution but limited to FLmin and FLmax.
local FLcruise=self:_Random_Gaussian(FLcruise_expect, math.abs(FLmax-FLmin)/4, FLmin, FLmax) local FLcruise=UTILS.RandomGaussian(FLcruise_expect, math.abs(FLmax-FLmin)/4, FLmin, FLmax)
-- Overrule setting if user specified a flight level explicitly. -- Overrule setting if user specified a flight level explicitly.
if self.FLuser then if self.FLuser then
@ -5013,38 +5014,6 @@ function RAT:_Randomize(value, fac, lower, upper)
return r return r
end end
--- Generate Gaussian pseudo-random numbers.
-- @param #number x0 Expectation value of distribution.
-- @param #number sigma (Optional) Standard deviation. Default 10.
-- @param #number xmin (Optional) Lower cut-off value.
-- @param #number xmax (Optional) Upper cut-off value.
-- @return #number Gaussian random number.
function RAT:_Random_Gaussian(x0, sigma, xmin, xmax)
-- Standard deviation. Default 10 if not given.
sigma=sigma or 10
local r
local gotit=false
local i=0
while not gotit do
-- Uniform numbers in [0,1). We need two.
local x1=math.random()
local x2=math.random()
-- Transform to Gaussian exp(-(x-x0)²/(2*sigma²).
r = math.sqrt(-2*sigma*sigma * math.log(x1)) * math.cos(2*math.pi * x2) + x0
i=i+1
if (r>=xmin and r<=xmax) or i>100 then
gotit=true
end
end
return r
end
--- Place markers of the waypoints. Note we assume a very specific number and type of waypoints here. --- Place markers of the waypoints. Note we assume a very specific number and type of waypoints here.
-- @param #RAT self -- @param #RAT self
@ -5103,9 +5072,10 @@ end
-- @param Core.Point#COORDINATE spawnplace (Optional) Place where spawning should happen. If not present, first waypoint is taken. -- @param Core.Point#COORDINATE spawnplace (Optional) Place where spawning should happen. If not present, first waypoint is taken.
-- @param Wrapper.Airbase#AIRBASE departure Departure airbase or zone. -- @param Wrapper.Airbase#AIRBASE departure Departure airbase or zone.
-- @param #number takeoff Takeoff type. -- @param #number takeoff Takeoff type.
-- @param #table parkingdata Parking data, i.e. parking spot coordinates and terminal ids for all units of the group.
-- @return #boolean True if modification was successful or nil if not, e.g. when no parking space was found and spawn in air is disabled. -- @return #boolean True if modification was successful or nil if not, e.g. when no parking space was found and spawn in air is disabled.
function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, takeoff) function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, takeoff, parkingdata)
self:F2({waypoints=waypoints, livery=livery, spawnplace=spawnplace, departure=departure, takeoff=takeoff}) self:F2({waypoints=waypoints, livery=livery, spawnplace=spawnplace, departure=departure, takeoff=takeoff, parking=parkingdata})
-- The 3D vector of the first waypoint, i.e. where we actually spawn the template group. -- The 3D vector of the first waypoint, i.e. where we actually spawn the template group.
local PointVec3 = COORDINATE:New(waypoints[1].x, waypoints[1].alt, waypoints[1].y) local PointVec3 = COORDINATE:New(waypoints[1].x, waypoints[1].alt, waypoints[1].y)
@ -5193,6 +5163,10 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
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, true) nfree=departure:GetFreeParkingSpotsNumber(termtype, true)
spots=departure:GetFreeParkingSpotsTable(termtype, true) spots=departure:GetFreeParkingSpotsTable(termtype, true)
elseif parkingdata~=nil then
-- Parking data explicitly set by user as input parameter.
nfree=#parkingdata
spots=parkingdata
else else
-- Helo is spawned. -- Helo is spawned.
if self.category==RAT.cat.heli then if self.category==RAT.cat.heli then

File diff suppressed because it is too large Load Diff

View File

@ -592,3 +592,70 @@ function UTILS.DisplayMissionTime(duration)
local text=string.format("Time: %s - %02d:%02d", local_time, mission_time_minutes, mission_time_seconds) local text=string.format("Time: %s - %02d:%02d", local_time, mission_time_minutes, mission_time_seconds)
MESSAGE:New(text, duration):ToAll() MESSAGE:New(text, duration):ToAll()
end end
--- Generate a Gaussian pseudo-random number.
-- @param #number x0 Expectation value of distribution.
-- @param #number sigma (Optional) Standard deviation. Default 10.
-- @param #number xmin (Optional) Lower cut-off value.
-- @param #number xmax (Optional) Upper cut-off value.
-- @param #number imax (Optional) Max number of tries to get a value between xmin and xmax (if specified). Default 100.
-- @return #number Gaussian random number.
function UTILS.RandomGaussian(x0, sigma, xmin, xmax, imax)
-- Standard deviation. Default 10 if not given.
sigma=sigma or 10
-- Max attempts.
imax=imax or 100
local r
local gotit=false
local i=0
while not gotit do
-- Uniform numbers in [0,1). We need two.
local x1=math.random()
local x2=math.random()
-- Transform to Gaussian exp(-(x-x0)²/(2*sigma²).
r = math.sqrt(-2*sigma*sigma * math.log(x1)) * math.cos(2*math.pi * x2) + x0
i=i+1
if (r>=xmin and r<=xmax) or i>imax then
gotit=true
end
end
return r
end
--- Randomize a value by a certain amount.
-- @param #number value The value which should be randomized
-- @param #number fac Randomization factor.
-- @param #number lower (Optional) Lower limit of the returned value.
-- @param #number upper (Optional) Upper limit of the returned value.
-- @return #number Randomized value.
-- @usage UTILS.Randomize(100, 0.1) returns a value between 90 and 110, i.e. a plus/minus ten percent variation.
-- @usage UTILS.Randomize(100, 0.5, nil, 120) returns a value between 50 and 120, i.e. a plus/minus fivty percent variation with upper bound 120.
function UTILS.Randomize(value, fac, lower, upper)
local min
if lower then
min=math.max(value-value*fac, lower)
else
min=value-value*fac
end
local max
if upper then
max=math.min(value+value*fac, upper)
else
max=value+value*fac
end
local r=math.random(min, max)
return r
end

View File

@ -4,7 +4,7 @@
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- --
-- ### Contributions: -- ### Contributions: **funkyfranky**
-- --
-- === -- ===
-- --
@ -261,6 +261,16 @@ AIRBASE.PersianGulf = {
["Kerman_Airport"] = "Kerman Airport", ["Kerman_Airport"] = "Kerman Airport",
} }
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
-- @type AIRBASE.ParkingSpot
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
-- @field #number TerminalID Terminal ID of the spot. Generally, this is not the same number as displayed in the mission editor.
-- @field #AIRBASE.TerminalType TerminalType Type of the spot, i.e. for which type of aircraft it can be used.
-- @field #boolean TOAC Takeoff or landing aircarft. I.e. this stop is occupied currently by an aircraft until it took of or until it landed.
-- @field #boolean Free This spot is currently free, i.e. there is no alive aircraft on it at the present moment.
-- @field #number TerminalID0 Unknown what this means. If you know, please tell us!
-- @field #number DistToRwy Distance to runway in meters. Currently bugged and giving the same number as the TerminalID.
--- Terminal Types of parking spots. See also https://wiki.hoggitworld.com/view/DCS_func_getParking --- Terminal Types of parking spots. See also https://wiki.hoggitworld.com/view/DCS_func_getParking
-- --
-- Supported types are: -- Supported types are:
@ -273,7 +283,16 @@ AIRBASE.PersianGulf = {
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots. -- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
-- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig. -- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft. -- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
-- @field TerminalType --
-- @type AIRBASE.TerminalType
-- @field #number Runway 16: Valid spawn points on runway.
-- @field #number HelicopterOnly 40: Special spots for Helicopers.
-- @field #number Shelter 68: Hardened Air Shelter. Currently only on Caucaus map.
-- @field #number OpenMed 72: Open/Shelter air airplane only.
-- @field #number OpenBig 104: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
-- @field #number OpenMedOrBig 176: Combines OpenMed and OpenBig spots.
-- @field #number HelicopterUnsable 216: Combines HelicopterOnly, OpenMed and OpenBig.
-- @field #number FighterAircraft 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
AIRBASE.TerminalType = { AIRBASE.TerminalType = {
Runway=16, Runway=16,
HelicopterOnly=40, HelicopterOnly=40,
@ -594,8 +613,9 @@ end
-- @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. -- @param #number nspots (Optional) Number of freeparking spots requested. Default is the number of aircraft in the group.
-- @param #table parkingdata (Optional) Parking spots data table. If not given it is automatically derived from the GetParkingSpotsTable() function.
-- @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, nspots) function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots, parkingdata)
-- Init default -- Init default
scanradius=scanradius or 50 scanradius=scanradius or 50
@ -647,7 +667,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
-- 1. A spot is considered as NOT free until an aircraft that is present has finally taken off. This might be a bit long especiall at smaller airports. -- 1. A spot is considered as NOT free until an aircraft that is present has finally taken off. This might be a bit long especiall at smaller airports.
-- 2. A "free" spot does not take the aircraft size into accound. So if two big aircraft are spawned on spots next to each other, they might overlap and get destroyed. -- 2. A "free" spot does not take the aircraft size into accound. So if two big aircraft are spawned on spots next to each other, they might overlap and get destroyed.
-- 3. The routine return a free spot, if there a static objects placed on the spot. -- 3. The routine return a free spot, if there a static objects placed on the spot.
local parkingdata=self:GetParkingSpotsTable(terminaltype) parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
-- 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)
@ -679,6 +699,8 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE local _spot=parkingspot.Coordinate -- Core.Point#COORDINATE
local _termid=parkingspot.TerminalID local _termid=parkingspot.TerminalID
if AIRBASE._CheckTerminalType(parkingspot.TerminalType, terminaltype) then
-- Very safe uses the DCS getParking() info to check if a spot is free. Unfortunately, the function returns free=false until the aircraft has actually taken-off. -- Very safe uses the DCS getParking() info to check if a spot is free. Unfortunately, the function returns free=false until the aircraft has actually taken-off.
if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) then if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) then
@ -695,11 +717,12 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
-- Check all units. -- Check all units.
for _,unit in pairs(_units) do for _,unit in pairs(_units) do
-- Unis are now returned as MOOSE units not DCS units!
local _vec3=unit:getPoint() --local _vec3=unit:getPoint()
local _coord=COORDINATE:NewFromVec3(_vec3) --local _coord=COORDINATE:NewFromVec3(_vec3)
local _coord=unit:GetCoordinate()
local _dist=_coord:Get2DDistance(_spot) local _dist=_coord:Get2DDistance(_spot)
local _safe=_overlap(aircraft, true, unit, false,_dist) local _safe=_overlap(aircraft, true, unit, true,_dist)
if markobstacles then if markobstacles then
local l,x,y,z=_GetObjectSize(unit) local l,x,y,z=_GetObjectSize(unit)
@ -771,7 +794,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
if nvalid>=_nspots then if nvalid>=_nspots then
return validspots return validspots
end end
end -- check terminal type
end end
-- Retrun spots we found, even if there were not enough. -- Retrun spots we found, even if there were not enough.

View File

@ -617,6 +617,14 @@ function CONTROLLABLE:CommandStopRoute( StopRoute )
end end
--- Give an uncontrolled air controllable the start command.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:StartUncontrolled()
self:SetCommand({id='Start', params={}})
return self
end
-- TASKS FOR AIR CONTROLLABLES -- TASKS FOR AIR CONTROLLABLES
@ -724,28 +732,56 @@ end
-- @param DCS#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
-- @param #number Altitude (optional) The altitude from where to attack. -- @param #number Altitude (optional) The altitude from where to attack.
-- @param #number WeaponType (optional) The WeaponType. -- @param #number WeaponType (optional) The WeaponType.
-- @param #boolean Divebomb (optional) Perform dive bombing. Default false.
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType ) function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb )
self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } ) self:E( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb } )
local _groupattack=false
if GroupAttack then
_groupattack=GroupAttack
end
local _direction=0
local _directionenabled=false
if Direction then
_direction=math.rad(Direction)
_directionenabled=true
end
local _altitude=5000
local _altitudeenabled=false
if Altitude then
_altitude=Altitude
_altitudeenabled=true
end
local _attacktype=nil
if Divebomb then
_attacktype="Dive"
end
local DCSTask local DCSTask
DCSTask = { DCSTask = {
id = 'Bombing', id = 'Bombing',
params = { params = {
point = Vec2, x = Vec2.x,
groupAttack = GroupAttack or false, y = Vec2.y,
groupAttack = _groupattack,
expend = WeaponExpend or "Auto", expend = WeaponExpend or "Auto",
attackQtyLimit = AttackQty and true or false, attackQtyLimit = false, --AttackQty and true or false,
attackQty = AttackQty, attackQty = AttackQty or 1,
directionEnabled = Direction and true or false, directionEnabled = _directionenabled,
direction = Direction, direction = _direction,
altitudeEnabled = Altitude and true or false, altitudeEnabled = _altitudeenabled,
altitude = Altitude or 30, altitude = _altitude,
weaponType = WeaponType, weaponType = WeaponType,
--attackType=_attacktype,
}, },
}, }
self:T3( { DCSTask } ) self:E( { TaskBombing=DCSTask } )
return DCSTask return DCSTask
end end
@ -1611,7 +1647,7 @@ end
-- RouteToZone( GroundGroup, ZoneList[1] ) -- RouteToZone( GroundGroup, ZoneList[1] )
-- --
function CONTROLLABLE:TaskFunction( FunctionString, ... ) function CONTROLLABLE:TaskFunction( FunctionString, ... )
self:F2( { FunctionString, arg } ) self:E({TaskFunction=FunctionString, arguments=arg})
local DCSTask local DCSTask
@ -1622,17 +1658,12 @@ function CONTROLLABLE:TaskFunction( FunctionString, ... )
local ArgumentKey = '_' .. tostring( arg ):match("table: (.*)") local ArgumentKey = '_' .. tostring( arg ):match("table: (.*)")
self:SetState( self, ArgumentKey, arg ) self:SetState( self, ArgumentKey, arg )
DCSScript[#DCSScript+1] = "local Arguments = MissionControllable:GetState( MissionControllable, '" .. ArgumentKey .. "' ) " DCSScript[#DCSScript+1] = "local Arguments = MissionControllable:GetState( MissionControllable, '" .. ArgumentKey .. "' ) "
--DCSScript[#DCSScript+1] = "MissionControllable:ClearState( MissionControllable, '" .. ArgumentKey .. "' ) "
DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable, unpack( Arguments ) )" DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable, unpack( Arguments ) )"
else else
DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable )" DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable )"
end end
DCSTask = self:TaskWrappedAction( DCSTask = self:TaskWrappedAction(self:CommandDoScript(table.concat( DCSScript )))
self:CommandDoScript(
table.concat( DCSScript )
)
)
self:T( DCSTask ) self:T( DCSTask )
@ -2003,6 +2034,28 @@ do -- Route methods
return self return self
end end
--- Make the TRAIN Controllable to drive towards a specific point using railroads.
-- @param #CONTROLLABLE self
-- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to.
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
-- @param #number DelaySeconds (Optional) Wait for the specified seconds before executing the Route. Default is one second.
-- @return #CONTROLLABLE The CONTROLLABLE.
function CONTROLLABLE:RouteGroundOnRailRoads( ToCoordinate, Speed, DelaySeconds)
-- Defaults.
Speed=Speed or 20
DelaySeconds=DelaySeconds or 1
-- Get the route task.
local route=self:TaskGroundOnRailRoads(ToCoordinate, Speed)
-- Route controllable to destination.
self:Route( route, DelaySeconds )
return self
end
--- Make a task for a GROUND Controllable to drive towards a specific point using (mostly) roads. --- Make a task for a GROUND Controllable to drive towards a specific point using (mostly) roads.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
@ -2010,16 +2063,18 @@ do -- Route methods
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
-- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road". -- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road".
-- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer or path on road is less than 5% of total path. -- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer or path on road is less than 5% of total path.
-- @return Task -- @param Core.Point#COORDINATE FromCoordinate (Optional) Explicit initial coordinate. Default is the position of the controllable.
function CONTROLLABLE:TaskGroundOnRoad( ToCoordinate, Speed, OffRoadFormation, Shortcut ) -- @return DCS#Task Task.
-- @return #boolean If true, path on road is possible. If false, task will route the group directly to its destination.
function CONTROLLABLE:TaskGroundOnRoad( ToCoordinate, Speed, OffRoadFormation, Shortcut, FromCoordinate )
self:F2({ToCoordinate=ToCoordinate, Speed=Speed, OffRoadFormation=OffRoadFormation}) self:F2({ToCoordinate=ToCoordinate, Speed=Speed, OffRoadFormation=OffRoadFormation})
-- Defaults. -- Defaults.
Speed=Speed or 20 Speed=Speed or 20
OffRoadFormation=OffRoadFormation or "Off Road" OffRoadFormation=OffRoadFormation or "Off Road"
-- Current coordinate. -- Initial (current) coordinate.
local FromCoordinate = self:GetCoordinate() FromCoordinate = FromCoordinate or self:GetCoordinate()
-- Get path and path length on road including the end points (From and To). -- Get path and path length on road including the end points (From and To).
local PathOnRoad, LengthOnRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, true) local PathOnRoad, LengthOnRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, true)
@ -2028,11 +2083,20 @@ do -- Route methods
local _,LengthRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, false) local _,LengthRoad=FromCoordinate:GetPathOnRoad(ToCoordinate, false)
-- Off road part of the rout: Total=OffRoad+OnRoad. -- Off road part of the rout: Total=OffRoad+OnRoad.
local LengthOffRoad=LengthOnRoad-LengthRoad local LengthOffRoad
local LongRoad
-- Calculate the direct distance between the initial and final points. -- Calculate the direct distance between the initial and final points.
local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate) local LengthDirect=FromCoordinate:Get2DDistance(ToCoordinate)
if PathOnRoad then
-- Off road part of the rout: Total=OffRoad+OnRoad.
LengthOffRoad=LengthOnRoad-LengthRoad
-- Length on road is 10 times longer than direct route or path on road is very short (<5% of total path).
LongRoad=LengthOnRoad and ((LengthOnRoad > LengthDirect*10) or (LengthRoad/LengthOnRoad*100<5))
-- Debug info. -- Debug info.
self:T(string.format("Length on road = %.3f km", LengthOnRoad/1000)) self:T(string.format("Length on road = %.3f km", LengthOnRoad/1000))
self:T(string.format("Length directly = %.3f km", LengthDirect/1000)) self:T(string.format("Length directly = %.3f km", LengthDirect/1000))
@ -2041,15 +2105,14 @@ do -- Route methods
self:T(string.format("Length off road = %.3f km", LengthOffRoad/1000)) self:T(string.format("Length off road = %.3f km", LengthOffRoad/1000))
self:T(string.format("Percent on road = %.1f", LengthRoad/LengthOnRoad*100)) self:T(string.format("Percent on road = %.1f", LengthRoad/LengthOnRoad*100))
end
-- Route, ground waypoints along road. -- Route, ground waypoints along road.
local route={} local route={}
local canroad=false
-- Length on road is 10 times longer than direct route or path on road is very short (<5% of total path).
local LongRoad=LengthOnRoad and ((LengthOnRoad > LengthDirect*10) or (LengthRoad/LengthOnRoad*100<5))
-- Check if a valid path on road could be found. -- Check if a valid path on road could be found.
if PathOnRoad then if PathOnRoad then
-- Check whether the road is very long compared to direct path. -- Check whether the road is very long compared to direct path.
if LongRoad and Shortcut then if LongRoad and Shortcut then
@ -2074,6 +2137,7 @@ do -- Route methods
end end
canroad=true
else else
-- No path on road could be found (can happen!) ==> Route group directly from A to B. -- No path on road could be found (can happen!) ==> Route group directly from A to B.
@ -2082,9 +2146,42 @@ do -- Route methods
end end
return route return route, canroad
end end
--- Make a task for a TRAIN Controllable to drive towards a specific point using railroad.
-- @param #CONTROLLABLE self
-- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to.
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
-- @return Task
function CONTROLLABLE:TaskGroundOnRailRoads(ToCoordinate, Speed)
self:F2({ToCoordinate=ToCoordinate, Speed=Speed})
-- Defaults.
Speed=Speed or 20
-- Current coordinate.
local FromCoordinate = self:GetCoordinate()
-- Get path and path length on railroad.
local PathOnRail, LengthOnRail=FromCoordinate:GetPathOnRoad(ToCoordinate, false, true)
-- Debug info.
self:T(string.format("Length on railroad = %.3f km", LengthOnRail/1000))
-- Route, ground waypoints along road.
local route={}
-- Check if a valid path on railroad could be found.
if PathOnRail then
table.insert(route, PathOnRail[1]:WaypointGround(Speed, "On Railroad"))
table.insert(route, PathOnRail[2]:WaypointGround(Speed, "On Railroad"))
end
return route
end
--- Make the AIR Controllable fly towards a specific point. --- Make the AIR Controllable fly towards a specific point.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self

View File

@ -445,6 +445,38 @@ function GROUP:GetSpeedMax()
return nil return nil
end end
--- Returns the maximum range of the group.
-- If the group is heterogenious and consists of different units, the smallest range of all units is returned.
-- @param #GROUP self
-- @return #number Range in meters.
function GROUP:GetRange()
self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject()
if DCSGroup then
local Units=self:GetUnits()
local Rangemin=nil
for _,unit in pairs(Units) do
local unit=unit --Wrapper.Unit#UNIT
local range=unit:GetRange()
if range then
if Rangemin==nil then
Rangemin=range
elseif range<Rangemin then
Rangemin=range
end
end
end
return Rangemin
end
return nil
end
--- Returns a list of @{Wrapper.Unit} objects of the @{Wrapper.Group}. --- Returns a list of @{Wrapper.Unit} objects of the @{Wrapper.Group}.
-- @param #GROUP self -- @param #GROUP self
@ -659,8 +691,9 @@ function GROUP:GetDCSUnits()
end end
--- Activates a GROUP. --- Activates a late activated GROUP.
-- @param #GROUP self -- @param #GROUP self
-- @return #GROUP self
function GROUP:Activate() function GROUP:Activate()
self:F2( { self.GroupName } ) self:F2( { self.GroupName } )
trigger.action.activateGroup( self:GetDCSObject() ) trigger.action.activateGroup( self:GetDCSObject() )
@ -1453,16 +1486,18 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
SpawnPoint.airdromeId = AirbaseID SpawnPoint.airdromeId = AirbaseID
end end
SpawnPoint.alt = AirbaseCoord:GetLandHeight()
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
-- Get the units of the group. -- Get the units of the group.
local units=self:GetUnits() local units=self:GetUnits()
for UnitID,_unit in pairs(units) do local x
local y
for UnitID=1,#units do
local unit=_unit --Wrapper.Unit#UNIT local unit=units[UnitID] --Wrapper.Unit#UNIT
-- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it! -- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it!
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase) local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
@ -1472,26 +1507,33 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
-- Get unit coordinates for respawning position. -- Get unit coordinates for respawning position.
local uc=unit:GetCoordinate() local uc=unit:GetCoordinate()
SpawnTemplate.units[UnitID].x = Parkingspot.x --uc:MarkToAll(string.format("re-spawnplace %s terminal %d", unit:GetName(), TermialID))
SpawnTemplate.units[UnitID].y = Parkingspot.z
SpawnTemplate.units[UnitID].alt = Parkingspot.y SpawnTemplate.units[UnitID].x = uc.x --Parkingspot.x
SpawnTemplate.units[UnitID].y = uc.z --Parkingspot.z
SpawnTemplate.units[UnitID].alt = uc.y --Parkingspot.y
SpawnTemplate.units[UnitID].parking = TermialID SpawnTemplate.units[UnitID].parking = TermialID
SpawnTemplate.units[UnitID].parking_id = nil SpawnTemplate.units[UnitID].parking_id = nil
--SpawnTemplate.units[UnitID].unitId=nil
end end
SpawnPoint.x = AirbaseCoord.x --SpawnTemplate.groupId=nil
SpawnPoint.y = AirbaseCoord.z
SpawnTemplate.x = AirbaseCoord.x SpawnPoint.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnTemplate.y = AirbaseCoord.z SpawnPoint.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
SpawnPoint.alt = SpawnTemplate.units[1].alt --AirbaseCoord:GetLandHeight()
SpawnTemplate.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnTemplate.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
-- Set uncontrolled state. -- Set uncontrolled state.
SpawnTemplate.uncontrolled=Uncontrolled SpawnTemplate.uncontrolled=Uncontrolled
-- Destroy and respawn. -- Destroy old group.
self:Destroy( false ) self:Destroy(false)
_DATABASE:Spawn( SpawnTemplate ) _DATABASE:Spawn( SpawnTemplate )
-- Reset events. -- Reset events.
@ -1592,8 +1634,7 @@ end
--- Returns true if the first unit of the GROUP is in the air. --- Returns true if the first unit of the GROUP is in the air.
-- @param Wrapper.Group#GROUP self -- @param Wrapper.Group#GROUP self
-- @return #boolean true if in the first unit of the group is in the air. -- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive.
-- @return #nil The GROUP is not existing or not alive.
function GROUP:InAir() function GROUP:InAir()
self:F2( self.GroupName ) self:F2( self.GroupName )
@ -1611,6 +1652,23 @@ function GROUP:InAir()
return nil return nil
end end
--- Returns the DCS descriptor table of the nth unit of the group.
-- @param #GROUP self
-- @param #number n (Optional) The number of the unit for which the dscriptor is returned.
-- @return DCS#Object.Desc The descriptor of the first unit of the group or #nil if the group does not exist any more.
function GROUP:GetDCSDesc(n)
-- Default.
n=n or 1
local unit=self:GetUnit(n)
if unit and unit:IsAlive()~=nil then
local desc=unit:GetDesc()
return desc
end
return nil
end
do -- Route methods do -- Route methods
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}. --- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.

View File

@ -207,7 +207,18 @@ function IDENTIFIABLE:GetCountry()
return nil return nil
end end
--- Returns country name of the Identifiable.
-- @param #IDENTIFIABLE self
-- @return #string Name of the country.
function IDENTIFIABLE:GetCountryName()
self:F2( self.IdentifiableName )
local countryid=self:GetCountry()
for name,id in pairs(country.id) do
if countryid==id then
return name
end
end
end
--- Returns Identifiable descriptor. Descriptor type depends on Identifiable category. --- Returns Identifiable descriptor. Descriptor type depends on Identifiable category.
-- @param #IDENTIFIABLE self -- @param #IDENTIFIABLE self

View File

@ -54,8 +54,7 @@ end
--- Returns the unit's unique identifier. --- Returns the unit's unique identifier.
-- @param Wrapper.Object#OBJECT self -- @param Wrapper.Object#OBJECT self
-- @return DCS#Object.ID ObjectID -- @return DCS#Object.ID ObjectID or #nil if the DCS Object is not existing or alive. Note that the ID is passed as a string and not a number.
-- @return #nil The DCS Object is not existing or alive.
function OBJECT:GetID() function OBJECT:GetID()
local DCSObject = self:GetDCSObject() local DCSObject = self:GetDCSObject()

View File

@ -994,6 +994,7 @@ do -- Cargo
-- return self.__.CargoBayVolumeLimit - CargoVolume -- return self.__.CargoBayVolumeLimit - CargoVolume
-- end -- end
-- --
--- Get Cargo Bay Free Weight in kg. --- Get Cargo Bay Free Weight in kg.
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
-- @return #number CargoBayFreeWeight -- @return #number CargoBayFreeWeight
@ -1018,7 +1019,7 @@ do -- Cargo
-- self.__.CargoBayVolumeLimit = VolumeLimit -- self.__.CargoBayVolumeLimit = VolumeLimit
-- end -- end
--- Get Cargo Bay Weight Limit in kg. --- Set Cargo Bay Weight Limit in kg.
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
-- @param #number WeightLimit -- @param #number WeightLimit
function POSITIONABLE:SetCargoBayWeightLimit( WeightLimit ) function POSITIONABLE:SetCargoBayWeightLimit( WeightLimit )

View File

@ -194,9 +194,10 @@ end
--- Respawn the @{Wrapper.Unit} at the same location with the same properties. --- Respawn the @{Wrapper.Unit} at the same location with the same properties.
-- This is useful to respawn a cargo after it has been destroyed. -- This is useful to respawn a cargo after it has been destroyed.
-- @param #STATIC self -- @param #STATIC self
function STATIC:ReSpawn() -- @param DCS#country.id countryid The country ID used for spawning the new static.
function STATIC:ReSpawn(countryid)
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName ) local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, countryid )
SpawnStatic:ReSpawn() SpawnStatic:ReSpawn()
end end

View File

@ -119,10 +119,12 @@ end
-- @param DCS#Unit DCSUnit An existing DCS Unit object reference. -- @param DCS#Unit DCSUnit An existing DCS Unit object reference.
-- @return #UNIT self -- @return #UNIT self
function UNIT:Find( DCSUnit ) function UNIT:Find( DCSUnit )
if DCSUnit then
local UnitName = DCSUnit:getName() local UnitName = DCSUnit:getName()
local UnitFound = _DATABASE:FindUnit( UnitName ) local UnitFound = _DATABASE:FindUnit( UnitName )
return UnitFound return UnitFound
end
return nil
end end
--- Find a UNIT in the _DATABASE using the name of an existing DCS Unit. --- Find a UNIT in the _DATABASE using the name of an existing DCS Unit.
@ -388,6 +390,28 @@ function UNIT:GetSpeedMax()
return nil return nil
end end
--- Returns the unit's max range in meters derived from the DCS descriptors.
-- For ground units it will return a range of 10,000 km as they have no real range.
-- @param #UNIT self
-- @return #number Range in meters.
function UNIT:GetRange()
self:F2( self.UnitName )
local Desc = self:GetDesc()
if Desc then
local Range = Desc.range --This is in nautical miles for some reason. But should check again!
if Range then
Range=UTILS.NMToMeters(Range)
else
Range=10000000 --10.000 km if no range
end
return Range
end
return nil
end
--- Returns the unit's group if it exist and nil otherwise. --- Returns the unit's group if it exist and nil otherwise.
-- @param Wrapper.Unit#UNIT self -- @param Wrapper.Unit#UNIT self
-- @return Wrapper.Group#GROUP The Group of the Unit. -- @return Wrapper.Group#GROUP The Group of the Unit.