Merge branch 'develop' into FF/Ops

This commit is contained in:
Frank 2021-11-07 18:20:27 +01:00
commit 02724dc26d
25 changed files with 191041 additions and 487 deletions

View File

@ -0,0 +1,24 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
local base = _G
__Moose = {}
__Moose.Include = function( IncludeFile )
if not __Moose.Includes[ IncludeFile ] then
__Moose.Includes[IncludeFile] = IncludeFile
local f = assert( base.loadfile( IncludeFile ) )
if f == nil then
error ("Moose: Could not load Moose file " .. IncludeFile )
else
env.info( "Moose: " .. IncludeFile .. " dynamically loaded." )
return f()
end
end
end
__Moose.Includes = {}
__Moose.Include( 'Scripts/Moose/Modules.lua' )
BASE:TraceOnOff( true )
env.info( '*** MOOSE INCLUDE END *** ' )

File diff suppressed because it is too large Load Diff

View File

@ -207,7 +207,7 @@ end
do -- MENU_BASE
--- @type MENU_BASE
-- @extends Base#BASE
-- @extends Core.Base#BASE
--- Defines the main MENU class where other MENU classes are derived from.
-- This is an abstract class, so don't use it.

View File

@ -310,17 +310,14 @@ do -- SET_BASE
-- @return Core.Set#SET_BASE The set of objects that are in set *B* but **not** in this set *A*.
function SET_BASE:GetSetComplement(SetB)
local complement=SET_BASE:New()
local complement = self:GetSetUnion(SetB)
local intersection = self:GetSetIntersection(SetB)
local union=self:GetSetUnion(SetA, SetB)
for _,Object in pairs(union.Set) do
if SetA:IsIncludeObject(Object) and SetB:IsIncludeObject(Object) then
intersection:Add(intersection)
end
for _,Object in pairs(intersection.Set) do
complement:Remove(Object.ObjectName,true)
end
return intersection
return complement
end

View File

@ -30,6 +30,7 @@
-- * Detect and lase contacts automatically
-- * Targets are lased by threat priority order
-- * Use FSM events to link functionality into your scripts
-- * Set laser codes and smoke colors per Recce unit
-- * Easy set-up
--
-- # 2 Basic usage
@ -46,7 +47,7 @@
--
-- local autolaser = AUTOLASE:New(FoxSet,coalition.side.BLUE,"Wolfpack",Pilotset)
--
-- ## 2.5 Example - Using a fixed laser code for a specific Recce unit:
-- ## 2.5 Example - Using a fixed laser code and color for a specific Recce unit:
--
-- local recce = SPAWN:New("Reaper")
-- :InitDelayOff()
@ -55,6 +56,7 @@
-- local unit = group:GetUnit(1)
-- local name = unit:GetName()
-- autolaser:SetRecceLaserCode(name,1688)
-- autolaser:SetRecceSmokeColor(name,SMOKECOLOR.Red)
-- end
-- )
-- :InitCleanUp(60)
@ -71,7 +73,7 @@
-- @module Functional.Autolase
-- @image Designation.JPG
--
-- Date: Oct 2021
-- Date: 24 Oct 2021
--
--- Class AUTOLASE
-- @type AUTOLASE
@ -107,7 +109,7 @@ AUTOLASE = {
--- AUTOLASE class version.
-- @field #string version
AUTOLASE.version = "0.0.8"
AUTOLASE.version = "0.0.10"
-------------------------------------------------------------------
-- Begin Functional.Autolase.lua
@ -169,6 +171,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.UnitsByThreat = {}
self.RecceNames = {}
self.RecceLaserCode = {}
self.RecceSmokeColor = {}
self.RecceUnitNames= {}
self.maxlasing = 4
self.CurrentLasing = {}
@ -294,13 +297,15 @@ end
-- @param #AUTOLASE self
-- @return #AUTOLASE self
function AUTOLASE:SetPilotMenu()
local pilottable = self.pilotset:GetSetObjects() or {}
for _,_unit in pairs (pilottable) do
local Unit = _unit -- Wrapper.Unit#UNIT
if Unit and Unit:IsAlive() then
local Group = Unit:GetGroup()
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group)
lasemenu:Refresh()
if self.usepilotset then
local pilottable = self.pilotset:GetSetObjects() or {}
for _,_unit in pairs (pilottable) do
local Unit = _unit -- Wrapper.Unit#UNIT
if Unit and Unit:IsAlive() then
local Group = Unit:GetGroup()
local lasemenu = MENU_GROUP_COMMAND:New(Group,"Autolase Status",nil,self.ShowStatus,self,Group)
lasemenu:Refresh()
end
end
end
return self
@ -330,6 +335,20 @@ function AUTOLASE:GetLaserCode(RecceName)
return code
end
--- (Internal) Function to get a smoke color by recce name
-- @param #AUTOLASE self
-- @param #string RecceName Unit(!) name of the Recce
-- @return #AUTOLASE self
function AUTOLASE:GetSmokeColor(RecceName)
local color = self.smokecolor
if self.RecceSmokeColor[RecceName] == nil then
self.RecceSmokeColor[RecceName] = color
else
color = self.RecceLaserCode[RecceName]
end
return color
end
--- (User) Function enable sending messages via SRS.
-- @param #AUTOLASE self
-- @param #boolean OnOff Switch usage on and off
@ -374,6 +393,17 @@ function AUTOLASE:SetRecceLaserCode(RecceName, Code)
return self
end
--- (User) Function to set a specific smoke color for a Recce.
-- @param #AUTOLASE self
-- @param #string RecceName (Unit!) Name of the Recce
-- @param #number Color The color, e.g. SMOKECOLOR.Red, SMOKECOLOR.Green etc
-- @return #AUTOLASE self
function AUTOLASE:SetRecceSmokeColor(RecceName, Color)
local color = Color or self.smokecolor
self.RecceSmokeColor[RecceName] = color
return self
end
--- (User) Function to force laser cooldown and cool down time
-- @param #AUTOLASE self
-- @param #boolean OnOff Switch cool down on (true) or off (false) - defaults to true
@ -812,7 +842,8 @@ function AUTOLASE:onafterMonitor(From, Event, To)
}
if self.smoketargets then
local coord = unit:GetCoordinate()
coord:Smoke(self.smokecolor)
local color = self:GetSmokeColor(reccename)
coord:Smoke(color)
end
self.lasingindex = self.lasingindex + 1
self.CurrentLasing[self.lasingindex] = laserspot

View File

@ -23,7 +23,6 @@
-- @module Functional.FOX
-- @image Functional_FOX.png
--- FOX class.
-- @type FOX
-- @field #string ClassName Name of the class.
@ -47,8 +46,7 @@
-- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec.
-- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec.
-- @field #number dt01 Time step [sec] for missile position updates if distance to target > 1 km and < 5 km. Default 0.1 sec.
-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec.
-- @field #boolean
-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec.
-- @extends Core.Fsm#FSM
--- Fox 3!
@ -1813,4 +1811,4 @@ end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -19,7 +19,7 @@
--
-- @module Functional.Mantis
-- @image Functional.Mantis.jpg
--
-- Date: July 2021
-------------------------------------------------------------------------

View File

@ -284,9 +284,11 @@ function SCORING:New( GameName )
-- Default fratricide penalty level (maximum penalty that can be assigned to a player before he gets kicked).
self:SetFratricide( self.ScaleDestroyPenalty * 3 )
self.penaltyonfratricide = true
-- Default penalty when a player changes coalition.
self:SetCoalitionChangePenalty( self.ScaleDestroyPenalty )
self.penaltyoncoalitionchange = true
self:SetDisplayMessagePrefix()
@ -582,6 +584,23 @@ function SCORING:SetFratricide( Fratricide )
return self
end
--- Decide if Fratricide is leading to penalties (true) or not (fals)
-- @param #SCORING self
-- @param #boolean OnOff Switch for Fratricide
-- @return #SCORING
function SCORING:SwitchFratricide( OnOff )
self.penaltyonfratricide = OnOff
return self
end
--- Decide if Coalition Changes is leading to penalties (true) or not (fals)
-- @param #SCORING self
-- @param #boolean OnOff Switch for Coalition Changes.
-- @return #SCORING
function SCORING:SwitchTreason( OnOff )
self.penaltyoncoalitionchange = OnOff
return self
end
--- When a player changes the coalition, he can receive a penalty score.
-- Use the method @{#SCORING.SetCoalitionChangePenalty}() to define the penalty when a player changes coalition.
@ -647,14 +666,15 @@ function SCORING:_AddPlayerFromUnit( UnitData )
if not self.Players[PlayerName].UnitCoalition then
self.Players[PlayerName].UnitCoalition = UnitCoalition
else
if self.Players[PlayerName].UnitCoalition ~= UnitCoalition then
self.Players[PlayerName].Penalty = self.Players[PlayerName].Penalty + 50
-- TODO: switch for coalition changes, make penalty alterable
if self.Players[PlayerName].UnitCoalition ~= UnitCoalition and self.penaltyoncoalitionchange then
self.Players[PlayerName].Penalty = self.Players[PlayerName].Penalty + self.CoalitionChangePenalty or 50
self.Players[PlayerName].PenaltyCoalition = self.Players[PlayerName].PenaltyCoalition + 1
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' changed coalition from " .. _SCORINGCoalition[self.Players[PlayerName].UnitCoalition] .. " to " .. _SCORINGCoalition[UnitCoalition] ..
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). 50 Penalty points added.",
"(changed " .. self.Players[PlayerName].PenaltyCoalition .. " times the coalition). ".. self.CoalitionChangePenalty .."Penalty points added.",
MESSAGE.Type.Information
):ToAll()
self:ScoreCSV( PlayerName, "", "COALITION_PENALTY", 1, -50, self.Players[PlayerName].UnitName, _SCORINGCoalition[self.Players[PlayerName].UnitCoalition], _SCORINGCategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
self:ScoreCSV( PlayerName, "", "COALITION_PENALTY", 1, -1*self.CoalitionChangePenalty, self.Players[PlayerName].UnitName, _SCORINGCoalition[self.Players[PlayerName].UnitCoalition], _SCORINGCategory[self.Players[PlayerName].UnitCategory], self.Players[PlayerName].UnitType,
UnitName, _SCORINGCoalition[UnitCoalition], _SCORINGCategory[UnitCategory], UnitData:GetTypeName() )
end
end
@ -666,8 +686,9 @@ function SCORING:_AddPlayerFromUnit( UnitData )
self.Players[PlayerName].UNIT = UnitData
self.Players[PlayerName].ThreatLevel = UnitThreatLevel
self.Players[PlayerName].ThreatType = UnitThreatType
if self.Players[PlayerName].Penalty > self.Fratricide * 0.50 then
-- TODO: make fratricide switchable
if self.Players[PlayerName].Penalty > self.Fratricide * 0.50 and self.penaltyonfratricide then
if self.Players[PlayerName].PenaltyWarning < 1 then
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "': WARNING! If you continue to commit FRATRICIDE and have a PENALTY score higher than " .. self.Fratricide .. ", you will be COURT MARTIALED and DISMISSED from this mission! \nYour total penalty is: " .. self.Players[PlayerName].Penalty,
MESSAGE.Type.Information
@ -676,7 +697,7 @@ function SCORING:_AddPlayerFromUnit( UnitData )
end
end
if self.Players[PlayerName].Penalty > self.Fratricide then
if self.Players[PlayerName].Penalty > self.Fratricide and self.penaltyonfratricide then
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. PlayerName .. "' committed FRATRICIDE, he will be COURT MARTIALED and is DISMISSED from this mission!",
MESSAGE.Type.Information
):ToAll()
@ -1121,9 +1142,9 @@ function SCORING:_EventOnHit( Event )
if InitCoalition then -- A coalition object was hit, probably a static.
if InitCoalition == TargetCoalition then
-- TODO: Penalty according scale
Player.Penalty = Player.Penalty + 10
PlayerHit.Penalty = PlayerHit.Penalty + 10
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1
Player.Penalty = Player.Penalty + 10 --* self.ScaleDestroyPenalty
PlayerHit.Penalty = PlayerHit.Penalty + 10 --* self.ScaleDestroyPenalty
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1 * self.ScaleDestroyPenalty
MESSAGE
:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit friendly target " ..

View File

@ -41,6 +41,7 @@
-- @field #boolean UseEmOnOff Decide if we are using Emission on/off (default) or AlarmState red/green.
-- @extends Core.Base#BASE
--- *Good friends are worth defending.* Mr Tushman, Wonder (the Movie)
--
-- Simple Class for a more intelligent Short Range Air Defense System

View File

