mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-17 03:11:28 +00:00
Merge branch 'develop' into FF/Ops
This commit is contained in:
@@ -46,7 +46,7 @@
|
||||
--
|
||||
-- # The ARMYGROUP Concept
|
||||
--
|
||||
-- This class enhances naval groups.
|
||||
-- This class enhances ground groups.
|
||||
--
|
||||
-- @field #ARMYGROUP
|
||||
ARMYGROUP = {
|
||||
@@ -115,6 +115,7 @@ function ARMYGROUP:New(group)
|
||||
self:AddTransition("*", "Cruise", "Cruising") -- Cruise along the given route of waypoints.
|
||||
|
||||
self:AddTransition("*", "RTZ", "Returning") -- Group is returning to (home) zone.
|
||||
self:AddTransition("Holding", "Returned", "Returned") -- Group is returned to (home) zone, e.g. when unloaded from carrier.
|
||||
self:AddTransition("Returning", "Returned", "Returned") -- Group is returned to (home) zone.
|
||||
|
||||
self:AddTransition("*", "Detour", "OnDetour") -- Make a detour to a coordinate and resume route afterwards.
|
||||
@@ -652,7 +653,10 @@ function ARMYGROUP:Status()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
-- Check damage of elements and group.
|
||||
self:_CheckDamage()
|
||||
end
|
||||
|
||||
-- Check that group EXISTS.
|
||||
@@ -691,7 +695,7 @@ function ARMYGROUP:Status()
|
||||
local text=string.format("State %s: Alive=%s", fsmstate, tostring(self:IsAlive()))
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
---
|
||||
@@ -706,7 +710,6 @@ function ARMYGROUP:Status()
|
||||
local name=element.name
|
||||
local status=element.status
|
||||
local unit=element.unit
|
||||
--local life=unit:GetLifeRelative() or 0
|
||||
local life,life0=self:GetLifePoints(element)
|
||||
|
||||
local life0=element.life0
|
||||
@@ -926,7 +929,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
||||
|
||||
-- Next waypoint.
|
||||
local wp=UTILS.DeepCopy(self.waypoints[i]) --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||
self:T({wp})
|
||||
|
||||
-- Speed.
|
||||
if Speed then
|
||||
wp.speed=UTILS.KnotsToMps(tonumber(Speed))
|
||||
@@ -981,6 +984,13 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
||||
|
||||
-- Insert a point on road.
|
||||
if wp.action==ENUMS.Formation.Vehicle.OnRoad and (wp.coordinate or wp.roadcoord) then
|
||||
|
||||
current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
|
||||
table.insert(waypoints, 2, current)
|
||||
|
||||
-- Removing this for now as I don't see why it is necessary and it is very CPU intensive.
|
||||
-- You only need the start and end waypoint on the road. Other waypoints on the road are not necessray.
|
||||
--[[
|
||||
-- take direct line if on road is too long
|
||||
local wptable,length,valid=self:GetCoordinate():GetPathOnRoad(wp.coordinate or wp.roadcoord,true,false,false,false) or {}
|
||||
|
||||
@@ -1002,7 +1012,8 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation)
|
||||
else
|
||||
current=self:GetClosestRoad():WaypointGround(UTILS.MpsToKmph(self.speedWp), ENUMS.Formation.Vehicle.OnRoad)
|
||||
table.insert(waypoints, count, current)
|
||||
end
|
||||
end
|
||||
]]
|
||||
end
|
||||
|
||||
-- Debug output.
|
||||
@@ -1105,16 +1116,6 @@ end
|
||||
-- @param #string To To state.
|
||||
function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
||||
self:T(self.lid..string.format("Group is out of ammo at t=%.3f", timer.getTime()))
|
||||
|
||||
-- Get current task.
|
||||
local task=self:GetTaskCurrent()
|
||||
|
||||
if task then
|
||||
if task.dcstask.id=="FireAtPoint" or task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
||||
self:T(self.lid..string.format("Cancelling current %s task because out of ammo!", task.dcstask.id))
|
||||
self:TaskCancel(task)
|
||||
end
|
||||
end
|
||||
|
||||
-- Fist, check if we want to rearm once out-of-ammo.
|
||||
--TODO: IsMobile() check
|
||||
@@ -1138,6 +1139,16 @@ function ARMYGROUP:onafterOutOfAmmo(From, Event, To)
|
||||
if self.rtzOnOutOfAmmo then
|
||||
self:__RTZ(-1)
|
||||
end
|
||||
|
||||
-- Get current task.
|
||||
local task=self:GetTaskCurrent()
|
||||
|
||||
if task then
|
||||
if task.dcstask.id=="FireAtPoint" or task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
||||
self:T(self.lid..string.format("Cancelling current %s task because out of ammo!", task.dcstask.id))
|
||||
self:TaskCancel(task)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1223,9 +1234,6 @@ end
|
||||
-- @param Core.Zone#ZONE Zone The zone to return to.
|
||||
-- @param #number Formation Formation of the group.
|
||||
function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
|
||||
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Zone.
|
||||
local zone=Zone or self.homezone
|
||||
@@ -1240,6 +1248,9 @@ function ARMYGROUP:onafterRTZ(From, Event, To, Zone, Formation)
|
||||
self:T(self.lid..string.format("RTZ to Zone %s", zone:GetName()))
|
||||
|
||||
local Coordinate=zone:GetRandomCoordinate()
|
||||
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrentUID()
|
||||
|
||||
-- Add waypoint after current.
|
||||
local wp=self:AddWaypoint(Coordinate, nil, uid, Formation, true)
|
||||
@@ -1351,6 +1362,9 @@ function ARMYGROUP:onafterRetreat(From, Event, To, Zone, Formation)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
wp.detour=0
|
||||
|
||||
-- Cancel all missions.
|
||||
self:CancelAllMissions()
|
||||
|
||||
end
|
||||
|
||||
@@ -1417,6 +1431,7 @@ end
|
||||
function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
self:T(self.lid.."Engaging Target")
|
||||
|
||||
-- Make sure this is a target.
|
||||
if Target:IsInstanceOf("TARGET") then
|
||||
self.engage.Target=Target
|
||||
else
|
||||
@@ -1426,11 +1441,9 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
-- Target coordinate.
|
||||
self.engage.Coordinate=UTILS.DeepCopy(self.engage.Target:GetCoordinate())
|
||||
|
||||
|
||||
-- Get a coordinate close to the target.
|
||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||
|
||||
|
||||
|
||||
-- Backup ROE and alarm state.
|
||||
self.engage.roe=self:GetROE()
|
||||
self.engage.alarmstate=self:GetAlarmstate()
|
||||
@@ -1442,6 +1455,10 @@ function ARMYGROUP:onafterEngageTarget(From, Event, To, Target)
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Set formation.
|
||||
--TODO: make this input.
|
||||
local Formation=ENUMS.Formation.Vehicle.Vee
|
||||
|
||||
-- Add waypoint after current.
|
||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||
|
||||
@@ -1458,37 +1475,46 @@ function ARMYGROUP:_UpdateEngageTarget()
|
||||
|
||||
-- Get current position vector.
|
||||
local vec3=self.engage.Target:GetVec3()
|
||||
|
||||
if vec3 then
|
||||
|
||||
-- Distance to last known position of target.
|
||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||
|
||||
-- Check if target moved more than 100 meters.
|
||||
if dist>100 then
|
||||
|
||||
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
|
||||
|
||||
-- Update new position.
|
||||
self.engage.Coordinate:UpdateFromVec3(vec3)
|
||||
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Remove current waypoint
|
||||
self:RemoveWaypointByID(self.engage.Waypoint.uid)
|
||||
-- Distance to last known position of target.
|
||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||
|
||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||
-- Check if target moved more than 100 meters.
|
||||
if dist>100 then
|
||||
|
||||
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
|
||||
|
||||
-- Update new position.
|
||||
self.engage.Coordinate:UpdateFromVec3(vec3)
|
||||
|
||||
-- Add waypoint after current.
|
||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Remove current waypoint
|
||||
self:RemoveWaypointByID(self.engage.Waypoint.uid)
|
||||
|
||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
self.engage.Waypoint.detour=0
|
||||
-- Add waypoint after current.
|
||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
self.engage.Waypoint.detour=0
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||
self:Disengage()
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Target not alive any more == Disengage.
|
||||
-- Target not alive any more ==> Disengage.
|
||||
self:Disengage()
|
||||
|
||||
end
|
||||
@@ -1587,8 +1613,7 @@ function ARMYGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Formation
|
||||
-- Speed in knots.
|
||||
Speed=Speed or self:GetSpeedCruise()
|
||||
|
||||
-- Formation
|
||||
|
||||
-- Formation.
|
||||
if not Formation then
|
||||
if self.formationPerma then
|
||||
Formation = self.formationPerma
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
-- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported.
|
||||
-- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo.
|
||||
-- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo.
|
||||
-- @field #number transportPickupRadius Radius in meters for pickup zone. Default 500 m.
|
||||
--
|
||||
-- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment.
|
||||
-- @field #number NcarriersMin Min number of required carrier assets.
|
||||
@@ -383,6 +384,7 @@ _AUFTRAGSNR=0
|
||||
-- @field #string ARMOREDGUARD On guard - with armored groups.
|
||||
-- @field #string BARRAGE Barrage.
|
||||
-- @field #string ARMORATTACK Armor attack.
|
||||
-- @field #string CASENHANCED Enhanced CAS.
|
||||
AUFTRAG.Type={
|
||||
ANTISHIP="Anti Ship",
|
||||
AWACS="AWACS",
|
||||
@@ -415,6 +417,7 @@ AUFTRAG.Type={
|
||||
ARMOREDGUARD="Armored Guard",
|
||||
BARRAGE="Barrage",
|
||||
ARMORATTACK="Armor Attack",
|
||||
CASENHANCED="CAS Enhanced",
|
||||
}
|
||||
|
||||
--- Mission status of an assigned group.
|
||||
@@ -557,7 +560,7 @@ AUFTRAG.Category={
|
||||
|
||||
--- AUFTRAG class version.
|
||||
-- @field #string version
|
||||
AUFTRAG.version="0.8.1"
|
||||
AUFTRAG.version="0.8.4"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -1186,6 +1189,45 @@ function AUFTRAG:NewCAS(ZoneCAS, Altitude, Speed, Coordinate, Heading, Leg, Targ
|
||||
return mission
|
||||
end
|
||||
|
||||
--- **[AIR]** Create a CASENHANCED mission. Group(s) will go to the zone and patrol it randomly.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Core.Zone#ZONE CasZone The CAS zone.
|
||||
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||
-- @param #number Speed Speed in knots.
|
||||
-- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM.
|
||||
-- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`.
|
||||
-- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZoneSet, TargetTypes)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.CASENHANCED)
|
||||
|
||||
-- Ensure we got a ZONE and not just the zone name.
|
||||
if type(CasZone)=="string" then
|
||||
CasZone=ZONE:New(CasZone)
|
||||
end
|
||||
|
||||
mission:_TargetFromObject(CasZone)
|
||||
|
||||
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CASENHANCED)
|
||||
|
||||
mission:SetEngageDetected(RangeMax, TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"}, CasZone, NoEngageZoneSet)
|
||||
|
||||
mission.optionROE=ENUMS.ROE.OpenFire
|
||||
mission.optionROT=ENUMS.ROT.EvadeFire
|
||||
|
||||
mission.missionFraction=1.0
|
||||
mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil
|
||||
mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil
|
||||
|
||||
mission.categories={AUFTRAG.Category.AIRCRAFT}
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
|
||||
--- **[AIR]** Create a FACA mission.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object.
|
||||
@@ -1492,8 +1534,9 @@ end
|
||||
-- @param Core.Set#SET_GROUP TransportGroupSet The set group(s) to be transported.
|
||||
-- @param Core.Point#COORDINATE DropoffCoordinate Coordinate where the helo will land drop off the the troops.
|
||||
-- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the fist transport group.
|
||||
-- @param #number PickupRadius Radius around the pickup coordinate in meters. Default 100 m.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate)
|
||||
function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate, PickupRadius)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.TROOPTRANSPORT)
|
||||
|
||||
@@ -1509,14 +1552,16 @@ function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupC
|
||||
|
||||
mission:_TargetFromObject(mission.transportGroupSet)
|
||||
|
||||
mission.transportPickup=PickupCoordinate or mission:GetTargetCoordinate()
|
||||
mission.transportPickup=PickupCoordinate or mission:GetTargetCoordinate()
|
||||
mission.transportDropoff=DropoffCoordinate
|
||||
|
||||
mission.transportPickupRadius=PickupRadius or 100
|
||||
|
||||
mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.TROOPTRANSPORT)
|
||||
|
||||
-- Debug.
|
||||
mission.transportPickup:MarkToAll("Pickup")
|
||||
mission.transportDropoff:MarkToAll("Drop off")
|
||||
--mission.transportPickup:MarkToAll("Pickup Transport")
|
||||
--mission.transportDropoff:MarkToAll("Drop off")
|
||||
|
||||
-- TODO: what's the best ROE here?
|
||||
mission.optionROE=ENUMS.ROE.ReturnFire
|
||||
@@ -1645,8 +1690,9 @@ end
|
||||
-- @param Core.Zone#ZONE Zone The patrol zone.
|
||||
-- @param #number Speed Speed in knots.
|
||||
-- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL.
|
||||
-- @param #string Formation Formation used during patrol.
|
||||
-- @return #AUFTRAG self
|
||||
function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
|
||||
function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation)
|
||||
|
||||
local mission=AUFTRAG:New(AUFTRAG.Type.PATROLZONE)
|
||||
|
||||
@@ -1670,10 +1716,13 @@ function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude)
|
||||
mission.categories={AUFTRAG.Category.ALL}
|
||||
|
||||
mission.DCStask=mission:GetDCSMissionTask()
|
||||
|
||||
mission.DCStask.params.formation=Formation
|
||||
|
||||
return mission
|
||||
end
|
||||
|
||||
|
||||
--- **[GROUND]** Create a ARMORATTACK mission. Armoured ground group(s) will go to the zone and attack.
|
||||
-- @param #AUFTRAG self
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object.
|
||||
@@ -3478,7 +3527,7 @@ function AUFTRAG:SetGroupStatus(opsgroup, status)
|
||||
local groupsDone=self:CheckGroupsDone()
|
||||
|
||||
-- Debug info.
|
||||
self:T2(self.lid..string.format("Setting OPSGROUP %s status to %s. IsNotOver=%s CheckGroupsDone=%s", opsgroup.groupname, self:GetGroupStatus(opsgroup), tostring(self:IsNotOver()), tostring(self:CheckGroupsDone())))
|
||||
self:T2(self.lid..string.format("Setting OPSGROUP %s status to %s. IsNotOver=%s CheckGroupsDone=%s", opsgroup.groupname, self:GetGroupStatus(opsgroup), tostring(self:IsNotOver()), tostring(groupsDone)))
|
||||
|
||||
-- Check if ALL flights are done with their mission.
|
||||
if isNotOver and groupsDone then
|
||||
@@ -4958,6 +5007,26 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable)
|
||||
DCStask.params=param
|
||||
|
||||
table.insert(DCStasks, DCStask)
|
||||
|
||||
elseif self.type==AUFTRAG.Type.CASENHANCED then
|
||||
|
||||
-------------------------
|
||||
-- CAS ENHANCED Mission --
|
||||
-------------------------
|
||||
|
||||
local DCStask={}
|
||||
|
||||
DCStask.id="PatrolZone"
|
||||
|
||||
-- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP.
|
||||
local param={}
|
||||
param.zone=self:GetObjective()
|
||||
param.altitude=self.missionAltitude
|
||||
param.speed=self.missionSpeed
|
||||
|
||||
DCStask.params=param
|
||||
|
||||
table.insert(DCStasks, DCStask)
|
||||
|
||||
elseif self.type==AUFTRAG.Type.ARMORATTACK then
|
||||
|
||||
@@ -5147,6 +5216,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType)
|
||||
mtask=ENUMS.MissionTask.CAS
|
||||
elseif MissionType==AUFTRAG.Type.PATROLZONE then
|
||||
mtask=ENUMS.MissionTask.CAS
|
||||
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
||||
mtask=ENUMS.MissionTask.CAS
|
||||
elseif MissionType==AUFTRAG.Type.ESCORT then
|
||||
mtask=ENUMS.MissionTask.ESCORT
|
||||
elseif MissionType==AUFTRAG.Type.FACA then
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:--- **Ops** -- Combat Search and Rescue.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- **CSAR** - MOOSE based Helicopter CSAR Operations.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- ### [CSAR - Combat Search & Rescue](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20CSAR)
|
||||
@@ -118,7 +126,8 @@
|
||||
-- self.SRSModulation = radio.modulation.AM -- modulation
|
||||
-- --
|
||||
-- self.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection --shagrat
|
||||
--
|
||||
-- self.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
|
||||
--
|
||||
-- ## 3. Results
|
||||
--
|
||||
-- Number of successful landings with save pilots and aggregated number of saved pilots is stored in these variables in the object:
|
||||
@@ -227,8 +236,9 @@ CSAR = {
|
||||
-- @field #number frequency Frequency of the NDB.
|
||||
-- @field #string player Player name if applicable.
|
||||
-- @field Wrapper.Group#GROUP group Spawned group object.
|
||||
-- @field #number timestamp Timestamp for approach process
|
||||
-- @field #boolean alive Group is alive or dead/rescued
|
||||
-- @field #number timestamp Timestamp for approach process.
|
||||
-- @field #boolean alive Group is alive or dead/rescued.
|
||||
-- @field #boolean wetfeet Group is spawned over (deep) water.
|
||||
|
||||
--- All slot / Limit settings
|
||||
-- @type CSAR.AircraftType
|
||||
@@ -244,11 +254,12 @@ CSAR.AircraftType["Mi-8MT"] = 12
|
||||
CSAR.AircraftType["Mi-24P"] = 8
|
||||
CSAR.AircraftType["Mi-24V"] = 8
|
||||
CSAR.AircraftType["Bell-47"] = 2
|
||||
CSAR.AircraftType["UH-60L"] = 10
|
||||
CSAR.AircraftType["UH-60L"] = 10
|
||||
CSAR.AircraftType["AH-64D_BLK_II"] = 2
|
||||
|
||||
--- CSAR class version.
|
||||
-- @field #string version
|
||||
CSAR.version="1.0.3"
|
||||
CSAR.version="1.0.4d"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -390,6 +401,10 @@ function CSAR:New(Coalition, Template, Alias)
|
||||
|
||||
-- added 0.1.3
|
||||
self.csarUsePara = false -- shagrat set to true, will use the LandingAfterEjection Event instead of Ejection
|
||||
|
||||
-- added 0.1.4
|
||||
self.wetfeettemplate = nil
|
||||
self.usewetfeet = false
|
||||
|
||||
-- WARNING - here\'ll be dragons
|
||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||
@@ -502,8 +517,9 @@ end
|
||||
-- @param #string Typename Typename of unit.
|
||||
-- @param #number Frequency Frequency of the NDB in Hz
|
||||
-- @param #string Playername Name of Player (if applicable)
|
||||
-- @param #boolean Wetfeet Ejected over water
|
||||
-- @return #CSAR self.
|
||||
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername)
|
||||
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet)
|
||||
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
|
||||
|
||||
-- create new entry
|
||||
@@ -519,6 +535,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
|
||||
DownedPilot.group = Group
|
||||
DownedPilot.timestamp = 0
|
||||
DownedPilot.alive = true
|
||||
DownedPilot.wetfeet = Wetfeet or false
|
||||
|
||||
-- Add Pilot
|
||||
local PilotTable = self.downedPilots
|
||||
@@ -568,17 +585,23 @@ end
|
||||
-- @param #number country Country for template.
|
||||
-- @param Core.Point#COORDINATE point Coordinate to spawn at.
|
||||
-- @param #number frequency Frequency of the pilot's beacon
|
||||
-- @param #boolean wetfeet Spawn is over water
|
||||
-- @return Wrapper.Group#GROUP group The #GROUP object.
|
||||
-- @return #string alias The alias name.
|
||||
function CSAR:_SpawnPilotInField(country,point,frequency)
|
||||
self:T({country,point,frequency})
|
||||
function CSAR:_SpawnPilotInField(country,point,frequency,wetfeet)
|
||||
self:T({country,point,frequency,tostring(wetfeet)})
|
||||
local freq = frequency or 1000
|
||||
local freq = freq / 1000 -- kHz
|
||||
for i=1,10 do
|
||||
math.random(i,10000)
|
||||
end
|
||||
if point:IsSurfaceTypeWater() then point.y = 0 end
|
||||
if point:IsSurfaceTypeWater() or wetfeet then
|
||||
point.y = 0
|
||||
end
|
||||
local template = self.template
|
||||
if self.usewetfeet and wetfeet then
|
||||
template = self.wetfeettemplate
|
||||
end
|
||||
local alias = string.format("Pilot %.2fkHz-%d", freq, math.random(1,99))
|
||||
local coalition = self.coalition
|
||||
local pilotcacontrol = self.allowDownedPilotCAcontrol -- Switch AI on/oof - is this really correct for CA?
|
||||
@@ -644,13 +667,19 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
||||
self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description})
|
||||
|
||||
local template = self.template
|
||||
local wetfeet = false
|
||||
|
||||
local surface = _point:GetSurfaceType()
|
||||
if surface == land.SurfaceType.WATER then
|
||||
wetfeet = true
|
||||
end
|
||||
|
||||
if not _freq then
|
||||
_freq = self:_GenerateADFFrequency()
|
||||
if not _freq then _freq = 333000 end --noob catch
|
||||
end
|
||||
|
||||
local _spawnedGroup, _alias = self:_SpawnPilotInField(_country,_point,_freq)
|
||||
local _spawnedGroup, _alias = self:_SpawnPilotInField(_country,_point,_freq,wetfeet)
|
||||
|
||||
local _typeName = _typeName or "Pilot"
|
||||
|
||||
@@ -688,7 +717,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
||||
|
||||
local _GroupName = _spawnedGroup:GetName() or _alias
|
||||
|
||||
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName)
|
||||
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
|
||||
|
||||
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
||||
|
||||
@@ -935,9 +964,19 @@ function CSAR:_EventHandler(EventData)
|
||||
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
||||
-- might create dual pilots in edge cases
|
||||
|
||||
local wetfeet = false
|
||||
|
||||
local surface = _unit:GetCoordinate():GetSurfaceType()
|
||||
if surface == land.SurfaceType.WATER then
|
||||
wetfeet = true
|
||||
end
|
||||
-- all checks passed, get going.
|
||||
if self.csarUsePara == false then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
||||
if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
||||
local _freq = self:_GenerateADFFrequency()
|
||||
self:_AddCsar(_coalition, _unit:GetCountry(), _unit:GetCoordinate() , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
|
||||
return true
|
||||
@@ -1294,7 +1333,8 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG
|
||||
_time = self.landedStatus[_lookupKeyHeli] - 10
|
||||
self.landedStatus[_lookupKeyHeli] = _time
|
||||
end
|
||||
if _time <= 0 or _distance < self.loadDistance then
|
||||
--if _time <= 0 or _distance < self.loadDistance then
|
||||
if _distance < self.loadDistance + 5 or _distance <= 13 then
|
||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_heliName) then
|
||||
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me in!", self.messageTime, true)
|
||||
return true
|
||||
@@ -1999,6 +2039,9 @@ function CSAR:onafterStart(From, Event, To)
|
||||
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
||||
end
|
||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
|
||||
if self.wetfeettemplate then
|
||||
self.usewetfeet = true
|
||||
end
|
||||
self:__Status(-10)
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1017,11 +1017,12 @@ CTLD.UnitTypes = {
|
||||
["Hercules"] = {type="Hercules", crates=true, troops=true, cratelimit = 7, trooplimit = 64, length = 25, cargoweightlimit = 19000}, -- 19t cargo, 64 paratroopers.
|
||||
--Actually it's longer, but the center coord is off-center of the model.
|
||||
["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats
|
||||
["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo
|
||||
}
|
||||
|
||||
--- CTLD class version.
|
||||
-- @field #string version
|
||||
CTLD.version="1.0.9"
|
||||
CTLD.version="1.0.10"
|
||||
|
||||
--- Instantiate a new CTLD.
|
||||
-- @param #CTLD self
|
||||
@@ -2095,11 +2096,18 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight)
|
||||
-- cycle
|
||||
local index = 0
|
||||
local found = {}
|
||||
local loadedmass = self:_GetUnitCargoMass(_unit)
|
||||
local unittype = _unit:GetTypeName()
|
||||
local capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
||||
local maxmass = capabilities.cargoweightlimit
|
||||
local maxloadable = maxmass - loadedmass
|
||||
local loadedmass = 0
|
||||
local unittype = "none"
|
||||
local capabilities = {}
|
||||
local maxmass = 2000
|
||||
local maxloadable = 2000
|
||||
if not _ignoreweight then
|
||||
loadedmass = self:_GetUnitCargoMass(_unit)
|
||||
unittype = _unit:GetTypeName()
|
||||
capabilities = self:_GetUnitCapabilities(_unit) -- #CTLD.UnitCapabilities
|
||||
maxmass = capabilities.cargoweightlimit or 2000
|
||||
maxloadable = maxmass - loadedmass
|
||||
end
|
||||
self:T(self.lid .. " Max loadable mass: " .. maxloadable)
|
||||
for _,_cargoobject in pairs (existingcrates) do
|
||||
local cargo = _cargoobject -- #CTLD_CARGO
|
||||
@@ -2256,6 +2264,7 @@ end
|
||||
-- @return #number mass in kgs
|
||||
function CTLD:_GetUnitCargoMass(Unit)
|
||||
self:T(self.lid .. " _GetUnitCargoMass")
|
||||
if not Unit then return 0 end
|
||||
local unitname = Unit:GetName()
|
||||
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
||||
local loadedmass = 0 -- #number
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
--
|
||||
-- Strategically important zones, which should be captured can be added via the @{#CHIEF.AddStrategicZone}() function.
|
||||
--
|
||||
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS mission is lauchned.
|
||||
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS and an ARTY mission are lauchned, provided assets are available.
|
||||
--
|
||||
-- Once the zone is cleaned of enemy forces, ground (infantry) troops are send there. These require a transportation via helicopters.
|
||||
-- So in order to deploy our own troops, infantry assets with `AUFTRAG.Type.ONGUARD` and helicopters with `AUFTRAG.Type.OPSTRANSPORT` need to be available.
|
||||
@@ -180,7 +180,7 @@ CHIEF.Strategy = {
|
||||
|
||||
--- CHIEF class version.
|
||||
-- @field #string version
|
||||
CHIEF.version="0.1.0"
|
||||
CHIEF.version="0.1.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -1731,7 +1731,7 @@ function CHIEF:CheckOpsZoneQueue()
|
||||
-- Has a patrol mission?
|
||||
local hasMissionPatrol=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ONGUARD) or stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARMOREDGUARD)
|
||||
-- Has a CAS mission?
|
||||
local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS)
|
||||
local hasMissionCAS=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
|
||||
-- Has a ARTY mission?
|
||||
local hasMissionARTY=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
||||
|
||||
@@ -1775,12 +1775,13 @@ function CHIEF:CheckOpsZoneQueue()
|
||||
|
||||
|
||||
-- Recruite CAS assets.
|
||||
local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CAS, 1, 1)
|
||||
local recruited=self:RecruitAssetsForZone(stratzone, AUFTRAG.Type.CASENHANCED, 1, 1)
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Zone is NOT empty ==> Recruit CAS assets=%s", tostring(recruited)))
|
||||
|
||||
end
|
||||
|
||||
if not hasMissionARTY then
|
||||
|
||||
-- Debug message.
|
||||
@@ -1811,7 +1812,7 @@ function CHIEF:CheckOpsZoneQueue()
|
||||
local hasMissionPATROL=stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.PATROLZONE)
|
||||
|
||||
-- Has a CAS mission?
|
||||
local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CAS)
|
||||
local hasMissionCAS, CASMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.CASENHANCED)
|
||||
local hasMissionARTY, ARTYMissions = stratzone.opszone:_FindMissions(self.coalition,AUFTRAG.Type.ARTY)
|
||||
|
||||
if ownercoalition==self.coalition and stratzone.opszone:IsEmpty() and hasMissionCAS then
|
||||
@@ -2208,7 +2209,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM
|
||||
end
|
||||
|
||||
-- Recruite infantry assets.
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, Categories, Attributes)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, Categories, Attributes)
|
||||
|
||||
if recruited then
|
||||
|
||||
@@ -2260,12 +2261,48 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM
|
||||
-- Attach mission to ops zone.
|
||||
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
||||
|
||||
-- Set ops zone to transport.
|
||||
transport.opszone=StratZone.opszone
|
||||
transport.chief=self
|
||||
transport.commander=self.commander
|
||||
|
||||
return true
|
||||
else
|
||||
LEGION.UnRecruitAssets(assets)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
||||
|
||||
-- Create Patrol zone mission.
|
||||
local caszone = StratZone.opszone.zone
|
||||
local coord = caszone:GetCoordinate()
|
||||
local height = UTILS.MetersToFeet(coord:GetLandHeight())+2500
|
||||
|
||||
local Speed = 200
|
||||
if assets[1] then
|
||||
if assets[1].speedmax then
|
||||
Speed = UTILS.KmphToKnots(assets[1].speedmax * 0.7) or 200
|
||||
end
|
||||
end
|
||||
|
||||
--local mission=AUFTRAG:NewCAS(caszone,height,Speed,coord,math.random(0,359),Leg)
|
||||
local mission=AUFTRAG:NewCASENHANCED(caszone, height, Speed)
|
||||
|
||||
-- Add assets to mission.
|
||||
for _,asset in pairs(assets) do
|
||||
mission:AddAsset(asset)
|
||||
end
|
||||
|
||||
-- Assign mission to legions.
|
||||
self:MissionAssign(mission, legions)
|
||||
|
||||
-- Attach mission to ops zone.
|
||||
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
||||
|
||||
return true
|
||||
|
||||
elseif MissionType==AUFTRAG.Type.CAS then
|
||||
|
||||
-- Create Patrol zone mission.
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
-- @field #string livery Livery of the cohort.
|
||||
-- @field #number skill Skill of cohort members.
|
||||
-- @field Ops.Legion#LEGION legion The LEGION object the cohort belongs to.
|
||||
-- @field #number Ngroups Number of asset OPS groups this cohort has.
|
||||
-- @field #number Ngroups Number of asset OPS groups this cohort has.
|
||||
-- @field #number Nkilled Number of destroyed asset groups.
|
||||
-- @field #number engageRange Mission range in meters.
|
||||
-- @field #string attribute Generalized attribute of the cohort template group.
|
||||
-- @field #table tacanChannel List of TACAN channels available to the cohort.
|
||||
@@ -67,6 +68,7 @@ COHORT = {
|
||||
skill = nil,
|
||||
legion = nil,
|
||||
Ngroups = nil,
|
||||
Ngroups = 0,
|
||||
engageRange = nil,
|
||||
tacanChannel = {},
|
||||
weightAsset = 99999,
|
||||
@@ -275,12 +277,10 @@ end
|
||||
|
||||
--- Set number of units in groups.
|
||||
-- @param #COHORT self
|
||||
-- @param #number nunits Number of units. Must be >=1 and <=4. Default 2.
|
||||
-- @param #number nunits Number of units. Default 2.
|
||||
-- @return #COHORT self
|
||||
function COHORT:SetGrouping(nunits)
|
||||
self.ngrouping=nunits or 2
|
||||
if self.ngrouping<1 then self.ngrouping=1 end
|
||||
if self.ngrouping>4 then self.ngrouping=4 end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -919,36 +919,38 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
|
||||
-- ARMY/NAVYGROUP combat ready?
|
||||
---
|
||||
|
||||
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
|
||||
--self:I("Attribute is: "..asset.attribute)
|
||||
if flightgroup:IsArmygroup() then
|
||||
-- check for fighting assets
|
||||
if asset.attribute == WAREHOUSE.Attribute.GROUND_ARTILLERY or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_TANK or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_INFANTRY or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_AAA or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_SAM
|
||||
then
|
||||
combatready=true
|
||||
end
|
||||
else
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- Not ready when rearming, retreating or returning!
|
||||
if flightgroup:IsRearming() or flightgroup:IsRetreating() or flightgroup:IsReturning() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Check transport/cargo for combat readyness!
|
||||
-- Not ready when currently acting as ops transport carrier.
|
||||
if flightgroup:IsLoading() or flightgroup:IsTransporting() or flightgroup:IsUnloading() or flightgroup:IsPickingup() or flightgroup:IsCarrier() then
|
||||
combatready=false
|
||||
end
|
||||
end
|
||||
-- Not ready when currently acting as ops transport cargo.
|
||||
if flightgroup:IsCargo() or flightgroup:IsBoarding() or flightgroup:IsAwaitingLift() then
|
||||
combatready=false
|
||||
end
|
||||
|
||||
-- Disable this for now as it can cause problems - at least with transport and cargo assets.
|
||||
--self:I("Attribute is: "..asset.attribute)
|
||||
if flightgroup:IsArmygroup() then
|
||||
-- check for fighting assets
|
||||
if asset.attribute == WAREHOUSE.Attribute.GROUND_ARTILLERY or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_TANK or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_INFANTRY or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_AAA or
|
||||
asset.attribute == WAREHOUSE.Attribute.GROUND_SAM
|
||||
then
|
||||
combatready=true
|
||||
end
|
||||
else
|
||||
combatready=false
|
||||
end
|
||||
|
||||
|
||||
-- This asset is "combatready".
|
||||
if combatready then
|
||||
self:T(self.lid.."Adding SPAWNED asset to ANOTHER mission as it is COMBATREADY")
|
||||
|
||||
@@ -132,7 +132,7 @@ COMMANDER = {
|
||||
|
||||
--- COMMANDER class version.
|
||||
-- @field #string version
|
||||
COMMANDER.version="0.1.0"
|
||||
COMMANDER.version="0.1.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -1190,7 +1190,7 @@ function COMMANDER:RecruitAssetsForMission(Mission)
|
||||
local Payloads=Mission.payloads
|
||||
|
||||
-- Recruite assets.
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem)
|
||||
|
||||
return recruited, assets, legions
|
||||
end
|
||||
@@ -1292,6 +1292,7 @@ function COMMANDER:CheckTransportQueue()
|
||||
|
||||
-- Weight of the heaviest cargo group. Necessary condition that this fits into on carrier unit!
|
||||
local weightGroup=0
|
||||
local TotalWeight=0
|
||||
|
||||
-- Calculate the max weight so we know which cohorts can provide carriers.
|
||||
if #cargoOpsGroups>0 then
|
||||
@@ -1301,13 +1302,14 @@ function COMMANDER:CheckTransportQueue()
|
||||
if weight>weightGroup then
|
||||
weightGroup=weight
|
||||
end
|
||||
TotalWeight=TotalWeight+weight
|
||||
end
|
||||
end
|
||||
|
||||
if weightGroup>0 then
|
||||
|
||||
-- Recruite assets from legions.
|
||||
local recruited, assets, legions=self:RecruitAssetsForTransport(transport, weightGroup)
|
||||
local recruited, assets, legions=self:RecruitAssetsForTransport(transport, weightGroup, TotalWeight)
|
||||
|
||||
if recruited then
|
||||
|
||||
@@ -1344,10 +1346,12 @@ end
|
||||
--- Recruit assets for a given OPS transport.
|
||||
-- @param #COMMANDER self
|
||||
-- @param Ops.OpsTransport#OPSTRANSPORT Transport The OPS transport.
|
||||
-- @param #number CargoWeight Weight of the heaviest cargo group.
|
||||
-- @param #number TotalWeight Total weight of all cargo groups.
|
||||
-- @return #boolean If `true`, enough assets could be recruited.
|
||||
-- @return #table Recruited assets.
|
||||
-- @return #table Legions that have recruited assets.
|
||||
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
|
||||
function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight, TotalWeight)
|
||||
|
||||
if CargoWeight==0 then
|
||||
-- No cargo groups!
|
||||
@@ -1381,7 +1385,7 @@ function COMMANDER:RecruitAssetsForTransport(Transport, CargoWeight)
|
||||
local NreqMin,NreqMax=Transport:GetRequiredCarriers()
|
||||
|
||||
-- Recruit assets and legions.
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, CargoWeight)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, CargoWeight, TotalWeight)
|
||||
|
||||
return recruited, assets, legions
|
||||
end
|
||||
|
||||
@@ -168,7 +168,7 @@ FLIGHTGROUP.Attribute = {
|
||||
|
||||
--- FLIGHTGROUP class version.
|
||||
-- @field #string version
|
||||
FLIGHTGROUP.version="0.7.0"
|
||||
FLIGHTGROUP.version="0.7.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -730,60 +730,6 @@ end
|
||||
-- Status
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---- Update status.
|
||||
-- @param #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:onbeforeStatus(From, Event, To)
|
||||
|
||||
-- First we check if elements are still alive. Could be that they were despawned without notice, e.g. when landing on a too small airbase.
|
||||
for i,_element in pairs(self.elements) do
|
||||
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
||||
|
||||
-- Check that element is not already dead or not yet alive.
|
||||
if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then
|
||||
|
||||
-- Unit shortcut.
|
||||
local unit=element.unit
|
||||
|
||||
local isdead=false
|
||||
if unit and unit:IsAlive() then
|
||||
|
||||
-- Get life points.
|
||||
local life=unit:GetLife() or 0
|
||||
|
||||
-- Units with life <=1 are dead.
|
||||
if life<=1 then
|
||||
--env.info(string.format("FF unit %s: live<=1 in status at T=%.3f", unit:GetName(), timer.getTime()))
|
||||
isdead=true
|
||||
end
|
||||
|
||||
else
|
||||
-- Not alive any more.
|
||||
--env.info(string.format("FF unit %s: NOT alive in status at T=%.3f", unit:GetName(), timer.getTime()))
|
||||
isdead=true
|
||||
end
|
||||
|
||||
-- This one is dead.
|
||||
if isdead then
|
||||
local text=string.format("Element %s is dead at t=%.3f but has status %s! Maybe despawned without notice or landed at a too small airbase. Calling ElementDead in 60 sec to give other events a chance",
|
||||
tostring(element.name), timer.getTime(), tostring(element.status))
|
||||
self:T(self.lid..text)
|
||||
self:__ElementDead(60, element)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
--- Status update.
|
||||
-- @param #FLIGHTGROUP self
|
||||
function FLIGHTGROUP:Status()
|
||||
@@ -845,7 +791,10 @@ function FLIGHTGROUP:Status()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
-- Check damage.
|
||||
self:_CheckDamage()
|
||||
end
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,13 +45,14 @@ LEGION = {
|
||||
|
||||
--- LEGION class version.
|
||||
-- @field #string version
|
||||
LEGION.version="0.2.0"
|
||||
LEGION.version="0.2.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Create FLEED class.
|
||||
-- DONE: Aircraft will not start hot on Alert5.
|
||||
-- DONE: OPS transport.
|
||||
-- DONE: Make general so it can be inherited by AIRWING and BRIGADE classes.
|
||||
|
||||
@@ -81,6 +82,10 @@ function LEGION:New(WarehouseName, LegionName)
|
||||
-- Defaults:
|
||||
-- TODO: What?
|
||||
self:SetMarker(false)
|
||||
|
||||
-- Dead and crash events are handled via opsgroups.
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self:UnHandleEvent(EVENTS.Dead)
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
@@ -530,6 +535,7 @@ function LEGION:CheckMissionQueue()
|
||||
local Transport=nil
|
||||
if mission.NcarriersMin then
|
||||
local Legions=mission.transportLegions or {self}
|
||||
|
||||
TransportAvail, Transport=self:AssignAssetsForTransport(Legions, assets, mission.NcarriersMin, mission.NcarriersMax, mission.transportDeployZone, mission.transportDisembarkZone)
|
||||
end
|
||||
|
||||
@@ -743,6 +749,10 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission)
|
||||
if Mission.missionTask then
|
||||
asset.missionTask=Mission.missionTask
|
||||
end
|
||||
|
||||
if Mission.type==AUFTRAG.Type.ALERT5 then
|
||||
asset.takeoffType=COORDINATE.WaypointType.TakeOffParking
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -882,7 +892,18 @@ function LEGION:onafterTransportCancel(From, Event, To, Transport)
|
||||
local cargos=Transport:GetCargoOpsGroups(false)
|
||||
for _,_cargo in pairs(cargos) do
|
||||
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
|
||||
|
||||
-- Remover my lift.
|
||||
cargo:_DelMyLift(Transport)
|
||||
|
||||
-- Legion of cargo group
|
||||
local legion=cargo.legion
|
||||
|
||||
-- Add asset back to legion.
|
||||
if legion then
|
||||
legion:T(self.lid..string.format("Adding cargo group %s back to legion", cargo:GetName()))
|
||||
legion:__AddAsset(0.1, cargo.group, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove asset from mission.
|
||||
@@ -993,7 +1014,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("New asset %s with assignment %s and request assignment %s", asset.spawngroupname, tostring(asset.assignment), tostring(assignment))
|
||||
self:T3(self.lid..text)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Get cohort.
|
||||
local cohort=self:_GetCohort(asset.assignment)
|
||||
@@ -1010,7 +1031,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
local nunits=#asset.template.units
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset to squadron %s: assignment=%s, type=%s, attribute=%s, nunits=%d %s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping))
|
||||
local text=string.format("Adding asset to squadron %s: assignment=%s, type=%s, attribute=%s, nunits=%d ngroup=%s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping))
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Adjust number of elements in the group.
|
||||
@@ -1018,6 +1039,10 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
local template=asset.template
|
||||
|
||||
local N=math.max(#template.units, cohort.ngrouping)
|
||||
|
||||
-- We need to recalc the total weight and cargo bay.
|
||||
asset.weight=0
|
||||
asset.cargobaytot=0
|
||||
|
||||
-- Handle units.
|
||||
for i=1,N do
|
||||
@@ -1028,15 +1053,28 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
-- If grouping is larger than units present, copy first unit.
|
||||
if i>nunits then
|
||||
table.insert(template.units, UTILS.DeepCopy(template.units[1]))
|
||||
asset.cargobaytot=asset.cargobaytot+asset.cargobay[1]
|
||||
asset.weight=asset.weight+asset.weights[1]
|
||||
template.units[i].x=template.units[1].x+5*(i-nunits)
|
||||
template.units[i].y=template.units[1].y+5*(i-nunits)
|
||||
else
|
||||
if i<=cohort.ngrouping then
|
||||
asset.weight=asset.weight+asset.weights[i]
|
||||
asset.cargobaytot=asset.cargobaytot+asset.cargobay[i]
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove units if original template contains more than in grouping.
|
||||
if cohort.ngrouping<nunits and i>nunits then
|
||||
unit=nil
|
||||
if i>cohort.ngrouping then
|
||||
template.units[i]=nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Set number of units.
|
||||
asset.nunits=cohort.ngrouping
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("After regrouping: Nunits=%d, weight=%.1f cargobaytot=%.1f kg", #asset.template.units, asset.weight, asset.cargobaytot))
|
||||
end
|
||||
|
||||
-- Set takeoff type.
|
||||
@@ -1061,6 +1099,11 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment)
|
||||
-- Asset is returned to the COHORT
|
||||
---
|
||||
|
||||
self:T(self.lid..string.format("Asset returned to legion ==> calling LegionAssetReturned event"))
|
||||
|
||||
-- Set takeoff type in case it was overwritten for an ALERT5 mission.
|
||||
asset.takeoffType=cohort.takeoffType
|
||||
|
||||
-- Trigger event.
|
||||
self:LegionAssetReturned(cohort, asset)
|
||||
|
||||
@@ -1078,7 +1121,7 @@ end
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
|
||||
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
|
||||
-- Debug message.
|
||||
self:T(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
||||
self:I(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
|
||||
|
||||
-- Stop flightgroup.
|
||||
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
|
||||
@@ -1246,7 +1289,7 @@ function LEGION:onafterAssetDead(From, Event, To, asset, request)
|
||||
-- Remove group from the detection set of the CHIEF (INTEL).
|
||||
if self.commander and self.commander.chief then
|
||||
self.commander.chief.detectionset:RemoveGroupsByName({asset.spawngroupname})
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove asset from mission is done via Mission:AssetDead() call from flightgroup onafterFlightDead function
|
||||
-- Remove asset from squadron same
|
||||
@@ -1809,7 +1852,7 @@ function LEGION:RecruitAssetsForMission(Mission)
|
||||
end
|
||||
|
||||
-- Recuit assets.
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem, nil)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, Mission.type, Mission.alert5MissionType, NreqMin, NreqMax, TargetVec2, Payloads, Mission.engageRange, Mission.refuelSystem)
|
||||
|
||||
return recruited, assets, legions
|
||||
end
|
||||
@@ -1826,17 +1869,20 @@ function LEGION:RecruitAssetsForTransport(Transport)
|
||||
local cargoOpsGroups=Transport:GetCargoOpsGroups(false)
|
||||
|
||||
local weightGroup=0
|
||||
local TotalWeight=nil
|
||||
|
||||
-- At least one group should be spawned.
|
||||
if #cargoOpsGroups>0 then
|
||||
|
||||
-- Calculate the max weight so we know which cohorts can provide carriers.
|
||||
TotalWeight=0
|
||||
for _,_opsgroup in pairs(cargoOpsGroups) do
|
||||
local opsgroup=_opsgroup --Ops.OpsGroup#OPSGROUP
|
||||
local weight=opsgroup:GetWeightTotal()
|
||||
if weight>weightGroup then
|
||||
weightGroup=weight
|
||||
end
|
||||
TotalWeight=TotalWeight+weight
|
||||
end
|
||||
else
|
||||
-- No cargo groups!
|
||||
@@ -1854,7 +1900,7 @@ function LEGION:RecruitAssetsForTransport(Transport)
|
||||
|
||||
|
||||
-- Recruit assets and legions.
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(self.cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, weightGroup)
|
||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(self.cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NreqMin, NreqMax, TargetVec2, nil, nil, nil, weightGroup, TotalWeight)
|
||||
|
||||
return recruited, assets, legions
|
||||
end
|
||||
@@ -1915,12 +1961,13 @@ end
|
||||
-- @param #number RangeMax Max range in meters.
|
||||
-- @param #number RefuelSystem Refuelsystem.
|
||||
-- @param #number CargoWeight Cargo weight for recruiting transport carriers.
|
||||
-- @param #number TotalWeight Total cargo weight in kg.
|
||||
-- @param #table Categories Group categories.
|
||||
-- @param #table Attributes Group attributes. See `GROUP.Attribute.`
|
||||
-- @return #boolean If `true` enough assets could be recruited.
|
||||
-- @return #table Recruited assets. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
|
||||
-- @return #table Legions of recruited assets.
|
||||
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, Categories, Attributes)
|
||||
function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt, NreqMin, NreqMax, TargetVec2, Payloads, RangeMax, RefuelSystem, CargoWeight, TotalWeight, Categories, Attributes)
|
||||
|
||||
-- The recruited assets.
|
||||
local Assets={}
|
||||
@@ -2055,10 +2102,30 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
||||
---
|
||||
|
||||
-- Add assets to mission.
|
||||
local cargobay=0
|
||||
for i=1,Nassets do
|
||||
local asset=Assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
|
||||
asset.isReserved=true
|
||||
|
||||
Legions[asset.legion.alias]=asset.legion
|
||||
|
||||
if TotalWeight then
|
||||
|
||||
-- Number of
|
||||
local N=math.floor(asset.cargobaytot/asset.nunits / CargoWeight)*asset.nunits
|
||||
--env.info(string.format("cargobaytot=%d, cargoweight=%d ==> N=%d", asset.cargobaytot, CargoWeight, N))
|
||||
|
||||
cargobay=cargobay + N*CargoWeight
|
||||
|
||||
if cargobay>=TotalWeight then
|
||||
--env.info(string.format("FF found enough assets to transport all cargo! N=%d [%d], cargobay=%.1f >= %.1f kg total weight", i, Nassets, cargobay, TotalWeight))
|
||||
Nassets=i
|
||||
break
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Return payloads of not needed assets.
|
||||
@@ -2153,7 +2220,7 @@ function LEGION:AssignAssetsForEscort(Cohorts, Assets, NescortMin, NescortMax)
|
||||
end
|
||||
|
||||
-- Recruit escort asset for the mission asset.
|
||||
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, Categories)
|
||||
local Erecruited, eassets, elegions=LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.ESCORT, nil, NescortMin, NescortMax, TargetVec2, nil, nil, nil, nil, nil, Categories)
|
||||
|
||||
if Erecruited then
|
||||
Escorts[asset.spawngroupname]={EscortLegions=elegions, EscortAssets=eassets, ecategory=asset.category, TargetTypes=TargetTypes}
|
||||
@@ -2264,13 +2331,14 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca
|
||||
end
|
||||
|
||||
-- Get all legions and heaviest cargo group weight
|
||||
local CargoLegions={} ; local CargoWeight=nil
|
||||
local CargoLegions={} ; local CargoWeight=nil ; local TotalWeight=0
|
||||
for _,_asset in pairs(CargoAssets) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
CargoLegions[asset.legion.alias]=asset.legion
|
||||
if CargoWeight==nil or asset.weight>CargoWeight then
|
||||
CargoWeight=asset.weight
|
||||
end
|
||||
TotalWeight=TotalWeight+asset.weight
|
||||
end
|
||||
|
||||
-- Target is the deploy zone.
|
||||
@@ -2278,7 +2346,7 @@ function LEGION:AssignAssetsForTransport(Legions, CargoAssets, NcarriersMin, Nca
|
||||
|
||||
-- Recruit assets and legions.
|
||||
local TransportAvail, CarrierAssets, CarrierLegions=
|
||||
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NcarriersMin, NcarriersMax, TargetVec2, nil, nil, nil, CargoWeight, Categories, Attributes)
|
||||
LEGION.RecruitCohortAssets(Cohorts, AUFTRAG.Type.OPSTRANSPORT, nil, NcarriersMin, NcarriersMax, TargetVec2, nil, nil, nil, CargoWeight, TotalWeight, Categories, Attributes)
|
||||
|
||||
if TransportAvail then
|
||||
|
||||
@@ -2396,12 +2464,34 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
|
||||
-- Reduce score for legions that are futher away.
|
||||
score=score-distance
|
||||
|
||||
-- Intercepts need to be carried out quickly. We prefer spawned assets.
|
||||
--if MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
if asset.spawned then
|
||||
score=score+25
|
||||
-- Intercepts need to be carried out quickly. We prefer spawned assets.
|
||||
if asset.spawned and asset.flightgroup and asset.flightgroup:IsAlive() then
|
||||
|
||||
local currmission=asset.flightgroup:GetMissionCurrent()
|
||||
|
||||
if currmission then
|
||||
|
||||
if currmission.type==AUFTRAG.Type.ALERT5 and currmission.alert5MissionType==MissionType then
|
||||
-- Prefer assets that are on ALERT5 for this mission type.
|
||||
score=score+25
|
||||
elseif currmission==AUFTRAG.Type.GCICAP and MissionType==AUFTRAG.Type.INTERCEPT then
|
||||
-- Prefer assets that are on GCICAP to perform INTERCEPTS
|
||||
score=score+25
|
||||
end
|
||||
end
|
||||
--end
|
||||
|
||||
if MissionType==AUFTRAG.Type.OPSTRANSPORT or MissionType==AUFTRAG.Type.AMMOSUPPLY or MissionType==AUFTRAG.Type.AWACS or MissionType==AUFTRAG.Type.FUELSUPPLY or MissionType==AUFTRAG.Type.TANKER then
|
||||
-- TODO: need to check for missions that do not require ammo like transport, recon, awacs, tanker etc.
|
||||
-- We better take a fresh asset. Sometimes spawned assets to something else, which is difficult to check.
|
||||
score=score-10
|
||||
else
|
||||
-- Combat mission.
|
||||
if asset.flightgroup:IsOutOfAmmo() then
|
||||
-- Assets that are out of ammo are not considered.
|
||||
score=score-1000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TRANSPORT specific.
|
||||
if MissionType==AUFTRAG.Type.OPSTRANSPORT then
|
||||
|
||||
@@ -90,7 +90,7 @@ NAVYGROUP = {
|
||||
|
||||
--- NavyGroup version.
|
||||
-- @field #string version
|
||||
NAVYGROUP.version="0.7.0"
|
||||
NAVYGROUP.version="0.7.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -760,6 +760,12 @@ function NAVYGROUP:Status(From, Event, To)
|
||||
|
||||
-- Check into wind queue.
|
||||
self:_CheckTurnsIntoWind()
|
||||
|
||||
-- Check ammo status.
|
||||
self:_CheckAmmoStatus()
|
||||
|
||||
-- Check damage of elements and group.
|
||||
self:_CheckDamage()
|
||||
|
||||
-- Check if group got stuck.
|
||||
self:_CheckStuck()
|
||||
@@ -775,6 +781,9 @@ function NAVYGROUP:Status(From, Event, To)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
-- Check damage of elements and group.
|
||||
self:_CheckDamage()
|
||||
end
|
||||
|
||||
-- Group exists but can also be inactive.
|
||||
@@ -1430,37 +1439,46 @@ function NAVYGROUP:_UpdateEngageTarget()
|
||||
|
||||
-- Get current position vector.
|
||||
local vec3=self.engage.Target:GetVec3()
|
||||
|
||||
if vec3 then
|
||||
|
||||
-- Distance to last known position of target.
|
||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||
|
||||
-- Check if target moved more than 100 meters.
|
||||
if dist>100 then
|
||||
|
||||
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
|
||||
|
||||
-- Update new position.
|
||||
self.engage.Coordinate:UpdateFromVec3(vec3)
|
||||
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Remove current waypoint
|
||||
self:RemoveWaypointByID(self.engage.Waypoint.uid)
|
||||
-- Distance to last known position of target.
|
||||
local dist=UTILS.VecDist3D(vec3, self.engage.Coordinate:GetVec3())
|
||||
|
||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||
-- Check if target moved more than 100 meters.
|
||||
if dist>100 then
|
||||
|
||||
--env.info("FF Update Engage Target Moved "..self.engage.Target:GetName())
|
||||
|
||||
-- Update new position.
|
||||
self.engage.Coordinate:UpdateFromVec3(vec3)
|
||||
|
||||
-- Add waypoint after current.
|
||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||
-- ID of current waypoint.
|
||||
local uid=self:GetWaypointCurrent().uid
|
||||
|
||||
-- Remove current waypoint
|
||||
self:RemoveWaypointByID(self.engage.Waypoint.uid)
|
||||
|
||||
local intercoord=self:GetCoordinate():GetIntermediateCoordinate(self.engage.Coordinate, 0.9)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
self.engage.Waypoint.detour=0
|
||||
-- Add waypoint after current.
|
||||
self.engage.Waypoint=self:AddWaypoint(intercoord, nil, uid, Formation, true)
|
||||
|
||||
-- Set if we want to resume route after reaching the detour waypoint.
|
||||
self.engage.Waypoint.detour=0
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||
self:Disengage()
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Target not alive any more == Disengage.
|
||||
-- Target not alive any more ==> Disengage.
|
||||
self:Disengage()
|
||||
|
||||
end
|
||||
|
||||
@@ -466,7 +466,7 @@ OPSGROUP.CargoStatus={
|
||||
|
||||
--- OpsGroup version.
|
||||
-- @field #string version
|
||||
OPSGROUP.version="0.7.5"
|
||||
OPSGROUP.version="0.7.6"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -541,6 +541,9 @@ function OPSGROUP:New(group)
|
||||
else
|
||||
|
||||
end
|
||||
|
||||
-- Set gen attribute.
|
||||
self.attribute=self.group:GetAttribute()
|
||||
|
||||
local units=self.group:GetUnits()
|
||||
|
||||
@@ -864,6 +867,12 @@ function OPSGROUP:GetLifePoints(Element)
|
||||
return life, life0
|
||||
end
|
||||
|
||||
--- Get generalized attribute.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #string Generalized attribute.
|
||||
function OPSGROUP:GetAttribute()
|
||||
return self.attribute
|
||||
end
|
||||
|
||||
--- Set verbosity level.
|
||||
-- @param #OPSGROUP self
|
||||
@@ -879,6 +888,7 @@ end
|
||||
-- @param Ops.Legion#LEGION Legion The Legion.
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:_SetLegion(Legion)
|
||||
self:T2(self.lid..string.format("Adding opsgroup to legion %s", Legion.alias))
|
||||
self.legion=Legion
|
||||
return self
|
||||
end
|
||||
@@ -1609,13 +1619,6 @@ function OPSGROUP:Despawn(Delay, NoEventRemoveUnit)
|
||||
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.Despawn, self, 0, NoEventRemoveUnit)
|
||||
else
|
||||
|
||||
if self.legion and not NoEventRemoveUnit then
|
||||
-- Add asset back in 10 seconds.
|
||||
self:T(self.lid..string.format("Despawning Group by adding asset to LEGION!"))
|
||||
self.legion:AddAsset(self.group, 1)
|
||||
return
|
||||
end
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Despawning Group!"))
|
||||
|
||||
@@ -1647,6 +1650,30 @@ function OPSGROUP:Despawn(Delay, NoEventRemoveUnit)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Return group back to the legion it belongs to.
|
||||
-- Group is despawned and added back to the stock.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number Delay Delay in seconds before the group will be despawned. Default immediately
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:ReturnToLegion(Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self.scheduleIDDespawn=self:ScheduleOnce(Delay, OPSGROUP.ReturnToLegion, self)
|
||||
else
|
||||
|
||||
if self.legion then
|
||||
-- Add asset back.
|
||||
self:T(self.lid..string.format("Adding asset back to LEGION"))
|
||||
self.legion:AddAsset(self.group, 1)
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: Group does not belong to a LEGION!"))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Destroy a unit of the group. A *Unit Lost* for aircraft or *Dead* event for ground/naval units is generated.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string UnitName Name of the unit which should be destroyed.
|
||||
@@ -1670,6 +1697,9 @@ function OPSGROUP:DestroyUnit(UnitName, Delay)
|
||||
else
|
||||
self:CreateEventDead(EventTime, unit)
|
||||
end
|
||||
|
||||
-- Despawn unit.
|
||||
unit:destroy()
|
||||
|
||||
end
|
||||
|
||||
@@ -2618,6 +2648,17 @@ function OPSGROUP:GetWaypointCurrent()
|
||||
return self.waypoints[self.currentwp]
|
||||
end
|
||||
|
||||
--- Get current waypoint UID.
|
||||
-- @param #OPSGROUP self
|
||||
-- @return #number Current waypoint UID.
|
||||
function OPSGROUP:GetWaypointCurrentUID()
|
||||
local wp=self:GetWaypointCurrent()
|
||||
if wp then
|
||||
return wp.uid
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get coordinate of next waypoint of the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #boolean cyclic If true, return first waypoint if last waypoint was reached.
|
||||
@@ -3574,8 +3615,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
--Coordinate:MarkToAll("Random Patrol Zone Coordinate")
|
||||
|
||||
-- Speed and altitude.
|
||||
local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
--local Speed=UTILS.KmphToKnots(Task.dcstask.params.speed or self.speedCruise)
|
||||
local Speed=Task.dcstask.params.speed and UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
||||
|
||||
local currUID=self:GetWaypointCurrent().uid
|
||||
@@ -3585,7 +3625,7 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
if self.isFlightgroup then
|
||||
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||
elseif self.isArmygroup then
|
||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation)
|
||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Task.dcstask.params.formation)
|
||||
elseif self.isNavygroup then
|
||||
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||
end
|
||||
@@ -3612,7 +3652,6 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
|
||||
-- Speed and altitude.
|
||||
local Speed=UTILS.MpsToKnots(Task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
--local Speed=UTILS.KmphToKnots(Task.dcstask.params.speed or self.speedCruise)
|
||||
local Altitude=Task.dcstask.params.altitude and UTILS.MetersToFeet(Task.dcstask.params.altitude) or nil
|
||||
|
||||
--Coordinate:MarkToAll("Recon Waypoint Execute")
|
||||
@@ -3673,7 +3712,6 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task)
|
||||
|
||||
-- BARRAGE is special!
|
||||
if Task.dcstask.id==AUFTRAG.SpecialTask.BARRAGE then
|
||||
env.info("FF Barrage")
|
||||
local vec2=self:GetVec2()
|
||||
local param=Task.dcstask.params
|
||||
local heading=param.heading or math.random(1, 360)
|
||||
@@ -4230,7 +4268,7 @@ function OPSGROUP:onafterMissionStart(From, Event, To, Mission)
|
||||
-- IMMOBILE Group
|
||||
---
|
||||
|
||||
env.info("FF Immobile GROUP")
|
||||
--env.info("FF Immobile GROUP")
|
||||
|
||||
-- Add waypoint task. UpdateRoute is called inside.
|
||||
local Clock=Mission.Tpush and UTILS.SecondsToClock(Mission.Tpush) or 5
|
||||
@@ -4580,13 +4618,22 @@ function OPSGROUP:RouteToMission(mission, delay)
|
||||
|
||||
-- Refresh DCS task with the known controllable.
|
||||
mission.DCStask=mission:GetDCSMissionTask(self.group)
|
||||
|
||||
-- Create a pickup zone around the pickup coordinate. The troops will go to a random point inside the zone.
|
||||
-- This is necessary so the helos do not try to land at the exact same location where the troops wait.
|
||||
local pradius=mission.transportPickupRadius
|
||||
local pickupZone=ZONE_RADIUS:New("Pickup Zone", mission.transportPickup:GetVec2(), pradius)
|
||||
|
||||
-- Add task to embark for the troops.
|
||||
for _,_group in pairs(mission.transportGroupSet.Set) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
|
||||
if group and group:IsAlive() then
|
||||
local DCSTask=group:TaskEmbarkToTransport(mission.transportPickup, 500)
|
||||
-- Get random coordinate inside the zone.
|
||||
local pcoord=pickupZone:GetRandomCoordinate(20, pradius, {land.SurfaceType.LAND, land.SurfaceType.ROAD})
|
||||
|
||||
-- Let the troops embark the transport.
|
||||
local DCSTask=group:TaskEmbarkToTransport(pcoord, pradius)
|
||||
group:SetTask(DCSTask, 5)
|
||||
end
|
||||
|
||||
@@ -4901,7 +4948,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
||||
local Coordinate=zone:GetRandomCoordinate(nil, nil, surfacetypes)
|
||||
|
||||
-- Speed and altitude.
|
||||
local Speed=UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
local Speed=task.dcstask.params.speed and UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
-- local Speed=UTILS.KmphToKnots(speed or self.speedCruise)
|
||||
local Altitude=UTILS.MetersToFeet(task.dcstask.params.altitude or self.altitudeCruise)
|
||||
|
||||
@@ -4911,7 +4958,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
||||
if self.isFlightgroup then
|
||||
wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||
elseif self.isArmygroup then
|
||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation)
|
||||
wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, task.dcstask.params.formation)
|
||||
elseif self.isNavygroup then
|
||||
wp=NAVYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Altitude)
|
||||
end
|
||||
@@ -4938,8 +4985,7 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint)
|
||||
local Coordinate=zone:GetRandomCoordinate()
|
||||
|
||||
-- Speed and altitude.
|
||||
local Speed=UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
--local Speed=UTILS.KmphToKnots(task.dcstask.params.speed or self.speedCruise)
|
||||
local Speed=task.dcstask.params.speed and UTILS.MpsToKnots(task.dcstask.params.speed) or UTILS.KmphToKnots(self.speedCruise)
|
||||
local Altitude=task.dcstask.params.altitude and UTILS.MetersToFeet(task.dcstask.params.altitude) or nil
|
||||
|
||||
-- Debug.
|
||||
@@ -5759,6 +5805,38 @@ function OPSGROUP:onafterElementInUtero(From, Event, To, Element)
|
||||
|
||||
end
|
||||
|
||||
--- On after "ElementDamaged" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #OPSGROUP.Element Element The flight group element.
|
||||
function OPSGROUP:onafterElementDamaged(From, Event, To, Element)
|
||||
self:T(self.lid..string.format("Element damaged %s", Element.name))
|
||||
|
||||
if Element and (Element.status~=OPSGROUP.ElementStatus.DEAD and Element.status~=OPSGROUP.ElementStatus.INUTERO) then
|
||||
|
||||
local lifepoints=0
|
||||
|
||||
if Element.DCSunit and Element.DCSunit:isExist() then
|
||||
|
||||
-- Get life of unit
|
||||
lifepoints=Element.DCSunit:getLife()
|
||||
|
||||
-- Debug output.
|
||||
self:T(self.lid..string.format("Element life %s: %.2f/%.2f", Element.name, lifepoints, Element.life0))
|
||||
|
||||
end
|
||||
|
||||
if lifepoints<=1.0 then
|
||||
self:T(self.lid..string.format("Element %s life %.2f <= 1.0 ==> Destroyed!", Element.name, lifepoints))
|
||||
self:ElementDestroyed(Element)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "ElementDestroyed" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
@@ -5793,7 +5871,7 @@ end
|
||||
function OPSGROUP:onafterElementDead(From, Event, To, Element)
|
||||
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
||||
self:I(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
|
||||
|
||||
-- Set element status.
|
||||
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
|
||||
@@ -5890,6 +5968,80 @@ function OPSGROUP:onafterRespawn(From, Event, To, Template)
|
||||
|
||||
end
|
||||
|
||||
--- Teleport the group to a different location.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate where the group is teleported to.
|
||||
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:Teleport(Coordinate, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, OPSGROUP.Teleport, self, Coordinate)
|
||||
else
|
||||
|
||||
-- Debug message.
|
||||
self:T(self.lid.."FF Teleporting...")
|
||||
--Coordinate:MarkToAll("Teleport "..self.groupname)
|
||||
|
||||
-- Check if we have a mission running.
|
||||
if self.currentmission>0 then
|
||||
self:T(self.lid.."Pausing current mission")
|
||||
self:PauseMission()
|
||||
end
|
||||
|
||||
-- Get copy of template.
|
||||
local Template=UTILS.DeepCopy(self.template) --DCS#Template
|
||||
|
||||
-- Template units.
|
||||
local units=Template.units
|
||||
|
||||
-- Table with teleported vectors.
|
||||
local d={}
|
||||
for i=1,#units do
|
||||
local unit=units[i]
|
||||
d[i]={x=Coordinate.x+(units[i].x-units[1].x), y=Coordinate.z+units[i].y-units[1].y}
|
||||
--COORDINATE:NewFromVec2(d[i]):MarkToAll(unit.name.." teleported")
|
||||
end
|
||||
|
||||
for i=#units,1,-1 do
|
||||
local unit=units[i]
|
||||
|
||||
-- Get element.
|
||||
local element=self:GetElementByName(unit.name)
|
||||
|
||||
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||
|
||||
-- No parking.
|
||||
unit.parking=nil
|
||||
unit.parking_id=nil
|
||||
|
||||
-- Current position.
|
||||
local vec3=element.unit:GetVec3()
|
||||
|
||||
-- Current heading.
|
||||
local heading=element.unit:GetHeading()
|
||||
|
||||
-- Set new x,y.
|
||||
unit.x=d[i].x
|
||||
unit.y=d[i].y
|
||||
|
||||
-- Set altitude.
|
||||
unit.alt=Coordinate.y
|
||||
|
||||
-- Set heading.
|
||||
unit.heading=math.rad(heading)
|
||||
unit.psi=-unit.heading
|
||||
else
|
||||
table.remove(units, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- Respawn from new template.
|
||||
self:_Respawn(0, Template, true)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- Respawn the group.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
||||
@@ -5905,58 +6057,60 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
||||
-- Debug message.
|
||||
self:T2(self.lid.."FF _Respawn")
|
||||
|
||||
-- Given template or get old.
|
||||
-- Given template or get copy of old.
|
||||
Template=Template or self:_GetTemplate(true)
|
||||
|
||||
-- Number of destroyed units.
|
||||
self.Ndestroyed=0
|
||||
|
||||
-- Check if group is currently alive.
|
||||
if self:IsAlive() then
|
||||
|
||||
---
|
||||
-- Group is ALIVE
|
||||
---
|
||||
|
||||
--[[
|
||||
|
||||
-- Get units.
|
||||
local units=self.group:GetUnits()
|
||||
|
||||
-- Loop over template units.
|
||||
for UnitID, Unit in pairs(Template.units) do
|
||||
|
||||
for _,_unit in pairs(units) do
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
if unit:GetName()==Unit.name then
|
||||
local vec3=unit:GetVec3()
|
||||
local heading=unit:GetHeading()
|
||||
Unit.x=vec3.x
|
||||
Unit.y=vec3.z
|
||||
Unit.alt=vec3.y
|
||||
Unit.heading=math.rad(heading)
|
||||
Unit.psi=-Unit.heading
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
]]
|
||||
|
||||
-- Template units.
|
||||
local units=Template.units
|
||||
|
||||
for i=#units,1,-1 do
|
||||
local unit=units[i]
|
||||
|
||||
-- Get the element.
|
||||
local element=self:GetElementByName(unit.name)
|
||||
|
||||
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||
unit.parking=element.parking and element.parking.TerminalID or unit.parking
|
||||
unit.parking_id=nil
|
||||
local vec3=element.unit:GetVec3()
|
||||
local heading=element.unit:GetHeading()
|
||||
unit.x=vec3.x
|
||||
unit.y=vec3.z
|
||||
unit.alt=vec3.y
|
||||
unit.heading=math.rad(heading)
|
||||
unit.psi=-unit.heading
|
||||
|
||||
if not Reset then
|
||||
|
||||
-- Parking ID.
|
||||
unit.parking=element.parking and element.parking.TerminalID or unit.parking
|
||||
unit.parking_id=nil
|
||||
|
||||
-- Get current position vector.
|
||||
local vec3=element.unit:GetVec3()
|
||||
|
||||
-- Get heading.
|
||||
local heading=element.unit:GetHeading()
|
||||
|
||||
-- Set unit position.
|
||||
unit.x=vec3.x
|
||||
unit.y=vec3.z
|
||||
unit.alt=vec3.y
|
||||
|
||||
-- Set heading in rad.
|
||||
unit.heading=math.rad(heading)
|
||||
unit.psi=-unit.heading
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Element is dead. Remove from template.
|
||||
table.remove(units, i)
|
||||
|
||||
self.Ndestroyed=self.Ndestroyed+1
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5967,7 +6121,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
||||
else
|
||||
|
||||
---
|
||||
-- Group is DESPAWNED
|
||||
-- Group is NOT ALIVE
|
||||
---
|
||||
|
||||
-- Ensure elements in utero.
|
||||
@@ -5997,8 +6151,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
||||
self.isDestroyed=false
|
||||
|
||||
|
||||
self.groupinitialized=false
|
||||
self.Ndestroyed=0
|
||||
self.groupinitialized=false
|
||||
self.wpcounter=1
|
||||
self.currentwp=1
|
||||
|
||||
@@ -6007,7 +6160,7 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
||||
|
||||
-- Init Group.
|
||||
self:_InitGroup(Template)
|
||||
|
||||
|
||||
-- Reset events.
|
||||
--self:ResetEvents()
|
||||
|
||||
@@ -6074,6 +6227,19 @@ function OPSGROUP:onbeforeDead(From, Event, To)
|
||||
end
|
||||
end
|
||||
|
||||
--- Cancel all missions in mission queue.
|
||||
-- @param #OPSGROUP self
|
||||
function OPSGROUP:CancelAllMissions()
|
||||
|
||||
-- Cancel all missions.
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
self:T(self.lid.."Cancelling mission "..tostring(mission:GetName()))
|
||||
self:MissionCancel(mission)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "Dead" event.
|
||||
-- @param #OPSGROUP self
|
||||
-- @param #string From From state.
|
||||
@@ -6131,12 +6297,31 @@ function OPSGROUP:onafterDead(From, Event, To)
|
||||
-- All elements were destroyed ==> Asset group is gone.
|
||||
self.cohort:DelGroup(self.groupname)
|
||||
end
|
||||
if self.legion then
|
||||
--self.legion:Get
|
||||
--self.legion:AssetDead()
|
||||
end
|
||||
else
|
||||
-- Not all assets were destroyed (despawn) ==> Add asset back to legion?
|
||||
end
|
||||
|
||||
-- Stop in a sec.
|
||||
--self:__Stop(-5)
|
||||
|
||||
if self.legion then
|
||||
if not self:IsInUtero() then
|
||||
|
||||
-- Get asset.
|
||||
local asset=self.legion:GetAssetByName(self.groupname)
|
||||
|
||||
-- Get request.
|
||||
local request=self.legion:GetRequestByID(asset.rid)
|
||||
|
||||
-- Trigger asset dead event.
|
||||
self.legion:AssetDead(asset, request)
|
||||
end
|
||||
|
||||
-- Stop in 5 sec to give possible respawn attempts a chance.
|
||||
self:__Stop(-5)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On before "Stop" event.
|
||||
@@ -6178,6 +6363,11 @@ function OPSGROUP:onafterStop(From, Event, To)
|
||||
self:UnHandleEvent(EVENTS.Crash)
|
||||
self.currbase=nil
|
||||
end
|
||||
|
||||
for _,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
self:MissionCancel(mission)
|
||||
end
|
||||
|
||||
-- Stop check timers.
|
||||
self.timerCheckZone:Stop()
|
||||
@@ -7993,6 +8183,12 @@ end
|
||||
-- @param #OPSGROUP OpsGroupCargo Cargo OPSGROUP that was unloaded from a carrier.
|
||||
function OPSGROUP:onafterUnloaded(From, Event, To, OpsGroupCargo)
|
||||
self:T(self.lid..string.format("Unloaded OPSGROUP %s", OpsGroupCargo:GetName()))
|
||||
|
||||
if OpsGroupCargo.legion and OpsGroupCargo:IsInZone(OpsGroupCargo.legion.spawnzone) then
|
||||
self:T(self.lid..string.format("Unloaded group %s returned to legion", OpsGroupCargo:GetName()))
|
||||
OpsGroupCargo:Returned()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -8530,18 +8726,24 @@ function OPSGROUP:_CheckGroupDone(delay)
|
||||
return
|
||||
end
|
||||
|
||||
-- Group is returning
|
||||
-- Group is returning.
|
||||
if self:IsReturning() then
|
||||
self:T(self.lid.."Returning! Group NOT done...")
|
||||
return
|
||||
end
|
||||
|
||||
-- Group is returning
|
||||
-- Group is rearming.
|
||||
if self:IsRearming() then
|
||||
self:T(self.lid.."Rearming! Group NOT done...")
|
||||
return
|
||||
end
|
||||
|
||||
-- Group is retreating.
|
||||
if self:IsRetreating() then
|
||||
self:T(self.lid.."Retreating! Group NOT done...")
|
||||
return
|
||||
end
|
||||
|
||||
-- Group is waiting. We deny all updates.
|
||||
if self:IsWaiting() then
|
||||
-- If group is waiting, we assume that is the way it is meant to be.
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
-- @field #table statusLegion Transport status of all assigned LEGIONs.
|
||||
-- @field #string statusCommander Staus of the COMMANDER.
|
||||
-- @field Ops.Commander#COMMANDER commander Commander of the transport.
|
||||
-- @field Ops.Chief#CHIEF chief Chief of the transport.
|
||||
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
|
||||
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
|
||||
--
|
||||
-- @extends Core.Fsm#FSM
|
||||
@@ -1305,7 +1307,7 @@ function OPSTRANSPORT:GetNcarrier()
|
||||
return self.Ncarrier
|
||||
end
|
||||
|
||||
--- Add asset to transport.
|
||||
--- Add carrier asset to transport.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added.
|
||||
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
|
||||
@@ -1323,7 +1325,7 @@ function OPSTRANSPORT:AddAsset(Asset, TransportZoneCombo)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Delete asset from mission.
|
||||
--- Delete carrier asset from transport.
|
||||
-- @param #OPSTRANSPORT self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed.
|
||||
-- @return #OPSTRANSPORT self
|
||||
@@ -1736,12 +1738,12 @@ function OPSTRANSPORT:onafterDeadCarrierGroup(From, Event, To, OpsGroup)
|
||||
-- Increase dead counter.
|
||||
self.NcarrierDead=self.NcarrierDead+1
|
||||
|
||||
if #self.carriers==0 then
|
||||
self:DeadCarrierAll()
|
||||
end
|
||||
|
||||
-- Remove group from carrier list/table.
|
||||
self:_DelCarrier(OpsGroup)
|
||||
|
||||
if #self.carriers==0 then
|
||||
self:DeadCarrierAll()
|
||||
end
|
||||
end
|
||||
|
||||
--- On after "DeadCarrierAll" event.
|
||||
@@ -1750,15 +1752,30 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function OPSTRANSPORT:onafterDeadCarrierAll(From, Event, To)
|
||||
self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead! Setting stage to PLANNED if not all cargo was delivered."))
|
||||
self:I(self.lid..string.format("ALL Carrier OPSGROUPs are dead!"))
|
||||
|
||||
if self.opszone then
|
||||
|
||||
self:I(self.lid..string.format("Cancelling transport on CHIEF level"))
|
||||
self.chief:TransportCancel(self)
|
||||
|
||||
--for _,_legion in pairs(self.legions) do
|
||||
-- local legion=_legion --Ops.Legion#LEGION
|
||||
-- legion:TransportCancel(self)
|
||||
--end
|
||||
|
||||
else
|
||||
|
||||
-- Check if cargo was delivered.
|
||||
self:_CheckDelivered()
|
||||
-- Check if cargo was delivered.
|
||||
self:_CheckDelivered()
|
||||
|
||||
-- Set state back to PLANNED if not delivered.
|
||||
if not self:IsDelivered() then
|
||||
self:Planned()
|
||||
end
|
||||
|
||||
-- Set state back to PLANNED if not delivered.
|
||||
if not self:IsDelivered() then
|
||||
self:Planned()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after "Cancel" event.
|
||||
|
||||
Reference in New Issue
Block a user