mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
New Module AI CSAR
This commit is contained in:
parent
9686e74feb
commit
4ce09a3845
622
Moose Development/Moose/Functional/AICSAR.lua
Normal file
622
Moose Development/Moose/Functional/AICSAR.lua
Normal file
@ -0,0 +1,622 @@
|
|||||||
|
--- **Functional** - AI CSAR system
|
||||||
|
--
|
||||||
|
-- ## Main Features:
|
||||||
|
--
|
||||||
|
-- * Send out helicopters to downed pilots
|
||||||
|
-- * Rescues players and AI alike
|
||||||
|
-- * Coalition specific
|
||||||
|
-- * Starting from a FARP or Airbase
|
||||||
|
-- * Dedicated MASH zone
|
||||||
|
-- * Some FSM functions to include in your mission scripts
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Example Missions:
|
||||||
|
--
|
||||||
|
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/).
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **applevangelist**
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
-- @module Functional.AICSAR
|
||||||
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- AI CSAR class.
|
||||||
|
-- @type AICSAR
|
||||||
|
-- @field #string ClassName Name of this class.
|
||||||
|
-- @field #string version Versioning.
|
||||||
|
-- @field #string lid LID for log entries.
|
||||||
|
-- @field #number coalition Colition side.
|
||||||
|
-- @field #string template Template for pilot.
|
||||||
|
-- @field #string helotemplate Template for CSAR helo.
|
||||||
|
-- @field #string alias Alias Name.
|
||||||
|
-- @field Wrapper.Airbase#AIRBASE farp FARP object from where to start.
|
||||||
|
-- @field Core.Zone#ZONE farpzone MASH zone to drop rescued pilots.
|
||||||
|
-- @field #number maxdistance Max distance to go for a rescue.
|
||||||
|
-- @field #table pilotqueue Queue of pilots to rescue.
|
||||||
|
-- @field #number pilotindex Table index to bind pilot to helo.
|
||||||
|
-- @field #table helos Table of Ops.FlightGroup#FLIGHTGROUP objects
|
||||||
|
-- @field #boolean verbose Switch more output.
|
||||||
|
-- @field #number rescuezoneradius Radius around downed pilot for the helo to land in.
|
||||||
|
-- @field #table rescued Track number of rescued pilot.
|
||||||
|
-- @field #boolean autoonoff Only send a helo when no human heli pilots are available.
|
||||||
|
-- @field Core.Set#SET_CLIENT playerset Track if alive heli pilots are available.
|
||||||
|
--
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
|
--- *I once donated a pint of my finest red corpuscles to the great American Red Cross and the doctor opined my blood was very helpful; contained so much alcohol they could use it to sterilize their instruments.*
|
||||||
|
-- W.C. Fields
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- # AICSAR Concept
|
||||||
|
--
|
||||||
|
-- For an AI or human pilot landing with a parachute, a rescue mission will be spawned. The helicopter will fly to the pilot, pick him or her up,
|
||||||
|
-- and fly back to a designated MASH (medical) zone, drop the pilot and then return to base.
|
||||||
|
-- Operational maxdistance can be set as well as the landing radius around the downed pilot.
|
||||||
|
-- Keep in mind that AI helicopters cannot hover-load at the time of writing, so rescue operations over water or in the mountains might not
|
||||||
|
-- work.
|
||||||
|
-- Optionally, if you have a CSAR operation with human pilots in your mission, you can set AICSAR to ignore missions when humna helicopter
|
||||||
|
-- pilots are around.
|
||||||
|
--
|
||||||
|
-- ## Setup
|
||||||
|
--
|
||||||
|
-- Setup is a one-liner:
|
||||||
|
--
|
||||||
|
-- -- @param #string Alias Name of this instance.
|
||||||
|
-- -- @param #number Coalition Coalition as in coalition.side.BLUE, can also be passed as "blue", "red" or "neutral"
|
||||||
|
-- -- @param #string Pilottemplate Pilot template name.
|
||||||
|
-- -- @param #string Helotemplate Helicopter template name.
|
||||||
|
-- -- @param Wrapper.Airbase#AIRBASE FARP FARP object or Airbase from where to start.
|
||||||
|
-- -- @param Core.Zone#ZONE MASHZone Zone where to drop pilots after rescue.
|
||||||
|
-- local my_aicsar=AICSAR:New("Luftrettung",coalition.side.BLUE,"Downed Pilot","Rescue Helo",AIRBASE:FindByName("Test FARP"),ZONE:New("MASH"))
|
||||||
|
--
|
||||||
|
-- ## Options are
|
||||||
|
--
|
||||||
|
-- my_aicsar.maxdistance -- maximum operational distance in meters. Defaults to 50NM or 92.6km
|
||||||
|
-- my_aicsar.rescuezoneradius -- landing zone around downed pilot. Defaults to 200m
|
||||||
|
-- my_aicsar.autoonoff -- stop operations when human helicopter pilots are around. Defaults to true.
|
||||||
|
-- my_aicsar.verbose -- messages coalition side about ongoing operations. Defaults to true.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
---
|
||||||
|
--
|
||||||
|
-- @field #AICSAR
|
||||||
|
AICSAR = {
|
||||||
|
ClassName = "AICSAR",
|
||||||
|
version = "0.0.1",
|
||||||
|
lid = "",
|
||||||
|
coalition = coalition.side.BLUE,
|
||||||
|
template = "",
|
||||||
|
helotemplate = "",
|
||||||
|
alias = "",
|
||||||
|
farp = nil,
|
||||||
|
farpzone = nil,
|
||||||
|
maxdistance = UTILS.NMToMeters(50),
|
||||||
|
pilotqueue = {},
|
||||||
|
pilotindex = 0,
|
||||||
|
helos = {},
|
||||||
|
verbose = true,
|
||||||
|
rescuezoneradius = 200,
|
||||||
|
rescued = {},
|
||||||
|
autoonoff = true,
|
||||||
|
playerset = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Function to create a new AICSAR object
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string Alias Name of this instance.
|
||||||
|
-- @param #number Coalition Coalition as in coalition.side.BLUE, can also be passed as "blue", "red" or "neutral"
|
||||||
|
-- @param #string Pilottemplate Pilot template name.
|
||||||
|
-- @param #string Helotemplate Helicopter template name.
|
||||||
|
-- @param Wrapper.Airbase#AIRBASE FARP FARP object or Airbase from where to start.
|
||||||
|
-- @param Core.Zone#ZONE MASHZone Zone where to drop pilots after rescue.
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:New(Alias,Coalition,Pilottemplate,Helotemplate,FARP,MASHZone)
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self=BASE:Inherit(self, FSM:New())
|
||||||
|
|
||||||
|
--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
|
||||||
|
self.coalitiontxt = Coalition
|
||||||
|
elseif Coalition=="neutral" then
|
||||||
|
self.coalition=coalition.side.NEUTRAL
|
||||||
|
self.coalitiontxt = Coalition
|
||||||
|
else
|
||||||
|
self:E("ERROR: Unknown coalition in CSAR!")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.coalition = Coalition
|
||||||
|
self.coalitiontxt = string.lower(UTILS.GetCoalitionName(self.coalition))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Set alias.
|
||||||
|
if Alias then
|
||||||
|
self.alias=tostring(Alias)
|
||||||
|
else
|
||||||
|
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"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.template = Pilottemplate
|
||||||
|
self.helotemplate = Helotemplate
|
||||||
|
self.farp = FARP
|
||||||
|
self.farpzone = MASHZone
|
||||||
|
self.playerset = SET_CLIENT:New():FilterActive(true):FilterCategories("helicopter"):FilterStart()
|
||||||
|
|
||||||
|
-- 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")
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Stopped")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Status", "*") -- CSAR status update.
|
||||||
|
self:AddTransition("*", "PilotDown", "*") -- Pilot down
|
||||||
|
self:AddTransition("*", "PilotPickedUp", "*") -- Pilot in helo
|
||||||
|
self:AddTransition("*", "PilotRescued", "*") -- Pilot Rescued
|
||||||
|
self:AddTransition("*", "PilotKIA", "*") -- Pilot dead
|
||||||
|
self:AddTransition("*", "HeloDown", "*") -- Helo dead
|
||||||
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
|
|
||||||
|
self:HandleEvent(EVENTS.LandingAfterEjection)
|
||||||
|
|
||||||
|
self:__Start(math.random(2,5))
|
||||||
|
|
||||||
|
self:I(self.lid .. " AI CSAR Starting")
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
--- Pseudo Functions ---
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Status".
|
||||||
|
-- @function [parent=#AICSAR] Status
|
||||||
|
-- @param #AICSAR self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Status" after a delay.
|
||||||
|
-- @function [parent=#AICSAR] __Status
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop".
|
||||||
|
-- @function [parent=#AICSAR] Stop
|
||||||
|
-- @param #AICSAR self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop" after a delay.
|
||||||
|
-- @function [parent=#AICSAR] __Stop
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- On after "PilotDown" event.
|
||||||
|
-- @function [parent=#AICSAR] OnAfterPilotDown
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Location of the pilot.
|
||||||
|
-- @param #boolean InReach True if in maxdistance else false.
|
||||||
|
|
||||||
|
--- On after "PilotPickedUp" event.
|
||||||
|
-- @function [parent=#AICSAR] OnAfterPilotPickedUp
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Ops.FlightGroup#FLIGHTGROUP Helo
|
||||||
|
-- @param #table CargoTable of Ops.OpsGroup#OPSGROUP Cargo objects
|
||||||
|
-- @param #number Index
|
||||||
|
|
||||||
|
--- On after "PilotRescued" event.
|
||||||
|
-- @function [parent=#AICSAR] OnAfterPilotRescued
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
|
||||||
|
--- On after "PilotKIA" event.
|
||||||
|
-- @function [parent=#AICSAR] OnAfterPilotKIA
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
|
||||||
|
--- On after "HeloDown" event.
|
||||||
|
-- @function [parent=#AICSAR] OnAfterHeloDown
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Ops.FlightGroup#FLIGHTGROUP Helo
|
||||||
|
-- @param #number Index
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- [Internal] Catch the landing after ejection and spawn a pilot in situ.
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:OnEventLandingAfterEjection(EventData)
|
||||||
|
self:T(self.lid .. "OnEventLandingAfterEjection ID=" .. EventData.id)
|
||||||
|
|
||||||
|
-- autorescue on off?
|
||||||
|
if self.autoonoff then
|
||||||
|
if self.playerset:CountAlive() > 0 then
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local _event = EventData -- Core.Event#EVENTDATA
|
||||||
|
-- get position and spawn in a template pilot
|
||||||
|
local _LandingPos = COORDINATE:NewFromVec3(_event.initiator:getPosition().p)
|
||||||
|
local _country = _event.initiator:getCountry()
|
||||||
|
local _coalition = coalition.getCountryCoalition( _country )
|
||||||
|
|
||||||
|
-- DONE: add distance check
|
||||||
|
local distancetofarp = _LandingPos:Get2DDistance(self.farp:GetCoordinate())
|
||||||
|
|
||||||
|
if _coalition == self.coalition and distancetofarp <= self.maxdistance then
|
||||||
|
self:T(self.lid .. "Spawning new Pilot")
|
||||||
|
self.pilotindex = self.pilotindex + 1
|
||||||
|
local newpilot = SPAWN:NewWithAlias(self.template,string.format("%s-AICSAR-%d",self.template, self.pilotindex))
|
||||||
|
newpilot:InitDelayOff()
|
||||||
|
newpilot:OnSpawnGroup(
|
||||||
|
function (grp)
|
||||||
|
self.pilotqueue[self.pilotindex] = grp
|
||||||
|
end
|
||||||
|
)
|
||||||
|
newpilot:SpawnFromCoordinate(_LandingPos)
|
||||||
|
--self.pilotqueue[self.pilotindex] = newpilot
|
||||||
|
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
|
||||||
|
self:__PilotDown(2,_LandingPos,true)
|
||||||
|
if self.verbose then
|
||||||
|
local text = "Roger, Pilot, we hear you. Stay where you are, a helo is on the way!"
|
||||||
|
MESSAGE:New(text,15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
elseif _coalition == self.coalition and distancetofarp > self.maxdistance then
|
||||||
|
-- apologies, too far off
|
||||||
|
self:T(self.lid .. "Pilot out of reach")
|
||||||
|
self:__PilotDown(2,_LandingPos,false)
|
||||||
|
if self.verbose then
|
||||||
|
local text = "Sorry, Pilot. You're behind maximum operational distance! Good Luck!"
|
||||||
|
MESSAGE:New(text,15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Get (available?) FlightGroup
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @return Ops.FlightGroup#FLIGHTGROUP The FlightGroup
|
||||||
|
function AICSAR:_GetFlight()
|
||||||
|
self:T(self.lid .. "_GetFlight")
|
||||||
|
-- Helo Carrier.
|
||||||
|
local newhelo = SPAWN:NewWithAlias(self.helotemplate,self.helotemplate..math.random(1,10000))
|
||||||
|
:InitDelayOff()
|
||||||
|
:InitUnControlled(true)
|
||||||
|
:Spawn()
|
||||||
|
|
||||||
|
local nhelo=FLIGHTGROUP:New(newhelo)
|
||||||
|
nhelo:SetHomebase(self.farp)
|
||||||
|
nhelo:Activate()
|
||||||
|
return nhelo
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Create a new rescue mission
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param Wrapper.Group#GROUP Pilot The pilot to be rescued.
|
||||||
|
-- @param #number Index Index number of this pilot
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:_InitMission(Pilot,Index)
|
||||||
|
self:T(self.lid .. "_InitMission")
|
||||||
|
|
||||||
|
local pickupzone = ZONE_GROUP:New(Pilot:GetName(),Pilot,self.rescuezoneradius)
|
||||||
|
--local pilotset = SET_GROUP:New()
|
||||||
|
--pilotset:AddGroup(Pilot)
|
||||||
|
|
||||||
|
-- Cargo transport assignment.
|
||||||
|
local opstransport=OPSTRANSPORT:New(Pilot, pickupzone, self.farpzone)
|
||||||
|
|
||||||
|
local helo = self:_GetFlight()
|
||||||
|
-- inject reservation
|
||||||
|
helo.AICSARReserved = true
|
||||||
|
|
||||||
|
-- Cargo transport assignment to first Huey group.
|
||||||
|
helo:AddOpsTransport(opstransport)
|
||||||
|
|
||||||
|
-- callback functions
|
||||||
|
local function AICPickedUp(Helo,Cargo,Index)
|
||||||
|
self:__PilotPickedUp(2,Helo,Cargo,Index)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function AICHeloDead(Helo,Index)
|
||||||
|
self:__HeloDown(2,Helo,Index)
|
||||||
|
end
|
||||||
|
|
||||||
|
function helo:OnAfterLoadingDone(From,Event,To)
|
||||||
|
AICPickedUp(helo,helo:GetCargoGroups(),Index)
|
||||||
|
end
|
||||||
|
|
||||||
|
function helo:OnAfterDead(From,Event,To)
|
||||||
|
AICHeloDead(helo,Index)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.helos[Index] = helo
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check if pilot arrived in rescue zone (MASH)
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param Wrapper.Group#GROUP Pilot The pilot to be rescued.
|
||||||
|
-- @return #boolean outcome
|
||||||
|
function AICSAR:_CheckInMashZone(Pilot)
|
||||||
|
self:T(self.lid .. "_CheckQueue")
|
||||||
|
if Pilot:IsInZone(self.farpzone) then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check helo queue
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:_CheckHelos()
|
||||||
|
self:T(self.lid .. "_CheckHelos")
|
||||||
|
for _index,_helo in pairs(self.helos) do
|
||||||
|
local helo = _helo -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
if helo and helo.ClassName == "FLIGHTGROUP" then
|
||||||
|
local state = helo:GetState()
|
||||||
|
local name = helo:GetName()
|
||||||
|
self:T("Helo group "..name.." in state "..state)
|
||||||
|
if state == "Arrived" then
|
||||||
|
helo:__Stop(1)
|
||||||
|
self.helos[_index] = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.helos[_index] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check pilot queue for next mission
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:_CheckQueue()
|
||||||
|
self:T(self.lid .. "_CheckQueue")
|
||||||
|
for _index, _pilot in pairs(self.pilotqueue) do
|
||||||
|
local classname = _pilot.ClassName and _pilot.ClassName or "NONE"
|
||||||
|
local name = _pilot.GroupName and _pilot.GroupName or "NONE"
|
||||||
|
--self:T("Looking at " .. classname .. " " .. name)
|
||||||
|
-- find one w/o mission
|
||||||
|
if _pilot and _pilot.ClassName and _pilot.ClassName == "GROUP" then
|
||||||
|
-- has no mission assigned?
|
||||||
|
if not _pilot.AICSAR then
|
||||||
|
_pilot.AICSAR = {}
|
||||||
|
_pilot.AICSAR.Status = "Initiated"
|
||||||
|
_pilot.AICSAR.Boarded = false
|
||||||
|
self:_InitMission(_pilot,_index)
|
||||||
|
break
|
||||||
|
else
|
||||||
|
-- update status from OPSGROUP
|
||||||
|
local flightgroup = self.helos[_index] -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
if flightgroup then
|
||||||
|
local state = flightgroup:GetState()
|
||||||
|
_pilot.AICSAR.Status = state
|
||||||
|
end
|
||||||
|
--self:T("Flight for " .. _pilot.GroupName .. " in state " .. state)
|
||||||
|
if self:_CheckInMashZone(_pilot) then
|
||||||
|
self:T("Pilot" .. _pilot.GroupName .. " rescued!")
|
||||||
|
_pilot:Destroy(false)
|
||||||
|
self.pilotqueue[_index] = nil
|
||||||
|
self.rescued[_index] = true
|
||||||
|
self:__PilotRescued(2)
|
||||||
|
flightgroup.AICSARReserved = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- [Internal] onafterStart
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterStart(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
self:__Status(3)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterStatus
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterStatus(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
self:_CheckQueue()
|
||||||
|
self:_CheckHelos()
|
||||||
|
self:__Status(30)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterStop
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterStop(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
self:UnHandleEvent(EVENTS.LandingAfterEjection)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterPilotDown
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Location of the pilot.
|
||||||
|
-- @param #boolean InReach True if in maxdistance else false.
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterPilotDown(From, Event, To, Coordinate, InReach)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
local CoordinateText = Coordinate:ToStringMGRS()
|
||||||
|
local inreach = tostring(InReach)
|
||||||
|
local text = string.format("Pilot down at %s. In reach = %s",CoordinateText,inreach)
|
||||||
|
self:T(text)
|
||||||
|
if self.verbose then
|
||||||
|
MESSAGE:New(text,15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterPilotKIA
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterPilotKIA(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.verbose then
|
||||||
|
MESSAGE:New("Pilot KIA!",15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterHeloDown
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @param Ops.FlightGroup#FLIGHTGROUP Helo
|
||||||
|
-- @param #number Index
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterHeloDown(From, Event, To, Helo, Index)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.verbose then
|
||||||
|
MESSAGE:New("CSAR Helo Down!",15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
local findex = 0
|
||||||
|
local fhname = Helo:GetName()
|
||||||
|
-- find index of Helo
|
||||||
|
if Index and Index > 0 then
|
||||||
|
findex=Index
|
||||||
|
else
|
||||||
|
for _index, _helo in pairs(self.helos) do
|
||||||
|
local helo = _helo -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
local hname = helo:GetName()
|
||||||
|
if fhname == hname then
|
||||||
|
findex = _index
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- find pilot
|
||||||
|
if findex > 0 and not self.rescued[findex] then
|
||||||
|
local pilot = self.pilotqueue[findex]
|
||||||
|
self.helos[findex] = nil
|
||||||
|
if pilot.AICSAR.Boarded then
|
||||||
|
self:T("Helo Down: Found DEAD Pilot ID " .. findex .. " with name " .. pilot:GetName())
|
||||||
|
-- pilot also dead
|
||||||
|
self:__PilotKIA(2)
|
||||||
|
self.pilotqueue[findex] = nil
|
||||||
|
else
|
||||||
|
-- initiate new mission
|
||||||
|
self:T("Helo Down: Found ALIVE Pilot ID " .. findex .. " with name " .. pilot:GetName())
|
||||||
|
self:_InitMission(pilot,findex)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterPilotRescued
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterPilotRescued(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.verbose then
|
||||||
|
MESSAGE:New("Pilot rescued!",15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] onafterPilotPickedUp
|
||||||
|
-- @param #AICSAR self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @param Ops.FlightGroup#FLIGHTGROUP Helo
|
||||||
|
-- @param #table CargoTable of Ops.OpsGroup#OPSGROUP Cargo objects
|
||||||
|
-- @param #number Index
|
||||||
|
-- @return #AICSAR self
|
||||||
|
function AICSAR:onafterPilotPickedUp(From, Event, To, Helo, CargoTable, Index)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.verbose then
|
||||||
|
MESSAGE:New("Pilot picked up!",15,"AICSAR"):ToCoalition(self.coalition)
|
||||||
|
end
|
||||||
|
local findex = 0
|
||||||
|
local fhname = Helo:GetName()
|
||||||
|
if Index and Index > 0 then
|
||||||
|
findex = Index
|
||||||
|
else
|
||||||
|
-- find index of Helo
|
||||||
|
for _index, _helo in pairs(self.helos) do
|
||||||
|
local helo = _helo -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
local hname = helo:GetName()
|
||||||
|
if fhname == hname then
|
||||||
|
findex = _index
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- find pilot
|
||||||
|
if findex > 0 then
|
||||||
|
local pilot = self.pilotqueue[findex]
|
||||||
|
self:T("Boarded: Found Pilot ID " .. findex .. " with name " .. pilot:GetName())
|
||||||
|
pilot.AICSAR.Boarded = true -- mark as boarded
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
@ -71,6 +71,7 @@ __Moose.Include( 'Scripts/Moose/Functional/Fox.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Mantis.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Shorad.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/Autolase.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/Autolase.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Functional/AICSAR.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' )
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user