@ -27,11 +27,11 @@
-- **Supported Carriers:**
--
-- * [USS John C. Stennis](https://en.wikipedia.org/wiki/USS_John_C._Stennis) (CVN-74)
-- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_(CVN-71)) (CVN-71) [Super Carrier Module]
-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72)) (CVN-72) [Super Carrier Module]
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59)) (CV-59) [Heatblur Carrier Module]
-- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_(CVN-71)) (CVN-71) [Super Carrier Module]
-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72)) (CVN-72) [Super Carrier Module]
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59)) (CV-59) [Heatblur Carrier Module]
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**]
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**]
@ -51,7 +51,7 @@
--
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
--
-- The AV-8B Harrier, the USS Tarawa, USS America and Juan Carlos I are WIP. The AV-8B harrier and the LHA's and LHD can only be used together, i.e. these ships are the only carriers the harrier is supposed to land on and
-- The AV-8B Harrier, the USS Tarawa, USS America, HMAS Canberra and Juan Carlos I are WIP. The AV-8B harrier and the LHA's and LHD can only be used together, i.e. these ships are the only carriers the harrier is supposed to land on and
-- no other fixed wing aircraft (human or AI controlled) are supposed to land on these ships. Currently only Case I is supported. Case II/III take slightly different steps from the CVN carrier.
-- However, the two Case II/III pattern are very similar so this is not a big drawback.
--
@ -108,9 +108,10 @@
-- * [DCS: F/A-18C Hornet – Episode 16: CASE III Introduction](https://www.youtube.com/watch?v=DvlMHnLjbDQ)
-- * [DCS: F/A-18C Hornet Case I Carrier Landing Training Lesson Recording](https://www.youtube.com/watch?v=D33uM9q4xgA)
--
-- ### AV-8B Harrier at USS Tarawa
-- ### AV-8B Harrier and V/STOL Operations:
--
-- * [Harrier Ship Landing Mission with Auto LSO!](https://www.youtube.com/watch?v=lqmVvpunk2c)
-- * [Updated Airboss V/STOL Features USS Tarawa](https://youtu.be/K7I4pU6j718)
-- * [Harrier Practice pattern USS America](https://youtu.be/99NigITYmcI)
--
-- ===
@ -300,7 +301,7 @@
--
-- Once the aircraft reaches the Initial, the landing pattern begins. The important steps of the pattern are shown in the image above.
-- The AV-8B Harrier pattern is very similar, the only differences are as there is no angled deck there is no wake check. from the ninety you wil fly a straight approach offset 26 ft to port (left) of the tram line.
-- The aim is to arrive abeam the landing spot in a stable hover at 120 ft with forward speed matched to the boat. From there the LSO will call "cleared to land". You then level cross to the tram line at the designated landing spot at land vertcally.
-- The aim is to arrive abeam the landing spot in a stable hover at 120 ft with forward speed matched to the boat. From there the LSO will call "cleared to land". You then level cross to the tram line at the designated landing spot at land vertcally. When you stabalise over the landing spot LSO will call Stabalise to indicate you are centered at the correct spot.
--
--
-- ## CASE III
@ -634,12 +635,12 @@
--
-- Furthermore, we have the cases:
--
-- * 2.5 Points **B**: "Bolder", when the player landed but did not catch a wire.
-- * 2.5 Points **B**: "Bolter", when the player landed but did not catch a wire.
-- * 2.0 Points **WOP**: "Pattern Wave-Off", when pilot was far away from where he should be in the pattern.
-- * 2.0 Points **OWO**: "Own Wave-Off**, when pilot flies past the deck without touching it.
-- * 1.0 Points **WO**: "Technique Wave-Off": Player got waved off in the final parts of the groove.
-- * 1.0 Points **LIG**: "Long In the Groove", when pilot extents the downwind leg too far and screws up the timing for the following aircraft.
-- * 0.0 Points **CUT**: "Cut pass", when player was waved off but landed anyway.
-- * 0.0 Points **CUT**: "Cut pass", when player was waved off but landed anyway. In addition if a V/STOL lands without having been Cleared to Land.
--
-- ## Foul Deck Waveoff
--
@ -1298,9 +1299,10 @@ AIRBOSS.AircraftCarrier={
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
-- @field #string FORRESTAL USS Forrestal (CV-59) [Heatblur Carrier Module]
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
-- @field #string TARAWA USS Tarawa (LHA-1)
-- @field #string AMERICA USS America (LHA-6)
-- @field #string JCARLOS Juan Carlos I (L61)
-- @field #string TARAWA USS Tarawa (LHA-1) [V/STOL Carrier]
-- @field #string AMERICA USS America (LHA-6) [V/STOL Carrier]
-- @field #string JCARLOS Juan Carlos I (L61) [V/STOL Carrier]
-- @field #string HMAS Canberra (L02) [V/STOL Carrier]
-- @field #string KUZNETSOV Admiral Kuznetsov (CV 1143.5)
AIRBOSS.CarrierType={
ROOSEVELT="CVN_71",
@ -1313,6 +1315,7 @@ AIRBOSS.CarrierType={
TARAWA="LHA_Tarawa",
AMERICA="USS America LHA-6",
JCARLOS="L61",
CANBERRA="L02",
KUZNETSOV="KUZNECOW",
}
@ -1726,7 +1729,7 @@ AIRBOSS.MenuF10Root=nil
--- Airboss class version.
-- @field #string version
AIRBOSS.version="1.2.0"
AIRBOSS.version="1.2.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -1991,6 +1994,9 @@ function AIRBOSS:New(carriername, alias)
elseif self.carriertype==AIRBOSS.CarrierType.JCARLOS then
-- Use Juan Carlos parameters.
self:_InitJcarlos()
elseif self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Use Juan Carlos parameters at this stage --TODO Check primary Landing spot.
self:_InitJcarlos()
elseif self.carriertype==AIRBOSS.CarrierType.KUZNETSOV then
-- Kusnetsov parameters - maybe...
self:_InitStennis()
@ -2028,10 +2034,10 @@ function AIRBOSS:New(carriername, alias)
self:_GetZonePlatform(case):SmokeZone(SMOKECOLOR.Blue, 45)
self:_GetZoneCorridor(case):SmokeZone(SMOKECOLOR.Green, 45)
self:_GetZoneHolding(case, 1):SmokeZone(SMOKECOLOR.White, 45)
self:_GetZoneHolding(case, 2):SmokeZone(SMOKECOLOR.White, 45)
self:_GetZoneHolding(case, 2):SmokeZone(SMOKECOLOR.White, 45)
self:_GetZoneInitial(case):SmokeZone(SMOKECOLOR.Orange, 45)
self:_GetZoneCommence(case, 1):SmokeZone(SMOKECOLOR.Red, 45)
self:_GetZoneCommence(case, 2):SmokeZone(SMOKECOLOR.Red, 45)
self:_GetZoneCommence(case, 2):SmokeZone(SMOKECOLOR.Red, 45)
self:_GetZoneAbeamLandingSpot():SmokeZone(SMOKECOLOR.Red, 5)
self:_GetZoneLandingSpot():SmokeZone(SMOKECOLOR.Red, 5)
end
@ -2082,7 +2088,7 @@ function AIRBOSS:New(carriername, alias)
-- Carrier specific.
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.JCARLOS then
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.JCARLOS or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.CANBERRA then
-- Flare wires.
local w1=stern:Translate(self.carrierparam.wire1, FB, true)
@ -4407,10 +4413,10 @@ function AIRBOSS:_InitForrestal()
self.carrierparam.rwywidth = 25
-- Wires.
self.carrierparam.wire1 = 42 -- Distance from stern to first wire.
self.carrierparam.wire2 = 51.5
self.carrierparam.wire3 = 62
self.carrierparam.wire4 = 72.5
self.carrierparam.wire1 = 44 -- Distance from stern to first wire. Original from Frank - 42
self.carrierparam.wire2 = 54 --51.5
self.carrierparam.wire3 = 64 --62
self.carrierparam.wire4 = 74 --72.5
end
@ -5015,7 +5021,7 @@ function AIRBOSS:_InitVoiceOvers()
duration=2.0,
subduration=5,
},
EXPECTSPOT5={
EXPECTSPOT5={
file="LSO-ExpectSpot5",
suffix="ogg",
loud=false,
@ -5854,8 +5860,8 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
elseif skyhawk then
alt=UTILS.FeetToMeters(600)
speed=UTILS.KnotsToMps(250)
elseif goshawk then
alt=UTILS.FeetToMeters(800)
elseif goshawk then
alt=UTILS.FeetToMeters(800)
speed=UTILS.KnotsToMps(300)
end
@ -5867,8 +5873,8 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
elseif skyhawk then
alt=UTILS.FeetToMeters(600)
speed=UTILS.KnotsToMps(250)
elseif goshawk then
alt=UTILS.FeetToMeters(800)
elseif goshawk then
alt=UTILS.FeetToMeters(800)
speed=UTILS.KnotsToMps(300)
end
@ -5905,7 +5911,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
dist=UTILS.NMToMeters(1.2)
end
if goshawk then
if goshawk then
-- 0.9 to 1.1 NM per natops ch.4 page 48
dist=UTILS.NMToMeters(0.9)
else
@ -5916,7 +5922,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
if hornet or tomcat then
alt=UTILS.FeetToMeters(500)
elseif goshawk then
elseif goshawk then
alt=UTILS.FeetToMeters(450)
elseif skyhawk then
alt=UTILS.FeetToMeters(500)
@ -6420,8 +6426,8 @@ function AIRBOSS:_MarshalPlayer(playerData, stack)
-- Set stack flag.
flight.flag=stack
-- Trigger Marshal event.
self:Marshal(flight)
-- Trigger Marshal event.
self:Marshal(flight)
end
else
@ -6891,7 +6897,7 @@ function AIRBOSS:_GetMarshalAltitude(stack, case)
p2=Carrier:Translate(UTILS.NMToMeters(1.5), hdg)
-- Tarawa,LHA,LHD Delta patterns.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Pattern is directly overhead the carrier.
p1=Carrier:Translate(UTILS.NMToMeters(1.0), hdg+90)
@ -7719,6 +7725,8 @@ function AIRBOSS:_InitPlayer(playerData, step)
playerData.wofd=false
playerData.owo=false
playerData.boltered=false
playerData.hover=false
playerData.stable=false
playerData.landed=false
playerData.Tlso=timer.getTime()
playerData.Tgroove=nil
@ -8736,7 +8744,7 @@ function AIRBOSS:OnEventLand(EventData)
self:T(self.lid..text)
-- Check carrier type.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Power "Idle".
self:RadioTransmission(self.LSORadio, self.LSOCall.IDLE, false, 1, nil, true)
@ -8771,7 +8779,7 @@ function AIRBOSS:OnEventLand(EventData)
-- AI unit landed --
--------------------
if self.carriertype~=AIRBOSS.CarrierType.TARAWA or self.carriertype~=AIRBOSS.CarrierType.AMERICA or self.carriertype~=AIRBOSS.CarrierType.JCARLOS then
if self.carriertype~=AIRBOSS.CarrierType.TARAWA or self.carriertype~=AIRBOSS.CarrierType.AMERICA or self.carriertype~=AIRBOSS.CarrierType.JCARLOS or self.carriertype~=AIRBOSS.CarrierType.CANBERRA then
-- Coordinate at landing event
local coord=EventData.IniUnit:GetCoordinate()
@ -9679,7 +9687,9 @@ function AIRBOSS:_Bullseye(playerData)
self:_PlayerHint(playerData)
-- LSO expect spot 5 or 7.5 call
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, nil, nil, nil, true)
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.CANBERRA then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, nil, nil, nil, true)
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, nil, nil, nil, true)
@ -9818,7 +9828,7 @@ function AIRBOSS:_CheckForLongDownwind(playerData)
local limit=UTILS.NMToMeters(-1.6)
-- For the tarawa, other LHA and LHD we give a bit more space.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
limit=UTILS.NMToMeters(-2.0)
end
@ -9864,9 +9874,11 @@ function AIRBOSS:_Abeam(playerData)
self:RadioTransmission(self.LSORadio, self.LSOCall.PADDLESCONTACT, nil, nil, nil, true)
-- LSO expect spot 5 or 7.5 call
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, false, 5, nil, true)
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.CANBERRA then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, false, 5, nil, true)
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, false, 5, nil, true)
end
@ -9903,7 +9915,7 @@ function AIRBOSS:_Ninety(playerData)
self:_PlayerHint(playerData)
-- Next step: wake.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Harrier has no wake stop. It stays port of the boat.
self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.FINAL)
else
@ -10160,8 +10172,8 @@ function AIRBOSS:_Groove(playerData)
-- Speed difference.
local dv=math.abs(vplayer-vcarrier)
-- Stable when speed difference < 10 km/h.
local stable=dv<10
-- Stable when speed difference < 20 km/h.
local stable=dv<20
-- Check if player is inside the zone.
if playerData.unit:IsInZone(ZoneALS) and stable then
@ -10171,6 +10183,9 @@ function AIRBOSS:_Groove(playerData)
-- Next step: Level cross.
self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.GROOVE_LC)
-- Set Stable Hover
playerData.stable=true
playerData.hover=true
end
elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_LC then
@ -10190,13 +10205,14 @@ function AIRBOSS:_Groove(playerData)
-- Speed difference.
local dv=math.abs(vplayer-vcarrier)
-- Stable when v<7.5 km/h.
local stable=dv<7.5
-- Stable when v<10 km/h.
local stable=dv<10
-- Radio Transmission "Cleared to land" once the aircraft is inside the zone.
if playerData.unit:IsInZone(ZoneLS) and stable and playerData.warning==false then
self:RadioTransmission(self.LSORadio, self.LSOCall.STABILIZED, nil, nil, nil, true)
playerData.warning=true
-- Radio Transmission "Stabilized" once the aircraft has been cleared to cross and is over the Landing Spot and stable.
if playerData.unit:IsInZone(ZoneLS) and stable and playerData.stable==true then
self:RadioTransmission(self.LSORadio, self.LSOCall.STABILIZED, nil, nil, nil, false)
playerData.stable=false
playerData.warning=true
end
-- We keep it in this step until landed.
@ -10229,8 +10245,25 @@ function AIRBOSS:_Groove(playerData)
-- Nothing else necessary.
return
end
end
end
-- Long V/STOL groove time Wave Off over 75 seconds to IC - TOPGUN level Only. --pene testing (WIP)
--if rho>=RAR and rho<=RIC and not playerData.waveoff and playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype== AIRBOSS.AircraftCarrier.AV8B then
-- Get groove time
--local vSlow=groovedata.time
-- If too slow wave off.
--if vSlow >75 then
-- LSO Wave off!
--self:RadioTransmission(self.LSORadio, self.LSOCall.WAVEOFF, nil, nil, nil, true)
--playerData.Tlso=timer.getTime()
-- Player was waved Off
--playerData.waveoff=true
--return
--end
--end
-- Groovedata step.
groovedata.Step=playerData.step
@ -10254,25 +10287,25 @@ function AIRBOSS:_Groove(playerData)
-- Distance in NM.
local d=UTILS.MetersToNM(rho)
-- Drift on lineup.
if rho>=RAR and rho<=RIM then
if gd.LUE>0.22 and lineupError<-0.22 then
env.info" Drift Right across centre ==> DR-"
gd.Drift=" DR"
self:T(self.lid..string.format("Got Drift Right across centre step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE<-0.22 and lineupError>0.22 then
env.info" Drift Left ==> DL-"
gd.Drift=" DL"
self:T(self.lid..string.format("Got Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE>0.13 and lineupError<-0.14 then
env.info" Little Drift Right across centre ==> (DR-)"
gd.Drift=" (DR)"
self:T(self.lid..string.format("Got Little Drift Right across centre at step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE<-0.13 and lineupError>0.14 then
env.info" Little Drift Left across centre ==> (DL-)"
gd.Drift=" (DL)"
self:E(self.lid..string.format("Got Little Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
end
-- Drift on lineup.
if rho>=RAR and rho<=RIM then
if gd.LUE>0.22 and lineupError<-0.22 then
env.info" Drift Right across centre ==> DR-"
gd.Drift=" DR"
self:T(self.lid..string.format("Got Drift Right across centre step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE<-0.22 and lineupError>0.22 then
env.info" Drift Left ==> DL-"
gd.Drift=" DL"
self:T(self.lid..string.format("Got Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE>0.13 and lineupError<-0.14 then
env.info" Little Drift Right across centre ==> (DR-)"
gd.Drift=" (DR)"
self:T(self.lid..string.format("Got Little Drift Right across centre at step %s, d=%.3f: Max LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
elseif gd.LUE<-0.13 and lineupError>0.14 then
env.info" Little Drift Left across centre ==> (DL-)"
gd.Drift=" (DL)"
self:E(self.lid..string.format("Got Little Drift Left across centre at step %s, d=%.3f: Min LUE=%.3f, lower LUE=%.3f", gs, d, gd.LUE, lineupError))
end
end
-- Update max deviation of line up error.
@ -10400,11 +10433,10 @@ function AIRBOSS:_CheckWaveOff(glideslopeError, lineupError, AoA, playerData)
-- For the harrier, we allow a bit more room.
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
glMax= 4.0
glMin=-3.0
luAbs= 5.0
-- No waveoff for harrier pilots at the moment.
return false
glMax= 2.6
glMin=-2.0
luAbs= 4.1 -- Testing Pene (WIP) needs feedback to tighten up tolerences.
end
-- Too high or too low?
@ -10428,9 +10460,10 @@ function AIRBOSS:_CheckWaveOff(glideslopeError, lineupError, AoA, playerData)
waveoff=true
end
-- Too slow or too fast? Only for pros.
if playerData.difficulty==AIRBOSS.Difficulty.HARD then
-- Get aircraft specific AoA values
-- Too slow or too fast? Only for pros.
if playerData.difficulty==AIRBOSS.Difficulty.HARD and playerData.actype~=AIRBOSS.AircraftCarrier.AV8B then
-- Get aircraft specific AoA values. Not for AV-8B due to transition to Stable Hover.
local aoaac=self:_GetAircraftAoA(playerData)
-- Check too slow or too fast.
if AoA<aoaac.FAST then
@ -10443,6 +10476,7 @@ function AIRBOSS:_CheckWaveOff(glideslopeError, lineupError, AoA, playerData)
self:T(self.lid..string.format("%s: %s", playerData.name, text))
self:_AddToDebrief(playerData, text)
waveoff=true
end
end
@ -10577,7 +10611,7 @@ function AIRBOSS:_GetSternCoord()
--local stern=self:GetCoordinate()
-- Stern coordinate (sterndist<0).
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Tarawa: Translate 8 meters port.
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
@ -10621,7 +10655,7 @@ function AIRBOSS:_GetWire(Lcoord, dc)
-- Multiplayer wire correction.
if self.mpWireCorrection then
d=d-self.mpWireCorrection
d=d-self.mpWireCorrection
end
-- Shift wires from stern to their correct position.
@ -10714,7 +10748,7 @@ function AIRBOSS:_Trapped(playerData)
elseif playerData.actype==AIRBOSS.AircraftCarrier.A4EC then
-- A-4E gets slowed down much faster the the F/A-18C!
dcorr=56
elseif playerData.actype==AIRBOSS.AircraftCarrier.T45C then
elseif playerData.actype==AIRBOSS.AircraftCarrier.T45C then
-- T-45 also gets slowed down much faster the the F/A-18C.
dcorr=56
end
@ -11218,7 +11252,8 @@ function AIRBOSS:_GetZoneRunwayBox()
end
--- Get zone of primary abeam landing position of USS Tarawa. Box length and width 30 meters.
--- Get zone of primary abeam landing position of USS Tarawa, USS America and Juan Carlos. Box length 50 meters and width 30 meters.
--- Allow for Clear to land call from LSO approaching abeam the landing spot if stable as per NATOPS 00-80T
-- @param #AIRBOSS self
-- @return Core.Zone#ZONE_POLYGON Zone surrounding landing runway.
function AIRBOSS:_GetZoneAbeamLandingSpot()
@ -11234,8 +11269,8 @@ function AIRBOSS:_GetZoneAbeamLandingSpot()
-- Points.
p[1]=S:Translate( 15, FB):Translate(15, FB+90) -- Top-Right
p[2]=S:Translate(-15, FB):Translate(15, FB+90) -- Bottom-Right
p[3]=S:Translate(-15, FB):Translate(15, FB-90) -- Bottom-Left
p[2]=S:Translate(-45, FB):Translate(15, FB+90) -- Bottom-Right
p[3]=S:Translate(-45, FB):Translate(15, FB-90) -- Bottom-Left
p[4]=S:Translate( 15, FB):Translate(15, FB-90) -- Top-Left
-- Convert to vec2.
@ -11323,7 +11358,7 @@ function AIRBOSS:_GetZoneHolding(case, stack)
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", Post:GetVec2(), self.marshalradius)
-- Delta pattern.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", self.carrier:GetVec2(), UTILS.NMToMeters(5))
end
@ -11345,7 +11380,7 @@ function AIRBOSS:_GetZoneHolding(case, stack)
-- So stay 0-5 NM (+1 NM error margin) port of carrier.
self.zoneHolding=self.zoneHolding or ZONE_POLYGON_BASE:New("CASE II/III Holding Zone")
self.zoneHolding:UpdateFromVec2(p)
self.zoneHolding:UpdateFromVec2(p)
end
return self.zoneHolding
@ -11376,7 +11411,7 @@ function AIRBOSS:_GetZoneCommence(case, stack)
-- Three position
local Three=self:GetCoordinate():Translate(D, hdg+275)
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
local Dx=UTILS.NMToMeters(2.25)
@ -11391,12 +11426,12 @@ function AIRBOSS:_GetZoneCommence(case, stack)
-- Create holding zone.
self.zoneCommence=self.zoneCommence or ZONE_RADIUS:New("CASE I Commence Zone")
self.zoneCommence:UpdateFromVec2(Three:GetVec2(), R)
self.zoneCommence:UpdateFromVec2(Three:GetVec2(), R)
else
-- Case II/III
stack=stack or 1
stack=stack or 1
-- Start point at 21 NM for stack=1.
local l=20+stack
@ -11424,7 +11459,7 @@ function AIRBOSS:_GetZoneCommence(case, stack)
-- Zone polygon.
self.zoneCommence=self.zoneCommence or ZONE_POLYGON_BASE:New("CASE II/III Commence Zone")
self.zoneCommence:UpdateFromVec2(p)
self.zoneCommence:UpdateFromVec2(p)
end
@ -11684,7 +11719,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
@ -11692,7 +11727,7 @@ function AIRBOSS:_GetOptLandingCoordinate()
elseif self.carriertype==AIRBOSS.CarrierType.AMERICA then
-- Landing 100 ft abeam, 120 ft alt. To allow adjustments to match different deck configurations.
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
@ -11701,12 +11736,21 @@ function AIRBOSS:_GetOptLandingCoordinate()
elseif self.carriertype==AIRBOSS.CarrierType.JCARLOS then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-100, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-100)
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
elseif self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Landing 100 ft abeam, 120 ft alt.
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
-- Alitude 120 ft.
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
else
-- Ideally we want to land between 2nd and 3rd wire.
@ -11754,9 +11798,16 @@ function AIRBOSS:_GetLandingSpotCoordinate()
-- Landing 100 ft abeam, 120 alt.
local hdg=self:GetHeading()
-- Primary landing spot 5.0 -- TODO voice for different landing Spots.
-- Primary landing spot 5.0 -- Done voice for different landing Spots.
self.landingspotcoord:Translate(89, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
elseif self.carriertype==AIRBOSS.CarrierType.CANBERRA then
-- Landing 100 ft abeam, 120 alt.
local hdg=self:GetHeading()
-- Primary landing spot 5.0 -- Done voice for different landing Spots.
self.landingspotcoord:Translate(89, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
end
return self.landingspotcoord
@ -12249,10 +12300,14 @@ end
--
-- If you manage to be between 16.4 and and 16.6 seconds, you will even get and okay underline "\_OK\_".
-- No groove time for Harrier on LHA, LHD set to Tgroove Unicorn as starting point to allow possible _OK_ 5.0.
--
-- If time in the AV-8B
--
-- * < 90 seconds: OK V/STOL
-- * > 91 Seconds: SLOW V/STOL (Early hover stop selection)
-- * < 55 seconds: Fast V/STOL
-- * < 75 seconds: OK V/STOL
-- * > 76 Seconds: SLOW V/STOL (Early hover stop selection)
--
-- If you manage to be between 60.0 and 65.0 seconds in the AV-8B, you will even get and okay underline "\_OK\_"
--
-- @param #AIRBOSS self
-- @param #AIRBOSS.PlayerData playerData Player data table.
@ -12274,9 +12329,9 @@ function AIRBOSS:_EvalGrooveTime(playerData)
-- Time in groove for AV-8B
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t<55 then -- VSTOL Late Hover stop selection too fast to Abeam LDG Spot AV-8B.
grade="FAST V/STOL Groove"
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t<90 then -- VSTOL Operations with AV-8B.
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t<75 then -- VSTOL Operations with AV-8B.
grade="OK V/STOL Groove"
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t>=91 then -- VSTOL Early Hover stop selection slow to Abeam LDG Spot AV-8B.
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t>=76 then -- VSTOL Early Hover stop selection slow to Abeam LDG Spot AV-8B.
grade="SLOW V/STOL Groove"
else
grade="LIG"
@ -12288,7 +12343,7 @@ function AIRBOSS:_EvalGrooveTime(playerData)
end
-- V/STOL Unicorn!
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and (t>=65.0 and t<=75.0) then
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and (t>=60.0 and t<=65.0) then
grade="_OK_ V/STOL"
end
@ -12317,7 +12372,7 @@ function AIRBOSS:_LSOgrade(playerData)
-- Put everything together.
local G=GXX.." "..GIM.." ".." "..GIC.." "..GAR
-- Count number of minor, normal and major deviations. TODO - work on Harrier counts due slower approach speed.
-- Count number of minor, normal and major deviations.
local N=nXX+nIM+nIC+nAR
local nL=count(G, '_')/2
local nS=count(G, '%(')
@ -12326,7 +12381,7 @@ function AIRBOSS:_LSOgrade(playerData)
-- Groove time 15-18.99 sec for a unicorn. Or 65-70 for V/STOL unicorn.
local Tgroove=playerData.Tgroove
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
local TgrooveVstolUnicorn=Tgroove and (Tgroove>=65.0 and Tgroove<=70.0)and playerData.actype==AIRBOSS.AircraftCarrier.AV8B or false
local TgrooveVstolUnicorn=Tgroove and (Tgroove>=60.0 and Tgroove<=65.0)and playerData.actype==AIRBOSS.AircraftCarrier.AV8B or false
local grade
local points
@ -12337,17 +12392,17 @@ function AIRBOSS:_LSOgrade(playerData)
G="Unicorn"
else
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe. (WIP requires feedback)
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe. (WIP requires feedback)
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
if nL>3 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
if nL>3 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Larger deviations ==> "No grade" 2.0 points.
grade="--"
points=2.0
elseif nN>2 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
elseif nN>2 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-- Only average deviations ==> "Fair Pass" Pass with average deviations and corrections.
grade="(OK)"
points=3.0
elseif nL>0 then
elseif nL>0 then
-- Larger deviations ==> "No grade" 2.0 points.
grade="--"
points=2.0
@ -12376,7 +12431,7 @@ end
text=text.."# of normal deviations = "..nN.."\n"
text=text.."# of small deviations ( = "..nS.."\n"
self:T2(self.lid..text)
-- Special cases.
if playerData.wop then
---------------------
@ -12432,8 +12487,18 @@ end
-- Bolter
grade="-- (BOLTER)"
points=2.5
end
elseif not playerData.hover and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
-------------------------------
-- AV-8B not cleared to land -- -- Landing clearence is carrier from LC to Landing
-------------------------------
if playerData.landed then
-- AIRBOSS wants your balls!
grade="CUT"
points=0.0
end
end
return grade, points, G
end
@ -12475,29 +12540,29 @@ function AIRBOSS:_Flightdata2Text(playerData, groovestep)
--Angled Approach.
local P=nil
if step==AIRBOSS.PatternStep.GROOVE_XX and ROL<=4.0 and playerData.case<3 then
if LUE>self.lue.RIGHT then
P=underline("AA")
elseif
LUE>self.lue.RightMed then
P="AA "
elseif
LUE>self.lue.Right then
P=little("AA")
end
if LUE>self.lue.RIGHT then
P=underline("AA")
elseif
LUE>self.lue.RightMed then
P="AA "
elseif
LUE>self.lue.Right then
P=little("AA")
end
end
--Overshoot Start.
local O=nil
if step==AIRBOSS.PatternStep.GROOVE_XX then
if LUE<self.lue.LEFT then
O=underline("OS")
elseif
LUE<self.lue.Left then
O="OS"
elseif
LUE<self.lue._min then
O=little("OS")
end
if LUE<self.lue.LEFT then
O=underline("OS")
elseif
LUE<self.lue.Left then
O="OS"
elseif
LUE<self.lue._min then
O=little("OS")
end
end
-- Speed via AoA. Depends on aircraft type.
@ -12541,21 +12606,21 @@ function AIRBOSS:_Flightdata2Text(playerData, groovestep)
elseif LUE>self.lue._max then
D=little("LUL")
elseif playerData.case<3 then
if LUE<self.lue.LEFT and step~=AIRBOSS.PatternStep.GROOVE_XX then
D=underline("LUR")
elseif LUE<self.lue.Left and step~=AIRBOSS.PatternStep.GROOVE_XX then
D="LUR"
elseif LUE<self.lue._min and step~=AIRBOSS.PatternStep.GROOVE_XX then
D=little("LUR")
end
if LUE<self.lue.LEFT and step~=AIRBOSS.PatternStep.GROOVE_XX then
D=underline("LUR")
elseif LUE<self.lue.Left and step~=AIRBOSS.PatternStep.GROOVE_XX then
D="LUR"
elseif LUE<self.lue._min and step~=AIRBOSS.PatternStep.GROOVE_XX then
D=little("LUR")
end
elseif playerData.case==3 then
if LUE<self.lue.LEFT then
D=underline("LUR")
elseif LUE<self.lue.Left then
D="LUR"
elseif LUE<self.lue._min then
D=little("LUR")
end
if LUE<self.lue.LEFT then
D=underline("LUR")
elseif LUE<self.lue.Left then
D="LUR"
elseif LUE<self.lue._min then
D=little("LUR")
end
end
-- Compile.
@ -12588,7 +12653,7 @@ function AIRBOSS:_Flightdata2Text(playerData, groovestep)
--Drift in Lineup
if fdata.Drift then
G=G..fdata.Drift
n=n -- Drift doesn't affect score, advisory only.
n=n -- Drift doesn't affect score, advisory only.
end
-- Overshoot.
if O then
@ -12657,7 +12722,7 @@ function AIRBOSS:_GS(step, n)
if n==-1 then
gp=AIRBOSS.GroovePos.IC
elseif n==1 then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
gp=AIRBOSS.GroovePos.AL
else
gp=AIRBOSS.GroovePos.IW
@ -14549,7 +14614,7 @@ function AIRBOSS:_IsCarrierAircraft(unit)
-- Special case for Harrier which can only land on Tarawa, LHA and LHD.
if aircrafttype==AIRBOSS.AircraftCarrier.AV8B then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
return true
else
return false
@ -14557,7 +14622,7 @@ function AIRBOSS:_IsCarrierAircraft(unit)
end
-- Also only Harriers can land on the Tarawa, LHA and LHD.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
if aircrafttype~=AIRBOSS.AircraftCarrier.AV8B then
return false
end
@ -14860,8 +14925,8 @@ end
-- @param #table param Parameters.
-- @param #number time Time.
function AIRBOSS._CheckRadioQueueT(param, time)
AIRBOSS._CheckRadioQueue(param.airboss, param.radioqueue, param.name)
return time+0.05
AIRBOSS._CheckRadioQueue(param.airboss, param.radioqueue, param.name)
return time+0.05
end
--- Radio queue item.
@ -14885,15 +14950,15 @@ function AIRBOSS:_CheckRadioQueue(radioqueue, name)
-- Check if queue is empty.
if #radioqueue==0 then
if name=="LSO" then
self:T(self.lid..string.format("Stopping LSO radio queue."))
self.radiotimer:Stop(self.RQLid)
self.RQLid=nil
elseif name=="MARSHAL" then
self:T(self.lid..string.format("Stopping Marshal radio queue."))
self.radiotimer:Stop(self.RQMid)
self.RQMid=nil
end
if name=="LSO" then
self:T(self.lid..string.format("Stopping LSO radio queue."))
self.radiotimer:Stop(self.RQLid)
self.RQLid=nil
elseif name=="MARSHAL" then
self:T(self.lid..string.format("Stopping Marshal radio queue."))
self.radiotimer:Stop(self.RQMid)
self.RQMid=nil
end
return
end
@ -15035,11 +15100,11 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay, interval, click, pi
caller="LSOCall"
-- Schedule radio queue checks.
if not self.RQLid then
-- Schedule radio queue checks.
if not self.RQLid then
self:T(self.lid..string.format("Starting LSO radio queue."))
self.RQLid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQLSO, "LSO"}, 0.02, 0.05)
end
self.RQLid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQLSO, "LSO"}, 0.02, 0.05)
end
elseif radio.alias=="MARSHAL" then
@ -15047,10 +15112,10 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay, interval, click, pi
caller="MarshalCall"
if not self.RQMid then
self:T(self.lid..string.format("Starting Marhal radio queue."))
self.RQMid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQMarshal, "MARSHAL"}, 0.02, 0.05)
end
if not self.RQMid then
self:T(self.lid..string.format("Starting Marhal radio queue."))
self.RQMid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQMarshal, "MARSHAL"}, 0.02, 0.05)
end
end
@ -16217,9 +16282,9 @@ function AIRBOSS:_SkipperStartRecovery(_unitName, case)
-- Inform player.
local text=string.format("affirm, Case %d recovery will start in 5 min for %d min. Wind on deck %d knots. U-turn=%s.", case, self.skipperTime, self.skipperSpeed, tostring(self.skipperUturn))
if case>1 then
text=text..string.format(" Marshal radial %d°.", self.skipperOffset)
end
if case>1 then
text=text..string.format(" Marshal radial %d°.", self.skipperOffset)
end
if self:IsRecovering() then
text="negative, carrier is already recovering."
self:MessageToPlayer(playerData, text, "AIRBOSS")
@ -17927,7 +17992,7 @@ function AIRBOSS:_MarkCaseZones(_unitName, flare)
end
-- Tarawa, LHA and LHD landing spots.
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then
text=text.."\n* abeam landing stop with RED flares"
-- Abeam landing spot zone.
local ALSPT=self:_GetZoneAbeamLandingSpot()
@ -18070,12 +18135,12 @@ function AIRBOSS:_SaveTrapSheet(playerData, grade)
for i=1,9999 do
-- Create file name
if self.trapprefix then
filename=string.format("%s_%s-%04d.csv", self.trapprefix, playerData.actype, i)
else
local name=UTILS.ReplaceIllegalCharacters(playerData.name, "_")
filename=string.format("AIRBOSS-%s_Trapsheet-%s_%s-%04d.csv", self.alias, name, playerData.actype, i)
end
if self.trapprefix then
filename=string.format("%s_%s-%04d.csv", self.trapprefix, playerData.actype, i)
else
local name=UTILS.ReplaceIllegalCharacters(playerData.name, "_")
filename=string.format("AIRBOSS-%s_Trapsheet-%s_%s-%04d.csv", self.alias, name, playerData.actype, i)
end
-- Set path.
if path~=nil then

View File

@ -45,6 +45,7 @@
-- * Object oriented refactoring of Ciribob\'s fantastic CSAR script.
-- * No need for extra MIST loading.
-- * Additional events to tailor your mission.
-- * Optional SpawnCASEVAC to create casualties without beacon (e.g. handling dead ground vehicles and create CASVAC requests).
--
-- ## 0. Prerequisites
--
@ -105,7 +106,7 @@
-- self.countryblue= country.id.USA
-- self.countryred = country.id.RUSSIA
-- self.countryneutral = country.id.UN_PEACEKEEPERS
--
--
-- ## 2.1 Experimental Features
--
-- WARNING - Here\'ll be dragons!
@ -115,7 +116,9 @@
-- self.SRSPath = "E:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!)
-- self.SRSchannel = 300 -- radio channel
-- self.SRSModulation = radio.modulation.AM -- modulation
--
-- --
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
--
-- ## 3. Results
--
-- Number of successful landings with save pilots and aggregated number of saved pilots is stored in these variables in the object:
@ -175,6 +178,8 @@
-- -- Create downed "Pilot Wagner" in #ZONE "CSAR_Start_1" at a random point for the blue coalition
-- my_csar:SpawnCSARAtZone( "CSAR_Start_1", coalition.side.BLUE, "Pilot Wagner", true )
--
-- --Create a casualty and CASEVAC request from a "Point" (VEC2) for the blue coalition --shagrat
-- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE)
--
-- @field #CSAR
CSAR = {
@ -238,10 +243,11 @@ CSAR.AircraftType["Mi-8MTV2"] = 12
CSAR.AircraftType["Mi-8MT"] = 12
CSAR.AircraftType["Mi-24P"] = 8
CSAR.AircraftType["Mi-24V"] = 8
CSAR.AircraftType["Bell-47"] = 2
--- CSAR class version.
-- @field #string version
CSAR.version="0.1.11r1"
CSAR.version="0.1.12r2"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@ -249,7 +255,7 @@ CSAR.version="0.1.11r1"
-- DONE: SRS Integration (to be tested)
-- TODO: Maybe - add option to smoke/flare closest MASH
-- TODO: shagrat Add cargoWeight to helicopter when pilot boarded
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -379,7 +385,10 @@ function CSAR:New(Coalition, Template, Alias)
self.countryblue= country.id.USA
self.countryred = country.id.RUSSIA
self.countryneutral = country.id.UN_PEACEKEEPERS
-- added 0.1.3
self.csarUsePara = true -- shagrat set to true, will use the LandingAfterEjection Event instead of Ejection
-- WARNING - here\'ll be dragons
-- 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)
@ -644,10 +653,14 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
local _typeName = _typeName or "Pilot"
if not noMessage then
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
if _freq ~= 0 then --shagrat different CASEVAC msg
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
else
self:_DisplayToAllSAR("Troops In Contact. " .. _typeName .. " requests CASEVAC. ", self.coalition, self.messageTime)
end
end
if _freq then
if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0
self:_AddBeaconToGroup(_spawnedGroup, _freq)
end
@ -656,10 +669,18 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
local _text = _description
if not forcedesc then
if _playerName ~= nil then
_text = "Pilot " .. _playerName
if _freq ~= 0 then --shagrat
_text = "Pilot " .. _playerName
else
_text = "TIC - " .. _playerName
end
elseif _unitName ~= nil then
_text = "AI Pilot of " .. _unitName
end
if _freq ~= 0 then --shagrat
_text = "AI Pilot of " .. _unitName
else
_text = "TIC - " .. _unitName
end
end
end
self:T({_spawnedGroup, _alias})
@ -667,7 +688,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName)
self:_InitSARForPilot(_spawnedGroup, _GroupName, _freq, noMessage)
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
return self
end
@ -736,6 +757,58 @@ function CSAR:SpawnCSARAtZone(Zone, Coalition, Description, RandomPoint, Nomessa
return self
end
--- (Internal) Function to add a CSAR object into the scene at a Point coordinate (VEC_2). For mission designers wanting to add e.g. casualties to the scene, that don't use beacons.
-- @param #CSAR self
-- @param #string _Point a POINT_VEC2.
-- @param #number _coalition Coalition.
-- @param #string _description (optional) Description.
-- @param #boolean _nomessage (optional) If true, don\'t send a message to SAR.
-- @param #string unitname (optional) Name of the lost unit.
-- @param #string typename (optional) Type of plane.
-- @param #boolean forcedesc (optional) Force to use the description passed only for the pilot track entry. Use to have fully custom names.
function CSAR:_SpawnCASEVAC( _Point, _coalition, _description, _nomessage, unitname, typename, forcedesc) --shagrat added internal Function _SpawnCASEVAC
self:T(self.lid .. " _SpawnCASEVAC")
local _description = _description or "CASEVAC"
local unitname = unitname or "CASEVAC"
local typename = typename or "Ground Commander"
local pos = {}
pos = _Point
local _country = 0
if _coalition == coalition.side.BLUE then
_country = self.countryblue
elseif _coalition == coalition.side.RED then
_country = self.countryred
else
_country = self.countryneutral
end
--shagrat set frequency to 0 as "flag" for no beacon
self:_AddCsar(_coalition, _country, pos, typename, unitname, _description, 0, _nomessage, _description, forcedesc)
return self
end
--- Function to add a CSAR object into the scene at a zone coordinate. For mission designers wanting to add e.g. PoWs to the scene.
-- @param #CSAR self
-- @param #string Point a POINT_VEC2.
-- @param #number Coalition Coalition.
-- @param #string Description (optional) Description.
-- @param #boolean addBeacon (optional) yes or no.
-- @param #boolean Nomessage (optional) If true, don\'t send a message to SAR.
-- @param #string Unitname (optional) Name of the lost unit.
-- @param #string Typename (optional) Type of plane.
-- @param #boolean Forcedesc (optional) Force to use the **description passed only** for the pilot track entry. Use to have fully custom names.
-- @usage If missions designers want to spawn downed pilots into the field, e.g. at mission begin, to give the helicopter guys work, they can do this like so:
--
-- -- Create casualty "CASEVAC" at Point #POINT_VEC2 for the blue coalition.
-- my_csar:SpawnCASEVAC( POINT_VEC2, coalition.side.BLUE )
function CSAR:SpawnCASEVAC(Point, Coalition, Description, Nomessage, Unitname, Typename, Forcedesc)
self:_SpawnCASEVAC(Point, Coalition, Description, Nomessage, Unitname, Typename, Forcedesc)
return self
end --shagrat end added CASEVAC
--- (Internal) Event handler.
-- @param #CSAR self
function CSAR:_EventHandler(EventData)
@ -747,7 +820,7 @@ function CSAR:_EventHandler(EventData)
-- no event
if _event == nil or _event.initiator == nil then
return false
-- take off
elseif _event.id == EVENTS.Takeoff then -- taken off
self:T(self.lid .. " Event unit - Takeoff")
@ -823,12 +896,12 @@ function CSAR:_EventHandler(EventData)
local _unit = _event.IniUnit
local _unitname = _event.IniUnitName
local _group = _event.IniGroup
if _unit == nil then
return -- error!
end
local _coalition = _unit:GetCoalition()
local _coalition = _unit:GetCoalition()
if _coalition ~= self.coalition then
return --ignore!
end
@ -851,11 +924,27 @@ function CSAR:_EventHandler(EventData)
return
end
-- all checks passed, get going.
local _freq = self:_GenerateADFFrequency()
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
return true
-- 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
local _freq = self:_GenerateADFFrequency()
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
return true
end
---- shagrat on event LANDING_AFTER_EJECTION spawn pilot at parachute location
elseif (_event.id == EVENTS.LandingAfterEjection and self.csarUsePara == true) then
self:I({EVENT=_event})
local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p)
local _unitname = "Aircraft" --_event.initiator:getName() or "Aircraft" --shagrat Optional use of Object name which is unfortunately 'f15_Pilot_Parachute'
local _typename = "Ejected Pilot" --_event.Initiator.getTypeName() or "Ejected Pilot"
local _country = _event.initiator:getCountry()
local _coalition = coalition.getCountryCoalition( _country )
local _freq = self:_GenerateADFFrequency()
self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq})
self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location.
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
return true
elseif _event.id == EVENTS.Land then
self:T(self.lid .. " Landing")
@ -920,8 +1009,13 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
local _leadername = _leader:GetName()
if not _nomessage then
local _text = string.format("%s requests SAR at %s, beacon at %.2f KHz", _leadername, _coordinatesText, _freqk)
self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
if _freq ~= 0 then --shagrat
local _text = string.format("%s requests SAR at %s, beacon at %.2f KHz", _groupName, _coordinatesText, _freqk)--shagrat _groupName to prevent 'f15_Pilot_Parachute'
self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
else --shagrat CASEVAC msg
local _text = string.format("Pickup Zone at %s.", _coordinatesText )
self:_DisplayToAllSAR(_text,self.coalition,self.messageTime)
end
end
for _,_heliName in pairs(self.csarUnits) do
@ -1059,7 +1153,7 @@ function CSAR:_PopSmokeForGroup(_woundedGroupName, _woundedLeader)
if _lastSmoke == nil or timer.getTime() > _lastSmoke then
local _smokecolor = self.smokecolor
local _smokecoord = _woundedLeader:GetCoordinate()
local _smokecoord = _woundedLeader:GetCoordinate():Translate( 6, math.random( 1, 360) ) --shagrat place smoke at a random 6 m distance, so smoke does not obscure the pilot
_smokecoord:Smoke(_smokecolor)
self.smokeMarkers[_woundedGroupName] = timer.getTime() + 300 -- next smoke time
end
@ -1434,7 +1528,11 @@ function CSAR:_DisplayActiveSAR(_unitName)
else
distancetext = string.format("%.1fkm", _distance/1000.0)
end
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
if _value.frequency == 0 then--shagrat insert CASEVAC without Frequency
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) })
else
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
end
end
end
@ -1875,6 +1973,7 @@ function CSAR:onafterStart(From, Event, To)
self:HandleEvent(EVENTS.Takeoff, self._EventHandler)
self:HandleEvent(EVENTS.Land, self._EventHandler)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.LandingAfterEjection, self._EventHandler) --shagrat
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
@ -1985,6 +2084,7 @@ function CSAR:onafterStop(From, Event, To)
self:UnHandleEvent(EVENTS.Takeoff)
self:UnHandleEvent(EVENTS.Land)
self:UnHandleEvent(EVENTS.Ejection)
self:UnHandleEvent(EVENTS.LandingAfterEjection) -- shagrat
self:UnHandleEvent(EVENTS.PlayerEnterUnit)
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
self:UnHandleEvent(EVENTS.PilotDead)

