mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
commit
24559c475b
@ -9,7 +9,7 @@
|
|||||||
-- * Create polygon zones.
|
-- * Create polygon zones.
|
||||||
-- * Create moving zones around a unit.
|
-- * Create moving zones around a unit.
|
||||||
-- * Create moving zones around a group.
|
-- * Create moving zones around a group.
|
||||||
-- * Provide the zone behaviour. Some zones are static, while others are moveable.
|
-- * Provide the zone behavior. Some zones are static, while others are moveable.
|
||||||
-- * Enquiry if a coordinate is within a zone.
|
-- * Enquiry if a coordinate is within a zone.
|
||||||
-- * Smoke zones.
|
-- * Smoke zones.
|
||||||
-- * Set a zone probability to control zone selection.
|
-- * Set a zone probability to control zone selection.
|
||||||
@ -20,10 +20,10 @@
|
|||||||
-- * Draw zones (circular and polygon) on the F10 map.
|
-- * Draw zones (circular and polygon) on the F10 map.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- There are essentially two core functions that zones accomodate:
|
-- There are essentially two core functions that zones accommodate:
|
||||||
--
|
--
|
||||||
-- * Test if an object is within the zone boundaries.
|
-- * Test if an object is within the zone boundaries.
|
||||||
-- * Provide the zone behaviour. Some zones are static, while others are moveable.
|
-- * Provide the zone behavior. Some zones are static, while others are moveable.
|
||||||
--
|
--
|
||||||
-- The object classes are using the zone classes to test the zone boundaries, which can take various forms:
|
-- The object classes are using the zone classes to test the zone boundaries, which can take various forms:
|
||||||
--
|
--
|
||||||
@ -1219,7 +1219,7 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
|
|||||||
while gotit==false and N<=Nmax do
|
while gotit==false and N<=Nmax do
|
||||||
gotit=_checkSurface(point)
|
gotit=_checkSurface(point)
|
||||||
if gotit then
|
if gotit then
|
||||||
env.info(string.format("Got random coordinate with surface type %d after N=%d/%d iterations", land.getSurfaceType(point), N, Nmax))
|
--env.info(string.format("Got random coordinate with surface type %d after N=%d/%d iterations", land.getSurfaceType(point), N, Nmax))
|
||||||
else
|
else
|
||||||
point=_getpoint()
|
point=_getpoint()
|
||||||
N=N+1
|
N=N+1
|
||||||
@ -2126,12 +2126,12 @@ end
|
|||||||
--
|
--
|
||||||
-- ## Declare a ZONE_POLYGON directly in the DCS mission editor!
|
-- ## Declare a ZONE_POLYGON directly in the DCS mission editor!
|
||||||
--
|
--
|
||||||
-- You can declare a ZONE_POLYGON using the DCS mission editor by adding the ~ZONE_POLYGON tag in the group name.
|
-- You can declare a ZONE_POLYGON using the DCS mission editor by adding the #ZONE_POLYGON tag in the group name.
|
||||||
--
|
--
|
||||||
-- So, imagine you have a group declared in the mission editor, with group name `DefenseZone~ZONE_POLYGON`.
|
-- So, imagine you have a group declared in the mission editor, with group name `DefenseZone#ZONE_POLYGON`.
|
||||||
-- Then during mission startup, when loading Moose.lua, this group will be detected as a ZONE_POLYGON declaration.
|
-- Then during mission startup, when loading Moose.lua, this group will be detected as a ZONE_POLYGON declaration.
|
||||||
-- Within the background, a ZONE_POLYGON object will be created within the @{Core.Database} using the properties of the group.
|
-- Within the background, a ZONE_POLYGON object will be created within the @{Core.Database} using the properties of the group.
|
||||||
-- The ZONE_POLYGON name will be the group name without the ~ZONE_POLYGON tag.
|
-- The ZONE_POLYGON name will be the group name without the #ZONE_POLYGON tag.
|
||||||
--
|
--
|
||||||
-- So, you can search yourself for the ZONE_POLYGON by using the @{#ZONE_POLYGON.FindByName}() method.
|
-- So, you can search yourself for the ZONE_POLYGON by using the @{#ZONE_POLYGON.FindByName}() method.
|
||||||
-- In this example, `local PolygonZone = ZONE_POLYGON:FindByName( "DefenseZone" )` would return the ZONE_POLYGON object
|
-- In this example, `local PolygonZone = ZONE_POLYGON:FindByName( "DefenseZone" )` would return the ZONE_POLYGON object
|
||||||
|
|||||||
@ -674,6 +674,7 @@ end
|
|||||||
function AUTOLASE:CanLase(Recce,Unit)
|
function AUTOLASE:CanLase(Recce,Unit)
|
||||||
local canlase = false
|
local canlase = false
|
||||||
-- cooldown?
|
-- cooldown?
|
||||||
|
if Recce and Recce:IsAlive() == true then
|
||||||
local name = Recce:GetName()
|
local name = Recce:GetName()
|
||||||
local cooldown = self.RecceUnits[name].cooldown and self.forcecooldown
|
local cooldown = self.RecceUnits[name].cooldown and self.forcecooldown
|
||||||
if cooldown then
|
if cooldown then
|
||||||
@ -694,6 +695,7 @@ function AUTOLASE:CanLase(Recce,Unit)
|
|||||||
if distance <= lasedistance and islos then
|
if distance <= lasedistance and islos then
|
||||||
canlase = true
|
canlase = true
|
||||||
end
|
end
|
||||||
|
end
|
||||||
return canlase
|
return canlase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -98,6 +98,7 @@
|
|||||||
-- * Patriot
|
-- * Patriot
|
||||||
-- * Rapier
|
-- * Rapier
|
||||||
-- * Roland
|
-- * Roland
|
||||||
|
-- * Silkworm (though strictly speaking this is a surface to ship missile)
|
||||||
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
|
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
|
||||||
-- * and from HDS (see note below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
|
-- * and from HDS (see note below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
|
||||||
--
|
--
|
||||||
@ -356,6 +357,7 @@ MANTIS.SamData = {
|
|||||||
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
||||||
["Chaparrel"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
["Chaparrel"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
||||||
|
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
||||||
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" },
|
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" },
|
||||||
|
|||||||
@ -1704,7 +1704,7 @@ function SCORING:ReportScoreGroupDetailed( PlayerGroup )
|
|||||||
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
|
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
|
||||||
|
|
||||||
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
||||||
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + ScoreGoals + PenaltyMissions
|
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
|
||||||
|
|
||||||
PlayerMessage =
|
PlayerMessage =
|
||||||
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )%s%s%s%s%s",
|
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )%s%s%s%s%s",
|
||||||
@ -1760,7 +1760,7 @@ function SCORING:ReportScoreAllSummary( PlayerGroup )
|
|||||||
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
|
self:F( { ReportMissions, ScoreMissions, PenaltyMissions } )
|
||||||
|
|
||||||
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
local PlayerScore = ScoreHits + ScoreDestroys + ScoreCoalitionChanges + ScoreGoals + ScoreMissions
|
||||||
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + ScoreGoals + PenaltyMissions
|
local PlayerPenalty = PenaltyHits + PenaltyDestroys + PenaltyCoalitionChanges + PenaltyGoals + PenaltyMissions
|
||||||
|
|
||||||
PlayerMessage =
|
PlayerMessage =
|
||||||
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )",
|
string.format( "Player '%s' Score = %d ( %d Score, -%d Penalties )",
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**, **applevangelist**
|
-- ### Authors: **FlightControl**, **applevangelist**
|
||||||
--
|
--
|
||||||
-- Last Update: Nov 2021
|
-- Last Update: Feb 2022
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -33,7 +33,7 @@
|
|||||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||||
--
|
--
|
||||||
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
|
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
|
||||||
-- Once a HARM attack is detected, SEADwill shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
-- Once a HARM attack is detected, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
||||||
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the
|
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the
|
||||||
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
|
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
|
||||||
-- period of time to stay defensive, before it takes evasive actions.
|
-- period of time to stay defensive, before it takes evasive actions.
|
||||||
@ -79,6 +79,7 @@ SEAD = {
|
|||||||
["Kh25"] = "Kh25",
|
["Kh25"] = "Kh25",
|
||||||
["BGM_109"] = "BGM_109",
|
["BGM_109"] = "BGM_109",
|
||||||
["AGM_154"] = "AGM_154",
|
["AGM_154"] = "AGM_154",
|
||||||
|
["HY-2"] = "HY-2",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Missile enumerators - from DCS ME and Wikipedia
|
--- Missile enumerators - from DCS ME and Wikipedia
|
||||||
@ -98,6 +99,7 @@ SEAD = {
|
|||||||
["Kh25"] = {25, 0.8},
|
["Kh25"] = {25, 0.8},
|
||||||
["BGM_109"] = {460, 0.705}, --in-game ~465kn
|
["BGM_109"] = {460, 0.705}, --in-game ~465kn
|
||||||
["AGM_154"] = {130, 0.61},
|
["AGM_154"] = {130, 0.61},
|
||||||
|
["HY-2"] = {90,1},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
||||||
@ -141,7 +143,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
|||||||
self:AddTransition("*", "ManageEvasion", "*")
|
self:AddTransition("*", "ManageEvasion", "*")
|
||||||
self:AddTransition("*", "CalculateHitZone", "*")
|
self:AddTransition("*", "CalculateHitZone", "*")
|
||||||
|
|
||||||
self:I("*** SEAD - Started Version 0.4.2")
|
self:I("*** SEAD - Started Version 0.4.3")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -267,9 +269,10 @@ end
|
|||||||
-- @param Core.Point#COORDINATE pos0 Position of the plane when it fired
|
-- @param Core.Point#COORDINATE pos0 Position of the plane when it fired
|
||||||
-- @param #number height Height when the missile was fired
|
-- @param #number height Height when the missile was fired
|
||||||
-- @param Wrapper.Group#GROUP SEADGroup Attacker group
|
-- @param Wrapper.Group#GROUP SEADGroup Attacker group
|
||||||
|
-- @param #string SEADWeaponName Weapon Name
|
||||||
-- @return #SEAD self
|
-- @return #SEAD self
|
||||||
function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup)
|
function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADGroup,SEADWeaponName)
|
||||||
self:T("**** Calculating hit zone")
|
self:T("**** Calculating hit zone for " .. (SEADWeaponName or "None"))
|
||||||
if SEADWeapon and SEADWeapon:isExist() then
|
if SEADWeapon and SEADWeapon:isExist() then
|
||||||
--local pos = SEADWeapon:getPoint()
|
--local pos = SEADWeapon:getPoint()
|
||||||
|
|
||||||
@ -285,6 +288,9 @@ function SEAD:onafterCalculateHitZone(From,Event,To,SEADWeapon,pos0,height,SEADG
|
|||||||
|
|
||||||
-- velocity
|
-- velocity
|
||||||
local wpndata = SEAD.HarmData["AGM_88"]
|
local wpndata = SEAD.HarmData["AGM_88"]
|
||||||
|
if string.find(SEADWeaponName,"154",1) then
|
||||||
|
wpndata = SEAD.HarmData["AGM_154"]
|
||||||
|
end
|
||||||
local mveloc = math.floor(wpndata[2] * 340.29)
|
local mveloc = math.floor(wpndata[2] * 340.29)
|
||||||
local c1 = (2*mheight*9.81)/(mveloc^2)
|
local c1 = (2*mheight*9.81)/(mveloc^2)
|
||||||
local c2 = (mveloc^2) / 9.81
|
local c2 = (mveloc^2) / 9.81
|
||||||
@ -459,14 +465,15 @@ function SEAD:HandleEventShot( EventData )
|
|||||||
local _targetskill = "Random"
|
local _targetskill = "Random"
|
||||||
local _targetgroupname = "none"
|
local _targetgroupname = "none"
|
||||||
local _target = EventData.Weapon:getTarget() -- Identify target
|
local _target = EventData.Weapon:getTarget() -- Identify target
|
||||||
if not _target or self.debug then -- AGM-88 w/o target data
|
if not _target or self.debug then -- AGM-88 or 154 w/o target data
|
||||||
if string.find(SEADWeaponName,"AGM_88",1,true) then
|
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
|
||||||
self:I("**** Tracking AGM-88 with no target data.")
|
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
|
||||||
|
self:I("**** Tracking AGM-88/154 with no target data.")
|
||||||
local pos0 = SEADPlane:GetCoordinate()
|
local pos0 = SEADPlane:GetCoordinate()
|
||||||
local fheight = SEADPlane:GetHeight()
|
local fheight = SEADPlane:GetHeight()
|
||||||
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup)
|
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
local targetcat = _target:getCategory() -- Identify category
|
local targetcat = _target:getCategory() -- Identify category
|
||||||
local _targetUnit = nil -- Wrapper.Unit#UNIT
|
local _targetUnit = nil -- Wrapper.Unit#UNIT
|
||||||
|
|||||||
@ -4107,6 +4107,7 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
|
|||||||
local cargobay={}
|
local cargobay={}
|
||||||
local cargobaytot=0
|
local cargobaytot=0
|
||||||
local cargobaymax=0
|
local cargobaymax=0
|
||||||
|
local weights={}
|
||||||
for _i,_unit in pairs(group:GetUnits()) do
|
for _i,_unit in pairs(group:GetUnits()) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
local Desc=unit:GetDesc()
|
local Desc=unit:GetDesc()
|
||||||
@ -4115,6 +4116,7 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
|
|||||||
local unitweight=forceweight or Desc.massEmpty
|
local unitweight=forceweight or Desc.massEmpty
|
||||||
if unitweight then
|
if unitweight then
|
||||||
weight=weight+unitweight
|
weight=weight+unitweight
|
||||||
|
weights[_i]=unitweight
|
||||||
end
|
end
|
||||||
|
|
||||||
local cargomax=0
|
local cargomax=0
|
||||||
@ -4165,6 +4167,7 @@ function WAREHOUSE:_RegisterAsset(group, ngroups, forceattribute, forcecargobay,
|
|||||||
asset.speedmax=SpeedMax
|
asset.speedmax=SpeedMax
|
||||||
asset.size=smax
|
asset.size=smax
|
||||||
asset.weight=weight
|
asset.weight=weight
|
||||||
|
asset.weights=weights
|
||||||
asset.DCSdesc=Descriptors
|
asset.DCSdesc=Descriptors
|
||||||
asset.attribute=attribute
|
asset.attribute=attribute
|
||||||
asset.cargobay=cargobay
|
asset.cargobay=cargobay
|
||||||
@ -5449,9 +5452,59 @@ end
|
|||||||
-- @param #WAREHOUSE.Assetitem asset The asset that is dead.
|
-- @param #WAREHOUSE.Assetitem asset The asset that is dead.
|
||||||
-- @param #WAREHOUSE.Pendingitem request The request of the dead asset.
|
-- @param #WAREHOUSE.Pendingitem request The request of the dead asset.
|
||||||
function WAREHOUSE:onafterAssetDead(From, Event, To, asset, request)
|
function WAREHOUSE:onafterAssetDead(From, Event, To, asset, request)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
local text=string.format("Asset %s from request id=%d is dead!", asset.templatename, request.uid)
|
local text=string.format("Asset %s from request id=%d is dead!", asset.templatename, request.uid)
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
self:_DebugMessage(text)
|
|
||||||
|
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
|
||||||
|
local groupname=asset.spawngroupname --self:_GetNameWithOut(group)
|
||||||
|
|
||||||
|
-- Dont trigger a Remove event for the group sets.
|
||||||
|
local NoTriggerEvent=true
|
||||||
|
|
||||||
|
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Easy case: Group can simply be removed from the cargogroupset.
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Remove dead group from cargo group set.
|
||||||
|
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
||||||
|
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Complicated case: Dead unit could be:
|
||||||
|
-- 1.) A Cargo unit (e.g. waiting to be picked up).
|
||||||
|
-- 2.) A Transport unit which itself holds cargo groups.
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Check if this a cargo or transport group.
|
||||||
|
local istransport=not asset.iscargo --self:_GroupIsTransport(group, request)
|
||||||
|
|
||||||
|
if istransport==true then
|
||||||
|
|
||||||
|
-- Whole carrier group is dead. Remove it from the carrier group set.
|
||||||
|
request.transportgroupset:Remove(groupname, NoTriggerEvent)
|
||||||
|
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
|
||||||
|
|
||||||
|
elseif istransport==false then
|
||||||
|
|
||||||
|
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
|
||||||
|
-- Remove dead group from cargo group set.
|
||||||
|
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
||||||
|
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
|
||||||
|
-- This as well?
|
||||||
|
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
|
||||||
|
|
||||||
|
else
|
||||||
|
--self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName()))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -6556,7 +6609,8 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:I(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s.", self.alias, tostring(EventData.IniUnitName)))
|
-- Debug info.
|
||||||
|
self:T2(self.lid..string.format("Warehouse %s captured event dead or crash or unit %s", self.alias, tostring(EventData.IniUnitName)))
|
||||||
|
|
||||||
-- Check if an asset unit was destroyed.
|
-- Check if an asset unit was destroyed.
|
||||||
if EventData.IniGroup then
|
if EventData.IniGroup then
|
||||||
@ -6571,7 +6625,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
|
|||||||
if wid==self.uid then
|
if wid==self.uid then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s.", self.alias, EventData.IniUnitName))
|
self:T(self.lid..string.format("Warehouse %s captured event dead or crash of its asset unit %s", self.alias, EventData.IniUnitName))
|
||||||
|
|
||||||
-- Loop over all pending requests and get the one belonging to this unit.
|
-- Loop over all pending requests and get the one belonging to this unit.
|
||||||
for _,request in pairs(self.pending) do
|
for _,request in pairs(self.pending) do
|
||||||
@ -6581,7 +6635,7 @@ function WAREHOUSE:_OnEventCrashOrDead(EventData)
|
|||||||
if request.uid==rid then
|
if request.uid==rid then
|
||||||
|
|
||||||
-- Update cargo and transport group sets of this request. We need to know if this job is finished.
|
-- Update cargo and transport group sets of this request. We need to know if this job is finished.
|
||||||
self:_UnitDead(EventData.IniUnit, request)
|
self:_UnitDead(EventData.IniUnit, EventData.IniGroup, request)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -6594,38 +6648,46 @@ end
|
|||||||
-- This is important in order to determine if a job is done and can be removed from the (pending) queue.
|
-- This is important in order to determine if a job is done and can be removed from the (pending) queue.
|
||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @param Wrapper.Unit#UNIT deadunit Unit that died.
|
-- @param Wrapper.Unit#UNIT deadunit Unit that died.
|
||||||
|
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
|
||||||
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
|
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
|
||||||
function WAREHOUSE:_UnitDead(deadunit, request)
|
function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
|
||||||
|
self:F(self.lid.."FF unit dead "..deadunit:GetName())
|
||||||
|
|
||||||
-- Flare unit.
|
-- Find opsgroup.
|
||||||
if self.Debug then
|
local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
|
||||||
deadunit:FlareRed()
|
|
||||||
|
-- Check if we have an opsgroup.
|
||||||
|
if opsgroup then
|
||||||
|
-- Handled in OPSGROUP:onafterDead() now.
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Group the dead unit belongs to.
|
|
||||||
local group=deadunit:GetGroup()
|
|
||||||
|
|
||||||
-- Number of alive units in group.
|
-- Number of alive units in group.
|
||||||
local nalive=group:CountAliveUnits()
|
local nalive=deadgroup:CountAliveUnits()
|
||||||
|
|
||||||
-- Whole group is dead?
|
-- Whole group is dead?
|
||||||
local groupdead=true
|
local groupdead=false
|
||||||
if nalive>0 then
|
if nalive>0 then
|
||||||
groupdead=false
|
groupdead=false
|
||||||
|
else
|
||||||
|
groupdead=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Find asset.
|
||||||
|
local asset=self:FindAssetInDB(deadgroup)
|
||||||
|
|
||||||
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
|
-- Here I need to get rid of the #CARGO at the end to obtain the original name again!
|
||||||
local unitname=self:_GetNameWithOut(deadunit)
|
local unitname=self:_GetNameWithOut(deadunit)
|
||||||
local groupname=self:_GetNameWithOut(group)
|
local groupname=self:_GetNameWithOut(deadgroup)
|
||||||
|
|
||||||
-- Group is dead!
|
-- Group is dead!
|
||||||
if groupdead then
|
if groupdead then
|
||||||
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(group,request))))
|
-- Debug output.
|
||||||
|
self:T(self.lid..string.format("Group %s (transport=%s) is dead!", groupname, tostring(self:_GroupIsTransport(deadgroup,request))))
|
||||||
if self.Debug then
|
if self.Debug then
|
||||||
group:SmokeWhite()
|
deadgroup:SmokeWhite()
|
||||||
end
|
end
|
||||||
-- Trigger AssetDead event.
|
-- Trigger AssetDead event.
|
||||||
local asset=self:FindAssetInDB(group)
|
|
||||||
self:AssetDead(asset, request)
|
self:AssetDead(asset, request)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -6633,19 +6695,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
|
|||||||
-- Dont trigger a Remove event for the group sets.
|
-- Dont trigger a Remove event for the group sets.
|
||||||
local NoTriggerEvent=true
|
local NoTriggerEvent=true
|
||||||
|
|
||||||
if request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
|
if not request.transporttype==WAREHOUSE.TransportType.SELFPROPELLED then
|
||||||
|
|
||||||
---
|
|
||||||
-- Easy case: Group can simply be removed from the cargogroupset.
|
|
||||||
---
|
|
||||||
|
|
||||||
-- Remove dead group from cargo group set.
|
|
||||||
if groupdead==true then
|
|
||||||
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
|
||||||
self:T(self.lid..string.format("Removed selfpropelled cargo %s: ncargo=%d.", groupname, request.cargogroupset:Count()))
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Complicated case: Dead unit could be:
|
-- Complicated case: Dead unit could be:
|
||||||
@ -6653,10 +6703,7 @@ function WAREHOUSE:_UnitDead(deadunit, request)
|
|||||||
-- 2.) A Transport unit which itself holds cargo groups.
|
-- 2.) A Transport unit which itself holds cargo groups.
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Check if this a cargo or transport group.
|
if not asset.iscargo then
|
||||||
local istransport=self:_GroupIsTransport(group,request)
|
|
||||||
|
|
||||||
if istransport==true then
|
|
||||||
|
|
||||||
-- Get the carrier unit table holding the cargo groups inside this carrier.
|
-- Get the carrier unit table holding the cargo groups inside this carrier.
|
||||||
local cargogroupnames=request.carriercargo[unitname]
|
local cargogroupnames=request.carriercargo[unitname]
|
||||||
@ -6671,25 +6718,8 @@ function WAREHOUSE:_UnitDead(deadunit, request)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Whole carrier group is dead. Remove it from the carrier group set.
|
|
||||||
if groupdead then
|
|
||||||
request.transportgroupset:Remove(groupname, NoTriggerEvent)
|
|
||||||
self:T(self.lid..string.format("Removed transport %s: ntransport=%d", groupname, request.transportgroupset:Count()))
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif istransport==false then
|
|
||||||
|
|
||||||
-- This must have been an alive cargo group that was killed outside the carrier, e.g. waiting to be transported or waiting to be put back.
|
|
||||||
-- Remove dead group from cargo group set.
|
|
||||||
if groupdead==true then
|
|
||||||
request.cargogroupset:Remove(groupname, NoTriggerEvent)
|
|
||||||
self:T(self.lid..string.format("Removed transported cargo %s outside carrier: ncargo=%d", groupname, request.cargogroupset:Count()))
|
|
||||||
-- This as well?
|
|
||||||
--request.transportcargoset:RemoveCargosByName(RemoveCargoNames)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", group:GetName()))
|
self:E(self.lid..string.format("ERROR: Group %s is neither cargo nor transport!", deadgroup:GetName()))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -8065,6 +8095,28 @@ end
|
|||||||
-- @return #number Request ID.
|
-- @return #number Request ID.
|
||||||
function WAREHOUSE:_GetIDsFromGroup(group)
|
function WAREHOUSE:_GetIDsFromGroup(group)
|
||||||
|
|
||||||
|
if group then
|
||||||
|
|
||||||
|
-- Group name
|
||||||
|
local groupname=group:GetName()
|
||||||
|
|
||||||
|
local wid, aid, rid=self:_GetIDsFromGroupName(groupname)
|
||||||
|
|
||||||
|
return wid,aid,rid
|
||||||
|
else
|
||||||
|
self:E("WARNING: Group not found in GetIDsFromGroup() function!")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get warehouse id, asset id and request id from group name (alias).
|
||||||
|
-- @param #WAREHOUSE self
|
||||||
|
-- @param #string groupname Name of the group from which the info is gathered.
|
||||||
|
-- @return #number Warehouse ID.
|
||||||
|
-- @return #number Asset ID.
|
||||||
|
-- @return #number Request ID.
|
||||||
|
function WAREHOUSE:_GetIDsFromGroupName(groupname)
|
||||||
|
|
||||||
---@param #string text The text to analyse.
|
---@param #string text The text to analyse.
|
||||||
local function analyse(text)
|
local function analyse(text)
|
||||||
|
|
||||||
@ -8094,13 +8146,9 @@ function WAREHOUSE:_GetIDsFromGroup(group)
|
|||||||
return _wid,_aid,_rid
|
return _wid,_aid,_rid
|
||||||
end
|
end
|
||||||
|
|
||||||
if group then
|
|
||||||
|
|
||||||
-- Group name
|
|
||||||
local name=group:GetName()
|
|
||||||
|
|
||||||
-- Get asset id from group name.
|
-- Get asset id from group name.
|
||||||
local wid,aid,rid=analyse(name)
|
local wid,aid,rid=analyse(groupname)
|
||||||
|
|
||||||
-- Get Asset.
|
-- Get Asset.
|
||||||
local asset=self:GetAssetByID(aid)
|
local asset=self:GetAssetByID(aid)
|
||||||
@ -8112,75 +8160,12 @@ function WAREHOUSE:_GetIDsFromGroup(group)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Debug info
|
-- Debug info
|
||||||
self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
|
self:T3(self.lid..string.format("Group Name = %s", tostring(groupname)))
|
||||||
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
|
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
|
||||||
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
|
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
|
||||||
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
|
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
|
||||||
|
|
||||||
return wid,aid,rid
|
return wid,aid,rid
|
||||||
else
|
|
||||||
self:E("WARNING: Group not found in GetIDsFromGroup() function!")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get warehouse id, asset id and request id from group name (alias).
|
|
||||||
-- @param #WAREHOUSE self
|
|
||||||
-- @param Wrapper.Group#GROUP group The group from which the info is gathered.
|
|
||||||
-- @return #number Warehouse ID.
|
|
||||||
-- @return #number Asset ID.
|
|
||||||
-- @return #number Request ID.
|
|
||||||
function WAREHOUSE:_GetIDsFromGroupOLD(group)
|
|
||||||
|
|
||||||
---@param #string text The text to analyse.
|
|
||||||
local function analyse(text)
|
|
||||||
|
|
||||||
-- Get rid of #0001 tail from spawn.
|
|
||||||
local unspawned=UTILS.Split(text, "#")[1]
|
|
||||||
|
|
||||||
-- Split keywords.
|
|
||||||
local keywords=UTILS.Split(unspawned, "_")
|
|
||||||
local _wid=nil -- warehouse UID
|
|
||||||
local _aid=nil -- asset UID
|
|
||||||
local _rid=nil -- request UID
|
|
||||||
|
|
||||||
-- Loop over keys.
|
|
||||||
for _,keys in pairs(keywords) do
|
|
||||||
local str=UTILS.Split(keys, "-")
|
|
||||||
local key=str[1]
|
|
||||||
local val=str[2]
|
|
||||||
if key:find("WID") then
|
|
||||||
_wid=tonumber(val)
|
|
||||||
elseif key:find("AID") then
|
|
||||||
_aid=tonumber(val)
|
|
||||||
elseif key:find("RID") then
|
|
||||||
_rid=tonumber(val)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return _wid,_aid,_rid
|
|
||||||
end
|
|
||||||
|
|
||||||
if group then
|
|
||||||
|
|
||||||
-- Group name
|
|
||||||
local name=group:GetName()
|
|
||||||
|
|
||||||
-- Get ids
|
|
||||||
local wid,aid,rid=analyse(name)
|
|
||||||
|
|
||||||
-- Debug info
|
|
||||||
self:T3(self.lid..string.format("Group Name = %s", tostring(name)))
|
|
||||||
self:T3(self.lid..string.format("Warehouse ID = %s", tostring(wid)))
|
|
||||||
self:T3(self.lid..string.format("Asset ID = %s", tostring(aid)))
|
|
||||||
self:T3(self.lid..string.format("Request ID = %s", tostring(rid)))
|
|
||||||
|
|
||||||
return wid,aid,rid
|
|
||||||
else
|
|
||||||
self:E("WARNING: Group not found in GetIDsFromGroup() function!")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Filter stock assets by descriptor and attribute.
|
--- Filter stock assets by descriptor and attribute.
|
||||||
|
|||||||
@ -46,7 +46,7 @@
|
|||||||
--
|
--
|
||||||
-- # The ARMYGROUP Concept
|
-- # The ARMYGROUP Concept
|
||||||
--
|
--
|
||||||
-- This class enhances naval groups.
|
-- This class enhances ground groups.
|
||||||
--
|
--
|
||||||
-- @field #ARMYGROUP
|
-- @field #ARMYGROUP
|
||||||
ARMYGROUP = {
|
ARMYGROUP = {
|
||||||
@ -115,6 +115,7 @@ function ARMYGROUP:New(group)
|
|||||||
self:AddTransition("*", "Cruise", "Cruising") -- Cruise along the given route of waypoints.
|
self:AddTransition("*", "Cruise", "Cruising") -- Cruise along the given route of waypoints.
|
||||||
|
|
||||||
self:AddTransition("*", "RTZ", "Returning") -- Group is returning to (home) zone.
|
self:AddTransition("*", "RTZ", "Returning") -- Group is returning to (home) zone.
|
||||||
|
self:AddTransition("Holding", "Returned", "Returned") -- Group is returned to (home) zone, e.g. when unloaded from carrier.
|
||||||
self:AddTransition("Returning", "Returned", "Returned") -- Group is returned to (home) zone.
|
self:AddTransition("Returning", "Returned", "Returned") -- Group is returned to (home) zone.
|
||||||
|
|
||||||
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
||||||
@ -653,6 +654,9 @@ function ARMYGROUP:Status()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Check damage of elements and group.
|
||||||
|
self:_CheckDamage()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check that group EXISTS.
|
-- Check that group EXISTS.
|
||||||
@ -706,7 +710,6 @@ function ARMYGROUP:Status()
|
|||||||
local name=element.name
|
local name=element.name
|
||||||
local status=element.status
|
local status=element.status
|
||||||
local unit=element.unit
|
local unit=element.unit
|
||||||
--local life=unit:GetLifeRelative() or 0
|
|
||||||
local life,life0=self:GetLifePoints(element)
|
local life,life0=self:GetLifePoints(element)
|
||||||
|
|
||||||
local life0=element.life0
|
local life0=element.life0
|
||||||
@ -926,7 +929,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
|||||||
|
|
||||||
-- Next waypoint.
|
-- Next waypoint.
|
||||||
local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
|
local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||||
self:T({wp})
|
|
||||||
-- Speed.
|
-- Speed.
|
||||||
if Speed then
|
if Speed then
|
||||||
wp.speed=UTILS.KnotsToMps(tonumber(Speed))
|
wp.speed=UTILS.KnotsToMps(tonumber(Speed))
|
||||||
@ -981,6 +984,13 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
|||||||
|
|
||||||
-- Insert a point on road.
|
-- Insert a point on road.
|
||||||
if wp.action==ENUMS.Formation.Vehicle.OnRoad and (wp.coordinate or wp.roadcoord) then
|
if wp.action==ENUMS.Formation.Vehicle.OnRoad and (wp.coordinate or wp.roadcoord) then
|
||||||
|
|
||||||
|
current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
|
||||||
|
table.insert(waypoints, 2, current)
|
||||||
|
|
||||||
|
-- Removing this for now as I don't see why it is necessary and it is very CPU intensive.
|
||||||
|
-- You only need the start and end waypoint on the road. Other waypoints on the road are not necessray.
|
||||||
|
--[[
|
||||||
-- take direct line if on road is too long
|
-- take direct line if on road is too long
|
||||||
local wptable,length,valid=self:GetCoordinate():GetPathOnRoad(wp.coordinate or wp.roadcoord,true,false,false,false) or {}
|
local wptable,length,valid=self:GetCoordinate():GetPathOnRoad(wp.coordinate or wp.roadcoord,true,false,false,false) or {}
|
||||||
|
|
||||||
@ -1003,6 +1013,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
|||||||
current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
|
current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
|
||||||
table.insert(waypoints, count, current)
|
table.insert(waypoints, count, current)
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
@ -1106,16 +1117,6 @@ end
|
|||||||
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
||||||
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
||||||
|
|
||||||
-- Get current task.
|
|
||||||
local task=self:GetTaskCurrent()
|
|
||||||
|
|
||||||
if task then
|
|
||||||
if task.dcstask.id=="FireAtPoint" or task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
|
||||||
self:T(self.lid..string.format("Cancelling current %s task because out of ammo!", task.dcstask.id))
|
|
||||||
self:TaskCancel(task)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Fist, check if we want to rearm once out-of-ammo.
|
-- Fist, check if we want to rearm once out-of-ammo.
|
||||||
--TODO: IsMobile() check
|
--TODO: IsMobile() check
|
||||||
if self.rearmOnOutOfAmmo then
|
if self.rearmOnOutOfAmmo then
|
||||||
@ -1139,6 +1140,16 @@ function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
|||||||
self:__RTZ(-1)
|
self:__RTZ(-1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get current task.
|
||||||
|
local task=self:GetTaskCurrent()
|
||||||
|
|
||||||
|
if task then
|
||||||
|
if task.dcstask.id=="FireAtPoint" or task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
||||||
|
self:T(self.lid..string.format("Cancelling current %s task because out of ammo!", task.dcstask.id))
|
||||||
|
self:TaskCancel(task)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1224,9 +1235,6 @@ end
|
|||||||
-- @param #number Formation Formation of the group.
|
-- @param #number Formation Formation of the group.
|
||||||
function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
|
function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
|
||||||
|
|
||||||
-- ID of current waypoint.
|
|
||||||
local uid=self:GetWaypointCurrent().uid
|
|
||||||
|
|
||||||
-- Zone.
|
-- Zone.
|
||||||
local zone=Zone or self.homezone
|
local zone=Zone or self.homezone
|
||||||
|
|
||||||
@ -1241,6 +1249,9 @@ function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
|
|||||||
|
|
||||||
local Coordinate=zone:GetRandomCoordinate()
|
local Coordinate=zone:GetRandomCoordinate()
|
||||||
|
|
||||||
|
-- ID of current waypoint.
|
||||||
|
local uid=self:GetWaypointCurrentUID()
|
||||||
|
|
||||||
-- Add waypoint after current.
|
-- Add waypoint after current.
|
||||||
local wp=self:AddWaypoint(Coordinate, nil, uid, Formation, true)
|
local wp=self:AddWaypoint(Coordinate, nil, uid, Formation, true)
|
||||||
|
|
||||||
@ -1352,6 +1363,9 @@ function ARMYGROUP:onafterRetreat(From, Event, To, Zone, Formation)
|
|||||||
-- Set if we want to resume route after reaching the detour waypoint.
|
-- Set if we want to resume route after reaching the detour waypoint.
|
||||||
wp.detour=0
|
wp.detour=0
|
||||||
|
|
||||||
|
-- Cancel all missions.
|
||||||
|
self:CancelAllMissions()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "Retreated" event.
|
--- On after "Retreated" event.
|
||||||
@ -1417,6 +1431,7 @@ end
|
|||||||
function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||||
self:T(self.lid.."Engaging Target")
|
self:T(self.lid.."Engaging Target")
|
||||||
|
|
||||||
|
-- Make sure this is a target.
|
||||||
if Target:IsInstanceOf("TARGET") then
|
if Target:IsInstanceOf("TARGET") then
|
||||||
self.engage.Target=Target
|
self.engage.Target=Target
|
||||||
else
|
else
|
||||||
@ -1426,11 +1441,9 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
|||||||
-- Target coordinate.
|
-- Target coordinate.
|
||||||
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
|
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
|
||||||
|
|
||||||
|
-- Get a coordinate close to the target.
|
||||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Backup ROE and alarm state.
|
-- Backup ROE and alarm state.
|
||||||
self.engage.roe=self:GetROE()
|
self.engage.roe=self:GetROE()
|
||||||
self.engage.alarmstate=self:GetAlarmstate()
|
self.engage.alarmstate=self:GetAlarmstate()
|
||||||
@ -1442,6 +1455,10 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
|||||||
-- ID of current waypoint.
|
-- ID of current waypoint.
|
||||||
local uid=self:GetWaypointCurrent().uid
|
local uid=self:GetWaypointCurrent().uid
|
||||||
|
|
||||||
|
-- Set formation.
|
||||||
|
--TODO: make this input.
|
||||||
|
local Formation=ENUMS.Formation.Vehicle.Vee
|
||||||
|
|
||||||
-- Add waypoint after current.
|
-- Add waypoint after current.
|
||||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||||
|
|
||||||
@ -1459,6 +1476,8 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
-- Get current position vector.
|
-- Get current position vector.
|
||||||
local vec3=self.engage.Target:GetVec3()
|
local vec3=self.engage.Target:GetVec3()
|
||||||
|
|
||||||
|
if vec3 then
|
||||||
|
|
||||||
-- Distance to last known position of target.
|
-- Distance to last known position of target.
|
||||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||||
|
|
||||||
@ -1488,7 +1507,14 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Target not alive any more == Disengage.
|
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||||
|
self:Disengage()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Target not alive any more ==> Disengage.
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -1587,8 +1613,7 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
|||||||
-- Speed in knots.
|
-- Speed in knots.
|
||||||
Speed=Speed or self:GetSpeedCruise()
|
Speed=Speed or self:GetSpeedCruise()
|
||||||
|
|
||||||
-- Formation
|
-- Formation.
|
||||||
|
|
||||||
if not Formation then
|
if not Formation then
|
||||||
if self.formationPerma then
|
if self.formationPerma then
|
||||||
Formation = self.formationPerma
|
Formation = self.formationPerma
|
||||||
|
|||||||
@ -94,6 +94,7 @@
|
|||||||
-- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported.
|
-- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported.
|
||||||
-- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo.
|
-- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo.
|
||||||
-- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo.
|
-- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo.
|
||||||
|
-- @field #number transportPickupRadius Radius in meters for pickup zone. Default 500 m.
|
||||||
--
|
--
|
||||||
-- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment.
|
-- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment.
|
||||||
-- @field #number NcarriersMin Min number of required carrier assets.
|
-- @field #number NcarriersMin Min number of required carrier assets.
|
||||||
@ -383,6 +384,7 @@ _AUFTRAGSNR=0
|
|||||||
-- @field #string ARMOREDGUARD On guard - with armored groups.
|
-- @field #string ARMOREDGUARD On guard - with armored groups.
|
||||||
-- @field #string BARRAGE Barrage.
|
-- @field #string BARRAGE Barrage.
|
||||||
-- @field #string ARMORATTACK Armor attack.
|
-- @field #string ARMORATTACK Armor attack.
|
||||||
|
-- @field #string CASENHANCED Enhanced CAS.
|
||||||
AUFTRAG.Type={
|
AUFTRAG.Type={
|
||||||
ANTISHIP="Anti Ship",
|
ANTISHIP="Anti Ship",
|
||||||
AWACS="AWACS",
|
AWACS="AWACS",
|
||||||
@ -415,6 +417,7 @@ AUFTRAG.Type={
|
|||||||
ARMOREDGUARD="Armored Guard",
|
ARMOREDGUARD="Armored Guard",
|
||||||
BARRAGE="Barrage",
|
BARRAGE="Barrage",
|
||||||
ARMORATTACK="Armor Attack",
|
ARMORATTACK="Armor Attack",
|
||||||
|
CASENHANCED="CAS Enhanced",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Mission status of an assigned group.
|
--- Mission status of an assigned group.
|
||||||
@ -557,7 +560,7 @@ AUFTRAG.Category={
|
|||||||
|
|
||||||
--- AUFTRAG class version.
|
--- AUFTRAG class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AUFTRAG.version="0.8.1"
|
AUFTRAG.version="0.8.4"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -1186,6 +1189,45 @@ function AUFTRAG:NewCAS(ZoneCAS, Altitude, Speed, Coordinate, Heading, Leg, Targ
|
|||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[AIR]** Create a CASENHANCED mission. Group(s) will go to the zone and patrol it randomly.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Zone#ZONE CasZone The CAS zone.
|
||||||
|
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||||
|
-- @param #number Speed Speed in knots.
|
||||||
|
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
|
||||||
|
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`.
|
||||||
|
-- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZoneSet, TargetTypes)
|
||||||
|
|
||||||
|
local mission=AUFTRAG:New(AUFTRAG.Type.CASENHANCED)
|
||||||
|
|
||||||
|
-- Ensure we got a ZONE and not just the zone name.
|
||||||
|
if type(CasZone)=="string" then
|
||||||
|
CasZone=ZONE:New(CasZone)
|
||||||
|
end
|
||||||
|
|
||||||
|
mission:_TargetFromObject(CasZone)
|
||||||
|
|
||||||
|
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CASENHANCED)
|
||||||
|
|
||||||
|
mission:SetEngageDetected(RangeMax, TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"}, CasZone, NoEngageZoneSet)
|
||||||
|
|
||||||
|
mission.optionROE=ENUMS.ROE.OpenFire
|
||||||
|
mission.optionROT=ENUMS.ROT.EvadeFire
|
||||||
|
|
||||||
|
mission.missionFraction=1.0
|
||||||
|
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
|
||||||
|
mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil
|
||||||
|
|
||||||
|
mission.categories={AUFTRAG.Category.AIRCRAFT}
|
||||||
|
|
||||||
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- **[AIR]** Create a FACA mission.
|
--- **[AIR]** Create a FACA mission.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object.
|
-- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object.
|
||||||
@ -1492,8 +1534,9 @@ end
|
|||||||
-- @param Core.Set#SET_GROUP TransportGroupSet The set group(s) to be transported.
|
-- @param Core.Set#SET_GROUP TransportGroupSet The set group(s) to be transported.
|
||||||
-- @param Core.Point#COORDINATE DropoffCoordinate Coordinate where the helo will land drop off the the troops.
|
-- @param Core.Point#COORDINATE DropoffCoordinate Coordinate where the helo will land drop off the the troops.
|
||||||
-- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the fist transport group.
|
-- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the fist transport group.
|
||||||
|
-- @param #number PickupRadius Radius around the pickup coordinate in meters. Default 100 m.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate)
|
function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate, PickupRadius)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.TROOPTRANSPORT)
|
local mission=AUFTRAG:New(AUFTRAG.Type.TROOPTRANSPORT)
|
||||||
|
|
||||||
@ -1512,11 +1555,13 @@ function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupC
|
|||||||
mission.transportPickup=PickupCoordinate or mission:GetTargetCoordinate()
|
mission.transportPickup=PickupCoordinate or mission:GetTargetCoordinate()
|
||||||
mission.transportDropoff=DropoffCoordinate
|
mission.transportDropoff=DropoffCoordinate
|
||||||
|
|
||||||
|
mission.transportPickupRadius=PickupRadius or 100
|
||||||
|
|
||||||
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.TROOPTRANSPORT)
|
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.TROOPTRANSPORT)
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
mission.transportPickup:MarkToAll("Pickup")
|
--mission.transportPickup:MarkToAll("Pickup Transport")
|
||||||
mission.transportDropoff:MarkToAll("Drop off")
|
--mission.transportDropoff:MarkToAll("Drop off")
|
||||||
|
|
||||||
-- TODO: what's the best ROE here?
|
-- TODO: what's the best ROE here?
|
||||||
mission.optionROE=ENUMS.ROE.ReturnFire
|
mission.optionROE=ENUMS.ROE.ReturnFire
|
||||||
@ -1645,8 +1690,9 @@ end
|
|||||||
-- @param Core.Zone#ZONE Zone The patrol zone.
|
-- @param Core.Zone#ZONE Zone The patrol zone.
|
||||||
-- @param #number Speed Speed in knots.
|
-- @param #number Speed Speed in knots.
|
||||||
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||||
|
-- @param #string Formation Formation used during patrol.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
|
function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.PATROLZONE)
|
local mission=AUFTRAG:New(AUFTRAG.Type.PATROLZONE)
|
||||||
|
|
||||||
@ -1671,9 +1717,12 @@ function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
|
|||||||
|
|
||||||
mission.DCStask=mission:GetDCSMissionTask()
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
mission.DCStask.params.formation=Formation
|
||||||
|
|
||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack.
|
--- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object.
|
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object.
|
||||||
@ -3478,7 +3527,7 @@ function AUFTRAG:SetGroupStatus(opsgroup, status)
|
|||||||
local groupsDone=self:CheckGroupsDone()
|
local groupsDone=self:CheckGroupsDone()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T2(self.lid..string.format("Setting OPSGROUP %s status to %s. IsNotOver=%s CheckGroupsDone=%s", opsgroup.groupname, self:GetGroupStatus(opsgroup), tostring(self:IsNotOver()), tostring(self:CheckGroupsDone())))
|
self:T2(self.lid..string.format("Setting OPSGROUP %s status to %s. IsNotOver=%s CheckGroupsDone=%s", opsgroup.groupname, self:GetGroupStatus(opsgroup), tostring(self:IsNotOver()), tostring(groupsDone)))
|
||||||
|
|
||||||
-- Check if ALL flights are done with their mission.
|
-- Check if ALL flights are done with their mission.
|
||||||
if isNotOver and groupsDone then
|
if isNotOver and groupsDone then
|
||||||
@ -4959,6 +5008,26 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
|||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.CASENHANCED then
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- CAS ENHANCED Mission --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
local DCStask={}
|
||||||
|
|
||||||
|
DCStask.id="PatrolZone"
|
||||||
|
|
||||||
|
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
|
||||||
|
local param={}
|
||||||
|
param.zone=self:GetObjective()
|
||||||
|
param.altitude=self.missionAltitude
|
||||||
|
param.speed=self.missionSpeed
|
||||||
|
|
||||||
|
DCStask.params=param
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
elseif self.type==AUFTRAG.Type.ARMORATTACK then
|
elseif self.type==AUFTRAG.Type.ARMORATTACK then
|
||||||
|
|
||||||
-------------------------
|
-------------------------
|
||||||
@ -5147,6 +5216,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType)
|
|||||||
mtask=ENUMS.MissionTask.CAS
|
mtask=ENUMS.MissionTask.CAS
|
||||||
elseif MissionType==AUFTRAG.Type.PATROLZONE then
|
elseif MissionType==AUFTRAG.Type.PATROLZONE then
|
||||||
mtask=ENUMS.MissionTask.CAS
|
mtask=ENUMS.MissionTask.CAS
|
||||||
|
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
||||||
|
mtask=ENUMS.MissionTask.CAS
|
||||||
elseif MissionType==AUFTRAG.Type.ESCORT then
|
elseif MissionType==AUFTRAG.Type.ESCORT then
|
||||||
mtask=ENUMS.MissionTask.ESCORT
|
mtask=ENUMS.MissionTask.ESCORT
|
||||||
elseif MissionType==AUFTRAG.Type.FACA then
|
elseif MissionType==AUFTRAG.Type.FACA then
|
||||||
|
|||||||
@ -6,6 +6,14 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- ## Missions:--- **Ops** -- Combat Search and Rescue.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- **CSAR** - MOOSE based Helicopter CSAR Operations.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CSAR)
|
-- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CSAR)
|
||||||
@ -118,6 +126,7 @@
|
|||||||
-- self.SRSModulation = radio.modulation.AM -- modulation
|
-- self.SRSModulation = radio.modulation.AM -- modulation
|
||||||
-- --
|
-- --
|
||||||
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
|
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
|
||||||
|
-- self.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
|
||||||
--
|
--
|
||||||
-- ## 3. Results
|
-- ## 3. Results
|
||||||
--
|
--
|
||||||
@ -227,8 +236,9 @@ CSAR = {
|
|||||||
-- @field #number frequency Frequency of the NDB.
|
-- @field #number frequency Frequency of the NDB.
|
||||||
-- @field #string player Player name if applicable.
|
-- @field #string player Player name if applicable.
|
||||||
-- @field Wrapper.Group#GROUP group Spawned group object.
|
-- @field Wrapper.Group#GROUP group Spawned group object.
|
||||||
-- @field #number timestamp Timestamp for approach process
|
-- @field #number timestamp Timestamp for approach process.
|
||||||
-- @field #boolean alive Group is alive or dead/rescued
|
-- @field #boolean alive Group is alive or dead/rescued.
|
||||||
|
-- @field #boolean wetfeet Group is spawned over (deep) water.
|
||||||
|
|
||||||
--- All slot / Limit settings
|
--- All slot / Limit settings
|
||||||
-- @type CSAR.AircraftType
|
-- @type CSAR.AircraftType
|
||||||
@ -245,10 +255,11 @@ CSAR.AircraftType["Mi-24P"] = 8
|
|||||||
CSAR.AircraftType["Mi-24V"] = 8
|
CSAR.AircraftType["Mi-24V"] = 8
|
||||||
CSAR.AircraftType["Bell-47"] = 2
|
CSAR.AircraftType["Bell-47"] = 2
|
||||||
CSAR.AircraftType["UH-60L"] = 10
|
CSAR.AircraftType["UH-60L"] = 10
|
||||||
|
CSAR.AircraftType["AH-64D_BLK_II"] = 2
|
||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="1.0.3"
|
CSAR.version="1.0.4d"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@ -391,6 +402,10 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
-- added 0.1.3
|
-- added 0.1.3
|
||||||
self.csarUsePara = false -- shagrat set to true, will use the LandingAfterEjection Event instead of Ejection
|
self.csarUsePara = false -- shagrat set to true, will use the LandingAfterEjection Event instead of Ejection
|
||||||
|
|
||||||
|
-- added 0.1.4
|
||||||
|
self.wetfeettemplate = nil
|
||||||
|
self.usewetfeet = false
|
||||||
|
|
||||||
-- WARNING - here\'ll be dragons
|
-- WARNING - here\'ll be dragons
|
||||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||||
-- needs SRS => 1.9.6 to work (works on the *server* side)
|
-- needs SRS => 1.9.6 to work (works on the *server* side)
|
||||||
@ -502,8 +517,9 @@ end
|
|||||||
-- @param #string Typename Typename of unit.
|
-- @param #string Typename Typename of unit.
|
||||||
-- @param #number Frequency Frequency of the NDB in Hz
|
-- @param #number Frequency Frequency of the NDB in Hz
|
||||||
-- @param #string Playername Name of Player (if applicable)
|
-- @param #string Playername Name of Player (if applicable)
|
||||||
|
-- @param #boolean Wetfeet Ejected over water
|
||||||
-- @return #CSAR self.
|
-- @return #CSAR self.
|
||||||
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername)
|
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet)
|
||||||
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
|
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
|
||||||
|
|
||||||
-- create new entry
|
-- create new entry
|
||||||
@ -519,6 +535,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
|
|||||||
DownedPilot.group = Group
|
DownedPilot.group = Group
|
||||||
DownedPilot.timestamp = 0
|
DownedPilot.timestamp = 0
|
||||||
DownedPilot.alive = true
|
DownedPilot.alive = true
|
||||||
|
DownedPilot.wetfeet = Wetfeet or false
|
||||||
|
|
||||||
-- Add Pilot
|
-- Add Pilot
|
||||||
local PilotTable = self.downedPilots
|
local PilotTable = self.downedPilots
|
||||||
@ -568,17 +585,23 @@ end
|
|||||||
-- @param #number country Country for template.
|
-- @param #number country Country for template.
|
||||||
-- @param Core.Point#COORDINATE point Coordinate to spawn at.
|
-- @param Core.Point#COORDINATE point Coordinate to spawn at.
|
||||||
-- @param #number frequency Frequency of the pilot's beacon
|
-- @param #number frequency Frequency of the pilot's beacon
|
||||||
|
-- @param #boolean wetfeet Spawn is over water
|
||||||
-- @return Wrapper.Group#GROUP group The #GROUP object.
|
-- @return Wrapper.Group#GROUP group The #GROUP object.
|
||||||
-- @return #string alias The alias name.
|
-- @return #string alias The alias name.
|
||||||
function CSAR:_SpawnPilotInField(country,point,frequency)
|
function CSAR:_SpawnPilotInField(country,point,frequency,wetfeet)
|
||||||
self:T({country,point,frequency})
|
self:T({country,point,frequency,tostring(wetfeet)})
|
||||||
local freq = frequency or 1000
|
local freq = frequency or 1000
|
||||||
local freq = freq / 1000 -- kHz
|
local freq = freq / 1000 -- kHz
|
||||||
for i=1,10 do
|
for i=1,10 do
|
||||||
math.random(i,10000)
|
math.random(i,10000)
|
||||||
end
|
end
|
||||||
if point:IsSurfaceTypeWater() then point.y = 0 end
|
if point:IsSurfaceTypeWater() or wetfeet then
|
||||||
|
point.y = 0
|
||||||
|
end
|
||||||
local template = self.template
|
local template = self.template
|
||||||
|
if self.usewetfeet and wetfeet then
|
||||||
|
template = self.wetfeettemplate
|
||||||
|
end
|
||||||
local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99))
|
local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99))
|
||||||
local coalition = self.coalition
|
local coalition = self.coalition
|
||||||
local pilotcacontrol = self.allowDownedPilotCAcontrol -- Switch AI on/oof - is this really correct for CA?
|
local pilotcacontrol = self.allowDownedPilotCAcontrol -- Switch AI on/oof - is this really correct for CA?
|
||||||
@ -644,13 +667,19 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description})
|
self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description})
|
||||||
|
|
||||||
local template = self.template
|
local template = self.template
|
||||||
|
local wetfeet = false
|
||||||
|
|
||||||
|
local surface = _point:GetSurfaceType()
|
||||||
|
if surface == land.SurfaceType.WATER then
|
||||||
|
wetfeet = true
|
||||||
|
end
|
||||||
|
|
||||||
if not _freq then
|
if not _freq then
|
||||||
_freq = self:_GenerateADFFrequency()
|
_freq = self:_GenerateADFFrequency()
|
||||||
if not _freq then _freq = 333000 end --noob catch
|
if not _freq then _freq = 333000 end --noob catch
|
||||||
end
|
end
|
||||||
|
|
||||||
local _spawnedGroup, _alias = self:_SpawnPilotInField(_country,_point,_freq)
|
local _spawnedGroup, _alias = self:_SpawnPilotInField(_country,_point,_freq,wetfeet)
|
||||||
|
|
||||||
local _typeName = _typeName or "Pilot"
|
local _typeName = _typeName or "Pilot"
|
||||||
|
|
||||||
@ -688,7 +717,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
|
|
||||||
local _GroupName = _spawnedGroup:GetName() or _alias
|
local _GroupName = _spawnedGroup:GetName() or _alias
|
||||||
|
|
||||||
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName)
|
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
|
||||||
|
|
||||||
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
||||||
|
|
||||||
@ -936,8 +965,18 @@ function CSAR:_EventHandler(EventData)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
||||||
|
-- might create dual pilots in edge cases
|
||||||
|
|
||||||
|
local wetfeet = false
|
||||||
|
|
||||||
|
local surface = _unit:GetCoordinate():GetSurfaceType()
|
||||||
|
if surface == land.SurfaceType.WATER then
|
||||||
|
wetfeet = true
|
||||||
|
end
|
||||||
-- all checks passed, get going.
|
-- all checks passed, get going.
|
||||||
if self.csarUsePara == false then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
||||||
local _freq = self:_GenerateADFFrequency()
|
local _freq = self:_GenerateADFFrequency()
|
||||||
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
|
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
|
||||||
return true
|
return true
|
||||||
@ -1294,7 +1333,8 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG
|
|||||||
_time = self.landedStatus[_lookupKeyHeli] - 10
|
_time = self.landedStatus[_lookupKeyHeli] - 10
|
||||||
self.landedStatus[_lookupKeyHeli] = _time
|
self.landedStatus[_lookupKeyHeli] = _time
|
||||||
end
|
end
|
||||||
if _time <= 0 or _distance < self.loadDistance then
|
--if _time <= 0 or _distance < self.loadDistance then
|
||||||
|
if _distance < self.loadDistance + 5 or _distance <= 13 then
|
||||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then
|
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then
|
||||||
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true)
|
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true)
|
||||||
return true
|
return true
|
||||||
@ -1999,6 +2039,9 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
||||||
end
|
end
|
||||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
|
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
|
||||||
|
if self.wetfeettemplate then
|
||||||
|
self.usewetfeet = true
|
||||||
|
end
|
||||||
self:__Status(-10)
|
self:__Status(-10)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1017,11 +1017,12 @@ CTLD.UnitTypes = {
|
|||||||
["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers.
|
["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers.
|
||||||
--Actually it's longer, but the center coord is off-center of the model.
|
--Actually it's longer, but the center coord is off-center of the model.
|
||||||
["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
|
["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
|
||||||
|
["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo
|
||||||
}
|
}
|
||||||
|
|
||||||
--- CTLD class version.
|
--- CTLD class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CTLD.version="1.0.9"
|
CTLD.version="1.0.10"
|
||||||
|
|
||||||
--- Instantiate a new CTLD.
|
--- Instantiate a new CTLD.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@ -2095,11 +2096,18 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight)
|
|||||||
-- cycle
|
-- cycle
|
||||||
local index = 0
|
local index = 0
|
||||||
local found = {}
|
local found = {}
|
||||||
local loadedmass = self:_GetUnitCargoMass(_unit)
|
local loadedmass = 0
|
||||||
local unittype = _unit:GetTypeName()
|
local unittype = "none"
|
||||||
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
local capabilities = {}
|
||||||
local maxmass = capabilities.cargoweightlimit
|
local maxmass = 2000
|
||||||
local maxloadable = maxmass - loadedmass
|
local maxloadable = 2000
|
||||||
|
if not _ignoreweight then
|
||||||
|
loadedmass = self:_GetUnitCargoMass(_unit)
|
||||||
|
unittype = _unit:GetTypeName()
|
||||||
|
capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
||||||
|
maxmass = capabilities.cargoweightlimit or 2000
|
||||||
|
maxloadable = maxmass - loadedmass
|
||||||
|
end
|
||||||
self:T(self.lid .. " Max loadable mass: " .. maxloadable)
|
self:T(self.lid .. " Max loadable mass: " .. maxloadable)
|
||||||
for _,_cargoobject in pairs (existingcrates) do
|
for _,_cargoobject in pairs (existingcrates) do
|
||||||
local cargo = _cargoobject -- #CTLD_CARGO
|
local cargo = _cargoobject -- #CTLD_CARGO
|
||||||
@ -2256,6 +2264,7 @@ end
|
|||||||
-- @return #number mass in kgs
|
-- @return #number mass in kgs
|
||||||
function CTLD:_GetUnitCargoMass(Unit)
|
function CTLD:_GetUnitCargoMass(Unit)
|
||||||
self:T(self.lid .. " _GetUnitCargoMass")
|
self:T(self.lid .. " _GetUnitCargoMass")
|
||||||
|
if not Unit then return 0 end
|
||||||
local unitname = Unit:GetName()
|
local unitname = Unit:GetName()
|
||||||
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
||||||
local loadedmass = 0 -- #number
|
local loadedmass = 0 -- #number
|
||||||
|
|||||||
@ -103,7 +103,7 @@
|
|||||||
--
|
--
|
||||||
-- Strategically important zones, which should be captured can be added via the @{#CHIEF.AddStrategicZone}() function.
|
-- Strategically important zones, which should be captured can be added via the @{#CHIEF.AddStrategicZone}() function.
|
||||||
--
|
--
|
||||||
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS mission is lauchned.
|
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS and an ARTY mission are lauchned, provided assets are available.
|
||||||
--
|
--
|
||||||
-- Once the zone is cleaned of enemy forces, ground (infantry) troops are send there. These require a transportation via helicopters.
|
-- Once the zone is cleaned of enemy forces, ground (infantry) troops are send there. These require a transportation via helicopters.
|
||||||
-- So in order to deploy our own troops, infantry assets with `AUFTRAG.Type.ONGUARD` and helicopters with `AUFTRAG.Type.OPSTRANSPORT` need to be available.
|
-- So in order to deploy our own troops, infantry assets with `AUFTRAG.Type.ONGUARD` and helicopters with `AUFTRAG.Type.OPSTRANSPORT` need to be available.
|
||||||
@ -180,7 +180,7 @@ CHIEF.Strategy = {
|
|||||||
|
|
||||||
--- CHIEF class version.
|
--- CHIEF class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CHIEF.version="0.1.0"
|
CHIEF.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -1731,7 +1731,7 @@ function CHIEF:CheckOpsZoneQueue()
|
|||||||
-- Has a patrol mission?
|
-- Has a patrol mission?
|
||||||
local hasMissionPatrol=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ONGUARD) or stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARMOREDGUARD)
|
local hasMissionPatrol=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ONGUARD) or stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARMOREDGUARD)
|
||||||
-- Has a CAS mission?
|
-- Has a CAS mission?
|
||||||
local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS)
|
local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
|
||||||
-- Has a ARTY mission?
|
-- Has a ARTY mission?
|
||||||
local hasMissionARTY=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
local hasMissionARTY=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
||||||
|
|
||||||
@ -1775,12 +1775,13 @@ function CHIEF:CheckOpsZoneQueue()
|
|||||||
|
|
||||||
|
|
||||||
-- Recruite CAS assets.
|
-- Recruite CAS assets.
|
||||||
local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CAS, 1, 1)
|
local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CASENHANCED, 1, 1)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T(self.lid..string.format("Zone is NOT empty ==> Recruit CAS assets=%s", tostring(recruited)))
|
self:T(self.lid..string.format("Zone is NOT empty ==> Recruit CAS assets=%s", tostring(recruited)))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if not hasMissionARTY then
|
if not hasMissionARTY then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
@ -1811,7 +1812,7 @@ function CHIEF:CheckOpsZoneQueue()
|
|||||||
local hasMissionPATROL=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.PATROLZONE)
|
local hasMissionPATROL=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.PATROLZONE)
|
||||||
|
|
||||||
-- Has a CAS mission?
|
-- Has a CAS mission?
|
||||||
local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS)
|
local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
|
||||||
local hasMissionARTY, ARTYMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
local hasMissionARTY, ARTYMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
||||||
|
|
||||||
if ownercoalition==self.coalition and stratzone.opszone:IsEmpty() and hasMissionCAS then
|
if ownercoalition==self.coalition and stratzone.opszone:IsEmpty() and hasMissionCAS then
|
||||||
@ -2208,7 +2209,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Recruite infantry assets.
|
-- Recruite infantry assets.
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, Categories, Attributes)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, Categories, Attributes)
|
||||||
|
|
||||||
if recruited then
|
if recruited then
|
||||||
|
|
||||||
@ -2260,12 +2261,48 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM
|
|||||||
-- Attach mission to ops zone.
|
-- Attach mission to ops zone.
|
||||||
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
||||||
|
|
||||||
|
-- Set ops zone to transport.
|
||||||
|
transport.opszone=StratZone.opszone
|
||||||
|
transport.chief=self
|
||||||
|
transport.commander=self.commander
|
||||||
|
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
LEGION.UnRecruitAssets(assets)
|
LEGION.UnRecruitAssets(assets)
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
||||||
|
|
||||||
|
-- Create Patrol zone mission.
|
||||||
|
local caszone = StratZone.opszone.zone
|
||||||
|
local coord = caszone:GetCoordinate()
|
||||||
|
local height = UTILS.MetersToFeet(coord:GetLandHeight())+2500
|
||||||
|
|
||||||
|
local Speed = 200
|
||||||
|
if assets[1] then
|
||||||
|
if assets[1].speedmax then
|
||||||
|
Speed = UTILS.KmphToKnots(assets[1].speedmax * 0.7) or 200
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--local mission=AUFTRAG:NewCAS(caszone,height,Speed,coord,math.random(0,359),Leg)
|
||||||
|
local mission=AUFTRAG:NewCASENHANCED(caszone, height, Speed)
|
||||||
|
|
||||||
|
-- Add assets to mission.
|
||||||
|
for _,asset in pairs(assets) do
|
||||||
|
mission:AddAsset(asset)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Assign mission to legions.
|
||||||
|
self:MissionAssign(mission, legions)
|
||||||
|
|
||||||
|
-- Attach mission to ops zone.
|
||||||
|
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
elseif MissionType==AUFTRAG.Type.CAS then
|
elseif MissionType==AUFTRAG.Type.CAS then
|
||||||
|
|
||||||
-- Create Patrol zone mission.
|
-- Create Patrol zone mission.
|
||||||
|
|||||||
@ -32,6 +32,7 @@
|
|||||||
-- @field #number skill Skill of cohort members.
|
-- @field #number skill Skill of cohort members.
|
||||||
-- @field Ops.Legion#LEGION legion The LEGION object the cohort belongs to.
|
-- @field Ops.Legion#LEGION legion The LEGION object the cohort belongs to.
|
||||||
-- @field #number Ngroups Number of asset OPS groups this cohort has.
|
-- @field #number Ngroups Number of asset OPS groups this cohort has.
|
||||||
|
-- @field #number Nkilled Number of destroyed asset groups.
|
||||||
-- @field #number engageRange Mission range in meters.
|
-- @field #number engageRange Mission range in meters.
|
||||||
-- @field #string attribute Generalized attribute of the cohort template group.
|
-- @field #string attribute Generalized attribute of the cohort template group.
|
||||||
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
||||||
@ -67,6 +68,7 @@ COHORT = {
|
|||||||
skill = nil,
|
skill = nil,
|
||||||
legion = nil,
|
legion = nil,
|
||||||
Ngroups = nil,
|
Ngroups = nil,
|
||||||
|
Ngroups = 0,
|
||||||
engageRange = nil,
|
engageRange = nil,
|
||||||
tacanChannel = {},
|
tacanChannel = {},
|
||||||
weightAsset = 99999,
|
weightAsset = 99999,
|
||||||
@ -275,12 +277,10 @@ end
|
|||||||
|
|
||||||
--- Set number of units in groups.
|
--- Set number of units in groups.
|
||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @param #number nunits Number of units. Must be >=1 and <=4. Default 2.
|
-- @param #number nunits Number of units. Default 2.
|
||||||
-- @return #COHORT self
|
-- @return #COHORT self
|
||||||
function COHORT:SetGrouping(nunits)
|
function COHORT:SetGrouping(nunits)
|
||||||
self.ngrouping=nunits or 2
|
self.ngrouping=nunits or 2
|
||||||
if self.ngrouping<1 then self.ngrouping=1 end
|
|
||||||
if self.ngrouping>4 then self.ngrouping=4 end
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -919,20 +919,6 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
|||||||
-- ARMY/NAVYGROUP combat ready?
|
-- ARMY/NAVYGROUP combat ready?
|
||||||
---
|
---
|
||||||
|
|
||||||
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
|
|
||||||
combatready=false
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check transport/cargo for combat readyness!
|
|
||||||
if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then
|
|
||||||
combatready=false
|
|
||||||
end
|
|
||||||
if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then
|
|
||||||
combatready=false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
|
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
|
||||||
--self:I("Attribute is: "..asset.attribute)
|
--self:I("Attribute is: "..asset.attribute)
|
||||||
if flightgroup:IsArmygroup() then
|
if flightgroup:IsArmygroup() then
|
||||||
@ -949,6 +935,22 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
|||||||
combatready=false
|
combatready=false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Not ready when rearming, retreating or returning!
|
||||||
|
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
|
||||||
|
combatready=false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Not ready when currently acting as ops transport carrier.
|
||||||
|
if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then
|
||||||
|
combatready=false
|
||||||
|
end
|
||||||
|
-- Not ready when currently acting as ops transport cargo.
|
||||||
|
if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then
|
||||||
|
combatready=false
|
||||||
|
end
|
||||||
|
|
||||||
-- This asset is "combatready".
|
-- This asset is "combatready".
|
||||||
if combatready then
|
if combatready then
|
||||||
self:T(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
self:T(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||||
|
|||||||
@ -132,7 +132,7 @@ COMMANDER = {
|
|||||||
|
|
||||||
--- COMMANDER class version.
|
--- COMMANDER class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
COMMANDER.version="0.1.0"
|
COMMANDER.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -1190,7 +1190,7 @@ function COMMANDER:RecruitAssetsForMission(Mission)
|
|||||||
local Payloads=Mission.payloads
|
local Payloads=Mission.payloads
|
||||||
|
|
||||||
-- Recruite assets.
|
-- Recruite assets.
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem)
|
||||||
|
|
||||||
return recruited, assets, legions
|
return recruited, assets, legions
|
||||||
end
|
end
|
||||||
@ -1292,6 +1292,7 @@ function COMMANDER:CheckTransportQueue()
|
|||||||
|
|
||||||
-- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit!
|
-- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit!
|
||||||
local weightGroup=0
|
local weightGroup=0
|
||||||
|
local TotalWeight=0
|
||||||
|
|
||||||
-- Calculate the max weight so we know which cohorts can provide carriers.
|
-- Calculate the max weight so we know which cohorts can provide carriers.
|
||||||
if #cargoOpsGroups>0 then
|
if #cargoOpsGroups>0 then
|
||||||
@ -1301,13 +1302,14 @@ function COMMANDER:CheckTransportQueue()
|
|||||||
if weight>weightGroup then
|
if weight>weightGroup then
|
||||||
weightGroup=weight
|
weightGroup=weight
|
||||||
end
|
end
|
||||||
|
TotalWeight=TotalWeight+weight
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if weightGroup>0 then
|
if weightGroup>0 then
|
||||||
|
|
||||||
-- Recruite assets from legions.
|
-- Recruite assets from legions.
|
||||||
local recruited, assets, legions=self:RecruitAssetsForTransport(transport, weightGroup)
|
local recruited, assets, legions=self:RecruitAssetsForTransport(transport, weightGroup, TotalWeight)
|
||||||
|
|
||||||
if recruited then
|
if recruited then
|
||||||
|
|
||||||
@ -1344,10 +1346,12 @@ end
|
|||||||
--- Recruit assets for a given OPS transport.
|
--- Recruit assets for a given OPS transport.
|
||||||
-- @param #COMMANDER self
|
-- @param #COMMANDER self
|
||||||
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport.
|
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport.
|
||||||
|
-- @param #number CargoWeight Weight of the heaviest cargo group.
|
||||||
|
-- @param #number TotalWeight Total weight of all cargo groups.
|
||||||
-- @return #boolean If `true`, enough assets could be recruited.
|
-- @return #boolean If `true`, enough assets could be recruited.
|
||||||
-- @return #table Recruited assets.
|
-- @return #table Recruited assets.
|
||||||
-- @return #table Legions that have recruited assets.
|
-- @return #table Legions that have recruited assets.
|
||||||
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
|
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight, TotalWeight)
|
||||||
|
|
||||||
if CargoWeight==0 then
|
if CargoWeight==0 then
|
||||||
-- No cargo groups!
|
-- No cargo groups!
|
||||||
@ -1381,7 +1385,7 @@ function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
|
|||||||
local NreqMin,NreqMax=Transport:GetRequiredCarriers()
|
local NreqMin,NreqMax=Transport:GetRequiredCarriers()
|
||||||
|
|
||||||
-- Recruit assets and legions.
|
-- Recruit assets and legions.
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, CargoWeight)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, CargoWeight, TotalWeight)
|
||||||
|
|
||||||
return recruited, assets, legions
|
return recruited, assets, legions
|
||||||
end
|
end
|
||||||
|
|||||||
@ -168,7 +168,7 @@ FLIGHTGROUP.Attribute = {
|
|||||||
|
|
||||||
--- FLIGHTGROUP class version.
|
--- FLIGHTGROUP class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FLIGHTGROUP.version="0.7.0"
|
FLIGHTGROUP.version="0.7.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -730,60 +730,6 @@ end
|
|||||||
-- Status
|
-- Status
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
---- Update status.
|
|
||||||
-- @param #FLIGHTGROUP self
|
|
||||||
function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
|
||||||
|
|
||||||
-- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase.
|
|
||||||
for i,_element in pairs(self.elements) do
|
|
||||||
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
|
||||||
|
|
||||||
-- Check that element is not already dead or not yet alive.
|
|
||||||
if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then
|
|
||||||
|
|
||||||
-- Unit shortcut.
|
|
||||||
local unit=element.unit
|
|
||||||
|
|
||||||
local isdead=false
|
|
||||||
if unit and unit:IsAlive() then
|
|
||||||
|
|
||||||
-- Get life points.
|
|
||||||
local life=unit:GetLife() or 0
|
|
||||||
|
|
||||||
-- Units with life <=1 are dead.
|
|
||||||
if life<=1 then
|
|
||||||
--env.info(string.format("FF unit %s: live<=1 in status at T=%.3f", unit:GetName(), timer.getTime()))
|
|
||||||
isdead=true
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
-- Not alive any more.
|
|
||||||
--env.info(string.format("FF unit %s: NOT alive in status at T=%.3f", unit:GetName(), timer.getTime()))
|
|
||||||
isdead=true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- This one is dead.
|
|
||||||
if isdead then
|
|
||||||
local text=string.format("Element %s is dead at t=%.3f but has status %s! Maybe despawned without notice or landed at a too small airbase. Calling ElementDead in 60 sec to give other events a chance",
|
|
||||||
tostring(element.name), timer.getTime(), tostring(element.status))
|
|
||||||
self:T(self.lid..text)
|
|
||||||
self:__ElementDead(60, element)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if self:IsDead() then
|
|
||||||
self:T(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
|
||||||
return false
|
|
||||||
elseif self:IsStopped() then
|
|
||||||
self:T(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Status update.
|
--- Status update.
|
||||||
-- @param #FLIGHTGROUP self
|
-- @param #FLIGHTGROUP self
|
||||||
function FLIGHTGROUP:Status()
|
function FLIGHTGROUP:Status()
|
||||||
@ -846,6 +792,9 @@ function FLIGHTGROUP:Status()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Check damage.
|
||||||
|
self:_CheckDamage()
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -45,13 +45,14 @@ LEGION = {
|
|||||||
|
|
||||||
--- LEGION class version.
|
--- LEGION class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
LEGION.version="0.2.0"
|
LEGION.version="0.2.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Create FLEED class.
|
-- TODO: Create FLEED class.
|
||||||
|
-- DONE: Aircraft will not start hot on Alert5.
|
||||||
-- DONE: OPS transport.
|
-- DONE: OPS transport.
|
||||||
-- DONE: Make general so it can be inherited by AIRWING and BRIGADE classes.
|
-- DONE: Make general so it can be inherited by AIRWING and BRIGADE classes.
|
||||||
|
|
||||||
@ -82,6 +83,10 @@ function LEGION:New(WarehouseName, LegionName)
|
|||||||
-- TODO: What?
|
-- TODO: What?
|
||||||
self:SetMarker(false)
|
self:SetMarker(false)
|
||||||
|
|
||||||
|
-- Dead and crash events are handled via opsgroups.
|
||||||
|
self:UnHandleEvent(EVENTS.Crash)
|
||||||
|
self:UnHandleEvent(EVENTS.Dead)
|
||||||
|
|
||||||
-- Add FSM transitions.
|
-- Add FSM transitions.
|
||||||
-- From State --> Event --> To State
|
-- From State --> Event --> To State
|
||||||
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
|
self:AddTransition("*", "MissionRequest", "*") -- Add a (mission) request to the warehouse.
|
||||||
@ -530,6 +535,7 @@ function LEGION:CheckMissionQueue()
|
|||||||
local Transport=nil
|
local Transport=nil
|
||||||
if mission.NcarriersMin then
|
if mission.NcarriersMin then
|
||||||
local Legions=mission.transportLegions or {self}
|
local Legions=mission.transportLegions or {self}
|
||||||
|
|
||||||
TransportAvail, Transport=self:AssignAssetsForTransport(Legions, assets, mission.NcarriersMin, mission.NcarriersMax, mission.transportDeployZone, mission.transportDisembarkZone)
|
TransportAvail, Transport=self:AssignAssetsForTransport(Legions, assets, mission.NcarriersMin, mission.NcarriersMax, mission.transportDeployZone, mission.transportDisembarkZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -744,6 +750,10 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
|
|||||||
asset.missionTask=Mission.missionTask
|
asset.missionTask=Mission.missionTask
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Mission.type==AUFTRAG.Type.ALERT5 then
|
||||||
|
asset.takeoffType=COORDINATE.WaypointType.TakeOffParking
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Special for reloading brigade units
|
-- Special for reloading brigade units
|
||||||
@ -882,7 +892,18 @@ function LEGION:onafterTransportCancel(From, Event, To, Transport)
|
|||||||
local cargos=Transport:GetCargoOpsGroups(false)
|
local cargos=Transport:GetCargoOpsGroups(false)
|
||||||
for _,_cargo in pairs(cargos) do
|
for _,_cargo in pairs(cargos) do
|
||||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
||||||
|
|
||||||
|
-- Remover my lift.
|
||||||
cargo:_DelMyLift(Transport)
|
cargo:_DelMyLift(Transport)
|
||||||
|
|
||||||
|
-- Legion of cargo group
|
||||||
|
local legion=cargo.legion
|
||||||
|
|
||||||
|
-- Add asset back to legion.
|
||||||
|
if legion then
|
||||||
|
legion:T(self.lid..string.format("Adding cargo group %s back to legion", cargo:GetName()))
|
||||||
|
legion:__AddAsset(0.1, cargo.group, 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove asset from mission.
|
-- Remove asset from mission.
|
||||||
@ -993,7 +1014,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
|||||||
|
|
||||||
-- Debug text.
|
-- Debug text.
|
||||||
local text=string.format("New asset %s with assignment %s and request assignment %s", asset.spawngroupname, tostring(asset.assignment), tostring(assignment))
|
local text=string.format("New asset %s with assignment %s and request assignment %s", asset.spawngroupname, tostring(asset.assignment), tostring(assignment))
|
||||||
self:T3(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Get cohort.
|
-- Get cohort.
|
||||||
local cohort=self:_GetCohort(asset.assignment)
|
local cohort=self:_GetCohort(asset.assignment)
|
||||||
@ -1010,7 +1031,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
|||||||
local nunits=#asset.template.units
|
local nunits=#asset.template.units
|
||||||
|
|
||||||
-- Debug text.
|
-- Debug text.
|
||||||
local text=string.format("Adding asset to squadron %s: assignment=%s, type=%s, attribute=%s, nunits=%d %s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping))
|
local text=string.format("Adding asset to squadron %s: assignment=%s, type=%s, attribute=%s, nunits=%d ngroup=%s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping))
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Adjust number of elements in the group.
|
-- Adjust number of elements in the group.
|
||||||
@ -1019,6 +1040,10 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
|||||||
|
|
||||||
local N=math.max(#template.units, cohort.ngrouping)
|
local N=math.max(#template.units, cohort.ngrouping)
|
||||||
|
|
||||||
|
-- We need to recalc the total weight and cargo bay.
|
||||||
|
asset.weight=0
|
||||||
|
asset.cargobaytot=0
|
||||||
|
|
||||||
-- Handle units.
|
-- Handle units.
|
||||||
for i=1,N do
|
for i=1,N do
|
||||||
|
|
||||||
@ -1028,15 +1053,28 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
|||||||
-- If grouping is larger than units present, copy first unit.
|
-- If grouping is larger than units present, copy first unit.
|
||||||
if i>nunits then
|
if i>nunits then
|
||||||
table.insert(template.units, UTILS.DeepCopy(template.units[1]))
|
table.insert(template.units, UTILS.DeepCopy(template.units[1]))
|
||||||
|
asset.cargobaytot=asset.cargobaytot+asset.cargobay[1]
|
||||||
|
asset.weight=asset.weight+asset.weights[1]
|
||||||
|
template.units[i].x=template.units[1].x+5*(i-nunits)
|
||||||
|
template.units[i].y=template.units[1].y+5*(i-nunits)
|
||||||
|
else
|
||||||
|
if i<=cohort.ngrouping then
|
||||||
|
asset.weight=asset.weight+asset.weights[i]
|
||||||
|
asset.cargobaytot=asset.cargobaytot+asset.cargobay[i]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove units if original template contains more than in grouping.
|
-- Remove units if original template contains more than in grouping.
|
||||||
if cohort.ngrouping<nunits and i>nunits then
|
if i>cohort.ngrouping then
|
||||||
unit=nil
|
template.units[i]=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set number of units.
|
||||||
asset.nunits=cohort.ngrouping
|
asset.nunits=cohort.ngrouping
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("After regrouping: Nunits=%d, weight=%.1f cargobaytot=%.1f kg", #asset.template.units, asset.weight, asset.cargobaytot))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set takeoff type.
|
-- Set takeoff type.
|
||||||
@ -1061,6 +1099,11 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
|||||||
-- Asset is returned to the COHORT
|
-- Asset is returned to the COHORT
|
||||||
---
|
---
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Asset returned to legion ==> calling LegionAssetReturned event"))
|
||||||
|
|
||||||
|
-- Set takeoff type in case it was overwritten for an ALERT5 mission.
|
||||||
|
asset.takeoffType=cohort.takeoffType
|
||||||
|
|
||||||
-- Trigger event.
|
-- Trigger event.
|
||||||
self:LegionAssetReturned(cohort, asset)
|
self:LegionAssetReturned(cohort, asset)
|
||||||
|
|
||||||
@ -1078,7 +1121,7 @@ end
|
|||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||||
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
|
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
self:I(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
||||||
|
|
||||||
-- Stop flightgroup.
|
-- Stop flightgroup.
|
||||||
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
|
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
|
||||||
@ -1809,7 +1852,7 @@ function LEGION:RecruitAssetsForMission(Mission)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Recuit assets.
|
-- Recuit assets.
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem)
|
||||||
|
|
||||||
return recruited, assets, legions
|
return recruited, assets, legions
|
||||||
end
|
end
|
||||||
@ -1826,17 +1869,20 @@ function LEGION:RecruitAssetsForTransport(Transport)
|
|||||||
local cargoOpsGroups=Transport:GetCargoOpsGroups(false)
|
local cargoOpsGroups=Transport:GetCargoOpsGroups(false)
|
||||||
|
|
||||||
local weightGroup=0
|
local weightGroup=0
|
||||||
|
local TotalWeight=nil
|
||||||
|
|
||||||
-- At least one group should be spawned.
|
-- At least one group should be spawned.
|
||||||
if #cargoOpsGroups>0 then
|
if #cargoOpsGroups>0 then
|
||||||
|
|
||||||
-- Calculate the max weight so we know which cohorts can provide carriers.
|
-- Calculate the max weight so we know which cohorts can provide carriers.
|
||||||
|
TotalWeight=0
|
||||||
for _,_opsgroup in pairs(cargoOpsGroups) do
|
for _,_opsgroup in pairs(cargoOpsGroups) do
|
||||||
local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP
|
local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP
|
||||||
local weight=opsgroup:GetWeightTotal()
|
local weight=opsgroup:GetWeightTotal()
|
||||||
if weight>weightGroup then
|
if weight>weightGroup then
|
||||||
weightGroup=weight
|
weightGroup=weight
|
||||||
end
|
end
|
||||||
|
TotalWeight=TotalWeight+weight
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- No cargo groups!
|
-- No cargo groups!
|
||||||
@ -1854,7 +1900,7 @@ function LEGION:RecruitAssetsForTransport(Transport)
|
|||||||
|
|
||||||
|
|
||||||
-- Recruit assets and legions.
|
-- Recruit assets and legions.
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(self.cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, weightGroup)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(self.cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, weightGroup, TotalWeight)
|
||||||
|
|
||||||
return recruited, assets, legions
|
return recruited, assets, legions
|
||||||
end
|
end
|
||||||
@ -1915,12 +1961,13 @@ end
|
|||||||
-- @param #number RangeMax Max range in meters.
|
-- @param #number RangeMax Max range in meters.
|
||||||
-- @param #number RefuelSystem Refuelsystem.
|
-- @param #number RefuelSystem Refuelsystem.
|
||||||
-- @param #number CargoWeight Cargo weight for recruiting transport carriers.
|
-- @param #number CargoWeight Cargo weight for recruiting transport carriers.
|
||||||
|
-- @param #number TotalWeight Total cargo weight in kg.
|
||||||
-- @param #table Categories Group categories.
|
-- @param #table Categories Group categories.
|
||||||
-- @param #table Attributes Group attributes. See `GROUP.Attribute.`
|
-- @param #table Attributes Group attributes. See `GROUP.Attribute.`
|
||||||
-- @return #boolean If `true` enough assets could be recruited.
|
-- @return #boolean If `true` enough assets could be recruited.
|
||||||
-- @return #table Recruited assets. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
|
-- @return #table Recruited assets. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
|
||||||
-- @return #table Legions of recruited assets.
|
-- @return #table Legions of recruited assets.
|
||||||
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, Categories, Attributes)
|
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, TotalWeight, Categories, Attributes)
|
||||||
|
|
||||||
-- The recruited assets.
|
-- The recruited assets.
|
||||||
local Assets={}
|
local Assets={}
|
||||||
@ -2055,10 +2102,30 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
---
|
---
|
||||||
|
|
||||||
-- Add assets to mission.
|
-- Add assets to mission.
|
||||||
|
local cargobay=0
|
||||||
for i=1,Nassets do
|
for i=1,Nassets do
|
||||||
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
asset.isReserved=true
|
asset.isReserved=true
|
||||||
|
|
||||||
Legions[asset.legion.alias]=asset.legion
|
Legions[asset.legion.alias]=asset.legion
|
||||||
|
|
||||||
|
if TotalWeight then
|
||||||
|
|
||||||
|
-- Number of
|
||||||
|
local N=math.floor(asset.cargobaytot/asset.nunits / CargoWeight)*asset.nunits
|
||||||
|
--env.info(string.format("cargobaytot=%d, cargoweight=%d ==> N=%d", asset.cargobaytot, CargoWeight, N))
|
||||||
|
|
||||||
|
cargobay=cargobay + N*CargoWeight
|
||||||
|
|
||||||
|
if cargobay>=TotalWeight then
|
||||||
|
--env.info(string.format("FF found enough assets to transport all cargo! N=%d [%d], cargobay=%.1f >= %.1f kg total weight", i, Nassets, cargobay, TotalWeight))
|
||||||
|
Nassets=i
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Return payloads of not needed assets.
|
-- Return payloads of not needed assets.
|
||||||
@ -2153,7 +2220,7 @@ function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Recruit escort asset for the mission asset.
|
-- Recruit escort asset for the mission asset.
|
||||||
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, Categories)
|
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, nil, Categories)
|
||||||
|
|
||||||
if Erecruited then
|
if Erecruited then
|
||||||
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets, ecategory=asset.category, TargetTypes=TargetTypes}
|
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets, ecategory=asset.category, TargetTypes=TargetTypes}
|
||||||
@ -2264,13 +2331,14 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Get all legions and heaviest cargo group weight
|
-- Get all legions and heaviest cargo group weight
|
||||||
local CargoLegions={} ; local CargoWeight=nil
|
local CargoLegions={} ; local CargoWeight=nil ; local TotalWeight=0
|
||||||
for _,_asset in pairs(CargoAssets) do
|
for _,_asset in pairs(CargoAssets) do
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
CargoLegions[asset.legion.alias]=asset.legion
|
CargoLegions[asset.legion.alias]=asset.legion
|
||||||
if CargoWeight==nil or asset.weight>CargoWeight then
|
if CargoWeight==nil or asset.weight>CargoWeight then
|
||||||
CargoWeight=asset.weight
|
CargoWeight=asset.weight
|
||||||
end
|
end
|
||||||
|
TotalWeight=TotalWeight+asset.weight
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Target is the deploy zone.
|
-- Target is the deploy zone.
|
||||||
@ -2278,7 +2346,7 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca
|
|||||||
|
|
||||||
-- Recruit assets and legions.
|
-- Recruit assets and legions.
|
||||||
local TransportAvail, CarrierAssets, CarrierLegions=
|
local TransportAvail, CarrierAssets, CarrierLegions=
|
||||||
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NcarriersMin, NcarriersMax, TargetVec2, nil, nil, nil, CargoWeight, Categories, Attributes)
|
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NcarriersMin, NcarriersMax, TargetVec2, nil, nil, nil, CargoWeight, TotalWeight, Categories, Attributes)
|
||||||
|
|
||||||
if TransportAvail then
|
if TransportAvail then
|
||||||
|
|
||||||
@ -2397,11 +2465,33 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
|
|||||||
score=score-distance
|
score=score-distance
|
||||||
|
|
||||||
-- Intercepts need to be carried out quickly. We prefer spawned assets.
|
-- Intercepts need to be carried out quickly. We prefer spawned assets.
|
||||||
--if MissionType==AUFTRAG.Type.INTERCEPT then
|
if asset.spawned and asset.flightgroup and asset.flightgroup:IsAlive() then
|
||||||
if asset.spawned then
|
|
||||||
|
local currmission=asset.flightgroup:GetMissionCurrent()
|
||||||
|
|
||||||
|
if currmission then
|
||||||
|
|
||||||
|
if currmission.type==AUFTRAG.Type.ALERT5 and currmission.alert5MissionType==MissionType then
|
||||||
|
-- Prefer assets that are on ALERT5 for this mission type.
|
||||||
|
score=score+25
|
||||||
|
elseif currmission==AUFTRAG.Type.GCICAP and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||||
|
-- Prefer assets that are on GCICAP to perform INTERCEPTS
|
||||||
score=score+25
|
score=score+25
|
||||||
end
|
end
|
||||||
--end
|
end
|
||||||
|
|
||||||
|
if MissionType==AUFTRAG.Type.OPSTRANSPORT or MissionType==AUFTRAG.Type.AMMOSUPPLY or MissionType==AUFTRAG.Type.AWACS or MissionType==AUFTRAG.Type.FUELSUPPLY or MissionType==AUFTRAG.Type.TANKER then
|
||||||
|
-- TODO: need to check for missions that do not require ammo like transport, recon, awacs, tanker etc.
|
||||||
|
-- We better take a fresh asset. Sometimes spawned assets to something else, which is difficult to check.
|
||||||
|
score=score-10
|
||||||
|
else
|
||||||
|
-- Combat mission.
|
||||||
|
if asset.flightgroup:IsOutOfAmmo() then
|
||||||
|
-- Assets that are out of ammo are not considered.
|
||||||
|
score=score-1000
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- TRANSPORT specific.
|
-- TRANSPORT specific.
|
||||||
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
||||||
|
|||||||
@ -90,7 +90,7 @@ NAVYGROUP = {
|
|||||||
|
|
||||||
--- NavyGroup version.
|
--- NavyGroup version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
NAVYGROUP.version="0.7.0"
|
NAVYGROUP.version="0.7.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -761,6 +761,12 @@ function NAVYGROUP:Status(From, Event, To)
|
|||||||
-- Check into wind queue.
|
-- Check into wind queue.
|
||||||
self:_CheckTurnsIntoWind()
|
self:_CheckTurnsIntoWind()
|
||||||
|
|
||||||
|
-- Check ammo status.
|
||||||
|
self:_CheckAmmoStatus()
|
||||||
|
|
||||||
|
-- Check damage of elements and group.
|
||||||
|
self:_CheckDamage()
|
||||||
|
|
||||||
-- Check if group got stuck.
|
-- Check if group got stuck.
|
||||||
self:_CheckStuck()
|
self:_CheckStuck()
|
||||||
|
|
||||||
@ -775,6 +781,9 @@ function NAVYGROUP:Status(From, Event, To)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Check damage of elements and group.
|
||||||
|
self:_CheckDamage()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Group exists but can also be inactive.
|
-- Group exists but can also be inactive.
|
||||||
@ -1431,6 +1440,8 @@ function NAVYGROUP:_UpdateEngageTarget()
|
|||||||
-- Get current position vector.
|
-- Get current position vector.
|
||||||
local vec3=self.engage.Target:GetVec3()
|
local vec3=self.engage.Target:GetVec3()
|
||||||
|
|
||||||
|
if vec3 then
|
||||||
|
|
||||||
-- Distance to last known position of target.
|
-- Distance to last known position of target.
|
||||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||||
|
|
||||||
@ -1460,7 +1471,14 @@ function NAVYGROUP:_UpdateEngageTarget()
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Target not alive any more == Disengage.
|
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||||
|
self:Disengage()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Target not alive any more ==> Disengage.
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@ -466,7 +466,7 @@ OPSGROUP.CargoStatus={
|
|||||||
|
|
||||||
--- OpsGroup version.
|
--- OpsGroup version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
OPSGROUP.version="0.7.5"
|
OPSGROUP.version="0.7.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -542,6 +542,9 @@ function OPSGROUP:New(group)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set gen attribute.
|
||||||
|
self.attribute=self.group:GetAttribute()
|
||||||
|
|
||||||
local units=self.group:GetUnits()
|
local units=self.group:GetUnits()
|
||||||
|
|
||||||
if units then
|
if units then
|
||||||
@ -864,6 +867,12 @@ function OPSGROUP:GetLifePoints(Element)
|
|||||||
return life, life0
|
return life, life0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get generalized attribute.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @return #string Generalized attribute.
|
||||||
|
function OPSGROUP:GetAttribute()
|
||||||
|
return self.attribute
|
||||||
|
end
|
||||||
|
|
||||||
--- Set verbosity level.
|
--- Set verbosity level.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
@ -879,6 +888,7 @@ end
|
|||||||
-- @param Ops.Legion#LEGION Legion The Legion.
|
-- @param Ops.Legion#LEGION Legion The Legion.
|
||||||
-- @return #OPSGROUP self
|
-- @return #OPSGROUP self
|
||||||
function OPSGROUP:_SetLegion(Legion)
|
function OPSGROUP:_SetLegion(Legion)
|
||||||
|
self:T2(self.lid..string.format("Adding opsgroup to legion %s", Legion.alias))
|
||||||
self.legion=Legion
|
self.legion=Legion
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1609,13 +1619,6 @@ function OPSGROUP:Despawn(Delay, NoEventRemoveUnit)
|
|||||||
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.Despawn, self, 0, NoEventRemoveUnit)
|
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.Despawn, self, 0, NoEventRemoveUnit)
|
||||||
else
|
else
|
||||||
|
|
||||||
if self.legion and not NoEventRemoveUnit then
|
|
||||||
-- Add asset back in 10 seconds.
|
|
||||||
self:T(self.lid..string.format("Despawning Group by adding asset to LEGION!"))
|
|
||||||
self.legion:AddAsset(self.group, 1)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Despawning Group!"))
|
self:T(self.lid..string.format("Despawning Group!"))
|
||||||
|
|
||||||
@ -1647,6 +1650,30 @@ function OPSGROUP:Despawn(Delay, NoEventRemoveUnit)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return group back to the legion it belongs to.
|
||||||
|
-- Group is despawned and added back to the stock.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #number Delay Delay in seconds before the group will be despawned. Default immediately
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:ReturnToLegion(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.ReturnToLegion, self)
|
||||||
|
else
|
||||||
|
|
||||||
|
if self.legion then
|
||||||
|
-- Add asset back.
|
||||||
|
self:T(self.lid..string.format("Adding asset back to LEGION"))
|
||||||
|
self.legion:AddAsset(self.group, 1)
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("ERROR: Group does not belong to a LEGION!"))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Destroy a unit of the group. A *Unit Lost* for aircraft or *Dead* event for ground/naval units is generated.
|
--- Destroy a unit of the group. A *Unit Lost* for aircraft or *Dead* event for ground/naval units is generated.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string UnitName Name of the unit which should be destroyed.
|
-- @param #string UnitName Name of the unit which should be destroyed.
|
||||||
@ -1671,6 +1698,9 @@ function OPSGROUP:DestroyUnit(UnitName, Delay)
|
|||||||
self:CreateEventDead(EventTime, unit)
|
self:CreateEventDead(EventTime, unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Despawn unit.
|
||||||
|
unit:destroy()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -2618,6 +2648,17 @@ function OPSGROUP:GetWaypointCurrent()
|
|||||||
return self.waypoints[self.currentwp]
|
return self.waypoints[self.currentwp]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get current waypoint UID.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @return #number Current waypoint UID.
|
||||||
|
function OPSGROUP:GetWaypointCurrentUID()
|
||||||
|
local wp=self:GetWaypointCurrent()
|
||||||
|
if wp then
|
||||||
|
return wp.uid
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Get coordinate of next waypoint of the group.
|
--- Get coordinate of next waypoint of the group.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #boolean cyclic If true, return first waypoint if last waypoint was reached.
|
-- @param #boolean cyclic If true, return first waypoint if last waypoint was reached.
|
||||||
@ -3574,8 +3615,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
--Coordinate:MarkToAll("Random Patrol Zone Coordinate")
|
--Coordinate:MarkToAll("Random Patrol Zone Coordinate")
|
||||||
|
|
||||||
-- Speed and altitude.
|
-- Speed and altitude.
|
||||||
local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
local Speed=Task.dcstask.params.speed and UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||||
--local Speed=UTILS.KmphToKnots(Task.dcstask.params.speed or self.speedCruise)
|
|
||||||
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
||||||
|
|
||||||
local currUID=self:GetWaypointCurrent().uid
|
local currUID=self:GetWaypointCurrent().uid
|
||||||
@ -3585,7 +3625,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
if self.isFlightgroup then
|
if self.isFlightgroup then
|
||||||
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||||
elseif self.isArmygroup then
|
elseif self.isArmygroup then
|
||||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation)
|
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Task.dcstask.params.formation)
|
||||||
elseif self.isNavygroup then
|
elseif self.isNavygroup then
|
||||||
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||||
end
|
end
|
||||||
@ -3612,7 +3652,6 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
|
|
||||||
-- Speed and altitude.
|
-- Speed and altitude.
|
||||||
local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||||
--local Speed=UTILS.KmphToKnots(Task.dcstask.params.speed or self.speedCruise)
|
|
||||||
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
||||||
|
|
||||||
--Coordinate:MarkToAll("Recon Waypoint Execute")
|
--Coordinate:MarkToAll("Recon Waypoint Execute")
|
||||||
@ -3673,7 +3712,6 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
|||||||
|
|
||||||
-- BARRAGE is special!
|
-- BARRAGE is special!
|
||||||
if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
||||||
env.info("FF Barrage")
|
|
||||||
local vec2=self:GetVec2()
|
local vec2=self:GetVec2()
|
||||||
local param=Task.dcstask.params
|
local param=Task.dcstask.params
|
||||||
local heading=param.heading or math.random(1, 360)
|
local heading=param.heading or math.random(1, 360)
|
||||||
@ -4230,7 +4268,7 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
|
|||||||
-- IMMOBILE Group
|
-- IMMOBILE Group
|
||||||
---
|
---
|
||||||
|
|
||||||
env.info("FF Immobile GROUP")
|
--env.info("FF Immobile GROUP")
|
||||||
|
|
||||||
-- Add waypoint task. UpdateRoute is called inside.
|
-- Add waypoint task. UpdateRoute is called inside.
|
||||||
local Clock=Mission.Tpush and UTILS.SecondsToClock(Mission.Tpush) or 5
|
local Clock=Mission.Tpush and UTILS.SecondsToClock(Mission.Tpush) or 5
|
||||||
@ -4581,12 +4619,21 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- Refresh DCS task with the known controllable.
|
-- Refresh DCS task with the known controllable.
|
||||||
mission.DCStask=mission:GetDCSMissionTask(self.group)
|
mission.DCStask=mission:GetDCSMissionTask(self.group)
|
||||||
|
|
||||||
|
-- Create a pickup zone around the pickup coordinate. The troops will go to a random point inside the zone.
|
||||||
|
-- This is necessary so the helos do not try to land at the exact same location where the troops wait.
|
||||||
|
local pradius=mission.transportPickupRadius
|
||||||
|
local pickupZone=ZONE_RADIUS:New("Pickup Zone", mission.transportPickup:GetVec2(), pradius)
|
||||||
|
|
||||||
-- Add task to embark for the troops.
|
-- Add task to embark for the troops.
|
||||||
for _,_group in pairs(mission.transportGroupSet.Set) do
|
for _,_group in pairs(mission.transportGroupSet.Set) do
|
||||||
local group=_group --Wrapper.Group#GROUP
|
local group=_group --Wrapper.Group#GROUP
|
||||||
|
|
||||||
if group and group:IsAlive() then
|
if group and group:IsAlive() then
|
||||||
local DCSTask=group:TaskEmbarkToTransport(mission.transportPickup, 500)
|
-- Get random coordinate inside the zone.
|
||||||
|
local pcoord=pickupZone:GetRandomCoordinate(20, pradius, {land.SurfaceType.LAND, land.SurfaceType.ROAD})
|
||||||
|
|
||||||
|
-- Let the troops embark the transport.
|
||||||
|
local DCSTask=group:TaskEmbarkToTransport(pcoord, pradius)
|
||||||
group:SetTask(DCSTask, 5)
|
group:SetTask(DCSTask, 5)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -4901,7 +4948,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
|||||||
local Coordinate=zone:GetRandomCoordinate(nil, nil, surfacetypes)
|
local Coordinate=zone:GetRandomCoordinate(nil, nil, surfacetypes)
|
||||||
|
|
||||||
-- Speed and altitude.
|
-- Speed and altitude.
|
||||||
local Speed=UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
local Speed=task.dcstask.params.speed and UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||||
-- local Speed=UTILS.KmphToKnots(speed or self.speedCruise)
|
-- local Speed=UTILS.KmphToKnots(speed or self.speedCruise)
|
||||||
local Altitude=UTILS.MetersToFeet(task.dcstask.params.altitude or self.altitudeCruise)
|
local Altitude=UTILS.MetersToFeet(task.dcstask.params.altitude or self.altitudeCruise)
|
||||||
|
|
||||||
@ -4911,7 +4958,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
|||||||
if self.isFlightgroup then
|
if self.isFlightgroup then
|
||||||
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||||
elseif self.isArmygroup then
|
elseif self.isArmygroup then
|
||||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation)
|
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, task.dcstask.params.formation)
|
||||||
elseif self.isNavygroup then
|
elseif self.isNavygroup then
|
||||||
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||||
end
|
end
|
||||||
@ -4938,8 +4985,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
|||||||
local Coordinate=zone:GetRandomCoordinate()
|
local Coordinate=zone:GetRandomCoordinate()
|
||||||
|
|
||||||
-- Speed and altitude.
|
-- Speed and altitude.
|
||||||
local Speed=UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
local Speed=task.dcstask.params.speed and UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||||
--local Speed=UTILS.KmphToKnots(task.dcstask.params.speed or self.speedCruise)
|
|
||||||
local Altitude=task.dcstask.params.altitude and UTILS.MetersToFeet(task.dcstask.params.altitude) or nil
|
local Altitude=task.dcstask.params.altitude and UTILS.MetersToFeet(task.dcstask.params.altitude) or nil
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
@ -5759,6 +5805,38 @@ function OPSGROUP:onafterElementInUtero(From, Event, To, Element)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after "ElementDamaged" event.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #OPSGROUP.Element Element The flight group element.
|
||||||
|
function OPSGROUP:onafterElementDamaged(From, Event, To, Element)
|
||||||
|
self:T(self.lid..string.format("Element damaged %s", Element.name))
|
||||||
|
|
||||||
|
if Element and (Element.status~=OPSGROUP.ElementStatus.DEAD and Element.status~=OPSGROUP.ElementStatus.INUTERO) then
|
||||||
|
|
||||||
|
local lifepoints=0
|
||||||
|
|
||||||
|
if Element.DCSunit and Element.DCSunit:isExist() then
|
||||||
|
|
||||||
|
-- Get life of unit
|
||||||
|
lifepoints=Element.DCSunit:getLife()
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
self:T(self.lid..string.format("Element life %s: %.2f/%.2f", Element.name, lifepoints, Element.life0))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if lifepoints<=1.0 then
|
||||||
|
self:T(self.lid..string.format("Element %s life %.2f <= 1.0 ==> Destroyed!", Element.name, lifepoints))
|
||||||
|
self:ElementDestroyed(Element)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- On after "ElementDestroyed" event.
|
--- On after "ElementDestroyed" event.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -5793,7 +5871,7 @@ end
|
|||||||
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
self:I(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
||||||
|
|
||||||
-- Set element status.
|
-- Set element status.
|
||||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||||
@ -5890,6 +5968,80 @@ function OPSGROUP:onafterRespawn(From, Event, To, Template)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Teleport the group to a different location.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where the group is teleported to.
|
||||||
|
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:Teleport(Coordinate, Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, OPSGROUP.Teleport, self, Coordinate)
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:T(self.lid.."FF Teleporting...")
|
||||||
|
--Coordinate:MarkToAll("Teleport "..self.groupname)
|
||||||
|
|
||||||
|
-- Check if we have a mission running.
|
||||||
|
if self.currentmission>0 then
|
||||||
|
self:T(self.lid.."Pausing current mission")
|
||||||
|
self:PauseMission()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get copy of template.
|
||||||
|
local Template=UTILS.DeepCopy(self.template) --DCS#Template
|
||||||
|
|
||||||
|
-- Template units.
|
||||||
|
local units=Template.units
|
||||||
|
|
||||||
|
-- Table with teleported vectors.
|
||||||
|
local d={}
|
||||||
|
for i=1,#units do
|
||||||
|
local unit=units[i]
|
||||||
|
d[i]={x=Coordinate.x+(units[i].x-units[1].x), y=Coordinate.z+units[i].y-units[1].y}
|
||||||
|
--COORDINATE:NewFromVec2(d[i]):MarkToAll(unit.name.." teleported")
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=#units,1,-1 do
|
||||||
|
local unit=units[i]
|
||||||
|
|
||||||
|
-- Get element.
|
||||||
|
local element=self:GetElementByName(unit.name)
|
||||||
|
|
||||||
|
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
|
|
||||||
|
-- No parking.
|
||||||
|
unit.parking=nil
|
||||||
|
unit.parking_id=nil
|
||||||
|
|
||||||
|
-- Current position.
|
||||||
|
local vec3=element.unit:GetVec3()
|
||||||
|
|
||||||
|
-- Current heading.
|
||||||
|
local heading=element.unit:GetHeading()
|
||||||
|
|
||||||
|
-- Set new x,y.
|
||||||
|
unit.x=d[i].x
|
||||||
|
unit.y=d[i].y
|
||||||
|
|
||||||
|
-- Set altitude.
|
||||||
|
unit.alt=Coordinate.y
|
||||||
|
|
||||||
|
-- Set heading.
|
||||||
|
unit.heading=math.rad(heading)
|
||||||
|
unit.psi=-unit.heading
|
||||||
|
else
|
||||||
|
table.remove(units, i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Respawn from new template.
|
||||||
|
self:_Respawn(0, Template, true)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Respawn the group.
|
--- Respawn the group.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
||||||
@ -5905,58 +6057,60 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:T2(self.lid.."FF _Respawn")
|
self:T2(self.lid.."FF _Respawn")
|
||||||
|
|
||||||
-- Given template or get old.
|
-- Given template or get copy of old.
|
||||||
Template=Template or self:_GetTemplate(true)
|
Template=Template or self:_GetTemplate(true)
|
||||||
|
|
||||||
|
-- Number of destroyed units.
|
||||||
|
self.Ndestroyed=0
|
||||||
|
|
||||||
|
-- Check if group is currently alive.
|
||||||
if self:IsAlive() then
|
if self:IsAlive() then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Group is ALIVE
|
-- Group is ALIVE
|
||||||
---
|
---
|
||||||
|
|
||||||
--[[
|
-- Template units.
|
||||||
|
|
||||||
-- Get units.
|
|
||||||
local units=self.group:GetUnits()
|
|
||||||
|
|
||||||
-- Loop over template units.
|
|
||||||
for UnitID, Unit in pairs(Template.units) do
|
|
||||||
|
|
||||||
for _,_unit in pairs(units) do
|
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
if unit:GetName()==Unit.name then
|
|
||||||
local vec3=unit:GetVec3()
|
|
||||||
local heading=unit:GetHeading()
|
|
||||||
Unit.x=vec3.x
|
|
||||||
Unit.y=vec3.z
|
|
||||||
Unit.alt=vec3.y
|
|
||||||
Unit.heading=math.rad(heading)
|
|
||||||
Unit.psi=-Unit.heading
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
local units=Template.units
|
local units=Template.units
|
||||||
|
|
||||||
for i=#units,1,-1 do
|
for i=#units,1,-1 do
|
||||||
local unit=units[i]
|
local unit=units[i]
|
||||||
|
|
||||||
|
-- Get the element.
|
||||||
local element=self:GetElementByName(unit.name)
|
local element=self:GetElementByName(unit.name)
|
||||||
|
|
||||||
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
|
|
||||||
|
if not Reset then
|
||||||
|
|
||||||
|
-- Parking ID.
|
||||||
unit.parking=element.parking and element.parking.TerminalID or unit.parking
|
unit.parking=element.parking and element.parking.TerminalID or unit.parking
|
||||||
unit.parking_id=nil
|
unit.parking_id=nil
|
||||||
|
|
||||||
|
-- Get current position vector.
|
||||||
local vec3=element.unit:GetVec3()
|
local vec3=element.unit:GetVec3()
|
||||||
|
|
||||||
|
-- Get heading.
|
||||||
local heading=element.unit:GetHeading()
|
local heading=element.unit:GetHeading()
|
||||||
|
|
||||||
|
-- Set unit position.
|
||||||
unit.x=vec3.x
|
unit.x=vec3.x
|
||||||
unit.y=vec3.z
|
unit.y=vec3.z
|
||||||
unit.alt=vec3.y
|
unit.alt=vec3.y
|
||||||
|
|
||||||
|
-- Set heading in rad.
|
||||||
unit.heading=math.rad(heading)
|
unit.heading=math.rad(heading)
|
||||||
unit.psi=-unit.heading
|
unit.psi=-unit.heading
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- Element is dead. Remove from template.
|
||||||
table.remove(units, i)
|
table.remove(units, i)
|
||||||
|
|
||||||
|
self.Ndestroyed=self.Ndestroyed+1
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -5967,7 +6121,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
else
|
else
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Group is DESPAWNED
|
-- Group is NOT ALIVE
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Ensure elements in utero.
|
-- Ensure elements in utero.
|
||||||
@ -5998,7 +6152,6 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
|
|
||||||
|
|
||||||
self.groupinitialized=false
|
self.groupinitialized=false
|
||||||
self.Ndestroyed=0
|
|
||||||
self.wpcounter=1
|
self.wpcounter=1
|
||||||
self.currentwp=1
|
self.currentwp=1
|
||||||
|
|
||||||
@ -6074,6 +6227,19 @@ function OPSGROUP:onbeforeDead(From, Event, To)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Cancel all missions in mission queue.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
function OPSGROUP:CancelAllMissions()
|
||||||
|
|
||||||
|
-- Cancel all missions.
|
||||||
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
self:T(self.lid.."Cancelling mission "..tostring(mission:GetName()))
|
||||||
|
self:MissionCancel(mission)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- On after "Dead" event.
|
--- On after "Dead" event.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -6131,12 +6297,31 @@ function OPSGROUP:onafterDead(From, Event, To)
|
|||||||
-- All elements were destroyed ==> Asset group is gone.
|
-- All elements were destroyed ==> Asset group is gone.
|
||||||
self.cohort:DelGroup(self.groupname)
|
self.cohort:DelGroup(self.groupname)
|
||||||
end
|
end
|
||||||
|
if self.legion then
|
||||||
|
--self.legion:Get
|
||||||
|
--self.legion:AssetDead()
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Not all assets were destroyed (despawn) ==> Add asset back to legion?
|
-- Not all assets were destroyed (despawn) ==> Add asset back to legion?
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Stop in a sec.
|
if self.legion then
|
||||||
--self:__Stop(-5)
|
if not self:IsInUtero() then
|
||||||
|
|
||||||
|
-- Get asset.
|
||||||
|
local asset=self.legion:GetAssetByName(self.groupname)
|
||||||
|
|
||||||
|
-- Get request.
|
||||||
|
local request=self.legion:GetRequestByID(asset.rid)
|
||||||
|
|
||||||
|
-- Trigger asset dead event.
|
||||||
|
self.legion:AssetDead(asset, request)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stop in 5 sec to give possible respawn attempts a chance.
|
||||||
|
self:__Stop(-5)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On before "Stop" event.
|
--- On before "Stop" event.
|
||||||
@ -6179,6 +6364,11 @@ function OPSGROUP:onafterStop(From, Event, To)
|
|||||||
self.currbase=nil
|
self.currbase=nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
for _,_mission in pairs(self.missionqueue) do
|
||||||
|
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||||
|
self:MissionCancel(mission)
|
||||||
|
end
|
||||||
|
|
||||||
-- Stop check timers.
|
-- Stop check timers.
|
||||||
self.timerCheckZone:Stop()
|
self.timerCheckZone:Stop()
|
||||||
self.timerQueueUpdate:Stop()
|
self.timerQueueUpdate:Stop()
|
||||||
@ -7993,6 +8183,12 @@ end
|
|||||||
-- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier.
|
-- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier.
|
||||||
function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
|
function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
|
||||||
self:T(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName()))
|
self:T(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName()))
|
||||||
|
|
||||||
|
if OpsGroupCargo.legion and OpsGroupCargo:IsInZone(OpsGroupCargo.legion.spawnzone) then
|
||||||
|
self:T(self.lid..string.format("Unloaded group %s returned to legion", OpsGroupCargo:GetName()))
|
||||||
|
OpsGroupCargo:Returned()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -8530,18 +8726,24 @@ function OPSGROUP:_CheckGroupDone(delay)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Group is returning
|
-- Group is returning.
|
||||||
if self:IsReturning() then
|
if self:IsReturning() then
|
||||||
self:T(self.lid.."Returning! Group NOT done...")
|
self:T(self.lid.."Returning! Group NOT done...")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Group is returning
|
-- Group is rearming.
|
||||||
if self:IsRearming() then
|
if self:IsRearming() then
|
||||||
self:T(self.lid.."Rearming! Group NOT done...")
|
self:T(self.lid.."Rearming! Group NOT done...")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Group is retreating.
|
||||||
|
if self:IsRetreating() then
|
||||||
|
self:T(self.lid.."Retreating! Group NOT done...")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Group is waiting. We deny all updates.
|
-- Group is waiting. We deny all updates.
|
||||||
if self:IsWaiting() then
|
if self:IsWaiting() then
|
||||||
-- If group is waiting, we assume that is the way it is meant to be.
|
-- If group is waiting, we assume that is the way it is meant to be.
|
||||||
|
|||||||
@ -57,6 +57,8 @@
|
|||||||
-- @field #table statusLegion Transport status of all assigned LEGIONs.
|
-- @field #table statusLegion Transport status of all assigned LEGIONs.
|
||||||
-- @field #string statusCommander Staus of the COMMANDER.
|
-- @field #string statusCommander Staus of the COMMANDER.
|
||||||
-- @field Ops.Commander#COMMANDER commander Commander of the transport.
|
-- @field Ops.Commander#COMMANDER commander Commander of the transport.
|
||||||
|
-- @field Ops.Chief#CHIEF chief Chief of the transport.
|
||||||
|
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
|
||||||
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
|
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
|
||||||
--
|
--
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
@ -1305,7 +1307,7 @@ function OPSTRANSPORT:GetNcarrier()
|
|||||||
return self.Ncarrier
|
return self.Ncarrier
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add asset to transport.
|
--- Add carrier asset to transport.
|
||||||
-- @param #OPSTRANSPORT self
|
-- @param #OPSTRANSPORT self
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added.
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added.
|
||||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
||||||
@ -1323,7 +1325,7 @@ function OPSTRANSPORT:AddAsset(Asset, TransportZoneCombo)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Delete asset from mission.
|
--- Delete carrier asset from transport.
|
||||||
-- @param #OPSTRANSPORT self
|
-- @param #OPSTRANSPORT self
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed.
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed.
|
||||||
-- @return #OPSTRANSPORT self
|
-- @return #OPSTRANSPORT self
|
||||||
@ -1736,12 +1738,12 @@ function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup)
|
|||||||
-- Increase dead counter.
|
-- Increase dead counter.
|
||||||
self.NcarrierDead=self.NcarrierDead+1
|
self.NcarrierDead=self.NcarrierDead+1
|
||||||
|
|
||||||
|
-- Remove group from carrier list/table.
|
||||||
|
self:_DelCarrier(OpsGroup)
|
||||||
|
|
||||||
if #self.carriers==0 then
|
if #self.carriers==0 then
|
||||||
self:DeadCarrierAll()
|
self:DeadCarrierAll()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove group from carrier list/table.
|
|
||||||
self:_DelCarrier(OpsGroup)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "DeadCarrierAll" event.
|
--- On after "DeadCarrierAll" event.
|
||||||
@ -1750,7 +1752,19 @@ end
|
|||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To)
|
function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To)
|
||||||
self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead! Setting stage to PLANNED if not all cargo was delivered."))
|
self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead!"))
|
||||||
|
|
||||||
|
if self.opszone then
|
||||||
|
|
||||||
|
self:I(self.lid..string.format("Cancelling transport on CHIEF level"))
|
||||||
|
self.chief:TransportCancel(self)
|
||||||
|
|
||||||
|
--for _,_legion in pairs(self.legions) do
|
||||||
|
-- local legion=_legion --Ops.Legion#LEGION
|
||||||
|
-- legion:TransportCancel(self)
|
||||||
|
--end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
-- Check if cargo was delivered.
|
-- Check if cargo was delivered.
|
||||||
self:_CheckDelivered()
|
self:_CheckDelivered()
|
||||||
@ -1759,6 +1773,9 @@ function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To)
|
|||||||
if not self:IsDelivered() then
|
if not self:IsDelivered() then
|
||||||
self:Planned()
|
self:Planned()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "Cancel" event.
|
--- On after "Cancel" event.
|
||||||
|
|||||||
@ -1097,6 +1097,14 @@ function UTILS.VecSubstract(a, b)
|
|||||||
return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z}
|
return {x=a.x-b.x, y=a.y-b.y, z=a.z-b.z}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Calculate the difference between two 2D vectors by substracting the x,y components from each other.
|
||||||
|
-- @param DCS#Vec2 a Vector in 2D with x, y components.
|
||||||
|
-- @param DCS#Vec2 b Vector in 2D with x, y components.
|
||||||
|
-- @return DCS#Vec2 Vector c=a-b with c(i)=a(i)-b(i), i=x,y.
|
||||||
|
function UTILS.Vec2Substract(a, b)
|
||||||
|
return {x=a.x-b.x, y=a.y-b.y}
|
||||||
|
end
|
||||||
|
|
||||||
--- Calculate the total vector of two 3D vectors by adding the x,y,z components of each other.
|
--- Calculate the total vector of two 3D vectors by adding the x,y,z components of each other.
|
||||||
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
||||||
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
||||||
@ -1105,6 +1113,14 @@ function UTILS.VecAdd(a, b)
|
|||||||
return {x=a.x+b.x, y=a.y+b.y, z=a.z+b.z}
|
return {x=a.x+b.x, y=a.y+b.y, z=a.z+b.z}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Calculate the total vector of two 2D vectors by adding the x,y components of each other.
|
||||||
|
-- @param DCS#Vec2 a Vector in 2D with x, y components.
|
||||||
|
-- @param DCS#Vec2 b Vector in 2D with x, y components.
|
||||||
|
-- @return DCS#Vec2 Vector c=a+b with c(i)=a(i)+b(i), i=x,y.
|
||||||
|
function UTILS.Vec2Add(a, b)
|
||||||
|
return {x=a.x+b.x, y=a.y+b.y}
|
||||||
|
end
|
||||||
|
|
||||||
--- Calculate the angle between two 3D vectors.
|
--- Calculate the angle between two 3D vectors.
|
||||||
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
||||||
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
|
||||||
@ -1321,26 +1337,6 @@ function UTILS.GetMissionDayOfYear(Time)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the current date.
|
|
||||||
-- @return #string Mission date in yyyy/mm/dd format.
|
|
||||||
-- @return #number The year anno domini.
|
|
||||||
-- @return #number The month.
|
|
||||||
-- @return #number The day.
|
|
||||||
function UTILS.GetDate()
|
|
||||||
|
|
||||||
-- Mission start date
|
|
||||||
local date, year, month, day=UTILS.GetDCSMissionDate()
|
|
||||||
|
|
||||||
local time=timer.getAbsTime()
|
|
||||||
|
|
||||||
local clock=UTILS.SecondsToClock(time, false)
|
|
||||||
|
|
||||||
local x=tonumber(UTILS.Split(clock, "+")[2])
|
|
||||||
|
|
||||||
local day=day+x
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the magnetic declination of the map.
|
--- Returns the magnetic declination of the map.
|
||||||
-- Returned values for the current maps are:
|
-- Returned values for the current maps are:
|
||||||
--
|
--
|
||||||
@ -1751,6 +1747,11 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
ret_val = true
|
ret_val = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if string.find(type_name, "AH-64D") then
|
||||||
|
BASE:T(unit_name .. " front door(s) are open")
|
||||||
|
ret_val = true -- no doors on this one ;)
|
||||||
|
end
|
||||||
|
|
||||||
if ret_val == false then
|
if ret_val == false then
|
||||||
BASE:T(unit_name .. " all doors are closed")
|
BASE:T(unit_name .. " all doors are closed")
|
||||||
end
|
end
|
||||||
|
|||||||
@ -385,6 +385,16 @@ AIRBASE.TheChannel = {
|
|||||||
-- * AIRBASE.Syria.Beirut_Rafic_Hariri
|
-- * AIRBASE.Syria.Beirut_Rafic_Hariri
|
||||||
-- * AIRBASE.Syria.An_Nasiriyah
|
-- * AIRBASE.Syria.An_Nasiriyah
|
||||||
-- * AIRBASE.Syria.Abu_al_Duhur
|
-- * AIRBASE.Syria.Abu_al_Duhur
|
||||||
|
-- * AIRBASE.Syria.At_Tanf
|
||||||
|
-- * AIRBASE.Syria.H3
|
||||||
|
-- * AIRBASE.Syria.H3_Northwest
|
||||||
|
-- * AIRBASE.Syria.H3_Southwest
|
||||||
|
-- * AIRBASE.Syria.Kharab_Ishk
|
||||||
|
-- * AIRBASE.Syria.Raj_al_Issa_East
|
||||||
|
-- * AIRBASE.Syria.Raj_al_Issa_West
|
||||||
|
-- * AIRBASE.Syria.Ruwayshid
|
||||||
|
-- * AIRBASE.Syria.Sanliurfa
|
||||||
|
-- * AIRBASE.Syria.Tal_Siman
|
||||||
--
|
--
|
||||||
--@field Syria
|
--@field Syria
|
||||||
AIRBASE.Syria={
|
AIRBASE.Syria={
|
||||||
@ -440,10 +450,18 @@ AIRBASE.Syria={
|
|||||||
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
|
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
|
||||||
["An_Nasiriyah"]="An Nasiriyah",
|
["An_Nasiriyah"]="An Nasiriyah",
|
||||||
["Abu_al_Duhur"]="Abu al-Duhur",
|
["Abu_al_Duhur"]="Abu al-Duhur",
|
||||||
|
["At_Tanf"]="At Tanf",
|
||||||
|
["H3"]="H3",
|
||||||
|
["H3_Northwest"]="H3 Northwest",
|
||||||
|
["H3_Southwest"]="H3 Southwest",
|
||||||
|
["Kharab_Ishk"]="Kharab Ishk",
|
||||||
|
["Raj_al_Issa_East"]="Raj al Issa East",
|
||||||
|
["Raj_al_Issa_West"]="Raj al Issa West",
|
||||||
|
["Ruwayshid"]="Ruwayshid",
|
||||||
|
["Sanliurfa"]="Sanliurfa",
|
||||||
|
["Tal_Siman"]="Tal Siman",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Airbases of the Mariana Islands map:
|
--- Airbases of the Mariana Islands map:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.MarianaIslands.Rota_Intl
|
-- * AIRBASE.MarianaIslands.Rota_Intl
|
||||||
|
|||||||
@ -3844,3 +3844,45 @@ function POSITIONABLE:IsSubmarine()
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Sets the controlled group to go at the specified speed in meters per second.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number Speed Speed in meters per second
|
||||||
|
-- @param #boolean Keep (Optional) When set to true, will maintain the speed on passing waypoints. If not present or false, the controlled group will return to the speed as defined by their route.
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetSpeed(Speed, Keep)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
-- Set default if not specified.
|
||||||
|
local speed = Speed or 5
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
if Controller then
|
||||||
|
Controller:setSpeed(speed, Keep)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Sets the controlled aircraft group to fly at the specified altitude in meters.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number Altitude Altitude in meters.
|
||||||
|
-- @param #boolean Keep (Optional) When set to true, will maintain the altitude on passing waypoints. If not present or false, the controlled group will return to the altitude as defined by their route.
|
||||||
|
-- @param #string AltType (Optional) Specifies the altitude type used. If nil, the altitude type of the current waypoint will be used. Accepted values are "BARO" and "RADIO".
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetAltitude(Altitude, Keep, AltType)
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
-- Set default if not specified.
|
||||||
|
local altitude = Altitude or 1000
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
if Controller then
|
||||||
|
if self:IsAir() then
|
||||||
|
Controller:setAltitude(altitude, Keep, AltType)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
@ -765,8 +765,7 @@ end
|
|||||||
|
|
||||||
--- Returns the average velocity Vec3 vector.
|
--- Returns the average velocity Vec3 vector.
|
||||||
-- @param Wrapper.Group#GROUP self
|
-- @param Wrapper.Group#GROUP self
|
||||||
-- @return DCS#Vec3 The velocity Vec3 vector
|
-- @return DCS#Vec3 The velocity Vec3 vector or `#nil` if the GROUP is not existing or alive.
|
||||||
-- @return #nil The GROUP is not existing or alive.
|
|
||||||
function GROUP:GetVelocityVec3()
|
function GROUP:GetVelocityVec3()
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
@ -1009,9 +1008,8 @@ end
|
|||||||
|
|
||||||
--- Returns a random @{DCS#Vec3} vector (point in 3D of the UNIT within the mission) within a range around the first UNIT of the GROUP.
|
--- Returns a random @{DCS#Vec3} vector (point in 3D of the UNIT within the mission) within a range around the first UNIT of the GROUP.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #number Radius
|
-- @param #number Radius Radius in meters.
|
||||||
-- @return DCS#Vec3 The random 3D point vector around the first UNIT of the GROUP.
|
-- @return DCS#Vec3 The random 3D point vector around the first UNIT of the GROUP or #nil The GROUP is invalid or empty.
|
||||||
-- @return #nil The GROUP is invalid or empty
|
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP
|
-- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP
|
||||||
function GROUP:GetRandomVec3(Radius)
|
function GROUP:GetRandomVec3(Radius)
|
||||||
@ -1032,8 +1030,7 @@ end
|
|||||||
|
|
||||||
--- Returns the mean heading of every UNIT in the GROUP in degrees
|
--- Returns the mean heading of every UNIT in the GROUP in degrees
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #number mean heading of the GROUP
|
-- @return #number Mean heading of the GROUP in degrees or #nil The first UNIT is not existing or alive.
|
||||||
-- @return #nil The first UNIT is not existing or alive.
|
|
||||||
function GROUP:GetHeading()
|
function GROUP:GetHeading()
|
||||||
self:F2(self.GroupName)
|
self:F2(self.GroupName)
|
||||||
|
|
||||||
@ -1061,8 +1058,8 @@ end
|
|||||||
--- Return the fuel state and unit reference for the unit with the least
|
--- Return the fuel state and unit reference for the unit with the least
|
||||||
-- amount of fuel in the group.
|
-- amount of fuel in the group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #number The fuel state of the unit with the least amount of fuel
|
-- @return #number The fuel state of the unit with the least amount of fuel.
|
||||||
-- @return #Unit reference to #Unit object for further processing
|
-- @return #Unit reference to #Unit object for further processing.
|
||||||
function GROUP:GetFuelMin()
|
function GROUP:GetFuelMin()
|
||||||
self:F3(self.ControllableName)
|
self:F3(self.ControllableName)
|
||||||
|
|
||||||
|
|||||||
@ -152,7 +152,7 @@ _MARKERID=0
|
|||||||
|
|
||||||
--- Marker class version.
|
--- Marker class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
MARKER.version="0.1.0"
|
MARKER.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -177,7 +177,7 @@ function MARKER:New(Coordinate, Text)
|
|||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
||||||
|
|
||||||
self.coordinate=Coordinate
|
self.coordinate=UTILS.DeepCopy(Coordinate)
|
||||||
|
|
||||||
self.text=Text
|
self.text=Text
|
||||||
|
|
||||||
|
|||||||
@ -1494,7 +1494,7 @@ do -- Cargo
|
|||||||
|
|
||||||
-- Fuel. The descriptor provides the max fuel mass in kg. This needs to be multiplied by the relative fuel amount to calculate the actual fuel mass on board.
|
-- Fuel. The descriptor provides the max fuel mass in kg. This needs to be multiplied by the relative fuel amount to calculate the actual fuel mass on board.
|
||||||
local massFuelMax=Desc.fuelMassMax or 0
|
local massFuelMax=Desc.fuelMassMax or 0
|
||||||
local relFuel=math.max(self:GetFuel() or 1.0, 1.0) -- We take 1.0 as max in case of external fuel tanks.
|
local relFuel=math.min(self:GetFuel() or 1.0, 1.0) -- We take 1.0 as max in case of external fuel tanks.
|
||||||
local massFuel=massFuelMax*relFuel
|
local massFuel=massFuelMax*relFuel
|
||||||
|
|
||||||
-- Number of soldiers according to DCS function
|
-- Number of soldiers according to DCS function
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user