mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
RESCUEHELO v0.9.7
- Fixed spawn bug with multiple helos. - Adjusted default parameters. - Changed RTB to respawn (not perfect). - Improved documentation.
This commit is contained in:
parent
242151eedf
commit
1559f14f11
@ -1002,11 +1002,15 @@ do -- COORDINATE
|
||||
function COORDINATE:WaypointAir( AltType, Type, Action, Speed, SpeedLocked, airbase, DCSTasks, description )
|
||||
self:F2( { AltType, Type, Action, Speed, SpeedLocked } )
|
||||
|
||||
-- Defaults
|
||||
-- Set alttype or "RADIO" which is AGL.
|
||||
AltType=AltType or "RADIO"
|
||||
|
||||
-- Speedlocked by default
|
||||
if SpeedLocked==nil then
|
||||
SpeedLocked=true
|
||||
end
|
||||
|
||||
-- Speed or default 500 km/h.
|
||||
Speed=Speed or 500
|
||||
|
||||
-- Waypoint array.
|
||||
@ -1015,19 +1019,26 @@ do -- COORDINATE
|
||||
-- Coordinates.
|
||||
RoutePoint.x = self.x
|
||||
RoutePoint.y = self.z
|
||||
|
||||
-- Altitude.
|
||||
RoutePoint.alt = self.y
|
||||
RoutePoint.alt_type = AltType
|
||||
|
||||
-- Waypoint type.
|
||||
RoutePoint.type = Type or nil
|
||||
RoutePoint.action = Action or nil
|
||||
-- Set speed/ETA.
|
||||
|
||||
-- Speed.
|
||||
RoutePoint.speed = Speed/3.6
|
||||
RoutePoint.speed_locked = SpeedLocked
|
||||
|
||||
-- ETA.
|
||||
RoutePoint.ETA=nil
|
||||
RoutePoint.ETA_locked = false
|
||||
RoutePoint.ETA_locked = false
|
||||
|
||||
-- Waypoint description.
|
||||
RoutePoint.name=description
|
||||
|
||||
-- Airbase parameters for takeoff and landing points.
|
||||
if airbase then
|
||||
local AirbaseID = airbase:GetID()
|
||||
@ -1036,31 +1047,24 @@ do -- COORDINATE
|
||||
RoutePoint.linkUnit = AirbaseID
|
||||
RoutePoint.helipadId = AirbaseID
|
||||
elseif AirbaseCategory == Airbase.Category.AIRDROME then
|
||||
RoutePoint.airdromeId = AirbaseID
|
||||
RoutePoint.airdromeId = AirbaseID
|
||||
else
|
||||
self:T("ERROR: Unknown airbase category in COORDINATE:WaypointAir()!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:MarkToAll(string.format("Landing waypoint at airbase %s", airbase:GetName()))
|
||||
end
|
||||
|
||||
|
||||
-- ["task"] =
|
||||
-- {
|
||||
-- ["id"] = "ComboTask",
|
||||
-- ["params"] =
|
||||
-- {
|
||||
-- ["tasks"] =
|
||||
-- {
|
||||
-- }, -- end of ["tasks"]
|
||||
-- }, -- end of ["params"]
|
||||
-- }, -- end of ["task"]
|
||||
|
||||
-- Waypoint tasks.
|
||||
RoutePoint.task = {}
|
||||
RoutePoint.task.id = "ComboTask"
|
||||
RoutePoint.task.params = {}
|
||||
RoutePoint.task.params.tasks = DCSTasks or {}
|
||||
|
||||
-- Debug.
|
||||
self:T({RoutePoint=RoutePoint})
|
||||
|
||||
-- Return waypoint.
|
||||
return RoutePoint
|
||||
end
|
||||
|
||||
|
||||
@ -13,7 +13,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- ### Author: **funkyfranky**
|
||||
-- ### Contributions: Flightcontrol (@{#AI_FORMATION} class)
|
||||
--
|
||||
-- @module Ops.RescueHelo
|
||||
-- @image MOOSE.JPG
|
||||
@ -26,6 +27,7 @@
|
||||
-- @field Wrapper.Unit#UNIT carrier The carrier the helo is attached to.
|
||||
-- @field #string carriertype Carrier type.
|
||||
-- @field #string helogroupname Name of the late activated helo template group.
|
||||
-- @field #string helogroupalias Spawn alias name of the group. Necessary for multiple RESCUEHELO objects in one mission. Uses groupname plus carrier name.
|
||||
-- @field Wrapper.Group#GROUP helo Helo group.
|
||||
-- @field #number takeoff Takeoff type.
|
||||
-- @field Wrapper.Airbase#AIRBASE airbase The airbase object acting as home base of the helo.
|
||||
@ -45,6 +47,7 @@
|
||||
-- @field #boolean rescuestopboat If true, stop carrier during rescue operations.
|
||||
-- @field #boolean carrierstop If true, route of carrier was stopped.
|
||||
-- @field #number HeloFuel0 Initial fuel of helo in percent. Necessary due to DCS bug that helo with full tank does not return fuel via API function.
|
||||
-- @field #boolean rtb If true, Helo will be return to base on the next status check.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Rescue Helo
|
||||
@ -77,13 +80,13 @@
|
||||
--
|
||||
-- Once the helo is out of fuel, it will return to the carrier. When the helo lands, it will be respawned immidiately and go back on station.
|
||||
--
|
||||
-- If a unit crashes or a pilot ejects within a radius of 100 km from the USS Stennis, the helo will automatically fly to the crash side and
|
||||
-- If a unit crashes or a pilot ejects within a radius of 30 km from the USS Stennis, the helo will automatically fly to the crash side and
|
||||
-- rescue to pilot. This will take around 5 minutes. After that, the helo will return to the Stennis, land there and bring back the poor guy.
|
||||
-- When this is done, the helo will go back on station.
|
||||
--
|
||||
-- # Fine Tuning
|
||||
--
|
||||
-- The implementation allows to customize quite a few settings easily
|
||||
-- The implementation allows to customize quite a few settings easily.
|
||||
--
|
||||
-- ## Takeoff Type
|
||||
--
|
||||
@ -129,7 +132,22 @@
|
||||
--
|
||||
-- * @{#RESCUEHELO.SetAltitude}(*altitude*), where *altitude* is the altitude the helo flies at in meters. Default is 70 meters.
|
||||
-- * @{#RESCUEHELO.SetOffsetX}(*distance*)}, where *distance is the distance in the direction of movement of the carrier. Default is 200 meters.
|
||||
-- * @{#RESCUEHELO.SetOffsetZ}(*distance*)}, where *distance is the distance on the starboard side. Default is 200 meters.
|
||||
-- * @{#RESCUEHELO.SetOffsetZ}(*distance*)}, where *distance is the distance on the starboard side. Default is 100 meters.
|
||||
--
|
||||
-- ## Rescue Operations
|
||||
--
|
||||
-- By default the rescue helo will start a rescue operation if an aircraft crashes or a pilot ejects in the vicinity of the carrier.
|
||||
-- The standard "rescue zone" has a radius of 30 km around the carrier. The radius can be adjusted via the @{#RESCUEHELO.SetRescueZone}(*radius*) functions,
|
||||
-- where *radius* is the radius of the zone in kilometers. If you use multiple rescue helos in the same mission, you might want to ensure that the radii
|
||||
-- are not overlapping so that two helos try to rescue the same pilot. But it should not hurt either way.
|
||||
--
|
||||
-- Once the helo reaches the crash site, the rescue operation will last 5 minutes. This time can be changed by @{#RESCUEHELO.SetRescueDuration(*time*),
|
||||
-- where *time* is the duration in minutes.
|
||||
--
|
||||
-- During the rescue operation, the helo will hover (orbit) over the crash site at a speed of 10 km/h. The speed can be set by @{#RESCUEHELO.SetRescueHoverSpeed}(*speed*),
|
||||
-- where the *speed* is given in km/h.
|
||||
--
|
||||
-- If no rescue operations should be carried out by the helo, this option can be completely disabled by using @{#RESCUEHELO.SetRescueOff}().
|
||||
--
|
||||
-- # Finite State Machine
|
||||
--
|
||||
@ -164,6 +182,7 @@
|
||||
-- You have the option to enable the debug mode for this class via the @{#RESCUEHELO.SetDebugModeON} function.
|
||||
-- If enabled, text messages about the helo status will be displayed on screen and marks of the pattern created on the F10 map.
|
||||
--
|
||||
--
|
||||
-- @field #RESCUEHELO
|
||||
RESCUEHELO = {
|
||||
ClassName = "RESCUEHELO",
|
||||
@ -172,6 +191,7 @@ RESCUEHELO = {
|
||||
carrier = nil,
|
||||
carriertype = nil,
|
||||
helogroupname = nil,
|
||||
helogroupalias = nil,
|
||||
helo = nil,
|
||||
airbase = nil,
|
||||
takeoff = nil,
|
||||
@ -190,17 +210,19 @@ RESCUEHELO = {
|
||||
rescuespeed = nil,
|
||||
rescuestopboat = nil,
|
||||
HeloFuel0 = nil,
|
||||
carrierstop = false,
|
||||
rtb = nil,
|
||||
carrierstop = nil,
|
||||
}
|
||||
|
||||
--- Class version.
|
||||
-- @field #string version
|
||||
RESCUEHELO.version="0.9.6"
|
||||
RESCUEHELO.version="0.9.7"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Add messages for rescue mission.
|
||||
-- TODO: Add option to stop carrier while rescue operation is in progress? Done but NOT working!
|
||||
-- DONE: Write documenation.
|
||||
-- DONE: Add option to deactivate the rescueing.
|
||||
@ -250,7 +272,17 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
||||
self:SetRescueHoverSpeed()
|
||||
self:SetRescueDuration()
|
||||
self:SetRescueStopBoatOff()
|
||||
|
||||
|
||||
-- Some more.
|
||||
self.rtb=false
|
||||
self.carrierstop=false
|
||||
|
||||
--[[
|
||||
BASE:TraceOnOff(true)
|
||||
BASE:TraceClass("RESCUEHELO")
|
||||
BASE:TraceLevel(1)
|
||||
]]
|
||||
|
||||
-----------------------
|
||||
--- FSM Transitions ---
|
||||
-----------------------
|
||||
@ -263,6 +295,7 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
||||
self:AddTransition("Stopped", "Start", "Running")
|
||||
self:AddTransition("Running", "Rescue", "Rescuing")
|
||||
self:AddTransition("Running", "RTB", "Returning")
|
||||
self:AddTransition("Rescuing", "RTB", "Returning")
|
||||
self:AddTransition("*", "Run", "Running")
|
||||
self:AddTransition("*", "Status", "*")
|
||||
self:AddTransition("*", "Stop", "Stopped")
|
||||
@ -301,11 +334,13 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
||||
--- Triggers the FSM event "RTB" that sends the helo home.
|
||||
-- @function [parent=#RESCUEHELO] RTB
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to return to. Default is the home base.
|
||||
|
||||
--- Triggers the FSM event "RTB" that sends the helo home after a delay.
|
||||
-- @function [parent=#RESCUEHELO] __RTB
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to return to. Default is the home base.
|
||||
|
||||
--- On after "RTB" event user function. Called when a the the helo returns to its home base.
|
||||
-- @function [parent=#RESCUEHELO] OnAfterRTB
|
||||
@ -313,6 +348,7 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase to return to. Default is the home base.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Run".
|
||||
@ -369,21 +405,22 @@ function RESCUEHELO:SetHomeBase(airbase)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set rescue zone radius. Crashed or ejected units inside this radius of the carrier will be rescued.
|
||||
--- Set rescue zone radius. Crashed or ejected units inside this radius of the carrier will be rescued if possible.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #number radius Radius of rescue zone in meters. Default is 100000 m = 100 km.
|
||||
-- @param #number radius Radius of rescue zone in kilometers. Default is 30 km.
|
||||
-- @return #RESCUEHELO self
|
||||
function RESCUEHELO:SetRescueZone(radius)
|
||||
self.rescuezone=ZONE_UNIT:New("Rescue Zone", self.carrier, radius or 100000)
|
||||
radius=(radius or 30)*1000
|
||||
self.rescuezone=ZONE_UNIT:New("Rescue Zone", self.carrier, radius)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set rescue hover speed.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #number speed Speed in km/h. Default 25 km/h.
|
||||
-- @param #number speed Speed in km/h. Default 10 km/h.
|
||||
-- @return #RESCUEHELO self
|
||||
function RESCUEHELO:SetRescueHoverSpeed(speed)
|
||||
self.rescuespeed=UTILS.KmphToMps(speed or 25)
|
||||
self.rescuespeed=UTILS.KmphToMps(speed or 10)
|
||||
return self
|
||||
end
|
||||
|
||||
@ -471,21 +508,21 @@ function RESCUEHELO:SetAltitude(alt)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set latitudinal offset to carrier.
|
||||
--- Set offset parallel to orienation of carrier.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #number distance Latitual offset distance in meters. Default 200 m.
|
||||
-- @param #number distance Offset distance in meters. Default 200 m.
|
||||
-- @return #RESCUEHELO self
|
||||
function RESCUEHELO:SetOffsetX(distance)
|
||||
self.offsetX=distance or 200
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set longitudal offset to carrier.
|
||||
--- Set offset perpendicular to orientation to carrier.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #number distance Longitual offset distance in meters. Default 200 m.
|
||||
-- @param #number distance Offset distance in meters. Default 100 m.
|
||||
-- @return #RESCUEHELO self
|
||||
function RESCUEHELO:SetOffsetZ(distance)
|
||||
self.offsetZ=distance or 200
|
||||
self.offsetZ=distance or 100
|
||||
return self
|
||||
end
|
||||
|
||||
@ -576,6 +613,13 @@ function RESCUEHELO:IsRescuing()
|
||||
return self:is("Rescuing")
|
||||
end
|
||||
|
||||
--- Check if FMS was stopped.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @return #boolean If true, is stopped.
|
||||
function RESCUEHELO:IsStopped()
|
||||
return self:is("Stopped")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- EVENT functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -587,18 +631,39 @@ function RESCUEHELO:OnEventLand(EventData)
|
||||
local group=EventData.IniGroup --Wrapper.Group#GROUP
|
||||
|
||||
if group:IsAlive() then
|
||||
|
||||
-- Group name that landed.
|
||||
local groupname=group:GetName()
|
||||
|
||||
if groupname:match(self.helogroupname) then
|
||||
-- Check that it was our helo that landed.
|
||||
if groupname==self.helo:GetName() then
|
||||
|
||||
-- Respawn the Helo.
|
||||
local text=string.format("Respawning rescue helo group %s at home base.", groupname)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:T(self.lid..text)
|
||||
|
||||
if self:IsRescuing() then
|
||||
|
||||
self:T(string.format("Rescue helo %s returned from rescue operation.", groupname))
|
||||
|
||||
end
|
||||
|
||||
if self.takeoff==SPAWN.Takeoff.Air or self.respawninair then
|
||||
|
||||
self:E("ERROR: Rescue helo %s landed. This should not happen for Takeoff=Air or respawninair=true!", groupname)
|
||||
if self:IsRescuing() then
|
||||
|
||||
self:T(string.format("Rescue helo %s returned from rescue operation.", groupname))
|
||||
|
||||
else
|
||||
|
||||
self:T2(string.format("WARNING: Rescue helo %s landed. This should not happen for Takeoff=Air or respawninair=true unless a rescue operation finished.", groupname))
|
||||
|
||||
end
|
||||
|
||||
-- Respawn helo at current airbase anyway.
|
||||
self.helo=group:RespawnAtCurrentAirbase()
|
||||
|
||||
|
||||
else
|
||||
|
||||
@ -609,6 +674,7 @@ function RESCUEHELO:OnEventLand(EventData)
|
||||
|
||||
-- Restart the formation.
|
||||
self:__Run(10)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -686,10 +752,13 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
self:HandleEvent(EVENTS.Ejection, self._OnEventCrashOrEject)
|
||||
|
||||
-- Delay before formation is started.
|
||||
local delay=120
|
||||
local delay=120
|
||||
|
||||
-- Spawn helo.
|
||||
local Spawn=SPAWN:New(self.helogroupname):InitUnControlled(false)
|
||||
-- Set unique alias for spawn.
|
||||
self.helogroupalias=string.format("%s_%s", self.helogroupname, self.carrier:GetName())
|
||||
|
||||
-- Spawn helo. We need to introduce an alias in case this class is used twice. This would confuse the spawn routine.
|
||||
local Spawn=SPAWN:NewWithAlias(self.helogroupname, self.helogroupalias)
|
||||
|
||||
-- Spawn in air or at airbase.
|
||||
if self.takeoff==SPAWN.Takeoff.Air then
|
||||
@ -697,11 +766,11 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
-- Carrier heading
|
||||
local hdg=self.carrier:GetHeading()
|
||||
|
||||
-- Spawn distance behind carrier.
|
||||
-- Spawn distance in front of carrier.
|
||||
local dist=UTILS.NMToMeters(0.2)
|
||||
|
||||
-- Coordinate behind the carrier
|
||||
local Carrier=self.carrier:GetCoordinate():SetAltitude(math.min(100, self.altitude)):Translate(dist, hdg)
|
||||
-- Coordinate behind the carrier. Altitude at least 100 meters for spawning because it drops down a bit.
|
||||
local Carrier=self.carrier:GetCoordinate():SetAltitude(math.max(140, self.altitude)):Translate(dist, hdg)
|
||||
|
||||
-- Orientation of spawned group.
|
||||
Spawn:InitHeading(hdg)
|
||||
@ -720,6 +789,9 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
-- Use an uncontrolled aircraft group.
|
||||
self.helo=GROUP:FindByName(self.helogroupname)
|
||||
|
||||
-- Also set the alias just in case.
|
||||
self.helogroupalias=self.helogroupname
|
||||
|
||||
if self.helo:IsAlive() then
|
||||
|
||||
-- Start uncontrolled group.
|
||||
@ -770,7 +842,6 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
|
||||
-- Init status check
|
||||
self:__Status(1)
|
||||
|
||||
end
|
||||
|
||||
--- On after Status event. Checks player status.
|
||||
@ -791,13 +862,50 @@ function RESCUEHELO:onafterStatus(From, Event, To)
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- If fuel < threshold ==> send helo to home base!
|
||||
if fuel<self.lowfuel and self:IsRunning() then
|
||||
self:RTB()
|
||||
-- Check if helo is running and not RTBing already or rescuing.
|
||||
if self:IsRunning() then
|
||||
|
||||
-- Check if fuel is low.
|
||||
if fuel<self.lowfuel then
|
||||
|
||||
-- Check if spawn in air is activated.
|
||||
if self.takeoff==SPAWN.Takeoff.Air or self.respawninair then
|
||||
|
||||
-- Check if respawn is enabled.
|
||||
if self.respawn then
|
||||
|
||||
-- Respawn helo in air.
|
||||
self.helo:Respawn(nil, true)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Send helo back to base.
|
||||
self:RTB()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
elseif self:IsRescuing() then
|
||||
|
||||
if self.rtb then
|
||||
|
||||
-- Send helo back to base.
|
||||
self:RTB()
|
||||
|
||||
-- Switch to false.
|
||||
self.rtb=false
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Call status again in one minute.
|
||||
self:__Status(-60)
|
||||
-- Call status again in 30 seconds.
|
||||
if not self:IsStopped() then
|
||||
self:__Status(-30)
|
||||
end
|
||||
end
|
||||
|
||||
--- On after "Run" event. FSM will go to "Running" state. If formation is topped, it will be started again.
|
||||
@ -832,6 +940,20 @@ function RESCUEHELO:onafterRun(From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Function called when a group is passing a waypoint.
|
||||
--@param Wrapper.Group#GROUP group Group that passed the waypoint
|
||||
--@param #RESCUEHELO rescuehelo Rescue helo object.
|
||||
function RESCUEHELO._TaskRTB(group, rescuehelo)
|
||||
env.info(string.format("FF Executing TaskRTB for group %s.", group:GetName()))
|
||||
|
||||
-- Set RTB switch so on next status update, the helo is respawned with RTB waypoints.
|
||||
rescuehelo.rtb=true
|
||||
|
||||
-- This made DCS crash to desktop!
|
||||
--rescuehelo:RTB()
|
||||
end
|
||||
|
||||
--- On after "Rescue" event. Helo will fly to the given coordinate, orbit there for 5 minutes and then return to the carrier.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #string From From state.
|
||||
@ -850,17 +972,32 @@ function RESCUEHELO:onafterRescue(From, Event, To, RescueCoord)
|
||||
|
||||
--local RescueTask=self.helo:TaskControlled(self.helo:TaskOrbitCircle(20, 2, RescueCoord), self.helo:TaskCondition(nil, nil, nil, nil, 5*60, nil))
|
||||
|
||||
-- Rescue task: Orbit at crash site for 5 minutes.
|
||||
-- Rescue task: Orbit at crash site for ~5 minutes at 20 meters altitude and ~10 km/h.
|
||||
local RescueTask={}
|
||||
RescueTask.id="ControlledTask"
|
||||
RescueTask.params={}
|
||||
RescueTask.params.task=self.helo:TaskOrbit(RescueCoord, 20, self.rescuespeed)
|
||||
RescueTask.params.stopCondition={duration=self.rescueduration}
|
||||
|
||||
-- Set Waypoints.
|
||||
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, 200, {}, "Current Position")
|
||||
wp[2]=RescueCoord:SetAltitude(50):WaypointAirTurningPoint(nil, 200, {RescueTask}, "Crash Site")
|
||||
wp[3]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(200, self.airbase, {}, "Land at Home Base")
|
||||
-- Passing waypoint taskfunction
|
||||
local TaskRTB=self.helo:TaskFunction("RESCUEHELO._TaskRTB", self)
|
||||
|
||||
-- Rescue speed 90% of max possible.
|
||||
local speed=self.helo:GetSpeedMax()*0.9
|
||||
|
||||
-- Set Waypoints:
|
||||
|
||||
-- Current position.
|
||||
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, speed, {}, "Current Position")
|
||||
|
||||
-- Go to crash site and hover a bit.
|
||||
wp[2]=RescueCoord:SetAltitude(50):WaypointAirTurningPoint(nil, speed, {RescueTask, TaskRTB}, "Crash Site")
|
||||
|
||||
-- Route helo back home and respawn next status update.
|
||||
wp[3]=self.airbase:GetCoordinate():SetAltitude(50):WaypointAirTurningPoint(nil, speed, {}, "RTB")
|
||||
|
||||
-- Unfortunately not possible reliably due to DCS bug that units dont land or just land on any nearby base.
|
||||
--wp[3]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(200, self.airbase, {}, "Land at Home Base")
|
||||
|
||||
-- Initialize WP and route helo.
|
||||
self.helo:WayPointInitialize(wp)
|
||||
@ -882,61 +1019,44 @@ function RESCUEHELO:onafterRescue(From, Event, To, RescueCoord)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- On before RTB event. Check if takeoff type is air and if so respawn the helo and deny RTB transition.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @return #boolean If true, transition is allowed.
|
||||
function RESCUEHELO:onbeforeRTB(From, Event, To)
|
||||
|
||||
-- For takeoff in air, we just respawn the helo with full fuel.
|
||||
if (self.takeoff==SPAWN.Takeoff.Air or self.respawninair) and self.respawn then
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Respawning rescue helo group %s in air.", self.helo:GetName())
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Respawn helo.
|
||||
self.helo:InitHeading(self.helo:GetHeading())
|
||||
self.helo=self.helo:Respawn(nil, true)
|
||||
|
||||
-- Deny transition to RTB.
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- On after RTB event. Send helo back to carrier.
|
||||
-- @param #RESCUEHELO self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function RESCUEHELO:onafterRTB(From, Event, To)
|
||||
-- @param Wrapper.Airbase#AIRBASE airbase The base to return to. Default is the home base.
|
||||
function RESCUEHELO:onafterRTB(From, Event, To, airbase)
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("Rescue helo %s is returning to airbase %s.", self.helo:GetName(), self.airbase:GetName())
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Waypoint array.
|
||||
local wp={}
|
||||
|
||||
-- Set landing waypoint at home base.
|
||||
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
||||
wp[2]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(300, self.airbase, {}, "Landing at Home Base")
|
||||
-- Set airbase.
|
||||
airbase=airbase or self.airbase
|
||||
|
||||
-- Initialize WP and route helo.
|
||||
self.helo:WayPointInitialize(wp)
|
||||
-- Debug message.
|
||||
local text=string.format("Rescue helo %s is returning to airbase %s.", self.helo:GetName(), airbase:GetName())
|
||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Set task.
|
||||
self.helo:Route(wp, 1)
|
||||
|
||||
-- Stop formation.
|
||||
--[[
|
||||
-- Waypoint array.
|
||||
local wp={}
|
||||
|
||||
-- Set landing waypoint at home base.
|
||||
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
||||
wp[2]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(300, self.airbase, {}, "Landing at Home Base")
|
||||
|
||||
-- Initialize WP and route helo.
|
||||
self.helo:WayPointInitialize(wp)
|
||||
|
||||
-- Set task.
|
||||
self.helo:Route(wp, 1)
|
||||
]]
|
||||
|
||||
-- Stop formation.
|
||||
if From=="Running" then
|
||||
self.formation:Stop()
|
||||
end
|
||||
|
||||
-- Route helo back home. It is respawned! But this is the only way to ensure that it actually lands at the airbase.
|
||||
self.helo:RouteRTB(airbase)
|
||||
end
|
||||
|
||||
--- On after Stop event. Unhandle events and stop status updates.
|
||||
@ -950,7 +1070,6 @@ function RESCUEHELO:onafterStop(From, Event, To)
|
||||
self:UnHandleEvent(EVENTS.Ejection)
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -1477,11 +1477,12 @@ end
|
||||
--
|
||||
-- @param Wrapper.Group#GROUP self
|
||||
-- @param #table Template (optional) The template of the Group retrieved with GROUP:GetTemplate(). If the template is not provided, the template will be retrieved of the group itself.
|
||||
-- @param #boolean Reset Reset positons if TRUE.
|
||||
-- @return Wrapper.Group#GROUP self
|
||||
function GROUP:Respawn( Template, Reset )
|
||||
|
||||
if not Template then
|
||||
Template = self:GetTemplate()
|
||||
end
|
||||
-- Given template or get old.
|
||||
Template = Template or self:GetTemplate()
|
||||
|
||||
-- Get correct heading.
|
||||
local function _Heading(course)
|
||||
@ -1494,23 +1495,43 @@ function GROUP:Respawn( Template, Reset )
|
||||
return h
|
||||
end
|
||||
|
||||
-- First check if group is alive.
|
||||
if self:IsAlive() then
|
||||
|
||||
-- Respawn zone.
|
||||
local Zone = self.InitRespawnZone -- Core.Zone#ZONE
|
||||
|
||||
-- Zone position or current group position.
|
||||
local Vec3 = Zone and Zone:GetVec3() or self:GetVec3()
|
||||
|
||||
-- From point of the template.
|
||||
local From = { x = Template.x, y = Template.y }
|
||||
|
||||
-- X, Y
|
||||
Template.x = Vec3.x
|
||||
Template.y = Vec3.z
|
||||
|
||||
--Template.x = nil
|
||||
--Template.y = nil
|
||||
|
||||
-- Debug number of units.
|
||||
self:F( #Template.units )
|
||||
|
||||
-- Reset position etc?
|
||||
if Reset == true then
|
||||
|
||||
-- Loop over units in group.
|
||||
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
||||
local GroupUnit = UnitData -- Wrapper.Unit#UNIT
|
||||
self:F( GroupUnit:GetName() )
|
||||
self:F(GroupUnit:GetName())
|
||||
|
||||
if GroupUnit:IsAlive() then
|
||||
self:F( "Alive" )
|
||||
local GroupUnitVec3 = GroupUnit:GetVec3()
|
||||
self:F("Alive")
|
||||
|
||||
-- Get unit position vector.
|
||||
local GroupUnitVec3 = GroupUnit:GetVec3()
|
||||
|
||||
-- Check if respawn zone is set.
|
||||
if Zone then
|
||||
if self.InitRespawnRandomizePositionZone then
|
||||
GroupUnitVec3 = Zone:GetRandomVec3()
|
||||
@ -1523,18 +1544,38 @@ function GROUP:Respawn( Template, Reset )
|
||||
end
|
||||
end
|
||||
|
||||
-- Altitude
|
||||
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
|
||||
-- Unit position. Why not simply take the current positon?
|
||||
if Zone then
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
else
|
||||
Template.units[UnitID].x=GroupUnitVec3.x
|
||||
Template.units[UnitID].y=GroupUnitVec3.z
|
||||
end
|
||||
|
||||
-- Set heading.
|
||||
Template.units[UnitID].heading = _Heading(self.InitRespawnHeading and self.InitRespawnHeading or GroupUnit:GetHeading())
|
||||
Template.units[UnitID].psi = -Template.units[UnitID].heading
|
||||
|
||||
-- Debug.
|
||||
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
else -- Reset=false or nil
|
||||
|
||||
-- Loop over template units.
|
||||
for UnitID, TemplateUnitData in pairs( Template.units ) do
|
||||
|
||||
self:F( "Reset" )
|
||||
|
||||
-- Position from template.
|
||||
local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.y }
|
||||
|
||||
-- Respawn zone position.
|
||||
if Zone then
|
||||
if self.InitRespawnRandomizePositionZone then
|
||||
GroupUnitVec3 = Zone:GetRandomVec3()
|
||||
@ -1547,23 +1588,36 @@ function GROUP:Respawn( Template, Reset )
|
||||
end
|
||||
end
|
||||
|
||||
-- Set altitude.
|
||||
Template.units[UnitID].alt = self.InitRespawnHeight and self.InitRespawnHeight or GroupUnitVec3.y
|
||||
|
||||
-- Unit position.
|
||||
Template.units[UnitID].x = ( Template.units[UnitID].x - From.x ) + GroupUnitVec3.x -- Keep the original x position of the template and translate to the new position.
|
||||
Template.units[UnitID].y = ( Template.units[UnitID].y - From.y ) + GroupUnitVec3.z -- Keep the original z position of the template and translate to the new position.
|
||||
|
||||
-- Heading
|
||||
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading
|
||||
|
||||
-- Debug.
|
||||
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self:Destroy()
|
||||
_DATABASE:Spawn( Template )
|
||||
-- Destroy old group. Dont trigger any dead/crash events since this is a respawn.
|
||||
self:Destroy(false)
|
||||
|
||||
self:E({Template=Template})
|
||||
|
||||
-- Spawn new group.
|
||||
_DATABASE:Spawn(Template)
|
||||
|
||||
-- Reset events.
|
||||
self:ResetEvents()
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1664,6 +1718,7 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
|
||||
-- Destroy old group.
|
||||
self:Destroy(false)
|
||||
|
||||
-- Spawn new group.
|
||||
_DATABASE:Spawn( SpawnTemplate )
|
||||
|
||||
-- Reset events.
|
||||
@ -1812,8 +1867,8 @@ do -- Route methods
|
||||
--
|
||||
-- @param #GROUP self
|
||||
-- @param Wrapper.Airbase#AIRBASE RTBAirbase (optional) The @{Wrapper.Airbase} to return to. If blank, the controllable will return to the nearest friendly airbase.
|
||||
-- @param #number Speed (optional) The Speed, if no Speed is given, the maximum Speed of the first unit is selected.
|
||||
-- @return #GROUP
|
||||
-- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected.
|
||||
-- @return #GROUP self
|
||||
function GROUP:RouteRTB( RTBAirbase, Speed )
|
||||
self:F( { RTBAirbase:GetName(), Speed } )
|
||||
|
||||
@ -1823,17 +1878,19 @@ do -- Route methods
|
||||
|
||||
if RTBAirbase then
|
||||
|
||||
-- If speed is not given take 80% of max speed.
|
||||
local Speed=Speed or self:GetSpeedMax()*0.8
|
||||
|
||||
--[[
|
||||
local GroupPoint = self:GetVec2()
|
||||
local GroupVelocity = self:GetUnit(1):GetDesc().speedMax
|
||||
|
||||
local GroupVelocity = self:GetUnit(1):GetDesc().speedMax
|
||||
local PointFrom = {}
|
||||
PointFrom.x = GroupPoint.x
|
||||
PointFrom.y = GroupPoint.y
|
||||
PointFrom.type = "Turning Point"
|
||||
PointFrom.action = "Turning Point"
|
||||
PointFrom.speed = GroupVelocity
|
||||
|
||||
|
||||
|
||||
local PointTo = {}
|
||||
local AirbasePointVec2 = RTBAirbase:GetPointVec2()
|
||||
local AirbaseAirPoint = AirbasePointVec2:WaypointAir(
|
||||
@ -1844,21 +1901,43 @@ do -- Route methods
|
||||
)
|
||||
|
||||
AirbaseAirPoint["airdromeId"] = RTBAirbase:GetID()
|
||||
AirbaseAirPoint["speed_locked"] = true,
|
||||
AirbaseAirPoint["speed_locked"] = true
|
||||
]]
|
||||
|
||||
-- Curent (from) waypoint.
|
||||
local coord=self:GetCoordinate()
|
||||
local PointFrom=coord:WaypointAirTurningPoint(nil, Speed)
|
||||
|
||||
-- Airbase coordinate.
|
||||
--local PointAirbase=RTBAirbase:GetCoordinate():SetAltitude(coord.y):WaypointAirTurningPoint(nil ,Speed)
|
||||
|
||||
-- Landing waypoint. More general than prev version since it should also work with FAPRS and ships.
|
||||
local PointLanding=RTBAirbase:GetCoordinate():WaypointAirLanding(Speed, RTBAirbase)
|
||||
|
||||
|
||||
-- Waypoint table.
|
||||
local Points={PointFrom, PointLanding}
|
||||
--local Points={PointFrom, PointAirbase, PointLanding}
|
||||
|
||||
self:F(AirbaseAirPoint )
|
||||
|
||||
local Points = { PointFrom, AirbaseAirPoint }
|
||||
|
||||
self:T3( Points )
|
||||
-- Debug info.
|
||||
self:T3(Points)
|
||||
|
||||
local Template = self:GetTemplate()
|
||||
Template.route.points = Points
|
||||
self:Respawn( Template )
|
||||
|
||||
--self:Route( Points )
|
||||
-- Get group template.
|
||||
local Template=self:GetTemplate()
|
||||
|
||||
-- Set route points.
|
||||
Template.route.points=Points
|
||||
|
||||
-- Respawn the group.
|
||||
self:Respawn(Template, true)
|
||||
|
||||
-- Route the group or this will not work.
|
||||
self:Route(Points)
|
||||
else
|
||||
|
||||
-- Clear all tasks.
|
||||
self:ClearTasks()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user