View File

@ -2145,24 +2145,39 @@ function CTLD:_LoadCratesNearby(Group, Unit)
self.Loaded_Cargo[unitname] = loaded
self:_UpdateUnitCargoMass(Unit)
-- clean up real world crates
local existingcrates = self.Spawned_Cargo -- #table
local newexcrates = {}
for _,_crate in pairs(existingcrates) do
local excrate = _crate -- #CTLD_CARGO
local ID = excrate:GetID()
for _,_ID in pairs(crateidsloaded) do
if ID ~= _ID then
table.insert(newexcrates,_crate)
end
end
end
self.Spawned_Cargo = nil
self.Spawned_Cargo = newexcrates
self:_CleanupTrackedCrates(crateidsloaded)
end
end
return self
end
--- (Internal) Function to clean up tracked cargo crates
function CTLD:_CleanupTrackedCrates(crateIdsToRemove)
local existingcrates = self.Spawned_Cargo -- #table
local newexcrates = {}
for _,_crate in pairs(existingcrates) do
local excrate = _crate -- #CTLD_CARGO
local ID = excrate:GetID()
local keep = true
for _,_ID in pairs(crateIdsToRemove) do
if ID == _ID then
keep = false
end
end
-- remove destroyed crates here too
local static = _crate:GetPositionable() -- Wrapper.Static#STATIC -- crates
if not static or not static:IsAlive() then
keep = false
end
if keep then
table.insert(newexcrates,_crate)
end
end
self.Spawned_Cargo = nil
self.Spawned_Cargo = newexcrates
return self
end
--- (Internal) Function to get current loaded mass
-- @param #CTLD self
-- @param Wrapper.Unit#UNIT Unit
@ -2849,19 +2864,7 @@ function CTLD:_CleanUpCrates(Crates,Build,Number)
if found == numberdest then break end -- got enough
end
-- loop and remove from real world representation
for _,_crate in pairs(existingcrates) do
local excrate = _crate -- #CTLD_CARGO
local ID = excrate:GetID()
for _,_ID in pairs(destIDs) do
if ID ~= _ID then
table.insert(newexcrates,_crate)
end
end
end
-- reset Spawned_Cargo
self.Spawned_Cargo = nil
self.Spawned_Cargo = newexcrates
self:_CleanupTrackedCrates(destIDs)
return self
end

