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:
commit
654f752ca0
@ -577,13 +577,19 @@ do -- Zones and Pathlines
|
|||||||
-- For a rectangular polygon drawing, we have the width (y) and height (x).
|
-- For a rectangular polygon drawing, we have the width (y) and height (x).
|
||||||
local w=objectData.width
|
local w=objectData.width
|
||||||
local h=objectData.height
|
local h=objectData.height
|
||||||
|
local rotation = UTILS.ToRadian(objectData.angle or 0)
|
||||||
|
|
||||||
-- Create points from center using with and height (width for y and height for x is a bit confusing, but this is how ED implemented it).
|
local sinRot = math.sin(rotation)
|
||||||
local points={}
|
local cosRot = math.cos(rotation)
|
||||||
points[1]={x=vec2.x-h/2, y=vec2.y+w/2} --Upper left
|
local dx = h / 2
|
||||||
points[2]={x=vec2.x+h/2, y=vec2.y+w/2} --Upper right
|
local dy = w / 2
|
||||||
points[3]={x=vec2.x+h/2, y=vec2.y-w/2} --Lower right
|
|
||||||
points[4]={x=vec2.x-h/2, y=vec2.y-w/2} --Lower left
|
local points = {
|
||||||
|
{ x = -dx * cosRot - (-dy * sinRot) + vec2.x, y = -dx * sinRot + (-dy * cosRot) + vec2.y },
|
||||||
|
{ x = dx * cosRot - (-dy * sinRot) + vec2.x, y = dx * sinRot + (-dy * cosRot) + vec2.y },
|
||||||
|
{ x = dx * cosRot - (dy * sinRot) + vec2.x, y = dx * sinRot + (dy * cosRot) + vec2.y },
|
||||||
|
{ x = -dx * cosRot - (dy * sinRot) + vec2.x, y = -dx * sinRot + (dy * cosRot) + vec2.y },
|
||||||
|
}
|
||||||
|
|
||||||
--local coord=COORDINATE:NewFromVec2(vec2):MarkToAll("MapX, MapY")
|
--local coord=COORDINATE:NewFromVec2(vec2):MarkToAll("MapX, MapY")
|
||||||
|
|
||||||
|
|||||||
@ -7865,6 +7865,28 @@ do -- SET_OPSGROUP
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Iterate the SET_OPSGROUP and count how many GROUPs and UNITs are alive.
|
||||||
|
-- @param #SET_GROUP self
|
||||||
|
-- @return #number The number of GROUPs alive.
|
||||||
|
-- @return #number The number of UNITs alive.
|
||||||
|
function SET_OPSGROUP:CountAlive()
|
||||||
|
local CountG = 0
|
||||||
|
local CountU = 0
|
||||||
|
|
||||||
|
local Set = self:GetSet()
|
||||||
|
|
||||||
|
for GroupID, GroupData in pairs( Set ) do -- For each GROUP in SET_GROUP
|
||||||
|
if GroupData and GroupData:IsAlive() then
|
||||||
|
CountG = CountG + 1
|
||||||
|
-- Count Units.
|
||||||
|
CountU = CountU + GroupData:GetGroup():CountAliveUnits()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return CountG, CountU
|
||||||
|
end
|
||||||
|
|
||||||
--- Finds an OPSGROUP based on the group name.
|
--- Finds an OPSGROUP based on the group name.
|
||||||
-- @param #SET_OPSGROUP self
|
-- @param #SET_OPSGROUP self
|
||||||
-- @param #string GroupName Name of the group.
|
-- @param #string GroupName Name of the group.
|
||||||
|
|||||||
@ -633,7 +633,8 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
|
|
||||||
if self.StaticCopyFrom ~= nil then
|
if self.StaticCopyFrom ~= nil then
|
||||||
mystatic.StaticCopyFrom = self.StaticCopyFrom
|
mystatic.StaticCopyFrom = self.StaticCopyFrom
|
||||||
if not _DATABASE.Templates.Statics[Template.name] then
|
end
|
||||||
|
|
||||||
local TemplateGroup={}
|
local TemplateGroup={}
|
||||||
TemplateGroup.units={}
|
TemplateGroup.units={}
|
||||||
TemplateGroup.units[1]=Template
|
TemplateGroup.units[1]=Template
|
||||||
@ -641,8 +642,6 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
TemplateGroup.y=Template.y
|
TemplateGroup.y=Template.y
|
||||||
TemplateGroup.name=Template.name
|
TemplateGroup.name=Template.name
|
||||||
_DATABASE:_RegisterStaticTemplate( TemplateGroup, self.CoalitionID, self.CategoryID, CountryID )
|
_DATABASE:_RegisterStaticTemplate( TemplateGroup, self.CoalitionID, self.CategoryID, CountryID )
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return mystatic
|
return mystatic
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1934,6 +1934,21 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Updates the current location from a @{Wrapper.Group}.
|
||||||
|
-- @param #ZONE_UNIT self
|
||||||
|
-- @param Wrapper.Group#GROUP Group (optional) Update from this Unit, if nil, update from the UNIT this zone is based on.
|
||||||
|
-- @return self
|
||||||
|
function ZONE_UNIT:UpdateFromUnit(Unit)
|
||||||
|
if Unit and Unit:IsAlive() then
|
||||||
|
local vec2 = Unit:GetVec2()
|
||||||
|
self.LastVec2 = vec2
|
||||||
|
elseif self.ZoneUNIT and self.ZoneUNIT:IsAlive() then
|
||||||
|
local ZoneVec2 = self.ZoneUNIT:GetVec2()
|
||||||
|
self.LastVec2 = ZoneVec2
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the current location of the @{Wrapper.Unit#UNIT}.
|
--- Returns the current location of the @{Wrapper.Unit#UNIT}.
|
||||||
-- @param #ZONE_UNIT self
|
-- @param #ZONE_UNIT self
|
||||||
@ -2071,6 +2086,22 @@ function ZONE_GROUP:GetVec2()
|
|||||||
return ZoneVec2
|
return ZoneVec2
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Updates the current location from a @{Wrapper.Group}.
|
||||||
|
-- @param #ZONE_GROUP self
|
||||||
|
-- @param Wrapper.Group#GROUP Group (optional) Update from this Group, if nil, update from the GROUP this zone is based on.
|
||||||
|
-- @return self
|
||||||
|
function ZONE_GROUP:UpdateFromGroup(Group)
|
||||||
|
if Group and Group:IsAlive() then
|
||||||
|
local vec2 = Group:GetVec2()
|
||||||
|
self.Vec2 = vec2
|
||||||
|
elseif self._.ZoneGROUP and self._.ZoneGROUP:IsAlive() then
|
||||||
|
local ZoneVec2 = self._.ZoneGROUP:GetVec2()
|
||||||
|
self.Vec2 = ZoneVec2
|
||||||
|
self._.ZoneVec2Cache = ZoneVec2
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns a random location within the zone of the @{Wrapper.Group}.
|
--- Returns a random location within the zone of the @{Wrapper.Group}.
|
||||||
-- @param #ZONE_GROUP self
|
-- @param #ZONE_GROUP self
|
||||||
-- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
|
-- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
|
||||||
|
|||||||
@ -321,7 +321,9 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
|||||||
-- Create the CSV file.
|
-- Create the CSV file.
|
||||||
self.AutoSavePath = SavePath
|
self.AutoSavePath = SavePath
|
||||||
self.AutoSave = AutoSave or true
|
self.AutoSave = AutoSave or true
|
||||||
|
if self.AutoSave == true then
|
||||||
self:OpenCSV( GameName )
|
self:OpenCSV( GameName )
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -1935,7 +1937,7 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes,
|
|||||||
TargetUnitType = TargetUnitType or ""
|
TargetUnitType = TargetUnitType or ""
|
||||||
TargetUnitName = TargetUnitName or ""
|
TargetUnitName = TargetUnitName or ""
|
||||||
|
|
||||||
if lfs and io and os and self.AutoSave then
|
if lfs and io and os and self.AutoSave == true and self.CSVFile ~= nil then
|
||||||
self.CSVFile:write(
|
self.CSVFile:write(
|
||||||
'"' .. self.GameName .. '"' .. ',' ..
|
'"' .. self.GameName .. '"' .. ',' ..
|
||||||
'"' .. self.RunTime .. '"' .. ',' ..
|
'"' .. self.RunTime .. '"' .. ',' ..
|
||||||
|
|||||||
@ -33,7 +33,7 @@
|
|||||||
-- @module Functional.Tiresias
|
-- @module Functional.Tiresias
|
||||||
-- @image Functional.Tiresias.jpg
|
-- @image Functional.Tiresias.jpg
|
||||||
|
|
||||||
--- Last Update: July 2025
|
--- Last Update: Oct 2025
|
||||||
|
|
||||||
--- **TIRESIAS** class, extends Core.Base#BASE
|
--- **TIRESIAS** class, extends Core.Base#BASE
|
||||||
-- @type TIRESIAS
|
-- @type TIRESIAS
|
||||||
@ -104,8 +104,8 @@
|
|||||||
-- @field #TIRESIAS
|
-- @field #TIRESIAS
|
||||||
TIRESIAS = {
|
TIRESIAS = {
|
||||||
ClassName = "TIRESIAS",
|
ClassName = "TIRESIAS",
|
||||||
debug = true,
|
debug = false,
|
||||||
version = " 0.0.7-OPT" ,
|
version = " 0.0.8" ,
|
||||||
Interval = 20,
|
Interval = 20,
|
||||||
GroundSet = nil,
|
GroundSet = nil,
|
||||||
VehicleSet = nil,
|
VehicleSet = nil,
|
||||||
@ -140,7 +140,7 @@ function TIRESIAS:New()
|
|||||||
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
||||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
|
|
||||||
self.ExceptionSet = nil --SET_GROUP:New():Clear(false)
|
self.ExceptionSet = SET_GROUP:New() --:Clear(false)
|
||||||
self._cached_zones = {} -- Initialize zone cache
|
self._cached_zones = {} -- Initialize zone cache
|
||||||
|
|
||||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
||||||
@ -224,10 +224,10 @@ function TIRESIAS:AddExceptionSet(Set)
|
|||||||
|
|
||||||
Set:ForEachGroupAlive(
|
Set:ForEachGroupAlive(
|
||||||
function(grp)
|
function(grp)
|
||||||
local inAAASet = self.AAASet:IsIncludeObject(grp)
|
--local inAAASet = self.AAASet:IsIncludeObject(grp)
|
||||||
local inVehSet = self.VehicleSet:IsIncludeObject(grp)
|
--local inVehSet = self.VehicleSet:IsIncludeObject(grp)
|
||||||
local inSAMSet = self.SAMSet:IsIncludeObject(grp)
|
--local inSAMSet = self.SAMSet:IsIncludeObject(grp)
|
||||||
if grp:IsGround() and (not grp.Tiresias) and (not inAAASet) and (not inVehSet) and (not inSAMSet) then
|
if grp:IsGround() and (not grp.Tiresias) then --and (not inAAASet) and (not inVehSet) and (not inSAMSet) then
|
||||||
grp.Tiresias = exception_data
|
grp.Tiresias = exception_data
|
||||||
exceptions:AddGroup(grp, true)
|
exceptions:AddGroup(grp, true)
|
||||||
BASE:T(" TIRESIAS: Added exception group: " .. grp:GetName())
|
BASE:T(" TIRESIAS: Added exception group: " .. grp:GetName())
|
||||||
@ -419,8 +419,8 @@ function TIRESIAS:_SwitchOnGroups(group, radius)
|
|||||||
-- Use cached zones to reduce object creation
|
-- Use cached zones to reduce object creation
|
||||||
local group_name = group:GetName()
|
local group_name = group:GetName()
|
||||||
local cache_key = group_name .. " _" .. radius
|
local cache_key = group_name .. " _" .. radius
|
||||||
local zone = self._cached_zones[cache_key]
|
local zone = self._cached_zones[cache_key] -- Core.Zone#ZONE_RADIUS
|
||||||
local ground = self._cached_groupsets[cache_key]
|
--local ground = self._cached_groupsets[cache_key] -- Core.Set#SET_GROUP
|
||||||
|
|
||||||
if not zone then
|
if not zone then
|
||||||
zone = ZONE_GROUP:New(" Zone-" .. group_name, group, UTILS.NMToMeters(radius))
|
zone = ZONE_GROUP:New(" Zone-" .. group_name, group, UTILS.NMToMeters(radius))
|
||||||
@ -430,12 +430,14 @@ function TIRESIAS:_SwitchOnGroups(group, radius)
|
|||||||
zone:UpdateFromGroup(group)
|
zone:UpdateFromGroup(group)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not ground then
|
--if not ground then
|
||||||
ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
--ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
||||||
self._cached_groupsets[cache_key] = ground
|
--self._cached_groupsets[cache_key] = ground
|
||||||
else
|
--else
|
||||||
ground:FilterZones({zone},true):FilterOnce()
|
--ground:FilterZones({zone},true):FilterOnce()
|
||||||
end
|
zone:Scan({Object.Category.UNIT},{Unit.Category.GROUND_UNIT})
|
||||||
|
local ground = zone:GetScannedSetGroup()
|
||||||
|
--end
|
||||||
|
|
||||||
local count = ground:CountAlive()
|
local count = ground:CountAlive()
|
||||||
|
|
||||||
|
|||||||
@ -6950,6 +6950,9 @@ function AIRBOSS:_AddMarshalGroup( flight, stack )
|
|||||||
-- Convert to clock string.
|
-- Convert to clock string.
|
||||||
local Ccharlie = UTILS.SecondsToClock( flight.Tcharlie )
|
local Ccharlie = UTILS.SecondsToClock( flight.Tcharlie )
|
||||||
|
|
||||||
|
-- Make sure brc is never above 360
|
||||||
|
brc = brc % 360
|
||||||
|
|
||||||
-- Combined marshal call.
|
-- Combined marshal call.
|
||||||
self:_MarshalCallArrived( flight.onboard, flight.case, brc, alt, Ccharlie, P )
|
self:_MarshalCallArrived( flight.onboard, flight.case, brc, alt, Ccharlie, P )
|
||||||
|
|
||||||
@ -7603,7 +7606,7 @@ function AIRBOSS:_InitPlayer( playerData, step )
|
|||||||
playerData.landed = false
|
playerData.landed = false
|
||||||
playerData.Tlso = timer.getTime()
|
playerData.Tlso = timer.getTime()
|
||||||
playerData.Tgroove = nil
|
playerData.Tgroove = nil
|
||||||
playerData.TIG0 = nil
|
playerData.TIG0 = 0 --changed to prevent errors in script when player is not in correct spot
|
||||||
playerData.wire = nil
|
playerData.wire = nil
|
||||||
playerData.flag = -100
|
playerData.flag = -100
|
||||||
playerData.debriefschedulerID = nil
|
playerData.debriefschedulerID = nil
|
||||||
@ -8142,7 +8145,6 @@ end
|
|||||||
--- Check current player status.
|
--- Check current player status.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
function AIRBOSS:_CheckPlayerStatus()
|
function AIRBOSS:_CheckPlayerStatus()
|
||||||
|
|
||||||
-- Loop over all players.
|
-- Loop over all players.
|
||||||
for _playerName, _playerData in pairs( self.players ) do
|
for _playerName, _playerData in pairs( self.players ) do
|
||||||
local playerData = _playerData -- #AIRBOSS.PlayerData
|
local playerData = _playerData -- #AIRBOSS.PlayerData
|
||||||
@ -9644,7 +9646,7 @@ end
|
|||||||
--- Break entry for case I/II recoveries.
|
--- Break entry for case I/II recoveries.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_BreakEntry( playerData ) --Adam Edits begin 7/24/23
|
function AIRBOSS:_BreakEntry( playerData )
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
||||||
local X, Z = self:_GetDistances( playerData.unit )
|
local X, Z = self:_GetDistances( playerData.unit )
|
||||||
@ -9655,111 +9657,16 @@ function AIRBOSS:_BreakEntry( playerData ) --Adam Edits begin 7/24/23
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local stern = self:_GetSternCoord()
|
|
||||||
local coord = playerData.unit:GetCoordinate()
|
|
||||||
local dist = coord:Get2DDistance( stern )
|
|
||||||
|
|
||||||
--adam edits
|
|
||||||
local playerCallsign = playerData.unit:GetCallsign()
|
|
||||||
--trigger.action.outText(' Hornet is hook down on pre-break entry for testing hook argument ', 5)
|
|
||||||
--trigger.action.outText(' Hornet callsign is '..playerCallsign, 5)
|
|
||||||
local playerName = playerData.name
|
|
||||||
local unit = playerData.unit
|
|
||||||
|
|
||||||
--local playerName = unit:GetName()
|
|
||||||
--trigger.action.outText(' Hornet name is '..playerName, 5)
|
|
||||||
local unitClient = Unit.getByName(unit:GetName())
|
|
||||||
local hookArgument = unitClient:getDrawArgumentValue(25)
|
|
||||||
local hookArgument_Tomcat = unitClient:getDrawArgumentValue(1305)
|
|
||||||
local speedMPS = playerData.unit:GetVelocityMPS()
|
|
||||||
local speedKTS = UTILS.MpsToKnots( speedMPS )
|
|
||||||
local player_alt = playerData.unit:GetAltitude()
|
|
||||||
|
|
||||||
player_alt_feet = player_alt * 3.28
|
|
||||||
player_alt_feet = player_alt_feet/10
|
|
||||||
player_alt_feet = math.floor(player_alt_feet)*10
|
|
||||||
|
|
||||||
local player_velocity_round = speedKTS * 1.00
|
|
||||||
player_velocity_round = player_velocity_round/10
|
|
||||||
player_velocity_round = math.floor(player_velocity_round)*10
|
|
||||||
|
|
||||||
local player_alt_feet = player_alt * 3.28
|
|
||||||
player_alt_feet = player_alt_feet/10
|
|
||||||
player_alt_feet = math.floor(player_alt_feet)*10
|
|
||||||
|
|
||||||
local Play_SH_Sound = USERSOUND:New( "Airboss Soundfiles/GreatBallsOfFire.ogg" )
|
|
||||||
local Play_666SH_Sound = USERSOUND:New( "Airboss Soundfiles/Runninwiththedevil.ogg" )
|
|
||||||
local playerType = playerData.actype
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if dist <1000 and clientSHBFlag == false then
|
|
||||||
|
|
||||||
if speedKTS > 450 and speedKTS < 590 then
|
|
||||||
if player_alt_feet < 1500 then
|
|
||||||
if hookArgument > 0 or hookArgument_Tomcat > 0 then
|
|
||||||
--trigger.action.outText(' 1 - Hornet is hook down so SHB!!!! Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = true
|
|
||||||
trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType, 10)
|
|
||||||
local sh_message_to_discord = ('**'..playerName..' is performing a Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
|
|
||||||
HypeMan.sendBotMessage(sh_message_to_discord)
|
|
||||||
Play_SH_Sound:ToAll()
|
|
||||||
clientSHBFlag = true
|
|
||||||
else
|
|
||||||
--trigger.action.outText(' Hornet is hook up on initial and just fast so no SHB. Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = false
|
|
||||||
end
|
|
||||||
-- Next step: Early Break.
|
|
||||||
else
|
|
||||||
end
|
|
||||||
elseif speedKTS > 589 then
|
|
||||||
if player_alt_feet < 625 and player_alt_feet >575 then --SHB 666
|
|
||||||
if hookArgument > 0 or hookArgument_Tomcat > 0 then
|
|
||||||
--trigger.action.outText(' 1 - Hornet is hook down so SHB!!!! Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = true
|
|
||||||
trigger.action.outText(playerName..' performing a 666 Sierra Hotel Break in a '..playerType, 10)
|
|
||||||
local sh_message_to_discord = ('**'..playerName..' is performing a 666 Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
|
|
||||||
HypeMan.sendBotMessage(sh_message_to_discord)
|
|
||||||
Play_666SH_Sound:ToAll()
|
|
||||||
clientSHBFlag = true
|
|
||||||
else
|
|
||||||
--trigger.action.outText(' Hornet is hook up on initial and just fast so no SHB. Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = false
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if hookArgument > 0 or hookArgument_Tomcat > 0 then
|
|
||||||
--trigger.action.outText(' 1 - Hornet is hook down so SHB!!!! Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = true
|
|
||||||
trigger.action.outText(playerName..' performing a Sierra Hotel Break in a '..playerType, 10)
|
|
||||||
local sh_message_to_discord = ('**'..playerName..' is performing a Sierra Hotel Break in a '..playerType..' at '..player_velocity_round..' knots and '..player_alt_feet..' feet!**')
|
|
||||||
HypeMan.sendBotMessage(sh_message_to_discord)
|
|
||||||
Play_SH_Sound:ToAll()
|
|
||||||
clientSHBFlag = true
|
|
||||||
else
|
|
||||||
--trigger.action.outText(' Hornet is hook up on initial and just fast so no SHB. Hook argument is: '..hookArgument, 5)
|
|
||||||
playerData.shb = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
--trigger.action.outText(' Hornet is less than 400 kts so not SHB.... ', 5)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
--trigger.action.outText(' ******TEST OF of Break Entry and distance to CVN is: '..dist, 5)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Check if we are in front of the boat (diffX > 0).
|
-- Check if we are in front of the boat (diffX > 0).
|
||||||
if self:_CheckLimits( X, Z, self.BreakEntry ) then
|
if self:_CheckLimits( X, Z, self.BreakEntry ) then
|
||||||
--trigger.action.outText(' 2 - Hornet is hook down on break entry for testing hook argument ', 5)
|
|
||||||
|
|
||||||
-- Hint for player about altitude, AoA etc.
|
-- Hint for player about altitude, AoA etc.
|
||||||
self:_PlayerHint( playerData )
|
self:_PlayerHint( playerData )
|
||||||
|
-- Next step: Early Break.
|
||||||
self:_SetPlayerStep( playerData, AIRBOSS.PatternStep.EARLYBREAK )
|
self:_SetPlayerStep( playerData, AIRBOSS.PatternStep.EARLYBREAK )
|
||||||
clientSHBFlag = false
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end--Adam Edits end 7/24/23
|
end
|
||||||
|
|
||||||
--- Break.
|
--- Break.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
@ -10361,19 +10268,19 @@ function AIRBOSS:_Groove( playerData )
|
|||||||
if rho >= RAR and rho <= RIM then
|
if rho >= RAR and rho <= RIM then
|
||||||
if gd.LUE > 0.22 and lineupError < -0.22 then
|
if gd.LUE > 0.22 and lineupError < -0.22 then
|
||||||
env.info " Drift Right across centre ==> DR-"
|
env.info " Drift Right across centre ==> DR-"
|
||||||
gd.Drift = " DR"
|
gd.Drift = "DR"
|
||||||
self:T( self.lid .. string.format( "Got Drift Right across centre step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
self:T( self.lid .. string.format( "Got Drift Right across centre step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
||||||
elseif gd.LUE < -0.22 and lineupError > 0.22 then
|
elseif gd.LUE < -0.22 and lineupError > 0.22 then
|
||||||
env.info " Drift Left ==> DL-"
|
env.info " Drift Left ==> DL-"
|
||||||
gd.Drift = " DL"
|
gd.Drift = "DL"
|
||||||
self:T( self.lid .. string.format( "Got Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
self:T( self.lid .. string.format( "Got Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
||||||
elseif gd.LUE > 0.13 and lineupError < -0.14 then
|
elseif gd.LUE > 0.13 and lineupError < -0.14 then
|
||||||
env.info " Little Drift Right across centre ==> (DR-)"
|
env.info " Little Drift Right across centre ==> (DR-)"
|
||||||
gd.Drift = " (DR)"
|
gd.Drift = "(DR)"
|
||||||
self:T( self.lid .. string.format( "Got Little Drift Right across centre at step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
self:T( self.lid .. string.format( "Got Little Drift Right across centre at step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
||||||
elseif gd.LUE < -0.13 and lineupError > 0.14 then
|
elseif gd.LUE < -0.13 and lineupError > 0.14 then
|
||||||
env.info " Little Drift Left across centre ==> (DL-)"
|
env.info " Little Drift Left across centre ==> (DL-)"
|
||||||
gd.Drift = " (DL)"
|
gd.Drift = "(DL)"
|
||||||
self:E( self.lid .. string.format( "Got Little Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
self:E( self.lid .. string.format( "Got Little Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError ) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -12051,10 +11958,12 @@ function AIRBOSS:GetHeading( magnetic )
|
|||||||
hdg = hdg - self.magvar
|
hdg = hdg - self.magvar
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adjust negative values.
|
-- -- Adjust negative values.
|
||||||
if hdg < 0 then
|
-- if hdg < 0 then
|
||||||
hdg = hdg + 360
|
-- hdg = hdg + 360
|
||||||
end
|
-- end
|
||||||
|
|
||||||
|
hdg = hdg % 360 -- using this to replace the above function to prevent negative values and BRC higher than 360
|
||||||
|
|
||||||
return hdg
|
return hdg
|
||||||
end
|
end
|
||||||
@ -12321,7 +12230,7 @@ function AIRBOSS:GetHeadingIntoWind_new( vdeck, magnetic, coord )
|
|||||||
|
|
||||||
-- Ship heading so cross wind is min for the given wind.
|
-- Ship heading so cross wind is min for the given wind.
|
||||||
-- local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360 -- VNAO Edit: Using old heading into wind algorithm
|
-- local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360 -- VNAO Edit: Using old heading into wind algorithm
|
||||||
local intowind = self:GetHeadingIntoWind_old(vdeck) -- VNAO Edit: Using old heading into wind algorithm
|
local intowind = self:GetHeadingIntoWind_old(vdeck,magnetic) -- VNAO Edit: Using old heading into wind algorithm
|
||||||
|
|
||||||
return intowind, v
|
return intowind, v
|
||||||
end
|
end
|
||||||
@ -12751,7 +12660,7 @@ function AIRBOSS:_LSOgrade( playerData )
|
|||||||
local TIG = ""
|
local TIG = ""
|
||||||
-- Analyse flight data and convert to LSO text.
|
-- Analyse flight data and convert to LSO text.
|
||||||
if playerData.Tgroove and playerData.Tgroove <= 360 and playerData.case < 3 then --Circuit Added
|
if playerData.Tgroove and playerData.Tgroove <= 360 and playerData.case < 3 then --Circuit Added
|
||||||
TIG = self:_EvalGrooveTime( playerData ) --Circuit Added
|
TIG = self:_EvalGrooveTime( playerData ) or "N/A" --Circuit Added
|
||||||
end --Circuit Added
|
end --Circuit Added
|
||||||
local GXX, nXX = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.XX )
|
local GXX, nXX = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.XX )
|
||||||
local GIM, nIM = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.IM )
|
local GIM, nIM = self:_Flightdata2Text( playerData, AIRBOSS.GroovePos.IM )
|
||||||
@ -12945,16 +12854,21 @@ function AIRBOSS:_LSOgrade( playerData )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- VNAO EDIT: Subtract 1pt from overall grade if it is a 1 wire. If it's already a 1pt pass, ignore.
|
-- -- VNAO EDIT: Subtract 1pt from overall grade if it is a 1 wire. If it's already a 1pt pass, ignore.
|
||||||
if playerData.wire == 1 and points > 1 then -- VNAO EDIT: added
|
-- if playerData.wire == 1 and points > 1 then -- VNAO EDIT: added
|
||||||
if points == 4 then -- VNAO EDIT: added
|
-- if points == 4 then -- VNAO EDIT: added
|
||||||
points = 3 -- VNAO EDIT: added
|
-- points = 3 -- VNAO EDIT: added
|
||||||
grade = "(OK)" -- VNAO EDIT: added
|
-- grade = "(OK)" -- VNAO EDIT: added
|
||||||
elseif points == 3 then -- VNAO EDIT: added
|
-- elseif points == 3 then -- VNAO EDIT: added
|
||||||
points = 2 -- VNAO EDIT: added
|
-- points = 2 -- VNAO EDIT: added
|
||||||
grade = "--" -- VNAO EDIT: added
|
-- grade = "--" -- VNAO EDIT: added
|
||||||
end -- VNAO EDIT: added
|
-- end -- VNAO EDIT: added
|
||||||
end -- VNAO EDIT: added
|
-- end -- VNAO EDIT: added
|
||||||
|
|
||||||
|
-- Circuit edit only take points awary from a 1 wire if there are more than 4 other deviations
|
||||||
|
if playerData.wire == 1 and points >= 3 and N > 4 then
|
||||||
|
points = points -1
|
||||||
|
end
|
||||||
|
|
||||||
env.info("Returning: " .. grade .. " " .. points .. " " .. G)
|
env.info("Returning: " .. grade .. " " .. points .. " " .. G)
|
||||||
|
|
||||||
@ -13030,6 +12944,7 @@ function AIRBOSS:_Flightdata2Text( playerData, groovestep )
|
|||||||
|
|
||||||
-- Speed via AoA. Depends on aircraft type.
|
-- Speed via AoA. Depends on aircraft type.
|
||||||
local S = nil
|
local S = nil
|
||||||
|
local A = nil --circuit moved this line to be seen outside of this scope
|
||||||
if step~=AIRBOSS.PatternStep.GROOVE_IW then -- VNAO Edit - Added To avoid getting an AOA or GS grade in the wires... let's just check left or right in the wires
|
if step~=AIRBOSS.PatternStep.GROOVE_IW then -- VNAO Edit - Added To avoid getting an AOA or GS grade in the wires... let's just check left or right in the wires
|
||||||
if AIRBOSS.PatternStep.GROOVE_AR and playerData.waveoff == true and playerData.owo == true then -- VNAO Edit - Added
|
if AIRBOSS.PatternStep.GROOVE_AR and playerData.waveoff == true and playerData.owo == true then -- VNAO Edit - Added
|
||||||
-- env.info('Adam MOOSE Edit -AR and waved off so do not add AOA or GS errors to comments ') -- VNAO Edit - Added
|
-- env.info('Adam MOOSE Edit -AR and waved off so do not add AOA or GS errors to comments ') -- VNAO Edit - Added
|
||||||
@ -13050,7 +12965,7 @@ function AIRBOSS:_Flightdata2Text( playerData, groovestep )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Glideslope/altitude. Good [-0.3, 0.4] asymmetric!
|
-- Glideslope/altitude. Good [-0.3, 0.4] asymmetric!
|
||||||
local A = nil
|
|
||||||
if GSE > self.gle.HIGH then
|
if GSE > self.gle.HIGH then
|
||||||
A = underline( "H" )
|
A = underline( "H" )
|
||||||
elseif GSE > self.gle.High then
|
elseif GSE > self.gle.High then
|
||||||
|
|||||||
@ -2324,8 +2324,9 @@ end
|
|||||||
-- @param #number Speed Speed in knots.
|
-- @param #number Speed Speed in knots.
|
||||||
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||||
-- @param #string Formation Formation used by ground units during patrol. Default "Off Road".
|
-- @param #string Formation Formation used by ground units during patrol. Default "Off Road".
|
||||||
|
-- @param #number StayInZoneTime Stay this many seconds in the zone when done, only then drive back.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewCAPTUREZONE(OpsZone, Coalition, Speed, Altitude, Formation)
|
function AUFTRAG:NewCAPTUREZONE(OpsZone, Coalition, Speed, Altitude, Formation, StayInZoneTime)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.CAPTUREZONE)
|
local mission=AUFTRAG:New(AUFTRAG.Type.CAPTUREZONE)
|
||||||
|
|
||||||
@ -2339,6 +2340,7 @@ function AUFTRAG:NewCAPTUREZONE(OpsZone, Coalition, Speed, Altitude, Formation)
|
|||||||
mission.optionROE=ENUMS.ROE.ReturnFire
|
mission.optionROE=ENUMS.ROE.ReturnFire
|
||||||
mission.optionROT=ENUMS.ROT.PassiveDefense
|
mission.optionROT=ENUMS.ROT.PassiveDefense
|
||||||
mission.optionAlarm=ENUMS.AlarmState.Auto
|
mission.optionAlarm=ENUMS.AlarmState.Auto
|
||||||
|
mission.StayInZoneTime = StayInZoneTime
|
||||||
|
|
||||||
mission.missionFraction=0.1
|
mission.missionFraction=0.1
|
||||||
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
|
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
|
||||||
@ -4016,6 +4018,23 @@ function AUFTRAG:IsOver()
|
|||||||
return over
|
return over
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if mission is repeatable.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @return #boolean If true, mission is repeatable.
|
||||||
|
function AUFTRAG:IsRepeatable()
|
||||||
|
local repeatmeS=self.repeatedSuccess<self.NrepeatSuccess or self.repeated<self.Nrepeat
|
||||||
|
local repeatmeF=self.repeatedFailure<self.NrepeatFailure or self.repeated<self.Nrepeat
|
||||||
|
if repeatmeS==true or repeatmeF==true then return true else return false end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if mission is NOT repeatable.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @return #boolean If true, mission is NOT repeatable.
|
||||||
|
function AUFTRAG:IsNotRepeatable()
|
||||||
|
return not self:IsRepeatable()
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if mission is NOT over.
|
--- Check if mission is NOT over.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @return #boolean If true, mission is NOT over yet.
|
-- @return #boolean If true, mission is NOT over yet.
|
||||||
|
|||||||
@ -509,7 +509,7 @@ do
|
|||||||
-- @field #AWACS
|
-- @field #AWACS
|
||||||
AWACS = {
|
AWACS = {
|
||||||
ClassName = "AWACS", -- #string
|
ClassName = "AWACS", -- #string
|
||||||
version = "0.2.72", -- #string
|
version = "0.2.73", -- #string
|
||||||
lid = "", -- #string
|
lid = "", -- #string
|
||||||
coalition = coalition.side.BLUE, -- #number
|
coalition = coalition.side.BLUE, -- #number
|
||||||
coalitiontxt = "blue", -- #string
|
coalitiontxt = "blue", -- #string
|
||||||
@ -1596,6 +1596,16 @@ function AWACS:SetLocale(Locale)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Set own coordinate for BullsEye.
|
||||||
|
-- @param #AWACS self
|
||||||
|
-- @param Core.Point#COORDINATE
|
||||||
|
-- @return #AWACS self
|
||||||
|
function AWACS:SetBullsCoordinate(Coordinate)
|
||||||
|
self:T(self.lid.."SetBullsCoordinate")
|
||||||
|
self.AOCoordinate = Coordinate
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [User] Set the max mission range flights can be away from their home base.
|
--- [User] Set the max mission range flights can be away from their home base.
|
||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #number NM Distance in nautical miles
|
-- @param #number NM Distance in nautical miles
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Last Update July 2025
|
-- Last Update Oct 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@ -315,7 +315,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31
|
|||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="1.0.33"
|
CSAR.version="1.0.34"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@ -1150,11 +1150,11 @@ function CSAR:_EventHandler(EventData)
|
|||||||
|
|
||||||
local initdcscoord = nil
|
local initdcscoord = nil
|
||||||
local initcoord = nil
|
local initcoord = nil
|
||||||
if _event.id == EVENTS.Ejection then
|
if _event.id == EVENTS.Ejection and _event.TgtDCSUnit then
|
||||||
initdcscoord = _event.TgtDCSUnit:getPoint()
|
initdcscoord = _event.TgtDCSUnit:getPoint()
|
||||||
initcoord = COORDINATE:NewFromVec3(initdcscoord)
|
initcoord = COORDINATE:NewFromVec3(initdcscoord)
|
||||||
self:T({initdcscoord})
|
self:T({initdcscoord})
|
||||||
else
|
elseif _event.IniDCSUnit then
|
||||||
initdcscoord = _event.IniDCSUnit:getPoint()
|
initdcscoord = _event.IniDCSUnit:getPoint()
|
||||||
initcoord = COORDINATE:NewFromVec3(initdcscoord)
|
initcoord = COORDINATE:NewFromVec3(initdcscoord)
|
||||||
self:T({initdcscoord})
|
self:T({initdcscoord})
|
||||||
@ -1244,7 +1244,10 @@ function CSAR:_EventHandler(EventData)
|
|||||||
|
|
||||||
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
|
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
|
||||||
self:__Landed(2,_event.IniUnitName, _place)
|
self:__Landed(2,_event.IniUnitName, _place)
|
||||||
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true)
|
local IsHeloBase = false
|
||||||
|
local ABName = _place:GetName()
|
||||||
|
if ABName and string.find(ABName,"^H") then IsHeloBase = true end -- if name starts with an H it's an (possibly elevated) helo base on current maps
|
||||||
|
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true,true,IsHeloBase)
|
||||||
else
|
else
|
||||||
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
|
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
|
||||||
end
|
end
|
||||||
@ -1731,8 +1734,9 @@ end
|
|||||||
-- @param #string heliname Heli name
|
-- @param #string heliname Heli name
|
||||||
-- @param #string groupname Group name
|
-- @param #string groupname Group name
|
||||||
-- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP
|
-- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP
|
||||||
-- @param #boolean noreschedule If true, do not try to reschedule this is distances are not ok (coming from landing event)
|
-- @param #boolean noreschedule If true, do not try to reschedule this if distances are not ok (coming from landing event)
|
||||||
function CSAR:_ScheduledSARFlight(heliname,groupname, isairport, noreschedule)
|
-- @param #boolean IsHeloBase If true, landing took place at a Helo Base (name "H ..." on current maps)
|
||||||
|
function CSAR:_ScheduledSARFlight(heliname,groupname, isairport, noreschedule, IsHeloBase)
|
||||||
self:T(self.lid .. " _ScheduledSARFlight")
|
self:T(self.lid .. " _ScheduledSARFlight")
|
||||||
self:T({heliname,groupname})
|
self:T({heliname,groupname})
|
||||||
local _heliUnit = self:_GetSARHeli(heliname)
|
local _heliUnit = self:_GetSARHeli(heliname)
|
||||||
@ -1758,7 +1762,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname, isairport, noreschedule)
|
|||||||
|
|
||||||
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
|
self:T(self.lid.."[Drop off debug] Check distance to MASH for "..heliname.." Distance km: "..math.floor(_dist/1000))
|
||||||
|
|
||||||
if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then
|
if ( _dist < self.FARPRescueDistance or isairport ) and ((_heliUnit:InAir() == false) or (IsHeloBase == true)) then
|
||||||
self:T(self.lid.."[Drop off debug] Distance ok, door check")
|
self:T(self.lid.."[Drop off debug] Distance ok, door check")
|
||||||
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then
|
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then
|
||||||
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true, true)
|
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true, true)
|
||||||
@ -1773,7 +1777,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname, isairport, noreschedule)
|
|||||||
--queue up
|
--queue up
|
||||||
if not noreschedule then
|
if not noreschedule then
|
||||||
self:__Returning(5,heliname,_woundedGroupName, isairport)
|
self:__Returning(5,heliname,_woundedGroupName, isairport)
|
||||||
self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname, isairport, noreschedule)
|
self:ScheduleOnce(5,self._ScheduledSARFlight,self,heliname,groupname, isairport, noreschedule, IsHeloBase)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
-- @module Ops.CTLD
|
-- @module Ops.CTLD
|
||||||
-- @image OPS_CTLD.jpg
|
-- @image OPS_CTLD.jpg
|
||||||
|
|
||||||
-- Last Update July 2025
|
-- Last Update Oct 2025
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -147,6 +147,7 @@ CTLD_CARGO = {
|
|||||||
Location = ZONE:New(Location)
|
Location = ZONE:New(Location)
|
||||||
end
|
end
|
||||||
self.Location = Location
|
self.Location = Location
|
||||||
|
self.NoMoveToZone = false
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -783,6 +784,7 @@ do
|
|||||||
-- my_ctld:AddCratesCargo("Humvee",{"Humvee"},CTLD_CARGO.Enum.VEHICLE,2,2775,10)
|
-- my_ctld:AddCratesCargo("Humvee",{"Humvee"},CTLD_CARGO.Enum.VEHICLE,2,2775,10)
|
||||||
-- -- additionally, you can limit **where** the stock is available (one location only!) - this one is available in a zone called "Vehicle Store".
|
-- -- additionally, you can limit **where** the stock is available (one location only!) - this one is available in a zone called "Vehicle Store".
|
||||||
-- my_ctld:AddCratesCargo("Humvee",{"Humvee"},CTLD_CARGO.Enum.VEHICLE,2,2775,10,nil,nil,"Vehicle Store")
|
-- my_ctld:AddCratesCargo("Humvee",{"Humvee"},CTLD_CARGO.Enum.VEHICLE,2,2775,10,nil,nil,"Vehicle Store")
|
||||||
|
-- -- Tip: if you want the spawned/built group NOT to move to a MOVE zone, replace AddCratesCargo with AddCratesCargoNoMove (same parameters).
|
||||||
--
|
--
|
||||||
-- -- add infantry unit called "Forward Ops Base" using template "FOB", of type FOB, size 4, i.e. needs four crates to be build:
|
-- -- add infantry unit called "Forward Ops Base" using template "FOB", of type FOB, size 4, i.e. needs four crates to be build:
|
||||||
-- my_ctld:AddCratesCargo("Forward Ops Base",{"FOB"},CTLD_CARGO.Enum.FOB,4)
|
-- my_ctld:AddCratesCargo("Forward Ops Base",{"FOB"},CTLD_CARGO.Enum.FOB,4)
|
||||||
@ -1556,6 +1558,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
self.smokedistance = 2000
|
self.smokedistance = 2000
|
||||||
self.movetroopstowpzone = true
|
self.movetroopstowpzone = true
|
||||||
self.movetroopsdistance = 5000
|
self.movetroopsdistance = 5000
|
||||||
|
self.returntroopstobase = true -- if set to false, troops would stay after deployment inside a load zone.
|
||||||
self.troopdropzoneradius = 100
|
self.troopdropzoneradius = 100
|
||||||
|
|
||||||
self.VehicleMoveFormation = AI.Task.VehicleFormation.VEE
|
self.VehicleMoveFormation = AI.Task.VehicleFormation.VEE
|
||||||
@ -3676,7 +3679,7 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.SHIP)
|
||||||
end
|
end
|
||||||
if inzone then
|
if inzone then
|
||||||
droppingatbase = true
|
droppingatbase = self.returntroopstobase
|
||||||
end
|
end
|
||||||
-- check for hover unload
|
-- check for hover unload
|
||||||
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
|
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
|
||||||
@ -4513,7 +4516,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
for _,cargoObj in pairs(self.Cargo_Crates) do
|
for _,cargoObj in pairs(self.Cargo_Crates) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)",needed,needed==1 and "" or "s",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4524,7 +4528,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
for _,cargoObj in pairs(self.Cargo_Statics) do
|
for _,cargoObj in pairs(self.Cargo_Statics) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)",needed,needed==1 and "" or "s",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4536,7 +4541,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
else
|
else
|
||||||
for _,cargoObj in pairs(self.Cargo_Crates) do
|
for _,cargoObj in pairs(self.Cargo_Crates) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)",needed,needed==1 and "" or "s",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4547,7 +4553,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
for _,cargoObj in pairs(self.Cargo_Statics) do
|
for _,cargoObj in pairs(self.Cargo_Statics) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)",needed,needed==1 and "" or "s",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4559,14 +4566,15 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if self.usesubcats then
|
if self.usesubcats == true then
|
||||||
local subcatmenus = {}
|
local subcatmenus = {}
|
||||||
for catName, _ in pairs(self.subcats) do
|
for catName, _ in pairs(self.subcats) do
|
||||||
subcatmenus[catName] = MENU_GROUP:New(_group, catName, cratesmenu) -- fixed variable case
|
subcatmenus[catName] = MENU_GROUP:New(_group, catName, cratesmenu) -- fixed variable case
|
||||||
end
|
end
|
||||||
for _, cargoObj in pairs(self.Cargo_Crates) do
|
for _, cargoObj in pairs(self.Cargo_Crates) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)", needed, needed==1 and "" or "s", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4575,7 +4583,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
for _, cargoObj in pairs(self.Cargo_Statics) do
|
for _, cargoObj in pairs(self.Cargo_Statics) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)", needed, needed==1 and "" or "s", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4585,7 +4594,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
else
|
else
|
||||||
for _, cargoObj in pairs(self.Cargo_Crates) do
|
for _, cargoObj in pairs(self.Cargo_Crates) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)", needed, needed==1 and "" or "s", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -4594,7 +4604,8 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
for _, cargoObj in pairs(self.Cargo_Statics) do
|
for _, cargoObj in pairs(self.Cargo_Statics) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
local needed = cargoObj:GetCratesNeeded() or 1
|
||||||
|
local txt = string.format("%d crate%s %s (%dkg)", needed, needed==1 and "" or "s", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
||||||
if cargoObj.Location then txt = txt.."[R]" end
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
local stock = cargoObj:GetStock()
|
local stock = cargoObj:GetStock()
|
||||||
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
if stock >= 0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
@ -5134,7 +5145,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
|||||||
inzone, zonename, zone, distance = self:IsUnitInZone(Unit, CTLD.CargoZoneType.SHIP)
|
inzone, zonename, zone, distance = self:IsUnitInZone(Unit, CTLD.CargoZoneType.SHIP)
|
||||||
end
|
end
|
||||||
if inzone then
|
if inzone then
|
||||||
droppingatbase = true
|
droppingatbase = self.returntroopstobase
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
@ -5426,6 +5437,52 @@ function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,Sub
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Identical to AddCratesCargo, but registers the cargo so the spawned/built group does not move to MOVE zones.
|
||||||
|
--- User function - Add *generic* crate-type loadable as cargo. This type will create crates that need to be loaded, moved, dropped and built.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string Name Unique name of this type of cargo. E.g. "Humvee".
|
||||||
|
-- @param #table Templates Table of #string names of late activated Wrapper.Group#GROUP building this cargo.
|
||||||
|
-- @param #CTLD_CARGO.Enum Type Type of cargo. I.e. VEHICLE or FOB. VEHICLE will move to destination zones when dropped/build, FOB stays put.
|
||||||
|
-- @param #number NoCrates Number of crates needed to build this cargo.
|
||||||
|
-- @param #number PerCrateMass Mass in kg of each crate
|
||||||
|
-- @param #number Stock Number of buildable groups in stock. Nil for unlimited.
|
||||||
|
-- @param #string SubCategory Name of sub-category (optional).
|
||||||
|
-- @param #boolean DontShowInMenu (optional) If set to "true" this won't show up in the menu.
|
||||||
|
-- @param Core.Zone#ZONE Location (optional) If set, the cargo item is **only** available here. Can be a #ZONE object or the name of a zone as #string.
|
||||||
|
-- @param #string UnitTypes Unit type names (optional). If set, only these unit types can pick up the cargo, e.g. "UH-1H" or {"UH-1H","OH58D"}.
|
||||||
|
-- @param #string Category Static category name (optional). If set, spawn cargo crate with an alternate category type, e.g. "Cargos".
|
||||||
|
-- @param #string TypeName Static type name (optional). If set, spawn cargo crate with an alternate type shape, e.g. "iso_container".
|
||||||
|
-- @param #string ShapeName Static shape name (optional). If set, spawn cargo crate with an alternate type sub-shape, e.g. "iso_container_cargo".
|
||||||
|
-- @return #CTLD self
|
||||||
|
function CTLD:AddCratesCargoNoMove(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location,UnitTypes,Category,TypeName,ShapeName)
|
||||||
|
self:T(self.lid .. " AddCratesCargoNoMove")
|
||||||
|
if not self:_CheckTemplates(Templates) then
|
||||||
|
self:E(self.lid .. "Crates Cargo for " .. Name .. " has missing template(s)!" )
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
self.CargoCounter = self.CargoCounter + 1
|
||||||
|
local cargo = CTLD_CARGO:New(self.CargoCounter,Name,Templates,Type,false,false,NoCrates,nil,nil,PerCrateMass,Stock,SubCategory,DontShowInMenu,Location)
|
||||||
|
cargo.NoMoveToZone = true
|
||||||
|
if UnitTypes then
|
||||||
|
cargo:AddUnitTypeName(UnitTypes)
|
||||||
|
end
|
||||||
|
cargo:SetStaticTypeAndShape("Cargos",self.basetype)
|
||||||
|
if TypeName then
|
||||||
|
cargo:SetStaticTypeAndShape(Category,TypeName,ShapeName)
|
||||||
|
end
|
||||||
|
table.insert(self.Cargo_Crates,cargo)
|
||||||
|
self.templateToCargoName = self.templateToCargoName or {}
|
||||||
|
if type(Templates)=="table" then
|
||||||
|
for _,t in pairs(Templates) do self.templateToCargoName[t] = Name end
|
||||||
|
else
|
||||||
|
self.templateToCargoName[Templates] = Name
|
||||||
|
end
|
||||||
|
self.nomovetozone_names = self.nomovetozone_names or {}
|
||||||
|
self.nomovetozone_names[Name] = true
|
||||||
|
if SubCategory and self.usesubcats ~= true then self.usesubcats=true end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- User function - Add *generic* static-type loadable as cargo. This type will create cargo that needs to be loaded, moved and dropped.
|
--- User function - Add *generic* static-type loadable as cargo. This type will create cargo that needs to be loaded, moved and dropped.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param #string Name Unique name of this type of cargo as set in the mission editor (note: UNIT name!), e.g. "Ammunition-1".
|
-- @param #string Name Unique name of this type of cargo as set in the mission editor (note: UNIT name!), e.g. "Ammunition-1".
|
||||||
@ -5671,7 +5728,13 @@ function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon, Shiplength, Ship
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local ctldzone = {} -- #CTLD.CargoZone
|
local exists = true
|
||||||
|
local ctldzone = self:GetCTLDZone(Name, Type) -- #CTLD.CargoZone
|
||||||
|
if not ctldzone then
|
||||||
|
exists = false
|
||||||
|
ctldzone = {}
|
||||||
|
end
|
||||||
|
|
||||||
ctldzone.active = Active or false
|
ctldzone.active = Active or false
|
||||||
ctldzone.color = Color or SMOKECOLOR.Red
|
ctldzone.color = Color or SMOKECOLOR.Red
|
||||||
ctldzone.name = Name or "NONE"
|
ctldzone.name = Name or "NONE"
|
||||||
@ -5698,10 +5761,55 @@ function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon, Shiplength, Ship
|
|||||||
ctldzone.shipwidth = Shipwidth or 10
|
ctldzone.shipwidth = Shipwidth or 10
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if not exists then
|
||||||
self:AddZone(ctldzone)
|
self:AddZone(ctldzone)
|
||||||
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- User function - find #CTLD.CargoZone zone by name.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string Name Name of this zone.
|
||||||
|
-- @param #string Type Type of this zone, #CTLD.CargoZoneType
|
||||||
|
-- @return #CTLD.CargoZone self
|
||||||
|
function CTLD:GetCTLDZone(Name, Type)
|
||||||
|
|
||||||
|
if Type == CTLD.CargoZoneType.LOAD then
|
||||||
|
for _, z in pairs(self.pickupZones) do
|
||||||
|
if z.name == Name then
|
||||||
|
return z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif Type == CTLD.CargoZoneType.DROP then
|
||||||
|
for _, z in pairs(self.dropOffZones) do
|
||||||
|
if z.name == Name then
|
||||||
|
return z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif Type == CTLD.CargoZoneType.SHIP then
|
||||||
|
for _, z in pairs(self.shipZones) do
|
||||||
|
if z.name == Name then
|
||||||
|
return z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif Type == CTLD.CargoZoneType.BEACON then
|
||||||
|
for _, z in pairs(self.droppedBeacons) do
|
||||||
|
if z.name == Name then
|
||||||
|
return z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _, z in pairs(self.wpZones) do
|
||||||
|
if z.name == Name then
|
||||||
|
return z
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- User function - Creates and adds a #CTLD.CargoZone zone for this CTLD instance from an Airbase or FARP name.
|
--- User function - Creates and adds a #CTLD.CargoZone zone for this CTLD instance from an Airbase or FARP name.
|
||||||
-- Zones of type LOAD: Players load crates and troops here.
|
-- Zones of type LOAD: Players load crates and troops here.
|
||||||
-- Zones of type DROP: Players can drop crates here. Note that troops can be unloaded anywhere.
|
-- Zones of type DROP: Players can drop crates here. Note that troops can be unloaded anywhere.
|
||||||
@ -7443,9 +7551,12 @@ end
|
|||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
function CTLD:onafterCratesBuild(From, Event, To, Group, Unit, Vehicle)
|
function CTLD:onafterCratesBuild(From, Event, To, Group, Unit, Vehicle)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
if self.movetroopstowpzone then
|
if self.movetroopstowpzone and Vehicle then
|
||||||
|
local cg = self:GetGenericCargoObjectFromGroupName(Vehicle:GetName())
|
||||||
|
if not (cg and (cg.NoMoveToZone or (self.nomovetozone_names and self.nomovetozone_names[cg:GetName()]))) then
|
||||||
self:_MoveGroupToZone(Vehicle)
|
self:_MoveGroupToZone(Vehicle)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -5029,7 +5029,7 @@ function FLIGHTGROUP:_UpdateMenu(delay)
|
|||||||
|
|
||||||
-- Message to group.
|
-- Message to group.
|
||||||
MESSAGE:New(text, 5):ToGroup(self.group)
|
MESSAGE:New(text, 5):ToGroup(self.group)
|
||||||
self:I(self.lid..text)
|
self:T(self.lid..text)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get current position of player.
|
-- Get current position of player.
|
||||||
|
|||||||
@ -662,6 +662,15 @@ function LEGION:CheckMissionQueue()
|
|||||||
if mission:IsNotOver() and mission:IsReadyToCancel() then
|
if mission:IsNotOver() and mission:IsReadyToCancel() then
|
||||||
mission:Cancel()
|
mission:Cancel()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Housekeeping
|
||||||
|
local TNow = timer.getTime()
|
||||||
|
if mission:IsOver() and mission:IsNotRepeatable() and mission.DeletionTimstamp == nil then
|
||||||
|
mission.DeletionTimstamp = TNow
|
||||||
|
end
|
||||||
|
if mission.DeletionTimstamp ~= nil and TNow - mission.DeletionTimstamp > 1800 then
|
||||||
|
mission = nil
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check that runway is operational and that carrier is not recovering.
|
-- Check that runway is operational and that carrier is not recovering.
|
||||||
@ -761,7 +770,7 @@ function LEGION:CheckMissionQueue()
|
|||||||
-- Reduce number of reinforcements.
|
-- Reduce number of reinforcements.
|
||||||
if reinforce then
|
if reinforce then
|
||||||
mission.reinforce=mission.reinforce-#assets
|
mission.reinforce=mission.reinforce-#assets
|
||||||
self:I(self.lid..string.format("Reinforced with N=%d Nreinforce=%d", #assets, mission.reinforce))
|
self:T(self.lid..string.format("Reinforced with N=%d Nreinforce=%d", #assets, mission.reinforce))
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
@ -4631,7 +4631,12 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
|||||||
self:T(self.lid..string.format("Zone %s captured ==> Task DONE!", zoneCurr:GetName()))
|
self:T(self.lid..string.format("Zone %s captured ==> Task DONE!", zoneCurr:GetName()))
|
||||||
|
|
||||||
-- Task done.
|
-- Task done.
|
||||||
|
if Task.StayInZoneTime then
|
||||||
|
local stay = Task.StayInZoneTime
|
||||||
|
self:__TaskDone(stay,Task)
|
||||||
|
else
|
||||||
self:TaskDone(Task)
|
self:TaskDone(Task)
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
-- Current zone NOT captured yet ==> Find Target
|
-- Current zone NOT captured yet ==> Find Target
|
||||||
@ -7534,7 +7539,7 @@ end
|
|||||||
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
||||||
|
|
||||||
-- Set element status.
|
-- Set element status.
|
||||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||||
@ -8090,7 +8095,7 @@ function OPSGROUP:onafterStop(From, Event, To)
|
|||||||
_DATABASE.FLIGHTGROUPS[self.groupname]=nil
|
_DATABASE.FLIGHTGROUPS[self.groupname]=nil
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from _DATABASE")
|
self:T(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from _DATABASE")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "OutOfAmmo" event.
|
--- On after "OutOfAmmo" event.
|
||||||
|
|||||||
@ -606,6 +606,7 @@ ENUMS.Storage = {
|
|||||||
OH58 = {}, -- Kiowa specifics
|
OH58 = {}, -- Kiowa specifics
|
||||||
UH1H = {}, -- Huey specifics
|
UH1H = {}, -- Huey specifics
|
||||||
AH64D = {}, -- Huey specifics
|
AH64D = {}, -- Huey specifics
|
||||||
|
UH60L = {}, -- Blackhawk specifics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1315,6 +1316,26 @@ ENUMS.Storage.weapons.UH1H.M134_MiniGun_Right_Door = {4,15,46,175}
|
|||||||
ENUMS.Storage.weapons.UH1H.M60_MG_Right_Door = {4,15,46,177}
|
ENUMS.Storage.weapons.UH1H.M60_MG_Right_Door = {4,15,46,177}
|
||||||
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left_Door = {4,15,46,174}
|
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left_Door = {4,15,46,174}
|
||||||
ENUMS.Storage.weapons.UH1H.M60_MG_Left_Door = {4,15,46,176}
|
ENUMS.Storage.weapons.UH1H.M60_MG_Left_Door = {4,15,46,176}
|
||||||
|
-- UH-60L
|
||||||
|
ENUMS.Storage.weapons.UH60L.M151_HYDRA = {4, 7, 33, 147} -- 2.75" Hydra, UnGd Rkts M151, HE
|
||||||
|
ENUMS.Storage.weapons.UH60L.M156_HYDRA = {4, 7, 33, 148} -- 2.75" Hydra, UnGd Rkts M156, Wht Phos
|
||||||
|
ENUMS.Storage.weapons.UH60L.M229_HYDRA = {4, 7, 33, 148} -- 2.75" Hydra, UnGd Rkts M229, HE
|
||||||
|
ENUMS.Storage.weapons.UH60L.M257_HYDRA = {4, 7, 33, 151} -- 2.75" Hydra, UnGd Rkts M257, Para Illum
|
||||||
|
ENUMS.Storage.weapons.UH60L.M259_HYDRA = {4, 7, 33, 151} -- 2.75" Hydra, UnGd Rkts M259, Smoke Marker
|
||||||
|
ENUMS.Storage.weapons.UH60L.M274_HYDRA = {4, 7, 33, 150} -- 2.75" Hydra, UnGd Rkts M274, Practice Smk
|
||||||
|
ENUMS.Storage.weapons.UH60L.M134_DOOR_GUN = {4, 15, 46, 3031}
|
||||||
|
ENUMS.Storage.weapons.UH60L.M3M = {4, 15, 46, 2496}
|
||||||
|
ENUMS.Storage.weapons.UH60L.M3M_DOOR_GUN = {4, 15, 46, 3032}
|
||||||
|
ENUMS.Storage.weapons.UH60L.M60_DOOR_GUN = {4, 15, 46, 3033}
|
||||||
|
ENUMS.Storage.weapons.UH60L.FUEL_TANK_200 = {1,3,43,3023}
|
||||||
|
ENUMS.Storage.weapons.UH60L.FUEL_TANK_230 = {1,3,43,3024}
|
||||||
|
ENUMS.Storage.weapons.UH60L.FUEL_TANK_450 = {1,3,43,3025}
|
||||||
|
ENUMS.Storage.weapons.UH60L.FUEL_TANK_DUAL_AUX = {1,3,43,3026}
|
||||||
|
ENUMS.Storage.weapons.UH60L.CARGO_SEAT_REAR_ROW = {1,3,43,3030}
|
||||||
|
ENUMS.Storage.weapons.UH60L.CARGO_SEAT_THREE_ROWS = {1,3,43,3029}
|
||||||
|
ENUMS.Storage.weapons.UH60L.EMPTY_GUNNER_SEAT_1 = {1,3,43,3027}
|
||||||
|
ENUMS.Storage.weapons.UH60L.EMPTY_GUNNER_SEAT_2 = {1,3,43,3028}
|
||||||
|
|
||||||
-- Kiowa
|
-- Kiowa
|
||||||
ENUMS.Storage.weapons.OH58.FIM92 = {4,4,7,449}
|
ENUMS.Storage.weapons.OH58.FIM92 = {4,4,7,449}
|
||||||
ENUMS.Storage.weapons.OH58.MG_M3P100 = {4,15,46,2611}
|
ENUMS.Storage.weapons.OH58.MG_M3P100 = {4,15,46,2611}
|
||||||
|
|||||||
@ -2330,6 +2330,16 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if type_name == "UH-60L_DAP" and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
|
||||||
|
BASE:T(unit_name .. " cargo door is open")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
if type_name == "UH-60L_DAP" and (unit:getDrawArgumentValue(38) > 0 or unit:getDrawArgumentValue(400) == 1 ) then
|
||||||
|
BASE:T(unit_name .. " front door(s) are open")
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
if type_name == "AH-64D_BLK_II" then
|
if type_name == "AH-64D_BLK_II" then
|
||||||
BASE:T(unit_name .. " front door(s) are open")
|
BASE:T(unit_name .. " front door(s) are open")
|
||||||
return true -- no doors on this one ;)
|
return true -- no doors on this one ;)
|
||||||
@ -4127,6 +4137,45 @@ function UTILS.LCGRandom()
|
|||||||
return UTILS.lcg.seed / UTILS.lcg.m
|
return UTILS.lcg.seed / UTILS.lcg.m
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Create a table of grid-points for n points.
|
||||||
|
-- @param #number startVec2 Starting DCS#Vec2 map coordinate, e.g. `{x=63598575,y=-63598575}`
|
||||||
|
-- @param #number n Number of points to generate.
|
||||||
|
-- @param #number spacingX Horizonzal spacing (meters).
|
||||||
|
-- @param #number spacingY Vertical spacing (meters).
|
||||||
|
-- @return #table Grid Table of DCS#Vec2 entries.
|
||||||
|
function UTILS.GenerateGridPoints(startVec2, n, spacingX, spacingY)
|
||||||
|
local points = {}
|
||||||
|
local gridSize = math.ceil(math.sqrt(n))
|
||||||
|
local count = 0
|
||||||
|
local n = n or 1
|
||||||
|
local spacingX = spacingX or 100
|
||||||
|
local spacingY = spacingY or 100
|
||||||
|
local startX = startVec2.x or 100
|
||||||
|
local startY = startVec2.y or 100
|
||||||
|
|
||||||
|
for row = 0, gridSize - 1 do
|
||||||
|
for col = 0, gridSize - 1 do
|
||||||
|
if count >= n then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local point = {
|
||||||
|
x = startX + (col * spacingX),
|
||||||
|
y = startY + (row * spacingY)
|
||||||
|
}
|
||||||
|
|
||||||
|
table.insert(points, point)
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if count >= n then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return points
|
||||||
|
end
|
||||||
|
|
||||||
--- Spawns a new FARP of a defined type and coalition and functional statics (fuel depot, ammo storage, tent, windsock) around that FARP to make it operational.
|
--- Spawns a new FARP of a defined type and coalition and functional statics (fuel depot, ammo storage, tent, windsock) around that FARP to make it operational.
|
||||||
-- Adds vehicles from template if given. Fills the FARP warehouse with liquids and known materiels.
|
-- Adds vehicles from template if given. Fills the FARP warehouse with liquids and known materiels.
|
||||||
-- References: [DCS Forum Topic](https://forum.dcs.world/topic/282989-farp-equipment-to-run-it)
|
-- References: [DCS Forum Topic](https://forum.dcs.world/topic/282989-farp-equipment-to-run-it)
|
||||||
@ -4147,10 +4196,38 @@ end
|
|||||||
-- @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 #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 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.
|
-- @param #boolean HotStart If true and DynamicSpawns is true, allow hot starts for Dynamic Spawns from this FARP.
|
||||||
|
-- @param #number NumberPads If given, spawn this number of pads.
|
||||||
|
-- @param #number SpacingX For NumberPads > 1, space this many meters horizontally. Defaults to 100.
|
||||||
|
-- @param #number SpacingY For NumberPads > 1, space this many meters vertically. Defaults to 100.
|
||||||
-- @return #list<Wrapper.Static#STATIC> Table of spawned objects and vehicle object (if given).
|
-- @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.
|
-- @return #string ADFBeaconName Name of the ADF beacon, to be able to remove/stop it later.
|
||||||
-- @return #number MarkerID ID of the F10 Text, to be able to remove it later.
|
-- @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)
|
function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment,Airframes,F10Text,DynamicSpawns,HotStart,NumberPads,SpacingX,SpacingY)
|
||||||
|
|
||||||
|
local function PopulateStorage(Name,liquids,equip,airframes)
|
||||||
|
local newWH = STORAGE:New(Name)
|
||||||
|
if liquids and liquids > 0 then
|
||||||
|
-- Storage fill-up
|
||||||
|
newWH:SetLiquid(STORAGE.Liquid.DIESEL,liquids) -- kgs to tons
|
||||||
|
newWH:SetLiquid(STORAGE.Liquid.GASOLINE,liquids)
|
||||||
|
newWH:SetLiquid(STORAGE.Liquid.JETFUEL,liquids)
|
||||||
|
newWH:SetLiquid(STORAGE.Liquid.MW50,liquids)
|
||||||
|
end
|
||||||
|
|
||||||
|
if equip and equip > 0 then
|
||||||
|
for cat,nitem in pairs(ENUMS.Storage.weapons) do
|
||||||
|
for name,item in pairs(nitem) do
|
||||||
|
newWH:SetItem(item,equip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if airframes and airframes > 0 then
|
||||||
|
for typename in pairs (CSAR.AircraftType) do
|
||||||
|
newWH:SetItem(typename,airframes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Set Defaults
|
-- Set Defaults
|
||||||
local farplocation = Coordinate
|
local farplocation = Coordinate
|
||||||
@ -4171,12 +4248,36 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
local Country = Country or (Coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA)
|
local Country = Country or (Coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA)
|
||||||
local ReturnObjects = {}
|
local ReturnObjects = {}
|
||||||
|
|
||||||
|
-- many FARPs
|
||||||
|
local NumberPads = NumberPads or 1
|
||||||
|
local SpacingX = SpacingX or 100
|
||||||
|
local SpacingY = SpacingY or 100
|
||||||
|
local FarpVec2 = Coordinate:GetVec2()
|
||||||
|
|
||||||
|
if NumberPads > 1 then
|
||||||
|
local Grid = UTILS.GenerateGridPoints(FarpVec2, NumberPads, SpacingX, SpacingY)
|
||||||
|
for id,gridpoint in ipairs(Grid) do
|
||||||
|
-- Spawn FARP
|
||||||
|
local location = COORDINATE:NewFromVec2(gridpoint)
|
||||||
|
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
||||||
|
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
||||||
|
newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
|
||||||
|
local spawnedfarp = newfarp:SpawnFromCoordinate(location,0,Name.."-"..id)
|
||||||
|
table.insert(ReturnObjects,spawnedfarp)
|
||||||
|
|
||||||
|
PopulateStorage(Name.."-"..id,liquids,equip,airframes)
|
||||||
|
end
|
||||||
|
else
|
||||||
-- Spawn FARP
|
-- Spawn FARP
|
||||||
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
||||||
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
||||||
newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
|
newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
|
||||||
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
|
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
|
||||||
table.insert(ReturnObjects,spawnedfarp)
|
table.insert(ReturnObjects,spawnedfarp)
|
||||||
|
|
||||||
|
PopulateStorage(Name,liquids,equip,airframes)
|
||||||
|
end
|
||||||
|
|
||||||
-- Spawn Objects
|
-- Spawn Objects
|
||||||
local FARPStaticObjectsNato = {
|
local FARPStaticObjectsNato = {
|
||||||
["FUEL"] = { TypeName = "FARP Fuel Depot", ShapeName = "GSM Rus", Category = "Fortifications"},
|
["FUEL"] = { TypeName = "FARP Fuel Depot", ShapeName = "GSM Rus", Category = "Fortifications"},
|
||||||
@ -4210,29 +4311,6 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
table.insert(ReturnObjects,spawnedvehicle)
|
table.insert(ReturnObjects,spawnedvehicle)
|
||||||
end
|
end
|
||||||
|
|
||||||
local newWH = STORAGE:New(Name)
|
|
||||||
if liquids and liquids > 0 then
|
|
||||||
-- Storage fill-up
|
|
||||||
newWH:SetLiquid(STORAGE.Liquid.DIESEL,liquids) -- kgs to tons
|
|
||||||
newWH:SetLiquid(STORAGE.Liquid.GASOLINE,liquids)
|
|
||||||
newWH:SetLiquid(STORAGE.Liquid.JETFUEL,liquids)
|
|
||||||
newWH:SetLiquid(STORAGE.Liquid.MW50,liquids)
|
|
||||||
end
|
|
||||||
|
|
||||||
if equip and equip > 0 then
|
|
||||||
for cat,nitem in pairs(ENUMS.Storage.weapons) do
|
|
||||||
for name,item in pairs(nitem) do
|
|
||||||
newWH:SetItem(item,equip)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if airframes and airframes > 0 then
|
|
||||||
for typename in pairs (CSAR.AircraftType) do
|
|
||||||
newWH:SetItem(typename,airframes)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ADFName
|
local ADFName
|
||||||
if ADF and type(ADF) == "number" then
|
if ADF and type(ADF) == "number" then
|
||||||
local ADFFreq = ADF*1000 -- KHz to Hz
|
local ADFFreq = ADF*1000 -- KHz to Hz
|
||||||
|
|||||||
@ -1574,6 +1574,17 @@ end
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the true airbase center as seen in the ME. The position returned by the dcs object is is wrong and often at the start of the runway.
|
||||||
|
-- @return DCS#Vec2 The center of the true center of the airbase if it contains runways, otherwise the default DCS object position.
|
||||||
|
function AIRBASE:GetVec2()
|
||||||
|
local runways = self:GetRunways()
|
||||||
|
if runways and #runways > 0 then
|
||||||
|
return runways[1].center:GetVec2()
|
||||||
|
end
|
||||||
|
return self:GetCoordinate():GetVec2()
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the category of this airbase. This is only a debug function because DCS 2.9 incorrectly returns heliports as airdromes.
|
--- Get the category of this airbase. This is only a debug function because DCS 2.9 incorrectly returns heliports as airdromes.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
function AIRBASE:_GetCategory()
|
function AIRBASE:_GetCategory()
|
||||||
|
|||||||
@ -4163,7 +4163,7 @@ function CONTROLLABLE:OptionRestrictBurner( RestrictBurner )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets Controllable Option for A2A attack range for AIR FIGHTER units.
|
--- [AIR] Sets Controllable Option for A2A attack range for AIR FIGHTER units.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #number range Defines the range
|
-- @param #number range Defines the range
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
@ -4188,6 +4188,66 @@ function CONTROLLABLE:OptionAAAttackRange( range )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [GROUND/AAA] Sets Controllable Option for Ground AAA minimum firing height.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number meters The minimum height in meters.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionAAAMinFiringHeightMeters(meters)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
local meters = meters or 20
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
if Controller then
|
||||||
|
if self:IsGround() then
|
||||||
|
self:SetOption(27, meters)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND/AAA] Sets Controllable Option for Ground AAA maximum firing height.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number meters The maximum height in meters.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionAAAMaxFiringHeightMeters(meters)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
local meters = meters or 1000
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
if Controller then
|
||||||
|
if self:IsGround() then
|
||||||
|
self:SetOption(29, meters)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND/AAA] Sets Controllable Option for Ground AAA minimum firing height.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number feet The minimum height in feet.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionAAAMinFiringHeightFeet(feet)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
local feet = feet or 60
|
||||||
|
return self:OptionAAAMinFiringHeightMeters(UTILS.FeetToMeters(feet))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND/AAA] Sets Controllable Option for Ground AAA maximum firing height.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number feet The maximum height in feet.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionAAAMaxFiringHeightfeet(feet)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
local feet = feet or 3000
|
||||||
|
return self:OptionAAAMaxFiringHeightMeters(UTILS.FeetToMeters(feet))
|
||||||
|
end
|
||||||
|
|
||||||
--- Defines the range at which a GROUND unit/group is allowed to use its weapons automatically.
|
--- Defines the range at which a GROUND unit/group is allowed to use its weapons automatically.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #number EngageRange Engage range limit in percent (a number between 0 and 100). Default 100.
|
-- @param #number EngageRange Engage range limit in percent (a number between 0 and 100). Default 100.
|
||||||
|
|||||||
@ -108,6 +108,8 @@ DYNAMICCARGO.State = {
|
|||||||
-- @type DYNAMICCARGO.AircraftTypes
|
-- @type DYNAMICCARGO.AircraftTypes
|
||||||
DYNAMICCARGO.AircraftTypes = {
|
DYNAMICCARGO.AircraftTypes = {
|
||||||
["CH-47Fbl1"] = "CH-47Fbl1",
|
["CH-47Fbl1"] = "CH-47Fbl1",
|
||||||
|
["Mi-8MTV2"] = "CH-47Fbl1",
|
||||||
|
["Mi-8MT"] = "CH-47Fbl1",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Helo types possible.
|
--- Helo types possible.
|
||||||
@ -120,17 +122,30 @@ DYNAMICCARGO.AircraftDimensions = {
|
|||||||
["length"] = 11,
|
["length"] = 11,
|
||||||
["ropelength"] = 30,
|
["ropelength"] = 30,
|
||||||
},
|
},
|
||||||
|
["Mi-8MTV2"] = {
|
||||||
|
["width"] = 6,
|
||||||
|
["height"] = 6,
|
||||||
|
["length"] = 15,
|
||||||
|
["ropelength"] = 30,
|
||||||
|
},
|
||||||
|
["Mi-8MT"] = {
|
||||||
|
["width"] = 6,
|
||||||
|
["height"] = 6,
|
||||||
|
["length"] = 15,
|
||||||
|
["ropelength"] = 30,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- DYNAMICCARGO class version.
|
--- DYNAMICCARGO class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
DYNAMICCARGO.version="0.0.7"
|
DYNAMICCARGO.version="0.0.9"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: A lot...
|
-- TODO: A lot...
|
||||||
|
-- DONE: Added Mi-8 type and dimensions
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
|
|||||||
@ -361,6 +361,7 @@ function POSITIONABLE:GetCoord()
|
|||||||
-- Get the current position.
|
-- Get the current position.
|
||||||
local PositionableVec3 = self:GetVec3()
|
local PositionableVec3 = self:GetVec3()
|
||||||
|
|
||||||
|
if PositionableVec3 then
|
||||||
if self.coordinate then
|
if self.coordinate then
|
||||||
-- Update COORDINATE from 3D vector.
|
-- Update COORDINATE from 3D vector.
|
||||||
self.coordinate:UpdateFromVec3( PositionableVec3 )
|
self.coordinate:UpdateFromVec3( PositionableVec3 )
|
||||||
@ -371,6 +372,7 @@ function POSITIONABLE:GetCoord()
|
|||||||
|
|
||||||
return self.coordinate
|
return self.coordinate
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Error message.
|
-- Error message.
|
||||||
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user