diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index df96af4c4..859c2e3c2 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -1,17 +1,17 @@ --- **Ops** -- Combat Search and Rescue. -- -- === --- +-- -- **CSAR** - MOOSE based Helicopter CSAR Operations. --- +-- -- === --- +-- -- ## Missions: -- -- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CSAR) --- +-- -- === --- +-- -- **Main Features:** -- -- * MOOSE-based Helicopter CSAR Operations for Players. @@ -40,22 +40,22 @@ -- ![Banner Image](OPS_CSAR.jpg) -- -- # CSAR Concept --- +-- -- * MOOSE-based Helicopter CSAR Operations for Players. --- * Object oriented refactoring of Ciribob's fantastic CSAR script. --- * No need for extra MIST loading. +-- * 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 CASEVAC requests). --- +-- * Optional SpawnCASEVAC to create casualties without beacon (e.g. handling dead ground vehicles and create CASVAC requests). +-- -- ## 0. Prerequisites --- --- You need to load an .ogg sound file for the pilot's beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that. +-- +-- You need to load an .ogg soundfile for the pilot\'s beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that. -- Create a late-activated single infantry unit as template in the mission editor and name it e.g. "Downed Pilot". --- +-- -- ## 1. Basic Setup --- +-- -- A basic setup example is the following: --- +-- -- -- Instantiate and start a CSAR for the blue side, with template "Downed Pilot" and alias "Luftrettung" -- local my_csar = CSAR:New(coalition.side.BLUE,"Downed Pilot","Luftrettung") -- -- options @@ -63,35 +63,35 @@ -- my_csar.invisiblecrew = false -- downed pilot spawn is visible -- -- start the FSM -- my_csar:__Start(5) --- +-- -- ## 2. Options --- +-- -- The following options are available (with their defaults). Only set the ones you want changed: -- --- self.allowDownedPilotCAcontrol = false -- Set to false if you don't want to allow control by Combined Arms. +-- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms. -- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only! -- self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued. --- self.autosmoke = false -- automatically smoke a downed pilot's location when a helicopter is near. --- self.autosmokedistance = 1000 -- distance in meters for automatic smoke deployment +-- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near. +-- self.autosmokedistance = 1000 -- distance for autosmoke -- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates. -- self.csarOncrash = false -- (WIP) If set to true, will generate a downed pilot when a plane crashes as well. -- self.enableForAI = false -- set to false to disable AI pilots from being rescued. --- self.pilotRuntoExtractPoint = true -- Downed pilot will run to the rescue helicopter up to self.extractDistance in meters. +-- self.pilotRuntoExtractPoint = true -- Downed pilot will run to the rescue helicopter up to self.extractDistance in meters. -- self.extractDistance = 500 -- Distance the downed pilot will start to run to the rescue helicopter. -- self.immortalcrew = true -- Set to true to make wounded crew immortal. --- self.invisiblecrew = false -- Set to true to make wounded crew invisible. +-- self.invisiblecrew = false -- Set to true to make wounded crew insvisible. -- self.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters. -- self.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. -- self.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined. -- self.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages. --- self.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots' radio beacons. --- self.smokecolor = 4 -- Color of smoke marker, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue. +-- self.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons. +-- self.smokecolor = 4 -- Color of smokemarker, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue. -- self.useprefix = true -- Requires CSAR helicopter #GROUP names to have the prefix(es) defined below. --- self.csarPrefix = { "helicargo", "MEDEVAC"} -- #GROUP name prefixes used for useprefix=true - DO NOT use # in helicopter names in the Mission Editor! +-- self.csarPrefix = { "helicargo", "MEDEVAC"} -- #GROUP name prefixes used for useprefix=true - DO NOT use # in helicopter names in the Mission Editor! -- self.verbose = 0 -- set to > 1 for stats output for debugging. -- -- (added 0.1.4) limit amount of downed pilots spawned by **ejection** events -- self.limitmaxdownedpilots = true --- self.maxdownedpilots = 10 +-- self.maxdownedpilots = 10 -- -- (added 0.1.8) - allow to set far/near distance for approach and optionally pilot must open doors -- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters -- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters @@ -106,13 +106,13 @@ -- 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! +-- +-- WARNING - Here\'ll be dragons! -- DANGER - For this to work you need to de-sanitize your mission environment (all three entries) in \Scripts\MissionScripting.lua -- Needs SRS => 1.9.6 to work (works on the **server** side of SRS) --- self.useSRS = false -- Set true to use FF's SRS integration +-- self.useSRS = false -- Set true to use FF\'s SRS integration -- 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 @@ -120,78 +120,78 @@ -- 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: --- +-- -- self.rescues -- number of successful landings *with* saved pilots -- self.rescuedpilots -- aggregated number of pilots rescued from the field (of *all* players) --- +-- -- ## 4. Events -- -- The class comes with a number of FSM-based events that missions designers can use to shape their mission. -- These are: --- --- ### 4.1. PilotDown. --- +-- +-- ### 4.1. PilotDown. +-- -- The event is triggered when a new downed pilot is detected. Use e.g. `function my_csar:OnAfterPilotDown(...)` to link into this event: --- +-- -- function my_csar:OnAfterPilotDown(from, event, to, spawnedgroup, frequency, groupname, coordinates_text) -- ... your code here ... -- end --- --- ### 4.2. Approach. --- --- A CSAR helicopter is closing in on a downed pilot. Use e.g. `function my_csar:OnAfterApproach(...)` to link into this event: --- +-- +-- ### 4.2. Approach. +-- +-- A CSAR helicpoter is closing in on a downed pilot. Use e.g. `function my_csar:OnAfterApproach(...)` to link into this event: +-- -- function my_csar:OnAfterApproach(from, event, to, heliname, groupname) -- ... your code here ... -- end --- --- ### 4.3. Boarded. --- +-- +-- ### 4.3. Boarded. +-- -- The pilot has been boarded to the helicopter. Use e.g. `function my_csar:OnAfterBoarded(...)` to link into this event: --- +-- -- function my_csar:OnAfterBoarded(from, event, to, heliname, groupname) -- ... your code here ... -- end --- --- ### 4.4. Returning. --- +-- +-- ### 4.4. Returning. +-- -- The CSAR helicopter is ready to return to an Airbase, FARP or MASH. Use e.g. `function my_csar:OnAfterReturning(...)` to link into this event: --- +-- -- function my_csar:OnAfterReturning(from, event, to, heliname, groupname) -- ... your code here ... -- end --- --- ### 4.5. Rescued. --- +-- +-- ### 4.5. Rescued. +-- -- The CSAR helicopter has landed close to an Airbase/MASH/FARP and the pilots are safe. Use e.g. `function my_csar:OnAfterRescued(...)` to link into this event: --- +-- -- function my_csar:OnAfterRescued(from, event, to, heliunit, heliname, pilotssaved) -- ... your code here ... --- end +-- end -- -- ## 5. Spawn downed pilots at location to be picked up. --- +-- -- If missions designers want to spawn downed pilots into the field, e.g. at mission begin to give the helicopter guys works, they can do this like so: --- +-- -- -- 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) +-- my_csar:SpawnCASEVAC(Point, coalition.side.BLUE) -- -- @field #CSAR CSAR = { - ClassName = "CSAR", - verbose = 0, - lid = "", - coalition = 1, - coalitiontxt = "blue", + ClassName = "CSAR", + verbose = 0, + lid = "", + coalition = 1, + coalitiontxt = "blue", FreeVHFFrequencies = {}, UsedVHFFrequencies = {}, takenOff = {}, - csarUnits = {}, -- table of unit names + csarUnits = {}, -- table of unit names downedPilots = {}, woundedGroups = {}, landedStatus = {}, @@ -201,11 +201,11 @@ CSAR = { smokeMarkers = {}, -- tracks smoke markers for groups heliVisibleMessage = {}, -- tracks if the first message has been sent of the heli being visible heliCloseMessage = {}, -- tracks heli close message ie heli < 500m distance - max_units = 6, -- number of pilots that can be carried + max_units = 6, --number of pilots that can be carried hoverStatus = {}, -- tracks status of a helis hover above a downed pilot pilotDisabled = {}, -- tracks what aircraft a pilot is disabled for pilotLives = {}, -- tracks how many lives a pilot has - useprefix = true, -- Use the Prefix defined below, requires Unit to have the Prefix defined + useprefix = true, -- Use the Prefixed defined below, Requires Unit have the Prefix defined below csarPrefix = {}, template = nil, mash = {}, @@ -240,14 +240,15 @@ CSAR.AircraftType["SA342L"] = 4 CSAR.AircraftType["SA342M"] = 4 CSAR.AircraftType["UH-1H"] = 8 CSAR.AircraftType["Mi-8MTV2"] = 12 -CSAR.AircraftType["Mi-8MT"] = 12 -CSAR.AircraftType["Mi-24P"] = 8 +CSAR.AircraftType["Mi-8MT"] = 12 +CSAR.AircraftType["Mi-24P"] = 8 CSAR.AircraftType["Mi-24V"] = 8 -CSAR.AircraftType["Bell-47"] = 2 +CSAR.AircraftType["Bell-47"] = 2 +CSAR.AircraftType["UH-60L"] = 10 --- CSAR class version. -- @field #string version -CSAR.version = "1.0.1r1" +CSAR.version="1.0.2" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -266,49 +267,49 @@ CSAR.version = "1.0.1r1" -- @param #string Template Name of the late activated infantry unit standing in for the downed pilot. -- @param #string Alias An *optional* alias how this object is called in the logs etc. -- @return #CSAR self -function CSAR:New( Coalition, Template, Alias ) - +function CSAR:New(Coalition, Template, Alias) + -- Inherit everything from FSM class. - local self = BASE:Inherit( self, FSM:New() ) -- #CSAR - - -- set Coalition - if Coalition and type( Coalition ) == "string" then - if Coalition == "blue" then - self.coalition = coalition.side.BLUE + local self=BASE:Inherit(self, FSM:New()) -- #CSAR + + --set Coalition + if Coalition and type(Coalition)=="string" then + if Coalition=="blue" then + self.coalition=coalition.side.BLUE self.coalitiontxt = Coalition - elseif Coalition == "red" then - self.coalition = coalition.side.RED + elseif Coalition=="red" then + self.coalition=coalition.side.RED self.coalitiontxt = Coalition - elseif Coalition == "neutral" then - self.coalition = coalition.side.NEUTRAL + elseif Coalition=="neutral" then + self.coalition=coalition.side.NEUTRAL self.coalitiontxt = Coalition else - self:E( "ERROR: Unknown coalition in CSAR!" ) + self:E("ERROR: Unknown coalition in CSAR!") end else self.coalition = Coalition - self.coalitiontxt = string.lower( UTILS.GetCoalitionName( self.coalition ) ) + self.coalitiontxt = string.lower(UTILS.GetCoalitionName(self.coalition)) end - + -- Set alias. if Alias then - self.alias = tostring( Alias ) + self.alias=tostring(Alias) else - self.alias = "Red Cross" + self.alias="Red Cross" if self.coalition then - if self.coalition == coalition.side.RED then - self.alias = "IFRC" - elseif self.coalition == coalition.side.BLUE then - self.alias = "CSAR" + if self.coalition==coalition.side.RED then + self.alias="IFRC" + elseif self.coalition==coalition.side.BLUE then + self.alias="CSAR" end end end - + -- Set some string id for output to DCS.log file. - self.lid = string.format( "%s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName( self.coalition ) or "unknown" ) - + self.lid=string.format("%s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown") + -- Start State. - self:SetStartState( "Stopped" ) + self:SetStartState("Stopped") -- Add FSM transitions. -- From State --> Event --> To State @@ -339,70 +340,70 @@ function CSAR:New( Coalition, Template, Alias ) self.woundedGroups = {} -- contains the new group of units self.downedPilots = {} -- Replacement woundedGroups self.downedpilotcounter = 1 - + -- settings, counters etc self.rescues = 0 -- counter for successful rescue landings at FARP/AFB/MASH self.rescuedpilots = 0 -- counter for saved pilots self.csarOncrash = false -- If set to true, will generate a csar when a plane crashes as well. - self.allowDownedPilotCAcontrol = false -- Set to false if you don't want to allow control by Combined arms. + self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined arms. self.enableForAI = false -- set to false to disable AI units from being rescued. - self.smokecolor = 4 -- Color of smoke marker for blue side, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue + self.smokecolor = 4 -- Color of smokemarker for blue side, 0 is green, 1 is red, 2 is white, 3 is orange and 4 is blue self.coordtype = 2 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates. self.immortalcrew = true -- Set to true to make wounded crew immortal - self.invisiblecrew = false -- Set to true to make wounded crew invisible - self.messageTime = 15 -- Time to show longer messages for in seconds - self.pilotRuntoExtractPoint = true -- Downed Pilot will run to the rescue helicopter up to self.extractDistance METERS. + self.invisiblecrew = false -- Set to true to make wounded crew insvisible + self.messageTime = 15 -- Time to show longer messages for in seconds + self.pilotRuntoExtractPoint = true -- Downed Pilot will run to the rescue helicopter up to self.extractDistance METERS self.loadDistance = 75 -- configure distance for pilot to get in helicopter in meters. - self.extractDistance = 500 -- Distance the Downed pilot will run to the rescue helicopter. + self.extractDistance = 500 -- Distance the Downed pilot will run to the rescue helicopter self.loadtimemax = 135 -- seconds - self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isn't added to the mission BEACONS WONT WORK! + self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK! self.beaconRefresher = 29 -- seconds - self.allowFARPRescue = true -- allows pilot to be rescued by landing at a FARP or Airbase + self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued. - self.max_units = 6 -- max number of pilots that can be carried - self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below. - self.csarPrefix = { "helicargo", "MEDEVAC" } -- prefixes used for useprefix=true - DON'T use # in names! + self.max_units = 6 --max number of pilots that can be carried + self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below + self.csarPrefix = { "helicargo", "MEDEVAC"} -- prefixes used for useprefix=true - DON\'T use # in names! self.template = Template or "generic" -- template for downed pilot - self.mashprefix = { "MASH" } -- prefixes used to find MASHes - + self.mashprefix = {"MASH"} -- prefixes used to find MASHes + self.autosmoke = false -- automatically smoke location when heli is near - self.autosmokedistance = 2000 -- distance in meters for automatic smoke deployment + self.autosmokedistance = 2000 -- distance for autosmoke -- added 0.1.4 self.limitmaxdownedpilots = true self.maxdownedpilots = 25 -- generate Frequencies self:_GenerateVHFrequencies() -- added 0.1.8 - self.approachdist_far = 5000 -- switch to 10 sec interval approach mode, meters + self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters self.pilotmustopendoors = false -- switch to true to enable check on open doors self.suppressmessages = false - + -- added 0.1.11r1 self.rescuehoverheight = 20 self.rescuehoverdistance = 10 - + -- added 0.1.12 - self.countryblue = country.id.USA + self.countryblue= country.id.USA self.countryred = country.id.RUSSIA self.countryneutral = country.id.UN_PEACEKEEPERS - + -- added 0.1.3 self.csarUsePara = false -- shagrat set to true, will use the LandingAfterEjection Event instead of Ejection - - -- WARNING - here'll be dragons + + -- WARNING - here\'ll be dragons -- for this to work you need to de-sanitize your mission environment in \Scripts\MissionScripting.lua -- needs SRS => 1.9.6 to work (works on the *server* side) - self.useSRS = false -- Use FF's SRS integration + self.useSRS = false -- Use FF\'s SRS integration self.SRSPath = "E:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your server(!) self.SRSchannel = 300 -- radio channel self.SRSModulation = radio.modulation.AM -- modulation - + ------------------------ --- Pseudo Functions --- ------------------------ - - --- Triggers the FSM event "Start". Starts the CSAR. Initializes parameters and starts event handlers. + + --- Triggers the FSM event "Start". Starts the CSAR. Initializes parameters and starts event handlers. -- @function [parent=#CSAR] Start -- @param #CSAR self @@ -427,7 +428,7 @@ function CSAR:New( Coalition, Template, Alias ) -- @function [parent=#CSAR] __Status -- @param #CSAR self -- @param #number delay Delay in seconds. - + --- On After "PilotDown" event. Downed Pilot detected. -- @function [parent=#CSAR] OnAfterPilotDown -- @param #CSAR self @@ -438,7 +439,7 @@ function CSAR:New( Coalition, Template, Alias ) -- @param #number Frequency Beacon frequency in kHz. -- @param #string Leadername Name of the #UNIT of the downed pilot. -- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype. - + --- On After "Aproach" event. Heli close to downed Pilot. -- @function [parent=#CSAR] OnAfterApproach -- @param #CSAR self @@ -446,27 +447,27 @@ function CSAR:New( Coalition, Template, Alias ) -- @param #string Event Event. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. - -- @param #string Woundedgroupname Name of the downed pilot's group. - - --- On After "Boarded" event. Downed pilot boarded heli. + -- @param #string Woundedgroupname Name of the downed pilot\'s group. + + --- On After "Boarded" event. Downed pilot boarded heli. -- @function [parent=#CSAR] OnAfterBoarded -- @param #CSAR self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. - -- @param #string Woundedgroupname Name of the downed pilot's group. + -- @param #string Woundedgroupname Name of the downed pilot\'s group. - --- On After "Returning" event. Heli can return home with downed pilot(s). + --- On After "Returning" event. Heli can return home with downed pilot(s). -- @function [parent=#CSAR] OnAfterReturning -- @param #CSAR self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. - -- @param #string Woundedgroupname Name of the downed pilot's group. - - --- On After "Rescued" event. Pilot(s) have been brought to the MASH/FARP/AFB. + -- @param #string Woundedgroupname Name of the downed pilot\'s group. + + --- On After "Rescued" event. Pilot(s) have been brought to the MASH/FARP/AFB. -- @function [parent=#CSAR] OnAfterRescued -- @param #CSAR self -- @param #string From From state. @@ -475,7 +476,7 @@ function CSAR:New( Coalition, Template, Alias ) -- @param Wrapper.Unit#UNIT HeliUnit Unit of the helicopter. -- @param #string HeliName Name of the helicopter group. -- @param #number PilotsSaved Number of the saved pilots on board when landing. - + --- On After "KIA" event. Pilot is dead. -- @function [parent=#CSAR] OnAfterKIA -- @param #CSAR self @@ -483,7 +484,7 @@ function CSAR:New( Coalition, Template, Alias ) -- @param #string Event Event. -- @param #string To To state. -- @param #string Pilotname Name of the pilot KIA. - + return self end @@ -502,9 +503,9 @@ end -- @param #number Frequency Frequency of the NDB in Hz -- @param #string Playername Name of Player (if applicable) -- @return #CSAR self. -function CSAR:_CreateDownedPilotTrack( Group, Groupname, Side, OriginalUnit, Description, Typename, Frequency, Playername ) - self:T( { "_CreateDownedPilotTrack", Groupname, Side, OriginalUnit, Description, Typename, Frequency, Playername } ) - +function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername) + self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername}) + -- create new entry local DownedPilot = {} -- #CSAR.DownedPilot DownedPilot.desc = Description or "" @@ -518,16 +519,16 @@ function CSAR:_CreateDownedPilotTrack( Group, Groupname, Side, OriginalUnit, Des DownedPilot.group = Group DownedPilot.timestamp = 0 DownedPilot.alive = true - + -- Add Pilot local PilotTable = self.downedPilots local counter = self.downedpilotcounter PilotTable[counter] = {} PilotTable[counter] = DownedPilot - self:T( { Table = PilotTable } ) + self:T({Table=PilotTable}) self.downedPilots = PilotTable -- Increase counter - self.downedpilotcounter = self.downedpilotcounter + 1 + self.downedpilotcounter = self.downedpilotcounter+1 return self end @@ -535,13 +536,13 @@ end -- @param #CSAR self -- @param #string _heliName -- @return #number count -function CSAR:_PilotsOnboard( _heliName ) - self:T( self.lid .. " _PilotsOnboard" ) - local count = 0 +function CSAR:_PilotsOnboard(_heliName) + self:T(self.lid .. " _PilotsOnboard") + local count = 0 if self.inTransitGroups[_heliName] then - for _, _group in pairs( self.inTransitGroups[_heliName] ) do - count = count + 1 - end + for _, _group in pairs(self.inTransitGroups[_heliName]) do + count = count + 1 + end end return count end @@ -550,16 +551,16 @@ end -- @param #CSAR self -- @param #string _unitname Name of unit. -- @return #boolean Outcome -function CSAR:_DoubleEjection( _unitname ) - if self.lastCrash[_unitname] then - local _time = self.lastCrash[_unitname] - if timer.getTime() - _time < 10 then - self:E( self.lid .. "Caught double ejection!" ) - return true +function CSAR:_DoubleEjection(_unitname) + if self.lastCrash[_unitname] then + local _time = self.lastCrash[_unitname] + if timer.getTime() - _time < 10 then + self:E(self.lid.."Caught double ejection!") + return true + end end - end - self.lastCrash[_unitname] = timer.getTime() - return false + self.lastCrash[_unitname] = timer.getTime() + return false end --- (Internal) Spawn a downed pilot @@ -569,18 +570,16 @@ end -- @param #number frequency Frequency of the pilot's beacon -- @return Wrapper.Group#GROUP group The #GROUP object. -- @return #string alias The alias name. -function CSAR:_SpawnPilotInField( country, point, frequency ) - self:T( { country, point, frequency } ) +function CSAR:_SpawnPilotInField(country,point,frequency) + self:T({country,point,frequency}) local freq = frequency or 1000 local freq = freq / 1000 -- kHz - for i = 1, 10 do - math.random( i, 10000 ) - end - if point:IsSurfaceTypeWater() then - point.y = 0 + for i=1,10 do + math.random(i,10000) end + if point:IsSurfaceTypeWater() then point.y = 0 end local template = self.template - local alias = string.format( "Pilot %.2fkHz-%d", freq, math.random( 1, 99 ) ) + local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99)) local coalition = self.coalition local pilotcacontrol = self.allowDownedPilotCAcontrol -- Switch AI on/oof - is this really correct for CA? local _spawnedGroup = SPAWN @@ -597,32 +596,32 @@ end --- (Internal) Add options to a downed pilot -- @param #CSAR self -- @param Wrapper.Group#GROUP group Group to use. -function CSAR:_AddSpecialOptions( group ) - self:T( self.lid .. " _AddSpecialOptions" ) - self:T( { group } ) - +function CSAR:_AddSpecialOptions(group) + self:T(self.lid.." _AddSpecialOptions") + self:T({group}) + local immortalcrew = self.immortalcrew local invisiblecrew = self.invisiblecrew if immortalcrew then local _setImmortal = { - id = 'SetImmortal', - params = { - value = true, - }, + id = 'SetImmortal', + params = { + value = true + } } - group:SetCommand( _setImmortal ) + group:SetCommand(_setImmortal) end if invisiblecrew then local _setInvisible = { - id = 'SetInvisible', - params = { - value = true, - }, + id = 'SetInvisible', + params = { + value = true + } } - group:SetCommand( _setInvisible ) + group:SetCommand(_setInvisible) end - + group:OptionAlarmStateGreen() group:OptionROEHoldFire() return self @@ -640,61 +639,59 @@ end -- @param #boolean noMessage -- @param #string _description Description -- @param #boolean forcedesc Use the description only for the pilot track entry -function CSAR:_AddCsar( _coalition, _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description, forcedesc ) - self:T( self.lid .. " _AddCsar" ) - self:T( { _coalition, _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description } ) +function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description, forcedesc ) + self:T(self.lid .. " _AddCsar") + self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description}) local template = self.template - + if not _freq then _freq = self:_GenerateADFFrequency() - if not _freq then - _freq = 333000 - end -- noob catch - end - - local _spawnedGroup, _alias = self:_SpawnPilotInField( _country, _point, _freq ) - + if not _freq then _freq = 333000 end --noob catch + end + + local _spawnedGroup, _alias = self:_SpawnPilotInField(_country,_point,_freq) + local _typeName = _typeName or "Pilot" - + if not noMessage then - 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 + 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 - - if (_freq and _freq ~= 0) then -- shagrat only add beacon if _freq is NOT 0 - self:_AddBeaconToGroup( _spawnedGroup, _freq ) end - - self:_AddSpecialOptions( _spawnedGroup ) + + if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0 + self:_AddBeaconToGroup(_spawnedGroup, _freq) + end + + self:_AddSpecialOptions(_spawnedGroup) local _text = _description if not forcedesc then if _playerName ~= nil then - if _freq ~= 0 then -- shagrat - _text = "Pilot " .. _playerName - else - _text = "TIC - " .. _playerName - end + if _freq ~= 0 then --shagrat + _text = "Pilot " .. _playerName + else + _text = "TIC - " .. _playerName + end elseif _unitName ~= nil then - if _freq ~= 0 then -- shagrat - _text = "AI Pilot of " .. _unitName - else - _text = "TIC - " .. _unitName - end + if _freq ~= 0 then --shagrat + _text = "AI Pilot of " .. _unitName + else + _text = "TIC - " .. _unitName end end - self:T( { _spawnedGroup, _alias } ) - + end + self:T({_spawnedGroup, _alias}) + local _GroupName = _spawnedGroup:GetName() or _alias - self:_CreateDownedPilotTrack( _spawnedGroup, _GroupName, _coalition, _unitName, _text, _typeName, _freq, _playerName ) - - self:_InitSARForPilot( _spawnedGroup, _unitName, _freq, noMessage ) -- shagrat use unitName to have the aircraft callsign / descriptive "name" etc. + self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName) + self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc. + return self end @@ -704,31 +701,31 @@ end -- @param #number _coalition Coalition. -- @param #string _description (optional) Description. -- @param #boolean _randomPoint (optional) Random yes or no. --- @param #boolean _nomessage (optional) If true, don't send a message to SAR. +-- @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:_SpawnCsarAtZone( _zone, _coalition, _description, _randomPoint, _nomessage, unitname, typename, forcedesc ) - self:T( self.lid .. " _SpawnCsarAtZone" ) +function CSAR:_SpawnCsarAtZone( _zone, _coalition, _description, _randomPoint, _nomessage, unitname, typename, forcedesc) + self:T(self.lid .. " _SpawnCsarAtZone") local freq = self:_GenerateADFFrequency() - local _triggerZone = ZONE:New( _zone ) -- trigger to use as reference position + local _triggerZone = ZONE:New(_zone) -- trigger to use as reference position if _triggerZone == nil then - self:E( self.lid .. "ERROR: Can\'t find zone called " .. _zone, 10 ) + self:E(self.lid.."ERROR: Can\'t find zone called " .. _zone, 10) return end - + local _description = _description or "PoW" local unitname = unitname or "Old Rusty" local typename = typename or "Phantom II" - + local pos = {} if _randomPoint then - local _pos = _triggerZone:GetRandomPointVec3() - pos = COORDINATE:NewFromVec3( _pos ) + local _pos = _triggerZone:GetRandomPointVec3() + pos = COORDINATE:NewFromVec3(_pos) else - pos = _triggerZone:GetCoordinate() + pos = _triggerZone:GetCoordinate() end - + local _country = 0 if _coalition == coalition.side.BLUE then _country = self.countryblue @@ -737,9 +734,9 @@ function CSAR:_SpawnCsarAtZone( _zone, _coalition, _description, _randomPoint, _ else _country = self.countryneutral end - - self:_AddCsar( _coalition, _country, pos, typename, unitname, _description, freq, _nomessage, _description, forcedesc ) - + + self:_AddCsar(_coalition, _country, pos, typename, unitname, _description, freq, _nomessage, _description, forcedesc) + return self end @@ -749,7 +746,7 @@ end -- @param #number Coalition Coalition. -- @param #string Description (optional) Description. -- @param #boolean RandomPoint (optional) Random yes or no. --- @param #boolean Nomessage (optional) If true, don't send a message to SAR. +-- @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. @@ -757,8 +754,8 @@ end -- -- -- 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, "Wagner", true, false, "Charly-1-1", "F5E" ) -function CSAR:SpawnCSARAtZone( Zone, Coalition, Description, RandomPoint, Nomessage, Unitname, Typename, Forcedesc ) - self:_SpawnCsarAtZone( Zone, Coalition, Description, RandomPoint, Nomessage, Unitname, Typename, Forcedesc ) +function CSAR:SpawnCSARAtZone(Zone, Coalition, Description, RandomPoint, Nomessage, Unitname, Typename, Forcedesc) + self:_SpawnCsarAtZone(Zone, Coalition, Description, RandomPoint, Nomessage, Unitname, Typename, Forcedesc) return self end @@ -767,20 +764,20 @@ end -- @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 #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" ) - +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 - + pos = _Point + local _country = 0 if _coalition == coalition.side.BLUE then _country = self.countryblue @@ -789,9 +786,9 @@ function CSAR:_SpawnCASEVAC( _Point, _coalition, _description, _nomessage, unitn 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 ) - + --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 @@ -801,204 +798,204 @@ end -- @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 #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 ) +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 +end --shagrat end added CASEVAC --- (Internal) Event handler. -- @param #CSAR self -function CSAR:_EventHandler( EventData ) - self:T( self.lid .. " _EventHandler" ) - self:T( { Event = EventData.id } ) - +function CSAR:_EventHandler(EventData) + self:T(self.lid .. " _EventHandler") + self:T({Event = EventData.id}) + local _event = EventData -- Core.Event#EVENTDATA - - -- no Player + + -- no Player if self.enableForAI == false and _event.IniPlayerName == nil then - return - end - - -- no event + return + end + + -- no event if _event == nil or _event.initiator == nil then return false - - -- take off + + -- take off elseif _event.id == EVENTS.Takeoff then -- taken off - self:T( self.lid .. " Event unit - Takeoff" ) - + self:T(self.lid .. " Event unit - Takeoff") + local _coalition = _event.IniCoalition if _coalition ~= self.coalition then - return -- ignore! + return --ignore! end - + if _event.IniGroupName then - self.takenOff[_event.IniUnitName] = true + self.takenOff[_event.IniUnitName] = true end - + return true - - -- player enter unit - elseif _event.id == EVENTS.PlayerEnterAircraft or _event.id == EVENTS.PlayerEnterUnit then -- player entered unit - self:T( self.lid .. " Event unit - Player Enter" ) - + + -- player enter unit + elseif _event.id == EVENTS.PlayerEnterAircraft or _event.id == EVENTS.PlayerEnterUnit then --player entered unit + self:T(self.lid .. " Event unit - Player Enter") + local _coalition = _event.IniCoalition if _coalition ~= self.coalition then - return -- ignore! + return --ignore! end - + if _event.IniPlayerName then - self.takenOff[_event.IniPlayerName] = nil + self.takenOff[_event.IniPlayerName] = nil end - + local _unit = _event.IniUnit local _group = _event.IniGroup if _unit:IsHelicopter() or _group:IsHelicopter() then self:_AddMedevacMenuItem() - end - + end + return true - + elseif (_event.id == EVENTS.PilotDead and self.csarOncrash == false) then - -- Pilot dead + -- Pilot dead + + self:T(self.lid .. " Event unit - Pilot Dead") + + local _unit = _event.IniUnit + local _unitname = _event.IniUnitName + local _group = _event.IniGroup + + if _unit == nil then + return -- error! + end + + local _coalition = _event.IniCoalition + if _coalition ~= self.coalition then + return --ignore! + end + + -- Catch multiple events here? + if self.takenOff[_event.IniUnitName] == true or _group:IsAirborne() then + if self:_DoubleEjection(_unitname) then + return + end - self:T( self.lid .. " Event unit - Pilot Dead" ) - - local _unit = _event.IniUnit - local _unitname = _event.IniUnitName - local _group = _event.IniGroup - - if _unit == nil then - return -- error! - end - - local _coalition = _event.IniCoalition - if _coalition ~= self.coalition then - return -- ignore! - end - - -- Catch multiple events here? - if self.takenOff[_event.IniUnitName] == true or _group:IsAirborne() then - if self:_DoubleEjection( _unitname ) then - return + else + self:T(self.lid .. " Pilot has not taken off, ignore") + end + + return + + elseif _event.id == EVENTS.PilotDead or _event.id == EVENTS.Ejection then + if _event.id == EVENTS.PilotDead and self.csarOncrash == false then + return + end + self:T(self.lid .. " Event unit - Pilot Ejected") + + local _unit = _event.IniUnit + local _unitname = _event.IniUnitName + local _group = _event.IniGroup + + if _unit == nil then + return -- error! + end + + local _coalition = _unit:GetCoalition() + if _coalition ~= self.coalition then + return --ignore! end - else - self:T( self.lid .. " Pilot has not taken off, ignore" ) + if not self.takenOff[_event.IniUnitName] and not _group:IsAirborne() then + self:T(self.lid .. " Pilot has not taken off, ignore") + return -- give up, pilot hasnt taken off + end + + if self:_DoubleEjection(_unitname) then + return + end + + -- limit no of pilots in the field. + if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then + return + end + + -- 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 - - return - - elseif _event.id == EVENTS.PilotDead or _event.id == EVENTS.Ejection then - if _event.id == EVENTS.PilotDead and self.csarOncrash == false then - return - end - self:T( self.lid .. " Event unit - Pilot Ejected" ) - - local _unit = _event.IniUnit - local _unitname = _event.IniUnitName - local _group = _event.IniGroup - - if _unit == nil then - return -- error! - end - - local _coalition = _unit:GetCoalition() - if _coalition ~= self.coalition then - return -- ignore! - end - - if not self.takenOff[_event.IniUnitName] and not _group:IsAirborne() then - self:T( self.lid .. " Pilot has not taken off, ignore" ) - return -- give up, pilot hasnt taken off - end - - if self:_DoubleEjection( _unitname ) then - return - end - - -- limit no of pilots in the field. - if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then - return - end - - -- 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" + 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 ) if _coalition == self.coalition then 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 - end + 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 + end return true - + elseif _event.id == EVENTS.Land then - self:T( self.lid .. " Landing" ) - - if _event.IniUnitName then - self.takenOff[_event.IniUnitName] = nil - end - - if self.allowFARPRescue then - - local _unit = _event.IniUnit -- Wrapper.Unit#UNIT - - if _unit == nil then - self:T( self.lid .. " Unit nil on landing" ) - return -- error! + self:T(self.lid .. " Landing") + + if _event.IniUnitName then + self.takenOff[_event.IniUnitName] = nil end - - local _coalition = _event.IniCoalition - if _coalition ~= self.coalition then - return -- ignore! + + if self.allowFARPRescue then + + local _unit = _event.IniUnit -- Wrapper.Unit#UNIT + + if _unit == nil then + self:T(self.lid .. " Unit nil on landing") + return -- error! + end + + local _coalition = _event.IniCoalition + if _coalition ~= self.coalition then + return --ignore! + end + + self.takenOff[_event.IniUnitName] = nil + + local _place = _event.Place -- Wrapper.Airbase#AIRBASE + + if _place == nil then + self:T(self.lid .. " Landing Place Nil") + return -- error! + end + + -- anyone on board? + if self.inTransitGroups[_event.IniUnitName] == nil then + -- ignore + return + end + + if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then + self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true) + else + self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition())) + end + end + + return true end - - self.takenOff[_event.IniUnitName] = nil - - local _place = _event.Place -- Wrapper.Airbase#AIRBASE - - if _place == nil then - self:T( self.lid .. " Landing Place Nil" ) - return -- error! - end - - -- anyone on board? - if self.inTransitGroups[_event.IniUnitName] == nil then - -- ignore - return - end - - if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then - self:_ScheduledSARFlight( _event.IniUnitName, _event.IniGroupName, true ) - else - self:T( string.format( "Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition() ) ) - end - end - - return true - end return self end @@ -1008,31 +1005,31 @@ end -- @param #string _GroupName Name of the Group -- @param #number _freq Beacon frequency. -- @param #boolean _nomessage Send message true or false. -function CSAR:_InitSARForPilot( _downedGroup, _GroupName, _freq, _nomessage ) - self:T( self.lid .. " _InitSARForPilot" ) - local _leader = _downedGroup:GetUnit( 1 ) +function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage) + self:T(self.lid .. " _InitSARForPilot") + local _leader = _downedGroup:GetUnit(1) local _groupName = _GroupName local _freqk = _freq / 1000 - local _coordinatesText = self:_GetPositionOfWounded( _downedGroup ) + local _coordinatesText = self:_GetPositionOfWounded(_downedGroup) local _leadername = _leader:GetName() - + if not _nomessage then - 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 + 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 + self:_CheckWoundedGroupStatus(_heliName, _groupName) end - for _, _heliName in pairs( self.csarUnits ) do - self:_CheckWoundedGroupStatus( _heliName, _groupName ) - end - - -- trigger FSM event - self:__PilotDown( 2, _downedGroup, _freqk, _groupName, _coordinatesText ) - + -- trigger FSM event + self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText) + return self end @@ -1041,16 +1038,16 @@ end -- @param #string name Name to search for. -- @return #boolean Outcome. -- @return #CSAR.DownedPilot Table if found else nil. -function CSAR:_CheckNameInDownedPilots( name ) - local PilotTable = self.downedPilots -- #CSAR.DownedPilot +function CSAR:_CheckNameInDownedPilots(name) + local PilotTable = self.downedPilots --#CSAR.DownedPilot local found = false local table = nil - for _, _pilot in pairs( PilotTable ) do + for _,_pilot in pairs(PilotTable) do if _pilot.name == name and _pilot.alive == true then found = true table = _pilot break - end + end end return found, table end @@ -1060,10 +1057,10 @@ end -- @param #string name Name to search for. -- @param #boolean force Force removal. -- @return #boolean Outcome. -function CSAR:_RemoveNameFromDownedPilots( name, force ) - local PilotTable = self.downedPilots -- #CSAR.DownedPilot +function CSAR:_RemoveNameFromDownedPilots(name,force) + local PilotTable = self.downedPilots --#CSAR.DownedPilot local found = false - for _index, _pilot in pairs( PilotTable ) do + for _index,_pilot in pairs(PilotTable) do if _pilot.name == name then self.downedPilots[_index].alive = false end @@ -1075,95 +1072,95 @@ end -- @param #CSAR self -- @param #string heliname heliname -- @param #string woundedgroupname woundedgroupname -function CSAR:_CheckWoundedGroupStatus( heliname, woundedgroupname ) - self:T( self.lid .. " _CheckWoundedGroupStatus" ) +function CSAR:_CheckWoundedGroupStatus(heliname,woundedgroupname) + self:T(self.lid .. " _CheckWoundedGroupStatus") local _heliName = heliname local _woundedGroupName = woundedgroupname - self:T( { Heli = _heliName, Downed = _woundedGroupName } ) + self:T({Heli = _heliName, Downed = _woundedGroupName}) -- if wounded group is not here then message already been sent to SARs -- stop processing any further - local _found, _downedpilot = self:_CheckNameInDownedPilots( _woundedGroupName ) + local _found, _downedpilot = self:_CheckNameInDownedPilots(_woundedGroupName) if not _found then - self:T( "...not found in list!" ) + self:T("...not found in list!") return end - + local _woundedGroup = _downedpilot.group - if _woundedGroup ~= nil and _woundedGroup:IsAlive() then - local _heliUnit = self:_GetSARHeli( _heliName ) -- Wrapper.Unit#UNIT - - local _lookupKeyHeli = _heliName .. "_" .. _woundedGroupName -- lookup key for message state tracking - + if _woundedGroup ~= nil and _woundedGroup:IsAlive() then + local _heliUnit = self:_GetSARHeli(_heliName) -- Wrapper.Unit#UNIT + + local _lookupKeyHeli = _heliName .. "_" .. _woundedGroupName --lookup key for message state tracking + if _heliUnit == nil then self.heliVisibleMessage[_lookupKeyHeli] = nil self.heliCloseMessage[_lookupKeyHeli] = nil self.landedStatus[_lookupKeyHeli] = nil - self:T( "...helinunit nil!" ) + self:T("...helinunit nil!") return end - + local _heliCoord = _heliUnit:GetCoordinate() local _leaderCoord = _woundedGroup:GetCoordinate() - local _distance = self:_GetDistance( _heliCoord, _leaderCoord ) + local _distance = self:_GetDistance(_heliCoord,_leaderCoord) -- autosmoke if (self.autosmoke == true) and (_distance < self.autosmokedistance) and (_distance ~= -1) then - self:_PopSmokeForGroup( _woundedGroupName, _woundedGroup ) + self:_PopSmokeForGroup(_woundedGroupName, _woundedGroup) end - + if _distance < self.approachdist_near and _distance > 0 then - if self:_CheckCloseWoundedGroup( _distance, _heliUnit, _heliName, _woundedGroup, _woundedGroupName ) == true then - -- we're close, reschedule + if self:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedGroup, _woundedGroupName) == true then + -- we\'re close, reschedule _downedpilot.timestamp = timer.getAbsTime() - self:__Approach( -5, heliname, woundedgroupname ) + self:__Approach(-5,heliname,woundedgroupname) end elseif _distance >= self.approachdist_near and _distance < self.approachdist_far then -- message once if self.heliVisibleMessage[_lookupKeyHeli] == nil then - local _pilotName = _downedpilot.desc - if self.autosmoke == true then - local dist = self.autosmokedistance / 1000 - local disttext = string.format( "%.0fkm", dist ) - if _SETTINGS:IsImperial() then - local dist = UTILS.MetersToNM( self.autosmokedistance ) - disttext = string.format( "%.0fnm", dist ) + local _pilotName = _downedpilot.desc + if self.autosmoke == true then + local dist = self.autosmokedistance / 1000 + local disttext = string.format("%.0fkm",dist) + if _SETTINGS:IsImperial() then + local dist = UTILS.MetersToNM(self.autosmokedistance) + disttext = string.format("%.0fnm",dist) + end + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nI'll pop a smoke when you are %s away.\nLand or hover by the smoke.", _heliName, _pilotName, disttext), self.messageTime,false,true) + else + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nRequest a flare or smoke if you need.", _heliName, _pilotName), self.messageTime,false,true) end - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s: %s. I hear you! Finally, that is music in my ears!\nI'll pop a smoke when you are %s away.\nLand or hover by the smoke.", _heliName, _pilotName, disttext ), self.messageTime, false, true ) - else - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s: %s. I hear you! Finally, that is music in my ears!\nRequest a flare or smoke if you need.", _heliName, _pilotName ), self.messageTime, false, true ) - end - -- mark as shown for THIS heli and THIS group - self.heliVisibleMessage[_lookupKeyHeli] = true - end + --mark as shown for THIS heli and THIS group + self.heliVisibleMessage[_lookupKeyHeli] = true + end self.heliCloseMessage[_lookupKeyHeli] = nil self.landedStatus[_lookupKeyHeli] = nil - -- reschedule as units aren't dead yet , schedule for a bit slower though as we're far away + --reschedule as units aren\'t dead yet , schedule for a bit slower though as we\'re far away _downedpilot.timestamp = timer.getAbsTime() - self:__Approach( -10, heliname, woundedgroupname ) + self:__Approach(-10,heliname,woundedgroupname) end else - self:T( "...Downed Pilot KIA?!" ) - if not _downedpilot.alive then - -- self:__KIA(1,_downedpilot.name) - self:_RemoveNameFromDownedPilots( _downedpilot.name, true ) - end + self:T("...Downed Pilot KIA?!") + if not _downedpilot.alive then + --self:__KIA(1,_downedpilot.name) + self:_RemoveNameFromDownedPilots(_downedpilot.name, true) + end end return self end ---- (Internal) Function to pop a smoke at a wounded pilot's positions. +--- (Internal) Function to pop a smoke at a wounded pilot\'s positions. -- @param #CSAR self -- @param #string _woundedGroupName Name of the group. -- @param Wrapper.Group#GROUP _woundedLeader Object of the group. -function CSAR:_PopSmokeForGroup( _woundedGroupName, _woundedLeader ) - self:T( self.lid .. " _PopSmokeForGroup" ) +function CSAR:_PopSmokeForGroup(_woundedGroupName, _woundedLeader) + self:T(self.lid .. " _PopSmokeForGroup") -- have we popped smoke already in the last 5 mins local _lastSmoke = self.smokeMarkers[_woundedGroupName] if _lastSmoke == nil or timer.getTime() > _lastSmoke then - - local _smokecolor = self.smokecolor - 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 + + local _smokecolor = self.smokecolor + 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 return self end @@ -1174,40 +1171,47 @@ end -- @param #string _pilotName Name of the pilot. -- @param Wrapper.Group#GROUP _woundedGroup Object of the group. -- @param #string _woundedGroupName Name of the group. -function CSAR:_PickupUnit( _heliUnit, _pilotName, _woundedGroup, _woundedGroupName ) - self:T( self.lid .. " _PickupUnit" ) +function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) + self:T(self.lid .. " _PickupUnit") -- board local _heliName = _heliUnit:GetName() local _groups = self.inTransitGroups[_heliName] - local _unitsInHelicopter = self:_PilotsOnboard( _heliName ) - + local _unitsInHelicopter = self:_PilotsOnboard(_heliName) + -- init table if there is none for this helicopter if not _groups then - self.inTransitGroups[_heliName] = {} - _groups = self.inTransitGroups[_heliName] + self.inTransitGroups[_heliName] = {} + _groups = self.inTransitGroups[_heliName] end - + -- if the heli can\'t pick them up, show a message and return local _maxUnits = self.AircraftType[_heliUnit:GetTypeName()] if _maxUnits == nil then _maxUnits = self.max_units end if _unitsInHelicopter + 1 > _maxUnits then - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter ), self.messageTime ) - return true + self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter), self.messageTime) + return true end + + local found,downedgrouptable = self:_CheckNameInDownedPilots(_woundedGroupName) + local grouptable = downedgrouptable --#CSAR.DownedPilot + self.inTransitGroups[_heliName][_woundedGroupName] = + { + originalUnit = grouptable.originalUnit, + woundedGroup = _woundedGroupName, + side = self.coalition, + desc = grouptable.desc, + player = grouptable.player, + } - local found, downedgrouptable = self:_CheckNameInDownedPilots( _woundedGroupName ) - local grouptable = downedgrouptable -- #CSAR.DownedPilot - self.inTransitGroups[_heliName][_woundedGroupName] = { originalUnit = grouptable.originalUnit, woundedGroup = _woundedGroupName, side = self.coalition, desc = grouptable.desc, player = grouptable.player } - - _woundedGroup:Destroy( false ) - self:_RemoveNameFromDownedPilots( _woundedGroupName, true ) - - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName ), self.messageTime, true, true ) - - self:__Boarded( 5, _heliName, _woundedGroupName ) - + _woundedGroup:Destroy(false) + self:_RemoveNameFromDownedPilots(_woundedGroupName,true) + + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true) + + self:__Boarded(5,_heliName,_woundedGroupName) + return true end @@ -1215,23 +1219,24 @@ end -- @param #CSAR self -- @param Wrapper.Group#GROUP _leader -- @param Core.Point#COORDINATE _destination -function CSAR:_OrderGroupToMoveToPoint( _leader, _destination ) - self:T( self.lid .. " _OrderGroupToMoveToPoint" ) +function CSAR:_OrderGroupToMoveToPoint(_leader, _destination) + self:T(self.lid .. " _OrderGroupToMoveToPoint") local group = _leader local coordinate = _destination:GetVec2() group:SetAIOn() - group:RouteToVec2( coordinate, 5 ) + group:RouteToVec2(coordinate,5) return self end + --- (internal) Function to check if the heli door(s) are open. Thanks to Shadowze. -- @param #CSAR self -- @param #string unit_name Name of unit. -- @return #boolean outcome The outcome. function CSAR:_IsLoadingDoorOpen( unit_name ) - self:T( self.lid .. " _IsLoadingDoorOpen" ) - return UTILS.IsLoadingDoorOpen( unit_name ) + self:T(self.lid .. " _IsLoadingDoorOpen") + return UTILS.IsLoadingDoorOpen(unit_name) end --- (Internal) Function to check if heli is close to group. @@ -1242,123 +1247,122 @@ end -- @param Wrapper.Group#GROUP _woundedGroup -- @param #string _woundedGroupName -- @return #boolean Outcome -function CSAR:_CheckCloseWoundedGroup( _distance, _heliUnit, _heliName, _woundedGroup, _woundedGroupName ) - self:T( self.lid .. " _CheckCloseWoundedGroup" ) +function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedGroup, _woundedGroupName) + self:T(self.lid .. " _CheckCloseWoundedGroup") local _woundedLeader = _woundedGroup - local _lookupKeyHeli = _heliUnit:GetName() .. "_" .. _woundedGroupName -- lookup key for message state tracking - - local _found, _pilotable = self:_CheckNameInDownedPilots( _woundedGroupName ) -- #boolean, #CSAR.DownedPilot + local _lookupKeyHeli = _heliUnit:GetName() .. "_" .. _woundedGroupName --lookup key for message state tracking + + local _found, _pilotable = self:_CheckNameInDownedPilots(_woundedGroupName) -- #boolean, #CSAR.DownedPilot local _pilotName = _pilotable.desc + local _reset = true - + if (_distance < 500) then - - if self.heliCloseMessage[_lookupKeyHeli] == nil then - if self.autosmoke == true then - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s: %s. You\'re close now! Land or hover at the smoke.", _heliName, _pilotName ), self.messageTime, false, true ) - else - self:_DisplayMessageToSAR( _heliUnit, string.format( "%s: %s. You\'re close now! Land in a safe place, I will go there ", _heliName, _pilotName ), self.messageTime, false, true ) - end - self.heliCloseMessage[_lookupKeyHeli] = true - end - - -- have we landed close enough? - if not _heliUnit:InAir() then - - if self.pilotRuntoExtractPoint == true then - if (_distance < self.extractDistance) then - local _time = self.landedStatus[_lookupKeyHeli] - if _time == nil then - self.landedStatus[_lookupKeyHeli] = math.floor( (_distance - self.loadDistance) / 3.6 ) - _time = self.landedStatus[_lookupKeyHeli] - self:_OrderGroupToMoveToPoint( _woundedGroup, _heliUnit:GetCoordinate() ) - self:_DisplayMessageToSAR( _heliUnit, "Wait till " .. _pilotName .. " gets in. \nETA " .. _time .. " more seconds.", self.messageTime, false ) + + if self.heliCloseMessage[_lookupKeyHeli] == nil then + if self.autosmoke == true then + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land or hover at the smoke.", _heliName, _pilotName), self.messageTime,false,true) else - _time = self.landedStatus[_lookupKeyHeli] - 10 - self.landedStatus[_lookupKeyHeli] = _time + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land in a safe place, I will go there ", _heliName, _pilotName), self.messageTime,false,true) end - if _time <= 0 or _distance < self.loadDistance then - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen( _heliName ) then - self:_DisplayMessageToSAR( _heliUnit, "Open the door to let me in!", self.messageTime, true ) - return true - else - self.landedStatus[_lookupKeyHeli] = nil - self:_PickupUnit( _heliUnit, _pilotName, _woundedGroup, _woundedGroupName ) - return false - end - end - end - else - if (_distance < self.loadDistance) then - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen( _heliName ) then - self:_DisplayMessageToSAR( _heliUnit, "Open the door to let me in!", self.messageTime, true ) - return true - else - self:_PickupUnit( _heliUnit, _pilotName, _woundedGroup, _woundedGroupName ) - return false - end - end + self.heliCloseMessage[_lookupKeyHeli] = true end - else - - local _unitsInHelicopter = self:_PilotsOnboard( _heliName ) - local _maxUnits = self.AircraftType[_heliUnit:GetTypeName()] - if _maxUnits == nil then - _maxUnits = self.max_units - end - - if _heliUnit:InAir() and _unitsInHelicopter + 1 <= _maxUnits then - -- TODO - make variable - if _distance < self.rescuehoverdistance then - - -- check height! - local leaderheight = _woundedLeader:GetHeight() - if leaderheight < 0 then - leaderheight = 0 - end - local _height = _heliUnit:GetHeight() - leaderheight - - -- TODO - make variable - if _height <= self.rescuehoverheight then - - local _time = self.hoverStatus[_lookupKeyHeli] - - if _time == nil then - self.hoverStatus[_lookupKeyHeli] = 10 - _time = 10 - else - _time = self.hoverStatus[_lookupKeyHeli] - 10 - self.hoverStatus[_lookupKeyHeli] = _time - end - - if _time > 0 then - self:_DisplayMessageToSAR( _heliUnit, "Hovering above " .. _pilotName .. ". \n\nHold hover for " .. _time .. " seconds to winch them up. \n\nIf the countdown stops you\'re too far away!", self.messageTime, true ) - else - if self.pilotmustopendoors and not self:_IsLoadingDoorOpen( _heliName ) then - self:_DisplayMessageToSAR( _heliUnit, "Open the door to let me in!", self.messageTime, true ) - return true + + -- have we landed close enough? + if not _heliUnit:InAir() then + + if self.pilotRuntoExtractPoint == true then + if (_distance < self.extractDistance) then + local _time = self.landedStatus[_lookupKeyHeli] + if _time == nil then + self.landedStatus[_lookupKeyHeli] = math.floor( (_distance - self.loadDistance) / 3.6 ) + _time = self.landedStatus[_lookupKeyHeli] + self:_OrderGroupToMoveToPoint(_woundedGroup, _heliUnit:GetCoordinate()) + self:_DisplayMessageToSAR(_heliUnit, "Wait till " .. _pilotName .. " gets in. \nETA " .. _time .. " more seconds.", self.messageTime, false) else - self.hoverStatus[_lookupKeyHeli] = nil - self:_PickupUnit( _heliUnit, _pilotName, _woundedGroup, _woundedGroupName ) - return false + _time = self.landedStatus[_lookupKeyHeli] - 10 + self.landedStatus[_lookupKeyHeli] = _time + end + if _time <= 0 or _distance < self.loadDistance then + if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + return true + else + self.landedStatus[_lookupKeyHeli] = nil + self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) + return false + end end end - _reset = false - else - self:_DisplayMessageToSAR( _heliUnit, "Too high to winch " .. _pilotName .. " \nReduce height and hover for 10 seconds!", self.messageTime, true, true ) + else + if (_distance < self.loadDistance) then + if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + return true + else + self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) + return false + end end end - + else + + local _unitsInHelicopter = self:_PilotsOnboard(_heliName) + local _maxUnits = self.AircraftType[_heliUnit:GetTypeName()] + if _maxUnits == nil then + _maxUnits = self.max_units + end + + if _heliUnit:InAir() and _unitsInHelicopter + 1 <= _maxUnits then + -- TODO - make variable + if _distance < self.rescuehoverdistance then + + --check height! + local leaderheight = _woundedLeader:GetHeight() + if leaderheight < 0 then leaderheight = 0 end + local _height = _heliUnit:GetHeight() - leaderheight + + -- TODO - make variable + if _height <= self.rescuehoverheight then + + local _time = self.hoverStatus[_lookupKeyHeli] + + if _time == nil then + self.hoverStatus[_lookupKeyHeli] = 10 + _time = 10 + else + _time = self.hoverStatus[_lookupKeyHeli] - 10 + self.hoverStatus[_lookupKeyHeli] = _time + end + + if _time > 0 then + self:_DisplayMessageToSAR(_heliUnit, "Hovering above " .. _pilotName .. ". \n\nHold hover for " .. _time .. " seconds to winch them up. \n\nIf the countdown stops you\'re too far away!", self.messageTime, true) + else + if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true) + return true + else + self.hoverStatus[_lookupKeyHeli] = nil + self:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupName) + return false + end + end + _reset = false + else + self:_DisplayMessageToSAR(_heliUnit, "Too high to winch " .. _pilotName .. " \nReduce height and hover for 10 seconds!", self.messageTime, true,true) + end + end + + end end - end end - + if _reset then - self.hoverStatus[_lookupKeyHeli] = nil + self.hoverStatus[_lookupKeyHeli] = nil end - + if _distance < 500 then return true else @@ -1371,65 +1375,65 @@ end -- @param #string heliname Heli name -- @param #string groupname Group name -- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP -function CSAR:_ScheduledSARFlight( heliname, groupname, isairport ) - self:T( self.lid .. " _ScheduledSARFlight" ) - self:T( { heliname, groupname } ) - local _heliUnit = self:_GetSARHeli( heliname ) +function CSAR:_ScheduledSARFlight(heliname,groupname, isairport) + self:T(self.lid .. " _ScheduledSARFlight") + self:T({heliname,groupname}) + local _heliUnit = self:_GetSARHeli(heliname) local _woundedGroupName = groupname if (_heliUnit == nil) then - -- helicopter crashed? - self.inTransitGroups[heliname] = nil - return + --helicopter crashed? + self.inTransitGroups[heliname] = nil + return end if self.inTransitGroups[heliname] == nil or self.inTransitGroups[heliname][_woundedGroupName] == nil then - -- Groups already rescued - return + -- Groups already rescued + return end - local _dist = self:_GetClosestMASH( _heliUnit ) + local _dist = self:_GetClosestMASH(_heliUnit) if _dist == -1 then - return + return end - if (_dist < self.FARPRescueDistance or isairport) and _heliUnit:InAir() == false then - if self.pilotmustopendoors and self:_IsLoadingDoorOpen( heliname ) == false then - self:_DisplayMessageToSAR( _heliUnit, "Open the door to let me out!", self.messageTime, true ) + if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then + if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then + self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true) else - self:_RescuePilots( _heliUnit ) + self:_RescuePilots(_heliUnit) return end end - -- queue up - self:__Returning( -5, heliname, _woundedGroupName, isairport ) + --queue up + self:__Returning(-5,heliname,_woundedGroupName, isairport) return self end --- (Internal) Mark pilot as rescued and remove from tables. -- @param #CSAR self -- @param Wrapper.Unit#UNIT _heliUnit -function CSAR:_RescuePilots( _heliUnit ) - self:T( self.lid .. " _RescuePilots" ) +function CSAR:_RescuePilots(_heliUnit) + self:T(self.lid .. " _RescuePilots") local _heliName = _heliUnit:GetName() local _rescuedGroups = self.inTransitGroups[_heliName] - + if _rescuedGroups == nil then - -- Groups already rescued - return + -- Groups already rescued + return end - local PilotsSaved = self:_PilotsOnboard( _heliName ) - + local PilotsSaved = self:_PilotsOnboard(_heliName) + self.inTransitGroups[_heliName] = nil - - local _txt = string.format( "%s: The %d pilot(s) have been taken to the\nmedical clinic. Good job!", _heliName, PilotsSaved ) - - self:_DisplayMessageToSAR( _heliUnit, _txt, self.messageTime ) + + local _txt = string.format("%s: The %d pilot(s) have been taken to the\nmedical clinic. Good job!", _heliName, PilotsSaved) + + self:_DisplayMessageToSAR(_heliUnit, _txt, self.messageTime) -- trigger event - self:__Rescued( -1, _heliUnit, _heliName, PilotsSaved ) + self:__Rescued(-1,_heliUnit,_heliName, PilotsSaved) return self end @@ -1437,9 +1441,9 @@ end -- @param #CSAR self -- @param #string _unitname Name of Unit -- @return Wrapper.Unit#UNIT The unit or nil -function CSAR:_GetSARHeli( _unitName ) - self:T( self.lid .. " _GetSARHeli" ) - local unit = UNIT:FindByName( _unitName ) +function CSAR:_GetSARHeli(_unitName) + self:T(self.lid .. " _GetSARHeli") + local unit = UNIT:FindByName(_unitName) if unit and unit:IsAlive() then return unit else @@ -1455,43 +1459,43 @@ end -- @param #boolean _clear (optional) Clear screen. -- @param #boolean _speak (optional) Speak message via SRS. -- @param #boolean _override (optional) Override message suppression -function CSAR:_DisplayMessageToSAR( _unit, _text, _time, _clear, _speak, _override ) - self:T( self.lid .. " _DisplayMessageToSAR" ) +function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _override) + self:T(self.lid .. " _DisplayMessageToSAR") local group = _unit:GetGroup() local _clear = _clear or nil local _time = _time or self.messageTime if _override or not self.suppressmessages then - local m = MESSAGE:New( _text, _time, "Info", _clear ):ToGroup( group ) + local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group) end -- integrate SRS if _speak and self.useSRS then - local srstext = SOUNDTEXT:New( _text ) + local srstext = SOUNDTEXT:New(_text) local path = self.SRSPath local modulation = self.SRSModulation local channel = self.SRSchannel - local msrs = MSRS:New( path, channel, modulation ) - msrs:PlaySoundText( srstext, 2 ) + local msrs = MSRS:New(path,channel,modulation) + msrs:PlaySoundText(srstext, 2) end return self end ---- (Internal) Function to get string of a group's position. +--- (Internal) Function to get string of a group\'s position. -- @param #CSAR self -- @param Wrapper.Controllable#CONTROLLABLE _woundedGroup Group or Unit object. -- @return #string Coordinates as Text -function CSAR:_GetPositionOfWounded( _woundedGroup ) - self:T( self.lid .. " _GetPositionOfWounded" ) +function CSAR:_GetPositionOfWounded(_woundedGroup) + self:T(self.lid .. " _GetPositionOfWounded") local _coordinate = _woundedGroup:GetCoordinate() local _coordinatesText = "None" if _coordinate then if self.coordtype == 0 then -- Lat/Long DMTM _coordinatesText = _coordinate:ToStringLLDDM() elseif self.coordtype == 1 then -- Lat/Long DMS - _coordinatesText = _coordinate:ToStringLLDMS() + _coordinatesText = _coordinate:ToStringLLDMS() elseif self.coordtype == 2 then -- MGRS - _coordinatesText = _coordinate:ToStringMGRS() + _coordinatesText = _coordinate:ToStringMGRS() else -- Bullseye Metric --(medevac.coordtype == 4 or 3) - _coordinatesText = _coordinate:ToStringBULLS( self.coalition ) + _coordinatesText = _coordinate:ToStringBULLS(self.coalition) end end return _coordinatesText @@ -1500,55 +1504,55 @@ end --- (Internal) Display active SAR tasks to player. -- @param #CSAR self -- @param #string _unitName Unit to display to -function CSAR:_DisplayActiveSAR( _unitName ) - self:T( self.lid .. " _DisplayActiveSAR" ) - local _msg = "Active MEDEVAC/SAR:" - local _heli = self:_GetSARHeli( _unitName ) -- Wrapper.Unit#UNIT +function CSAR:_DisplayActiveSAR(_unitName) + self:T(self.lid .. " _DisplayActiveSAR") + local _msg = "Active MEDEVAC/SAR:" + local _heli = self:_GetSARHeli(_unitName) -- Wrapper.Unit#UNIT if _heli == nil then - return + return end - + local _heliSide = self.coalition local _csarList = {} - + local _DownedPilotTable = self.downedPilots - self:T( { Table = _DownedPilotTable } ) - for _, _value in pairs( _DownedPilotTable ) do + self:T({Table=_DownedPilotTable}) + for _, _value in pairs(_DownedPilotTable) do local _groupName = _value.name - self:T( string.format( "Display Active Pilot: %s", tostring( _groupName ) ) ) - self:T( { Table = _value } ) + self:T(string.format("Display Active Pilot: %s", tostring(_groupName))) + self:T({Table=_value}) local _woundedGroup = _value.group - if _woundedGroup and _value.alive then - local _coordinatesText = self:_GetPositionOfWounded( _woundedGroup ) - local _helicoord = _heli:GetCoordinate() - local _woundcoord = _woundedGroup:GetCoordinate() - local _distance = self:_GetDistance( _helicoord, _woundcoord ) - self:T( { _distance = _distance } ) - local distancetext = "" - if _SETTINGS:IsImperial() then - distancetext = string.format( "%.1fnm", UTILS.MetersToNM( _distance ) ) - else - distancetext = string.format( "%.1fkm", _distance / 1000.0 ) - end - 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 + if _woundedGroup and _value.alive then + local _coordinatesText = self:_GetPositionOfWounded(_woundedGroup) + local _helicoord = _heli:GetCoordinate() + local _woundcoord = _woundedGroup:GetCoordinate() + local _distance = self:_GetDistance(_helicoord, _woundcoord) + self:T({_distance = _distance}) + local distancetext = "" + if _SETTINGS:IsImperial() then + distancetext = string.format("%.1fnm",UTILS.MetersToNM(_distance)) + else + distancetext = string.format("%.1fkm", _distance/1000.0) + end + 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 - - local function sortDistance( a, b ) - return a.dist < b.dist + + local function sortDistance(a, b) + return a.dist < b.dist end - - table.sort( _csarList, sortDistance ) - - for _, _line in pairs( _csarList ) do - _msg = _msg .. "\n" .. _line.msg + + table.sort(_csarList, sortDistance) + + for _, _line in pairs(_csarList) do + _msg = _msg .. "\n" .. _line.msg end - - self:_DisplayMessageToSAR( _heli, _msg, self.messageTime * 2, false, false, true ) + + self:_DisplayMessageToSAR(_heli, _msg, self.messageTime*2, false, false, true) return self end @@ -1556,38 +1560,38 @@ end -- @param #CSAR self -- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT -- @return #table Table of results -function CSAR:_GetClosestDownedPilot( _heli ) - self:T( self.lid .. " _GetClosestDownedPilot" ) +function CSAR:_GetClosestDownedPilot(_heli) + self:T(self.lid .. " _GetClosestDownedPilot") local _side = self.coalition local _closestGroup = nil local _shortestDistance = -1 local _distance = 0 local _closestGroupInfo = nil local _heliCoord = _heli:GetCoordinate() or _heli:GetCoordinate() - - if _heliCoord == nil then - self:E( "****Error obtaining coordinate!" ) - return nil + + if _heliCoord == nil then + self:E("****Error obtaining coordinate!") + return nil end - + local DownedPilotsTable = self.downedPilots + + for _, _groupInfo in UTILS.spairs(DownedPilotsTable) do + --for _, _groupInfo in pairs(DownedPilotsTable) do + local _woundedName = _groupInfo.name + local _tempWounded = _groupInfo.group + + -- check group exists and not moving to someone else + if _tempWounded then + local _tempCoord = _tempWounded:GetCoordinate() + _distance = self:_GetDistance(_heliCoord, _tempCoord) - for _, _groupInfo in UTILS.spairs( DownedPilotsTable ) do - -- for _, _groupInfo in pairs(DownedPilotsTable) do - local _woundedName = _groupInfo.name - local _tempWounded = _groupInfo.group - - -- check group exists and not moving to someone else - if _tempWounded then - local _tempCoord = _tempWounded:GetCoordinate() - _distance = self:_GetDistance( _heliCoord, _tempCoord ) - - if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then - _shortestDistance = _distance - _closestGroup = _tempWounded - _closestGroupInfo = _groupInfo + if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then + _shortestDistance = _distance + _closestGroup = _tempWounded + _closestGroupInfo = _groupInfo + end end - end end return { pilot = _closestGroup, distance = _shortestDistance, groupInfo = _closestGroupInfo } @@ -1596,40 +1600,38 @@ end --- (Internal) Fire a flare at the point of a downed pilot. -- @param #CSAR self -- @param #string _unitName Name of the unit. -function CSAR:_SignalFlare( _unitName ) - self:T( self.lid .. " _SignalFlare" ) - local _heli = self:_GetSARHeli( _unitName ) +function CSAR:_SignalFlare(_unitName) + self:T(self.lid .. " _SignalFlare") + local _heli = self:_GetSARHeli(_unitName) if _heli == nil then - return + return end - - local _closest = self:_GetClosestDownedPilot( _heli ) + + local _closest = self:_GetClosestDownedPilot(_heli) local smokedist = 8000 - if self.approachdist_far > smokedist then - smokedist = self.approachdist_far - end + if self.approachdist_far > smokedist then smokedist = self.approachdist_far end if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then - - local _clockDir = self:_GetClockDirection( _heli, _closest.pilot ) - local _distance = 0 - if _SETTINGS:IsImperial() then - _distance = string.format( "%.1fnm", UTILS.MetersToNM( _closest.distance ) ) - else - _distance = string.format( "%.1fkm", _closest.distance ) - end - local _msg = string.format( "%s - Popping signal flare at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance ) - self:_DisplayMessageToSAR( _heli, _msg, self.messageTime, false, true, true ) - - local _coord = _closest.pilot:GetCoordinate() - _coord:FlareRed( _clockDir ) + + local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) + local _distance = 0 + if _SETTINGS:IsImperial() then + _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) + else + _distance = string.format("%.1fkm",_closest.distance) + end + local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) + self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) + + local _coord = _closest.pilot:GetCoordinate() + _coord:FlareRed(_clockDir) else - local _distance = smokedist - if _SETTINGS:IsImperial() then - _distance = string.format( "%.1fnm", UTILS.MetersToNM( smokedist ) ) - else - _distance = string.format( "%.1fkm", smokedist / 1000 ) - end - self:_DisplayMessageToSAR( _heli, string.format( "No Pilots within %s", _distance ), self.messageTime, false, false, true ) + local _distance = smokedist + if _SETTINGS:IsImperial() then + _distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) + else + _distance = string.format("%.1fkm",smokedist/1000) + end + self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true) end return self end @@ -1639,53 +1641,51 @@ end -- @param #string _message Message to display. -- @param #number _side Coalition of message. -- @param #number _messagetime How long to show. -function CSAR:_DisplayToAllSAR( _message, _side, _messagetime ) - self:T( self.lid .. " _DisplayToAllSAR" ) +function CSAR:_DisplayToAllSAR(_message, _side, _messagetime) + self:T(self.lid .. " _DisplayToAllSAR") local messagetime = _messagetime or self.messageTime - for _, _unitName in pairs( self.csarUnits ) do - local _unit = self:_GetSARHeli( _unitName ) + for _, _unitName in pairs(self.csarUnits) do + local _unit = self:_GetSARHeli(_unitName) if _unit and not self.suppressmessages then - self:_DisplayMessageToSAR( _unit, _message, _messagetime ) + self:_DisplayMessageToSAR(_unit, _message, _messagetime) end end return self end ---(Internal) Request smoke at closest downed pilot. --- @param #CSAR self --- @param #string _unitName Name of the helicopter +--@param #CSAR self +--@param #string _unitName Name of the helicopter function CSAR:_Reqsmoke( _unitName ) - self:T( self.lid .. " _Reqsmoke" ) - local _heli = self:_GetSARHeli( _unitName ) + self:T(self.lid .. " _Reqsmoke") + local _heli = self:_GetSARHeli(_unitName) if _heli == nil then - return + return end local smokedist = 8000 - if smokedist < self.approachdist_far then - smokedist = self.approachdist_far - end - local _closest = self:_GetClosestDownedPilot( _heli ) + if smokedist < self.approachdist_far then smokedist = self.approachdist_far end + local _closest = self:_GetClosestDownedPilot(_heli) if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then - local _clockDir = self:_GetClockDirection( _heli, _closest.pilot ) - local _distance = 0 - if _SETTINGS:IsImperial() then - _distance = string.format( "%.1fnm", UTILS.MetersToNM( _closest.distance ) ) - else - _distance = string.format( "%.1fkm", _closest.distance / 1000 ) - end - local _msg = string.format( "%s - Popping smoke at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance ) - self:_DisplayMessageToSAR( _heli, _msg, self.messageTime, false, true, true ) - local _coord = _closest.pilot:GetCoordinate() - local color = self.smokecolor - _coord:Smoke( color ) + local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) + local _distance = 0 + if _SETTINGS:IsImperial() then + _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) + else + _distance = string.format("%.1fkm",_closest.distance/1000) + end + local _msg = string.format("%s - Popping smoke at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) + self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) + local _coord = _closest.pilot:GetCoordinate() + local color = self.smokecolor + _coord:Smoke(color) else - local _distance = 0 - if _SETTINGS:IsImperial() then - _distance = string.format( "%.1fnm", UTILS.MetersToNM( smokedist ) ) - else - _distance = string.format( "%.1fkm", smokedist / 1000 ) - end - self:_DisplayMessageToSAR( _heli, string.format( "No Pilots within %s", _distance ), self.messageTime, false, false, true ) + local _distance = 0 + if _SETTINGS:IsImperial() then + _distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) + else + _distance = string.format("%.1fkm",smokedist/1000) + end + self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true) end return self end @@ -1694,120 +1694,120 @@ end -- @param #CSAR self -- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT -- @retunr -function CSAR:_GetClosestMASH( _heli ) - self:T( self.lid .. " _GetClosestMASH" ) +function CSAR:_GetClosestMASH(_heli) + self:T(self.lid .. " _GetClosestMASH") local _mashset = self.mash -- Core.Set#SET_GROUP local _mashes = _mashset:GetSetObjects() -- #table local _shortestDistance = -1 local _distance = 0 local _helicoord = _heli:GetCoordinate() - - local function GetCloseAirbase( coordinate, Coalition, Category ) - - local a = coordinate:GetVec3() - local distmin = math.huge - local airbase = nil - for DCSairbaseID, DCSairbase in pairs( world.getAirbases( Coalition ) ) do - local b = DCSairbase:getPoint() - - local c = UTILS.VecSubstract( a, b ) - local dist = UTILS.VecNorm( c ) - - if dist < distmin and (Category == nil or Category == DCSairbase:getDesc().category) then - distmin = dist - airbase = DCSairbase - end - - end - return distmin + + local function GetCloseAirbase(coordinate,Coalition,Category) + + local a=coordinate:GetVec3() + local distmin=math.huge + local airbase=nil + for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do + local b=DCSairbase:getPoint() + + local c=UTILS.VecSubstract(a,b) + local dist=UTILS.VecNorm(c) + + if dist 0 then - local PilotTable = self.downedPilots - for _, _pilot in pairs( PilotTable ) do - self:T( { _pilot } ) - local pilot = _pilot -- #CSAR.DownedPilot - local group = pilot.group - local frequency = pilot.frequency or 0 -- thanks to @Thrud - if group and group:IsAlive() and frequency > 0 then - self:_AddBeaconToGroup( group, frequency ) + self:T(self.lid .. " _RefreshRadioBeacons") + if self:_CountActiveDownedPilots() > 0 then + local PilotTable = self.downedPilots + for _,_pilot in pairs (PilotTable) do + self:T({_pilot}) + local pilot = _pilot -- #CSAR.DownedPilot + local group = pilot.group + local frequency = pilot.frequency or 0 -- thanks to @Thrud + if group and group:IsAlive() and frequency > 0 then + self:_AddBeaconToGroup(group,frequency) + end end end - end - return self + return self end --- (Internal) Helper function to count active downed pilots. -- @param #CSAR self -- @return #number Number of pilots in the field. function CSAR:_CountActiveDownedPilots() - self:T( self.lid .. " _CountActiveDownedPilots" ) + self:T(self.lid .. " _CountActiveDownedPilots") local PilotsInFieldN = 0 - for _, _unitName in pairs( self.downedPilots ) do - self:T( { _unitName.desc } ) + for _, _unitName in pairs(self.downedPilots) do + self:T({_unitName.desc}) if _unitName.alive == true then PilotsInFieldN = PilotsInFieldN + 1 end @@ -1956,45 +1952,45 @@ end -- @param #CSAR self -- @return #boolean True or false. function CSAR:_ReachedPilotLimit() - self:T( self.lid .. " _ReachedPilotLimit" ) - local limit = self.maxdownedpilots - local islimited = self.limitmaxdownedpilots - local count = self:_CountActiveDownedPilots() - if islimited and (count >= limit) then - return true - else - return false - end + self:T(self.lid .. " _ReachedPilotLimit") + local limit = self.maxdownedpilots + local islimited = self.limitmaxdownedpilots + local count = self:_CountActiveDownedPilots() + if islimited and (count >= limit) then + return true + else + return false + end end ------------------------------- ---- FSM internal Functions --- ------------------------------- + ------------------------------ + --- FSM internal Functions --- + ------------------------------ --- (Internal) Function called after Start() event. -- @param #CSAR self. -- @param #string From From state. -- @param #string Event Event triggered. -- @param #string To To state. -function CSAR:onafterStart( From, Event, To ) - self:T( { From, Event, To } ) - self:I( self.lid .. "Started." ) +function CSAR:onafterStart(From, Event, To) + self:T({From, Event, To}) + self:I(self.lid .. "Started.") -- event handler - 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 ) + 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) if self.useprefix then local prefixes = self.csarPrefix or {} - self.allheligroupset = SET_GROUP:New():FilterCoalitions( self.coalitiontxt ):FilterPrefixes( prefixes ):FilterCategoryHelicopter():FilterStart() + self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(prefixes):FilterCategoryHelicopter():FilterStart() else - self.allheligroupset = SET_GROUP:New():FilterCoalitions( self.coalitiontxt ):FilterCategoryHelicopter():FilterStart() + self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart() end - self.mash = SET_GROUP:New():FilterCoalitions( self.coalitiontxt ):FilterPrefixes( self.mashprefix ):FilterStart() -- currently only GROUP objects, maybe support STATICs also? - self:__Status( -10 ) + self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also? + self:__Status(-10) return self end @@ -2003,14 +1999,14 @@ end function CSAR:_CheckDownedPilotTable() local pilots = self.downedPilots local npilots = {} - - for _ind, _entry in pairs( pilots ) do + + for _ind,_entry in pairs(pilots) do local _group = _entry.group if _group:IsAlive() then - npilots[_ind] = _entry + npilots[_ind] = _entry else if _entry.alive then - self:__KIA( 1, _entry.desc ) + self:__KIA(1,_entry.desc) end end end @@ -2023,27 +2019,27 @@ end -- @param #string From From state. -- @param #string Event Event triggered. -- @param #string To To state. -function CSAR:onbeforeStatus( From, Event, To ) - self:T( { From, Event, To } ) +function CSAR:onbeforeStatus(From, Event, To) + self:T({From, Event, To}) -- housekeeping self:_AddMedevacMenuItem() - + if not self.BeaconTimer or (self.BeaconTimer and not self.BeaconTimer:IsRunning()) then - self.BeaconTimer = TIMER:New( self._RefreshRadioBeacons, self ) - self.BeaconTimer:Start( 2, self.beaconRefresher ) + self.BeaconTimer = TIMER:New(self._RefreshRadioBeacons,self) + self.BeaconTimer:Start(2,self.beaconRefresher) end - + self:_CheckDownedPilotTable() - for _, _sar in pairs( self.csarUnits ) do + for _,_sar in pairs (self.csarUnits) do local PilotTable = self.downedPilots - for _, _entry in pairs( PilotTable ) do + for _,_entry in pairs (PilotTable) do if _entry.alive then local entry = _entry -- #CSAR.DownedPilot local name = entry.name local timestamp = entry.timestamp or 0 local now = timer.getAbsTime() - if now - timestamp > 17 then -- only check if we're not in approach mode, which is iterations of 5 and 10. - self:_CheckWoundedGroupStatus( _sar, name ) + if now - timestamp > 17 then -- only check if we\'re not in approach mode, which is iterations of 5 and 10. + self:_CheckWoundedGroupStatus(_sar,name) end end end @@ -2056,34 +2052,35 @@ end -- @param #string From From state. -- @param #string Event Event triggered. -- @param #string To To state. -function CSAR:onafterStatus( From, Event, To ) - self:T( { From, Event, To } ) +function CSAR:onafterStatus(From, Event, To) + self:T({From, Event, To}) -- collect some stats local NumberOfSARPilots = 0 - for _, _unitName in pairs( self.csarUnits ) do + for _, _unitName in pairs(self.csarUnits) do NumberOfSARPilots = NumberOfSARPilots + 1 end local PilotsInFieldN = self:_CountActiveDownedPilots() - + local PilotsBoarded = 0 - for _, _unitName in pairs( self.inTransitGroups ) do - for _, _units in pairs( _unitName ) do + for _, _unitName in pairs(self.inTransitGroups) do + for _,_units in pairs(_unitName) do PilotsBoarded = PilotsBoarded + 1 end end - + if self.verbose > 0 then - local text = string.format( "%s Active SAR: %d | Downed Pilots in field: %d (max %d) | Pilots boarded: %d | Landings: %d | Pilots rescued: %d", self.lid, NumberOfSARPilots, PilotsInFieldN, self.maxdownedpilots, PilotsBoarded, self.rescues, self.rescuedpilots ) - self:T( text ) + local text = string.format("%s Active SAR: %d | Downed Pilots in field: %d (max %d) | Pilots boarded: %d | Landings: %d | Pilots rescued: %d", + self.lid,NumberOfSARPilots,PilotsInFieldN,self.maxdownedpilots,PilotsBoarded,self.rescues,self.rescuedpilots) + self:T(text) if self.verbose < 2 then - self:I( text ) + self:I(text) elseif self.verbose > 1 then - self:I( text ) - local m = MESSAGE:New( text, "10", "Status", true ):ToCoalition( self.coalition ) + self:I(text) + local m = MESSAGE:New(text,"10","Status",true):ToCoalition(self.coalition) end end - self:__Status( -20 ) + self:__Status(-20) return self end @@ -2092,17 +2089,17 @@ end -- @param #string From From state. -- @param #string Event Event triggered. -- @param #string To To state. -function CSAR:onafterStop( From, Event, To ) - self:T( { From, Event, To } ) +function CSAR:onafterStop(From, Event, To) + self:T({From, Event, To}) -- event handler - 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 ) - self:T( self.lid .. "Stopped." ) + 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) + self:T(self.lid .. "Stopped.") return self end @@ -2112,10 +2109,10 @@ end -- @param #string Event Event triggered. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. --- @param #string Woundedgroupname Name of the downed pilot's group. -function CSAR:onbeforeApproach( From, Event, To, Heliname, Woundedgroupname ) - self:T( { From, Event, To, Heliname, Woundedgroupname } ) - self:_CheckWoundedGroupStatus( Heliname, Woundedgroupname ) +-- @param #string Woundedgroupname Name of the downed pilot\'s group. +function CSAR:onbeforeApproach(From, Event, To, Heliname, Woundedgroupname) + self:T({From, Event, To, Heliname, Woundedgroupname}) + self:_CheckWoundedGroupStatus(Heliname,Woundedgroupname) return self end @@ -2125,10 +2122,10 @@ end -- @param #string Event Event triggered. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. --- @param #string Woundedgroupname Name of the downed pilot's group. -function CSAR:onbeforeBoarded( From, Event, To, Heliname, Woundedgroupname ) - self:T( { From, Event, To, Heliname, Woundedgroupname } ) - self:_ScheduledSARFlight( Heliname, Woundedgroupname ) +-- @param #string Woundedgroupname Name of the downed pilot\'s group. +function CSAR:onbeforeBoarded(From, Event, To, Heliname, Woundedgroupname) + self:T({From, Event, To, Heliname, Woundedgroupname}) + self:_ScheduledSARFlight(Heliname,Woundedgroupname) return self end @@ -2138,11 +2135,11 @@ end -- @param #string Event Event triggered. -- @param #string To To state. -- @param #string Heliname Name of the helicopter group. --- @param #string Woundedgroupname Name of the downed pilot's group. +-- @param #string Woundedgroupname Name of the downed pilot\'s group. -- @param #boolean IsAirport True if heli has landed on an AFB (from event land). -function CSAR:onbeforeReturning( From, Event, To, Heliname, Woundedgroupname, IsAirPort ) - self:T( { From, Event, To, Heliname, Woundedgroupname } ) - self:_ScheduledSARFlight( Heliname, Woundedgroupname, IsAirPort ) +function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname, IsAirPort) + self:T({From, Event, To, Heliname, Woundedgroupname}) + self:_ScheduledSARFlight(Heliname,Woundedgroupname, IsAirPort) return self end @@ -2154,8 +2151,8 @@ end -- @param Wrapper.Unit#UNIT HeliUnit Unit of the helicopter. -- @param #string HeliName Name of the helicopter group. -- @param #number PilotsSaved Number of the saved pilots on board when landing. -function CSAR:onbeforeRescued( From, Event, To, HeliUnit, HeliName, PilotsSaved ) - self:T( { From, Event, To, HeliName, HeliUnit } ) +function CSAR:onbeforeRescued(From, Event, To, HeliUnit, HeliName, PilotsSaved) + self:T({From, Event, To, HeliName, HeliUnit}) self.rescues = self.rescues + 1 self.rescuedpilots = self.rescuedpilots + PilotsSaved return self @@ -2170,8 +2167,8 @@ end -- @param #number Frequency Beacon frequency in kHz. -- @param #string Leadername Name of the #UNIT of the downed pilot. -- @param #string CoordinatesText String of the position of the pilot. Format determined by self.coordtype. -function CSAR:onbeforePilotDown( From, Event, To, Group, Frequency, Leadername, CoordinatesText ) - self:T( { From, Event, To, Group, Frequency, Leadername, CoordinatesText } ) +function CSAR:onbeforePilotDown(From, Event, To, Group, Frequency, Leadername, CoordinatesText) + self:T({From, Event, To, Group, Frequency, Leadername, CoordinatesText}) return self end -------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 04fb227d2..a1bc0e99c 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -696,7 +696,7 @@ do -- ["Mi-24P"] = {type="Mi-24P", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18}, -- ["Mi-24V"] = {type="Mi-24V", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18}, -- ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25}, --- +-- ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16}, -- -- ### 2.1.2 Activate and deactivate zones -- @@ -987,11 +987,12 @@ CTLD.UnitTypes = { ["Mi-24V"] = {type="Mi-24V", crates=true, troops=true, cratelimit = 2, trooplimit = 8, length = 18}, ["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25}, -- 19t cargo, 64 paratroopers. --Actually it's longer, but the center coord is off-center of the model. + ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16}, -- 4t cargo, 20 (unsec) seats } --- CTLD class version. -- @field #string version -CTLD.version="1.0.2" +CTLD.version="1.0.3" --- Instantiate a new CTLD. -- @param #CTLD self