View File

@ -116,10 +116,10 @@
-- @field Ops.OpsTransport#OPSTRANSPORT cargoTransport Current cargo transport assignment.
-- @field #string cargoStatus Cargo status of this group acting as cargo.
-- @field #number cargoTransportUID Unique ID of the transport assignment this cargo group is associated with.
-- @field #string carrierStatus Carrier status of this group acting as cargo carrier.
-- @field #string carrierStatus Carrier status of this group acting as cargo carrier.
-- @field #OPSGROUP.CarrierLoader carrierLoader Carrier loader parameters.
-- @field #OPSGROUP.CarrierLoader carrierUnloader Carrier unloader parameters.
--
--
-- @field #boolean useSRS Use SRS for transmissions.
-- @field Sound.SRS#MSRS msrs MOOSE SRS wrapper.
--
@ -223,7 +223,7 @@ OPSGROUP = {
-- @field #number weightCargo Current cargo weight in kg.
-- @field #number weight Current weight including cargo in kg.
-- @field #table cargoBay Cargo bay.
--
--
-- @field #string modex Tail number.
-- @field Wrapper.Client#CLIENT client The client if element is occupied by a human player.
-- @field #table pylons Table of pylons.
@ -509,7 +509,7 @@ function OPSGROUP:New(group)
return nil
end
end
-- Set the template.
self:_SetTemplate()
@ -528,7 +528,7 @@ function OPSGROUP:New(group)
self.spot.timer=TIMER:New(self._UpdateLaser, self)
self.spot.Coordinate=COORDINATE:New(0, 0, 0)
self:SetLaser(1688, true, false, 0.5)
-- Cargo.
self.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO
self.carrierStatus=OPSGROUP.CarrierStatus.NOTCARRIER
@ -1133,7 +1133,7 @@ function OPSGROUP:GetVelocity(UnitName)
local vel=UTILS.VecNorm(velvec3)
return vel
else
self:E(self.lid.."WARNING: Unit does not exist. Cannot get velocity!")
end
@ -1328,7 +1328,7 @@ function OPSGROUP:Despawn(Delay, NoEventRemoveUnit)
if Delay and Delay>0 then
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.Despawn, self, 0, NoEventRemoveUnit)
else
self:I(self.lid..string.format("Despawning Group!"))
local DCSGroup=self:GetDCSGroup()
@ -1527,18 +1527,18 @@ function OPSGROUP:RadioTransmission(Text, Delay)
else
if self.useSRS and self.msrs then
local freq, modu, radioon=self:GetRadio()
self.msrs:SetFrequencies(freq)
self.msrs:SetModulations(modu)
-- Debug info.
self:I(self.lid..string.format("Radio transmission on %.3f MHz %s: %s", freq, UTILS.GetModulationName(modu), Text))
self.msrs:PlayText(Text)
self.msrs:PlayText(Text)
end
end
return self
@ -1885,13 +1885,13 @@ end
-- @return #boolean If true, group is *not* cargo.
function OPSGROUP:IsNotCargo(CheckTransport)
local notcargo=self.cargoStatus==OPSGROUP.CargoStatus.NOTCARGO
if notcargo then
-- Not cargo.
return true
else
-- Is cargo (e.g. loaded or boarding)
if CheckTransport then
-- Check if transport UID was set.
if self.cargoTransportUID==nil then
@ -1904,10 +1904,10 @@ function OPSGROUP:IsNotCargo(CheckTransport)
-- Is cargo.
return false
end
end
return notcargo
end
@ -2415,16 +2415,16 @@ function OPSGROUP:OnEventBirth(EventData)
-- Get element.
local element=self:GetElementByName(unitname)
if element then
-- Set element to spawned state.
self:ElementSpawned(element)
end
end
end
--- Event function handling the crash of a unit.
@ -2460,7 +2460,7 @@ function OPSGROUP:OnEventRemoveUnit(EventData)
-- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
self:T2(self.lid..string.format("EVENT: Unit %s removed!", EventData.IniUnitName))
local unit=EventData.IniUnit
local group=EventData.IniGroup
local unitname=EventData.IniUnitName
@ -2928,17 +2928,17 @@ function OPSGROUP:onbeforeTaskExecute(From, Event, To, Task)
-- Get mission of this task (if any).
local Mission=self:GetMissionByTaskID(Task.id)
if Mission and (Mission.Tpush or #Mission.conditionPush>0) then
if Mission:IsReadyToPush() then
-- Not waiting any more.
self.Twaiting=nil
self.dTwait=nil
else
---
-- Not ready to push yet
---
@ -2952,17 +2952,17 @@ function OPSGROUP:onbeforeTaskExecute(From, Event, To, Task)
-- Time to for the next try.
local dt=Mission.Tpush and Mission.Tpush-timer.getAbsTime() or 20
-- Debug info.
self:T(self.lid..string.format("Mission %s task execute suspended for %d seconds", Mission.name, dt))
-- Reexecute task.
self:__TaskExecute(-dt, Task)
-- Deny transition.
return false
return false
end
end
return true
@ -2987,13 +2987,13 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- Set current task.
self.taskcurrent=Task.id
-- Set time stamp.
Task.timestamp=timer.getAbsTime()
-- Task status executing.
Task.status=OPSGROUP.TaskStatus.EXECUTING
-- Insert into task queue. Not sure any more, why I added this. But probably if a task is just executed without having been put into the queue.
if self:GetTaskCurrent()==nil then
table.insert(self.taskqueue, Task)
@ -3049,7 +3049,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- If task is scheduled (not waypoint) set task.
if Task.type==OPSGROUP.TaskType.SCHEDULED or Task.ismission then
local DCStasks={}
if Task.dcstask.id=='ComboTask' then
-- Loop over all combo tasks.
@ -3081,8 +3081,8 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
-- impacted (took rather long). Then the flight flew to the nearest airbase and one lost completely the control over the group.
self:PushTask(TaskFinal)
--self:SetTask(TaskFinal)
elseif Task.type==OPSGROUP.TaskType.WAYPOINT then
-- Waypoint tasks are executed elsewhere!
else
@ -3090,7 +3090,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
end
end
-- Get mission of this task (if any).
local Mission=self:GetMissionByTaskID(self.taskcurrent)
if Mission then
@ -3730,13 +3730,13 @@ function OPSGROUP:RouteToMission(mission, delay)
-- ID of current waypoint.
local uid=self:GetWaypointCurrent().uid
-- Random radius.
local randomradius=1000
if mission.type==AUFTRAG.Type.PATROLZONE then
randomradius=nil
end
-- Get coordinate where the mission is executed.
local waypointcoord=mission:GetMissionWaypointCoord(self.group, randomradius)
@ -3808,11 +3808,12 @@ function OPSGROUP:RouteToMission(mission, delay)
if self.isGround and mission.optionFormation then
formation=mission.optionFormation
end
--waypointcoord:MarkToAll(string.format("Mission %s alt=%d m", mission:GetName(), waypointcoord.y))
-- UID of this waypoint.
local uid=self:GetWaypointCurrent().uid
-- Add waypoint.
local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, nil, formation, false)
local waypoint=self:AddWaypoint(waypointcoord, SpeedToMission, uid, formation, false)
-- Add waypoint task. UpdateRoute is called inside.
local waypointtask=self:AddTaskWaypoint(mission.DCStask, waypoint, mission.name, mission.prio, mission.duration)
@ -3823,7 +3824,7 @@ function OPSGROUP:RouteToMission(mission, delay)
-- Set waypoint index.
mission:SetGroupWaypointIndex(self, waypoint.uid)
local egress=mission:GetMissionEgressCoord()
if egress then
local waypoint=self:AddWaypoint(egress, SpeedToMission, nil, formation, false)
@ -3948,12 +3949,12 @@ function OPSGROUP:onbeforeWait(From, Event, To, Duration)
Tsuspend=-30
allowed=false
end
-- Check for a current transport assignment.
if self.cargoTransport then
self:I(self.lid..string.format("WARNING: Got current TRANSPORT assignment ==> WAIT event is suspended for 30 sec!"))
Tsuspend=-30
allowed=false
allowed=false
end
-- Call wait again.
@ -4070,7 +4071,7 @@ function OPSGROUP:_SetWaypointTasks(Waypoint)
text=text.." None"
end
self:T(self.lid..text)
-- Check if there is mission task
if missiontask then
self:T(self.lid.."Executing mission task")
@ -4781,22 +4782,22 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element)
-- Clear cargo bay of element.
for i=#Element.cargoBay,1,-1 do
local cargo=Element.cargoBay[i] --#OPSGROUP.MyCargo
-- Remove from cargo bay.
self:_DelCargobay(cargo.group)
if cargo.group and not (cargo.group:IsDead() or cargo.group:IsStopped()) then
-- Remove my carrier
cargo.group:_RemoveMyCarrier()
if cargo.reserved then
-- This group was not loaded yet ==> Not cargo any more.
cargo.group:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
else
-- Carrier dead ==> cargo dead.
for _,cargoelement in pairs(cargo.group.elements) do
@ -4808,10 +4809,10 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element)
end
end
end
end
end
--- On after "Respawn" event.
@ -4882,7 +4883,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
end
end
]]
local units=Template.units
@ -4925,24 +4926,24 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
-- Debug output.
self:T({Template=Template})
-- Spawn new group.
_DATABASE:Spawn(Template)
-- Set activation and controlled state.
self.isLateActivated=Template.lateActivation
self.isUncontrolled=Template.uncontrolled
-- Not dead or destroyed any more.
self.isDead=false
self.isDestroyed=false
self.groupinitialized=false
self.Ndestroyed=0
self.Ndestroyed=0
self.wpcounter=1
self.currentwp=1
-- Init waypoints.
self:_InitWaypoints()
@ -5011,11 +5012,11 @@ function OPSGROUP:onafterDead(From, Event, To)
mission:GroupDead(self)
end
-- Delete waypoints so they are re-initialized at the next spawn.
self:ClearWaypoints()
self.groupinitialized=false
-- Set cargo status to NOTCARGO.
self.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO
self.carrierStatus=OPSGROUP.CarrierStatus.NOTCARRIER
@ -5024,21 +5025,21 @@ function OPSGROUP:onafterDead(From, Event, To)
local mycarrier=self:_GetMyCarrierGroup()
if mycarrier and not mycarrier:IsDead() then
mycarrier:_DelCargobay(self)
self:_RemoveMyCarrier()
self:_RemoveMyCarrier()
end
-- Inform all transports in the queue that this carrier group is dead now.
for i,_transport in pairs(self.cargoqueue) do
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
transport:__DeadCarrierGroup(1, self)
end
-- Cargo queue empty
self.cargoqueue={}
-- No current cargo transport.
self.cargoTransport=nil
-- Stop in a sec.
--self:__Stop(-5)
end
@ -5050,7 +5051,7 @@ end
-- @param #string To To state.
function OPSGROUP:onbeforeStop(From, Event, To)
-- We check if
-- We check if
if self:IsAlive() then
self:E(self.lid..string.format("WARNING: Group is still alive! Will not stop the FSM. Use :Despawn() instead"))
return false
@ -5081,7 +5082,7 @@ function OPSGROUP:onafterStop(From, Event, To)
self:UnHandleEvent(EVENTS.Ejection)
self:UnHandleEvent(EVENTS.Crash)
self.currbase=nil
end
end
-- Stop check timers.
self.timerCheckZone:Stop()
@ -5122,19 +5123,19 @@ function OPSGROUP:_CheckCargoTransport()
-- Cargo bay debug info.
-- Check cargo bay and declare cargo groups dead.
if self.verbose>=1 then
local text=""
local text=""
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
for _,_cargo in pairs(element.cargoBay) do
local cargo=_cargo --#OPSGROUP.MyCargo
text=text..string.format("\n- %s in carrier %s, reserved=%s", tostring(cargo.group:GetName()), tostring(element.name), tostring(cargo.reserved))
end
end
end
if text=="" then
text=" empty"
end
self:I(self.lid.."Cargo bay:"..text)
end
self:I(self.lid.."Cargo bay:"..text)
end
-- Cargo queue debug info.
if self.verbose>=3 then
@ -5307,9 +5308,9 @@ end
function OPSGROUP:_AddCargobay(CargoGroup, CarrierElement, Reserved)
--TODO: Check group is not already in cargobay of this carrier or any other carrier.
local cargo=self:_GetCargobay(CargoGroup)
if cargo then
cargo.reserved=Reserved
else
@ -5317,26 +5318,26 @@ function OPSGROUP:_AddCargobay(CargoGroup, CarrierElement, Reserved)
cargo={} --#OPSGROUP.MyCargo
cargo.group=CargoGroup
cargo.reserved=Reserved
table.insert(CarrierElement.cargoBay, cargo)
table.insert(CarrierElement.cargoBay, cargo)
end
-- Set my carrier.
CargoGroup:_SetMyCarrier(self, CarrierElement, Reserved)
-- Fill cargo bay (obsolete).
self.cargoBay[CargoGroup.groupname]=CarrierElement.name
if not Reserved then
-- Cargo weight.
local weight=CargoGroup:GetWeightTotal()
-- Add weight to carrier.
self:AddWeightCargo(CarrierElement.name, weight)
end
end
return self
end
@ -5381,22 +5382,22 @@ function OPSGROUP:_DelCargobay(CargoGroup)
-- Get cargo bay info.
local cargoBayItem, cargoBayIndex, CarrierElement=self:_GetCargobay(CargoGroup)
if cargoBayItem and cargoBayIndex then
-- Debug info.
self:T(self.lid..string.format("Removing cargo group %s from cargo bay (index=%d) of carrier %s", CargoGroup:GetName(), cargoBayIndex, CarrierElement.name))
-- Remove
table.remove(CarrierElement.cargoBay, cargoBayIndex)
-- Reduce weight (if cargo space was not just reserved).
if not cargoBayItem.reserved then
local weight=CargoGroup:GetWeightTotal()
self:RedWeightCargo(CarrierElement.name, weight)
end
return true
return true
end
self:E(self.lid.."ERROR: Group is not in cargo bay. Cannot remove it!")
@ -5534,13 +5535,13 @@ end
-- @param Ops.OpsTransport#OPSTRANSPORT CargoTransport Cargo transport do be deleted.
-- @return #OPSGROUP self
function OPSGROUP:DelOpsTransport(CargoTransport)
for i=#self.cargoqueue,1,-1 do
local transport=self.cargoqueue[i] --Ops.OpsTransport#OPSTRANSPORT
if transport.uid==CargoTransport.uid then
table.remove(self.cargoqueue, i)
return self
end
end
end
return self
@ -5561,19 +5562,19 @@ function OPSGROUP:GetWeightTotal(UnitName, IncludeReserved)
if (UnitName==nil or UnitName==element.name) and element.status~=OPSGROUP.ElementStatus.DEAD then
weight=weight+element.weightEmpty
for _,_cargo in pairs(element.cargoBay) do
local cargo=_cargo --#OPSGROUP.MyCargo
local wcargo=0
-- Count cargo that is not reserved or if reserved cargo should be included.
if (not cargo.reserved) or (cargo.reserved==true and (IncludeReserved==true or IncludeReserved==nil)) then
if (not cargo.reserved) or (cargo.reserved==true and (IncludeReserved==true or IncludeReserved==nil)) then
wcargo=cargo.group:GetWeightTotal(element.name)
end
weight=weight+wcargo
end
end
@ -5592,16 +5593,16 @@ function OPSGROUP:GetFreeCargobay(UnitName, IncludeReserved)
-- Max cargo weight.
local weightCargoMax=self:GetWeightCargoMax(UnitName)
-- Current cargo weight.
local weightCargo=self:GetWeightCargo(UnitName, IncludeReserved)
-- Free cargo.
local Free=weightCargoMax-weightCargo
-- Debug info.
self:T(self.lid..string.format("Free cargo bay=%d kg (unit=%s)", Free, (UnitName or "whole group")))
return Free
end
@ -5613,11 +5614,11 @@ end
function OPSGROUP:GetFreeCargobayRelative(UnitName, IncludeReserved)
local free=self:GetFreeCargobay(UnitName, IncludeReserved)
local total=self:GetWeightCargoMax(UnitName)
local percent=free/total*100
return percent
end
@ -5683,24 +5684,24 @@ function OPSGROUP:GetWeightCargo(UnitName, IncludeReserved)
end
-- Calculate weight from stuff in cargo bay. By default this includes the reserved weight if a cargo group was assigned and is currently boarding.
local gewicht=0
local gewicht=0
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
if (UnitName==nil or UnitName==element.name) and (element and element.status~=OPSGROUP.ElementStatus.DEAD) then
for _,_cargo in pairs(element.cargoBay) do
local cargo=_cargo --#OPSGROUP.MyCargo
if (not cargo.reserved) or (cargo.reserved==true and (IncludeReserved==true or IncludeReserved==nil)) then
local cargoweight=cargo.group:GetWeightTotal()
local cargoweight=cargo.group:GetWeightTotal()
gewicht=gewicht+cargoweight
--self:I(self.lid..string.format("unit=%s (reserved=%s): cargo=%s weight=%d, total weight=%d", tostring(UnitName), tostring(IncludeReserved), cargo.group:GetName(), cargoweight, weight))
end
end
end
end
end
-- Debug info.
self:T2(self.lid..string.format("Unit=%s (reserved=%s): weight=%d, gewicht=%d", tostring(UnitName), tostring(IncludeReserved), weight, gewicht))
-- Quick check.
if IncludeReserved==false and gewicht~=weight then
self:E(self.lid..string.format("ERROR: FF weight!=gewicht: weight=%.1f, gewicht=%.1f", weight, gewicht))
@ -5759,7 +5760,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight)
-- Add weight.
element.weightCargo=element.weightCargo+Weight
-- Debug info.
self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo))
@ -5848,7 +5849,7 @@ function OPSGROUP:_SetMyCarrier(CarrierGroup, CarrierElement, Reserved)
self.mycarrier.group=CarrierGroup
self.mycarrier.element=CarrierElement
self.mycarrier.reserved=Reserved
self.cargoTransportUID=CarrierGroup.cargoTransport and CarrierGroup.cargoTransport.uid or nil
end
@ -5961,10 +5962,10 @@ function OPSGROUP:onafterPickup(From, Event, To)
-- Add waypoint.
if self.isFlightgroup then
---
-- Flight Group
---
---
if airbasePickup then
@ -5994,11 +5995,11 @@ function OPSGROUP:onafterPickup(From, Event, To)
---
-- Helo can also land in a zone (NOTE: currently VTOL cannot!)
---
-- Activate uncontrolled group.
if self:IsParking() then
self:StartUncontrolled()
end
end
-- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone.
Coordinate:SetAltitude(200)
@ -6007,7 +6008,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
else
self:E(self.lid.."ERROR: Carrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone")
end
elseif self.isNavygroup then
---
@ -6040,7 +6041,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
---
-- Army Group
---
---
local cwp=self:GetWaypointCurrent()
local uid=cwp and cwp.uid or nil
@ -6059,7 +6060,7 @@ function OPSGROUP:onafterPickup(From, Event, To)
-- ARMYGROUP
local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1
self:__Cruise(-2)
end
@ -6101,7 +6102,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
-- Cargo MUST be inside zone or it will not be loaded!
if inzone then
-- Find a carrier for this cargo.
-- Find a carrier for this cargo.
local carrier=self:FindCarrierForCargo(cargo.opsgroup)
if carrier then
@ -6114,7 +6115,7 @@ function OPSGROUP:onafterLoading(From, Event, To)
else
-- Debug info.
self:T(self.lid..string.format("Cannot board carrier! Group %s is NOT (yet) in zone %s", cargo.opsgroup:GetName(), self.cargoTransport.embarkzone:GetName()))
self:T(self.lid..string.format("Cannot board carrier! Group %s is NOT (yet) in zone %s", cargo.opsgroup:GetName(), self.cargoTransport.embarkzone:GetName()))
end
else
@ -6179,7 +6180,7 @@ function OPSGROUP:_NewCarrierStatus(Status)
end
--- Transfer cargo from to another carrier.
--- Transfer cargo from to another carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP CargoGroup The cargo group to be transferred.
-- @param #OPSGROUP CarrierGroup The new carrier group.
@ -6188,11 +6189,11 @@ function OPSGROUP:_TransferCargo(CargoGroup, CarrierGroup, CarrierElement)
-- Debug info.
self:T(self.lid..string.format("Transferring cargo %s to new carrier group %s", CargoGroup:GetName(), CarrierGroup:GetName()))
-- Unload from this and directly load into the other carrier.
self:Unload(CargoGroup)
CarrierGroup:Load(CargoGroup, CarrierElement)
end
--- On after "Load" event. Carrier loads a cargo group into ints cargo bay.
@ -6221,7 +6222,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
---
-- Embark Cargo
---
-- New cargo status.
CargoGroup:_NewCargoStatus(OPSGROUP.CargoStatus.LOADED)
@ -6238,7 +6239,7 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier)
-- Trigger embarked event for cargo group.
CargoGroup:Embarked(self, carrier)
-- Trigger "Loaded" event for current cargo transport.
if self.cargoTransport then
self.cargoTransport:Loaded(CargoGroup, self, carrier)
@ -6393,7 +6394,7 @@ function OPSGROUP:onafterTransport(From, Event, To)
local uid=cwp and cwp.uid or nil
local path=self.cargoTransport:_GetPathTransport()
if path then
-- Loop over coordinates.
for i,coordinate in pairs(path) do
@ -6486,8 +6487,8 @@ function OPSGROUP:onafterUnloading(From, Event, To)
---
-- Delivered to another carrier group.
---
---
self:_TransferCargo(cargo.opsgroup, carrierGroup, carrier)
elseif zone and zone:IsInstanceOf("ZONE_AIRBASE") and zone:GetAirbase():IsShip() then
@ -6581,7 +6582,7 @@ end
-- @param #boolean Activated If `true`, group is active. If `false`, group is spawned in late activated state.
-- @param #number Heading (Optional) Heading of group in degrees. Default is random heading for each unit.
function OPSGROUP:onafterUnload(From, Event, To, OpsGroup, Coordinate, Activated, Heading)
-- New cargo status.
OpsGroup:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
@ -6660,7 +6661,7 @@ function OPSGROUP:onafterUnload(From, Event, To, OpsGroup, Coordinate, Activated
-- Trigger "Disembarked" event.
OpsGroup:Disembarked(OpsGroup:_GetMyCarrierGroup(), OpsGroup:_GetMyCarrierElement())
-- Trigger "Unloaded" event.
self:Unloaded(OpsGroup)
@ -6725,7 +6726,7 @@ function OPSGROUP:onafterDelivered(From, Event, To, CargoTransport)
-- Check if this was the current transport.
if self.cargoTransport and self.cargoTransport.uid==CargoTransport.uid then
-- This is not a carrier anymore.
self:_NewCarrierStatus(OPSGROUP.CarrierStatus.NOTCARRIER)
@ -6810,7 +6811,7 @@ end
function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
-- Set cargo status.
self:_NewCargoStatus(OPSGROUP.CargoStatus.BOARDING)
self:_NewCargoStatus(OPSGROUP.CargoStatus.BOARDING)
-- Army or Navy group.
local CarrierIsArmyOrNavy=CarrierGroup:IsArmygroup() or CarrierGroup:IsNavygroup()
@ -6857,9 +6858,9 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
-- Debug info.
self:T(self.lid..string.format("Board with direct load to carrier %s", CarrierGroup:GetName()))
local mycarriergroup=self:_GetMyCarrierGroup()
-- Unload cargo first.
if mycarriergroup then
mycarriergroup:Unload(self)
@ -6871,14 +6872,14 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
end
else
-- Redo boarding call.
self:T(self.lid.."Carrier not ready for boarding yet ==> repeating boarding call in 10 sec")
self:__Board(-10, CarrierGroup, Carrier)
-- Set carrier. As long as the group is not loaded, we only reserve the cargo space.´
-- Set carrier. As long as the group is not loaded, we only reserve the cargo space.<EFBFBD>
CarrierGroup:_AddCargobay(self, Carrier, true)
end
@ -7315,29 +7316,29 @@ function OPSGROUP:_CheckAmmoStatus()
-- Missiles AA.
if self.outofMissilesAA and ammo.MissilesAA>0 then
self.outofMissilesAA=false
end
end
if ammo.MissilesAA and self.ammo.MissilesAA>0 and not self.outofMissilesAA then
self.outofMissilesAA=true
self:OutOfMissilesAA()
self:OutOfMissilesAA()
end
-- Missiles AG.
if self.outofMissilesAG and ammo.MissilesAG>0 then
self.outofMissilesAG=false
end
end
if ammo.MissilesAG and self.ammo.MissilesAG>0 and not self.outofMissilesAG then
self.outofMissilesAG=true
self:OutOfMissilesAG()
end
self:OutOfMissilesAG()
end
-- Missiles AS.
if self.outofMissilesAS and ammo.MissilesAS>0 then
self.outofMissilesAS=false
end
end
if ammo.MissilesAS and self.ammo.MissilesAS>0 and not self.outofMissilesAS then
self.outofMissilesAS=true
self:OutOfMissilesAS()
end
self:OutOfMissilesAS()
end
-- Check if group is engaging.
@ -7465,10 +7466,10 @@ function OPSGROUP:_AddWaypoint(waypoint, wpnumber)
self:T(self.lid..string.format("Adding waypoint at index=%d with UID=%d", wpnumber, waypoint.uid))
-- Now we obviously did not pass the final waypoint.
if self.currentwp and wpnumber>self.currentwp then
if self.currentwp and wpnumber>self.currentwp then
self.passedfinalwp=false
end
end
--- Initialize Mission Editor waypoints.
@ -7483,19 +7484,19 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
-- Waypoints empty!
self.waypoints={}
WpIndexMin=WpIndexMin or 1
WpIndexMax=WpIndexMax or #self.waypoints0
WpIndexMax=WpIndexMax or #self.waypoints0
WpIndexMax=math.min(WpIndexMax, #self.waypoints0) --Ensure max is not out of bounce.
--for index,wp in pairs(self.waypoints0) do
for i=WpIndexMin,WpIndexMax do
local wp=self.waypoints0[i] --DCS#Waypoint
-- Coordinate of the waypoint.
local coordinate=COORDINATE:NewFromWaypoint(wp)
local coordinate=COORDINATE:NewFromWaypoint(wp)
-- Strange!
wp.speed=wp.speed or 0
@ -7506,30 +7507,30 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
if i==1 then
self.speedWp=wp.speed
end
local waypoint=self:_CreateWaypoint(wp)
self:_AddWaypoint(waypoint)
-- Add waypoint.
--[[
if self:IsFlightgroup() then
FLIGHTGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Altitude, false)
elseif self:IsArmygroup() then
elseif self:IsArmygroup() then
ARMYGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Formation, false)
elseif self:IsNavygroup() then
elseif self:IsNavygroup() then
NAVYGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Depth, false)
else
-- Should not happen!
self:AddWaypoint(coordinate, speedknots, index-1, nil, false)
end
]]
end
-- Debug info.
self:T(self.lid..string.format("Initializing %d waypoints", #self.waypoints))
-- Flight group specific.
if self:IsFlightgroup() then
@ -7537,14 +7538,14 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
self.homebase=self.homebase or self:GetHomebaseFromWaypoints()
self.destbase=self.destbase or self:GetDestinationFromWaypoints()
self.currbase=self:GetHomebaseFromWaypoints()
-- Remove the landing waypoint. We use RTB for that. It makes adding new waypoints easier as we do not have to check if the last waypoint is the landing waypoint.
if self.destbase and #self.waypoints>1 then
table.remove(self.waypoints, #self.waypoints)
else
self.destbase=self.homebase
end
end
-- Update route.
@ -7554,7 +7555,7 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
if #self.waypoints==1 then
self.passedfinalwp=true
end
else
self:E(self.lid.."WARNING: No waypoints initialized. Number of waypoints is 0!")
end
@ -8469,12 +8470,12 @@ function OPSGROUP:SwitchCallsign(CallsignName, CallsignNumber)
-- Give command to change the callsign.
self.group:CommandSetCallsign(self.callsign.NumberSquad, self.callsign.NumberGroup)
-- Callsign of the group, e.g. Colt-1
self.callsignName=UTILS.GetCallsignName(self.callsign.NumberSquad).."-"..self.callsign.NumberGroup
self.callsign.NameSquad=UTILS.GetCallsignName(self.callsign.NumberSquad)
-- Set callsign of elements.
-- Set callsign of elements.
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
if element.status~=OPSGROUP.ElementStatus.DEAD then
@ -8862,7 +8863,7 @@ function OPSGROUP:GetElementZoneBoundingBox(UnitName)
-- Orientation vector.
local X=self:GetOrientationX(element.name)
-- Heading in degrees.
local heading=math.deg(math.atan2(X.z, X.x))
@ -9406,7 +9407,7 @@ function OPSGROUP:_AddElementByName(unitname)
-- Max cargo weight:
unit:SetCargoBayWeightLimit()
element.weightMaxCargo=unit.__.CargoBayWeightLimit
-- Cargo bay (empty).
element.cargoBay={}
@ -9460,7 +9461,7 @@ function OPSGROUP:_SetTemplate(Template)
-- Set the template.
self.template=Template or self.group:GetTemplate()
-- Debug info.
self:T3(self.lid.."Setting group template")
@ -9481,9 +9482,9 @@ function OPSGROUP:_GetTemplate(Copy)
else
return self.template
end
else
self:E(self.lid..string.format("ERROR: No template was set yet!"))
self:E(self.lid..string.format("ERROR: No template was set yet!"))
end
return nil

View File

@ -88,10 +88,19 @@
--
-- Use a specific "culture" with the @{#MSRS.SetCulture} function, e.g. `:SetCulture("en-US")` or `:SetCulture("de-DE")`.
--
-- ## Set Google
--
-- Use Google's text-to-speech engine with the @{#MSRS.SetGoogle} function, e.g. ':SetGoogle()'.
-- By enabling this it also allows you to utilize SSML in your text for added flexibilty.
-- For more information on setting up a cloud account, visit: https://cloud.google.com/text-to-speech
-- Google's supported SSML reference: https://cloud.google.com/text-to-speech/docs/ssml
--
-- ## Set Voice
--
-- Use a specifc voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
-- Note that this must be installed on your windows system.
-- If enabling SetGoogle(), you can use voices provided by Google
-- Google's supported voices: https://cloud.google.com/text-to-speech/docs/voices
--
-- ## Set Coordinate
--
@ -678,7 +687,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
-- Set google.
if self.google then
command=command..string.format(' -G "%s"', self.google)
command=command..string.format(' --ssml -G "%s"', self.google)
end
-- Debug output.

View File

@ -216,7 +216,7 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local MenuReporting = MENU_GROUP:New( EventGroup, "Missions Reports", CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Status Report", MenuReporting, self.ReportSummary, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Players Report", MenuReporting, self.ReportMissionsPlayers, self, EventGroup )
self:ReportSummary( EventGroup )
--self:ReportSummary( EventGroup )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION

View File

@ -710,7 +710,7 @@ do -- TASK_CARGO_DISPATCHER
self.TransportCount = self.TransportCount + 1
local verbose = Silent and true
local verbose = Silent or false
local TaskName = string.format( ( TaskPrefix or "Transport" ) .. ".%03d", self.TransportCount )

View File

@ -2,7 +2,7 @@
--
-- **Specific features:**
--
-- * Creates a task to transport @{Cargo.Cargo} to and between deployment zones.
-- * Creates a task to transport #Cargo.Cargo to and between deployment zones.
-- * Derived from the TASK_CARGO class, which is derived from the TASK class.
-- * Orchestrate the task flow, so go from Planned to Assigned to Success, Failed or Cancelled.
-- * Co-operation tasking, so a player joins a group of players executing the same task.
@ -44,7 +44,7 @@
--
-- ===
--
-- Please read through the @{Tasking.Task_Cargo} process to understand the mechanisms of tasking and cargo tasking and handling.
-- Please read through the #Tasking.Task_Cargo process to understand the mechanisms of tasking and cargo tasking and handling.
--
-- Enjoy!
-- FC
@ -57,7 +57,7 @@
do -- TASK_CARGO_TRANSPORT
--- @type TASK_CARGO_TRANSPORT
-- @type TASK_CARGO_TRANSPORT
-- @extends Tasking.Task_CARGO#TASK_CARGO
--- Orchestrates the task for players to transport cargo to or between deployment zones.
@ -76,7 +76,7 @@ do -- TASK_CARGO_TRANSPORT
--
-- ## 1.1) Create a command center.
--
-- First you need to create a command center using the @{Tasking.CommandCenter#COMMANDCENTER.New}() constructor.
-- First you need to create a command center using the Tasking.CommandCenter#COMMANDCENTER.New constructor.
--
-- local CommandCenter = COMMANDCENTER
-- :New( HQ, "Lima" ) -- Create the CommandCenter.
@ -85,7 +85,7 @@ do -- TASK_CARGO_TRANSPORT
--
-- Tasks work in a mission, which groups these tasks to achieve a joint mission goal.
-- A command center can govern multiple missions.
-- Create a new mission, using the @{Tasking.Mission#MISSION.New}() constructor.
-- Create a new mission, using the Tasking.Mission#MISSION.New constructor.
--
-- -- Declare the Mission for the Command Center.
-- local Mission = MISSION
@ -99,7 +99,7 @@ do -- TASK_CARGO_TRANSPORT
-- ## 1.3) Create the transport cargo task.
--
-- So, now that we have a command center and a mission, we now create the transport task.
-- We create the transport task using the @{#TASK_CARGO_TRANSPORT.New}() constructor.
-- We create the transport task using the #TASK_CARGO_TRANSPORT.New constructor.
--
-- Because a transport task will not generate the cargo itself, you'll need to create it first.
-- The cargo in this case will be the downed pilot!
@ -118,7 +118,7 @@ do -- TASK_CARGO_TRANSPORT
-- -- The cargoset "CargoSet" will embed all defined cargo of type "Pilots" (prefix) into its set.
-- local CargoGroup = CARGO_GROUP:New( PilotGroup, "Cargo", "Engineer Team 1", 500 )
--
-- What is also needed, is to have a set of @{Core.Group}s defined that contains the clients of the players.
-- What is also needed, is to have a set of Core.Groups defined that contains the clients of the players.
--
-- -- Allocate the Transport, which are the helicopter to retrieve the pilot, that can be manned by players.
-- local GroupSet = SET_GROUP:New():FilterPrefixes( "Transport" ):FilterStart()
@ -139,48 +139,48 @@ do -- TASK_CARGO_TRANSPORT
-- By doing this, cargo transport tasking will become a dynamic experience.
--
--
-- # 2) Create a task using the @{Tasking.Task_Cargo_Dispatcher} module.
-- # 2) Create a task using the Tasking.Task_Cargo_Dispatcher module.
--
-- Actually, it is better to **GENERATE** these tasks using the @{Tasking.Task_Cargo_Dispatcher} module.
-- Using the dispatcher module, transport tasks can be created much more easy.
-- Actually, it is better to **GENERATE** these tasks using the Tasking.Task_Cargo_Dispatcher module.
-- Using the dispatcher module, transport tasks can be created easier.
--
-- Find below an example how to use the TASK_CARGO_DISPATCHER class:
--
--
-- -- Find the HQ group.
-- HQ = GROUP:FindByName( "HQ", "Bravo" )
-- -- Find the HQ group.
-- HQ = GROUP:FindByName( "HQ", "Bravo" )
--
-- -- Create the command center with the name "Lima".
-- CommandCenter = COMMANDCENTER
-- :New( HQ, "Lima" )
-- -- Create the command center with the name "Lima".
-- CommandCenter = COMMANDCENTER
-- :New( HQ, "Lima" )
--
-- -- Create the mission, for the command center, with the name "Operation Cargo Fun", a "Tactical" mission, with the mission briefing "Transport Cargo", for the BLUE coalition.
-- Mission = MISSION
-- :New( CommandCenter, "Operation Cargo Fun", "Tactical", "Transport Cargo", coalition.side.BLUE )
-- -- Create the mission, for the command center, with the name "Operation Cargo Fun", a "Tactical" mission, with the mission briefing "Transport Cargo", for the BLUE coalition.
-- Mission = MISSION
-- :New( CommandCenter, "Operation Cargo Fun", "Tactical", "Transport Cargo", coalition.side.BLUE )
--
-- -- Create the SET of GROUPs containing clients (players) that will transport the cargo.
-- -- These are have a name that start with "Transport" and are of the "blue" coalition.
-- TransportGroups = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Transport" ):FilterStart()
-- -- Create the SET of GROUPs containing clients (players) that will transport the cargo.
-- -- These are have a name that start with "Transport" and are of the "blue" coalition.
-- TransportGroups = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Transport" ):FilterStart()
--
--
-- -- Here we create the TASK_CARGO_DISPATCHER object! This is where we assign the dispatcher to generate tasks in the Mission for the TransportGroups.
-- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, TransportGroups )
-- -- Here we create the TASK_CARGO_DISPATCHER object! This is where we assign the dispatcher to generate tasks in the Mission for the TransportGroups.
-- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, TransportGroups )
--
--
-- -- Here we declare the SET of CARGOs called "Workmaterials".
-- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart()
-- -- Here we declare the SET of CARGOs called "Workmaterials".
-- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart()
--
-- -- Here we declare (add) CARGO_GROUP objects of various types, that are filtered and added in the CargoSetworkmaterials cargo set.
-- -- These cargo objects have the type "Workmaterials" which is exactly the type of cargo the CargoSetworkmaterials is filtering on.
-- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 )
-- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 )
-- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 )
-- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 )
-- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 )
-- -- Here we declare (add) CARGO_GROUP objects of various types, that are filtered and added in the CargoSetworkmaterials cargo set.
-- -- These cargo objects have the type "Workmaterials" which is exactly the type of cargo the CargoSetworkmaterials is filtering on.
-- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 )
-- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 )
-- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 )
-- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 )
-- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 )
--
-- -- And here we create a new WorkplaceTask, using the :AddTransportTask method of the TaskDispatcher.
-- local WorkplaceTask = TaskDispatcher:AddTransportTask( "Build a Workplace", CargoSetWorkmaterials, "Transport the workers, engineers and the equipment near the Workplace." )
-- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) )
-- -- And here we create a new WorkplaceTask, using the :AddTransportTask method of the TaskDispatcher.
-- local WorkplaceTask = TaskDispatcher:AddTransportTask( "Build a Workplace", CargoSetWorkmaterials, "Transport the workers, engineers and the equipment near the Workplace." )
-- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) )
--
-- # 3) Handle cargo task events.
--
@ -189,7 +189,7 @@ do -- TASK_CARGO_TRANSPORT
-- In order to properly capture the events and avoid mistakes using the documentation, it is advised that you execute the following actions:
--
-- * **Copy / Paste** the code section into your script.
-- * **Change** the CLASS literal to the task object name you have in your script.
-- * **Change** the "myclass" literal to the task object name you have in your script.
-- * Within the function, you can now **write your own code**!
-- * **IntelliSense** will recognize the type of the variables provided by the function. Note: the From, Event and To variables can be safely ignored,
-- but you need to declare them as they are automatically provided by the event handling system of MOOSE.
@ -210,14 +210,13 @@ do -- TASK_CARGO_TRANSPORT
-- If you want to code your own event handler, use this code fragment to tailor the event when a player carrier has picked up a cargo object in the CarrierGroup.
-- You can use this event handler to post messages to players, or provide status updates etc.
--
-- --- CargoPickedUp event handler OnAfter for CLASS.
-- -- @param #CLASS self
-- --- CargoPickedUp event handler OnAfter for "myclass".
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Unit#UNIT TaskUnit The unit (client) of the player that has picked up the cargo.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object that has been picked up. Note that this can be a CARGO_GROUP, CARGO_CRATE or CARGO_SLINGLOAD object!
-- function CLASS:OnAfterCargoPickedUp( From, Event, To, TaskUnit, Cargo )
-- function myclass:OnAfterCargoPickedUp( From, Event, To, TaskUnit, Cargo )
--
-- -- Write here your own code.
--
@ -240,15 +239,14 @@ do -- TASK_CARGO_TRANSPORT
-- You can use this event handler to post messages to players, or provide status updates etc.
--
--
-- --- CargoDeployed event handler OnAfter for CLASS.
-- -- @param #CLASS self
-- --- CargoDeployed event handler OnAfter foR "myclass".
-- -- @param #string From A string that contains the "*from state name*" when the event was triggered.
-- -- @param #string Event A string that contains the "*event name*" when the event was triggered.
-- -- @param #string To A string that contains the "*to state name*" when the event was triggered.
-- -- @param Wrapper.Unit#UNIT TaskUnit The unit (client) of the player that has deployed the cargo.
-- -- @param Cargo.Cargo#CARGO Cargo The cargo object that has been deployed. Note that this can be a CARGO_GROUP, CARGO_CRATE or CARGO_SLINGLOAD object!
-- -- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
-- function CLASS:OnAfterCargoDeployed( From, Event, To, TaskUnit, Cargo, DeployZone )
-- function myclass:OnAfterCargoDeployed( From, Event, To, TaskUnit, Cargo, DeployZone )
--
-- -- Write here your own code.
--

