mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Ops
This commit is contained in:
parent
18e192b235
commit
7b8db597ef
@ -141,18 +141,6 @@ function ARMYGROUP:SetPatrolAdInfinitum(switch)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set default cruise speed. This is the speed a group will take by default if no speed is specified explicitly.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #number Speed Speed in knots. Default 70% of max speed.
|
||||
-- @return #ARMYGROUP self
|
||||
function ARMYGROUP:SetSpeedCruise(Speed)
|
||||
|
||||
self.speedCruise=Speed and UTILS.KnotsToKmph(Speed) or self.speedMax*0.7
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Get coordinate of the closest road.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return Core.Point#COORDINATE Coordinate of a road closest to the group.
|
||||
@ -212,7 +200,26 @@ function ARMYGROUP:AddTaskAttackGroup(TargetGroup, WeaponExpend, WeaponType, Clo
|
||||
|
||||
end
|
||||
|
||||
--- Check if the group is currently holding its positon.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group was ordered to hold.
|
||||
function ARMYGROUP:IsHolding()
|
||||
return self:Is("Holding")
|
||||
end
|
||||
|
||||
--- Check if the group is currently cruising.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group cruising.
|
||||
function ARMYGROUP:IsCruising()
|
||||
return self:Is("Cruising")
|
||||
end
|
||||
|
||||
--- Check if the group is currently on a detour.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group is on a detour
|
||||
function ARMYGROUP:IsOnDetour()
|
||||
return self:Is("OnDetour")
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Status
|
||||
@ -223,10 +230,10 @@ end
|
||||
function ARMYGROUP:onbeforeStatus(From, Event, To)
|
||||
|
||||
if self:IsDead() then
|
||||
self:I(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
self:T(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
return false
|
||||
elseif self:IsStopped() then
|
||||
self:I(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
self:T(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
return false
|
||||
end
|
||||
|
||||
@ -251,27 +258,36 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
||||
self:_CheckDetectedUnits()
|
||||
end
|
||||
|
||||
|
||||
-- Current heading and position of the carrier.
|
||||
local hdg=self:GetHeading()
|
||||
local pos=self:GetCoordinate()
|
||||
local speed=self.group:GetVelocityKNOTS()
|
||||
-- Update position etc.
|
||||
self:_UpdatePosition()
|
||||
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Get number of tasks and missions.
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("%s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
|
||||
fsmstate, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), speed, UTILS.MpsToKnots(self.speedWp or 0), hdg, self.option.ROE, self.option.Alarm, self.option.Formation, nTaskTot, nMissions)
|
||||
self:I(self.lid..text)
|
||||
-- Get number of tasks and missions.
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
local roe=self:GetROE()
|
||||
local alarm=self:GetAlarmstate()
|
||||
local speed=UTILS.MpsToKnots(self.velocity)
|
||||
local speedEx=UTILS.MpsToKnots(self:GetExpectedSpeed())
|
||||
local formation=self.option.Formation
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("%s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
|
||||
fsmstate, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), speed, speedEx, self.heading, roe, alarm, formation, nTaskTot, nMissions)
|
||||
self:I(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("State %s: Alive=%s", fsmstate, tostring(self:IsAlive()))
|
||||
self:I(self.lid..text)
|
||||
self:T2(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
@ -305,19 +321,6 @@ function ARMYGROUP:onafterElementSpawned(From, Event, To, Element)
|
||||
|
||||
end
|
||||
|
||||
--- On after "ElementDead" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #ARMYGROUP.Element Element The group element.
|
||||
function ARMYGROUP:onafterElementDead(From, Event, To, Element)
|
||||
self:T(self.lid..string.format("Element dead %s.", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||
end
|
||||
|
||||
--- On after "Spawned" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -326,10 +329,8 @@ end
|
||||
function ARMYGROUP:onafterSpawned(From, Event, To)
|
||||
self:T(self.lid..string.format("Group spawned!"))
|
||||
|
||||
-- TODO
|
||||
self.traveldist=0
|
||||
self.traveltime=timer.getAbsTime()
|
||||
self.position=self:GetCoordinate()
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
if self.ai then
|
||||
|
||||
@ -369,9 +370,6 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
||||
-- Update route from this waypoint number onwards.
|
||||
n=n or self:GetWaypointIndexNext(self.adinfinitum)
|
||||
|
||||
-- Debug info.
|
||||
--self:I(self.lid..string.format("FF Update route n=%d", n))
|
||||
|
||||
-- Update waypoint tasks, i.e. inject WP tasks into waypoint table.
|
||||
self:_UpdateWaypointTasks(n)
|
||||
|
||||
@ -428,8 +426,6 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
||||
end
|
||||
|
||||
if wp.roaddist>100 and wp.action==ENUMS.Formation.Vehicle.OnRoad then
|
||||
env.info("FF Adding ON road waypoint")
|
||||
--wp.roadcoord:MarkToAll("Added Road waypoint")
|
||||
|
||||
-- Waypoint is actually off road!
|
||||
wp.action=ENUMS.Formation.Vehicle.OffRoad
|
||||
@ -439,17 +435,8 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
||||
table.insert(waypoints, wproad)
|
||||
end
|
||||
|
||||
--if wp.formation==ENUMS.Formation.Vehicle.OnRoad and wp.action~=ENUMS.Formation.Vehicle.OnRoad then --and not self.formationPerma~=ENUMS.Formation.Vehicle.OnRoad then
|
||||
--[[
|
||||
if wp.action==ENUMS.Formation.Vehicle.OnRoad and wp.roaddist>100 then
|
||||
env.info("FF Adding ON road waypoint")
|
||||
local wproad=wp.roadcoord:WaypointGround(wp.speed, ENUMS.Formation.Vehicle.OnRoad)
|
||||
table.insert(waypoints, wproad)
|
||||
end
|
||||
]]
|
||||
|
||||
-- Debug info.
|
||||
self:I(string.format("WP %d %s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.type, wp.speed, wp.alt, wp.action))
|
||||
self:T(string.format("WP %d %s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.type, wp.speed, wp.alt, wp.action))
|
||||
|
||||
-- Add waypoint.
|
||||
table.insert(waypoints, wp)
|
||||
@ -463,7 +450,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
|
||||
|
||||
if #waypoints>2 then
|
||||
|
||||
self:I(self.lid..string.format("Updateing route: WP %d-->%d-->%d (#%d), Speed=%.1f knots, Formation=%s",
|
||||
self:T(self.lid..string.format("Updateing route: WP %d-->%d-->%d (#%d), Speed=%.1f knots, Formation=%s",
|
||||
self.currentwp, n, #self.waypoints, #waypoints-2, UTILS.MpsToKnots(self.speedWp), tostring(self.option.Formation)))
|
||||
|
||||
-- Route group to all defined waypoints remaining.
|
||||
@ -552,31 +539,6 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed, Formation)
|
||||
|
||||
end
|
||||
|
||||
--- On after "Dead" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterDead(From, Event, To)
|
||||
self:I(self.lid..string.format("Group dead!"))
|
||||
|
||||
-- Delete waypoints so they are re-initialized at the next spawn.
|
||||
self.waypoints=nil
|
||||
self.groupinitialized=false
|
||||
|
||||
-- Cancel all mission.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
self:MissionCancel(mission)
|
||||
mission:GroupDead(self)
|
||||
|
||||
end
|
||||
|
||||
-- Stop
|
||||
self:Stop()
|
||||
end
|
||||
|
||||
--- On after Start event. Starts the ARMYGROUP FSM and event handlers.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -584,25 +546,14 @@ end
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterStop(From, Event, To)
|
||||
|
||||
-- Check if group is still alive.
|
||||
if self:IsAlive() then
|
||||
-- Destroy group. No event is generated.
|
||||
self.group:Destroy(false)
|
||||
end
|
||||
|
||||
-- Handle events:
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
-- Stop check timers.
|
||||
self.timerCheckZone:Stop()
|
||||
self.timerQueueUpdate:Stop()
|
||||
|
||||
-- Stop FSM scheduler.
|
||||
self.CallScheduler:Clear()
|
||||
|
||||
self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from database.")
|
||||
|
||||
-- Call OPSGROUP function.
|
||||
self:GetParent(self).onafterStop(self, From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -662,8 +613,8 @@ function ARMYGROUP:OnEventDead(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.lid..string.format("EVENT: Element %s dead ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
self:T(self.lid..string.format("EVENT: Element %s dead ==> destroyed", element.name))
|
||||
self:ElementDestroyed(element)
|
||||
end
|
||||
|
||||
end
|
||||
@ -685,7 +636,7 @@ function ARMYGROUP:OnEventRemoveUnit(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name))
|
||||
self:T(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
end
|
||||
|
||||
@ -734,19 +685,9 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
||||
else
|
||||
waypoint.roaddist=1000*1000 --1000 km.
|
||||
end
|
||||
|
||||
--[[
|
||||
if waypoint.roaddist>100 and waypoint.action==ENUMS.Formation.Vehicle.OnRoad then
|
||||
waypoint.formation=ENUMS.Formation.Vehicle.OnRoad
|
||||
waypoint.action=ENUMS.Formation.Vehicle.OffRoad
|
||||
else
|
||||
waypoint.formation=waypoint.action
|
||||
end
|
||||
]]
|
||||
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Adding waypoint UID=%d (index=%d), Speed=%.1f knots, Dist2Road=%d m, Action=%s", waypoint.uid, wpnumber, Speed, waypoint.roaddist, waypoint.action))
|
||||
self:T(self.lid..string.format("Adding waypoint UID=%d (index=%d), Speed=%.1f knots, Dist2Road=%d m, Action=%s", waypoint.uid, wpnumber, Speed, waypoint.roaddist, waypoint.action))
|
||||
|
||||
-- Update route.
|
||||
if Updateroute==nil or Updateroute==true then
|
||||
@ -836,18 +777,20 @@ function ARMYGROUP:_InitGroup()
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
if self.verbose>=1 then
|
||||
local text=string.format("Initialized Army Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
@ -885,7 +828,7 @@ function ARMYGROUP:SwitchFormation(Formation, Permanently)
|
||||
self:__UpdateRoute(-1, nil, nil, Formation)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Switching formation to %s (permanently=%s)", self.option.Formation, tostring(Permanently)))
|
||||
self:T(self.lid..string.format("Switching formation to %s (permanently=%s)", self.option.Formation, tostring(Permanently)))
|
||||
|
||||
end
|
||||
|
||||
@ -897,6 +840,7 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -704,6 +704,21 @@ end
|
||||
-- Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---- Update status.
|
||||
-- @param #FLIHGTGROUP self
|
||||
function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
||||
|
||||
if self:IsDead() then
|
||||
self:T(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
return false
|
||||
elseif self:IsStopped() then
|
||||
self:T(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- On after "Status" event.
|
||||
-- @param #FLIGHTGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -713,6 +728,9 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
---
|
||||
-- Detection
|
||||
@ -752,21 +770,27 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
end
|
||||
|
||||
---
|
||||
-- Elements
|
||||
-- Group
|
||||
---
|
||||
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
-- Short info.
|
||||
if self.verbose>=1 then
|
||||
|
||||
local nTaskTot, nTaskSched, nTaskWP=self:CountRemainingTasks()
|
||||
local nMissions=self:CountRemainingMissison()
|
||||
|
||||
|
||||
local text=string.format("Status %s [%d/%d]: Tasks=%d (%d,%d) Curr=%d, Missions=%s, Waypoint=%d/%d, Detected=%d, Home=%s, Destination=%s",
|
||||
fsmstate, #self.elements, #self.elements, nTaskTot, nTaskSched, nTaskWP, self.taskcurrent, nMissions, self.currentwp or 0, self.waypoints and #self.waypoints or 0,
|
||||
self.detectedunits:Count(), self.homebase and self.homebase:GetName() or "unknown", self.destbase and self.destbase:GetName() or "unknown")
|
||||
self:I(self.lid..text)
|
||||
|
||||
end
|
||||
|
||||
-- Element status.
|
||||
---
|
||||
-- Elements
|
||||
---
|
||||
|
||||
if self.verbose>=2 then
|
||||
local text="Elements:"
|
||||
for i,_element in pairs(self.elements) do
|
||||
@ -801,25 +825,17 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
-- Distance travelled
|
||||
---
|
||||
|
||||
if self.verbose>=3 and self:IsAlive() and self.position then
|
||||
|
||||
local time=timer.getAbsTime()
|
||||
|
||||
-- Current position.
|
||||
local position=self:GetCoordinate()
|
||||
if self.verbose>=3 and self:IsAlive() then
|
||||
|
||||
-- Travelled distance since last check.
|
||||
local ds=self.position:Get3DDistance(position)
|
||||
local ds=self.travelds
|
||||
|
||||
-- Time interval.
|
||||
local dt=time-self.traveltime
|
||||
local dt=self.dTpositionUpdate
|
||||
|
||||
-- Speed.
|
||||
local v=ds/dt
|
||||
|
||||
-- Add up travelled distance.
|
||||
self.traveldist=self.traveldist+ds
|
||||
|
||||
|
||||
-- Max fuel time remaining.
|
||||
local TmaxFuel=math.huge
|
||||
@ -852,11 +868,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
|
||||
-- Log outut.
|
||||
self:I(self.lid..string.format("Travelled ds=%.1f km dt=%.1f s ==> v=%.1f knots. Fuel left for %.1f min", self.traveldist/1000, dt, UTILS.MpsToKnots(v), TmaxFuel/60))
|
||||
|
||||
|
||||
-- Update parameters.
|
||||
self.traveltime=time
|
||||
self.position=position
|
||||
|
||||
end
|
||||
|
||||
---
|
||||
@ -911,8 +923,6 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Events
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -1390,10 +1400,8 @@ end
|
||||
function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
||||
self:T(self.lid..string.format("Flight spawned"))
|
||||
|
||||
-- TODO: general routine in opsgroup
|
||||
self.traveldist=0
|
||||
self.traveltime=timer.getAbsTime()
|
||||
self.position=self:GetCoordinate()
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
if self.ai then
|
||||
|
||||
@ -1577,7 +1585,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function FLIGHTGROUP:onafterLandedAt(From, Event, To)
|
||||
self:I(self.lid..string.format("Flight landed at"))
|
||||
self:T(self.lid..string.format("Flight landed at"))
|
||||
end
|
||||
|
||||
|
||||
@ -2434,6 +2442,17 @@ function FLIGHTGROUP:onafterStop(From, Event, To)
|
||||
--self.group:Destroy(false)
|
||||
end
|
||||
|
||||
-- Handle events:
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.EngineStartup)
|
||||
self:UnHandleEvent(EVENTS.Takeoff)
|
||||
self:UnHandleEvent(EVENTS.Land)
|
||||
self:UnHandleEvent(EVENTS.EngineShutdown)
|
||||
self:UnHandleEvent(EVENTS.PilotDead)
|
||||
self:UnHandleEvent(EVENTS.Ejection)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
-- Remove flight from data base.
|
||||
_DATABASE.FLIGHTGROUPS[self.groupname]=nil
|
||||
|
||||
|
||||
@ -290,7 +290,7 @@ function NAVYGROUP:CreateTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
||||
return self
|
||||
end
|
||||
if Tstop<=Tnow then
|
||||
self:I(string.format("WARNING: Into wind stop time %s already over. Tnow=%s! Input rejected.", UTILS.SecondsToClock(Tstop), UTILS.SecondsToClock(Tnow)))
|
||||
self:E(string.format("WARNING: Into wind stop time %s already over. Tnow=%s! Input rejected.", UTILS.SecondsToClock(Tstop), UTILS.SecondsToClock(Tnow)))
|
||||
return self
|
||||
end
|
||||
|
||||
@ -389,10 +389,10 @@ end
|
||||
function NAVYGROUP:onbeforeStatus(From, Event, To)
|
||||
|
||||
if self:IsDead() then
|
||||
self:I(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
self:T(self.lid..string.format("Onbefore Status DEAD ==> false"))
|
||||
return false
|
||||
elseif self:IsStopped() then
|
||||
self:I(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
self:T(self.lid..string.format("Onbefore Status STOPPED ==> false"))
|
||||
return false
|
||||
end
|
||||
|
||||
@ -450,7 +450,7 @@ function NAVYGROUP:onafterStatus(From, Event, To)
|
||||
self:_CheckTurnsIntoWind()
|
||||
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
self:_CheckStuck()
|
||||
|
||||
if self.verbose>=1 then
|
||||
|
||||
@ -518,19 +518,6 @@ function NAVYGROUP:onafterElementSpawned(From, Event, To, Element)
|
||||
|
||||
end
|
||||
|
||||
--- On after "ElementDead" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #NAVYGROUP.Element Element The group element.
|
||||
function NAVYGROUP:onafterElementDead(From, Event, To, Element)
|
||||
self:T(self.lid..string.format("Element dead %s.", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||
end
|
||||
|
||||
--- On after "Spawned" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -539,10 +526,8 @@ end
|
||||
function NAVYGROUP:onafterSpawned(From, Event, To)
|
||||
self:T(self.lid..string.format("Group spawned!"))
|
||||
|
||||
-- TODO
|
||||
self.traveldist=0
|
||||
self.traveltime=timer.getAbsTime()
|
||||
self.position=self:GetCoordinate()
|
||||
-- Update position.
|
||||
self:_UpdatePosition()
|
||||
|
||||
if self.ai then
|
||||
|
||||
@ -571,9 +556,6 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
-- Get orientation.
|
||||
self.Corientlast=self.group:GetUnit(1):GetOrientationX()
|
||||
|
||||
-- Update route.
|
||||
self:Cruise()
|
||||
|
||||
@ -742,7 +724,7 @@ function NAVYGROUP:onafterTurnIntoWind(From, Event, To, IntoWind)
|
||||
local speed=math.max(IntoWind.Speed-vwind, 2)
|
||||
|
||||
-- Debug info.
|
||||
self:I(self.lid..string.format("Steaming into wind: Heading=%03d Speed=%.1f Vwind=%.1f Vtot=%.1f knots, Tstart=%d Tstop=%d", IntoWind.Heading, speed, vwind, speed+vwind, IntoWind.Tstart, IntoWind.Tstop))
|
||||
self:T(self.lid..string.format("Steaming into wind: Heading=%03d Speed=%.1f Vwind=%.1f Vtot=%.1f knots, Tstart=%d Tstop=%d", IntoWind.Heading, speed, vwind, speed+vwind, IntoWind.Tstart, IntoWind.Tstop))
|
||||
|
||||
local distance=UTILS.NMToMeters(1000)
|
||||
|
||||
@ -840,7 +822,7 @@ function NAVYGROUP:onafterDive(From, Event, To, Depth, Speed)
|
||||
|
||||
Depth=Depth or 50
|
||||
|
||||
self:I(self.lid..string.format("Diving to %d meters", Depth))
|
||||
self:T(self.lid..string.format("Diving to %d meters", Depth))
|
||||
|
||||
self.depth=Depth
|
||||
|
||||
@ -888,35 +870,10 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #number Distance Distance in meters where obstacle was detected.
|
||||
function NAVYGROUP:onafterCollisionWarning(From, Event, To, Distance)
|
||||
self:I(self.lid..string.format("Iceberg ahead in %d meters!", Distance or -1))
|
||||
self:T(self.lid..string.format("Iceberg ahead in %d meters!", Distance or -1))
|
||||
self.collisionwarning=true
|
||||
end
|
||||
|
||||
--- On after "Dead" event.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function NAVYGROUP:onafterDead(From, Event, To)
|
||||
self:I(self.lid..string.format("Group dead!"))
|
||||
|
||||
-- Delete waypoints so they are re-initialized at the next spawn.
|
||||
self.waypoints=nil
|
||||
self.groupinitialized=false
|
||||
|
||||
-- Cancel all mission.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
self:MissionCancel(mission)
|
||||
mission:GroupDead(self)
|
||||
|
||||
end
|
||||
|
||||
-- Stop
|
||||
self:Stop()
|
||||
end
|
||||
|
||||
--- On after Start event. Starts the NAVYGROUP FSM and event handlers.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -924,25 +881,14 @@ end
|
||||
-- @param #string To To state.
|
||||
function NAVYGROUP:onafterStop(From, Event, To)
|
||||
|
||||
-- Check if group is still alive.
|
||||
if self:IsAlive() then
|
||||
-- Destroy group. No event is generated.
|
||||
self.group:Destroy(false)
|
||||
end
|
||||
|
||||
-- Handle events:
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
-- Stop check timers.
|
||||
self.timerCheckZone:Stop()
|
||||
self.timerQueueUpdate:Stop()
|
||||
|
||||
-- Stop FSM scheduler.
|
||||
self.CallScheduler:Clear()
|
||||
|
||||
self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from database.")
|
||||
|
||||
-- Call OPSGROUP function.
|
||||
self:GetParent(self).onafterStop(self, From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -1002,8 +948,8 @@ function NAVYGROUP:OnEventDead(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.lid..string.format("EVENT: Element %s dead ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
self:T(self.lid..string.format("EVENT: Element %s dead ==> destroyed", element.name))
|
||||
self:ElementDestroyed(element)
|
||||
end
|
||||
|
||||
end
|
||||
@ -1025,7 +971,7 @@ function NAVYGROUP:OnEventRemoveUnit(EventData)
|
||||
local element=self:GetElementByName(unitname)
|
||||
|
||||
if element then
|
||||
self:I(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name))
|
||||
self:T(self.lid..string.format("EVENT: Element %s removed ==> dead", element.name))
|
||||
self:ElementDead(element)
|
||||
end
|
||||
|
||||
@ -1173,18 +1119,20 @@ function NAVYGROUP:_InitGroup()
|
||||
self.actype=unit:GetTypeName()
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d/T=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles, self.ammo.Torpedos)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
if self.verbose>=1 then
|
||||
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
|
||||
text=text..string.format("Unit type = %s\n", self.actype)
|
||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||
text=text..string.format("Elements = %d\n", #self.elements)
|
||||
text=text..string.format("Waypoints = %d\n", #self.waypoints)
|
||||
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radio.On))
|
||||
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d/T=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles, self.ammo.Torpedos)
|
||||
text=text..string.format("FSM state = %s\n", self:GetState())
|
||||
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
|
||||
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-- Init done.
|
||||
self.groupinitialized=true
|
||||
@ -1269,7 +1217,7 @@ function NAVYGROUP:_CheckFreePath(DistanceMax, dx)
|
||||
local los=LoS(x)
|
||||
|
||||
-- Debug message.
|
||||
self:I(self.lid..string.format("N=%d: xmin=%.1f xmax=%.1f x=%.1f d=%.3f los=%s", N, xmin, xmax, x, d, tostring(los)))
|
||||
self:T2(self.lid..string.format("N=%d: xmin=%.1f xmax=%.1f x=%.1f d=%.3f los=%s", N, xmin, xmax, x, d, tostring(los)))
|
||||
|
||||
if los and d<=eps then
|
||||
return x
|
||||
@ -1291,68 +1239,6 @@ function NAVYGROUP:_CheckFreePath(DistanceMax, dx)
|
||||
return check()
|
||||
end
|
||||
|
||||
--- Check for possible collisions between two coordinates.
|
||||
-- @param #NAVYGROUP self
|
||||
-- @param Core.Point#COORDINATE coordto Coordinate to which the collision is check.
|
||||
-- @param Core.Point#COORDINATE coordfrom Coordinate from which the collision is check.
|
||||
-- @return #boolean If true, surface type ahead is not deep water.
|
||||
-- @return #number Max free distance in meters.
|
||||
function NAVYGROUP:_CheckCollisionCoord(coordto, coordfrom)
|
||||
|
||||
-- Increment in meters.
|
||||
local dx=100
|
||||
|
||||
-- From coordinate. Default 500 in front of the carrier.
|
||||
local d=0
|
||||
if coordfrom then
|
||||
d=0
|
||||
else
|
||||
d=250
|
||||
coordfrom=self:GetCoordinate():Translate(d, self:GetHeading())
|
||||
end
|
||||
|
||||
-- Distance between the two coordinates.
|
||||
local dmax=coordfrom:Get2DDistance(coordto)
|
||||
|
||||
-- Direction.
|
||||
local direction=coordfrom:HeadingTo(coordto)
|
||||
|
||||
-- Scan path between the two coordinates.
|
||||
local clear=true
|
||||
while d<=dmax do
|
||||
|
||||
-- Check point.
|
||||
local cp=coordfrom:Translate(d, direction)
|
||||
|
||||
-- Check if surface type is water.
|
||||
if not cp:IsSurfaceTypeWater() then
|
||||
|
||||
-- Debug mark points.
|
||||
if self.Debug or true then
|
||||
local st=cp:GetSurfaceType()
|
||||
cp:MarkToAll(string.format("Collision check surface type %d", st))
|
||||
end
|
||||
|
||||
-- Collision WARNING!
|
||||
clear=false
|
||||
break
|
||||
end
|
||||
|
||||
-- Increase distance.
|
||||
d=d+dx
|
||||
end
|
||||
|
||||
local text=""
|
||||
if clear then
|
||||
text=string.format("Path into direction %03d° is clear for the next %.1f NM.", direction, UTILS.MetersToNM(d))
|
||||
else
|
||||
text=string.format("Detected obstacle at distance %.1f NM into direction %03d°.", UTILS.MetersToNM(d), direction)
|
||||
end
|
||||
self:T(self.lid..text)
|
||||
|
||||
return not clear, d
|
||||
end
|
||||
|
||||
--- Check if group is turning.
|
||||
-- @param #NAVYGROUP self
|
||||
function NAVYGROUP:_CheckTurning()
|
||||
@ -1365,7 +1251,7 @@ function NAVYGROUP:_CheckTurning()
|
||||
local vNew=self.orientX --unit:GetOrientationX()
|
||||
|
||||
-- Last orientation from 30 seconds ago.
|
||||
local vLast=self.orientXLast --self.Corientlast or vNew
|
||||
local vLast=self.orientXLast
|
||||
|
||||
-- We only need the X-Z plane.
|
||||
vNew.y=0 ; vLast.y=0
|
||||
@ -1373,9 +1259,6 @@ function NAVYGROUP:_CheckTurning()
|
||||
-- Angle between current heading and last time we checked ~30 seconds ago.
|
||||
local deltaLast=math.deg(math.acos(UTILS.VecDot(vNew,vLast)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vLast)))
|
||||
|
||||
-- Last orientation becomes new orientation
|
||||
--self.Corientlast=vNew
|
||||
|
||||
-- Carrier is turning when its heading changed by at least two degrees since last check.
|
||||
local turning=math.abs(deltaLast)>=2
|
||||
|
||||
@ -1399,33 +1282,6 @@ function NAVYGROUP:_CheckTurning()
|
||||
|
||||
end
|
||||
|
||||
--- Check if group got stuck.
|
||||
-- @param #NAVYGROUP self
|
||||
function NAVYGROUP:_CheckStuck()
|
||||
|
||||
if self:IsHolding() then
|
||||
return
|
||||
end
|
||||
|
||||
local holdtime=0
|
||||
if self.holdtimestamp then
|
||||
holdtime=timer.getTime()-self.holdtimestamp
|
||||
end
|
||||
|
||||
local ExpectedSpeed=self:GetExpectedSpeed()
|
||||
|
||||
local speed=self:GetVelocity()
|
||||
|
||||
if speed<0.5 and ExpectedSpeed>0 then
|
||||
if not self.holdtimestamp then
|
||||
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed))
|
||||
self.holdtimestamp=timer.getTime()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Check queued turns into wind.
|
||||
-- @param #NAVYGROUP self
|
||||
|
||||
@ -54,8 +54,14 @@
|
||||
-- @field #number Ndestroyed Number of destroyed units.
|
||||
--
|
||||
-- @field Core.Point#COORDINATE coordinate Current coordinate.
|
||||
-- @field Core.Point#COORDINATE position Position of the group at last status check.
|
||||
-- @field #number traveldist Distance traveled in meters. This is a lower bound!
|
||||
--
|
||||
-- @field DCS#Vec3 position Position of the group at last status check.
|
||||
-- @field DCS#Vec3 positionLast Backup of last position vec to monitor changes.
|
||||
-- @field #number heading Heading of the group at last status check.
|
||||
-- @field #number headingLast Backup of last heading to monitor changes.
|
||||
-- @field DCS#Vec3 orientX Orientation at last status check.
|
||||
-- @field DCS#Vec3 orientXLast Backup of last orientation to monitor changes.
|
||||
-- @field #number traveldist Distance traveled in meters. This is a lower bound.
|
||||
-- @field #number traveltime Time.
|
||||
--
|
||||
-- @field Core.Astar#ASTAR Astar path finding.
|
||||
@ -590,7 +596,7 @@ function OPSGROUP:Destroy(Delay)
|
||||
|
||||
if DCSGroup then
|
||||
|
||||
self:I(self.lid.."Destroying group")
|
||||
self:T(self.lid.."Destroying group")
|
||||
|
||||
-- Destroy DCS group.
|
||||
DCSGroup:destroy()
|
||||
@ -650,8 +656,9 @@ end
|
||||
|
||||
--- Get current coordinate of the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #boolean NewObject Create a new coordiante object.
|
||||
-- @return Core.Point#COORDINATE The coordinate (of the first unit) of the group.
|
||||
function OPSGROUP:GetCoordinate()
|
||||
function OPSGROUP:GetCoordinate(NewObject)
|
||||
|
||||
local vec3=self:GetVec3()
|
||||
|
||||
@ -663,7 +670,11 @@ function OPSGROUP:GetCoordinate()
|
||||
self.coordinate.y=vec3.y
|
||||
self.coordinate.z=vec3.z
|
||||
|
||||
return self.coordinate
|
||||
if NewObject then
|
||||
local coord=COORDINATE:NewFromCoordinate(self.coordinate)
|
||||
else
|
||||
return self.coordinate
|
||||
end
|
||||
else
|
||||
self:E(self.lid.."WARNING: Group is not alive. Cannot get coordinate!")
|
||||
end
|
||||
@ -725,6 +736,41 @@ function OPSGROUP:GetHeading()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get current orientation of the first unit in the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return DCS#Vec3 Orientation X parallel to where the "nose" is pointing.
|
||||
-- @return DCS#Vec3 Orientation Y pointing "upwards".
|
||||
-- @return DCS#Vec3 Orientation Z perpendicular to the "nose".
|
||||
function OPSGROUP:GetOrientation()
|
||||
|
||||
if self:IsExist() then
|
||||
|
||||
local unit=self:GetDCSUnit()
|
||||
|
||||
if unit then
|
||||
|
||||
local pos=unit:getPosition()
|
||||
|
||||
return pos.x, pos.y, pos.z
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."WARNING: Group does not exist. Cannot get orientation!")
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get current orientation of the first unit in the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return DCS#Vec3 Orientation X parallel to where the "nose" is pointing.
|
||||
function OPSGROUP:GetOrientationX()
|
||||
|
||||
local X,Y,Z=self:GetOrientation()
|
||||
|
||||
return X
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Check if task description is unique.
|
||||
@ -2658,7 +2704,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #OPSGROUP.Element Element The flight group element.
|
||||
function OPSGROUP:onafterElementDestroyed(From, Event, To, Element)
|
||||
self:I(self.lid..string.format("Element destroyed %s", Element.name))
|
||||
self:T(self.lid..string.format("Element destroyed %s", Element.name))
|
||||
|
||||
-- Cancel all missions.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
@ -2683,7 +2729,7 @@ end
|
||||
-- @param #string To To state.
|
||||
-- @param #OPSGROUP.Element Element The flight group element.
|
||||
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||
self:I(self.lid..string.format("Element dead %s", Element.name))
|
||||
self:T(self.lid..string.format("Element dead %s", Element.name))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||
@ -2695,7 +2741,7 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function OPSGROUP:onafterDead(From, Event, To)
|
||||
self:T(self.lid..string.format("Flight dead!"))
|
||||
self:T(self.lid..string.format("Group dead!"))
|
||||
|
||||
-- Delete waypoints so they are re-initialized at the next spawn.
|
||||
self.waypoints=nil
|
||||
@ -2710,8 +2756,8 @@ function OPSGROUP:onafterDead(From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
-- Stop
|
||||
self:Stop()
|
||||
-- Stop in a sec.
|
||||
self:__Stop(-1)
|
||||
end
|
||||
|
||||
--- On after "Stop" event.
|
||||
@ -2720,17 +2766,6 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function OPSGROUP:onafterStop(From, Event, To)
|
||||
|
||||
-- Handle events:
|
||||
self:UnHandleEvent(EVENTS.Birth)
|
||||
self:UnHandleEvent(EVENTS.EngineStartup)
|
||||
self:UnHandleEvent(EVENTS.Takeoff)
|
||||
self:UnHandleEvent(EVENTS.Land)
|
||||
self:UnHandleEvent(EVENTS.EngineShutdown)
|
||||
self:UnHandleEvent(EVENTS.PilotDead)
|
||||
self:UnHandleEvent(EVENTS.Ejection)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.RemoveUnit)
|
||||
|
||||
-- Stop check timers.
|
||||
self.timerCheckZone:Stop()
|
||||
@ -3915,26 +3950,43 @@ end
|
||||
|
||||
--- Check if all elements of the group have the same status (or are dead).
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string unitname Name of unit.
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:_UpdatePosition()
|
||||
|
||||
if self:IsAlive() then
|
||||
|
||||
self.positionLast=self.position or self:GetCoordinate()
|
||||
-- Backup last state to monitor differences.
|
||||
self.positionLast=self.position or self:GetVec3()
|
||||
self.headingLast=self.heading or self:GetHeading()
|
||||
self.orientXLast=self.orientX or self.group:GetUnit(1):GetOrientationX()
|
||||
self.orientXLast=self.orientX or self:GetOrientationX()
|
||||
self.velocityLast=self.velocity or self.group:GetVelocityMPS()
|
||||
|
||||
self.position=self:GetCoordinate()
|
||||
-- Current state.
|
||||
self.position=self:GetVec3()
|
||||
self.heading=self:GetHeading()
|
||||
self.orientX=self.group:GetUnit(1):GetOrientationX()
|
||||
self.velocity=self.group:GetVelocityMPS()
|
||||
self.orientX=self:GetOrientationX()
|
||||
self.velocity=self:GetVelocity()
|
||||
|
||||
self.dTpositionUpdate=self.TpositionUpdate and self.TpositionUpdate-timer.getAbsTime() or 0
|
||||
self.TpositionUpdate=timer.getAbsTime()
|
||||
-- Update time.
|
||||
local Tnow=timer.getTime()
|
||||
self.dTpositionUpdate=self.TpositionUpdate and Tnow-self.TpositionUpdate or 0
|
||||
self.TpositionUpdate=Tnow
|
||||
|
||||
if not self.traveldist then
|
||||
self.traveldist=0
|
||||
end
|
||||
|
||||
self.travelds=UTILS.VecNorm(UTILS.VecSubstract(self.position, self.positionLast))
|
||||
|
||||
-- Add up travelled distance.
|
||||
|
||||
self.traveldist=self.traveldist+self.travelds
|
||||
|
||||
env.info(string.format("FF Traveled %.1f m", self.traveldist))
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check if all elements of the group have the same status (or are dead).
|
||||
@ -4483,6 +4535,56 @@ function OPSGROUP:_MissileCategoryName(categorynumber)
|
||||
return cat
|
||||
end
|
||||
|
||||
--- Check if group got stuck.
|
||||
-- @param #OPSGROUP self
|
||||
function OPSGROUP:_CheckStuck()
|
||||
|
||||
-- Holding means we are not stuck.
|
||||
if self:IsHolding() then
|
||||
return
|
||||
end
|
||||
|
||||
-- Current time.
|
||||
local Tnow=timer.getTime()
|
||||
|
||||
-- Expected speed in m/s.
|
||||
local ExpectedSpeed=self:GetExpectedSpeed()
|
||||
|
||||
-- Current speed in m/s.
|
||||
local speed=self:GetVelocity()
|
||||
|
||||
-- Check speed.
|
||||
if speed<0.5 then
|
||||
|
||||
if ExpectedSpeed>0 and not self.stuckTimestamp then
|
||||
self:T2(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed))
|
||||
self.stuckTimestamp=Tnow
|
||||
self.stuckVec3=self:GetVec3()
|
||||
end
|
||||
|
||||
else
|
||||
-- Moving (again).
|
||||
self.stuckTimestamp=nil
|
||||
end
|
||||
|
||||
-- Somehow we are not moving...
|
||||
if self.stuckTimestamp then
|
||||
|
||||
-- Time we are holding.
|
||||
local holdtime=Tnow-self.stuckTimestamp
|
||||
|
||||
if holdtime>=5*60 then
|
||||
|
||||
self:E(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
|
||||
|
||||
--TODO: Stuck event!
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -62,7 +62,7 @@
|
||||
-- @field #SQUADRON
|
||||
SQUADRON = {
|
||||
ClassName = "SQUADRON",
|
||||
verbose = 3,
|
||||
verbose = 0,
|
||||
lid = nil,
|
||||
name = nil,
|
||||
templatename = nil,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user