mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
@@ -4143,9 +4143,14 @@ end
|
||||
-- @param #string VehicleTemplate, template name for additional vehicles. Can be nil for no additional vehicles.
|
||||
-- @param #number Liquids Tons of fuel to be added initially to the FARP. Defaults to 10 (tons). Set to 0 for no fill.
|
||||
-- @param #number Equipment Number of equipment items per known item to be added initially to the FARP. Defaults to 10 (items). Set to 0 for no fill.
|
||||
-- @param #number Airframes Number of helicopter airframes per known type in Ops.CSAR#CSAR.AircraftType to be added initially to the FARP. Set to 0 for no airframes.
|
||||
-- @param #string F10Text Text to display on F10 map if given. Handy to post things like the ADF beacon Frequency, Callsign and ATC Frequency.
|
||||
-- @param #boolean DynamicSpawns If true, allow Dynamic Spawns from this FARP.
|
||||
-- @param #boolean HotStart If true and DynamicSpawns is true, allow hot starts for Dynamic Spawns from this FARP.
|
||||
-- @return #list<Wrapper.Static#STATIC> Table of spawned objects and vehicle object (if given).
|
||||
-- @return #string ADFBeaconName Name of the ADF beacon, to be able to remove/stop it later.
|
||||
function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment)
|
||||
-- @return #number MarkerID ID of the F10 Text, to be able to remove it later.
|
||||
function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment,Airframes,F10Text,DynamicSpawns,HotStart)
|
||||
|
||||
-- Set Defaults
|
||||
local farplocation = Coordinate
|
||||
@@ -4159,6 +4164,7 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
||||
local liquids = Liquids or 10
|
||||
liquids = liquids * 1000 -- tons to kg
|
||||
local equip = Equipment or 10
|
||||
local airframes = Airframes or 10
|
||||
local statictypes = ENUMS.FARPObjectTypeNamesAndShape[farptype] or {TypeName="FARP", ShapeName="FARPS"}
|
||||
local STypeName = statictypes.TypeName
|
||||
local SShapeName = statictypes.ShapeName
|
||||
@@ -4168,7 +4174,7 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
||||
-- Spawn FARP
|
||||
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
||||
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
||||
newfarp:InitFARP(callsign,freq,mod)
|
||||
newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
|
||||
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
|
||||
table.insert(ReturnObjects,spawnedfarp)
|
||||
-- Spawn Objects
|
||||
@@ -4221,6 +4227,12 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
||||
end
|
||||
end
|
||||
|
||||
if airframes and airframes > 0 then
|
||||
for typename in pairs (CSAR.AircraftType) do
|
||||
newWH:SetItem(typename,airframes)
|
||||
end
|
||||
end
|
||||
|
||||
local ADFName
|
||||
if ADF and type(ADF) == "number" then
|
||||
local ADFFreq = ADF*1000 -- KHz to Hz
|
||||
@@ -4231,7 +4243,150 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
||||
trigger.action.radioTransmission(Sound, vec3, 0, true, ADFFreq, 250, ADFName)
|
||||
end
|
||||
|
||||
return ReturnObjects, ADFName
|
||||
local MarkerID = nil
|
||||
if F10Text then
|
||||
local Color = {0,0,1}
|
||||
if Coalition == coalition.side.RED then
|
||||
Color = {1,0,0}
|
||||
elseif Coalition == coalition.side.NEUTRAL then
|
||||
Color = {0,1,0}
|
||||
end
|
||||
local Alpha = 0.75
|
||||
local coordinate = Coordinate:Translate(600,0)
|
||||
MarkerID = coordinate:TextToAll(F10Text,Coalition,Color,1,{1,1,1},Alpha,14,true)
|
||||
end
|
||||
|
||||
return ReturnObjects, ADFName, MarkerID
|
||||
end
|
||||
|
||||
--- Spawn a MASH at a given coordinate, optionally, add an ADF Beacon.
|
||||
-- @param #string Name Unique Name of the Mash.
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate where to spawn the MASH. Can be given as a Core.Zone#ZONE object, in this case we take the center coordinate.
|
||||
-- @param #number Country Country ID the MASH belongs to, e.g. country.id.USA or country.id.RUSSIA.
|
||||
-- @param #number ADF (Optional) ADF Frequency in kHz (Kilohertz), if given activate an ADF Beacon at the location of the MASH.
|
||||
-- @param #string Livery (Optional) The livery of the static CH-47, defaults to dark green.
|
||||
-- @param #boolean DeployHelo (Optional) If true, deploy the helicopter static.
|
||||
-- @param #number MASHRadio MASH Radio Frequency, defaults to 127.5.
|
||||
-- @param #number MASHRadioModulation MASH Radio Modulation, defaults to radio.modulation.AM.
|
||||
-- @param #number MASHCallsign Defaults to CALLSIGN.FARP.Berlin.
|
||||
-- @param #table Templates (Optional) You can hand in your own template table of numbered(!) entries. Each entry consist of a relative(!) x,y position and data of a
|
||||
-- static, shape_name is optional. Also, livery_id is optional, but is applied to the helicopter static only.
|
||||
-- @return #table Table of Wrapper.Static#STATIC objects that were spawned.
|
||||
-- @return #string ADFName Name of the ADF Beacon to remove it later.
|
||||
-- @usage
|
||||
-- -- MASH Template example, this one is the built in one used in the function:
|
||||
-- MASHTemplates = {
|
||||
-- [1]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.000000,y=0.000000,},
|
||||
-- [2]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.313533,y=8.778935,},
|
||||
-- [3]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=16.303737,y=20.379671,},
|
||||
-- [4]={category='Helicopters',type='CH-47Fbl1',shape_name='none',heading=0,x=-20.047735,y=-63.166179,livery_id = "us army dark green",},
|
||||
-- [5]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=26.650339,y=20.066138,},
|
||||
-- [6]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.432292,y=9.077099,},
|
||||
-- [7]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=-3.216114,},
|
||||
-- [8]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.439281,y=-3.216114,},
|
||||
-- [9]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=9.155603,},
|
||||
-- [10]={category='Fortifications',type='TACAN_beacon',shape_name='none',heading=0,x=-2.329847,y=-16.579903,},
|
||||
-- [11]={category='Fortifications',type='FARP Fuel Depot',shape_name='GSM Rus',heading=0,x=2.222011,y=4.487030,},
|
||||
-- [12]={category='Fortifications',type='APFC fuel',shape_name='M92_APFCfuel',heading=0,x=3.614927,y=0.367838,},
|
||||
-- [13]={category='Fortifications',type='Camouflage03',shape_name='M92_Camouflage03',heading=0,x=21.544148,y=21.998879,},
|
||||
-- [14]={category='Fortifications',type='Container_generator',shape_name='M92_Container_generator',heading=0,x=20.989192,y=37.314334,},
|
||||
-- [15]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=3.988003,y=8.362333,},
|
||||
-- [16]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=-3.953195,y=12.945844,},
|
||||
-- [17]={category='Fortifications',type='Windsock',shape_name='H-Windsock_RW',heading=0,x=-18.944173,y=-33.042196,},
|
||||
-- [18]={category='Fortifications',type='Tent04',shape_name='M92_Tent04',heading=0,x=21.220671,y=30.247529,},
|
||||
-- }
|
||||
--
|
||||
function UTILS.SpawnMASHStatics(Name,Coordinate,Country,ADF,Livery,DeployHelo,MASHRadio,MASHRadioModulation,MASHCallsign,Templates)
|
||||
|
||||
-- Basic objects table
|
||||
|
||||
local MASHTemplates = {
|
||||
[1]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.000000,y=0.000000,},
|
||||
[2]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.313533,y=8.778935,},
|
||||
[3]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=16.303737,y=20.379671,},
|
||||
[4]={category='Helicopters',type='CH-47Fbl1',shape_name='none',heading=0,x=-20.047735,y=-63.166179,livery_id = "us army dark green",},
|
||||
[5]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=26.650339,y=20.066138,},
|
||||
[6]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.432292,y=9.077099,},
|
||||
[7]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=-3.216114,},
|
||||
[8]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.439281,y=-3.216114,},
|
||||
[9]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=9.155603,},
|
||||
[10]={category='Fortifications',type='TACAN_beacon',shape_name='none',heading=0,x=-2.329847,y=-16.579903,},
|
||||
[11]={category='Fortifications',type='FARP Fuel Depot',shape_name='GSM Rus',heading=0,x=2.222011,y=4.487030,},
|
||||
[12]={category='Fortifications',type='APFC fuel',shape_name='M92_APFCfuel',heading=0,x=3.614927,y=0.367838,},
|
||||
[13]={category='Fortifications',type='Camouflage03',shape_name='M92_Camouflage03',heading=0,x=21.544148,y=21.998879,},
|
||||
[14]={category='Fortifications',type='Container_generator',shape_name='M92_Container_generator',heading=0,x=20.989192,y=37.314334,},
|
||||
[15]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=3.988003,y=8.362333,},
|
||||
[16]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=-3.953195,y=12.945844,},
|
||||
[17]={category='Fortifications',type='Windsock',shape_name='H-Windsock_RW',heading=0,x=-18.944173,y=-33.042196,},
|
||||
[18]={category='Fortifications',type='Tent04',shape_name='M92_Tent04',heading=0,x=21.220671,y=30.247529,},
|
||||
}
|
||||
|
||||
if Templates then MASHTemplates=Templates end
|
||||
|
||||
-- locals
|
||||
local name = Name or "Florence Nightingale"
|
||||
local positionVec2
|
||||
local positionVec3
|
||||
local ReturnStatics = {}
|
||||
local CountryID = Country or country.id.USA
|
||||
local livery = "us army dark green"
|
||||
local MASHRadio = MASHRadio or 127.5
|
||||
local MASHRadioModulation = MASHRadioModulation or radio.modulation.AM
|
||||
local MASHCallsign = MASHCallsign or CALLSIGN.FARP.Berlin
|
||||
|
||||
-- check for coordinate or zone
|
||||
if type(Coordinate) == "table" then
|
||||
if Coordinate:IsInstanceOf("COORDINATE") or Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||
positionVec2 = Coordinate:GetVec2()
|
||||
positionVec3 = Coordinate:GetVec3()
|
||||
end
|
||||
else
|
||||
BASE:E("Spawn MASH - no ZONE or COORDINATE handed!")
|
||||
return
|
||||
end
|
||||
|
||||
-- position
|
||||
local BaseX = positionVec2.x
|
||||
local BaseY = positionVec2.y
|
||||
|
||||
-- Statics
|
||||
for id,object in pairs(MASHTemplates) do
|
||||
local NewName = string.format("%s#%3d",name,id)
|
||||
local vec2 = {x=BaseX+object.x,y=BaseY+object.y}
|
||||
local Coordinate=COORDINATE:NewFromVec2(vec2)
|
||||
local static = SPAWNSTATIC:NewFromType(object.type,object.category,CountryID)
|
||||
if object.shape_name and object.shape_name ~= "none" then
|
||||
static:InitShape(object.shape_name)
|
||||
end
|
||||
if object.category == "Helicopters" and DeployHelo == true then
|
||||
if object.livery_id ~= nil then
|
||||
livery = object.livery_id
|
||||
end
|
||||
static:InitLivery(livery)
|
||||
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||
table.insert(ReturnStatics,newstatic)
|
||||
elseif object.category == "Heliports" then
|
||||
static:InitFARP(MASHCallsign,MASHRadio,MASHRadioModulation,false,false)
|
||||
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||
table.insert(ReturnStatics,newstatic)
|
||||
elseif object.category ~= "Helicopters" and object.category ~= "Heliports" then
|
||||
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||
table.insert(ReturnStatics,newstatic)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Beacon
|
||||
local ADFName
|
||||
if ADF and type(ADF) == "number" then
|
||||
local ADFFreq = ADF*1000 -- KHz to Hz
|
||||
local Sound = "l10n/DEFAULT/beacon.ogg"
|
||||
ADFName = Name .. " ADF "..tostring(ADF).."KHz"
|
||||
--BASE:I(string.format("Adding MASH Beacon %d KHz Name %s",ADF,ADFName))
|
||||
trigger.action.radioTransmission(Sound, positionVec3, 0, true, ADFFreq, 250, ADFName)
|
||||
end
|
||||
|
||||
return ReturnStatics, ADFName
|
||||
end
|
||||
|
||||
--- Converts a Vec2 to a Vec3.
|
||||
@@ -4428,3 +4583,401 @@ end
|
||||
function UTILS.Weather.StopFogAnimation()
|
||||
return world.weather.setFogAnimation({})
|
||||
end
|
||||
|
||||
--- Find a ME created zone by its name
|
||||
function UTILS.GetEnvZone(name)
|
||||
for _,v in ipairs(env.mission.triggers.zones) do
|
||||
if v.name == name then
|
||||
return v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- net.dostring_in
|
||||
function UTILS.DoStringIn(State,DoString)
|
||||
return net.dostring_in(State,DoString)
|
||||
end
|
||||
|
||||
--- Show a picture on the screen to all
|
||||
-- @param #string FileName File name of the picture
|
||||
-- @param #number Duration Duration in seconds, defaults to 10
|
||||
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||
function UTILS.ShowPictureToAll(FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||
ClearView = ClearView or false
|
||||
StartDelay = StartDelay or 0
|
||||
HorizontalAlign = HorizontalAlign or 1
|
||||
VerticalAlign = VerticalAlign or 1
|
||||
Size = Size or 100
|
||||
SizeUnits = SizeUnits or 0
|
||||
|
||||
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||
|
||||
net.dostring_in("mission", string.format("a_out_picture(\"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||
end
|
||||
|
||||
--- Show a picture on the screen to Coalition
|
||||
-- @param #number Coalition Coalition ID, can be coalition.side.BLUE, coalition.side.RED or coalition.side.NEUTRAL
|
||||
-- @param #string FileName File name of the picture
|
||||
-- @param #number Duration Duration in seconds, defaults to 10
|
||||
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||
function UTILS.ShowPictureToCoalition(Coalition, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||
ClearView = ClearView or false
|
||||
StartDelay = StartDelay or 0
|
||||
HorizontalAlign = HorizontalAlign or 1
|
||||
VerticalAlign = VerticalAlign or 1
|
||||
Size = Size or 100
|
||||
SizeUnits = SizeUnits or 0
|
||||
|
||||
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||
|
||||
local coalName = string.lower(UTILS.GetCoalitionName(Coalition))
|
||||
|
||||
net.dostring_in("mission", string.format("a_out_picture_s(\"%s\", \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", coalName, FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||
end
|
||||
|
||||
--- Show a picture on the screen to Country
|
||||
-- @param #number Country Country ID, can be country.id.USA, country.id.RUSSIA, etc.
|
||||
-- @param #string FileName File name of the picture
|
||||
-- @param #number Duration Duration in seconds, defaults to 10
|
||||
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||
function UTILS.ShowPictureToCountry(Country, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||
ClearView = ClearView or false
|
||||
StartDelay = StartDelay or 0
|
||||
HorizontalAlign = HorizontalAlign or 1
|
||||
VerticalAlign = VerticalAlign or 1
|
||||
Size = Size or 100
|
||||
SizeUnits = SizeUnits or 0
|
||||
|
||||
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||
|
||||
net.dostring_in("mission", string.format("a_out_picture_c(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Country, FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||
end
|
||||
|
||||
--- Show a picture on the screen to Group
|
||||
-- @param Wrapper.Group#GROUP Group Group to show the picture to
|
||||
-- @param #string FileName File name of the picture
|
||||
-- @param #number Duration Duration in seconds, defaults to 10
|
||||
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||
function UTILS.ShowPictureToGroup(Group, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||
ClearView = ClearView or false
|
||||
StartDelay = StartDelay or 0
|
||||
HorizontalAlign = HorizontalAlign or 1
|
||||
VerticalAlign = VerticalAlign or 1
|
||||
Size = Size or 100
|
||||
SizeUnits = SizeUnits or 0
|
||||
|
||||
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||
|
||||
net.dostring_in("mission", string.format("a_out_picture_g(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Group:GetID(), FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||
end
|
||||
|
||||
--- Show a picture on the screen to Unit
|
||||
-- @param Wrapper.Unit#UNIT Unit Unit to show the picture to
|
||||
-- @param #string FileName File name of the picture
|
||||
-- @param #number Duration Duration in seconds, defaults to 10
|
||||
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||
function UTILS.ShowPictureToUnit(Unit, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||
ClearView = ClearView or false
|
||||
StartDelay = StartDelay or 0
|
||||
HorizontalAlign = HorizontalAlign or 1
|
||||
VerticalAlign = VerticalAlign or 1
|
||||
Size = Size or 100
|
||||
SizeUnits = SizeUnits or 0
|
||||
|
||||
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||
|
||||
net.dostring_in("mission", string.format("a_out_picture_u(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Unit:GetID(), FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||
end
|
||||
|
||||
--- Load a mission file. This will replace the current mission with the one given carrying along the online clients.
|
||||
-- @param #string FileName Mission filename
|
||||
function UTILS.LoadMission(FileName)
|
||||
net.dostring_in("mission", string.format("a_load_mission(\"%s\")", FileName))
|
||||
end
|
||||
|
||||
--- Set the mission briefing for a coalition.
|
||||
-- @param #number Coalition Briefing coalition ID, can be coalition.side.BLUE, coalition.side.RED or coalition.side.NEUTRAL
|
||||
-- @param #string Text Briefing text, can contain newlines, will be converted formatted properly for DCS
|
||||
-- @param #string Picture Picture file path, can be a file in the DEFAULT folder inside the .miz
|
||||
function UTILS.SetMissionBriefing(Coalition, Text, Picture)
|
||||
Text = Text or ""
|
||||
Text = Text:gsub("\n", "\\n")
|
||||
Picture = Picture or ""
|
||||
local coalName = string.lower(UTILS.GetCoalitionName(Coalition))
|
||||
net.dostring_in("mission", string.format("a_set_briefing(\"%s\", \"%s\", \"%s\")", coalName, Picture, Text))
|
||||
end
|
||||
|
||||
--- Show a helper gate at a DCS#Vec3 position
|
||||
-- @param DCS#Vec3 pos The position
|
||||
-- @param #number heading Heading in degrees, can be 0..359 degrees
|
||||
function UTILS.ShowHelperGate(pos, heading)
|
||||
net.dostring_in("mission",string.format("a_show_helper_gate(%s, %s, %s, %f)", pos.x, pos.y, pos.z, math.rad(heading)))
|
||||
end
|
||||
|
||||
--- Show a helper gate for a unit.
|
||||
-- @param Wrapper.Unit#UNIT Unit The unit to show the gate for
|
||||
-- @param #number Flag Helper gate flag
|
||||
function UTILS.ShowHelperGateForUnit(Unit, Flag)
|
||||
net.dostring_in("mission",string.format("a_show_route_gates_for_unit(%d, \"%d\")", Unit:GetID(), Flag))
|
||||
end
|
||||
|
||||
--- Set the carrier illumination mode. -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||
-- @param #number UnitID Carrier unit ID ( UNIT:GetID() )
|
||||
-- @param #number Mode Illumination mode, can be -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||
function UTILS.SetCarrierIlluminationMode(UnitID, Mode)
|
||||
net.dostring_in("mission",string.format("a_set_carrier_illumination_mode(%d, %d)", UnitID, Mode))
|
||||
end
|
||||
|
||||
--- Shell a zone, zone must ME created
|
||||
-- @param #string name The name of the ME created zone
|
||||
-- @param #number power Equals kg of TNT, e.g. 75
|
||||
-- @param #count Number of shells simulated
|
||||
function UTILS.ShellZone(name, power, count)
|
||||
local z = UTILS.GetEnvZone(name)
|
||||
if z then
|
||||
net.dostring_in("mission",string.format("a_shelling_zone(%d, %d, %d)", z.zoneId, power, count))
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove objects from a zone, zone must ME created
|
||||
-- @param #string name The name of the ME created zone
|
||||
-- @param #number type Type of objects to remove can be 0:all, 1: trees, 2:objects
|
||||
function UTILS.RemoveObjects(name, type)
|
||||
local z = UTILS.GetEnvZone(name)
|
||||
if z then
|
||||
net.dostring_in("mission",string.format("a_remove_scene_objects(%d, %d)", z.zoneId, type))
|
||||
end
|
||||
end
|
||||
|
||||
--- Remove scenery objects from a zone, zone must ME created
|
||||
-- @param #string name The name of the ME created zone
|
||||
-- @param #number level Level of removal
|
||||
function UTILS.DestroyScenery(name, level)
|
||||
local z = UTILS.GetEnvZone(name)
|
||||
if z then
|
||||
net.dostring_in("mission",string.format("a_scenery_destruction_zone(%d, %d)", z.zoneId, level))
|
||||
end
|
||||
end
|
||||
|
||||
--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||
-- @param DCS##Vec3 Center position vector for the search area.
|
||||
-- @param #number SearchRadius Radius of the search area.
|
||||
-- @param #number PosRadius Required clear radius around each position.
|
||||
-- @param #number NumPositions Number of positions to find.
|
||||
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius.
|
||||
function UTILS.GetSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions)
|
||||
return Disposition.getSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions)
|
||||
end
|
||||
|
||||
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||
-- @param Core.Zone#ZONE Zone to search.
|
||||
-- @param #number (Optional) PosRadius Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||
-- @param #number (Optional) NumPositions Number of positions to find. (Default 50)
|
||||
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
|
||||
function UTILS.GetClearZonePositions(Zone, PosRadius, NumPositions)
|
||||
local radius = PosRadius or math.min(Zone:GetRadius()/10, 200)
|
||||
local clearPositions = UTILS.GetSimpleZones(Zone:GetVec3(), Zone:GetRadius(), radius, NumPositions or 50)
|
||||
if clearPositions and #clearPositions > 0 then
|
||||
local validZones = {}
|
||||
for _, vec2 in pairs(clearPositions) do
|
||||
if Zone:IsVec2InZone(vec2) then
|
||||
table.insert(validZones, vec2)
|
||||
end
|
||||
end
|
||||
if #validZones > 0 then
|
||||
return validZones, radius
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||
-- @param Core.Zone#ZONE Zone to search.
|
||||
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
|
||||
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
|
||||
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
|
||||
function UTILS.GetRandomClearZoneCoordinate(Zone, PosRadius, NumPositions)
|
||||
local clearPositions = UTILS.GetClearZonePositions(Zone, PosRadius, NumPositions)
|
||||
if clearPositions and #clearPositions > 0 then
|
||||
local randomPosition, radius = clearPositions[math.random(1, #clearPositions)]
|
||||
return COORDINATE:NewFromVec2(randomPosition), radius
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Find the point on the radius of a circle closest to a point outside of the radius.
|
||||
-- @param DCS#Vec2 Vec1 Simple Vec2 marking the middle of the circle.
|
||||
-- @param #number Radius The radius of the circle.
|
||||
-- @param DCS#Vec2 Vec2 Simple Vec2 marking the point outside of the circle.
|
||||
-- @return DCS#Vec2 Vec2 point on the radius.
|
||||
function UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
|
||||
local r = Radius
|
||||
local cx = Vec1.x or 1
|
||||
local cy = Vec1.y or 1
|
||||
local px = Vec2.x or 1
|
||||
local py = Vec2.y or 1
|
||||
|
||||
-- Berechne den Vektor vom Mittelpunkt zum externen Punkt
|
||||
local dx = px - cx
|
||||
local dy = py - cy
|
||||
|
||||
-- Berechne die Länge des Vektors
|
||||
local dist = math.sqrt(dx * dx + dy * dy)
|
||||
|
||||
-- Wenn der Punkt im Mittelpunkt liegt, wähle einen Punkt auf der X-Achse
|
||||
if dist == 0 then
|
||||
return {x=cx + r, y=cy}
|
||||
end
|
||||
|
||||
-- Normalisiere den Vektor (richtungsweise Vektor mit Länge 1)
|
||||
local norm_dx = dx / dist
|
||||
local norm_dy = dy / dist
|
||||
|
||||
-- Berechne den Punkt auf dem Rand des Kreises
|
||||
local qx = cx + r * norm_dx
|
||||
local qy = cy + r * norm_dy
|
||||
|
||||
local shift_factor = 1
|
||||
qx = qx + shift_factor * norm_dx
|
||||
qy = qy + shift_factor * norm_dy
|
||||
|
||||
return {x=qx, y=qy}
|
||||
end
|
||||
|
||||
--- This function uses Disposition and other fallback logic to find better ground positions for ground units.
|
||||
--- NOTE: This is not a spawn randomizer.
|
||||
--- It will try to find clear ground locations avoiding trees, water, roads, runways, map scenery, statics and other units in the area and modifies the provided positions table.
|
||||
--- Maintains the original layout and unit positions as close as possible by searching for the next closest valid position to each unit.
|
||||
-- @param #table Positions A table of DCS#Vec2 or DCS#Vec3, can be a units table from the group template.
|
||||
-- @param DCS#Vec2 Anchor (Optional) DCS#Vec2 or DCS#Vec3 as anchor point to calculate offset of the units.
|
||||
-- @param #number MaxRadius (Optional) Max radius to search for valid ground locations in meters. Default is double the max radius of the units.
|
||||
-- @param #number Spacing (Optional) Minimum spacing between units in meters. Default is 5% of the search radius or 5 meters, whichever is larger.
|
||||
function UTILS.ValidateAndRepositionGroundUnits(Positions, Anchor, MaxRadius, Spacing)
|
||||
local units = Positions
|
||||
Anchor = Anchor or UTILS.GetCenterPoint(units)
|
||||
local gPos = { x = Anchor.x, y = Anchor.z or Anchor.y }
|
||||
local maxRadius = 0
|
||||
local unitCount = 0
|
||||
for _, unit in pairs(units) do
|
||||
local pos = { x = unit.x, y = unit.z or unit.y }
|
||||
local dist = UTILS.VecDist2D(pos, gPos)
|
||||
if dist > maxRadius then
|
||||
maxRadius = dist
|
||||
end
|
||||
unitCount = unitCount + 1
|
||||
end
|
||||
maxRadius = MaxRadius or math.max(maxRadius * 2, 10)
|
||||
local spacing = Spacing or math.max(maxRadius * 0.05, 5)
|
||||
if unitCount > 0 and maxRadius > 5 then
|
||||
local spots = UTILS.GetSimpleZones(UTILS.Vec2toVec3(gPos), maxRadius, spacing, 1000)
|
||||
if spots and #spots > 0 then
|
||||
local validSpots = {}
|
||||
for _, spot in pairs(spots) do -- Disposition sometimes returns points on roads, hence this filter.
|
||||
if land.getSurfaceType(spot) == land.SurfaceType.LAND then
|
||||
table.insert(validSpots, spot)
|
||||
end
|
||||
end
|
||||
spots = validSpots
|
||||
end
|
||||
|
||||
local step = spacing
|
||||
for _, unit in pairs(units) do
|
||||
local pos = { x = unit.x, y = unit.z or unit.y }
|
||||
local isOnLand = land.getSurfaceType(pos) == land.SurfaceType.LAND
|
||||
local isValid = false
|
||||
if spots and #spots > 0 then
|
||||
local si = 1
|
||||
local sid = 0
|
||||
local closestDist = 100000000
|
||||
local closestSpot
|
||||
for _, spot in pairs(spots) do
|
||||
local dist = UTILS.VecDist2D(pos, spot)
|
||||
if dist < closestDist then
|
||||
closestDist = dist
|
||||
closestSpot = spot
|
||||
sid = si
|
||||
end
|
||||
si = si + 1
|
||||
end
|
||||
if closestSpot then
|
||||
if closestDist >= spacing then
|
||||
pos = closestSpot
|
||||
end
|
||||
isValid = true
|
||||
table.remove(spots, sid)
|
||||
end
|
||||
end
|
||||
|
||||
-- Failsafe calculation
|
||||
if not isValid and not isOnLand then
|
||||
|
||||
local h = UTILS.HdgTo(pos, gPos)
|
||||
local retries = 0
|
||||
while not isValid and retries < 500 do
|
||||
|
||||
local dist = UTILS.VecDist2D(pos, gPos)
|
||||
pos = UTILS.Vec2Translate(pos, step, h)
|
||||
|
||||
local skip = false
|
||||
for _, unit2 in pairs(units) do
|
||||
if unit ~= unit2 then
|
||||
local pos2 = { x = unit2.x, y = unit2.z or unit2.y }
|
||||
local dist2 = UTILS.VecDist2D(pos, pos2)
|
||||
if dist2 < 12 then
|
||||
isValid = false
|
||||
skip = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not skip and dist > step and land.getSurfaceType(pos) == land.SurfaceType.LAND then
|
||||
isValid = true
|
||||
break
|
||||
elseif dist <= step then
|
||||
break
|
||||
end
|
||||
|
||||
retries = retries + 1
|
||||
end
|
||||
end
|
||||
|
||||
if isValid then
|
||||
unit.x = pos.x
|
||||
if unit.z then
|
||||
unit.z = pos.y
|
||||
else
|
||||
unit.y = pos.y
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user