View File

@ -1675,6 +1675,11 @@ function UTILS.IsLoadingDoorOpen( unit_name )
ret_val = true
end
if string.find(type_name, "Bell-47") then -- bell aint got no doors so always ready to load injured soldiers
BASE:T(unit_name .. " door is open")
ret_val = true
end
if ret_val == false then
BASE:T(unit_name .. " all doors are closed")
end

View File

@ -563,12 +563,12 @@ function GROUP:GetSpeedMax()
local Units=self:GetUnits()
local speedmax=nil
local speedmax=0
for _,unit in pairs(Units) do
local unit=unit --Wrapper.Unit#UNIT
local speed=unit:GetSpeedMax()
if speedmax==nil then
if speedmax==0 then
speedmax=speed
elseif speed<speedmax then
speedmax=speed

View File

@ -442,7 +442,7 @@ function UNIT:GetSpeedMax()
return SpeedMax*3.6
end
return nil
return 0
end
--- Returns the unit's max range in meters derived from the DCS descriptors.

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\ProgramData\chocolatey\lib\lua51\tools\lua5.1.exe"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose Setup\Moose_Create.lua&quot; &quot;D&quot; &quot;LOCAL&quot; &quot;${resource_loc:/MOOSE/Moose Development/Moose}&quot; &quot;${resource_loc:/MOOSE/Moose Setup}&quot;&#13;&#10;${resource_loc:/MOOSE_INCLUDE/Moose_Include_Dynamic}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/MOOSE}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/lua54/lua54.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose Setup/Moose_Create.lua&quot; &quot;D&quot; &quot;LOCAL&quot; &quot;${workspace_loc:/Moose_Framework/Moose Development/Moose}&quot; &quot;${workspace_loc:/Moose_Framework/Moose Setup}&quot;&#13;&#10;&quot;${workspace_loc:/Moose_Framework/MOOSE_INCLUDE\Moose_Include_Dynamic}&quot; 1"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework}"/>
</launchConfiguration>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="C:\ProgramData\chocolatey\lib\lua51\tools\lua5.1.exe"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose Setup\Moose_Create.lua&quot; &quot;S&quot; &quot;LOCAL&quot; &quot;${resource_loc:/MOOSE/Moose Development/Moose}&quot; &quot;${resource_loc:/MOOSE/Moose Setup}&quot;&#13;&#10;${resource_loc:/MOOSE_INCLUDE/Moose_Include_Static}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/MOOSE}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/Moose_Framework/lua54/lua54.exe}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="&quot;Moose Setup\Moose_Create.lua&quot; &quot;S&quot; &quot;LOCAL&quot; &quot;${workspace_loc:/Moose_Framework/Moose Development/Moose}&quot; &quot;${workspace_loc:/Moose_Framework/Moose Setup}&quot;&#13;&#10;&quot;${workspace_loc:/Moose_Framework/MOOSE_INCLUDE\Moose_Include_Static}&quot; 1"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/Moose_Framework}"/>
</launchConfiguration>

