diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index c3f9ee12e..62e39cadf 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -290,7 +290,7 @@ RANGE.id="RANGE | " --- Range script version. -- @field #string version -RANGE.version="1.2.5" +RANGE.version="1.3.0" --TODO list: --TODO: Verbosity level for messages. @@ -1183,25 +1183,39 @@ end function RANGE:OnEventShot(EventData) self:F({eventshot = EventData}) + -- Nil checks. + if EventData.Weapon==nil then + return + end + if EventData.IniDCSUnit==nil then + return + end + -- Weapon data. local _weapon = EventData.Weapon:getTypeName() -- should be the same as Event.WeaponTypeName local _weaponStrArray = UTILS.Split(_weapon,"%.") local _weaponName = _weaponStrArray[#_weaponStrArray] + -- Weapon descriptor. + local desc=EventData.Weapon:getDesc() + + -- Weapon category: 0=SHELL, 1=MISSILE, 2=ROCKET, 3=BOMB (Weapon.Category.X) + local weaponcategory=desc.category + -- Debug info. self:T(RANGE.id.."EVENT SHOT: Range "..self.rangename) self:T(RANGE.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName) self:T(RANGE.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName) self:T(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon) self:T(RANGE.id.."EVENT SHOT: Weapon name = ".._weaponName) - + self:T(RANGE.id.."EVENT SHOT: Weapon cate = "..weaponcategory) -- Special cases: - local _viggen=string.match(_weapon, "ROBOT") or string.match(_weapon, "RB75") or string.match(_weapon, "BK90") or string.match(_weapon, "RB15") or string.match(_weapon, "RB04") + --local _viggen=string.match(_weapon, "ROBOT") or string.match(_weapon, "RB75") or string.match(_weapon, "BK90") or string.match(_weapon, "RB15") or string.match(_weapon, "RB04") -- Tracking conditions for bombs, rockets and missiles. - local _bombs=string.match(_weapon, "weapons.bombs") - local _rockets=string.match(_weapon, "weapons.nurs") - local _missiles=string.match(_weapon, "weapons.missiles") or _viggen + local _bombs = weaponcategory==Weapon.Category.BOMB --string.match(_weapon, "weapons.bombs") + local _rockets = weaponcategory==Weapon.Category.ROCKET --string.match(_weapon, "weapons.nurs") + local _missiles = weaponcategory==Weapon.Category.MISSILE --string.match(_weapon, "weapons.missiles") or _viggen -- Check if any condition applies here. local _track = (_bombs and self.trackbombs) or (_rockets and self.trackrockets) or (_missiles and self.trackmissiles) @@ -1221,8 +1235,8 @@ function RANGE:OnEventShot(EventData) self:T(RANGE.id..string.format("Range %s, player %s, player-range distance = %d km.", self.rangename, _playername, dPR/1000)) end - -- Only track if distance player to range is < 25 km. - if _track and dPR<=self.BombtrackThreshold then + -- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons. + if _track and dPR<=self.BombtrackThreshold and _unit and _playername then -- Tracking info and init of last bomb position. self:T(RANGE.id..string.format("RANGE %s: Tracking %s - %s.", self.rangename, _weapon, EventData.weapon:getName())) @@ -1346,8 +1360,8 @@ function RANGE:OnEventShot(EventData) end -- end function trackBomb -- Weapon is not yet "alife" just yet. Start timer in one second. - self:T(RANGE.id..string.format("Range %s, player %s: Tracking of weapon starts in one second.", self.rangename, _playername)) - timer.scheduleFunction(trackBomb, EventData.weapon, timer.getTime() + 1.0) + self:T(RANGE.id..string.format("Range %s, player %s: Tracking of weapon starts in 0.1 seconds.", self.rangename, _playername)) + timer.scheduleFunction(trackBomb, EventData.weapon, timer.getTime()+0.1) end --if _track (string.match) and player-range distance < threshold. diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 1aa0b1f6f..792194f9b 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -1671,7 +1671,7 @@ AIRBOSS.MenuF10Root=nil --- Airboss class version. -- @field #string version -AIRBOSS.version="0.9.9.8" +AIRBOSS.version="0.9.9.9" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -2408,7 +2408,7 @@ function AIRBOSS:DeleteAllRecoveryWindows(delay) -- Loop over all recovery windows. for _,recovery in pairs(self.recoverytimes) do - env.info("FF deleting recovery window ID "..tostring(recovery.ID)) + self:I(self.lid..string.format("Deleting recovery window ID %s", tostring(recovery.ID))) self:DeleteRecoveryWindow(recovery, delay) end @@ -7978,29 +7978,6 @@ end -- EVENT functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ---- General DCS event handler. --- @param #AIRBOSS self --- @param #table Event DCS event table. -function AIRBOSS:onEvent(Event) - self:F3(Event) - - --[[ - if Event == nil or Event.initiator == nil then - self:T3("Skipping onEvent. Event or Event.initiator unknown.") - return true - end - if Unit.getByName(Event.initiator:getName()) == nil then - self:T3("Skipping onEvent. Initiator unit name unknown.") - return true - end - ]] - - --env.info("FF DCS Event") - --self:E(Event) - -end - - --- Airboss event handler for event birth. -- @param #AIRBOSS self -- @param Core.Event#EVENTDATA EventData @@ -9394,6 +9371,8 @@ function AIRBOSS:_GetGrooveData(playerData) groovedata.Grade=Gg groovedata.GradePoints=Gp groovedata.GradeDetail=Gd + + --env.info(string.format(", %.6f, %.6f, %.6f, %.6f, %.6f, %.6f, %.6f", groovedata.Time, groovedata.Rho, groovedata.X, groovedata.Alt, groovedata.GSE, groovedata.LUE, groovedata.AoA)) return groovedata end @@ -9439,7 +9418,7 @@ function AIRBOSS:_Final(playerData, nocheck) -- TODO: could add angled approach if lineup<5 and relhead>5. This would mean the player has not turned in correctly! -- Groove data. - playerData.groove.X0=groovedata + playerData.groove.X0=UTILS.DeepCopy(groovedata) -- Set time stamp. Next call in 4 seconds. playerData.Tlso=timer.getTime() @@ -9447,6 +9426,9 @@ function AIRBOSS:_Final(playerData, nocheck) -- Next step: X start. self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.GROOVE_XX) end + + -- Groovedata step. + groovedata.Step=playerData.step end @@ -9454,15 +9436,6 @@ end -- @param #AIRBOSS self -- @param #AIRBOSS.PlayerData playerData Player data table. function AIRBOSS:_Groove(playerData) - - -- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier) - local X, Z=self:_GetDistances(playerData.unit) - - -- Check abort conditions. - if self:_CheckAbort(X, Z, self.Groove) then - self:_AbortPattern(playerData, X, Z, self.Groove, true) - return - end -- Ranges in the groove. local RX0=UTILS.NMToMeters(1.000) -- Everything before X 1.00 = 1852 m @@ -9475,7 +9448,17 @@ function AIRBOSS:_Groove(playerData) local groovedata=self:_GetGrooveData(playerData) -- Add data to trapsheet. - table.insert(playerData.trapsheet, groovedata) + table.insert(playerData.trapsheet, groovedata) + + -- Coords. + local X=groovedata.X + local Z=groovedata.Z + + -- Check abort conditions. + if self:_CheckAbort(groovedata.X, groovedata.Z, self.Groove) then + self:_AbortPattern(playerData, groovedata.X, groovedata.Z, self.Groove, true) + return + end -- Shortcuts. local rho=groovedata.Rho @@ -9500,7 +9483,7 @@ function AIRBOSS:_Groove(playerData) self:RadioTransmission(self.LSORadio, self.LSOCall.ROGERBALL, false, nil, 2, true) -- Store data. - playerData.groove.XX=groovedata + playerData.groove.XX=UTILS.DeepCopy(groovedata) -- This is a valid approach and player did not miss any important steps in the pattern. playerData.valid=true @@ -9511,7 +9494,7 @@ function AIRBOSS:_Groove(playerData) elseif rho<=RIM and playerData.step==AIRBOSS.PatternStep.GROOVE_IM then -- Store data. - playerData.groove.IM=groovedata + playerData.groove.IM=UTILS.DeepCopy(groovedata) -- Next step: in close. self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.GROOVE_IC) @@ -9519,7 +9502,7 @@ function AIRBOSS:_Groove(playerData) elseif rho<=RIC and playerData.step==AIRBOSS.PatternStep.GROOVE_IC then -- Store data. - playerData.groove.IC=groovedata + playerData.groove.IC=UTILS.DeepCopy(groovedata) -- Next step: AR at the ramp. self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.GROOVE_AR) @@ -9527,7 +9510,7 @@ function AIRBOSS:_Groove(playerData) elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_AR then -- Store data. - playerData.groove.AR=groovedata + playerData.groove.AR=UTILS.DeepCopy(groovedata) -- Next step: in the wires. if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then @@ -9539,7 +9522,7 @@ function AIRBOSS:_Groove(playerData) elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_AL then -- Store data. - playerData.groove.AL=groovedata + playerData.groove.AL=UTILS.DeepCopy(groovedata) -- Get zone abeam LDG spot. local ZoneALS=self:_GetZoneAbeamLandingSpot() @@ -9569,7 +9552,7 @@ function AIRBOSS:_Groove(playerData) elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_LC then -- Store data. - playerData.groove.LC=groovedata + playerData.groove.LC=UTILS.DeepCopy(groovedata) -- Get zone primary LDG spot. local ZoneLS=self:_GetZoneLandingSpot() @@ -9625,25 +9608,31 @@ function AIRBOSS:_Groove(playerData) end + -- Groovedata step. + groovedata.Step=playerData.step + ----------------- -- Groove Data -- ----------------- - - -- Get groove step short hand of the previous step. - local gs=self:_GS(playerData.step, -1) -- Check if we are beween 3/4 NM and end of ship. if rho>=RAR and rhomath.abs(gd.LUE) then - self:T(self.lid..string.format("Got bigger Lineup error at %s: LUE %.3f>%.3f.", gs, lineupError, gd.LUE)) + self:T(self.lid..string.format("Got bigger LUE at step %s, d=%.3f: LUE %.3f>%.3f", gs, d, lineupError, gd.LUE)) gd.LUE=lineupError end @@ -9651,22 +9640,19 @@ function AIRBOSS:_Groove(playerData) if gd.GSE>0.4 and glideslopeError<-0.3 then -- Fly through down ==> "\" gd.FlyThrough="\\" - self:T(self.lid..string.format("Got Fly through DOWN at %s. Max GSE=%.1f, lower GSE=%.1f", gs, gd.GSE, glideslopeError)) + self:T(self.lid..string.format("Got Fly through DOWN at step %s, d=%.3f: Max GSE=%.3f, lower GSE=%.3f", gs, d, gd.GSE, glideslopeError)) elseif gd.GSE<-0.3 and glideslopeError>0.4 then -- Fly through up ==> "/" gd.FlyThrough="/" - self:T(self.lid..string.format("Got Fly through UP at %s. Min GSE=%.1f, lower GSE=%.1f", gs, gd.GSE, glideslopeError)) + self:E(self.lid..string.format("Got Fly through UP at step %s, d=%.3f: Min GSE=%.3f, lower GSE=%.3f", gs, d, gd.GSE, glideslopeError)) end -- Update max deviation of glideslope error. if math.abs(glideslopeError)>math.abs(gd.GSE) then - self:T(self.lid..string.format("Got bigger glideslope error at %s: GSE |%.3f|>|%.3f|.", gs, glideslopeError, gd.GSE)) + self:T(self.lid..string.format("Got bigger GSE at step %s, d=%.3f: GSE |%.3f|>|%.3f|", gs, d, glideslopeError, gd.GSE)) gd.GSE=glideslopeError end - -- Get current AoA. - local aoa=playerData.unit:GetAoA() - -- Get aircraft AoA parameters. local aircraftaoa=self:_GetAircraftAoA(playerData) @@ -9674,11 +9660,14 @@ function AIRBOSS:_Groove(playerData) local aoaopt=aircraftaoa.OnSpeed -- Compare AoAs wrt on speed AoA and update max deviation. - if math.abs(aoa-aoaopt)>math.abs(gd.AoA-aoaopt) then - self:T(self.lid..string.format("Got bigger AoA error at %s: AoA %.3f>%.3f.", gs, aoa, gd.AoA)) - gd.AoA=aoa + if math.abs(AoA-aoaopt)>math.abs(gd.AoA-aoaopt) then + self:T(self.lid..string.format("Got bigger AoA error at step %s, d=%.3f: AoA %.3f>%.3f.", gs, d, AoA, gd.AoA)) + gd.AoA=AoA end + --local gs2=self:_GS(groovedata.Step, -1) + --env.info(string.format("groovestep %s %s d=%.3f NM: GSE=%.3f %.3f, LUE=%.3f %.3f, AoA=%.3f %.3f", gs, gs2, d, groovedata.GSE, gd.GSE, groovedata.LUE, gd.LUE, groovedata.AoA, gd.AoA)) + end --------------- @@ -10836,8 +10825,9 @@ function AIRBOSS:_AttitudeMonitor(playerData) -- Get carrier velocity in km/h. local vcarrier=self.carrier:GetVelocityKMH() -- Speed difference. - local dv=math.abs(vplayer-vcarrier) - text=text..string.format("\nDist=%.1f m Alt=%.1f m delta|V|=%.1f km/h", dist, self:_GetAltCarrier(playerData.unit), dv) + local dv=math.abs(vplayer-vcarrier) + local alt=self:_GetAltCarrier(playerData.unit) + text=text..string.format("\nDist=%.1f m Alt=%.1f m delta|V|=%.1f km/h", dist, alt, dv) -- If in the groove, provide line up and glide slope error. if playerData.step==AIRBOSS.PatternStep.FINAL or playerData.step==AIRBOSS.PatternStep.GROOVE_XX or @@ -10849,7 +10839,6 @@ function AIRBOSS:_AttitudeMonitor(playerData) playerData.step==AIRBOSS.PatternStep.GROOVE_IW then local lue=self:_Lineup(playerData.unit, true) local gle=self:_Glideslope(playerData.unit) - --local gle2=self:_Glideslope2(playerData.unit) text=text..string.format("\nGamma=%.1f° | Rho=%.1f°", relhead, phi) text=text..string.format("\nLineUp=%.2f° | GlideSlope=%.2f° | AoA=%.1f Units", lue, gle, self:_AoADeg2Units(playerData, aoa)) local grade, points, analysis=self:_LSOgrade(playerData) @@ -10885,7 +10874,7 @@ function AIRBOSS:_Glideslope(unit, optangle) -- Altitude of unit corrected by the deck height of the carrier. local h=self:_GetAltCarrier(unit) - + -- Harrier should be 40-50 ft above the deck. if unit:GetTypeName()==AIRBOSS.AircraftCarrier.AV8B then h=unit:GetAltitude()-(UTILS.FeetToMeters(50)+self.carrierparam.deckheight+2) @@ -10893,16 +10882,10 @@ function AIRBOSS:_Glideslope(unit, optangle) -- Glide slope. local glideslope=math.atan(h/x) - + -- Glide slope (error) in degrees. local gs=math.deg(glideslope)-optangle - - -- Debug. - self:T2(self.lid..string.format("Glide slope error = %.1f, x=%.1f h=%.1f", gs, x, h)) - - --local gs2=self:_Glideslope2(unit) - --self:E(self.lid..string.format("Glide slope error = %.1f =%.1f, x=%.1f h=%.1f", gs, gs2, x, h)) - + return gs end @@ -10966,10 +10949,11 @@ function AIRBOSS:_Lineup(unit, runway) local C=UTILS.VecSubstract(A, B) -- Only in 2D plane. - C.y=0 + C.y=0.0 -- Orientation of carrier. - local X=self.carrier:GetOrientationX() + local X=self.carrier:GetOrientationX() + X.y=0.0 -- Rotate orientation to angled runway. if runway then @@ -10981,6 +10965,7 @@ function AIRBOSS:_Lineup(unit, runway) -- Orientation of carrier. local Z=self.carrier:GetOrientationZ() + Z.y=0.0 -- Rotate orientation to angled runway. if runway then @@ -10990,8 +10975,10 @@ function AIRBOSS:_Lineup(unit, runway) -- Projection of player pos on z component. local z=UTILS.VecDot(Z, C) - --- + --- + local lineup=math.deg(math.atan2(z, x)) + --[[ -- Position of the aircraft in the new coordinate system. local a={x=x, y=0, z=z} @@ -11003,7 +10990,8 @@ function AIRBOSS:_Lineup(unit, runway) -- Current line up and error wrt to final heading of the runway. local lineup=math.deg(math.atan2(c.z, c.x)) - + ]] + return lineup end @@ -17001,8 +16989,10 @@ function AIRBOSS:_SaveTrapSheet(playerData, grade) local g0=playerData.trapsheet[1] --#AIRBOSS.GrooveData local T0=g0.Time - for _,_groove in ipairs(playerData.trapsheet) do - local groove=_groove --#AIRBOSS.GrooveData + --for _,_groove in ipairs(playerData.trapsheet) do + for i=1,#playerData.trapsheet do + --local groove=_groove --#AIRBOSS.GrooveData + local groove=playerData.trapsheet[i] local t=groove.Time-T0 local a=UTILS.MetersToNM(groove.Rho or 0) local b=-groove.X or 0 diff --git a/Moose Development/Moose/Ops/RescueHelo.lua b/Moose Development/Moose/Ops/RescueHelo.lua index cabe8390f..f2fa53b80 100644 --- a/Moose Development/Moose/Ops/RescueHelo.lua +++ b/Moose Development/Moose/Ops/RescueHelo.lua @@ -235,7 +235,7 @@ RESCUEHELO.UID=0 --- Class version. -- @field #string version -RESCUEHELO.version="1.0.5" +RESCUEHELO.version="1.0.6" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -776,13 +776,18 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData) -- Debug. local text=string.format("Unit %s crashed or ejected.", unitname) MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) - self:T(self.lid..text) - - -- Unit "alive" and in our rescue zone. - if unit:IsAlive() and unit:IsInZone(self.rescuezone) then + self:I(self.lid..text) + + -- Get coordinate of unit. + local coord=unit:GetCoordinate() + if coord and self.rescuezone:IsCoordinateInZone(coord) then + + -- This does not seem to work any more. Is:Alive returns flase on ejection. + -- Unit "alive" and in our rescue zone. + --if unit:IsAlive() and unit:IsInZone(self.rescuezone) then -- Get coordinate of crashed unit. - local coord=unit:GetCoordinate() + --local coord=unit:GetCoordinate() -- Debug mark on map. if self.Debug then @@ -793,7 +798,7 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData) local rightcoalition=EventData.IniGroup:GetCoalition()==self.helo:GetCoalition() -- Only rescue if helo is "running" and not, e.g., rescuing already. - if self:IsRunning() and self.rescueon and rightcoalition then + if self:IsRunning() and self.rescueon and rightcoalition then self:Rescue(coord) end @@ -1091,7 +1096,7 @@ function RESCUEHELO:onafterRescue(From, Event, To, RescueCoord) -- Debug message. local text=string.format("Helo %s is send to rescue mission.", self.helo:GetName()) MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug) - self:T(self.lid..text) + self:I(self.lid..text) -- Waypoint array. local wp={}