mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e6f25f17c | ||
|
|
0cd6a59ce4 | ||
|
|
91a445961b | ||
|
|
749e9b7e08 | ||
|
|
905d29b279 | ||
|
|
5f97299cb2 | ||
|
|
60b75a4c8f | ||
|
|
0868286f27 | ||
|
|
ffcc46cb2d | ||
|
|
21bcd64c9d | ||
|
|
943b68f38f | ||
|
|
256b93087f | ||
|
|
7ed0d7eec3 | ||
|
|
9b8154246f | ||
|
|
c360759e49 | ||
|
|
d8b80aab1a | ||
|
|
b96ebc1872 | ||
|
|
6896dc155a | ||
|
|
1060d63808 | ||
|
|
88b6540f5b | ||
|
|
302e785f32 | ||
|
|
1507cc0b42 | ||
|
|
240307ef94 | ||
|
|
90c74bd82c | ||
|
|
9414096de7 | ||
|
|
07c3be9d6a | ||
|
|
9869dbd95a | ||
|
|
49b702106a | ||
|
|
8eb09beb96 | ||
|
|
b402a99a25 | ||
|
|
ad8938cd74 | ||
|
|
ee409c45a0 | ||
|
|
9d5da3388d | ||
|
|
9e138aa149 | ||
|
|
cf94c4d043 |
@@ -1687,6 +1687,20 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
return DefenderSquadron
|
||||
end
|
||||
|
||||
--- Get a resource count from a specific squadron
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string Squadron Name of the squadron.
|
||||
-- @return #number Number of airframes available or nil if the squadron does not exist
|
||||
function AI_A2A_DISPATCHER:QuerySquadron(Squadron)
|
||||
local Squadron = self:GetSquadron(Squadron)
|
||||
if Squadron.ResourceCount then
|
||||
self:T2(string.format("%s = %s",Squadron.Name,Squadron.ResourceCount))
|
||||
return Squadron.ResourceCount
|
||||
end
|
||||
self:F({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount})
|
||||
return nil
|
||||
end
|
||||
|
||||
--- [DEPRECATED - Might create problems launching planes] Set the Squadron visible before startup of the dispatcher.
|
||||
-- All planes will be spawned as uncontrolled on the parking spot.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **AI** - Create an automated A2G defense system based on a detection network of reconnaissance vehicles and air units, coordinating SEAD, BAI and CAS operations.
|
||||
--- **AI** - Create an automated A2G defense system with reconnaissance units, coordinating SEAD, BAI and CAS operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -951,7 +951,7 @@ do -- AI_A2G_DISPATCHER
|
||||
AI_A2G_DISPATCHER.DefenseQueue = {}
|
||||
|
||||
--- Defense approach types.
|
||||
-- @type #AI_A2G_DISPATCHER.DefenseApproach
|
||||
-- @type AI_A2G_DISPATCHER.DefenseApproach
|
||||
AI_A2G_DISPATCHER.DefenseApproach = {
|
||||
Random = 1,
|
||||
Distance = 2,
|
||||
@@ -1806,6 +1806,19 @@ do -- AI_A2G_DISPATCHER
|
||||
return DefenderSquadron
|
||||
end
|
||||
|
||||
--- Get a resource count from a specific squadron
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string Squadron Name of the squadron.
|
||||
-- @return #number Number of airframes available or nil if the squadron does not exist
|
||||
function AI_A2G_DISPATCHER:QuerySquadron(Squadron)
|
||||
local Squadron = self:GetSquadron(Squadron)
|
||||
if Squadron.ResourceCount then
|
||||
self:T2(string.format("%s = %s",Squadron.Name,Squadron.ResourceCount))
|
||||
return Squadron.ResourceCount
|
||||
end
|
||||
self:F({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount})
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Set the Squadron visible before startup of the dispatcher.
|
||||
-- All planes will be spawned as uncontrolled on the parking spot.
|
||||
@@ -1839,7 +1852,7 @@ do -- AI_A2G_DISPATCHER
|
||||
--- Check if the Squadron is visible before startup of the dispatcher.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @return #bool true if visible.
|
||||
-- @return #boolean true if visible.
|
||||
-- @usage
|
||||
--
|
||||
-- -- Set the Squadron visible before startup of dispatcher.
|
||||
|
||||
@@ -947,7 +947,7 @@ do -- AI_AIR_DISPATCHER
|
||||
AI_AIR_DISPATCHER.DefenseQueue = {}
|
||||
|
||||
--- Defense approach types
|
||||
-- @type #AI_AIR_DISPATCHER.DefenseApproach
|
||||
-- @type AI_AIR_DISPATCHER.DefenseApproach
|
||||
AI_AIR_DISPATCHER.DefenseApproach = {
|
||||
Random = 1,
|
||||
Distance = 2,
|
||||
@@ -1852,7 +1852,7 @@ do -- AI_AIR_DISPATCHER
|
||||
--- Check if the Squadron is visible before startup of the dispatcher.
|
||||
-- @param #AI_AIR_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @return #bool true if visible.
|
||||
-- @return #boolean true if visible.
|
||||
-- @usage
|
||||
--
|
||||
-- -- Set the Squadron visible before startup of dispatcher.
|
||||
|
||||
@@ -443,9 +443,9 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||
-- @return #AI_ESCORT
|
||||
@@ -493,9 +493,9 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||
-- @return #AI_ESCORT
|
||||
@@ -580,7 +580,7 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationTrail( XStart, XSpace, YStart )
|
||||
|
||||
@@ -594,7 +594,7 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationStack( XStart, XSpace, YStart, YSpace )
|
||||
@@ -609,8 +609,8 @@ end
|
||||
-- This menu will appear under **Formation**.
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationLeftLine( XStart, YStart, ZStart, ZSpace )
|
||||
@@ -625,8 +625,8 @@ end
|
||||
-- This menu will appear under **Formation**.
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationRightLine( XStart, YStart, ZStart, ZSpace )
|
||||
@@ -642,8 +642,8 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationLeftWing( XStart, XSpace, YStart, ZStart, ZSpace )
|
||||
@@ -659,8 +659,8 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationRightWing( XStart, XSpace, YStart, ZStart, ZSpace )
|
||||
@@ -676,9 +676,9 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationCenterWing( XStart, XSpace, YStart, YSpace, ZStart, ZSpace )
|
||||
@@ -694,9 +694,9 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:MenuFormationVic( XStart, XSpace, YStart, YSpace, ZStart, ZSpace )
|
||||
@@ -712,9 +712,9 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||
-- @return #AI_ESCORT
|
||||
@@ -1471,7 +1471,7 @@ end
|
||||
-- @param #AI_ESCORT self
|
||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @return #AI_ESCORT
|
||||
function AI_ESCORT:_EscortFormationTrail( EscortGroup, XStart, XSpace, YStart )
|
||||
|
||||
|
||||
@@ -88,6 +88,7 @@ DATABASE = {
|
||||
WAREHOUSES = {},
|
||||
FLIGHTGROUPS = {},
|
||||
FLIGHTCONTROLS = {},
|
||||
OPSZONES = {},
|
||||
PATHLINES = {},
|
||||
}
|
||||
|
||||
@@ -580,6 +581,46 @@ do -- Zone_Goal
|
||||
end
|
||||
|
||||
end -- Zone_Goal
|
||||
|
||||
do -- OpsZone
|
||||
|
||||
--- Finds a @{Ops.OpsZone#OPSZONE} based on the zone name.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string ZoneName The name of the zone.
|
||||
-- @return Ops.OpsZone#OPSZONE The found OPSZONE.
|
||||
function DATABASE:FindOpsZone( ZoneName )
|
||||
|
||||
local ZoneFound = self.OPSZONES[ZoneName]
|
||||
|
||||
return ZoneFound
|
||||
end
|
||||
|
||||
--- Adds a @{Ops.OpsZone#OPSZONE} based on the zone name in the DATABASE.
|
||||
-- @param #DATABASE self
|
||||
-- @param Ops.OpsZone#OPSZONE OpsZone The zone.
|
||||
function DATABASE:AddOpsZone( OpsZone )
|
||||
|
||||
if OpsZone then
|
||||
|
||||
local ZoneName=OpsZone:GetName()
|
||||
|
||||
if not self.OPSZONES[ZoneName] then
|
||||
self.OPSZONES[ZoneName] = OpsZone
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Deletes a @{Ops.OpsZone#OPSZONE} from the DATABASE based on the zone name.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string ZoneName The name of the zone.
|
||||
function DATABASE:DeleteOpsZone( ZoneName )
|
||||
self.OPSZONES[ZoneName] = nil
|
||||
end
|
||||
|
||||
end -- OpsZone
|
||||
|
||||
do -- cargo
|
||||
|
||||
--- Adds a Cargo based on the Cargo Name in the DATABASE.
|
||||
@@ -1599,10 +1640,10 @@ end
|
||||
-- @param #DATABASE self
|
||||
-- @param #function IteratorFunction The function that will be called object in the database. The function needs to accept a CLIENT parameter.
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:ForEachClient( IteratorFunction, ... )
|
||||
function DATABASE:ForEachClient( IteratorFunction, FinalizeFunction, ... )
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self.CLIENTS )
|
||||
self:ForEach( IteratorFunction, FinalizeFunction, arg, self.CLIENTS )
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -1611,10 +1652,10 @@ end
|
||||
-- @param #DATABASE self
|
||||
-- @param #function IteratorFunction The function that will be called for each object in the database. The function needs to accept a CLIENT parameter.
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:ForEachCargo( IteratorFunction, ... )
|
||||
function DATABASE:ForEachCargo( IteratorFunction, FinalizeFunction, ... )
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self.CARGOS )
|
||||
self:ForEach( IteratorFunction, FinalizeFunction, arg, self.CARGOS )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1224,7 +1224,7 @@ function EVENT:onEvent( Event )
|
||||
if Event.TgtObjectCategory == Object.Category.STATIC then
|
||||
-- get base data
|
||||
Event.TgtDCSUnit = Event.target
|
||||
if Event.target:isExist() and Event.id ~= 33 and not Event.TgtObjectCategory == Object.Category.COORDINATE then -- leave out ejected seat object
|
||||
if Event.target:isExist() and Event.id ~= 33 then -- leave out ejected seat object
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
||||
|
||||
@@ -540,7 +540,7 @@ do -- COORDINATE
|
||||
local gotscenery=false
|
||||
|
||||
local function EvaluateZone(ZoneObject)
|
||||
BASE:T({ZoneObject})
|
||||
|
||||
if ZoneObject then
|
||||
|
||||
-- Get category of scanned object.
|
||||
@@ -603,6 +603,46 @@ do -- COORDINATE
|
||||
|
||||
return set
|
||||
end
|
||||
|
||||
--- Scan/find STATICS within a certain radius around the coordinate using the world.searchObjects() DCS API function.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number radius (Optional) Scan radius in meters. Default 100 m.
|
||||
-- @return Core.Set#SET_UNIT Set of units.
|
||||
function COORDINATE:ScanStatics(radius)
|
||||
|
||||
local _,_,_,_,statics=self:ScanObjects(radius, false, true, false)
|
||||
|
||||
local set=SET_STATIC:New()
|
||||
|
||||
for _,stat in pairs(statics) do
|
||||
set:AddStatic(STATIC:Find(stat))
|
||||
end
|
||||
|
||||
return set
|
||||
end
|
||||
|
||||
--- Find the closest static to the COORDINATE within a certain radius.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number radius Scan radius in meters. Default 100 m.
|
||||
-- @return Wrapper.Static#STATIC The closest static or #nil if no unit is inside the given radius.
|
||||
function COORDINATE:FindClosestStatic(radius)
|
||||
|
||||
local units=self:ScanStatics(radius)
|
||||
|
||||
local umin=nil --Wrapper.Unit#UNIT
|
||||
local dmin=math.huge
|
||||
for _,_unit in pairs(units.Set) do
|
||||
local unit=_unit --Wrapper.Static#STATIC
|
||||
local coordinate=unit:GetCoordinate()
|
||||
local d=self:Get2DDistance(coordinate)
|
||||
if d<dmin then
|
||||
dmin=d
|
||||
umin=unit
|
||||
end
|
||||
end
|
||||
|
||||
return umin
|
||||
end
|
||||
|
||||
--- Find the closest unit to the COORDINATE within a certain radius.
|
||||
-- @param #COORDINATE self
|
||||
@@ -3283,7 +3323,52 @@ do -- COORDINATE
|
||||
|
||||
return self:GetTemperatureText( nil, Settings )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Function to check if a coordinate is in a steep (>8% elevation) area of the map
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
||||
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
||||
-- @return #boolen IsSteep If true, area is steep
|
||||
-- @return #number MaxElevation Elevation in meters measured over 100m
|
||||
function COORDINATE:IsInSteepArea(Radius,Minelevation)
|
||||
local steep = false
|
||||
local elev = Minelevation or 8
|
||||
local bdelta = 0
|
||||
local h0 = self:GetLandHeight()
|
||||
local radius = Radius or 50
|
||||
local diam = radius * 2
|
||||
for i=0,150,30 do
|
||||
local polar = math.fmod(i+180,360)
|
||||
local c1 = self:Translate(radius,i,false,false)
|
||||
local c2 = self:Translate(radius,polar,false,false)
|
||||
local h1 = c1:GetLandHeight()
|
||||
local h2 = c2:GetLandHeight()
|
||||
local d1 = math.abs(h1-h2)
|
||||
local d2 = math.abs(h0-h1)
|
||||
local d3 = math.abs(h0-h2)
|
||||
local dm = d1 > d2 and d1 or d2
|
||||
local dm1 = dm > d3 and dm or d3
|
||||
bdelta = dm1 > bdelta and dm1 or bdelta
|
||||
self:T(string.format("d1=%d, d2=%d, d3=%d, max delta=%d",d1,d2,d3,bdelta))
|
||||
end
|
||||
local steepness = bdelta / (radius / 100)
|
||||
if steepness >= elev then steep = true end
|
||||
return steep, math.floor(steepness)
|
||||
end
|
||||
|
||||
--- Function to check if a coordinate is in a flat (<8% elevation) area of the map
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
||||
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
||||
-- @return #boolen IsFlat If true, area is flat
|
||||
-- @return #number MaxElevation Elevation in meters measured over 100m
|
||||
function COORDINATE:IsInFlatArea(Radius,Minelevation)
|
||||
local steep, elev = self:IsInSteepArea(Radius,Minelevation)
|
||||
local flat = not steep
|
||||
return flat, elev
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do -- POINT_VEC3
|
||||
|
||||
@@ -904,6 +904,8 @@ end
|
||||
do -- SET_GROUP
|
||||
|
||||
--- @type SET_GROUP #SET_GROUP
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_GROUP} class to build sets of groups belonging to certain:
|
||||
@@ -1343,6 +1345,25 @@ do -- SET_GROUP
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] Private function for use of continous zone filter
|
||||
-- @param #SET_GROUP self
|
||||
-- @return #SET_GROUP self
|
||||
function SET_GROUP:_ContinousZoneFilter()
|
||||
|
||||
local Database = _DATABASE.GROUPS
|
||||
|
||||
for ObjectName, Object in pairs( Database ) do
|
||||
if self:IsIncludeObject( Object ) and self:IsNotInSet(Object) then
|
||||
self:Add( ObjectName, Object )
|
||||
elseif (not self:IsIncludeObject( Object )) and self:IsInSet(Object) then
|
||||
self:Remove(ObjectName)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
--- Builds a set of groups that are only active.
|
||||
-- Only the groups that are active will be included within the set.
|
||||
@@ -1381,10 +1402,46 @@ do -- SET_GROUP
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
|
||||
if self.Filter.Zones then
|
||||
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
|
||||
local timing = self.ZoneTimerInterval or 30
|
||||
self.ZoneTimer:Start(timing,timing)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set filter timer interval for FilterZones if using active filtering with FilterStart().
|
||||
-- @param #SET_GROUP self
|
||||
-- @param #number Seconds Seconds between check intervals, defaults to 30. **Caution** - do not be too agressive with timing! Groups are usually not moving fast enough
|
||||
-- to warrant a check of below 10 seconds.
|
||||
-- @return #SET_GROUP self
|
||||
function SET_GROUP:FilterZoneTimer(Seconds)
|
||||
self.ZoneTimerInterval = Seconds or 30
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stops the filtering.
|
||||
-- @param #SET_GROUP self
|
||||
-- @return #SET_GROUP self
|
||||
function SET_GROUP:FilterStop()
|
||||
|
||||
if _DATABASE then
|
||||
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
|
||||
self.ZoneTimer:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Handles the OnDead or OnCrash event for alive groups set.
|
||||
-- Note: The GROUP object in the SET_GROUP collection will only be removed if the last unit is destroyed of the GROUP.
|
||||
@@ -1888,7 +1945,7 @@ do -- SET_GROUP
|
||||
if self.Filter.Zones then
|
||||
local MGroupZone = false
|
||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||
self:T3( "Zone:", ZoneName )
|
||||
--self:I( "Zone:", ZoneName )
|
||||
if MGroup:IsInZone(Zone) then
|
||||
MGroupZone = true
|
||||
end
|
||||
@@ -1956,6 +2013,8 @@ end
|
||||
do -- SET_UNIT
|
||||
|
||||
--- @type SET_UNIT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the SET_UNIT class to build sets of units belonging to certain:
|
||||
@@ -2347,7 +2406,56 @@ do -- SET_UNIT
|
||||
|
||||
return CountU
|
||||
end
|
||||
|
||||
--- [Internal] Private function for use of continous zone filter
|
||||
-- @param #SET_UNIT self
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:_ContinousZoneFilter()
|
||||
|
||||
local Database = _DATABASE.UNITS
|
||||
|
||||
for ObjectName, Object in pairs( Database ) do
|
||||
if self:IsIncludeObject( Object ) and self:IsNotInSet(Object) then
|
||||
self:Add( ObjectName, Object )
|
||||
elseif (not self:IsIncludeObject( Object )) and self:IsInSet(Object) then
|
||||
self:Remove(ObjectName)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
--- Set filter timer interval for FilterZones if using active filtering with FilterStart().
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #number Seconds Seconds between check intervals, defaults to 30. **Caution** - do not be too agressive with timing! Groups are usually not moving fast enough
|
||||
-- to warrant a check of below 10 seconds.
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:FilterZoneTimer(Seconds)
|
||||
self.ZoneTimerInterval = Seconds or 30
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stops the filtering.
|
||||
-- @param #SET_UNIT self
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:FilterStop()
|
||||
|
||||
if _DATABASE then
|
||||
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
|
||||
self.ZoneTimer:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Starts the filtering.
|
||||
-- @param #SET_UNIT self
|
||||
-- @return #SET_UNIT self
|
||||
@@ -2359,6 +2467,11 @@ do -- SET_UNIT
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
|
||||
if self.Filter.Zones then
|
||||
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
|
||||
local timing = self.ZoneTimerInterval or 30
|
||||
self.ZoneTimer:Start(timing,timing)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -3834,6 +3947,8 @@ end
|
||||
do -- SET_CLIENT
|
||||
|
||||
--- @type SET_CLIENT
|
||||
-- @field Core.Timer#TIMER ZoneTimer
|
||||
-- @field #number ZoneTimerInterval
|
||||
-- @extends Core.Set#SET_BASE
|
||||
|
||||
--- Mission designers can use the @{Core.Set#SET_CLIENT} class to build sets of units belonging to certain:
|
||||
@@ -4141,6 +4256,54 @@ do -- SET_CLIENT
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] Private function for use of continous zone filter
|
||||
-- @param #SET_CLIENT self
|
||||
-- @return #SET_CLIENT self
|
||||
function SET_CLIENT:_ContinousZoneFilter()
|
||||
|
||||
local Database = _DATABASE.CLIENTS
|
||||
|
||||
for ObjectName, Object in pairs( Database ) do
|
||||
if self:IsIncludeObject( Object ) and self:IsNotInSet(Object) then
|
||||
self:Add( ObjectName, Object )
|
||||
elseif (not self:IsIncludeObject( Object )) and self:IsInSet(Object) then
|
||||
self:Remove(ObjectName)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
--- Set filter timer interval for FilterZones if using active filtering with FilterStart().
|
||||
-- @param #SET_CLIENT self
|
||||
-- @param #number Seconds Seconds between check intervals, defaults to 30. **Caution** - do not be too agressive with timing! Groups are usually not moving fast enough
|
||||
-- to warrant a check of below 10 seconds.
|
||||
-- @return #SET_CLIENT self
|
||||
function SET_CLIENT:FilterZoneTimer(Seconds)
|
||||
self.ZoneTimerInterval = Seconds or 30
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stops the filtering.
|
||||
-- @param #SET_CLIENT self
|
||||
-- @return #SET_CLIENT self
|
||||
function SET_CLIENT:FilterStop()
|
||||
|
||||
if _DATABASE then
|
||||
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
|
||||
if self.Filter.Zones and self.ZoneTimer and self.ZoneTimer:IsRunning() then
|
||||
self.ZoneTimer:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Starts the filtering.
|
||||
-- @param #SET_CLIENT self
|
||||
-- @return #SET_CLIENT self
|
||||
@@ -4151,6 +4314,11 @@ do -- SET_CLIENT
|
||||
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
if self.Filter.Zones then
|
||||
self.ZoneTimer = TIMER:New(self._ContinousZoneFilter,self)
|
||||
local timing = self.ZoneTimerInterval or 30
|
||||
self.ZoneTimer:Start(timing,timing)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -7629,7 +7797,7 @@ do -- SET_SCENERY
|
||||
|
||||
end
|
||||
|
||||
---
|
||||
--- [Internal] Determine if an object is to be included in the SET
|
||||
-- @param #SET_SCENERY self
|
||||
-- @param Wrapper.Scenery#SCENERY MScenery
|
||||
-- @return #SET_SCENERY self
|
||||
@@ -7637,4 +7805,47 @@ do -- SET_SCENERY
|
||||
self:F2( MScenery )
|
||||
return true
|
||||
end
|
||||
|
||||
--- Count overall initial (Life0) lifepoints of the SET objects.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number LIfe0Points
|
||||
function SET_SCENERY:GetLife0()
|
||||
local life0 = 0
|
||||
self:ForEachScenery(
|
||||
function(obj)
|
||||
local Obj = obj -- Wrapper.Scenery#SCENERY
|
||||
life0 = life0 + Obj:GetLife0()
|
||||
end
|
||||
)
|
||||
return life0
|
||||
end
|
||||
|
||||
--- Count overall current lifepoints of the SET objects.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number LifePoints
|
||||
function SET_SCENERY:GetLife()
|
||||
local life = 0
|
||||
self:ForEachScenery(
|
||||
function(obj)
|
||||
local Obj = obj -- Wrapper.Scenery#SCENERY
|
||||
life = life + Obj:GetLife()
|
||||
end
|
||||
)
|
||||
return life
|
||||
end
|
||||
|
||||
--- Calculate current relative lifepoints of the SET objects, i.e. Life divided by Life0 as percentage value, eg 75 meaning 75% alive.
|
||||
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the Life0 value to 120%
|
||||
-- of the last life value if life exceeds life0 ata any point.
|
||||
-- Thus will will get a smooth percentage decrease, if you use this e.g. as success criteria for a bombing task.
|
||||
-- @param #SET_SCENERY self
|
||||
-- @return #number LifePoints
|
||||
function SET_SCENERY:GetRelativeLife()
|
||||
local life = self:GetLife()
|
||||
local life0 = self:GetLife0()
|
||||
self:T3(string.format("Set Lifepoints: %d life0 | %d life",life0,life))
|
||||
local rlife = math.floor((life / life0) * 100)
|
||||
return rlife
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -335,7 +335,7 @@ end
|
||||
-- @param #SPAWN self
|
||||
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template.
|
||||
-- @param #string SpawnAliasPrefix is the name that will be given to the Group at runtime.
|
||||
-- @return #SPAWN
|
||||
-- @return #SPAWN self
|
||||
-- @usage
|
||||
-- -- NATO helicopters engaging in the battle field.
|
||||
-- Spawn_BE_KA50 = SPAWN:NewWithAlias( 'BE KA-50@RAMP-Ground Defense', 'Helicopter Attacking a City' )
|
||||
@@ -385,32 +385,129 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new SPAWN instance to create new groups based on the provided template.
|
||||
--- Creates a new SPAWN instance to create new groups based on the provided template. This will also register the template for future use.
|
||||
-- @param #SPAWN self
|
||||
-- @param #table SpawnTemplate is the Template of the Group. This must be a valid Group Template structure!
|
||||
-- @param #string SpawnTemplatePrefix is the name of the Group that will be given at each spawn.
|
||||
-- @param #string SpawnAliasPrefix is the name that will be given to the Group at runtime.
|
||||
-- @return #SPAWN
|
||||
-- @param #table SpawnTemplate is the Template of the Group. This must be a valid Group Template structure - see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_func_addGroup)!
|
||||
-- @param #string SpawnTemplatePrefix [Mandatory] is the name of the template and the prefix of the GROUP on spawn.
|
||||
-- @param #string SpawnAliasPrefix [Optional] is the prefix that will be given to the GROUP on spawn.
|
||||
-- @param #boolean MooseNaming [Optional] If false, skip the Moose naming additions (like groupname#001-01) - you need to ensure yourself no duplicate group names exist!
|
||||
-- @return #SPAWN self
|
||||
-- @usage
|
||||
-- -- Create a new SPAWN object based on a Group Template defined from scratch.
|
||||
-- Spawn_BE_KA50 = SPAWN:NewWithAlias( 'BE KA-50@RAMP-Ground Defense', 'Helicopter Attacking a City' )
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new CSAR_Spawn object based on a normal Group Template to spawn a soldier.
|
||||
-- local CSAR_Spawn = SPAWN:NewWithFromTemplate( Template, "CSAR", "Pilot" )
|
||||
--
|
||||
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
|
||||
if SpawnAliasPrefix == nil or SpawnAliasPrefix == "" then
|
||||
BASE:I( "ERROR: in function NewFromTemplate, required parameter SpawnAliasPrefix is not set" )
|
||||
-- -- Spawn a P51 Mustang from scratch
|
||||
-- local ttemp =
|
||||
-- {
|
||||
-- ["modulation"] = 0,
|
||||
-- ["tasks"] =
|
||||
-- {
|
||||
-- }, -- end of ["tasks"]
|
||||
-- ["task"] = "Reconnaissance",
|
||||
-- ["uncontrolled"] = false,
|
||||
-- ["route"] =
|
||||
-- {
|
||||
-- ["points"] =
|
||||
-- {
|
||||
-- [1] =
|
||||
-- {
|
||||
-- ["alt"] = 2000,
|
||||
-- ["action"] = "Turning Point",
|
||||
-- ["alt_type"] = "BARO",
|
||||
-- ["speed"] = 125,
|
||||
-- ["task"] =
|
||||
-- {
|
||||
-- ["id"] = "ComboTask",
|
||||
-- ["params"] =
|
||||
-- {
|
||||
-- ["tasks"] =
|
||||
-- {
|
||||
-- }, -- end of ["tasks"]
|
||||
-- }, -- end of ["params"]
|
||||
-- }, -- end of ["task"]
|
||||
-- ["type"] = "Turning Point",
|
||||
-- ["ETA"] = 0,
|
||||
-- ["ETA_locked"] = true,
|
||||
-- ["y"] = 666285.71428571,
|
||||
-- ["x"] = -312000,
|
||||
-- ["formation_template"] = "",
|
||||
-- ["speed_locked"] = true,
|
||||
-- }, -- end of [1]
|
||||
-- }, -- end of ["points"]
|
||||
-- }, -- end of ["route"]
|
||||
-- ["groupId"] = 1,
|
||||
-- ["hidden"] = false,
|
||||
-- ["units"] =
|
||||
-- {
|
||||
-- [1] =
|
||||
-- {
|
||||
-- ["alt"] = 2000,
|
||||
-- ["alt_type"] = "BARO",
|
||||
-- ["livery_id"] = "USAF 364th FS",
|
||||
-- ["skill"] = "High",
|
||||
-- ["speed"] = 125,
|
||||
-- ["type"] = "TF-51D",
|
||||
-- ["unitId"] = 1,
|
||||
-- ["psi"] = 0,
|
||||
-- ["y"] = 666285.71428571,
|
||||
-- ["x"] = -312000,
|
||||
-- ["name"] = "P51-1-1",
|
||||
-- ["payload"] =
|
||||
-- {
|
||||
-- ["pylons"] =
|
||||
-- {
|
||||
-- }, -- end of ["pylons"]
|
||||
-- ["fuel"] = 340.68,
|
||||
-- ["flare"] = 0,
|
||||
-- ["chaff"] = 0,
|
||||
-- ["gun"] = 100,
|
||||
-- }, -- end of ["payload"]
|
||||
-- ["heading"] = 0,
|
||||
-- ["callsign"] =
|
||||
-- {
|
||||
-- [1] = 1,
|
||||
-- [2] = 1,
|
||||
-- ["name"] = "Enfield11",
|
||||
-- [3] = 1,
|
||||
-- }, -- end of ["callsign"]
|
||||
-- ["onboard_num"] = "010",
|
||||
-- }, -- end of [1]
|
||||
-- }, -- end of ["units"]
|
||||
-- ["y"] = 666285.71428571,
|
||||
-- ["x"] = -312000,
|
||||
-- ["name"] = "P51",
|
||||
-- ["communication"] = true,
|
||||
-- ["start_time"] = 0,
|
||||
-- ["frequency"] = 124,
|
||||
-- }
|
||||
--
|
||||
--
|
||||
-- local mustang = SPAWN:NewFromTemplate(ttemp,"P51D")
|
||||
-- -- you MUST set the next three:
|
||||
-- mustang:InitCountry(country.id.FRANCE)
|
||||
-- mustang:InitCategory(Group.Category.AIRPLANE)
|
||||
-- mustang:InitCoalition(coalition.side.BLUE)
|
||||
-- mustang:OnSpawnGroup(
|
||||
-- function(grp)
|
||||
-- MESSAGE:New("Group Spawned: "..grp:GetName(),15,"SPAWN"):ToAll()
|
||||
-- end
|
||||
-- )
|
||||
-- mustang:Spawn()
|
||||
--
|
||||
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix, MooseNaming )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
|
||||
--if SpawnAliasPrefix == nil or SpawnAliasPrefix == "" then
|
||||
--BASE:I( "ERROR: in function NewFromTemplate, required parameter SpawnAliasPrefix is not set" )
|
||||
--return nil
|
||||
--end
|
||||
if SpawnTemplatePrefix == nil or SpawnTemplatePrefix == "" then
|
||||
BASE:I( "ERROR: in function NewFromTemplate, required parameter SpawnTemplatePrefix is not set" )
|
||||
return nil
|
||||
end
|
||||
|
||||
if SpawnTemplate then
|
||||
self.SpawnTemplate = SpawnTemplate -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
|
||||
self.SpawnTemplatePrefix = SpawnTemplatePrefix
|
||||
self.SpawnAliasPrefix = SpawnAliasPrefix
|
||||
self.SpawnAliasPrefix = SpawnAliasPrefix or SpawnTemplatePrefix
|
||||
self.SpawnTemplate.name = SpawnTemplatePrefix
|
||||
self.SpawnIndex = 0
|
||||
self.SpawnCount = 0 -- The internal counter of the amount of spawning the has happened since SpawnStart.
|
||||
self.AliveUnits = 0 -- Contains the counter how many units are currently alive
|
||||
@@ -435,7 +532,8 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
|
||||
self.SpawnInitModex = nil
|
||||
self.SpawnInitAirbase = nil
|
||||
self.TweakedTemplate = true -- Check if the user is using self made template.
|
||||
|
||||
self.MooseNameing = MooseNaming or true
|
||||
|
||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||
else
|
||||
error( "There is no template provided for SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
|
||||
@@ -3060,6 +3158,9 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
|
||||
if self.TweakedTemplate ~= nil and self.TweakedTemplate == true then
|
||||
BASE:I( "WARNING: You are using a tweaked template." )
|
||||
SpawnTemplate = self.SpawnTemplate
|
||||
if self.MooseNameing then
|
||||
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
|
||||
end
|
||||
else
|
||||
SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
||||
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
|
||||
|
||||
@@ -1001,6 +1001,24 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
||||
|
||||
end
|
||||
|
||||
--- Remove junk inside the zone using the `world.removeJunk` function.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @return #number Number of deleted objects.
|
||||
function ZONE_RADIUS:RemoveJunk()
|
||||
|
||||
local radius=self.Radius
|
||||
local vec3=self:GetVec3()
|
||||
|
||||
local volS = {
|
||||
id = world.VolumeType.SPHERE,
|
||||
params = {point = vec3, radius = radius}
|
||||
}
|
||||
|
||||
local n=world.removeJunk(volS)
|
||||
|
||||
return n
|
||||
end
|
||||
|
||||
--- Count the number of different coalitions inside the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @return #table Table of DCS units and DCS statics inside the zone.
|
||||
@@ -2141,6 +2159,35 @@ function ZONE_POLYGON_BASE:GetZoneQuad(ZoneName, DoNotRegisterZone)
|
||||
return zone
|
||||
end
|
||||
|
||||
--- Remove junk inside the zone. Due to DCS limitations, this works only for rectangular zones. So we get the smallest rectangular zone encompassing all points points of the polygon zone.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @param #number Height Height of the box in meters. Default 1000.
|
||||
-- @return #number Number of removed objects.
|
||||
function ZONE_POLYGON_BASE:RemoveJunk(Height)
|
||||
|
||||
Height=Height or 1000
|
||||
|
||||
local vec2SW, vec2NE=self:GetBoundingVec2()
|
||||
|
||||
local vec3SW={x=vec2SW.x, y=-Height, z=vec2SW.y} --DCS#Vec3
|
||||
local vec3NE={x=vec2NE.x, y= Height, z=vec2NE.y} --DCS#Vec3
|
||||
|
||||
--local coord1=COORDINATE:NewFromVec3(vec3SW):MarkToAll("SW")
|
||||
--local coord1=COORDINATE:NewFromVec3(vec3NE):MarkToAll("NE")
|
||||
|
||||
local volume = {
|
||||
id = world.VolumeType.BOX,
|
||||
params = {
|
||||
min=vec3SW,
|
||||
max=vec3SW
|
||||
}
|
||||
}
|
||||
|
||||
local n=world.removeJunk(volume)
|
||||
|
||||
return n
|
||||
end
|
||||
|
||||
--- Smokes the zone boundaries in a color.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **[funkyfranky](https://forums.eagle.ru/member.php?u=115026)**
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)
|
||||
-- ### Contributions: FlightControl, Applevangelist
|
||||
--
|
||||
-- ====
|
||||
-- @module Functional.PseudoATC
|
||||
@@ -44,7 +44,7 @@
|
||||
-- @field #number mrefresh Interval in seconds after which the F10 menu is refreshed. E.g. by the closest airports. Default is 120 sec.
|
||||
-- @field #number talt Interval in seconds between reporting altitude until touchdown. Default 3 sec.
|
||||
-- @field #boolean chatty Display some messages on events like take-off and touchdown.
|
||||
-- @field #boolean eventsmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler.
|
||||
-- @field #boolean eventsmoose [Deprecated] If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler.
|
||||
-- @field #boolean reportplayername If true, use playername not callsign on callouts
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
@@ -100,13 +100,14 @@ PSEUDOATC.id="PseudoATC | "
|
||||
|
||||
--- PSEUDOATC version.
|
||||
-- @field #number version
|
||||
PSEUDOATC.version="0.9.5"
|
||||
PSEUDOATC.version="0.10.5"
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO list
|
||||
-- DONE: Add takeoff event.
|
||||
-- DONE: Add user functions.
|
||||
-- DONE: Refactor to use Moose event handling only
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -131,23 +132,14 @@ function PSEUDOATC:Start()
|
||||
self:F()
|
||||
|
||||
-- Debug info
|
||||
self:E(PSEUDOATC.id.."Starting PseudoATC")
|
||||
self:I(PSEUDOATC.id.."Starting PseudoATC")
|
||||
|
||||
-- Handle events.
|
||||
if self.eventsmoose then
|
||||
self:T(PSEUDOATC.id.."Events are handled by MOOSE.")
|
||||
self:HandleEvent(EVENTS.Birth, self._OnBirth)
|
||||
self:HandleEvent(EVENTS.Land, self._PlayerLanded)
|
||||
self:HandleEvent(EVENTS.Takeoff, self._PlayerTakeOff)
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._PlayerLeft)
|
||||
self:HandleEvent(EVENTS.Crash, self._PlayerLeft)
|
||||
--self:HandleEvent(EVENTS.Ejection, self._PlayerLeft)
|
||||
--self:HandleEvent(EVENTS.PilotDead, self._PlayerLeft)
|
||||
else
|
||||
self:T(PSEUDOATC.id.."Events are handled by DCS.")
|
||||
-- Events are handled directly by DCS.
|
||||
world.addEventHandler(self)
|
||||
end
|
||||
self:HandleEvent(EVENTS.Birth, self._OnBirth)
|
||||
self:HandleEvent(EVENTS.Land, self._PlayerLanded)
|
||||
self:HandleEvent(EVENTS.Takeoff, self._PlayerTakeOff)
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._PlayerLeft)
|
||||
self:HandleEvent(EVENTS.Crash, self._PlayerLeft)
|
||||
|
||||
end
|
||||
|
||||
@@ -199,7 +191,7 @@ function PSEUDOATC:SetMenuRefresh(interval)
|
||||
self.mrefresh=interval or 120
|
||||
end
|
||||
|
||||
--- Enable/disable event handling by MOOSE or DCS.
|
||||
--- [Deprecated] Enable/disable event handling by MOOSE or DCS.
|
||||
-- @param #PSEUDOATC self
|
||||
-- @param #boolean switch If true, events are handled by MOOSE (default). If false, events are handled directly by DCS.
|
||||
function PSEUDOATC:SetEventsMoose(switch)
|
||||
@@ -216,84 +208,6 @@ end
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Event Handling
|
||||
|
||||
--- Event handler for suppressed groups.
|
||||
--@param #PSEUDOATC self
|
||||
--@param #table Event Event data table. Holds event.id, event.initiator and event.target etc.
|
||||
function PSEUDOATC:onEvent(Event)
|
||||
if Event == nil or Event.initiator == nil or Unit.getByName(Event.initiator:getName()) == nil then
|
||||
return true
|
||||
end
|
||||
|
||||
local DCSiniunit = Event.initiator
|
||||
local DCSplace = Event.place
|
||||
local DCSsubplace = Event.subplace
|
||||
|
||||
local EventData={}
|
||||
local _playerunit=nil
|
||||
local _playername=nil
|
||||
|
||||
if Event.initiator then
|
||||
EventData.IniUnitName = Event.initiator:getName()
|
||||
EventData.IniDCSGroup = Event.initiator:getGroup()
|
||||
EventData.IniGroupName = Event.initiator:getGroup():getName()
|
||||
-- Get player unit and name. This returns nil,nil if the event was not fired by a player unit. And these are the only events we are interested in.
|
||||
_playerunit, _playername = self:_GetPlayerUnitAndName(EventData.IniUnitName)
|
||||
end
|
||||
|
||||
if Event.place then
|
||||
EventData.Place=Event.place
|
||||
EventData.PlaceName=Event.place:getName()
|
||||
end
|
||||
if Event.subplace then
|
||||
EventData.SubPlace=Event.subplace
|
||||
EventData.SubPlaceName=Event.subplace:getName()
|
||||
end
|
||||
|
||||
-- Event info.
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: Event in onEvent with ID = %s", tostring(Event.id)))
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: Ini unit = %s" , tostring(EventData.IniUnitName)))
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: Ini group = %s" , tostring(EventData.IniGroupName)))
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: Ini player = %s" , tostring(_playername)))
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: Place = %s" , tostring(EventData.PlaceName)))
|
||||
self:T3(PSEUDOATC.id..string.format("EVENT: SubPlace = %s" , tostring(EventData.SubPlaceName)))
|
||||
|
||||
-- Event birth.
|
||||
if Event.id == world.event.S_EVENT_BIRTH and _playername then
|
||||
self:_OnBirth(EventData)
|
||||
end
|
||||
|
||||
-- Event takeoff.
|
||||
if Event.id == world.event.S_EVENT_TAKEOFF and _playername and EventData.Place then
|
||||
self:_PlayerTakeOff(EventData)
|
||||
end
|
||||
|
||||
-- Event land.
|
||||
if Event.id == world.event.S_EVENT_LAND and _playername and EventData.Place then
|
||||
self:_PlayerLanded(EventData)
|
||||
end
|
||||
|
||||
-- Event player left unit
|
||||
if Event.id == world.event.S_EVENT_PLAYER_LEAVE_UNIT and _playername then
|
||||
self:_PlayerLeft(EventData)
|
||||
end
|
||||
|
||||
-- Event crash ==> player left unit
|
||||
if Event.id == world.event.S_EVENT_CRASH and _playername then
|
||||
self:_PlayerLeft(EventData)
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Event eject ==> player left unit
|
||||
if Event.id == world.event.S_EVENT_EJECTION and _playername then
|
||||
self:_PlayerLeft(EventData)
|
||||
end
|
||||
|
||||
-- Event pilot dead ==> player left unit
|
||||
if Event.id == world.event.S_EVENT_PILOT_DEAD and _playername then
|
||||
self:_PlayerLeft(EventData)
|
||||
end
|
||||
]]
|
||||
end
|
||||
|
||||
--- Function called my MOOSE event handler when a player enters a unit.
|
||||
-- @param #PSEUDOATC self
|
||||
@@ -303,7 +217,9 @@ function PSEUDOATC:_OnBirth(EventData)
|
||||
|
||||
-- Get unit and player.
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
--local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
local _unit = EventData.IniUnit
|
||||
local _playername = EventData.IniPlayerName
|
||||
|
||||
-- Check if a player entered.
|
||||
if _unit and _playername then
|
||||
@@ -320,7 +236,10 @@ function PSEUDOATC:_PlayerLeft(EventData)
|
||||
|
||||
-- Get unit and player.
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
--local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
|
||||
local _unit = EventData.IniUnit
|
||||
local _playername = EventData.IniPlayerName
|
||||
|
||||
-- Check if a player left.
|
||||
if _unit and _playername then
|
||||
@@ -335,18 +254,16 @@ function PSEUDOATC:_PlayerLanded(EventData)
|
||||
self:F({EventData=EventData})
|
||||
|
||||
-- Get unit, player and place.
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit = EventData.IniUnit
|
||||
local _playername = EventData.IniPlayerName
|
||||
--local _unit, _playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
local _base=nil
|
||||
local _baseName=nil
|
||||
if EventData.place then
|
||||
_base=EventData.place
|
||||
_baseName=EventData.place:getName()
|
||||
end
|
||||
-- if EventData.subplace then
|
||||
-- local _subPlace=EventData.subplace
|
||||
-- local _subPlaceName=EventData.subplace:getName()
|
||||
-- end
|
||||
|
||||
-- Call landed function.
|
||||
if _unit and _playername and _base then
|
||||
@@ -361,8 +278,10 @@ function PSEUDOATC:_PlayerTakeOff(EventData)
|
||||
self:F({EventData=EventData})
|
||||
|
||||
-- Get unit, player and place.
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit,_playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
local _unitName=EventData.IniUnitName
|
||||
local _unit = EventData.IniUnit
|
||||
local _playername = EventData.IniPlayerName
|
||||
--local _unit,_playername=self:_GetPlayerUnitAndName(_unitName)
|
||||
local _base=nil
|
||||
local _baseName=nil
|
||||
if EventData.place then
|
||||
@@ -450,9 +369,6 @@ function PSEUDOATC:PlayerLanded(unit, place)
|
||||
local group=unit:GetGroup()
|
||||
local GID=group:GetID()
|
||||
local UID=unit:GetDCSObject():getID()
|
||||
--local PlayerName=self.group[GID].player[UID].playername
|
||||
--local UnitName=self.group[GID].player[UID].unitname
|
||||
--local GroupName=self.group[GID].player[UID].groupname
|
||||
local PlayerName = unit:GetPlayerName() or "Ghost"
|
||||
local UnitName = unit:GetName() or "Ghostplane"
|
||||
local GroupName = group:GetName() or "Ghostgroup"
|
||||
@@ -483,12 +399,6 @@ function PSEUDOATC:PlayerTakeOff(unit, place)
|
||||
|
||||
-- Gather some information.
|
||||
local group=unit:GetGroup()
|
||||
--local GID=group:GetID()
|
||||
--local UID=unit:GetDCSObject():getID()
|
||||
--local PlayerName=self.group[GID].player[UID].playername
|
||||
--local CallSign=self.group[GID].player[UID].callsign
|
||||
--local UnitName=self.group[GID].player[UID].unitname
|
||||
--local GroupName=self.group[GID].player[UID].groupname
|
||||
local PlayerName = unit:GetPlayerName() or "Ghost"
|
||||
local UnitName = unit:GetName() or "Ghostplane"
|
||||
local GroupName = group:GetName() or "Ghostgroup"
|
||||
@@ -926,7 +836,7 @@ function PSEUDOATC:AltitudeTimeStart(GID, UID)
|
||||
self:T(PSEUDOATC.id..string.format("Starting altitude report timer for player ID %d.", UID))
|
||||
|
||||
-- Start timer. Altitude is reported every ~3 seconds.
|
||||
self.group[GID].player[UID].altimer, self.group[GID].player[UID].altimerid=SCHEDULER:New(nil, self.ReportHeight, {self, GID, UID, 0.1, true}, 1, 3)
|
||||
self.group[GID].player[UID].altimer, self.group[GID].player[UID].altimerid=SCHEDULER:New(nil, self.ReportHeight, {self, GID, UID, 1, true}, 1, 3)
|
||||
end
|
||||
|
||||
--- Stop/destroy DCS scheduler function for reporting altitude.
|
||||
|
||||
@@ -1798,7 +1798,7 @@ _WAREHOUSEDB = {
|
||||
|
||||
--- Warehouse class version.
|
||||
-- @field #string version
|
||||
WAREHOUSE.version="1.0.2"
|
||||
WAREHOUSE.version="1.0.2a"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO: Warehouse todo list.
|
||||
@@ -4561,7 +4561,8 @@ function WAREHOUSE:onafterRequest(From, Event, To, Request)
|
||||
self:_ErrorMessage("ERROR: Cargo transport by train not supported yet!")
|
||||
return
|
||||
|
||||
elseif Request.transporttype==WAREHOUSE.TransportType.SHIP or Request.transporttype==WAREHOUSE.TransportType.NAVALCARRIER then
|
||||
elseif Request.transporttype==WAREHOUSE.TransportType.SHIP or Request.transporttype==WAREHOUSE.TransportType.NAVALCARRIER
|
||||
or Request.transporttype==WAREHOUSE.TransportType.ARMEDSHIP or Request.transporttype==WAREHOUSE.TransportType.WARSHIP then
|
||||
|
||||
-- Spawn Ship in port zone
|
||||
spawngroup=self:_SpawnAssetGroundNaval(_alias, _assetitem, Request, self.portzone)
|
||||
@@ -5829,62 +5830,65 @@ function WAREHOUSE:_SpawnAssetRequest(Request)
|
||||
|
||||
-- Get stock item.
|
||||
local asset=cargoassets[i] --#WAREHOUSE.Assetitem
|
||||
|
||||
if not asset.spawned then
|
||||
|
||||
-- Set asset status to not spawned until we capture its birth event.
|
||||
asset.spawned=false
|
||||
asset.iscargo=true
|
||||
|
||||
-- Set request ID.
|
||||
asset.rid=Request.uid
|
||||
|
||||
-- Spawn group name.
|
||||
local _alias=asset.spawngroupname
|
||||
|
||||
--Request add asset by id.
|
||||
Request.assets[asset.uid]=asset
|
||||
|
||||
-- Spawn an asset group.
|
||||
local _group=nil --Wrapper.Group#GROUP
|
||||
if asset.category==Group.Category.GROUND then
|
||||
|
||||
-- Spawn ground troops.
|
||||
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone, Request.lateActivation)
|
||||
|
||||
elseif asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then
|
||||
|
||||
-- Spawn air units.
|
||||
if Parking[asset.uid] then
|
||||
_group=self:_SpawnAssetAircraft(_alias, asset, Request, Parking[asset.uid], UnControlled, Request.lateActivation)
|
||||
else
|
||||
_group=self:_SpawnAssetAircraft(_alias, asset, Request, nil, UnControlled, Request.lateActivation)
|
||||
end
|
||||
|
||||
elseif asset.category==Group.Category.TRAIN then
|
||||
|
||||
-- Spawn train.
|
||||
if self.rail then
|
||||
--TODO: Rail should only get one asset because they would spawn on top!
|
||||
|
||||
-- Spawn naval assets.
|
||||
-- Set asset status to not spawned until we capture its birth event.
|
||||
asset.iscargo=true
|
||||
|
||||
-- Set request ID.
|
||||
asset.rid=Request.uid
|
||||
|
||||
-- Spawn group name.
|
||||
local _alias=asset.spawngroupname
|
||||
|
||||
--Request add asset by id.
|
||||
Request.assets[asset.uid]=asset
|
||||
|
||||
-- Spawn an asset group.
|
||||
local _group=nil --Wrapper.Group#GROUP
|
||||
if asset.category==Group.Category.GROUND then
|
||||
|
||||
-- Spawn ground troops.
|
||||
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone, Request.lateActivation)
|
||||
|
||||
elseif asset.category==Group.Category.AIRPLANE or asset.category==Group.Category.HELICOPTER then
|
||||
|
||||
-- Spawn air units.
|
||||
if Parking[asset.uid] then
|
||||
_group=self:_SpawnAssetAircraft(_alias, asset, Request, Parking[asset.uid], UnControlled, Request.lateActivation)
|
||||
else
|
||||
_group=self:_SpawnAssetAircraft(_alias, asset, Request, nil, UnControlled, Request.lateActivation)
|
||||
end
|
||||
|
||||
elseif asset.category==Group.Category.TRAIN then
|
||||
|
||||
-- Spawn train.
|
||||
if self.rail then
|
||||
--TODO: Rail should only get one asset because they would spawn on top!
|
||||
|
||||
-- Spawn naval assets.
|
||||
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.spawnzone, Request.lateActivation)
|
||||
end
|
||||
|
||||
--self:E(self.lid.."ERROR: Spawning of TRAIN assets not possible yet!")
|
||||
|
||||
elseif asset.category==Group.Category.SHIP then
|
||||
|
||||
-- Spawn naval assets.
|
||||
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.portzone, Request.lateActivation)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Unknown asset category!")
|
||||
end
|
||||
|
||||
--self:E(self.lid.."ERROR: Spawning of TRAIN assets not possible yet!")
|
||||
|
||||
elseif asset.category==Group.Category.SHIP then
|
||||
|
||||
-- Spawn naval assets.
|
||||
_group=self:_SpawnAssetGroundNaval(_alias, asset, Request, self.portzone, Request.lateActivation)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Unknown asset category!")
|
||||
|
||||
-- Trigger event.
|
||||
if _group then
|
||||
self:__AssetSpawned(0.01, _group, asset, Request)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Trigger event.
|
||||
if _group then
|
||||
self:__AssetSpawned(0.01, _group, asset, Request)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -5826,7 +5826,7 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
if knownflight then
|
||||
|
||||
-- Check if flight is AI and if we want to handle it at all.
|
||||
if knownflight.ai and knownflight.flag == -100 and self.handleai and false then --Disabled AI handling because of incorrect OPSGROUP reference!
|
||||
if knownflight.ai and knownflight.flag == -100 and self.handleai and false then --Disabled AI handling because of incorrect OPSGROUP reference!
|
||||
|
||||
local putintomarshal = false
|
||||
|
||||
@@ -8102,7 +8102,7 @@ end
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AIRBOSS:OnEventBirth( EventData )
|
||||
self:F3( { eventbirth = EventData } )
|
||||
|
||||
|
||||
-- Nil checks.
|
||||
if EventData == nil then
|
||||
self:E( self.lid .. "ERROR: EventData=nil in event BIRTH!" )
|
||||
@@ -8114,7 +8114,9 @@ function AIRBOSS:OnEventBirth( EventData )
|
||||
self:E( EventData )
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if EventData.IniObjectCategory ~= Object.Category.UNIT then return end
|
||||
|
||||
local _unitName = EventData.IniUnitName
|
||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
||||
|
||||
@@ -9792,23 +9794,23 @@ function AIRBOSS:_Groove( playerData )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)--- Need to think more about this.
|
||||
|
||||
|
||||
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)--- Need to think more about this.
|
||||
|
||||
--if rho>=RAR and rho<=RIC and not playerData.waveoff and playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype== AIRBOSS.AircraftCarrier.AV8B then
|
||||
-- Get groove time
|
||||
--local vSlow=groovedata.time
|
||||
-- If too slow wave off.
|
||||
--if vSlow >75 then
|
||||
|
||||
|
||||
-- LSO Wave off!
|
||||
--self:RadioTransmission(self.LSORadio, self.LSOCall.WAVEOFF, nil, nil, nil, true)
|
||||
--playerData.Tlso=timer.getTime()
|
||||
|
||||
|
||||
-- Player was waved Off
|
||||
--playerData.waveoff=true
|
||||
--return
|
||||
--end
|
||||
--end
|
||||
--end
|
||||
|
||||
-- Groovedata step.
|
||||
@@ -10162,7 +10164,7 @@ function AIRBOSS:_GetSternCoord()
|
||||
elseif case==2 or case==1 then
|
||||
-- V/Stol: Translate 8 meters port.
|
||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
|
||||
end
|
||||
end
|
||||
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
||||
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7, FB + 90, true, true )
|
||||
@@ -11302,7 +11304,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
|
||||
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
|
||||
-- Ideally we want to land between 2nd and 3rd wire.
|
||||
|
||||
@@ -22,7 +22,300 @@
|
||||
-- @module Ops.CTLD
|
||||
-- @image OPS_CTLD.jpg
|
||||
|
||||
-- Last Update Mar 2023
|
||||
-- Last Update Apr 2023
|
||||
|
||||
do
|
||||
|
||||
------------------------------------------------------
|
||||
--- **CTLD_CARGO** class, extends Core.Base#BASE
|
||||
-- @type CTLD_CARGO
|
||||
-- @field #string ClassName Class name.
|
||||
-- @field #number ID ID of this cargo.
|
||||
-- @field #string Name Name for menu.
|
||||
-- @field #table Templates Table of #POSITIONABLE objects.
|
||||
-- @field #string CargoType Enumerator of Type.
|
||||
-- @field #boolean HasBeenMoved Flag for moving.
|
||||
-- @field #boolean LoadDirectly Flag for direct loading.
|
||||
-- @field #number CratesNeeded Crates needed to build.
|
||||
-- @field Wrapper.Positionable#POSITIONABLE Positionable Representation of cargo in the mission.
|
||||
-- @field #boolean HasBeenDropped True if dropped from heli.
|
||||
-- @field #number PerCrateMass Mass in kg.
|
||||
-- @field #number Stock Number of builds available, -1 for unlimited.
|
||||
-- @field #string Subcategory Sub-category name.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @field #CTLD_CARGO CTLD_CARGO
|
||||
CTLD_CARGO = {
|
||||
ClassName = "CTLD_CARGO",
|
||||
ID = 0,
|
||||
Name = "none",
|
||||
Templates = {},
|
||||
CargoType = "none",
|
||||
HasBeenMoved = false,
|
||||
LoadDirectly = false,
|
||||
CratesNeeded = 0,
|
||||
Positionable = nil,
|
||||
HasBeenDropped = false,
|
||||
PerCrateMass = 0,
|
||||
Stock = nil,
|
||||
Mark = nil,
|
||||
}
|
||||
|
||||
--- Define cargo types.
|
||||
-- @type CTLD_CARGO.Enum
|
||||
-- @field #string VEHICLE
|
||||
-- @field #string TROOPS
|
||||
-- @field #string FOB
|
||||
-- @field #string CRATE
|
||||
-- @field #string REPAIR
|
||||
-- @field #string ENGINEERS
|
||||
-- @field #string STATIC
|
||||
CTLD_CARGO.Enum = {
|
||||
VEHICLE = "Vehicle", -- #string vehicles
|
||||
TROOPS = "Troops", -- #string troops
|
||||
FOB = "FOB", -- #string FOB
|
||||
CRATE = "Crate", -- #string crate
|
||||
REPAIR = "Repair", -- #string repair
|
||||
ENGINEERS = "Engineers", -- #string engineers
|
||||
STATIC = "Static", -- #string statics
|
||||
}
|
||||
|
||||
--- Function to create new CTLD_CARGO object.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number ID ID of this #CTLD_CARGO
|
||||
-- @param #string Name Name for menu.
|
||||
-- @param #table Templates Table of #POSITIONABLE objects.
|
||||
-- @param #CTLD_CARGO.Enum Sorte Enumerator of Type.
|
||||
-- @param #boolean HasBeenMoved Flag for moving.
|
||||
-- @param #boolean LoadDirectly Flag for direct loading.
|
||||
-- @param #number CratesNeeded Crates needed to build.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Positionable Representation of cargo in the mission.
|
||||
-- @param #boolean Dropped Cargo/Troops have been unloaded from a chopper.
|
||||
-- @param #number PerCrateMass Mass in kg
|
||||
-- @param #number Stock Number of builds available, nil for unlimited
|
||||
-- @param #string Subcategory Name of subcategory, handy if using > 10 types to load.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory)
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CTLD_CARGO
|
||||
self:T({ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped})
|
||||
self.ID = ID or math.random(100000,1000000)
|
||||
self.Name = Name or "none" -- #string
|
||||
self.Templates = Templates or {} -- #table
|
||||
self.CargoType = Sorte or "type" -- #CTLD_CARGO.Enum
|
||||
self.HasBeenMoved = HasBeenMoved or false -- #boolean
|
||||
self.LoadDirectly = LoadDirectly or false -- #boolean
|
||||
self.CratesNeeded = CratesNeeded or 0 -- #number
|
||||
self.Positionable = Positionable or nil -- Wrapper.Positionable#POSITIONABLE
|
||||
self.HasBeenDropped = Dropped or false --#boolean
|
||||
self.PerCrateMass = PerCrateMass or 0 -- #number
|
||||
self.Stock = Stock or nil --#number
|
||||
self.Mark = nil
|
||||
self.Subcategory = Subcategory or "Other"
|
||||
return self
|
||||
end
|
||||
|
||||
--- Query ID.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number ID
|
||||
function CTLD_CARGO:GetID()
|
||||
return self.ID
|
||||
end
|
||||
|
||||
--- Query Subcategory
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string SubCategory
|
||||
function CTLD_CARGO:GetSubCat()
|
||||
return self.Subcategory
|
||||
end
|
||||
|
||||
--- Query Mass.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Mass in kg
|
||||
function CTLD_CARGO:GetMass()
|
||||
return self.PerCrateMass
|
||||
end
|
||||
|
||||
--- Query Name.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string Name
|
||||
function CTLD_CARGO:GetName()
|
||||
return self.Name
|
||||
end
|
||||
|
||||
--- Query Templates.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #table Templates
|
||||
function CTLD_CARGO:GetTemplates()
|
||||
return self.Templates
|
||||
end
|
||||
|
||||
--- Query has moved.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean Has moved
|
||||
function CTLD_CARGO:HasMoved()
|
||||
return self.HasBeenMoved
|
||||
end
|
||||
|
||||
--- Query was dropped.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean Has been dropped.
|
||||
function CTLD_CARGO:WasDropped()
|
||||
return self.HasBeenDropped
|
||||
end
|
||||
|
||||
--- Query directly loadable.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean loadable
|
||||
function CTLD_CARGO:CanLoadDirectly()
|
||||
return self.LoadDirectly
|
||||
end
|
||||
|
||||
--- Query number of crates or troopsize.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Crates or size of troops.
|
||||
function CTLD_CARGO:GetCratesNeeded()
|
||||
return self.CratesNeeded
|
||||
end
|
||||
|
||||
--- Query type.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO.Enum Type
|
||||
function CTLD_CARGO:GetType()
|
||||
return self.CargoType
|
||||
end
|
||||
|
||||
--- Query type.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return Wrapper.Positionable#POSITIONABLE Positionable
|
||||
function CTLD_CARGO:GetPositionable()
|
||||
return self.Positionable
|
||||
end
|
||||
|
||||
--- Set HasMoved.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean moved
|
||||
function CTLD_CARGO:SetHasMoved(moved)
|
||||
self.HasBeenMoved = moved or false
|
||||
end
|
||||
|
||||
--- Query if cargo has been loaded.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean loaded
|
||||
function CTLD_CARGO:Isloaded()
|
||||
if self.HasBeenMoved and not self.WasDropped() then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Set WasDropped.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean dropped
|
||||
function CTLD_CARGO:SetWasDropped(dropped)
|
||||
self.HasBeenDropped = dropped or false
|
||||
end
|
||||
|
||||
--- Get Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Stock
|
||||
function CTLD_CARGO:GetStock()
|
||||
if self.Stock then
|
||||
return self.Stock
|
||||
else
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
--- Add Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to add, none if nil.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:AddStock(Number)
|
||||
if self.Stock then -- Stock nil?
|
||||
local number = Number or 1
|
||||
self.Stock = self.Stock + number
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to reduce, none if nil.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:RemoveStock(Number)
|
||||
if self.Stock then -- Stock nil?
|
||||
local number = Number or 1
|
||||
self.Stock = self.Stock - number
|
||||
if self.Stock < 0 then self.Stock = 0 end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to set, nil means unlimited.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:SetStock(Number)
|
||||
self.Stock = Number
|
||||
return self
|
||||
end
|
||||
|
||||
--- Query crate type for REPAIR
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean
|
||||
function CTLD_CARGO:IsRepair()
|
||||
if self.CargoType == "Repair" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Query crate type for STATIC
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean
|
||||
function CTLD_CARGO:IsStatic()
|
||||
if self.CargoType == "Static" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Add mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:AddMark(Mark)
|
||||
self.Mark = Mark
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string Mark
|
||||
function CTLD_CARGO:GetMark(Mark)
|
||||
return self.Mark
|
||||
end
|
||||
|
||||
--- Wipe mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:WipeMark()
|
||||
self.Mark = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get overall mass of a cargo object, i.e. crates needed x mass per crate
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number mass
|
||||
function CTLD_CARGO:GetNetMass()
|
||||
return self.CratesNeeded * self.PerCrateMass
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
|
||||
@@ -40,7 +333,7 @@ do
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @field #CTLD_ENGINEERING
|
||||
-- @field #CTLD_ENGINEERING CTLD_ENGINEERING
|
||||
CTLD_ENGINEERING = {
|
||||
ClassName = "CTLD_ENGINEERING",
|
||||
lid = "",
|
||||
@@ -287,300 +580,6 @@ CTLD_ENGINEERING = {
|
||||
|
||||
end
|
||||
|
||||
|
||||
do
|
||||
|
||||
------------------------------------------------------
|
||||
--- **CTLD_CARGO** class, extends Core.Base#BASE
|
||||
-- @type CTLD_CARGO
|
||||
-- @field #string ClassName Class name.
|
||||
-- @field #number ID ID of this cargo.
|
||||
-- @field #string Name Name for menu.
|
||||
-- @field #table Templates Table of #POSITIONABLE objects.
|
||||
-- @field #string CargoType Enumerator of Type.
|
||||
-- @field #boolean HasBeenMoved Flag for moving.
|
||||
-- @field #boolean LoadDirectly Flag for direct loading.
|
||||
-- @field #number CratesNeeded Crates needed to build.
|
||||
-- @field Wrapper.Positionable#POSITIONABLE Positionable Representation of cargo in the mission.
|
||||
-- @field #boolean HasBeenDropped True if dropped from heli.
|
||||
-- @field #number PerCrateMass Mass in kg.
|
||||
-- @field #number Stock Number of builds available, -1 for unlimited.
|
||||
-- @field #string Subcategory Sub-category name.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @field #CTLD_CARGO CTLD_CARGO
|
||||
CTLD_CARGO = {
|
||||
ClassName = "CTLD_CARGO",
|
||||
ID = 0,
|
||||
Name = "none",
|
||||
Templates = {},
|
||||
CargoType = "none",
|
||||
HasBeenMoved = false,
|
||||
LoadDirectly = false,
|
||||
CratesNeeded = 0,
|
||||
Positionable = nil,
|
||||
HasBeenDropped = false,
|
||||
PerCrateMass = 0,
|
||||
Stock = nil,
|
||||
Mark = nil,
|
||||
}
|
||||
|
||||
--- Define cargo types.
|
||||
-- @type CTLD_CARGO.Enum
|
||||
-- @field #string VEHICLE
|
||||
-- @field #string TROOPS
|
||||
-- @field #string FOB
|
||||
-- @field #string CRATE
|
||||
-- @field #string REPAIR
|
||||
-- @field #string ENGINEERS
|
||||
-- @field #string STATIC
|
||||
CTLD_CARGO.Enum = {
|
||||
VEHICLE = "Vehicle", -- #string vehicles
|
||||
TROOPS = "Troops", -- #string troops
|
||||
FOB = "FOB", -- #string FOB
|
||||
CRATE = "Crate", -- #string crate
|
||||
REPAIR = "Repair", -- #string repair
|
||||
ENGINEERS = "Engineers", -- #string engineers
|
||||
STATIC = "Static", -- #string statics
|
||||
}
|
||||
|
||||
--- Function to create new CTLD_CARGO object.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number ID ID of this #CTLD_CARGO
|
||||
-- @param #string Name Name for menu.
|
||||
-- @param #table Templates Table of #POSITIONABLE objects.
|
||||
-- @param #CTLD_CARGO.Enum Sorte Enumerator of Type.
|
||||
-- @param #boolean HasBeenMoved Flag for moving.
|
||||
-- @param #boolean LoadDirectly Flag for direct loading.
|
||||
-- @param #number CratesNeeded Crates needed to build.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Positionable Representation of cargo in the mission.
|
||||
-- @param #boolean Dropped Cargo/Troops have been unloaded from a chopper.
|
||||
-- @param #number PerCrateMass Mass in kg
|
||||
-- @param #number Stock Number of builds available, nil for unlimited
|
||||
-- @param #string Subcategory Name of subcategory, handy if using > 10 types to load.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:New(ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped, PerCrateMass, Stock, Subcategory)
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CTLD
|
||||
self:T({ID, Name, Templates, Sorte, HasBeenMoved, LoadDirectly, CratesNeeded, Positionable, Dropped})
|
||||
self.ID = ID or math.random(100000,1000000)
|
||||
self.Name = Name or "none" -- #string
|
||||
self.Templates = Templates or {} -- #table
|
||||
self.CargoType = Sorte or "type" -- #CTLD_CARGO.Enum
|
||||
self.HasBeenMoved = HasBeenMoved or false -- #boolean
|
||||
self.LoadDirectly = LoadDirectly or false -- #boolean
|
||||
self.CratesNeeded = CratesNeeded or 0 -- #number
|
||||
self.Positionable = Positionable or nil -- Wrapper.Positionable#POSITIONABLE
|
||||
self.HasBeenDropped = Dropped or false --#boolean
|
||||
self.PerCrateMass = PerCrateMass or 0 -- #number
|
||||
self.Stock = Stock or nil --#number
|
||||
self.Mark = nil
|
||||
self.Subcategory = Subcategory or "Other"
|
||||
return self
|
||||
end
|
||||
|
||||
--- Query ID.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number ID
|
||||
function CTLD_CARGO:GetID()
|
||||
return self.ID
|
||||
end
|
||||
|
||||
--- Query Subcategory
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string SubCategory
|
||||
function CTLD_CARGO:GetSubCat()
|
||||
return self.Subcategory
|
||||
end
|
||||
|
||||
--- Query Mass.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Mass in kg
|
||||
function CTLD_CARGO:GetMass()
|
||||
return self.PerCrateMass
|
||||
end
|
||||
|
||||
--- Query Name.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string Name
|
||||
function CTLD_CARGO:GetName()
|
||||
return self.Name
|
||||
end
|
||||
|
||||
--- Query Templates.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #table Templates
|
||||
function CTLD_CARGO:GetTemplates()
|
||||
return self.Templates
|
||||
end
|
||||
|
||||
--- Query has moved.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean Has moved
|
||||
function CTLD_CARGO:HasMoved()
|
||||
return self.HasBeenMoved
|
||||
end
|
||||
|
||||
--- Query was dropped.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean Has been dropped.
|
||||
function CTLD_CARGO:WasDropped()
|
||||
return self.HasBeenDropped
|
||||
end
|
||||
|
||||
--- Query directly loadable.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean loadable
|
||||
function CTLD_CARGO:CanLoadDirectly()
|
||||
return self.LoadDirectly
|
||||
end
|
||||
|
||||
--- Query number of crates or troopsize.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Crates or size of troops.
|
||||
function CTLD_CARGO:GetCratesNeeded()
|
||||
return self.CratesNeeded
|
||||
end
|
||||
|
||||
--- Query type.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO.Enum Type
|
||||
function CTLD_CARGO:GetType()
|
||||
return self.CargoType
|
||||
end
|
||||
|
||||
--- Query type.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return Wrapper.Positionable#POSITIONABLE Positionable
|
||||
function CTLD_CARGO:GetPositionable()
|
||||
return self.Positionable
|
||||
end
|
||||
|
||||
--- Set HasMoved.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean moved
|
||||
function CTLD_CARGO:SetHasMoved(moved)
|
||||
self.HasBeenMoved = moved or false
|
||||
end
|
||||
|
||||
--- Query if cargo has been loaded.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean loaded
|
||||
function CTLD_CARGO:Isloaded()
|
||||
if self.HasBeenMoved and not self.WasDropped() then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Set WasDropped.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean dropped
|
||||
function CTLD_CARGO:SetWasDropped(dropped)
|
||||
self.HasBeenDropped = dropped or false
|
||||
end
|
||||
|
||||
--- Get Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number Stock
|
||||
function CTLD_CARGO:GetStock()
|
||||
if self.Stock then
|
||||
return self.Stock
|
||||
else
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
--- Add Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to add, none if nil.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:AddStock(Number)
|
||||
if self.Stock then -- Stock nil?
|
||||
local number = Number or 1
|
||||
self.Stock = self.Stock + number
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to reduce, none if nil.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:RemoveStock(Number)
|
||||
if self.Stock then -- Stock nil?
|
||||
local number = Number or 1
|
||||
self.Stock = self.Stock - number
|
||||
if self.Stock < 0 then self.Stock = 0 end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set Stock.
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #number Number to set, nil means unlimited.
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:SetStock(Number)
|
||||
self.Stock = Number
|
||||
return self
|
||||
end
|
||||
|
||||
--- Query crate type for REPAIR
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @param #boolean
|
||||
function CTLD_CARGO:IsRepair()
|
||||
if self.CargoType == "Repair" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Query crate type for STATIC
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #boolean
|
||||
function CTLD_CARGO:IsStatic()
|
||||
if self.CargoType == "Static" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- Add mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:AddMark(Mark)
|
||||
self.Mark = Mark
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #string Mark
|
||||
function CTLD_CARGO:GetMark(Mark)
|
||||
return self.Mark
|
||||
end
|
||||
|
||||
--- Wipe mark
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #CTLD_CARGO self
|
||||
function CTLD_CARGO:WipeMark()
|
||||
self.Mark = nil
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get overall mass of a cargo object, i.e. crates needed x mass per crate
|
||||
-- @param #CTLD_CARGO self
|
||||
-- @return #number mass
|
||||
function CTLD_CARGO:GetNetMass()
|
||||
return self.CratesNeeded * self.PerCrateMass
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO CTLD
|
||||
@@ -726,6 +725,8 @@ do
|
||||
-- my_ctld.movecratesbeforebuild = true -- crates must be moved once before they can be build. Set to false for direct builds.
|
||||
-- my_ctld.surfacetypes = {land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.RUNWAY,land.SurfaceType.SHALLOW_WATER} -- surfaces for loading back objects.
|
||||
-- my_ctld.nobuildmenu = false -- if set to true effectively enforces to have engineers build/repair stuff for you.
|
||||
-- my_ctld.RadioSound = "beacon.ogg" -- -- this sound will be hearable if you tune in the beacon frequency. Add the sound file to your miz.
|
||||
-- my_ctld.RadioSoundFC3 = "beacon.ogg" -- this sound will be hearable by FC3 users (actually all UHF radios); change to something like "beaconsilent.ogg" and add the sound file to your miz if you don't want to annoy FC3 pilots.
|
||||
--
|
||||
-- ## 2.1 User functions
|
||||
--
|
||||
@@ -987,6 +988,7 @@ do
|
||||
-- my_ctld.filename = "missionsave.csv" -- example filename
|
||||
-- my_ctld.filepath = "C:\\Users\\myname\\Saved Games\\DCS\Missions\\MyMission" -- example path
|
||||
-- my_ctld.eventoninject = true -- fire OnAfterCratesBuild and OnAfterTroopsDeployed events when loading (uses Inject functions)
|
||||
-- my_ctld.useprecisecoordloads = true -- Instead if slightly varyiing the group position, try to maintain it as is
|
||||
--
|
||||
-- Then use an initial load at the beginning of your mission:
|
||||
--
|
||||
@@ -1219,7 +1221,7 @@ CTLD.UnitTypes = {
|
||||
|
||||
--- CTLD class version.
|
||||
-- @field #string version
|
||||
CTLD.version="1.0.32"
|
||||
CTLD.version="1.0.37"
|
||||
|
||||
--- Instantiate a new CTLD.
|
||||
-- @param #CTLD self
|
||||
@@ -1302,6 +1304,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
|
||||
-- radio beacons
|
||||
self.RadioSound = "beacon.ogg"
|
||||
self.RadioSoundFC3 = "beacon.ogg"
|
||||
self.RadioPath = "l10n/DEFAULT/"
|
||||
|
||||
-- zones stuff
|
||||
@@ -1312,6 +1315,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
||||
self.droppedBeacons = {}
|
||||
self.droppedbeaconref = {}
|
||||
self.droppedbeacontimeout = 600
|
||||
self.useprecisecoordloads = true
|
||||
|
||||
-- Cargo
|
||||
self.Cargo_Crates = {}
|
||||
@@ -2005,6 +2009,7 @@ end
|
||||
|
||||
function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
self:T(self.lid .. " _FindRepairNearby")
|
||||
--self:I({Group:GetName(),Unit:GetName(),Repairtype})
|
||||
local unitcoord = Unit:GetCoordinate()
|
||||
|
||||
-- find nearest group of deployed groups
|
||||
@@ -2021,7 +2026,9 @@ function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
nearestDistance = distance
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--self:I("Distance: ".. nearestDistance)
|
||||
|
||||
-- found one and matching distance?
|
||||
if nearestGroup == nil or nearestDistance > self.EngineerSearch then
|
||||
self:_SendMessage("No unit close enough to repair!", 10, false, Group)
|
||||
@@ -2033,8 +2040,10 @@ function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
-- helper to find matching template
|
||||
local function matchstring(String,Table)
|
||||
local match = false
|
||||
if type(Table) == "table" then
|
||||
String = string.gsub(String,"-"," ")
|
||||
if type(Table) == "table" then
|
||||
for _,_name in pairs (Table) do
|
||||
_name = string.gsub(_name,"-"," ")
|
||||
if string.find(String,_name) then
|
||||
match = true
|
||||
break
|
||||
@@ -2042,6 +2051,7 @@ function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
end
|
||||
else
|
||||
if type(String) == "string" then
|
||||
Table = string.gsub(Table,"-"," ")
|
||||
if string.find(String,Table) then match = true end
|
||||
end
|
||||
end
|
||||
@@ -2051,6 +2061,7 @@ function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
-- walk through generics and find matching type
|
||||
local Cargotype = nil
|
||||
for k,v in pairs(self.Cargo_Crates) do
|
||||
--self:I({groupname,v.Templates,Repairtype})
|
||||
if matchstring(groupname,v.Templates) and matchstring(groupname,Repairtype) then
|
||||
Cargotype = v -- #CTLD_CARGO
|
||||
break
|
||||
@@ -2060,6 +2071,7 @@ function CTLD:_FindRepairNearby(Group, Unit, Repairtype)
|
||||
if Cargotype == nil then
|
||||
return nil, nil
|
||||
else
|
||||
--self:I({groupname,Cargotype})
|
||||
return nearestGroup, Cargotype
|
||||
end
|
||||
|
||||
@@ -2074,7 +2086,7 @@ end
|
||||
-- @param #number Number Number of objects in Crates (found) to limit search.
|
||||
-- @param #boolean Engineering If true it is an Engineering repair.
|
||||
function CTLD:_RepairObjectFromCrates(Group,Unit,Crates,Build,Number,Engineering)
|
||||
self:T(self.lid .. " _RepairObjectFromCrates")
|
||||
self:T(self.lid .. " _RepairObjectFromCrates")
|
||||
local build = Build -- -- #CTLD.Buildable
|
||||
local Repairtype = build.Template -- #string
|
||||
local NearestGroup, CargoType = self:_FindRepairNearby(Group,Unit,Repairtype) -- Wrapper.Group#GROUP, #CTLD_CARGO
|
||||
@@ -2326,7 +2338,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop)
|
||||
rheading = UTILS.RandomGaussian(0,30,-90,90,100)
|
||||
rheading = math.fmod((heading + rheading + addon), 360)
|
||||
else
|
||||
local initialSpacing = IsHerc and 16 or 12 -- initial spacing of the first crates
|
||||
local initialSpacing = IsHerc and 16 or (capabilities.length+2) -- initial spacing of the first crates
|
||||
local crateSpacing = 4 -- further spacing of remaining crates
|
||||
local lateralSpacing = 4 -- lateral spacing of crates
|
||||
local nrSideBySideCrates = 3 -- number of crates that are placed side-by-side
|
||||
@@ -4014,7 +4026,7 @@ function CTLD:_AddRadioBeacon(Name, Sound, Mhz, Modulation, IsShip, IsDropped)
|
||||
local Sound = self.RadioPath..Sound
|
||||
trigger.action.radioTransmission(Sound, ZoneVec3, Modulation, false, Frequency, 1000, Name..math.random(1,10000)) -- Beacon in MP only runs for 30secs straight
|
||||
self:T2(string.format("Beacon added | Name = %s | Sound = %s | Vec3 = %d %d %d | Freq = %f | Modulation = %d (0=AM/1=FM)",Name,Sound,ZoneVec3.x,ZoneVec3.y,ZoneVec3.z,Mhz,Modulation))
|
||||
else
|
||||
else
|
||||
local ZoneCoord = Zone:GetCoordinate()
|
||||
local ZoneVec3 = ZoneCoord:GetVec3() or {x=0,y=0,z=0}
|
||||
local Frequency = Mhz * 1000000 -- Freq in Hert
|
||||
@@ -4068,6 +4080,7 @@ function CTLD:_RefreshRadioBeacons()
|
||||
-- Get Beacon object from zone
|
||||
local czone = cargozone -- #CTLD.CargoZone
|
||||
local Sound = self.RadioSound
|
||||
local Silent = self.RadioSoundFC3 or self.RadioSound
|
||||
if czone.active and czone.hasbeacon then
|
||||
local FMbeacon = czone.fmbeacon -- #CTLD.ZoneBeacon
|
||||
local VHFbeacon = czone.vhfbeacon -- #CTLD.ZoneBeacon
|
||||
@@ -4077,8 +4090,8 @@ function CTLD:_RefreshRadioBeacons()
|
||||
local VHF = VHFbeacon.frequency -- KHz
|
||||
local UHF = UHFbeacon.frequency -- MHz
|
||||
self:_AddRadioBeacon(Name,Sound,FM, CTLD.RadioModulation.FM, IsShip, IsDropped)
|
||||
self:_AddRadioBeacon(Name,Sound,VHF,CTLD.RadioModulation.FM, IsShip, IsDropped)
|
||||
self:_AddRadioBeacon(Name,Sound,UHF,CTLD.RadioModulation.AM, IsShip, IsDropped)
|
||||
self:_AddRadioBeacon(Name,Sound,VHF,CTLD.RadioModulation.AM, IsShip, IsDropped)
|
||||
self:_AddRadioBeacon(Name,Silent,UHF,CTLD.RadioModulation.AM, IsShip, IsDropped)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4721,6 +4734,7 @@ end
|
||||
-- @param Ops.CTLD#CTLD_CARGO Cargo The #CTLD_CARGO object to spawn.
|
||||
-- @param #table Surfacetypes (Optional) Table of surface types. Can also be a single surface type. We will try max 1000 times to find the right type!
|
||||
-- @param #boolean PreciseLocation (Optional) Don't try to get a random position in the zone but use the dead center. Caution not to stack up stuff on another!
|
||||
-- @param #string Structure (Optional) String object describing the current structure of the injected group; mainly for load/save to keep current state setup.
|
||||
-- @return #CTLD self
|
||||
-- @usage Use this function to pre-populate the field with Troops or Engineers at a random coordinate in a zone:
|
||||
-- -- create a matching #CTLD_CARGO type
|
||||
@@ -4729,7 +4743,7 @@ end
|
||||
-- local dropzone = ZONE:New("InjectZone") -- Core.Zone#ZONE
|
||||
-- -- and go:
|
||||
-- my_ctld:InjectTroops(dropzone,InjectTroopsType,{land.SurfaceType.LAND})
|
||||
function CTLD:InjectTroops(Zone,Cargo,Surfacetypes,PreciseLocation)
|
||||
function CTLD:InjectTroops(Zone,Cargo,Surfacetypes,PreciseLocation,Structure)
|
||||
self:T(self.lid.." InjectTroops")
|
||||
local cargo = Cargo -- #CTLD_CARGO
|
||||
|
||||
@@ -4747,6 +4761,49 @@ end
|
||||
return match
|
||||
end
|
||||
|
||||
local function Cruncher(group,typename,anzahl)
|
||||
local units = group:GetUnits()
|
||||
local reduced = 0
|
||||
for _,_unit in pairs (units) do
|
||||
local typo = _unit:GetTypeName()
|
||||
if typename == typo then
|
||||
_unit:Destroy(false)
|
||||
reduced = reduced + 1
|
||||
if reduced == anzahl then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function PostSpawn(args)
|
||||
local group = args[1]
|
||||
local structure = args[2]
|
||||
if structure then
|
||||
|
||||
local loadedstructure = {}
|
||||
local strcset = UTILS.Split(structure,";")
|
||||
for _,_data in pairs(strcset) do
|
||||
local datasplit = UTILS.Split(_data,"==")
|
||||
loadedstructure[datasplit[1]] = tonumber(datasplit[2])
|
||||
end
|
||||
|
||||
local originalstructure = UTILS.GetCountPerTypeName(group)
|
||||
|
||||
for _name,_number in pairs(originalstructure) do
|
||||
local loadednumber = 0
|
||||
if loadedstructure[_name] then
|
||||
loadednumber = loadedstructure[_name]
|
||||
end
|
||||
local reduce = false
|
||||
if loadednumber < _number then reduce = true end
|
||||
|
||||
if reduce then
|
||||
Cruncher(group,_name,_number-loadednumber)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not IsTroopsMatch(cargo) then
|
||||
self.CargoCounter = self.CargoCounter + 1
|
||||
cargo.ID = self.CargoCounter
|
||||
@@ -4783,6 +4840,11 @@ end
|
||||
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
|
||||
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
|
||||
end
|
||||
|
||||
if Structure then
|
||||
BASE:ScheduleOnce(0.5,PostSpawn,{self.DroppedTroops[self.TroopCounter],Structure})
|
||||
end
|
||||
|
||||
if self.eventoninject then
|
||||
self:__TroopsDeployed(1,nil,nil,self.DroppedTroops[self.TroopCounter],type)
|
||||
end
|
||||
@@ -4794,6 +4856,9 @@ end
|
||||
-- @param #CTLD self
|
||||
-- @param Core.Zone#ZONE Zone The zone where to drop the troops.
|
||||
-- @param Ops.CTLD#CTLD_CARGO Cargo The #CTLD_CARGO object to spawn.
|
||||
-- @param #table Surfacetypes (Optional) Table of surface types. Can also be a single surface type. We will try max 1000 times to find the right type!
|
||||
-- @param #boolean PreciseLocation (Optional) Don't try to get a random position in the zone but use the dead center. Caution not to stack up stuff on another!
|
||||
-- @param #string Structure (Optional) String object describing the current structure of the injected group; mainly for load/save to keep current state setup.
|
||||
-- @return #CTLD self
|
||||
-- @usage Use this function to pre-populate the field with Vehicles or FOB at a random coordinate in a zone:
|
||||
-- -- create a matching #CTLD_CARGO type
|
||||
@@ -4802,7 +4867,7 @@ end
|
||||
-- local dropzone = ZONE:New("InjectZone") -- Core.Zone#ZONE
|
||||
-- -- and go:
|
||||
-- my_ctld:InjectVehicles(dropzone,InjectVehicleType)
|
||||
function CTLD:InjectVehicles(Zone,Cargo)
|
||||
function CTLD:InjectVehicles(Zone,Cargo,Surfacetypes,PreciseLocation,Structure)
|
||||
self:T(self.lid.." InjectVehicles")
|
||||
local cargo = Cargo -- #CTLD_CARGO
|
||||
|
||||
@@ -4820,6 +4885,49 @@ end
|
||||
return match
|
||||
end
|
||||
|
||||
local function Cruncher(group,typename,anzahl)
|
||||
local units = group:GetUnits()
|
||||
local reduced = 0
|
||||
for _,_unit in pairs (units) do
|
||||
local typo = _unit:GetTypeName()
|
||||
if typename == typo then
|
||||
_unit:Destroy(false)
|
||||
reduced = reduced + 1
|
||||
if reduced == anzahl then break end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function PostSpawn(args)
|
||||
local group = args[1]
|
||||
local structure = args[2]
|
||||
if structure then
|
||||
|
||||
local loadedstructure = {}
|
||||
local strcset = UTILS.Split(structure,";")
|
||||
for _,_data in pairs(strcset) do
|
||||
local datasplit = UTILS.Split(_data,"==")
|
||||
loadedstructure[datasplit[1]] = tonumber(datasplit[2])
|
||||
end
|
||||
|
||||
local originalstructure = UTILS.GetCountPerTypeName(group)
|
||||
|
||||
for _name,_number in pairs(originalstructure) do
|
||||
local loadednumber = 0
|
||||
if loadedstructure[_name] then
|
||||
loadednumber = loadedstructure[_name]
|
||||
end
|
||||
local reduce = false
|
||||
if loadednumber < _number then reduce = true end
|
||||
|
||||
if reduce then
|
||||
Cruncher(group,_name,_number-loadednumber)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not IsVehicMatch(cargo) then
|
||||
self.CargoCounter = self.CargoCounter + 1
|
||||
cargo.ID = self.CargoCounter
|
||||
@@ -4834,7 +4942,10 @@ end
|
||||
local temptable = cargo:GetTemplates() or {}
|
||||
local factor = 1.5
|
||||
local zone = Zone
|
||||
local randomcoord = zone:GetRandomCoordinate(10,30*factor):GetVec2()
|
||||
local randomcoord = zone:GetRandomCoordinate(10,30*factor,Surfacetypes):GetVec2()
|
||||
if PreciseLocation then
|
||||
randomcoord = zone:GetCoordinate():GetVec2()
|
||||
end
|
||||
cargo:SetWasDropped(true)
|
||||
local canmove = false
|
||||
if type == CTLD_CARGO.Enum.VEHICLE then canmove = true end
|
||||
@@ -4851,6 +4962,11 @@ end
|
||||
:InitDelayOff()
|
||||
:SpawnFromVec2(randomcoord)
|
||||
end
|
||||
|
||||
if Structure then
|
||||
BASE:ScheduleOnce(0.5,PostSpawn,{self.DroppedTroops[self.TroopCounter],Structure})
|
||||
end
|
||||
|
||||
if self.eventoninject then
|
||||
self:__CratesBuild(1,nil,nil,self.DroppedTroops[self.TroopCounter])
|
||||
end
|
||||
@@ -5235,6 +5351,7 @@ end
|
||||
-- name matching a template in the table
|
||||
local match = false
|
||||
local cargo = nil
|
||||
name = string.gsub(name,"-"," ")
|
||||
for _ind,_cargo in pairs (table) do
|
||||
local thiscargo = _cargo -- #CTLD_CARGO
|
||||
local template = thiscargo:GetTemplates()
|
||||
@@ -5242,6 +5359,7 @@ end
|
||||
template = { template }
|
||||
end
|
||||
for _,_name in pairs (template) do
|
||||
_name = string.gsub(_name,"-"," ")
|
||||
if string.find(name,_name) and _cargo:GetType() ~= CTLD_CARGO.Enum.REPAIR then
|
||||
match = true
|
||||
cargo = thiscargo
|
||||
@@ -5254,18 +5372,21 @@ end
|
||||
|
||||
|
||||
--local data = "LoadedData = {\n"
|
||||
local data = "Group,x,y,z,CargoName,CargoTemplates,CargoType,CratesNeeded,CrateMass\n"
|
||||
local data = "Group,x,y,z,CargoName,CargoTemplates,CargoType,CratesNeeded,CrateMass,Structure\n"
|
||||
local n = 0
|
||||
for _,_grp in pairs(grouptable) do
|
||||
local group = _grp -- Wrapper.Group#GROUP
|
||||
if group and group:IsAlive() then
|
||||
-- get template name
|
||||
local name = group:GetName()
|
||||
local template = string.gsub(name,"-(.+)$","")
|
||||
local template = name
|
||||
|
||||
if string.find(template,"#") then
|
||||
template = string.gsub(name,"#(%d+)$","")
|
||||
end
|
||||
|
||||
local template = string.gsub(name,"-(%d+)$","")
|
||||
|
||||
local match, cargo = FindCargoType(template,cgotable)
|
||||
if not match then
|
||||
match, cargo = FindCargoType(template,cgovehic)
|
||||
@@ -5278,6 +5399,11 @@ end
|
||||
local cgotype = cargo.CargoType
|
||||
local cgoneed = cargo.CratesNeeded
|
||||
local cgomass = cargo.PerCrateMass
|
||||
local structure = UTILS.GetCountPerTypeName(group)
|
||||
local strucdata = ""
|
||||
for typen,anzahl in pairs (structure) do
|
||||
strucdata = strucdata .. typen .. "=="..anzahl..";"
|
||||
end
|
||||
|
||||
if type(cgotemp) == "table" then
|
||||
local templates = "{"
|
||||
@@ -5289,8 +5415,8 @@ end
|
||||
end
|
||||
|
||||
local location = group:GetVec3()
|
||||
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d\n"
|
||||
,template,location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass)
|
||||
local txt = string.format("%s,%d,%d,%d,%s,%s,%s,%d,%d,%s\n"
|
||||
,template,location.x,location.y,location.z,cgoname,cgotemp,cgotype,cgoneed,cgomass,strucdata)
|
||||
data = data .. txt
|
||||
end
|
||||
end
|
||||
@@ -5445,7 +5571,7 @@ end
|
||||
|
||||
for _id,_entry in pairs (loadeddata) do
|
||||
local dataset = UTILS.Split(_entry,",")
|
||||
-- 1=Group,2=x,3=y,4=z,5=CargoName,6=CargoTemplates,7=CargoType,8=CratesNeeded,9=CrateMass,10=SubCategory
|
||||
-- 1=Group,2=x,3=y,4=z,5=CargoName,6=CargoTemplates,7=CargoType,8=CratesNeeded,9=CrateMass,10=Structure
|
||||
local groupname = dataset[1]
|
||||
local vec2 = {}
|
||||
vec2.x = tonumber(dataset[2])
|
||||
@@ -5459,14 +5585,19 @@ end
|
||||
cargotemplates = UTILS.Split(cargotemplates,";")
|
||||
local size = tonumber(dataset[8])
|
||||
local mass = tonumber(dataset[9])
|
||||
local structure = nil
|
||||
if dataset[10] then
|
||||
structure = dataset[10]
|
||||
structure = string.gsub(structure,",","")
|
||||
end
|
||||
-- inject at Vec2
|
||||
local dropzone = ZONE_RADIUS:New("DropZone",vec2,20)
|
||||
if cargotype == CTLD_CARGO.Enum.VEHICLE or cargotype == CTLD_CARGO.Enum.FOB then
|
||||
local injectvehicle = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
|
||||
self:InjectVehicles(dropzone,injectvehicle)
|
||||
self:InjectVehicles(dropzone,injectvehicle,self.surfacetypes,self.useprecisecoordloads,structure)
|
||||
elseif cargotype == CTLD_CARGO.Enum.TROOPS or cargotype == CTLD_CARGO.Enum.ENGINEERS then
|
||||
local injecttroops = CTLD_CARGO:New(nil,cargoname,cargotemplates,cargotype,true,true,size,nil,true,mass)
|
||||
self:InjectTroops(dropzone,injecttroops,self.surfacetypes)
|
||||
self:InjectTroops(dropzone,injecttroops,self.surfacetypes,self.useprecisecoordloads,structure)
|
||||
end
|
||||
elseif (type(groupname) == "string" and groupname == "STATIC") or cargotype == CTLD_CARGO.Enum.REPAIR then
|
||||
local cargotemplates = dataset[6]
|
||||
|
||||
@@ -805,7 +805,9 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Get coordinate of unit.
|
||||
local coord=unit:GetCoordinate()
|
||||
--local coord=unit:GetCoordinate()
|
||||
local Vec3 = EventData.IniDCSUnit:getPoint() -- Vec3
|
||||
local coord = COORDINATE:NewFromVec3(Vec3)
|
||||
|
||||
if coord and self.rescuezone:IsCoordinateInZone(coord) then
|
||||
|
||||
|
||||
@@ -49,17 +49,19 @@ SOCKET = {
|
||||
-- @field #string BOMBRESULT Range bombing.
|
||||
-- @field #string STRAFERESULT Range strafeing result.
|
||||
-- @field #string LSOGRADE Airboss LSO grade.
|
||||
-- @field #string TTS Text-To-Speech.
|
||||
SOCKET.DataType={
|
||||
TEXT="moose_text",
|
||||
BOMBRESULT="moose_bomb_result",
|
||||
STRAFERESULT="moose_strafe_result",
|
||||
LSOGRADE="moose_lso_grade",
|
||||
TTS="moose_text2speech"
|
||||
}
|
||||
|
||||
|
||||
--- SOCKET class version.
|
||||
-- @field #string version
|
||||
SOCKET.version="0.2.0"
|
||||
SOCKET.version="0.3.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -140,7 +142,7 @@ end
|
||||
|
||||
--- Send a text message.
|
||||
-- @param #SOCKET self
|
||||
-- @param #string Text Test message.
|
||||
-- @param #string Text Text message.
|
||||
-- @return #SOCKET self
|
||||
function SOCKET:SendText(Text)
|
||||
|
||||
@@ -154,4 +156,32 @@ function SOCKET:SendText(Text)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a text-to-speech message.
|
||||
-- @param #SOCKET self
|
||||
-- @param #string Text The text message to speek.
|
||||
-- @param #number Provider The TTS provider: 0=Microsoft (default), 1=Google.
|
||||
-- @param #string Voice The specific voice to use, e.g. `"Microsoft David Desktop"` or "`en-US-Standard-A`". If not set, the service will choose a voice based on the other parameters such as culture and gender.
|
||||
-- @param #string Culture The Culture or language code, *e.g.* `"en-US"`.
|
||||
-- @param #string Gender The Gender, *i.e.* "male", "female". Default "female".
|
||||
-- @param #number Volume The volume. Microsoft: [0,100] default 50, Google: [-96, 10] default 0.
|
||||
-- @return #SOCKET self
|
||||
function SOCKET:SendTextToSpeech(Text, Provider, Voice, Culture, Gender, Volume)
|
||||
|
||||
Text=Text or "Hello World!"
|
||||
|
||||
local message={}
|
||||
|
||||
message.command = SOCKET.DataType.TTS
|
||||
message.text = Text
|
||||
message.provider=Provider
|
||||
message.voice = Voice
|
||||
message.culture = Culture
|
||||
message.gender = Gender
|
||||
message.volume = Volume
|
||||
|
||||
self:SendTable(message)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -385,6 +385,23 @@ UTILS.BasicSerialize = function(s)
|
||||
end
|
||||
end
|
||||
|
||||
function UTILS.PrintTableToLog(table, indent)
|
||||
if not table then
|
||||
BASE:E("No table passed!")
|
||||
return
|
||||
end
|
||||
if not indent then indent = 0 end
|
||||
for k, v in pairs(table) do
|
||||
if type(v) == "table" then
|
||||
BASE:I(string.rep(" ", indent) .. tostring(k) .. " = {")
|
||||
UTILS.PrintTableToLog(v, indent + 1)
|
||||
BASE:I(string.rep(" ", indent) .. "}")
|
||||
else
|
||||
BASE:I(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(v))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
UTILS.ToDegree = function(angle)
|
||||
return angle*180/math.pi
|
||||
|
||||
@@ -198,8 +198,47 @@ AIRBASE.Nevada = {
|
||||
-- * AIRBASE.Normandy.Needs_Oar_Point
|
||||
-- * AIRBASE.Normandy.Funtington
|
||||
-- * AIRBASE.Normandy.Tangmere
|
||||
-- * AIRBASE.Normandy.Ford_AF
|
||||
--
|
||||
-- * AIRBASE.Normandy.Ford
|
||||
-- * AIRBASE.Normandy.Argentan
|
||||
-- * AIRBASE.Normandy.Goulet
|
||||
-- * AIRBASE.Normandy.Barville
|
||||
-- * AIRBASE.Normandy.Essay
|
||||
-- * AIRBASE.Normandy.Hauterive
|
||||
-- * AIRBASE.Normandy.Lymington
|
||||
-- * AIRBASE.Normandy.Vrigny
|
||||
-- * AIRBASE.Normandy.Odiham
|
||||
-- * AIRBASE.Normandy.Conches
|
||||
-- * AIRBASE.Normandy.West_Malling
|
||||
-- * AIRBASE.Normandy.Villacoublay
|
||||
-- * AIRBASE.Normandy.Kenley
|
||||
-- * AIRBASE.Normandy.Beauvais_Tille
|
||||
-- * AIRBASE.Normandy.Cormeilles_en_Vexin
|
||||
-- * AIRBASE.Normandy.Creil
|
||||
-- * AIRBASE.Normandy.Guyancourt
|
||||
-- * AIRBASE.Normandy.Lonrai
|
||||
-- * AIRBASE.Normandy.Dinan_Trelivan
|
||||
-- * AIRBASE.Normandy.Heathrow
|
||||
-- * AIRBASE.Normandy.Fecamp_Benouville
|
||||
-- * AIRBASE.Normandy.Farnborough
|
||||
-- * AIRBASE.Normandy.Friston
|
||||
-- * AIRBASE.Normandy.Deanland
|
||||
-- * AIRBASE.Normandy.Triqueville
|
||||
-- * AIRBASE.Normandy.Poix
|
||||
-- * AIRBASE.Normandy.Orly
|
||||
-- * AIRBASE.Normandy.Stoney_Cross
|
||||
-- * AIRBASE.Normandy.Amiens_Glisy
|
||||
-- * AIRBASE.Normandy.Ronai
|
||||
-- * AIRBASE.Normandy.Rouen_Boos
|
||||
-- * AIRBASE.Normandy.Deauville
|
||||
-- * AIRBASE.Normandy.Saint_Aubin
|
||||
-- * AIRBASE.Normandy.Flers
|
||||
-- * AIRBASE.Normandy.Avranches_Le_Val_Saint_Pere
|
||||
-- * AIRBASE.Normandy.Gravesend
|
||||
-- * AIRBASE.Normandy.Beaumont_le_Roger
|
||||
-- * AIRBASE.Normandy.Broglie
|
||||
-- * AIRBASE.Normandy.Bernay_Saint_Martin
|
||||
-- * AIRBASE.Normandy.Saint_Andre_de_lEure
|
||||
--
|
||||
-- @field Normandy
|
||||
AIRBASE.Normandy = {
|
||||
["Saint_Pierre_du_Mont"] = "Saint Pierre du Mont",
|
||||
@@ -232,14 +271,46 @@ AIRBASE.Normandy = {
|
||||
["Needs_Oar_Point"] = "Needs Oar Point",
|
||||
["Funtington"] = "Funtington",
|
||||
["Tangmere"] = "Tangmere",
|
||||
["Ford_AF"] = "Ford_AF",
|
||||
["Goulet"] = "Goulet",
|
||||
["Ford"] = "Ford",
|
||||
["Argentan"] = "Argentan",
|
||||
["Vrigny"] = "Vrigny",
|
||||
["Goulet"] = "Goulet",
|
||||
["Barville"] = "Barville",
|
||||
["Essay"] = "Essay",
|
||||
["Hauterive"] = "Hauterive",
|
||||
["Barville"] = "Barville",
|
||||
["Lymington"] = "Lymington",
|
||||
["Vrigny"] = "Vrigny",
|
||||
["Odiham"] = "Odiham",
|
||||
["Conches"] = "Conches",
|
||||
["West_Malling"] = "West Malling",
|
||||
["Villacoublay"] = "Villacoublay",
|
||||
["Kenley"] = "Kenley",
|
||||
["Beauvais_Tille"] = "Beauvais-Tille",
|
||||
["Cormeilles_en_Vexin"] = "Cormeilles-en-Vexin",
|
||||
["Creil"] = "Creil",
|
||||
["Guyancourt"] = "Guyancourt",
|
||||
["Lonrai"] = "Lonrai",
|
||||
["Dinan_Trelivan"] = "Dinan-Trelivan",
|
||||
["Heathrow"] = "Heathrow",
|
||||
["Fecamp_Benouville"] = "Fecamp-Benouville",
|
||||
["Farnborough"] = "Farnborough",
|
||||
["Friston"] = "Friston",
|
||||
["Deanland "] = "Deanland ",
|
||||
["Triqueville"] = "Triqueville",
|
||||
["Poix"] = "Poix",
|
||||
["Orly"] = "Orly",
|
||||
["Stoney_Cross"] = "Stoney Cross",
|
||||
["Amiens_Glisy"] = "Amiens-Glisy",
|
||||
["Ronai"] = "Ronai",
|
||||
["Rouen_Boos"] = "Rouen-Boos",
|
||||
["Deauville"] = "Deauville",
|
||||
["Saint_Aubin"] = "Saint-Aubin",
|
||||
["Flers"] = "Flers",
|
||||
["Avranches_Le_Val_Saint_Pere"] = "Avranches Le Val-Saint-Pere",
|
||||
["Gravesend"] = "Gravesend",
|
||||
["Beaumont_le_Roger"] = "Beaumont-le-Roger",
|
||||
["Broglie"] = "Broglie",
|
||||
["Bernay_Saint_Martin"] = "Bernay Saint Martin",
|
||||
["Saint_Andre_de_lEure"] = "Saint-Andre-de-lEure",
|
||||
}
|
||||
|
||||
--- Airbases of the Persion Gulf Map:
|
||||
|
||||
@@ -690,7 +690,8 @@ function CONTROLLABLE:CommandActivateACLS( UnitID, Name, Delay )
|
||||
if Delay and Delay > 0 then
|
||||
SCHEDULER:New( nil, self.CommandActivateACLS, { self, UnitID, Name }, Delay )
|
||||
else
|
||||
self:SetCommand( CommandActivateACLS )
|
||||
local controller = self:_GetController()
|
||||
controller:setCommand( CommandActivateACLS )
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -711,7 +712,8 @@ function CONTROLLABLE:CommandDeactivateACLS( Delay )
|
||||
if Delay and Delay > 0 then
|
||||
SCHEDULER:New( nil, self.CommandDeactivateACLS, { self }, Delay )
|
||||
else
|
||||
self:SetCommand( CommandDeactivateACLS )
|
||||
local controller = self:_GetController()
|
||||
controller:setCommand( CommandDeactivateACLS )
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -761,7 +763,7 @@ function CONTROLLABLE:CommandActivateLink4(Frequency, UnitID, Callsign, Delay)
|
||||
local CommandActivateLink4= {
|
||||
id = "ActivateLink4",
|
||||
params= {
|
||||
["frequency "] = freq*1000000,
|
||||
["frequency"] = freq*1000000,
|
||||
["unitId"] = UnitID or self:GetID(),
|
||||
["name"] = Callsign or "LNK",
|
||||
}
|
||||
@@ -772,7 +774,8 @@ function CONTROLLABLE:CommandActivateLink4(Frequency, UnitID, Callsign, Delay)
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandActivateLink4, {self, Frequency, UnitID, Callsign}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandActivateLink4)
|
||||
local controller = self:_GetController()
|
||||
controller:setCommand(CommandActivateLink4)
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -810,7 +813,8 @@ function CONTROLLABLE:CommandDeactivateLink4(Delay)
|
||||
if Delay and Delay>0 then
|
||||
SCHEDULER:New(nil, self.CommandDeactivateLink4, {self}, Delay)
|
||||
else
|
||||
self:SetCommand(CommandDeactivateLink4)
|
||||
local controller = self:_GetController()
|
||||
controller:setCommand(CommandDeactivateLink4)
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -1692,7 +1696,9 @@ function CONTROLLABLE:EnRouteTaskSEAD(TargetTypes, Priority)
|
||||
return DCSTask
|
||||
end
|
||||
|
||||
--- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; it just allows the unit/controllable to engage the target controllable as well as other assigned targets.
|
||||
--- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now;
|
||||
-- it just allows the unit/controllable to engage the target controllable as well as other assigned targets.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_engageGroup).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #CONTROLLABLE AttackGroup The Controllable to be attacked.
|
||||
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
|
||||
@@ -1741,6 +1747,7 @@ function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType,
|
||||
end
|
||||
|
||||
--- (AIR) Search and attack the Unit.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_engageUnit).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param Wrapper.Unit#UNIT EngageUnit The UNIT.
|
||||
-- @param #number Priority (optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
|
||||
@@ -1776,6 +1783,7 @@ function CONTROLLABLE:EnRouteTaskEngageUnit( EngageUnit, Priority, GroupAttack,
|
||||
end
|
||||
|
||||
--- (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters.
|
||||
-- [hoggit](https://wiki.hoggitworld.com/view/DCS_task_awacs).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:EnRouteTaskAWACS()
|
||||
@@ -1789,6 +1797,7 @@ function CONTROLLABLE:EnRouteTaskAWACS()
|
||||
end
|
||||
|
||||
--- (AIR) Aircraft will act as a tanker for friendly units. No parameters.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_tanker).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:EnRouteTaskTanker()
|
||||
@@ -1804,6 +1813,7 @@ end
|
||||
-- En-route tasks for ground units/controllables
|
||||
|
||||
--- (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts). No parameters.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_ewr).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:EnRouteTaskEWR()
|
||||
@@ -1821,14 +1831,17 @@ end
|
||||
--- (AIR + GROUND) The task makes the controllable/unit a FAC and lets the FAC to choose the target (enemy ground controllable) as well as other assigned targets.
|
||||
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
|
||||
-- If the task is assigned to the controllable lead unit will be a FAC.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_fac_engageGroup).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param #CONTROLLABLE AttackGroup Target CONTROLLABLE.
|
||||
-- @param #number Priority (Optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default is 0.
|
||||
-- @param #number WeaponType (Optional) Bitmask of weapon types those allowed to use. Default is "Auto".
|
||||
-- @param DCS#AI.Task.Designation Designation (Optional) Designation type.
|
||||
-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.
|
||||
-- @param #number CallsignID CallsignID, e.g. `CALLSIGN.JTAC.Anvil` for ground or `CALLSIGN.Aircraft.Ford` for air.
|
||||
-- @param #number CallsignNumber Callsign first number, e.g. 2 for `Ford-2`.
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink )
|
||||
function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink, Frequency, Modulation, CallsignID, CallsignNumber )
|
||||
|
||||
local DCSTask = {
|
||||
id = 'FAC_EngageControllable',
|
||||
@@ -1837,6 +1850,10 @@ function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponT
|
||||
weaponType = WeaponType or "Auto",
|
||||
designation = Designation,
|
||||
datalink = Datalink and Datalink or false,
|
||||
frequency = (Frequency or 133)*1000000,
|
||||
modulation = Modulation or radio.modulation.AM,
|
||||
callname = CallsignID,
|
||||
number = CallsignNumber,
|
||||
priority = Priority or 0,
|
||||
},
|
||||
}
|
||||
@@ -1845,27 +1862,26 @@ function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponT
|
||||
end
|
||||
|
||||
--- (AIR + GROUND) The task makes the controllable/unit a FAC and lets the FAC to choose a targets (enemy ground controllable) around as well as other assigned targets.
|
||||
-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC.
|
||||
-- If the task is assigned to the controllable lead unit will be a FAC.
|
||||
-- Assigns the controlled group to act as a Forward Air Controller or JTAC. Any detected targets will be assigned as targets to the player via the JTAC radio menu.
|
||||
-- Target designation is set to auto and is dependent on the circumstances.
|
||||
-- See [hoggit](https://wiki.hoggitworld.com/view/DCS_task_fac).
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @param DCS#Distance Radius The maximal distance from the FAC to a target.
|
||||
-- @param #number Frequency Frequency in MHz. Default 133 MHz.
|
||||
-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`.
|
||||
-- @param #number CallsignID CallsignID, e.g. `CALLSIGN.JTAC.Anvil` for ground or `CALLSIGN.Aircraft.Ford` for air.
|
||||
-- @param #number CallsignNumber Callsign first number, e.g. 2 for `Ford-2`.
|
||||
-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:EnRouteTaskFAC( Radius, Priority )
|
||||
|
||||
-- FAC = {
|
||||
-- id = 'FAC',
|
||||
-- params = {
|
||||
-- radius = Distance,
|
||||
-- priority = number
|
||||
-- }
|
||||
-- }
|
||||
function CONTROLLABLE:EnRouteTaskFAC( Frequency, Modulation, CallsignID, CallsignNumber, Priority )
|
||||
|
||||
local DCSTask = {
|
||||
id = 'FAC',
|
||||
params = {
|
||||
radius = Radius,
|
||||
priority = Priority
|
||||
frequency = (Frequency or 133)*1000000,
|
||||
modulation = Modulation or radio.modulation.AM,
|
||||
callname = CallsignID,
|
||||
number = CallsignNumber,
|
||||
priority = Priority or 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **applevangelist**
|
||||
-- # Last Update Feb 2023
|
||||
-- ### Author: **Applevangelist**
|
||||
-- # Last Update Apr 2023
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -42,7 +42,7 @@ do
|
||||
-- @field #NET
|
||||
NET = {
|
||||
ClassName = "NET",
|
||||
Version = "0.1.0",
|
||||
Version = "0.1.1",
|
||||
BlockTime = 600,
|
||||
BlockedPilots = {},
|
||||
BlockedUCIDs = {},
|
||||
@@ -196,7 +196,7 @@ function NET:_EventHandler(EventData)
|
||||
|
||||
-- Get Player Data
|
||||
local name = data.IniPlayerName and data.IniPlayerName or data.IniUnit:GetPlayerName()
|
||||
local ucid = self:GetPlayerUCID(nil,name)
|
||||
local ucid = self:GetPlayerUCID(nil,name) or "none"
|
||||
local PlayerID = self:GetPlayerIDByName(name) or "none"
|
||||
local PlayerSide, PlayerSlot = self:GetSlot(data.IniUnit)
|
||||
local TNow = timer.getTime()
|
||||
@@ -771,7 +771,7 @@ end
|
||||
-- @param #string To
|
||||
-- @return #NET self
|
||||
function NET:onafterStatus(From,Event,To)
|
||||
self:T({From,Event,To})
|
||||
self:I({From,Event,To})
|
||||
|
||||
local function HouseHold(tavolo)
|
||||
local TNow = timer.getTime()
|
||||
@@ -799,7 +799,7 @@ end
|
||||
-- @param #string To
|
||||
-- @return #NET self
|
||||
function NET:onafterRun(From,Event,To)
|
||||
self:T({From,Event,To})
|
||||
self:I({From,Event,To})
|
||||
self:HandleEvent(EVENTS.PlayerEnterUnit,self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit,self._EventHandler)
|
||||
|
||||
@@ -394,6 +394,35 @@ function POSITIONABLE:GetCoordinate()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Triggers an explosion at the coordinates of the positionable.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param #number power Power of the explosion in kg TNT. Default 100 kg TNT.
|
||||
-- @param #number delay (Optional) Delay of explosion in seconds.
|
||||
-- @return #POSITIONABLE self
|
||||
function POSITIONABLE:Explode(power, delay)
|
||||
|
||||
-- Default.
|
||||
power=power or 100
|
||||
|
||||
-- Check if delay or not.
|
||||
if delay and delay>0 then
|
||||
-- Delayed call.
|
||||
self:ScheduleOnce(delay, POSITIONABLE.Explode, self, power, 0)
|
||||
else
|
||||
|
||||
local coord=self:GetCoord()
|
||||
|
||||
if coord then
|
||||
-- Create an explotion at the coordinate of the positionable.
|
||||
coord:Explosion(power)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m.
|
||||
|
||||
@@ -63,12 +63,18 @@ function SCENERY:GetDCSObject()
|
||||
end
|
||||
|
||||
--- Get current life points from the SCENERY Object.
|
||||
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the life0 value to 120%
|
||||
-- of the last life value if life exceeds life0 (initial life) at any point. Thus will will get a smooth percentage decrease, if you use this e.g. as success
|
||||
-- criteria for a bombing task.
|
||||
--@param #SCENERY self
|
||||
--@return #number life
|
||||
function SCENERY:GetLife()
|
||||
local life = 0
|
||||
if self.SceneryObject then
|
||||
life = self.SceneryObject:getLife()
|
||||
if life > self.Life0 then
|
||||
self.Life0 = math.floor(life * 1.2)
|
||||
end
|
||||
end
|
||||
return life
|
||||
end
|
||||
@@ -110,11 +116,13 @@ end
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius)
|
||||
|
||||
|
||||
local radius = Radius or 100
|
||||
local name = Name or "unknown"
|
||||
local scenery = nil
|
||||
|
||||
BASE:T({name, radius, Coordinate:GetVec2()})
|
||||
|
||||
---
|
||||
-- @param Core.Point#COORDINATE coordinate
|
||||
-- @param #number radius
|
||||
@@ -170,6 +178,7 @@ function SCENERY:FindByZoneName( ZoneName )
|
||||
zone = ZONE:FindByName(ZoneName)
|
||||
end
|
||||
local _id = zone:GetProperty('OBJECT ID')
|
||||
BASE:T("Object ID ".._id)
|
||||
if not _id then
|
||||
-- this zone has no object ID
|
||||
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
|
||||
@@ -235,4 +244,4 @@ end
|
||||
--@return #SCENERY self
|
||||
function SCENERY:Destroy()
|
||||
return self
|
||||
end
|
||||
end
|
||||
|
||||
@@ -804,7 +804,7 @@ function WEAPON:_TrackWeapon(time)
|
||||
|
||||
-- Return next time the function is called or nil to stop the scheduler.
|
||||
if self.tracking then
|
||||
if self.dtTrack and self.dtTrack>0.001 then
|
||||
if self.dtTrack and self.dtTrack>=0.00001 then
|
||||
return time+self.dtTrack
|
||||
else
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user