diff --git a/Moose Development/Moose/AI/AI_A2A_Cap.lua b/Moose Development/Moose/AI/AI_A2A_Cap.lua index ae4171ae5..a5bee30e4 100644 --- a/Moose Development/Moose/AI/AI_A2A_Cap.lua +++ b/Moose Development/Moose/AI/AI_A2A_Cap.lua @@ -119,7 +119,7 @@ function AI_A2A_CAP:New2( AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAlti local AI_Air = AI_AIR:New( AICap ) local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType ) - local self = BASE:Inherit( self, AI_Air_Engage ) + local self = BASE:Inherit( self, AI_Air_Engage ) --#AI_A2A_CAP self:SetFuelThreshold( .2, 60 ) self:SetDamageThreshold( 0.4 ) diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index eeb9053b7..5fbd84349 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -707,13 +707,14 @@ end function AI_AIR:onafterRefuel( AIGroup, From, Event, To ) self:F( { AIGroup, From, Event, To } ) - if AIGroup and AIGroup:IsAlive() then + + -- Get tanker group. local Tanker = GROUP:FindByName( self.TankerName ) - if Tanker:IsAlive() and Tanker:IsAirPlane() then + if Tanker and Tanker:IsAlive() and Tanker:IsAirPlane() then - self:I( "Group " .. self.Controllable:GetName() .. " ... Refuelling! ( " .. self:GetState() .. "), at tanker " .. self.TankerName ) + self:I( "Group " .. self.Controllable:GetName() .. " ... Refuelling! State=" .. self:GetState() .. ", Refuelling tanker " .. self.TankerName ) local RefuelRoute = {} @@ -724,40 +725,43 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To ) local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) --- Create a route point of type air. - local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToRefuelSpeed, - true - ) + local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true) - --- Create a route point of type air. - local ToRefuelRoutePoint = FromRefuelCoord:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToRefuelSpeed, - true - ) + --- Create a route point of type air. NOT used! + local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true) self:F( { ToRefuelSpeed = ToRefuelSpeed } ) RefuelRoute[#RefuelRoute+1] = FromRefuelRoutePoint - --RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint + RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint AIGroup:OptionROEHoldFire() AIGroup:OptionROTEvadeFire() + + -- Get Class name for .Resume function + local classname=self:GetClassName() + + -- AI_A2A_CAP can call this function but does not have a .Resume function. Try to fix. + if classname=="AI_A2A_CAP" then + classname="AI_AIR_PATROL" + end + + env.info("FF refueling classname="..classname) local Tasks = {} Tasks[#Tasks+1] = AIGroup:TaskRefueling() - Tasks[#Tasks+1] = AIGroup:TaskFunction( self:GetClassName() .. ".Resume", self ) + Tasks[#Tasks+1] = AIGroup:TaskFunction( classname .. ".Resume", self ) RefuelRoute[#RefuelRoute].task = AIGroup:TaskCombo( Tasks ) AIGroup:Route( RefuelRoute, self.TaskDelay ) + else + + -- No tanker defined ==> RTB! self:RTB() + end + end end diff --git a/Moose Development/Moose/AI/AI_Air_Patrol.lua b/Moose Development/Moose/AI/AI_Air_Patrol.lua index 6458c80d1..32bd99cea 100644 --- a/Moose Development/Moose/AI/AI_Air_Patrol.lua +++ b/Moose Development/Moose/AI/AI_Air_Patrol.lua @@ -356,7 +356,6 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To ) local taskOrbit=AIPatrol:TaskOrbit(c1, altitude, UTILS.KmphToMps(speedkmh), c2) -- Task function to redo the patrol at other random position. - --local taskPatrol=AIPatrol:TaskFunction("AI_A2A_PATROL.PatrolRoute", self) local taskPatrol=AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self) -- Controlled task with task condition. diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index d20f068ee..e95eac8ce 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -298,7 +298,8 @@ end -- -- -- @param #BASE self --- @param #BASE Child is the Child class from which the Parent class needs to be retrieved. +-- @param #BASE Child This is the Child class from which the Parent class needs to be retrieved. +-- @param #BASE FromClass (Optional) The class from which to get the parent. -- @return #BASE function BASE:GetParent( Child, FromClass ) diff --git a/Moose Development/Moose/Core/ScheduleDispatcher.lua b/Moose Development/Moose/Core/ScheduleDispatcher.lua index 01b8a7000..bfd1dabb4 100644 --- a/Moose Development/Moose/Core/ScheduleDispatcher.lua +++ b/Moose Development/Moose/Core/ScheduleDispatcher.lua @@ -336,7 +336,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID ) Schedule.ScheduleID = nil else - self:E(string.format("Error no ScheduleID for CallID=%s", tostring(CallID))) + self:T(string.format("Error no ScheduleID for CallID=%s", tostring(CallID))) end else diff --git a/Moose Development/Moose/Functional/Artillery.lua b/Moose Development/Moose/Functional/Artillery.lua index d1742c271..f5233e3b0 100644 --- a/Moose Development/Moose/Functional/Artillery.lua +++ b/Moose Development/Moose/Functional/Artillery.lua @@ -693,7 +693,7 @@ ARTY.db={ --- Arty script version. -- @field #string version -ARTY.version="1.1.6" +ARTY.version="1.1.7" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -3848,26 +3848,23 @@ end -- @param #boolean final True if it is the final waypoint. function ARTY._PassingWaypoint(group, arty, i, final) - -- Debug message. - local text=string.format("%s, passing waypoint %d.", group:GetName(), i) - if final then - text=string.format("%s, arrived at destination.", group:GetName()) - end - arty:T(self.lid..text) + if group and group:IsAlive() then + + local groupname=tostring(group:GetName()) - --[[ - if final then - MESSAGE:New(text, 10):ToCoalitionIf(group:GetCoalition(), arty.Debug or arty.report) - else - MESSAGE:New(text, 10):ToAllIf(arty.Debug) + -- Debug message. + local text=string.format("%s, passing waypoint %d.", groupname, i) + if final then + text=string.format("%s, arrived at destination.", groupname) + end + arty:T(arty.lid..text) + + -- Arrived event. + if final and arty.groupname==groupname then + arty:Arrived() + end + end - ]] - - -- Arrived event. - if final and arty.groupname==group:GetName() then - arty:Arrived() - end - end --- Relocate to another position, e.g. after an engagement to avoid couter strikes. diff --git a/Moose Development/Moose/Functional/Suppression.lua b/Moose Development/Moose/Functional/Suppression.lua index 098efeb20..073c009bd 100644 --- a/Moose Development/Moose/Functional/Suppression.lua +++ b/Moose Development/Moose/Functional/Suppression.lua @@ -287,7 +287,7 @@ SUPPRESSION.MenuF10=nil --- PSEUDOATC version. -- @field #number version -SUPPRESSION.version="0.9.1" +SUPPRESSION.version="0.9.2" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -363,6 +363,7 @@ function SUPPRESSION:New(group) self:AddTransition("FallingBack", "FightBack", "CombatReady") self:AddTransition("Retreating", "Retreated", "Retreated") self:AddTransition("*", "Dead", "*") + self:AddTransition("*", "Stop", "Stopped") self:AddTransition("TakingCover", "Hit", "TakingCover") self:AddTransition("FallingBack", "Hit", "FallingBack") @@ -874,28 +875,14 @@ function SUPPRESSION:StatusReport(message) local roe=self.CurrentROE local state=self.CurrentAlarmState local life_min, life_max, life_ave, life_ave0, groupstrength=self:_GetLife() - local ammotot=self.Controllable:GetAmmunition() + local ammotot=group:GetAmmunition() - --[[ - local text=string.format("Status of group %s\n", name) - text=text..string.format("Number of units: %d of %d\n", nunits, self.IniGroupStrength) - text=text..string.format("Current state: %s\n", self:GetState()) - text=text..string.format("ROE: %s\n", roe) - text=text..string.format("Alarm state: %s\n", state) - text=text..string.format("Hits taken: %d\n", self.Nhit) - text=text..string.format("Life min: %3.0f\n", life_min) - text=text..string.format("Life max: %3.0f\n", life_max) - text=text..string.format("Life ave: %3.0f\n", life_ave) - text=text..string.format("Life ave0: %3.0f\n", life_ave0) - text=text..string.format("Ammo tot: %d\n", at) - text=text..string.format("Group strength: %3.0f", groupstrength) - ]] - - local text=string.format("State %s, Units=%d/%d, ROE=%s Alarm State=%s, Hits=%d, Life=%d/%d/%d/%d, Ammo=%d", + + local text=string.format("State %s, Units=%d/%d, ROE=%s, AlarmState=%s, Hits=%d, Life(min/max/ave/ave0)=%d/%d/%d/%d, Total Ammo=%d", self:GetState(), nunits, self.IniGroupStrength, self.CurrentROE, self.CurrentAlarmState, self.Nhit, life_min, life_max, life_ave, life_ave0, ammotot) MESSAGE:New(text, 10):ToAllIf(message or self.Debug) - self:I(self.lid.."\n"..text) + self:I(self.lid..text) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -983,7 +970,6 @@ function SUPPRESSION:onafterStart(Controllable, From, Event, To) world.addEventHandler(self) end - self:__Status(-1) end @@ -995,23 +981,40 @@ end -- @param #string To To state. function SUPPRESSION:onafterStatus(Controllable, From, Event, To) - --local text=string.format("State=%s, ROE %d, Life=%.1f", Controllable:GetName()) - --MESSAGE:New(text, 10):ToAllIf(self.Debug) - + -- Suppressed group. local group=self.Controllable --Wrapper.Group#GROUP - local n=group:GetAmmunition() + -- Check if group object exists. + if group then - self:StatusReport(false) - - -- Retreat if completely out of ammo and retreat zone defined. - if n==0 and self.RetreatZone then - - self:Retreat() + -- Number of alive units. + local nunits=group:CountAliveUnits() - end + -- Check if there are units. + if nunits>0 then + + -- Retreat if completely out of ammo and retreat zone defined. + local nammo=group:GetAmmunition() + if nammo==0 and self.RetreatZone then + self:Retreat() + end - self:__Status(-30) + -- Status report. + self:StatusReport(false) + + -- Call status again if not "Stopped". + if self:GetState()~="Stopped" then + self:__Status(-30) + end + + else + self:Stop() + end + + else + self:Stop() + end + end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1409,27 +1412,54 @@ end function SUPPRESSION:onafterDead(Controllable, From, Event, To) self:_EventFromTo("onafterDead", Event, From, To) - -- Number of units left in the group. - local nunits=#self.Controllable:GetUnits() - - local text=string.format("Group %s: One of our units just died! %d units left.", self.Controllable:GetName(), nunits) - MESSAGE:New(text, 10):ToAllIf(self.Debug) - self:T(self.lid..text) - - -- Go to stop state. - if nunits==0 then - self:T(self.lid..string.format("Stopping SUPPRESSION for group %s.", Controllable:GetName())) - self:Stop() - if self.mooseevents then - self:UnHandleEvent(EVENTS.Dead) - self:UnHandleEvent(EVENTS.Hit) - else - world.removeEventHandler(self) + local group=self.Controllable --Wrapper.Group#GROUP + + if group then + + -- Number of units left in the group. + local nunits=group:CountAliveUnits() + + local text=string.format("Group %s: One of our units just died! %d units left.", self.Controllable:GetName(), nunits) + MESSAGE:New(text, 10):ToAllIf(self.Debug) + self:T(self.lid..text) + + -- Go to stop state. + if nunits==0 then + self:Stop() end + + else + self:Stop() end end +--- After "Stop" event. +-- @param #SUPPRESSION self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group. +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function SUPPRESSION:onafterStop(Controllable, From, Event, To) + self:_EventFromTo("onafterStop", Event, From, To) + + local text=string.format("Stopping SUPPRESSION for group %s", self.Controllable:GetName()) + MESSAGE:New(text, 10):ToAllIf(self.Debug) + self:I(self.lid..text) + + -- Clear all pending schedules + self.CallScheduler:Clear() + + if self.mooseevents then + self:UnHandleEvent(EVENTS.Dead) + self:UnHandleEvent(EVENTS.Hit) + else + world.removeEventHandler(self) + end + +end + + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Event Handler ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1623,95 +1653,101 @@ function SUPPRESSION:_Run(fin, speed, formation, wait) local group=self.Controllable -- Wrapper.Controllable#CONTROLLABLE - -- Clear all tasks. - group:ClearTasks() + if group and group:IsAlive() then - -- Current coordinates of group. - local ini=group:GetCoordinate() - - -- Distance between current and final point. - local dist=ini:Get2DDistance(fin) - - -- Heading from ini to fin. - local heading=self:_Heading(ini, fin) - - -- Number of waypoints. - local nx - if dist <= 50 then - nx=2 - elseif dist <= 100 then - nx=3 - elseif dist <= 500 then - nx=4 - else - nx=5 - end - - -- Number of intermediate waypoints. - local dx=dist/(nx-1) + -- Clear all tasks. + group:ClearTasks() - -- Waypoint and task arrays. - local wp={} - local tasks={} - - -- First waypoint is the current position of the group. - wp[1]=ini:WaypointGround(speed, formation) - tasks[1]=group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, 1, false) - - if self.Debug then - local MarkerID=ini:MarkToAll(string.format("Waypoing %d of group %s (initial)", #wp, self.Controllable:GetName())) - end - - self:T2(self.lid..string.format("Number of waypoints %d", nx)) - for i=1,nx-2 do - - local x=dx*i - local coord=ini:Translate(x, heading) + -- Current coordinates of group. + local ini=group:GetCoordinate() - wp[#wp+1]=coord:WaypointGround(speed, formation) - tasks[#tasks+1]=group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, #wp, false) + -- Distance between current and final point. + local dist=ini:Get2DDistance(fin) - self:T2(self.lid..string.format("%d x = %4.1f", i, x)) - if self.Debug then - local MarkerID=coord:MarkToAll(string.format("Waypoing %d of group %s", #wp, self.Controllable:GetName())) + -- Heading from ini to fin. + local heading=self:_Heading(ini, fin) + + -- Number of waypoints. + local nx + if dist <= 50 then + nx=2 + elseif dist <= 100 then + nx=3 + elseif dist <= 500 then + nx=4 + else + nx=5 end + -- Number of intermediate waypoints. + local dx=dist/(nx-1) + + -- Waypoint and task arrays. + local wp={} + local tasks={} + + -- First waypoint is the current position of the group. + wp[1]=ini:WaypointGround(speed, formation) + tasks[1]=group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, 1, false) + + if self.Debug then + local MarkerID=ini:MarkToAll(string.format("Waypoing %d of group %s (initial)", #wp, self.Controllable:GetName())) + end + + self:T2(self.lid..string.format("Number of waypoints %d", nx)) + for i=1,nx-2 do + + local x=dx*i + local coord=ini:Translate(x, heading) + + wp[#wp+1]=coord:WaypointGround(speed, formation) + tasks[#tasks+1]=group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, #wp, false) + + self:T2(self.lid..string.format("%d x = %4.1f", i, x)) + if self.Debug then + local MarkerID=coord:MarkToAll(string.format("Waypoing %d of group %s", #wp, self.Controllable:GetName())) + end + + end + self:T2(self.lid..string.format("Total distance: %4.1f", dist)) + + -- Final waypoint. + wp[#wp+1]=fin:WaypointGround(speed, formation) + if self.Debug then + local MarkerID=fin:MarkToAll(string.format("Waypoing %d of group %s (final)", #wp, self.Controllable:GetName())) + end + + -- Task to hold. + local ConditionWait=group:TaskCondition(nil, nil, nil, nil, wait, nil) + local TaskHold = group:TaskHold() + + -- Task combo to make group hold at final waypoint. + local TaskComboFin = {} + TaskComboFin[#TaskComboFin+1] = group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, #wp, true) + TaskComboFin[#TaskComboFin+1] = group:TaskControlled(TaskHold, ConditionWait) + + -- Add final task. + tasks[#tasks+1]=group:TaskCombo(TaskComboFin) + + -- Original waypoints of the group. + local Waypoints = group:GetTemplateRoutePoints() + + -- New points are added to the default route. + for i,p in ipairs(wp) do + table.insert(Waypoints, i, wp[i]) + end + + -- Set task for all waypoints. + for i,wp in ipairs(Waypoints) do + group:SetTaskWaypoint(Waypoints[i], tasks[i]) + end + + -- Submit task and route group along waypoints. + group:Route(Waypoints) + + else + self:E(self.lid..string.format("ERROR: Group is not alive!")) end - self:T2(self.lid..string.format("Total distance: %4.1f", dist)) - - -- Final waypoint. - wp[#wp+1]=fin:WaypointGround(speed, formation) - if self.Debug then - local MarkerID=fin:MarkToAll(string.format("Waypoing %d of group %s (final)", #wp, self.Controllable:GetName())) - end - - -- Task to hold. - local ConditionWait=group:TaskCondition(nil, nil, nil, nil, wait, nil) - local TaskHold = group:TaskHold() - - -- Task combo to make group hold at final waypoint. - local TaskComboFin = {} - TaskComboFin[#TaskComboFin+1] = group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, #wp, true) - TaskComboFin[#TaskComboFin+1] = group:TaskControlled(TaskHold, ConditionWait) - - -- Add final task. - tasks[#tasks+1]=group:TaskCombo(TaskComboFin) - - -- Original waypoints of the group. - local Waypoints = group:GetTemplateRoutePoints() - - -- New points are added to the default route. - for i,p in ipairs(wp) do - table.insert(Waypoints, i, wp[i]) - end - - -- Set task for all waypoints. - for i,wp in ipairs(Waypoints) do - group:SetTaskWaypoint(Waypoints[i], tasks[i]) - end - - -- Submit task and route group along waypoints. - group:Route(Waypoints) end diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index e3effd07c..37530551f 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -275,7 +275,7 @@ AIRBASE.PersianGulf = { ["Lavan_Island_Airport"] = "Lavan Island Airport", ["Liwa_Airbase"] = "Liwa Airbase", ["Qeshm_Island"] = "Qeshm Island", - ["Ras_Al_Khaimah_International_Airport"] = "Ras Al Khaimah International Airport", + ["Ras_Al_Khaimah"] = "Ras Al Khaimah", ["Sas_Al_Nakheel_Airport"] = "Sas Al Nakheel Airport", ["Sharjah_Intl"] = "Sharjah Intl", ["Shiraz_International_Airport"] = "Shiraz International Airport",