Merge branch 'FF/Develop' of https://github.com/FlightControl-Master/MOOSE into FF/Develop

This commit is contained in:
Frank 2018-10-26 18:55:41 +02:00
commit b754972490
3 changed files with 103 additions and 81 deletions

View File

@ -115,19 +115,20 @@ CARRIERTRAINER.Difficulty={
--- Player data table holding all important parameters for each player.
-- @type CARRIERTRAINER.PlayerData
-- @field #number id Player ID.
-- @field #string callsign Callsign of player.
-- @field #number score Player score.
-- @field #number totalscore Score of all landing attempts.
-- @field #number passes Number of passes.
-- @field #string collectedResultString Results text of all passes.
-- @field Wrapper.Unit#UNIT unit Aircraft unit of the player.
-- @field #number lowestAltitude Lowest altitude.
-- @field #number highestCarrierXDiff
-- @field #number secondsStandingStill Time player does not move after a landing attempt.
-- @field #string callsign Callsign of player.
-- @field #number score Player score of the current pass.
-- @field #number passes Number of passes.
-- @field #table debrief Debrief analysis of the current step of this pass.
-- @field #table results Results of all passes.
-- @field #string summary Result summary text.
-- @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 landed If true, player landed or attempted to land.
-- @field #boolean boltered If true, player boltered.
-- @field #boolean calledball If true, player called the ball.
-- @field #number Tlso Last time the LSO gave an advice.
--- Checkpoint parameters triggering the next step in the pattern.
-- @type CARRIERTRAINER.Checkpoint
@ -152,7 +153,7 @@ CARRIERTRAINER.MenuF10={}
--- Carrier trainer class version.
-- @field #string version
CARRIERTRAINER.version="0.1.0w"
CARRIERTRAINER.version="0.1.1w"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@ -374,19 +375,27 @@ function CARRIERTRAINER:_InitNewPlayer(unitname)
local playerData={} --#CARRIERTRAINER.PlayerData
-- Player unit, client and callsign.
playerData.unit = UNIT:FindByName(unitname)
playerData.client = CLIENT:FindByName(playerData.unit.UnitName, nil, true)
playerData.callsign = playerData.unit:GetCallsign()
playerData.totalscore = 0
-- Number of passes done by player.
playerData.passes=0
playerData.collectedResultString = ""
playerData=self:_InitNewRound(playerData)
playerData.results={}
-- Set difficulty level.
playerData.difficulty=CARRIERTRAINER.Difficulty.NORMAL
-- Player is in the big zone around the carrier.
playerData.inbigzone=playerData.unit:IsInZone(self.giantZone)
-- Init stuff for this round.
playerData=self:_InitNewRound(playerData)
return playerData
end
@ -396,21 +405,25 @@ end
-- @return #CARRIERTRAINER.PlayerData Initialized player data.
function CARRIERTRAINER:_InitNewRound(playerData)
playerData.step=0
playerData.score = 0
playerData.score=100
playerData.grade={}
playerData.summary = "Debriefing:\n"
playerData.longDownwindDone = false
playerData.highestCarrierXDiff = -9999999
playerData.secondsStandingStill = 0
playerData.lowestAltitude = 999999
playerData.boltered=false
playerData.landed=false
playerData.calledball=false
playerData.Tlso=timer.getTime()
return playerData
end
--- Append text to summary text.
--- Append text to debrief text.
-- @param #CARRIERTRAINER self
-- @param #CARRIERTRAINER.PlayerData playerData Player data.
-- @param #string item Text item appeded to the summary.
function CARRIERTRAINER:_AddToSummary(playerData, item)
playerData.summary = playerData.summary .. item .. "\n"
-- @param #string step Current step in the pattern.
-- @param #string item Text item appeded to the debrief.
function CARRIERTRAINER:_AddToSummary(playerData, step, item)
--playerData.summary = playerData.summary .. item .. "\n"
table.inser(playerData.debrief, {step=step, hint=item})
end
--- Append text to result text.
@ -492,7 +505,9 @@ function CARRIERTRAINER:_CheckPlayerStatus()
elseif playerData.step == 8 then
self:_Groove(playerData)
elseif playerData.step == 9 then
self:_Trap(playerData)
self:_CallTheBall(playerData)
elseif playerData.step == 99 then
self:_Debrief(playerData)
end
else
@ -882,7 +897,6 @@ function CARRIERTRAINER:_Start(playerData)
-- Next step: upwind.
playerData.step=2
end
end
@ -909,8 +923,10 @@ function CARRIERTRAINER:_Upwind(playerData)
-- Get altitude.
local hint=self:_AltitudeCheck(playerData, self.Upwind, altitude)
-- Message to player
self:_SendMessageToPlayer(hint, 8, playerData)
-- Debrief.
self:_AddToSummary(playerData, hint)
-- Next step.
@ -952,7 +968,7 @@ function CARRIERTRAINER:_Break(playerData, part)
-- Send message to player.
self:_SendMessageToPlayer(hint, 10, playerData)
-- Add hint to summary.
-- Debrif
self:_AddToSummary(playerData, hint)
-- Nest step: late break or abeam.
@ -986,7 +1002,7 @@ function CARRIERTRAINER:_CheckForLongDownwind(playerData)
local hint = "Your downwind leg is too long. Turn to final earlier next time."
self:_SendMessageToPlayer(hint, 10, playerData)
-- Add to debrief.
-- Debrief.
self:_AddToSummary(playerData, hint)
-- Decrease score.
@ -1042,7 +1058,7 @@ function CARRIERTRAINER:_Abeam(playerData)
self:_SendMessageToPlayer(hintFull, 10, playerData)
-- Add to debrief.
self:_AddToSummary(playerData, hintFull)
self:_AddToSummary(playerData, "Abeam", hintFull)
-- Proceed to next step.
playerData.step = 6
@ -1085,7 +1101,7 @@ function CARRIERTRAINER:_Ninety(playerData)
self:_SendMessageToPlayer(hintFull, 10, playerData)
-- Add to debrief.
self:_AddToSummary(playerData, hintFull)
self:_AddToSummary(playerData, "At the 90:", hintFull)
-- Long downwind not an issue any more
playerData.longDownwindDone = true
@ -1128,14 +1144,14 @@ function CARRIERTRAINER:_Wake(playerData)
self:_SendMessageToPlayer(hintFull, 10, playerData)
-- Add to debrief.
self:_AddToSummary(playerData, hintFull)
self:_AddToSummary(playerData, "At the wake:", hintFull)
-- Next step: Groove.
playerData.step = 8
end
end
--- Groove.
--- Entering the Groove.
-- @param #CARRIERTRAINER self
-- @param #CARRIERTRAINER.PlayerData playerData Player data table.
function CARRIERTRAINER:_Groove(playerData)
@ -1179,7 +1195,7 @@ function CARRIERTRAINER:_Groove(playerData)
self:_SendMessageToPlayer(hintFull, 10, playerData)
-- Add to debrief.
self:_AddToSummary(playerData, hintFull)
self:_AddToSummary(playerData, "Entering the Groove:", hintFull)
-- Next step.
playerData.step = 9
@ -1187,10 +1203,10 @@ function CARRIERTRAINER:_Groove(playerData)
end
--- Trap.
--- Call the ball, i.e. 3/4 NM distance between aircraft and carrier.
-- @param #CARRIERTRAINER self
-- @param #CARRIERTRAINER.PlayerData playerData Player data table.
function CARRIERTRAINER:_Trap(playerData)
function CARRIERTRAINER:_CallTheBall(playerData)
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
local diffX, diffZ, rho, phi = self:_GetDistances(playerData.unit)
@ -1208,23 +1224,21 @@ function CARRIERTRAINER:_Trap(playerData)
return
end
if (diffX > playerData.highestCarrierXDiff) then
playerData.highestCarrierXDiff = diffX
end
if (alt < playerData.lowestAltitude) then
playerData.lowestAltitude = alt
end
-- Lineup.
-- Lineup. We need to correct for the end of the carrier deck and the tilted angle of the runway.
-- TODO: make this parameter of the carrier.
local lineup = math.asin(diffZ/(-(diffX-100)))
local lineuperror = math.deg(lineup)-10
-- Glideslope.
-- Glideslope. Wee need to correct for the height of the deck. The ideal glide slope is 3.5 degrees.
-- TODO: make this parameter of the carrier.
local glideslope = math.atan((playerData.unit:GetAltitude()-22)/(-diffX))
local glideslopeError = math.deg(glideslope) - 3.5
if diffX<100 then
if diffX>-UTILS.NMToMeters(0.75) and diffX<-100 and playerData.calledball==false then
-- Check if we are beween 3/4 NM and end of ship.
if diffX>-UTILS.NMToMeters(0.75) and diffX<-100 then
local text="Good height."
if glideslopeError>1 then
@ -1259,7 +1273,7 @@ function CARRIERTRAINER:_Trap(playerData)
elseif lineuperror <3 then
text=text.."Right for lineup!"
elseif lineuperror <1 then
text=text.."Right for lineup.."
text=text.."Right for lineup..."
else
text=text.."Good on lineup."
end

View File

@ -5435,7 +5435,7 @@ function RAT:_ATCInit(airports_map)
if not RAT.ATC.init then
local text
text="Starting RAT ATC.\nSimultanious = "..RAT.ATC.Nclearance.."\n".."Delay = "..RAT.ATC.delay
self:T(RAT.id..text)
BASE:T(RAT.id..text)
RAT.ATC.init=true
for _,ap in pairs(airports_map) do
local name=ap:GetName()
@ -5458,7 +5458,7 @@ end
-- @param #string name Group name of the flight.
-- @param #string dest Name of the destination airport.
function RAT:_ATCAddFlight(name, dest)
self:T(string.format("%sATC %s: Adding flight %s with destination %s.", RAT.id, dest, name, dest))
BASE:T(string.format("%sATC %s: Adding flight %s with destination %s.", RAT.id, dest, name, dest))
RAT.ATC.flight[name]={}
RAT.ATC.flight[name].destination=dest
RAT.ATC.flight[name].Tarrive=-1
@ -5483,7 +5483,7 @@ end
-- @param #string name Group name of the flight.
-- @param #number time Time the fight first registered.
function RAT:_ATCRegisterFlight(name, time)
self:T(RAT.id.."Flight ".. name.." registered at ATC for landing clearance.")
BASE:T(RAT.id.."Flight ".. name.." registered at ATC for landing clearance.")
RAT.ATC.flight[name].Tarrive=time
RAT.ATC.flight[name].holding=0
end
@ -5514,7 +5514,7 @@ function RAT:_ATCStatus()
-- Aircraft is holding.
local text=string.format("ATC %s: Flight %s is holding for %i:%02d. %s.", dest, name, hold/60, hold%60, busy)
self:T(RAT.id..text)
BASE:T(RAT.id..text)
elseif hold==RAT.ATC.onfinal then
@ -5522,7 +5522,7 @@ function RAT:_ATCStatus()
local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
local text=string.format("ATC %s: Flight %s is on final. Waiting %i:%02d for landing event.", dest, name, Tfinal/60, Tfinal%60)
self:T(RAT.id..text)
BASE:T(RAT.id..text)
elseif hold==RAT.ATC.unregistered then
@ -5530,7 +5530,7 @@ function RAT:_ATCStatus()
--self:T(string.format("ATC %s: Flight %s is not registered yet (hold %d).", dest, name, hold))
else
self:E(RAT.id.."ERROR: Unknown holding time in RAT:_ATCStatus().")
BASE:E(RAT.id.."ERROR: Unknown holding time in RAT:_ATCStatus().")
end
end
@ -5572,12 +5572,12 @@ function RAT:_ATCCheck()
-- Debug message.
local text=string.format("ATC %s: Flight %s runway is busy. You are #%d of %d in landing queue. Your holding time is %i:%02d.", name, flight,qID, nqueue, RAT.ATC.flight[flight].holding/60, RAT.ATC.flight[flight].holding%60)
self:T(RAT.id..text)
BASE:T(RAT.id..text)
else
local text=string.format("ATC %s: Flight %s was cleared for landing. Your holding time was %i:%02d.", name, flight, RAT.ATC.flight[flight].holding/60, RAT.ATC.flight[flight].holding%60)
self:T(RAT.id..text)
BASE:T(RAT.id..text)
-- Clear flight for landing.
RAT:_ATCClearForLanding(name, flight)
@ -5706,11 +5706,6 @@ function RAT:_ATCQueue()
table.insert(RAT.ATC.airport[airport].queue, v[1])
end
--fvh
--for k,v in ipairs(RAT.ATC.airport[airport].queue) do
--print(string.format("queue #%02i flight \"%s\" holding %d seconds",k, v, RAT.ATC.flight[v].holding))
--end
end
end

View File

@ -69,6 +69,7 @@
-- @field #boolean autosave Automatically save assets to file when mission ends.
-- @field #string autosavepath Path where the asset file is saved on auto save.
-- @field #string autosavefilename File name of the auto asset save file. Default is auto generated from warehouse id and name.
-- @field #boolean safeparking If true, parking spots for aircraft are considered as occupied if e.g. a client aircraft is parked there. Default false.
-- @extends Core.Fsm#FSM
--- Have your assets at the right place at the right time - or not!
@ -1556,6 +1557,7 @@ WAREHOUSE = {
autosave = false,
autosavepath = nil,
autosavefile = nil,
saveparking = false,
}
--- Item of the warehouse stock table.
@ -2364,6 +2366,24 @@ function WAREHOUSE:SetReportOff()
return self
end
--- Enable safe parking option, i.e. parking spots at an airbase will be considered as occupied when a client aircraft is parked there (even if the client slot is not taken by a player yet).
-- Note that also incoming aircraft can reserve/occupie parking spaces.
-- @param #WAREHOUSE self
-- @return #WAREHOUSE self
function WAREHOUSE:SetSafeParkingOn()
self.safeparking=true
return self
end
--- Disable safe parking option. Note that is the default setting.
-- @param #WAREHOUSE self
-- @return #WAREHOUSE self
function WAREHOUSE:SetSafeParkingOff()
self.safeparking=false
return self
end
--- Set interval of status updates. Note that normally only one request can be processed per time interval.
-- @param #WAREHOUSE self
-- @param #number timeinterval Time interval in seconds.
@ -7004,20 +7024,6 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
table.insert(obstacles,{coord=_coord, size=_size, name=_name, type="scenery"})
end
--[[
-- TODO Clients? Unoccupied client aircraft are also important! Are they already included in scanned units maybe?
local clients=_DATABASE.CLIENTS
for _,_client in pairs(clients) do
local client=_client --Wrapper.Client#CLIENT
env.info(string.format("FF Client name %s", client:GetName()))
local unit=UNIT:FindByName(client:GetName())
--local unit=client:GetClientGroupUnit()
local _coord=unit:GetCoordinate()
local _name=unit:GetName()
local _size=self:_GetObjectSize(client:GetClientGroupDCSUnit())
table.insert(obstacles,{coord=_coord, size=_size, name=_name, type="client"})
end
]]
end
-- Parking data for all assets.
@ -7051,9 +7057,16 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
--env.info(string.format("FF asset=%s (id=%d): needs terminal type=%d, id=%d, #obstacles=%d", _asset.templatename, _asset.uid, terminaltype, _termid, #obstacles))
-- Loop over all obstacles.
local free=true
local problem=nil
-- Safe parking using TO_AC from DCS result.
if self.safeparking and _toac then
free=false
self:T("Parking spot %d is occupied by other aircraft taking off or landing.", _termid)
end
-- Loop over all obstacles.
for _,obstacle in pairs(obstacles) do
-- Check if aircraft overlaps with any obstacle.