mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #986 from FlightControl-Master/FF/Develop
WAREHOUSE v0.5.1
This commit is contained in:
commit
f655e7e652
@ -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
|
||||||
@ -484,4 +484,4 @@ function AI_CARGO_AIRPLANE:onafterHome(Airplane, From, Event, To, Coordinate, Sp
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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 )
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -663,12 +663,13 @@ do -- CARGO_GROUP
|
|||||||
else
|
else
|
||||||
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
|
||||||
|
|||||||
@ -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 )
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
@ -940,6 +944,12 @@ function EVENT:onEvent( Event )
|
|||||||
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
||||||
--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.
|
||||||
--[[
|
--[[
|
||||||
@ -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
|
||||||
|
|||||||
@ -294,8 +294,9 @@ 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 )
|
||||||
|
|
||||||
|
|||||||
@ -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 and Speed / 3.6 ) or ( 500 / 3.6 )
|
RoutePoint.speed = Speed/3.6
|
||||||
RoutePoint.speed_locked = true
|
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
|
||||||
|
|
||||||
|
|
||||||
-- ["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,13 +1256,18 @@ 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"
|
||||||
local vec2={ x = x, y = y }
|
if Railroad==true then
|
||||||
return COORDINATE:NewFromVec2(vec2)
|
roadtype="railroads"
|
||||||
|
end
|
||||||
|
local x,y = land.getClosestPointOnRoads(roadtype, self.x, self.z)
|
||||||
|
local vec2={ x = x, y = y }
|
||||||
|
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"
|
||||||
@ -1243,18 +1302,43 @@ do -- COORDINATE
|
|||||||
if IncludeEndpoints then
|
if IncludeEndpoints then
|
||||||
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 )
|
||||||
|
|||||||
@ -133,8 +133,8 @@ do -- SET_BASE
|
|||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @return #SET_BASE self
|
-- @return #SET_BASE self
|
||||||
function SET_BASE:GetSet()
|
function SET_BASE:GetSet()
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
return self.Set
|
return self.Set
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -312,12 +312,13 @@ end
|
|||||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
|
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
|
||||||
function ZONE_BASE:SmokeZone( SmokeColor )
|
function ZONE_BASE:SmokeZone( SmokeColor )
|
||||||
self:F2( SmokeColor )
|
self:F2( SmokeColor )
|
||||||
|
|
||||||
end
|
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 } )
|
||||||
|
|
||||||
@ -329,7 +330,7 @@ end
|
|||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
-- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||||
function ZONE_BASE:GetZoneProbability()
|
function ZONE_BASE:GetZoneProbability()
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
return self.ZoneProbability
|
return self.ZoneProbability
|
||||||
end
|
end
|
||||||
@ -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()
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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
@ -591,4 +591,71 @@ function UTILS.DisplayMissionTime(duration)
|
|||||||
local local_time=UTILS.SecondsToClock(Tnow)
|
local local_time=UTILS.SecondsToClock(Tnow)
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -260,6 +260,16 @@ AIRBASE.PersianGulf = {
|
|||||||
["Shiraz_International_Airport"] = "Shiraz International Airport",
|
["Shiraz_International_Airport"] = "Shiraz International Airport",
|
||||||
["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
|
||||||
--
|
--
|
||||||
@ -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,99 +699,102 @@ 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
|
||||||
|
|
||||||
-- 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 AIRBASE._CheckTerminalType(parkingspot.TerminalType, terminaltype) then
|
||||||
if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) 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.
|
||||||
-- DCS getParking() routine returned that spot is not free.
|
if verysafe and (parkingspot.Free==false or parkingspot.TOAC==true) then
|
||||||
self:E(string.format("%s: Parking spot id %d NOT free (or aircraft has not taken off yet). Free=%s, TOAC=%s.", airport, parkingspot.TerminalID, tostring(parkingspot.Free), tostring(parkingspot.TOAC)))
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
-- Scan a radius of 50 meters around the spot.
|
-- DCS getParking() routine returned that spot is not free.
|
||||||
local _,_,_,_units,_statics,_sceneries=_spot:ScanObjects(scanradius, scanunits, scanstatics, scanscenery)
|
self:E(string.format("%s: Parking spot id %d NOT free (or aircraft has not taken off yet). Free=%s, TOAC=%s.", airport, parkingspot.TerminalID, tostring(parkingspot.Free), tostring(parkingspot.TOAC)))
|
||||||
|
|
||||||
-- Loop over objects within scan radius.
|
|
||||||
local occupied=false
|
|
||||||
|
|
||||||
-- Check all units.
|
|
||||||
for _,unit in pairs(_units) do
|
|
||||||
|
|
||||||
local _vec3=unit:getPoint()
|
|
||||||
local _coord=COORDINATE:NewFromVec3(_vec3)
|
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
|
||||||
local _safe=_overlap(aircraft, true, unit, false,_dist)
|
|
||||||
|
|
||||||
if markobstacles then
|
|
||||||
local l,x,y,z=_GetObjectSize(unit)
|
|
||||||
_coord:MarkToAll(string.format("Unit %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", unit:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
|
||||||
end
|
|
||||||
|
|
||||||
if scanunits and not _safe then
|
|
||||||
occupied=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check all statics.
|
|
||||||
for _,static in pairs(_statics) do
|
|
||||||
local _vec3=static:getPoint()
|
|
||||||
local _coord=COORDINATE:NewFromVec3(_vec3)
|
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
|
||||||
local _safe=_overlap(aircraft, true, static, false,_dist)
|
|
||||||
|
|
||||||
if markobstacles then
|
|
||||||
local l,x,y,z=_GetObjectSize(static)
|
|
||||||
_coord:MarkToAll(string.format("Static %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", static:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
|
||||||
end
|
|
||||||
|
|
||||||
if scanstatics and not _safe then
|
|
||||||
occupied=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check all scenery.
|
|
||||||
for _,scenery in pairs(_sceneries) do
|
|
||||||
local _vec3=scenery:getPoint()
|
|
||||||
local _coord=COORDINATE:NewFromVec3(_vec3)
|
|
||||||
local _dist=_coord:Get2DDistance(_spot)
|
|
||||||
local _safe=_overlap(aircraft, true, scenery, false,_dist)
|
|
||||||
|
|
||||||
if markobstacles then
|
|
||||||
local l,x,y,z=_GetObjectSize(scenery)
|
|
||||||
_coord:MarkToAll(string.format("Scenery %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", scenery:getTypeName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
|
||||||
end
|
|
||||||
|
|
||||||
if scanscenery and not _safe then
|
|
||||||
occupied=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Now check the already given spots so that we do not put a large aircraft next to one we already assigned a nearby spot.
|
|
||||||
for _,_takenspot in pairs(validspots) do
|
|
||||||
local _dist=_takenspot.Coordinate:Get2DDistance(_spot)
|
|
||||||
local _safe=_overlap(aircraft, true, aircraft, true,_dist)
|
|
||||||
if not _safe then
|
|
||||||
occupied=true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--_spot:MarkToAll(string.format("Parking spot %d free=%s", parkingspot.TerminalID, tostring(not occupied)))
|
|
||||||
if occupied then
|
|
||||||
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))
|
|
||||||
if nvalid<_nspots then
|
-- Scan a radius of 50 meters around the spot.
|
||||||
table.insert(validspots, {Coordinate=_spot, TerminalID=_termid})
|
local _,_,_,_units,_statics,_sceneries=_spot:ScanObjects(scanradius, scanunits, scanstatics, scanscenery)
|
||||||
end
|
|
||||||
nvalid=nvalid+1
|
|
||||||
end
|
|
||||||
|
|
||||||
end -- loop over units
|
-- Loop over objects within scan radius.
|
||||||
|
local occupied=false
|
||||||
-- We found enough spots.
|
|
||||||
if nvalid>=_nspots then
|
|
||||||
return validspots
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Check all units.
|
||||||
|
for _,unit in pairs(_units) do
|
||||||
|
-- Unis are now returned as MOOSE units not DCS units!
|
||||||
|
--local _vec3=unit:getPoint()
|
||||||
|
--local _coord=COORDINATE:NewFromVec3(_vec3)
|
||||||
|
local _coord=unit:GetCoordinate()
|
||||||
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
|
local _safe=_overlap(aircraft, true, unit, true,_dist)
|
||||||
|
|
||||||
|
if markobstacles then
|
||||||
|
local l,x,y,z=_GetObjectSize(unit)
|
||||||
|
_coord:MarkToAll(string.format("Unit %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", unit:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
|
end
|
||||||
|
|
||||||
|
if scanunits and not _safe then
|
||||||
|
occupied=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check all statics.
|
||||||
|
for _,static in pairs(_statics) do
|
||||||
|
local _vec3=static:getPoint()
|
||||||
|
local _coord=COORDINATE:NewFromVec3(_vec3)
|
||||||
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
|
local _safe=_overlap(aircraft, true, static, false,_dist)
|
||||||
|
|
||||||
|
if markobstacles then
|
||||||
|
local l,x,y,z=_GetObjectSize(static)
|
||||||
|
_coord:MarkToAll(string.format("Static %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", static:getName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
|
end
|
||||||
|
|
||||||
|
if scanstatics and not _safe then
|
||||||
|
occupied=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check all scenery.
|
||||||
|
for _,scenery in pairs(_sceneries) do
|
||||||
|
local _vec3=scenery:getPoint()
|
||||||
|
local _coord=COORDINATE:NewFromVec3(_vec3)
|
||||||
|
local _dist=_coord:Get2DDistance(_spot)
|
||||||
|
local _safe=_overlap(aircraft, true, scenery, false,_dist)
|
||||||
|
|
||||||
|
if markobstacles then
|
||||||
|
local l,x,y,z=_GetObjectSize(scenery)
|
||||||
|
_coord:MarkToAll(string.format("Scenery %s\nx=%.1f y=%.1f z=%.1f\nl=%.1f d=%.1f\nspot %d safe=%s", scenery:getTypeName(),x,y,z,l,_dist, _termid, tostring(_safe)))
|
||||||
|
end
|
||||||
|
|
||||||
|
if scanscenery and not _safe then
|
||||||
|
occupied=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Now check the already given spots so that we do not put a large aircraft next to one we already assigned a nearby spot.
|
||||||
|
for _,_takenspot in pairs(validspots) do
|
||||||
|
local _dist=_takenspot.Coordinate:Get2DDistance(_spot)
|
||||||
|
local _safe=_overlap(aircraft, true, aircraft, true,_dist)
|
||||||
|
if not _safe then
|
||||||
|
occupied=true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--_spot:MarkToAll(string.format("Parking spot %d free=%s", parkingspot.TerminalID, tostring(not occupied)))
|
||||||
|
if occupied then
|
||||||
|
self:T(string.format("%s: Parking spot id %d occupied.", airport, _termid))
|
||||||
|
else
|
||||||
|
self:E(string.format("%s: Parking spot id %d free.", airport, _termid))
|
||||||
|
if nvalid<_nspots then
|
||||||
|
table.insert(validspots, {Coordinate=_spot, TerminalID=_termid})
|
||||||
|
end
|
||||||
|
nvalid=nvalid+1
|
||||||
|
end
|
||||||
|
|
||||||
|
end -- loop over units
|
||||||
|
|
||||||
|
-- We found enough spots.
|
||||||
|
if nvalid>=_nspots then
|
||||||
|
return validspots
|
||||||
|
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.
|
||||||
|
|||||||
@ -376,8 +376,8 @@ end
|
|||||||
-- @param #CLIENT self
|
-- @param #CLIENT self
|
||||||
-- @return Wrapper.Unit#UNIT
|
-- @return Wrapper.Unit#UNIT
|
||||||
function CLIENT:GetClientGroupUnit()
|
function CLIENT:GetClientGroupUnit()
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
local ClientDCSUnit = Unit.getByName( self.ClientName )
|
local ClientDCSUnit = Unit.getByName( self.ClientName )
|
||||||
|
|
||||||
self:T( self.ClientDCSUnit )
|
self:T( self.ClientDCSUnit )
|
||||||
|
|||||||
@ -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 )
|
||||||
|
|
||||||
@ -2002,6 +2033,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.
|
||||||
@ -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,28 +2083,36 @@ 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)
|
||||||
|
|
||||||
-- Debug info.
|
if PathOnRoad then
|
||||||
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 fraction = %.3f km", LengthOnRoad/LengthDirect))
|
|
||||||
self:T(string.format("Length only road = %.3f km", LengthRoad/1000))
|
|
||||||
self:T(string.format("Length off road = %.3f km", LengthOffRoad/1000))
|
|
||||||
self:T(string.format("Percent on road = %.1f", LengthRoad/LengthOnRoad*100))
|
|
||||||
|
|
||||||
|
-- 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.
|
||||||
|
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 fraction = %.3f km", LengthOnRoad/LengthDirect))
|
||||||
|
self:T(string.format("Length only road = %.3f km", LengthRoad/1000))
|
||||||
|
self:T(string.format("Length off road = %.3f km", LengthOffRoad/1000))
|
||||||
|
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,10 +2146,43 @@ do -- Route methods
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return route, canroad
|
||||||
|
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
|
return route
|
||||||
end
|
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
|
||||||
-- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to.
|
-- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to.
|
||||||
|
|||||||
@ -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 old group.
|
||||||
|
self:Destroy(false)
|
||||||
|
|
||||||
-- Destroy and respawn.
|
|
||||||
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}.
|
||||||
|
|||||||
@ -206,8 +206,19 @@ function IDENTIFIABLE:GetCountry()
|
|||||||
self:F( self.ClassName .. " " .. self.IdentifiableName .. " not found!" )
|
self:F( self.ClassName .. " " .. self.IdentifiableName .. " not found!" )
|
||||||
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
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -993,7 +993,8 @@ do -- Cargo
|
|||||||
-- end
|
-- end
|
||||||
-- 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 )
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user