mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
CT v0.1.7
This commit is contained in:
parent
087ac992a2
commit
1febe765bf
@ -460,12 +460,12 @@ do -- COORDINATE
|
|||||||
--- Add a Distance in meters from the COORDINATE orthonormal plane, with the given angle, and calculate the new COORDINATE.
|
--- Add a Distance in meters from the COORDINATE orthonormal plane, with the given angle, and calculate the new COORDINATE.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param DCS#Distance Distance The Distance to be added in meters.
|
-- @param DCS#Distance Distance The Distance to be added in meters.
|
||||||
-- @param DCS#Angle Angle The Angle in degrees.
|
-- @param DCS#Angle Angle The Angle in degrees. Defaults to 0 if not specified (nil).
|
||||||
-- @return #COORDINATE The new calculated COORDINATE.
|
-- @return #COORDINATE The new calculated COORDINATE.
|
||||||
function COORDINATE:Translate( Distance, Angle )
|
function COORDINATE:Translate( Distance, Angle )
|
||||||
local SX = self.x
|
local SX = self.x
|
||||||
local SY = self.z
|
local SY = self.z
|
||||||
local Radians = Angle / 180 * math.pi
|
local Radians = (Angle or 0) / 180 * math.pi
|
||||||
local TX = Distance * math.cos( Radians ) + SX
|
local TX = Distance * math.cos( Radians ) + SX
|
||||||
local TY = Distance * math.sin( Radians ) + SY
|
local TY = Distance * math.sin( Radians ) + SY
|
||||||
|
|
||||||
|
|||||||
@ -195,6 +195,49 @@ function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Creates a new @{Static} from a COORDINATE.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The 3D coordinate where to spawn the static.
|
||||||
|
-- @param #number Heading (Optional) Heading The heading of the static, which is a number in degrees from 0 to 360. Default is 0 degrees.
|
||||||
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
|
-- @return #SPAWNSTATIC
|
||||||
|
function SPAWNSTATIC:SpawnFromCoordinate(Coordinate, Heading, NewName) --R2.4
|
||||||
|
self:F( { PointVec2, Heading, NewName } )
|
||||||
|
|
||||||
|
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
||||||
|
|
||||||
|
if StaticTemplate then
|
||||||
|
|
||||||
|
Heading=Heading or 0
|
||||||
|
|
||||||
|
local StaticUnitTemplate = StaticTemplate.units[1]
|
||||||
|
|
||||||
|
StaticUnitTemplate.x = Coordinate.x
|
||||||
|
StaticUnitTemplate.y = Coordinate.z
|
||||||
|
StaticUnitTemplate.alt = Coordinate.y
|
||||||
|
|
||||||
|
StaticTemplate.route = nil
|
||||||
|
StaticTemplate.groupId = nil
|
||||||
|
|
||||||
|
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
||||||
|
StaticUnitTemplate.name = StaticTemplate.name
|
||||||
|
StaticUnitTemplate.heading = ( Heading / 180 ) * math.pi
|
||||||
|
|
||||||
|
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID)
|
||||||
|
|
||||||
|
self:F({StaticTemplate = StaticTemplate})
|
||||||
|
|
||||||
|
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
||||||
|
|
||||||
|
self.SpawnIndex = self.SpawnIndex + 1
|
||||||
|
|
||||||
|
return _DATABASE:FindStatic(Static:getName())
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Respawns the original @{Static}.
|
--- Respawns the original @{Static}.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @return #SPAWNSTATIC
|
-- @return #SPAWNSTATIC
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **Bankler** (original idea and script), **funkyfranky** (MOOSE class implementation and enhancements)
|
-- ### Authors: **funkyfranky** (MOOSE class implementation and enhancements), **Bankler** (original idea and script)
|
||||||
--
|
--
|
||||||
-- @module Functional.CarrierTrainer
|
-- @module Functional.CarrierTrainer
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
@ -151,7 +151,7 @@ CARRIERTRAINER.LSOcall={
|
|||||||
BOLTER=USERSOUND:New("LSO - Bolter.ogg"),
|
BOLTER=USERSOUND:New("LSO - Bolter.ogg"),
|
||||||
BOLTERT="Bolter, Bolter!",
|
BOLTERT="Bolter, Bolter!",
|
||||||
LONGGROOVE=USERSOUND:New("LSO - Long in Groove.ogg"),
|
LONGGROOVE=USERSOUND:New("LSO - Long in Groove.ogg"),
|
||||||
LONGGROOVET="You're lon in the groove. Depart and re-enter.",
|
LONGGROOVET="You're long in the groove. Depart and re-enter.",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Difficulty level.
|
--- Difficulty level.
|
||||||
@ -160,24 +160,28 @@ CARRIERTRAINER.LSOcall={
|
|||||||
-- @field #string NORMAL Normal difficulty: error margin 5 deviation from ideal for high score and 10 for low score. No score for deviation >10.
|
-- @field #string NORMAL Normal difficulty: error margin 5 deviation from ideal for high score and 10 for low score. No score for deviation >10.
|
||||||
-- @field #string HARD Hard difficulty: error margin 2.5 deviation from ideal value for high score and 5 for low score. No score for deviation >5.
|
-- @field #string HARD Hard difficulty: error margin 2.5 deviation from ideal value for high score and 5 for low score. No score for deviation >5.
|
||||||
CARRIERTRAINER.Difficulty={
|
CARRIERTRAINER.Difficulty={
|
||||||
EASY="Rookey",
|
EASY="Flight Student",
|
||||||
NORMAL="Naval Aviator",
|
NORMAL="Naval Aviator",
|
||||||
HARD="TOPGUN Graduate",
|
HARD="TOPGUN Graduate",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Groove position.
|
--- Groove position.
|
||||||
-- @type CARRIERTRAINER.GroovePos
|
-- @type CARRIERTRAINER.GroovePos
|
||||||
-- @field #string X At the start.
|
-- @field #string X0 Entering the groove.
|
||||||
|
-- @field #string XX At the start, i.e. 3/4 from the run down.
|
||||||
-- @field #string RB Roger ball.
|
-- @field #string RB Roger ball.
|
||||||
-- @field #string IM In the middle.
|
-- @field #string IM In the middle.
|
||||||
-- @field #string IC In close.
|
-- @field #string IC In close.
|
||||||
-- @field #string AR At the ramp.
|
-- @field #string AR At the ramp.
|
||||||
|
-- @field #string IW In the wires.
|
||||||
CARRIERTRAINER.GroovePos={
|
CARRIERTRAINER.GroovePos={
|
||||||
X="X",
|
X0="X0",
|
||||||
|
XX="X",
|
||||||
RB="RB",
|
RB="RB",
|
||||||
IM="IM",
|
IM="IM",
|
||||||
IC="IC",
|
IC="IC",
|
||||||
AR="AR",
|
AR="AR",
|
||||||
|
IW="IW",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Groove data.
|
--- Groove data.
|
||||||
@ -187,18 +191,18 @@ CARRIERTRAINER.GroovePos={
|
|||||||
-- @field #number Alt Altitude in meters.
|
-- @field #number Alt Altitude in meters.
|
||||||
-- @field #number GSE Glide slope error in degrees.
|
-- @field #number GSE Glide slope error in degrees.
|
||||||
-- @field #number LUE Lineup error in degrees.
|
-- @field #number LUE Lineup error in degrees.
|
||||||
|
-- @field #number Roll Roll angle.
|
||||||
|
|
||||||
--- Player data table holding all important parameters for each player.
|
--- Player data table holding all important parameters of each player.
|
||||||
-- @type CARRIERTRAINER.PlayerData
|
-- @type CARRIERTRAINER.PlayerData
|
||||||
-- @field #number id Player ID.
|
-- @field Wrapper.Client#CLIENT client Client object of player.
|
||||||
-- @field Wrapper.Unit#UNIT unit Aircraft unit of the player.
|
-- @field Wrapper.Unit#UNIT unit Aircraft of the player.
|
||||||
-- @field #string callsign Callsign of player.
|
-- @field #string callsign Callsign of player.
|
||||||
|
-- @field #string difficulty Difficulty level.
|
||||||
-- @field #number score Player score of the current pass.
|
-- @field #number score Player score of the current pass.
|
||||||
-- @field #number passes Number of passes.
|
-- @field #number passes Number of passes.
|
||||||
-- @field #table debrief Debrief analysis of the current step of this pass.
|
-- @field #table debrief Debrief analysis of the current step of this pass.
|
||||||
-- @field #table results Results of all passes.
|
-- @field #table results Results of all passes.
|
||||||
-- @field Wrapper.Client#CLIENT client object of player.
|
|
||||||
-- @field #string difficulty Difficulty level.
|
|
||||||
-- @field #boolean inbigzone If true, player is in the big zone.
|
-- @field #boolean inbigzone If true, player is in the big zone.
|
||||||
-- @field #boolean landed If true, player landed or attempted to land.
|
-- @field #boolean landed If true, player landed or attempted to land.
|
||||||
-- @field #boolean bolter If true, LSO told player to bolter.
|
-- @field #boolean bolter If true, LSO told player to bolter.
|
||||||
@ -206,7 +210,7 @@ CARRIERTRAINER.GroovePos={
|
|||||||
-- @field #boolean waveoff If true, player was waved off during final approach.
|
-- @field #boolean waveoff If true, player was waved off during final approach.
|
||||||
-- @field #boolean patternwo If true, playe was waved of during the pattern.
|
-- @field #boolean patternwo If true, playe was waved of during the pattern.
|
||||||
-- @field #number Tlso Last time the LSO gave an advice.
|
-- @field #number Tlso Last time the LSO gave an advice.
|
||||||
-- @field #CARRIERTRAINER.GroovePos Groove data table with elemets of type @{#CARRIERTRAINER.GrooveData}.
|
-- @field #CARRIERTRAINER.GroovePos groove Data table at each position in the groove. Elemets are of type @{#CARRIERTRAINER.GrooveData}.
|
||||||
|
|
||||||
--- Checkpoint parameters triggering the next step in the pattern.
|
--- Checkpoint parameters triggering the next step in the pattern.
|
||||||
-- @type CARRIERTRAINER.Checkpoint
|
-- @type CARRIERTRAINER.Checkpoint
|
||||||
@ -231,7 +235,7 @@ CARRIERTRAINER.MenuF10={}
|
|||||||
|
|
||||||
--- Carrier trainer class version.
|
--- Carrier trainer class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CARRIERTRAINER.version="0.1.6"
|
CARRIERTRAINER.version="0.1.7"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -257,7 +261,7 @@ CARRIERTRAINER.version="0.1.6"
|
|||||||
-- @param #CARRIERTRAINER self
|
-- @param #CARRIERTRAINER self
|
||||||
-- @param carriername Name of the aircraft carrier unit as defined in the mission editor.
|
-- @param carriername Name of the aircraft carrier unit as defined in the mission editor.
|
||||||
-- @param alias (Optional) Alias for the carrier. This will be used for radio messages and the F10 radius menu. Default is the carrier name as defined in the mission editor.
|
-- @param alias (Optional) Alias for the carrier. This will be used for radio messages and the F10 radius menu. Default is the carrier name as defined in the mission editor.
|
||||||
-- @return #CARRIERTRAINER self
|
-- @return #CARRIERTRAINER self or nil if carrier unit does not exist.
|
||||||
function CARRIERTRAINER:New(carriername, alias)
|
function CARRIERTRAINER:New(carriername, alias)
|
||||||
|
|
||||||
-- Inherit everthing from FSM class.
|
-- Inherit everthing from FSM class.
|
||||||
@ -267,13 +271,15 @@ function CARRIERTRAINER:New(carriername, alias)
|
|||||||
self.carrier=UNIT:FindByName(carriername)
|
self.carrier=UNIT:FindByName(carriername)
|
||||||
|
|
||||||
if self.carrier then
|
if self.carrier then
|
||||||
|
-- Carrier zones.
|
||||||
self.registerZone = ZONE_UNIT:New("registerZone", self.carrier, 2500, {dx = -5000, dy = 100, relative_to_unit=true})
|
self.registerZone = ZONE_UNIT:New("registerZone", self.carrier, 2500, {dx = -5000, dy = 100, relative_to_unit=true})
|
||||||
self.startZone = ZONE_UNIT:New("startZone", self.carrier, 1000, {dx = -2000, dy = 100, relative_to_unit=true})
|
self.startZone = ZONE_UNIT:New("startZone", self.carrier, 1000, {dx = -2000, dy = 100, relative_to_unit=true})
|
||||||
self.giantZone = ZONE_UNIT:New("giantZone", self.carrier, 30000, {dx = 0, dy = 0, relative_to_unit=true})
|
self.giantZone = ZONE_UNIT:New("giantZone", self.carrier, 30000, {dx = 0, dy = 0, relative_to_unit=true})
|
||||||
else
|
else
|
||||||
|
-- Carrier unit does not exist error.
|
||||||
local text=string.format("ERROR: Carrier unit %s could not be found! Make sure this UNIT is defined in the mission editor and check the spelling of the unit name carefully.", carriername)
|
local text=string.format("ERROR: Carrier unit %s could not be found! Make sure this UNIT is defined in the mission editor and check the spelling of the unit name carefully.", carriername)
|
||||||
MESSAGE:New(text, 120):ToAll()
|
MESSAGE:New(text, 120):ToAll()
|
||||||
self:E(self.lid..text)
|
self:E(text)
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -411,42 +417,62 @@ function CARRIERTRAINER:_CheckPlayerStatus()
|
|||||||
-- Check if player was previously not inside the zone.
|
-- Check if player was previously not inside the zone.
|
||||||
if playerData.inbigzone==false then
|
if playerData.inbigzone==false then
|
||||||
|
|
||||||
|
-- Welcome player once he enters the carrier zone.
|
||||||
local text=string.format("Welcome back, %s! TCN 74X, ICLS 1, BRC 354 (MAG HDG).\n", playerData.callsign)
|
local text=string.format("Welcome back, %s! TCN 74X, ICLS 1, BRC 354 (MAG HDG).\n", playerData.callsign)
|
||||||
|
|
||||||
|
-- Heading and distance to register for approach.
|
||||||
local heading=playerData.unit:GetCoordinate():HeadingTo(self.registerZone:GetCoordinate())
|
local heading=playerData.unit:GetCoordinate():HeadingTo(self.registerZone:GetCoordinate())
|
||||||
local distance=playerData.unit:GetCoordinate():Get2DDistance(self.registerZone:GetCoordinate())
|
local distance=playerData.unit:GetCoordinate():Get2DDistance(self.registerZone:GetCoordinate())
|
||||||
|
|
||||||
|
-- Send message.
|
||||||
text=text..string.format("Fly heading %d for %.1f NM and turn to BRC.", heading, distance)
|
text=text..string.format("Fly heading %d for %.1f NM and turn to BRC.", heading, distance)
|
||||||
MESSAGE:New(text, 5):ToClient(playerData.client)
|
MESSAGE:New(text, 5):ToClient(playerData.client)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if playerData.step==0 and unit:InAir() then
|
if playerData.step==0 and unit:InAir() then
|
||||||
|
-- New approach.
|
||||||
self:_NewRound(playerData)
|
self:_NewRound(playerData)
|
||||||
|
|
||||||
-- Jump to Groove for testing.
|
-- Jump to Groove for testing.
|
||||||
playerData.step=8
|
if self.groovedebug then
|
||||||
|
playerData.step=8
|
||||||
|
self.groovedebug=false
|
||||||
|
end
|
||||||
elseif playerData.step == 1 then
|
elseif playerData.step == 1 then
|
||||||
|
-- Entering the pattern.
|
||||||
self:_Start(playerData)
|
self:_Start(playerData)
|
||||||
elseif playerData.step == 2 then
|
elseif playerData.step == 2 then
|
||||||
|
-- Upwind leg.
|
||||||
self:_Upwind(playerData)
|
self:_Upwind(playerData)
|
||||||
elseif playerData.step == 3 then
|
elseif playerData.step == 3 then
|
||||||
|
-- Early break.
|
||||||
self:_Break(playerData, "early")
|
self:_Break(playerData, "early")
|
||||||
elseif playerData.step == 4 then
|
elseif playerData.step == 4 then
|
||||||
|
-- Late break.
|
||||||
self:_Break(playerData, "late")
|
self:_Break(playerData, "late")
|
||||||
elseif playerData.step == 5 then
|
elseif playerData.step == 5 then
|
||||||
|
-- Abeam position.
|
||||||
self:_Abeam(playerData)
|
self:_Abeam(playerData)
|
||||||
elseif playerData.step == 6 then
|
elseif playerData.step == 6 then
|
||||||
-- Check long down wind leg.
|
-- Check long down wind leg.
|
||||||
if playerData.longDownwindDone==false then
|
self:_CheckForLongDownwind(playerData)
|
||||||
self:_CheckForLongDownwind(playerData)
|
-- At the ninety.
|
||||||
end
|
|
||||||
self:_Ninety(playerData)
|
self:_Ninety(playerData)
|
||||||
elseif playerData.step==7 then
|
elseif playerData.step==7 then
|
||||||
|
-- In the wake.
|
||||||
self:_Wake(playerData)
|
self:_Wake(playerData)
|
||||||
elseif playerData.step==8 then
|
elseif playerData.step==8 then
|
||||||
|
-- Entering the groove.
|
||||||
self:_Groove(playerData)
|
self:_Groove(playerData)
|
||||||
elseif playerData.step>=90 and playerData.step<=99 then
|
elseif playerData.step>=90 and playerData.step<=99 then
|
||||||
|
-- In the groove.
|
||||||
self:_CallTheBall(playerData)
|
self:_CallTheBall(playerData)
|
||||||
elseif playerData.step==999 then
|
elseif playerData.step==999 then
|
||||||
self:_Debrief(playerData)
|
-- Debriefing.
|
||||||
|
SCHEDULER:New(nil, self._Debrief, {self,playerData}, 10)
|
||||||
|
--SCHEDULER:New(self:_Debrief(playerData)
|
||||||
|
playerData.step=-1
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -509,10 +535,8 @@ function CARRIERTRAINER:OnEventBirth(EventData)
|
|||||||
-- Init player data.
|
-- Init player data.
|
||||||
self.players[_playername]=self:_InitPlayer(_unitName)
|
self.players[_playername]=self:_InitPlayer(_unitName)
|
||||||
|
|
||||||
-- Test
|
-- Start in the groove for debugging.
|
||||||
--CARRIERTRAINER.LSOcall.HIGHL:ToGroup(_group)
|
self.groovedebug=false
|
||||||
--CARRIERTRAINER.LSOcall.CALLTHEBALL:ToGroup(_group, 10)
|
|
||||||
--MESSAGE:New(CARRIERTRAINER.LSOcall.HIGHT, 5):ToAllIf(self.Debug)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -547,19 +571,27 @@ function CARRIERTRAINER:OnEventLand(EventData)
|
|||||||
-- Coordinate at landing event
|
-- Coordinate at landing event
|
||||||
local coord=playerData.unit:GetCoordinate()
|
local coord=playerData.unit:GetCoordinate()
|
||||||
|
|
||||||
|
-- Debug mark of player landing coord.
|
||||||
|
local lp=coord:MarkToAll("Landing coord.")
|
||||||
|
coord:SmokeGreen()
|
||||||
|
|
||||||
|
-- Debug marks of wires.
|
||||||
|
local w1=self.carrier:GetCoordinate():Translate(-104, 0):MarkToAll("Wire 1")
|
||||||
|
local w2=self.carrier:GetCoordinate():Translate( -92, 0):MarkToAll("Wire 2")
|
||||||
|
local w3=self.carrier:GetCoordinate():Translate( -80, 0):MarkToAll("Wire 3")
|
||||||
|
local w4=self.carrier:GetCoordinate():Translate( -68, 0):MarkToAll("Wire 4")
|
||||||
|
|
||||||
-- We did land.
|
-- We did land.
|
||||||
playerData.landed=true
|
playerData.landed=true
|
||||||
|
|
||||||
--TODO: maybe check that we actually landed on the right carrier.
|
--TODO: maybe check that we actually landed on the right carrier.
|
||||||
|
|
||||||
-- Call trapped function in 5 seconds to make sure we did not bolter.
|
-- Call trapped function in 3 seconds to make sure we did not bolter.
|
||||||
SCHEDULER:New(nil, self._Trapped,{self, playerData, coord}, 5)
|
SCHEDULER:New(nil, self._Trapped,{self, playerData, coord}, 3)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- CARRIER TRAINING functions
|
-- CARRIER TRAINING functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -570,6 +602,7 @@ end
|
|||||||
-- @return #CARRIERTRAINER.PlayerData Player data.
|
-- @return #CARRIERTRAINER.PlayerData Player data.
|
||||||
function CARRIERTRAINER:_InitPlayer(unitname)
|
function CARRIERTRAINER:_InitPlayer(unitname)
|
||||||
|
|
||||||
|
-- Player data.
|
||||||
local playerData={} --#CARRIERTRAINER.PlayerData
|
local playerData={} --#CARRIERTRAINER.PlayerData
|
||||||
|
|
||||||
-- Player unit, client and callsign.
|
-- Player unit, client and callsign.
|
||||||
@ -602,15 +635,16 @@ end
|
|||||||
-- @param #CARRIERTRAINER.PlayerData playerData Player data.
|
-- @param #CARRIERTRAINER.PlayerData playerData Player data.
|
||||||
-- @return #CARRIERTRAINER.PlayerData Initialized player data.
|
-- @return #CARRIERTRAINER.PlayerData Initialized player data.
|
||||||
function CARRIERTRAINER:_InitNewRound(playerData)
|
function CARRIERTRAINER:_InitNewRound(playerData)
|
||||||
|
self:I(self.lid..string.format("New round for player %s.", playerData.callsign))
|
||||||
playerData.step=0
|
playerData.step=0
|
||||||
playerData.score=100
|
playerData.score=100
|
||||||
playerData.grade={}
|
playerData.groove={}
|
||||||
playerData.debrief={}
|
playerData.debrief={}
|
||||||
playerData.longDownwindDone=false
|
playerData.patternwo=false
|
||||||
|
playerData.waveoff=false
|
||||||
|
playerData.bolter=false
|
||||||
playerData.boltered=false
|
playerData.boltered=false
|
||||||
playerData.landed=false
|
playerData.landed=false
|
||||||
playerData.waveoff=false
|
|
||||||
playerData.patternwo=false
|
|
||||||
playerData.Tlso=timer.getTime()
|
playerData.Tlso=timer.getTime()
|
||||||
return playerData
|
return playerData
|
||||||
end
|
end
|
||||||
@ -642,7 +676,7 @@ function CARRIERTRAINER:_Start(playerData)
|
|||||||
-- Inform player.
|
-- Inform player.
|
||||||
local hint = string.format("Entering the pattern.")
|
local hint = string.format("Entering the pattern.")
|
||||||
if playerData.difficulty==CARRIERTRAINER.Difficulty.EASY then
|
if playerData.difficulty==CARRIERTRAINER.Difficulty.EASY then
|
||||||
hint=hint.."Aim for 800 feet and 350 kts in the break entry."
|
hint=hint.."Aim for 800 feet and 350 kts at the break entry."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Send message.
|
-- Send message.
|
||||||
@ -750,7 +784,7 @@ function CARRIERTRAINER:_CheckForLongDownwind(playerData)
|
|||||||
local relhead=self:_GetRelativeHeading(playerData.unit)
|
local relhead=self:_GetRelativeHeading(playerData.unit)
|
||||||
|
|
||||||
-- One NM from carrier is too far.
|
-- One NM from carrier is too far.
|
||||||
local limit=-UTILS.NMToMeters(1)
|
local limit=-UTILS.NMToMeters(1.5)
|
||||||
|
|
||||||
local text=string.format("Long groove check: X=%d, relhead=%.1f", X, relhead)
|
local text=string.format("Long groove check: X=%d, relhead=%.1f", X, relhead)
|
||||||
self:T(text)
|
self:T(text)
|
||||||
@ -773,9 +807,6 @@ function CARRIERTRAINER:_CheckForLongDownwind(playerData)
|
|||||||
|
|
||||||
local grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
local grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
||||||
|
|
||||||
-- Long downwind done!
|
|
||||||
playerData.longDownwindDone = true
|
|
||||||
|
|
||||||
-- Next step: Debriefing.
|
-- Next step: Debriefing.
|
||||||
playerData.step=999
|
playerData.step=999
|
||||||
end
|
end
|
||||||
@ -835,7 +866,7 @@ function CARRIERTRAINER:_Ninety(playerData)
|
|||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
||||||
local X, Z = self:_GetDistances(playerData.unit)
|
local X, Z = self:_GetDistances(playerData.unit)
|
||||||
|
|
||||||
--if(Z < -3700 or X < -3700 or X > 0) then
|
-- Check abort conditions.
|
||||||
if self:_CheckAbort(X, Z, self.Ninety) then
|
if self:_CheckAbort(X, Z, self.Ninety) then
|
||||||
self:_AbortPattern(playerData, X, Z, self.Ninety)
|
self:_AbortPattern(playerData, X, Z, self.Ninety)
|
||||||
return
|
return
|
||||||
@ -866,9 +897,6 @@ function CARRIERTRAINER:_Ninety(playerData)
|
|||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
self:_AddToSummary(playerData, "At the 90", hintFull)
|
self:_AddToSummary(playerData, "At the 90", hintFull)
|
||||||
|
|
||||||
-- Long downwind not an issue any more
|
|
||||||
playerData.longDownwindDone=true
|
|
||||||
|
|
||||||
-- Next step: wake.
|
-- Next step: wake.
|
||||||
playerData.step = 7
|
playerData.step = 7
|
||||||
|
|
||||||
@ -933,19 +961,21 @@ function CARRIERTRAINER:_Groove(playerData)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Call the ball distance.
|
||||||
|
local calltheball=UTILS.NMToMeters(0.75)+math.abs(self.sterndist)
|
||||||
|
|
||||||
local calltheball=UTILS.NMToMeters(0.75)
|
local relhead=self:_GetRelativeHeading(playerData.unit)+self.rwyangle
|
||||||
|
local lineup=self:_Lineup(playerData)-self.rwyangle
|
||||||
|
local roll=playerData.unit:GetRoll()
|
||||||
|
|
||||||
if rho<=calltheball then
|
env.info(string.format("FF relhead=%d lineup=%d roll=%d", relhead, lineup, roll))
|
||||||
|
|
||||||
|
if math.abs(lineup)<5 and math.abs(relhead)<10 then
|
||||||
|
|
||||||
-- Get player altitude and AoA.
|
-- Get player altitude and AoA.
|
||||||
local alt = playerData.unit:GetAltitude()
|
local alt = playerData.unit:GetAltitude()
|
||||||
local aoa = playerData.unit:GetAoA()
|
local aoa = playerData.unit:GetAoA()
|
||||||
|
|
||||||
|
|
||||||
self:_SendMessageToPlayer("Call the ball.", 8, playerData)
|
|
||||||
CARRIERTRAINER.LSOcall.CALLTHEBALL:ToGroup(playerData.unit:GetGroup())
|
|
||||||
|
|
||||||
-- Grade altitude.
|
-- Grade altitude.
|
||||||
local hintAlt=self:_AltitudeCheck(playerData, self.Groove, alt)
|
local hintAlt=self:_AltitudeCheck(playerData, self.Groove, alt)
|
||||||
|
|
||||||
@ -959,22 +989,20 @@ function CARRIERTRAINER:_Groove(playerData)
|
|||||||
self:_SendMessageToPlayer(hintFull, 10, playerData)
|
self:_SendMessageToPlayer(hintFull, 10, playerData)
|
||||||
|
|
||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
self:_AddToSummary(playerData, "Calling the ball", hintFull)
|
self:_AddToSummary(playerData, "Enter Groove", hintFull)
|
||||||
|
|
||||||
|
-- Gather pilot data.
|
||||||
local groovedata={} --#CARRIERTRAINER.GrooveData
|
local groovedata={} --#CARRIERTRAINER.GrooveData
|
||||||
groovedata.Alt=alt
|
groovedata.Alt=alt
|
||||||
groovedata.AoA=aoa
|
groovedata.AoA=aoa
|
||||||
groovedata.GSE=self:_Glideslope(playerData)-3.5
|
groovedata.GSE=self:_Glideslope(playerData)-3.5
|
||||||
groovedata.LUE=self:_Lineup(playerData)-10
|
groovedata.LUE=self:_Lineup(playerData)-self.rwyangle
|
||||||
groovedata.Step=playerData.step
|
groovedata.Step=playerData.step
|
||||||
|
|
||||||
-- Init groove table.
|
-- Groove
|
||||||
playerData.Groove={}
|
playerData.groove.X0=groovedata
|
||||||
|
|
||||||
|
-- Next step: X call the ball.
|
||||||
playerData.Groove.X=groovedata
|
|
||||||
|
|
||||||
-- Next step: roger ball.
|
|
||||||
playerData.step=90
|
playerData.step=90
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1013,51 +1041,63 @@ function CARRIERTRAINER:_CallTheBall(playerData)
|
|||||||
local AoA=playerData.unit:GetAoA()
|
local AoA=playerData.unit:GetAoA()
|
||||||
|
|
||||||
-- Ranges in the groove.
|
-- Ranges in the groove.
|
||||||
local RRB=UTILS.NMToMeters(0.500) -- Roger Ball! call.
|
local RXX=UTILS.NMToMeters(0.750)+math.abs(self.sterndist) -- Start of groove. 0.75 = 1389 m
|
||||||
local RIM=UTILS.NMToMeters(0.375) -- In the Middle 0.75/2.
|
local RRB=UTILS.NMToMeters(0.500)+math.abs(self.sterndist) -- Roger Ball! call. 0.5 = 926 m
|
||||||
local RIC=UTILS.NMToMeters(0.100) -- In Close.
|
local RIM=UTILS.NMToMeters(0.375)+math.abs(self.sterndist) -- In the Middle 0.75/2. 0.375 = 695 m
|
||||||
local RAR=UTILS.NMToMeters(0.050) -- At the Ramp.
|
local RIC=UTILS.NMToMeters(0.100)+math.abs(self.sterndist) -- In Close. 0.1 = 185 m
|
||||||
|
local RAR=UTILS.NMToMeters(0.000)+math.abs(self.sterndist) -- At the Ramp.
|
||||||
|
|
||||||
-- Data
|
-- Data
|
||||||
local groovedata={} --#CARRIERTRAINER.GrooveData
|
local groovedata={} --#CARRIERTRAINER.GrooveData
|
||||||
|
groovedata.Step=playerData.step
|
||||||
groovedata.Alt=alt
|
groovedata.Alt=alt
|
||||||
groovedata.AoA=AoA
|
groovedata.AoA=AoA
|
||||||
groovedata.GSE=glideslopeError
|
groovedata.GSE=glideslopeError
|
||||||
groovedata.LUE=lineupError
|
groovedata.LUE=lineupError
|
||||||
groovedata.Step=playerData.step
|
|
||||||
|
|
||||||
if rho<=RRB and playerData.step==90 then
|
if rho<=RXX and playerData.step==90 then
|
||||||
|
|
||||||
-- Roger ball!
|
-- LSO "Call the ball" call.
|
||||||
self:_SendMessageToPlayer(CARRIERTRAINER.LSOcall.ROGERBALLT, 8, playerData)
|
self:_SendMessageToPlayer("Call the ball.", 8, playerData)
|
||||||
CARRIERTRAINER.LSOcall.ROGERBALL:ToGroup(player)
|
CARRIERTRAINER.LSOcall.CALLTHEBALL:ToGroup(playerData.unit:GetGroup())
|
||||||
|
playerData.Tlso=timer.getTime()
|
||||||
|
|
||||||
-- Store data.
|
-- Next step: roger ball.
|
||||||
playerData.Groove.RB=groovedata
|
|
||||||
|
|
||||||
-- Next step: in the middle.
|
|
||||||
playerData.step=91
|
playerData.step=91
|
||||||
|
|
||||||
elseif rho<=RIM and playerData.step==91 then
|
elseif rho<=RRB and playerData.step==91 then
|
||||||
|
|
||||||
|
-- Pilot: "Roger ball" call.
|
||||||
|
self:_SendMessageToPlayer(CARRIERTRAINER.LSOcall.ROGERBALLT, 8, playerData)
|
||||||
|
CARRIERTRAINER.LSOcall.ROGERBALL:ToGroup(player)
|
||||||
|
playerData.Tlso=timer.getTime()+1
|
||||||
|
|
||||||
|
-- Store data.
|
||||||
|
playerData.groove.RB=groovedata
|
||||||
|
|
||||||
|
-- Next step: in the middle.
|
||||||
|
playerData.step=92
|
||||||
|
|
||||||
|
elseif rho<=RIM and playerData.step==92 then
|
||||||
|
|
||||||
--TODO: grade for IM
|
--TODO: grade for IM
|
||||||
self:_SendMessageToPlayer("IM", 8, playerData)
|
self:_SendMessageToPlayer("IM", 8, playerData)
|
||||||
env.info(string.format("FF IM=%d", rho))
|
env.info(string.format("FF IM=%d", rho))
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
playerData.Groove.IM=groovedata
|
playerData.groove.IM=groovedata
|
||||||
|
|
||||||
-- Next step: in close.
|
-- Next step: in close.
|
||||||
playerData.step=92
|
playerData.step=93
|
||||||
|
|
||||||
elseif rho<=RIC and playerData.step==92 then
|
elseif rho<=RIC and playerData.step==93 then
|
||||||
|
|
||||||
--TODO: grade for IC, call wave off?
|
--TODO: grade for IC, call wave off?
|
||||||
self:_SendMessageToPlayer("IC", 8, playerData)
|
self:_SendMessageToPlayer("IC", 8, playerData)
|
||||||
env.info(string.format("FF IC=%d", rho))
|
env.info(string.format("FF IC=%d", rho))
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
playerData.Groove.IC=groovedata
|
playerData.groove.IC=groovedata
|
||||||
|
|
||||||
-- Check if player should wave off.
|
-- Check if player should wave off.
|
||||||
local waveoff=self:_CheckWaveOff(glideslopeError, lineupError, AoA)
|
local waveoff=self:_CheckWaveOff(glideslopeError, lineupError, AoA)
|
||||||
@ -1068,26 +1108,28 @@ function CARRIERTRAINER:_CallTheBall(playerData)
|
|||||||
-- Wave off player.
|
-- Wave off player.
|
||||||
self:_SendMessageToPlayer(CARRIERTRAINER.LSOcall.WAVEOFFT, 10, playerData)
|
self:_SendMessageToPlayer(CARRIERTRAINER.LSOcall.WAVEOFFT, 10, playerData)
|
||||||
CARRIERTRAINER.LSOcall.WAVEOFF:ToGroup(playerData.unit:GetGroup())
|
CARRIERTRAINER.LSOcall.WAVEOFF:ToGroup(playerData.unit:GetGroup())
|
||||||
|
playerData.Tlso=timer.getTime()
|
||||||
|
|
||||||
-- Next step: debrief.
|
-- Next step: debrief.
|
||||||
playerData.step=999
|
playerData.step=999
|
||||||
|
|
||||||
|
return
|
||||||
else
|
else
|
||||||
-- Next step: at the ramp.
|
-- Next step: at the ramp.
|
||||||
playerData.step=93
|
playerData.step=94
|
||||||
end
|
end
|
||||||
|
|
||||||
|
elseif rho<=RAR and playerData.step==94 then
|
||||||
elseif rho<=RAR and playerData.step==93 then
|
|
||||||
|
|
||||||
--TODO: grade for AR
|
--TODO: grade for AR
|
||||||
self:_SendMessageToPlayer("AR", 8, playerData)
|
self:_SendMessageToPlayer("AR", 8, playerData)
|
||||||
env.info(string.format("FF AR=%d", rho))
|
env.info(string.format("FF AR=%d", rho))
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
playerData.Groove.AR=groovedata
|
playerData.groove.AR=groovedata
|
||||||
|
|
||||||
-- Next step: at the ramp.
|
-- Next step: at the ramp.
|
||||||
playerData.step=94
|
playerData.step=95
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Time since last LSO call.
|
-- Time since last LSO call.
|
||||||
@ -1095,31 +1137,35 @@ function CARRIERTRAINER:_CallTheBall(playerData)
|
|||||||
local deltaT=time-playerData.Tlso
|
local deltaT=time-playerData.Tlso
|
||||||
|
|
||||||
-- Check if we are beween 3/4 NM and end of ship.
|
-- Check if we are beween 3/4 NM and end of ship.
|
||||||
if rho<UTILS.NMToMeters(0.75) and deltaT>=3 then
|
if rho>=RAR and rho<RXX and deltaT>=3 then
|
||||||
|
|
||||||
|
-- LSO call if necessary.
|
||||||
self:_LSOcall(playerData, glideslopeError, lineupError)
|
self:_LSOcall(playerData, glideslopeError, lineupError)
|
||||||
|
|
||||||
elseif X>0 then
|
elseif X>0 then
|
||||||
|
|
||||||
local wire = 0
|
|
||||||
local hint = ""
|
|
||||||
local score = 0
|
|
||||||
|
|
||||||
|
|
||||||
if playerData.landed then
|
if playerData.landed then
|
||||||
hint = "You boltered."
|
|
||||||
|
local hint="You boltered."
|
||||||
|
|
||||||
|
-- Send message to player.
|
||||||
|
self:_SendMessageToPlayer(hint, 8, playerData)
|
||||||
|
|
||||||
|
-- Add to debrief.
|
||||||
|
self:_AddToSummary(playerData, "Bolter", hint)
|
||||||
|
|
||||||
else
|
else
|
||||||
hint = "You were waved off."
|
|
||||||
wire = -1
|
local hint="You were waved off."
|
||||||
score = -10
|
|
||||||
|
-- Send message to player.
|
||||||
|
self:_SendMessageToPlayer(hint, 8, playerData)
|
||||||
|
|
||||||
|
-- Add to debrief.
|
||||||
|
self:_AddToSummary(playerData, "Wave Off", hint)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Send message to player.
|
|
||||||
self:_SendMessageToPlayer(hint, 8, playerData)
|
|
||||||
|
|
||||||
-- Add to debrief.
|
|
||||||
self:_AddToSummary(playerData, "Bolter or wave off", hint)
|
|
||||||
|
|
||||||
-- Next step: debrief.
|
-- Next step: debrief.
|
||||||
playerData.step=999
|
playerData.step=999
|
||||||
end
|
end
|
||||||
@ -1135,14 +1181,17 @@ function CARRIERTRAINER:_CheckWaveOff(glideslopeError, lineupError, AoA)
|
|||||||
|
|
||||||
local waveoff=false
|
local waveoff=false
|
||||||
|
|
||||||
|
-- Too high or too low?
|
||||||
if math.abs(glideslopeError)>3 then
|
if math.abs(glideslopeError)>3 then
|
||||||
waveoff=true
|
waveoff=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Too far from centerline?
|
||||||
if math.abs(lineupError)>3 then
|
if math.abs(lineupError)>3 then
|
||||||
waveoff=true
|
waveoff=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Too slow or too fast?
|
||||||
if AoA<6.9 or AoA>9.3 then
|
if AoA<6.9 or AoA>9.3 then
|
||||||
waveoff=true
|
waveoff=true
|
||||||
end
|
end
|
||||||
@ -1188,25 +1237,26 @@ function CARRIERTRAINER:_Trapped(playerData, pos)
|
|||||||
local wire = 1
|
local wire = 1
|
||||||
local score = -10
|
local score = -10
|
||||||
|
|
||||||
-- Which wire
|
-- Little offset for the exact wire positions.
|
||||||
if X<-14 then
|
local wdx=11
|
||||||
wire = 1
|
|
||||||
score = -15
|
-- Which wire was caught?
|
||||||
elseif X<-3 then
|
if X<-104+wdx then
|
||||||
wire = 2
|
wire=1
|
||||||
score = 10
|
elseif X<-92+wdx then
|
||||||
elseif X<10 then
|
wire=2
|
||||||
wire = 3
|
elseif X<-80+wdx then
|
||||||
score = 20
|
wire=3
|
||||||
|
elseif X<68+wdx then
|
||||||
|
wire=4
|
||||||
else
|
else
|
||||||
wire = 4
|
wire=0
|
||||||
score = 7
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local text=string.format("TRAPPED! %d-wire.", wire)
|
local text=string.format("TRAPPED! %d-wire.", wire)
|
||||||
self:_SendMessageToPlayer(text, 30, playerData)
|
self:_SendMessageToPlayer(text, 30, playerData)
|
||||||
|
|
||||||
local text2=string.format("Distance %.1f meters resulted in a %d-wire estimate.", X, wire)
|
local text2=string.format("Distance X=%.1f meters resulted in a %d-wire estimate.", X, wire)
|
||||||
MESSAGE:New(text,30):ToAllIf(self.Debug)
|
MESSAGE:New(text,30):ToAllIf(self.Debug)
|
||||||
env.info(text2)
|
env.info(text2)
|
||||||
|
|
||||||
@ -1217,6 +1267,9 @@ function CARRIERTRAINER:_Trapped(playerData, pos)
|
|||||||
--Boltered!
|
--Boltered!
|
||||||
playerData.boltered=true
|
playerData.boltered=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Next step: debriefing.
|
||||||
|
playerData.step=999
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Entering the Groove.
|
--- Entering the Groove.
|
||||||
@ -1371,7 +1424,7 @@ function CARRIERTRAINER:_Debrief(playerData)
|
|||||||
|
|
||||||
-- Debriefing text.
|
-- Debriefing text.
|
||||||
local text=string.format("Debriefing:\n")
|
local text=string.format("Debriefing:\n")
|
||||||
text=text..string.format("===========\n\n")
|
text=text..string.format("===================================================\n")
|
||||||
for _,_data in pairs(playerData.debrief) do
|
for _,_data in pairs(playerData.debrief) do
|
||||||
local step=_data.step
|
local step=_data.step
|
||||||
local comment=_data.hint
|
local comment=_data.hint
|
||||||
@ -1618,6 +1671,19 @@ end
|
|||||||
-- @param #CARRIERTRAINER self
|
-- @param #CARRIERTRAINER self
|
||||||
function CARRIERTRAINER:_InitStennis()
|
function CARRIERTRAINER:_InitStennis()
|
||||||
|
|
||||||
|
-- Carrier Parameters.
|
||||||
|
self.rwyangle = -10
|
||||||
|
self.sterndist =-150
|
||||||
|
self.deckheight = 22
|
||||||
|
|
||||||
|
--[[
|
||||||
|
q0=self.carrier:GetCoordinate():SetAltitude(25)
|
||||||
|
q0:BigSmokeSmall(0.1)
|
||||||
|
q1=self.carrier:GetCoordinate():Translate(-104,0):SetAltitude(22) --1st wire
|
||||||
|
q1:BigSmokeSmall(0.1)--:SmokeGreen()
|
||||||
|
q2=self.carrier:GetCoordinate():Translate(-68,0):SetAltitude(22) --4th wire ==> distance between wires 12 m
|
||||||
|
q2:BigSmokeSmall(0.1)--:SmokeBlue()
|
||||||
|
]]
|
||||||
|
|
||||||
-- Upwind leg
|
-- Upwind leg
|
||||||
self.Upwind.name="Upwind"
|
self.Upwind.name="Upwind"
|
||||||
@ -1776,7 +1842,7 @@ function CARRIERTRAINER:_LSOgrade(playerData)
|
|||||||
|
|
||||||
elseif playerData.landed then
|
elseif playerData.landed then
|
||||||
|
|
||||||
local gdata=playerData.Groove.X --#CARRIERTRAINER.GrooveData
|
local gdata=playerData.groove.X --#CARRIERTRAINER.GrooveData
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -1947,7 +2013,9 @@ function CARRIERTRAINER:_SendMessageToPlayer(message, duration, playerData, clea
|
|||||||
if playerData.client then
|
if playerData.client then
|
||||||
--MESSAGE:New(string.format("%s, %s, ", self.alias, playerData.callsign)..message, duration, nil, clear):ToClient(playerData.client)
|
--MESSAGE:New(string.format("%s, %s, ", self.alias, playerData.callsign)..message, duration, nil, clear):ToClient(playerData.client)
|
||||||
end
|
end
|
||||||
MESSAGE:New(string.format("%s, %s, %s", self.alias, playerData.callsign, message), duration, nil, clear):ToAll()
|
local text=string.format("%s, %s, %s", self.alias, playerData.callsign, message)
|
||||||
|
MESSAGE:New(text, duration, nil, clear):ToAll()
|
||||||
|
env.info(text)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Display final score.
|
--- Display final score.
|
||||||
|
|||||||
@ -276,7 +276,7 @@ RANGE.id="RANGE | "
|
|||||||
|
|
||||||
--- Range script version.
|
--- Range script version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RANGE.version="1.2.2"
|
RANGE.version="1.2.3"
|
||||||
|
|
||||||
--TODO list:
|
--TODO list:
|
||||||
--TODO: Add custom weapons, which can be specified by the user.
|
--TODO: Add custom weapons, which can be specified by the user.
|
||||||
@ -460,9 +460,10 @@ function RANGE:SetBombtrackThreshold(distance)
|
|||||||
self.BombtrackThreshold=distance*1000 or 25*1000
|
self.BombtrackThreshold=distance*1000 or 25*1000
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set range location. If this is not done, one (random) unit position of the range is used to determine the center of the range.
|
--- Set range location. If this is not done, one (random) unit position of the range is used to determine the location of the range.
|
||||||
|
-- The range location determines the position at which the weather data is evaluated.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param Core.Point#COORDINATE coordinate Coordinate of the center of the range.
|
-- @param Core.Point#COORDINATE coordinate Coordinate of the range.
|
||||||
function RANGE:SetRangeLocation(coordinate)
|
function RANGE:SetRangeLocation(coordinate)
|
||||||
self.location=coordinate
|
self.location=coordinate
|
||||||
end
|
end
|
||||||
@ -471,7 +472,7 @@ end
|
|||||||
-- If a zone is not explicitly specified, the range zone is determined by its location and radius.
|
-- If a zone is not explicitly specified, the range zone is determined by its location and radius.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param Core.Zone#ZONE zone MOOSE zone defining the range perimeters.
|
-- @param Core.Zone#ZONE zone MOOSE zone defining the range perimeters.
|
||||||
function RANGE:SetRangeLocation(zone)
|
function RANGE:SetRangeZone(zone)
|
||||||
self.rangezone=zone
|
self.rangezone=zone
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1163,13 +1164,19 @@ function RANGE:OnEventShot(EventData)
|
|||||||
-- Coordinate of impact point.
|
-- Coordinate of impact point.
|
||||||
local impactcoord=COORDINATE:NewFromVec3(_lastBombPos)
|
local impactcoord=COORDINATE:NewFromVec3(_lastBombPos)
|
||||||
|
|
||||||
|
-- Check if impact happend in range zone.
|
||||||
|
local insidezone=self.rangezone:IsCoordinateInZone(impactcoord)
|
||||||
|
|
||||||
-- Distance from range. We dont want to smoke targets outside of the range.
|
-- Distance from range. We dont want to smoke targets outside of the range.
|
||||||
local impactdist=impactcoord:Get2DDistance(self.location)
|
local impactdist=impactcoord:Get2DDistance(self.location)
|
||||||
|
|
||||||
--impactcoord:MarkToAll("Bomb impact point")
|
-- Impact point of bomb.
|
||||||
|
if self.Debug then
|
||||||
|
impactcoord:MarkToAll("Bomb impact point")
|
||||||
|
end
|
||||||
|
|
||||||
-- Smoke impact point of bomb.
|
-- Smoke impact point of bomb.
|
||||||
if self.PlayerSettings[_playername].smokebombimpact and impactdist<self.rangeradius then
|
if self.PlayerSettings[_playername].smokebombimpact and insidezone then
|
||||||
if self.PlayerSettings[_playername].delaysmoke then
|
if self.PlayerSettings[_playername].delaysmoke then
|
||||||
timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
|
timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
|
||||||
else
|
else
|
||||||
@ -1207,7 +1214,7 @@ function RANGE:OnEventShot(EventData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Count if bomb fell less than 1 km away from the target.
|
-- Count if bomb fell less than ~1 km away from the target.
|
||||||
if _distance <= self.scorebombdistance then
|
if _distance <= self.scorebombdistance then
|
||||||
|
|
||||||
-- Init bomb player results.
|
-- Init bomb player results.
|
||||||
@ -1226,7 +1233,7 @@ function RANGE:OnEventShot(EventData)
|
|||||||
|
|
||||||
-- Send message.
|
-- Send message.
|
||||||
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
||||||
elseif _distance <= self.rangeradius then
|
elseif insidezone then
|
||||||
-- Send message
|
-- Send message
|
||||||
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
|
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
|
||||||
self:_DisplayMessageToGroup(_unit, _message, nil, false)
|
self:_DisplayMessageToGroup(_unit, _message, nil, false)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user