View File

@ -5,19 +5,32 @@ local MooseCommitHash = arg[2]
local MooseDevelopmentPath = arg[3]
local MooseSetupPath = arg[4]
local MooseTargetPath = arg[5]
local isWindows = arg[6]
if not isWindows then
isWindows = 0
end
print( "Moose (D)ynamic (S)tatic : " .. MooseDynamicStatic )
print( "Commit Hash ID : " .. MooseCommitHash )
print( "Moose development path : " .. MooseDevelopmentPath )
print( "Moose setup path : " .. MooseSetupPath )
print( "Moose target path : " .. MooseTargetPath )
print( "isWindows : " .. isWindows)
function PathConvert(splatnixPath)
if isWindows == 0 then
return splatnixPath
end
return splatnixPath:gsub("/", "\\")
end
local MooseModulesFilePath = MooseDevelopmentPath .. "/Modules.lua"
local LoaderFilePath = MooseTargetPath .. "/Moose.lua"
print( "Reading Moose source list : " .. MooseModulesFilePath )
local LoaderFile = io.open( LoaderFilePath, "w" )
print("Opening Loaderfile " .. PathConvert(LoaderFilePath))
local LoaderFile = assert(io.open( PathConvert(LoaderFilePath), "w+" ))
if MooseDynamicStatic == "S" then
LoaderFile:write( "env.info( '*** MOOSE GITHUB Commit Hash ID: " .. MooseCommitHash .. " ***' )\n" )
@ -31,13 +44,14 @@ if MooseDynamicStatic == "S" then
MooseLoaderPath = MooseSetupPath .. "/Moose Templates/Moose_Static_Loader.lua"
end
local MooseLoader = io.open( MooseLoaderPath, "r" )
local MooseLoader = assert(io.open( PathConvert(MooseLoaderPath), "r" ))
local MooseLoaderText = MooseLoader:read( "*a" )
MooseLoader:close()
LoaderFile:write( MooseLoaderText )
local MooseSourcesFile = io.open( MooseModulesFilePath, "r" )
local MooseSourcesFile = assert(io.open( PathConvert(MooseModulesFilePath), "r" ))
local MooseSource = MooseSourcesFile:read("*l")
while( MooseSource ) do
@ -50,7 +64,7 @@ while( MooseSource ) do
end
if MooseDynamicStatic == "S" then
print( "Load static: " .. MooseFilePath )
local MooseSourceFile = io.open( MooseFilePath, "r" )
local MooseSourceFile = assert(io.open( PathConvert(MooseFilePath), "r" ))
local MooseSourceFileText = MooseSourceFile:read( "*a" )
MooseSourceFile:close()
@ -72,3 +86,8 @@ LoaderFile:write( "env.info( '*** MOOSE INCLUDE END *** ' )\n" )
MooseSourcesFile:close()
LoaderFile:close()
print("Moose include generation complete.")
if MooseDynamicStatic == "D" then
print("To enable dynamic moose loading, add a soft or hard link from \"<YOUR_DCS_INSTALL_DIRECTORY>\\Scripts\\Moose\" to the \"Moose Development\\Moose\" subdirectory of the Moose_Framework repository.")
end

BIN
lua54/lua54.dll Normal file

Binary file not shown.

BIN
lua54/lua54.exe Normal file

Binary file not shown.