mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Ops
This commit is contained in:
parent
f3d9b9c5be
commit
1e0a0f8dc5
@ -817,6 +817,32 @@ function ZONE_RADIUS:GetScannedSetUnit()
|
||||
return SetUnit
|
||||
end
|
||||
|
||||
--- Get a set of scanned units.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @return Core.Set#SET_GROUP Set of groups.
|
||||
function ZONE_RADIUS:GetScannedSetGroup()
|
||||
|
||||
self.ScanSetGroup=self.ScanSetGroup or SET_GROUP:New() --Core.Set#SET_GROUP
|
||||
|
||||
self.ScanSetGroup.Set={}
|
||||
|
||||
if self.ScanData then
|
||||
for ObjectID, UnitObject in pairs( self.ScanData.Units ) do
|
||||
local UnitObject = UnitObject -- DCS#Unit
|
||||
if UnitObject:isExist() then
|
||||
|
||||
local FoundUnit=UNIT:FindByName(UnitObject:getName())
|
||||
if FoundUnit then
|
||||
local group=FoundUnit:GetGroup()
|
||||
self.ScanSetGroup:AddGroup(group)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self.ScanSetGroup
|
||||
end
|
||||
|
||||
|
||||
--- Count the number of different coalitions inside the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
|
||||
@ -890,12 +890,14 @@ do -- ZONE_CAPTURE_COALITION
|
||||
end
|
||||
|
||||
-- Status text.
|
||||
local text=string.format("CAPTURE ZONE %s: Owner=%s (Previous=%s): #blue=%d, #red=%d, Status %s", self:GetZoneName(), self:GetCoalitionName(), UTILS.GetCoalitionName(self:GetPreviousCoalition()), nBlue, nRed, State)
|
||||
local NewState = self:GetState()
|
||||
if NewState~=State then
|
||||
text=text..string.format(" --> %s", NewState)
|
||||
if false then
|
||||
local text=string.format("CAPTURE ZONE %s: Owner=%s (Previous=%s): #blue=%d, #red=%d, Status %s", self:GetZoneName(), self:GetCoalitionName(), UTILS.GetCoalitionName(self:GetPreviousCoalition()), nBlue, nRed, State)
|
||||
local NewState = self:GetState()
|
||||
if NewState~=State then
|
||||
text=text..string.format(" --> %s", NewState)
|
||||
end
|
||||
self:I(text)
|
||||
end
|
||||
self:I(text)
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -34,6 +34,8 @@
|
||||
-- @field #boolean formationPerma Formation that is used permanently and overrules waypoint formations.
|
||||
-- @field #boolean isMobile If true, group is mobile.
|
||||
-- @field #ARMYGROUP.Target engage Engage target.
|
||||
-- @field #boolean retreatOnOutOfAmmo If true, the group will automatically retreat when out of ammo. Needs a retreat zone!
|
||||
-- @field Core.Set#SET_ZONE retreatZones Set of retreat zones.
|
||||
-- @extends Ops.OpsGroup#OPSGROUP
|
||||
|
||||
--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B. Sledge
|
||||
@ -70,12 +72,13 @@ ARMYGROUP = {
|
||||
|
||||
--- Army Group version.
|
||||
-- @field #string version
|
||||
ARMYGROUP.version="0.3.0"
|
||||
ARMYGROUP.version="0.4.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Retreat.
|
||||
-- TODO: Suppression of fire.
|
||||
-- TODO: Check if group is mobile.
|
||||
-- TODO: F10 menu.
|
||||
@ -102,6 +105,7 @@ function ARMYGROUP:New(Group)
|
||||
self:SetDefaultAlarmstate()
|
||||
self:SetDetection()
|
||||
self:SetPatrolAdInfinitum(false)
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
@ -112,10 +116,11 @@ function ARMYGROUP:New(Group)
|
||||
self:AddTransition("OnDetour", "DetourReached", "Cruising") -- Group reached the detour coordinate.
|
||||
|
||||
self:AddTransition("*", "Retreat", "Retreating") --
|
||||
self:AddTransition("Retreating", "Retreated", "Holding") --
|
||||
self:AddTransition("Retreating", "Retreated", "Retreated") --
|
||||
|
||||
self:AddTransition("Cruising", "EngageTarget", "Engaging") -- Engage a target
|
||||
self:AddTransition("Holding", "EngageTarget", "Engaging") -- Engage a target
|
||||
self:AddTransition("OnDetour", "EngageTarget", "Engaging") -- Engage a target
|
||||
self:AddTransition("Engaging", "Disengage", "Cruising") -- Engage a target
|
||||
|
||||
self:AddTransition("*", "Rearm", "Rearm") -- Group is send to a coordinate and waits until ammo is refilled.
|
||||
@ -258,6 +263,24 @@ function ARMYGROUP:AddTaskAttackGroup(TargetGroup, WeaponExpend, WeaponType, Clo
|
||||
return task
|
||||
end
|
||||
|
||||
--- Define a set of possible retreat zones.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param Core.Set#SET_ZONE RetreatZoneSet The retreat zone set. Default is an empty set.
|
||||
-- @return #ARMYGROUP self
|
||||
function ARMYGROUP:SetRetreatZones(RetreatZoneSet)
|
||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a zone to the retreat zone set.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param Core.Zone#ZONE_BASE RetreatZone The retreat zone.
|
||||
-- @return #ARMYGROUP self
|
||||
function ARMYGROUP:AddRetreatZone(RetreatZone)
|
||||
self.retreatZones:AddZone(RetreatZone)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check if the group is currently holding its positon.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group was ordered to hold.
|
||||
@ -279,6 +302,20 @@ function ARMYGROUP:IsOnDetour()
|
||||
return self:Is("OnDetour")
|
||||
end
|
||||
|
||||
--- Check if the group is ready for combat. I.e. not reaming, retreating, retreated, out of ammo or engaging.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @return #boolean If true, group is on a combat ready.
|
||||
function ARMYGROUP:IsCombatReady()
|
||||
local combatready=true
|
||||
|
||||
if self:IsRearming() or self:IsRetreating() or self.outofAmmo or self:IsEngaging() or self:is("Retreated") or self:IsDead() or self:IsStopped() or self:IsInUtero() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
return combatready
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -325,6 +362,9 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
|
||||
-- Check damage of elements and group.
|
||||
self:_CheckDamage()
|
||||
|
||||
-- Update engagement.
|
||||
if self:IsEngaging() then
|
||||
self:_UpdateEngageTarget()
|
||||
@ -344,8 +384,8 @@ function ARMYGROUP:onafterStatus(From, Event, To)
|
||||
local ammo=self:GetAmmoTot()
|
||||
|
||||
-- Info text.
|
||||
local text=string.format("%s [ROE-AS=%d-%d T/M=%d/%d]: Wp=%d/%d-->%d (final %s), Speed=%.1f (%d), Heading=%03d, Ammo=%d",
|
||||
fsmstate, roe, alarm, nTaskTot, nMissions, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), tostring(self.passedfinalwp), speed, speedEx, self.heading, ammo.Total)
|
||||
local text=string.format("%s [ROE-AS=%d-%d T/M=%d/%d]: Wp=%d/%d-->%d (final %s), Life=%.1f, Speed=%.1f (%d), Heading=%03d, Ammo=%d",
|
||||
fsmstate, roe, alarm, nTaskTot, nMissions, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), tostring(self.passedfinalwp), self.life or 0, speed, speedEx, self.heading, ammo.Total)
|
||||
self:I(self.lid..text)
|
||||
|
||||
end
|
||||
@ -596,6 +636,13 @@ end
|
||||
-- @param #number ResumeRoute If true, resume route after detour point was reached. If false, the group will stop at the detour point and wait for futher commands.
|
||||
function ARMYGROUP:onafterDetour(From, Event, To, Coordinate, Speed, Formation, ResumeRoute)
|
||||
|
||||
for _,_wp in pairs(self.waypoints) do
|
||||
local wp=_wp --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||
if wp.detour then
|
||||
self:RemoveWaypointByID(wp.uid)
|
||||
end
|
||||
end
|
||||
|
||||
-- Speed in knots.
|
||||
Speed=Speed or self:GetSpeedCruise()
|
||||
|
||||
@ -652,6 +699,103 @@ function ARMYGROUP:onafterRearming(From, Event, To)
|
||||
|
||||
end
|
||||
|
||||
--- On before "Retreat" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE_BASE Zone (Optional) Zone where to retreat. Default is the closest retreat zone.
|
||||
-- @param #number Formation (Optional) Formation of the group.
|
||||
function ARMYGROUP:onbeforeRetreat(From, Event, To, Zone, Formation)
|
||||
|
||||
if not Zone then
|
||||
|
||||
local a=self:GetVec2()
|
||||
|
||||
local distmin=math.huge
|
||||
local zonemin=nil
|
||||
for _,_zone in pairs(self.retreatZones:GetSet()) do
|
||||
local zone=_zone --Core.Zone#ZONE_BASE
|
||||
|
||||
local b=zone:GetVec2()
|
||||
|
||||
local dist=UTILS.VecDist2D(a, b)
|
||||
|
||||
if dist<distmin then
|
||||
distmin=dist
|
||||
zonemin=zone
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if zonemin then
|
||||
self:__Retreat(0.1, zonemin, Formation)
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- On after "Retreat" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE_BASE Zone (Optional) Zone where to retreat. Default is the closest retreat zone.
|
||||
-- @param #number Formation (Optional) Formation of the group.
|
||||
function ARMYGROUP:onafterRetreat(From, Event, To, Zone, Formation)
|
||||
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
local Coordinate=Zone:GetRandomCoordinate()
|
||||
|
||||
-- Add waypoint after current.
|
||||
local wp=self:AddWaypoint(Coordinate, nil, uid, Formation, true)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
wp.detour=0
|
||||
|
||||
end
|
||||
|
||||
--- On after "Retreated" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterRetreated(From, Event, To)
|
||||
|
||||
-- Get current position.
|
||||
local pos=self:GetCoordinate()
|
||||
|
||||
-- Create a new waypoint.
|
||||
local wp=pos:WaypointGround(0)
|
||||
|
||||
-- Create new route consisting of only this position ==> Stop!
|
||||
self:Route({wp})
|
||||
|
||||
end
|
||||
|
||||
--- On after "EngageTarget" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Group#GROUP Group the group to be engaged.
|
||||
function ARMYGROUP:onbeforeEngageTarget(From, Event, To, Target)
|
||||
|
||||
local ammo=self:GetAmmoTot()
|
||||
|
||||
if ammo.Total==0 then
|
||||
env.info("FF cannot engage because no ammo!")
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--- On after "EngageTarget" event.
|
||||
-- @param #ARMYGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -1031,11 +1175,13 @@ function ARMYGROUP:_InitGroup()
|
||||
element.categoryname=element.unit:GetCategoryName()
|
||||
element.size, element.length, element.height, element.width=unit:GetObjectSize()
|
||||
element.ammo0=self:GetAmmoUnit(unit, false)
|
||||
element.life0=unit:GetLife0()
|
||||
element.life=element.life0
|
||||
|
||||
-- Debug text.
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Adding element %s: status=%s, skill=%s, category=%s (%d), size: %.1f (L=%.1f H=%.1f W=%.1f)",
|
||||
element.name, element.status, element.skill, element.categoryname, element.category, element.size, element.length, element.height, element.width)
|
||||
local text=string.format("Adding element %s: status=%s, skill=%s, life=%.3f category=%s (%d), size: %.1f (L=%.1f H=%.1f W=%.1f)",
|
||||
element.name, element.status, element.skill, element.life, element.categoryname, element.category, element.size, element.length, element.height, element.width)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
|
||||
@ -156,6 +156,8 @@ OPSGROUP = {
|
||||
-- @field #number length Length of element in meters.
|
||||
-- @field #number width Width of element in meters.
|
||||
-- @field #number height Height of element in meters.
|
||||
-- @field #number life0 Initial life points.
|
||||
-- @field #number life Life points when last updated.
|
||||
|
||||
--- Status of group element.
|
||||
-- @type OPSGROUP.ElementStatus
|
||||
@ -391,10 +393,13 @@ function OPSGROUP:New(Group)
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("InUtero", "Spawned", "Spawned") -- The whole group was spawned.
|
||||
self:AddTransition("*", "Dead", "Dead") -- The whole group is dead.
|
||||
self:AddTransition("*", "Dead", "Dead") -- The whole group is dead.
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||
|
||||
self:AddTransition("*", "Status", "*") -- Status update.
|
||||
|
||||
self:AddTransition("*", "Destroyed", "*") -- The whole group is dead.
|
||||
self:AddTransition("*", "Damaged", "*") -- Someone in the group took damage.
|
||||
|
||||
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group. Only if airborne.
|
||||
self:AddTransition("*", "Respawn", "*") -- Respawn group.
|
||||
@ -445,6 +450,7 @@ function OPSGROUP:New(Group)
|
||||
self:AddTransition("*", "ElementSpawned", "*") -- An element was spawned.
|
||||
self:AddTransition("*", "ElementDestroyed", "*") -- An element was destroyed.
|
||||
self:AddTransition("*", "ElementDead", "*") -- An element is dead.
|
||||
self:AddTransition("*", "ElementDamaged", "*") -- An element was damaged.
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
@ -936,8 +942,23 @@ function OPSGROUP:DespawnElement(Element, Delay, NoEventRemoveUnit)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get current 2D position vector of the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return DCS#Vec2 Vector with x,y components.
|
||||
function OPSGROUP:GetVec2()
|
||||
|
||||
--- Get current 3D vector of the group.
|
||||
local vec3=self:GetVec3()
|
||||
|
||||
if vec3 then
|
||||
local vec2={x=vec3.x, y=vec3.z}
|
||||
return vec2
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Get current 3D position vector of the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return DCS#Vec3 Vector with x,y,z components.
|
||||
function OPSGROUP:GetVec3()
|
||||
@ -973,6 +994,7 @@ function OPSGROUP:GetCoordinate(NewObject)
|
||||
|
||||
if NewObject then
|
||||
local coord=COORDINATE:NewFromCoordinate(self.coordinate)
|
||||
return coord
|
||||
else
|
||||
return self.coordinate
|
||||
end
|
||||
@ -1245,9 +1267,16 @@ function OPSGROUP:IsLasing()
|
||||
return self.spot.On
|
||||
end
|
||||
|
||||
--- Check if the group has currently switched a LASER on.
|
||||
--- Check if the group is currently retreating.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #boolean If true, LASER of the group is on.
|
||||
-- @return #boolean If true, group is retreating.
|
||||
function OPSGROUP:IsRetreating()
|
||||
return self:is("Retreating")
|
||||
end
|
||||
|
||||
--- Check if the group is engaging another unit or group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #boolean If true, group is engaging.
|
||||
function OPSGROUP:IsEngaging()
|
||||
return self:is("Engaging")
|
||||
end
|
||||
@ -3695,6 +3724,17 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||
|
||||
end
|
||||
|
||||
--- On before "Dead" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function OPSGROUP:onbeforeDead(From, Event, To)
|
||||
if self.Ndestroyed==#self.elements then
|
||||
self:Destroyed()
|
||||
end
|
||||
end
|
||||
|
||||
--- On after "Dead" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
@ -4052,6 +4092,37 @@ function OPSGROUP:_CheckStuck()
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Check damage.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:_CheckDamage()
|
||||
|
||||
self.life=0
|
||||
local damaged=false
|
||||
for _,_element in pairs(self.elements) do
|
||||
local element=_element --Ops.OpsGroup#OPSGROUP
|
||||
|
||||
-- Current life points.
|
||||
local life=element.unit:GetLife()
|
||||
|
||||
self.life=self.life+life
|
||||
|
||||
if life<element.life then
|
||||
element.life=life
|
||||
self:ElementDamaged(element)
|
||||
damaged=true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if damaged then
|
||||
self:Damaged()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Check ammo is full.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #boolean If true, ammo is full.
|
||||
@ -4094,6 +4165,7 @@ function OPSGROUP:_CheckAmmoStatus()
|
||||
self.outofAmmo=false
|
||||
end
|
||||
if ammo.Total==0 and not self.outofAmmo then
|
||||
env.info("FF out of ammo")
|
||||
self.outofAmmo=true
|
||||
self:OutOfAmmo()
|
||||
end
|
||||
@ -4443,6 +4515,11 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid)
|
||||
-- Trigger Rearming event.
|
||||
opsgroup:Rearming()
|
||||
|
||||
elseif opsgroup:IsRetreating() then
|
||||
|
||||
-- Trigger Retreated event.
|
||||
opsgroup:Retreated()
|
||||
|
||||
elseif opsgroup:IsEngaging() then
|
||||
|
||||
-- Nothing to do really.
|
||||
|
||||
@ -230,7 +230,13 @@ function TARGET:AddObject(Object)
|
||||
|
||||
for _,object in pairs(set.Set) do
|
||||
self:AddObject(object)
|
||||
end
|
||||
end
|
||||
|
||||
elseif Object:IsInstanceOf("GROUP") then
|
||||
|
||||
for _,unit in pairs(Object:GetUnits()) do
|
||||
self:_AddObject(unit)
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
@ -716,6 +722,8 @@ function TARGET:GetTargetVec3(Target)
|
||||
|
||||
if object and object:IsAlive() then
|
||||
return object:GetVec3()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
elseif Target.Type==TARGET.ObjectType.STATIC then
|
||||
@ -724,6 +732,8 @@ function TARGET:GetTargetVec3(Target)
|
||||
|
||||
if object and object:IsAlive() then
|
||||
return object:GetVec3()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
elseif Target.Type==TARGET.ObjectType.SCENERY then
|
||||
@ -732,6 +742,8 @@ function TARGET:GetTargetVec3(Target)
|
||||
|
||||
if object then
|
||||
return object:GetVec3()
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
elseif Target.Type==TARGET.ObjectType.AIRBASE then
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user