Ops group

This commit is contained in:
Frank 2020-08-03 00:31:10 +02:00
parent d1a18913f3
commit 11ec70441a
6 changed files with 186 additions and 126 deletions

View File

@ -14,6 +14,7 @@
--- ARMYGROUP class.
-- @type ARMYGROUP
-- @field #boolean adinfinitum Resume route at first waypoint when final waypoint is reached.
-- @field #boolean formationPerma Formation that is used permanently and overrules waypoint formations.
-- @extends Ops.OpsGroup#OPSGROUP
--- *Your soul may belong to Jesus, but your ass belongs to the marines.* -- Eugene B. Sledge
@ -29,6 +30,7 @@
-- @field #ARMYGROUP
ARMYGROUP = {
ClassName = "ARMYGROUP",
formationPerma = nil,
}
--- Navy group element.
@ -235,8 +237,8 @@ function ARMYGROUP:onafterStatus(From, Event, To)
local nMissions=self:CountRemainingMissison()
-- Info text.
local text=string.format("State %s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
fsmstate, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), speed, UTILS.MpsToKnots(self.speed), hdg, self.roe, self.alarmstate, self.formation, nTaskTot, nMissions)
local text=string.format("%s: Wp=%d/%d-->%d Speed=%.1f (%d) Heading=%03d ROE=%d Alarm=%d Formation=%s Tasks=%d Missions=%d",
fsmstate, self.currentwp, #self.waypoints, self:GetWaypointIndexNext(), speed, UTILS.MpsToKnots(self.speed), hdg, self.option.ROE, self.option.Alarm, self.option.Formation, nTaskTot, nMissions)
self:I(self.lid..text)
else
@ -397,13 +399,13 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
if Speed then
wp.speed=UTILS.KnotsToMps(Speed)
elseif self.speedCruise then
wp.speed=UTILS.KmphToMps(self.speedCruise)
else
-- Take default waypoint speed.
end
if Formation then
if self.formationPerma then
wp.action=self.formationPerma
elseif Formation then
wp.action=Formation
end
@ -419,8 +421,8 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
-- Later Waypoint(s)
---
if self.speedCruise then
wp.speed=UTILS.KmphToMps(self.speedCruise)
if self.formationPerma then
wp.action=self.formationPerma
else
-- Take default waypoint speed.
end
@ -454,8 +456,9 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, Speed, Formation)
-- No waypoints left
---
self:I(self.lid..string.format("No waypoints left"))
self:E(self.lid..string.format("WARNING: No waypoints left ==> Full Stop!"))
self:FullStop()
end
end
@ -742,8 +745,11 @@ function ARMYGROUP:_InitGroup()
-- Max speed in km/h.
self.speedmax=self.group:GetSpeedMax()
-- Cruise speed in km/h
self.speedCruise=self.speedmax*0.7
-- Group ammo.
--self.ammo=self:GetAmmoTot()
self.ammo=self:GetAmmoTot()
self.traveldist=0
self.traveltime=timer.getAbsTime()
@ -752,20 +758,15 @@ function ARMYGROUP:_InitGroup()
-- Radio parameters from template.
self.radioOn=false -- Radio is always OFF for ground.
-- If not set by the use explicitly yet, we take the template values as defaults.
if not self.radioFreqDefault then
self.radioFreqDefault=self.radioFreq
self.radioModuDefault=self.radioModu
end
-- We set some values.
self.radioDefault.Freq=133
self.radioDefault.Modu=radio.modulation.AM
self.radio.Freq=133
self.radio.Modu=radio.modulation.AM
-- Set default formation.
if not self.formationDefault then
if self.ishelo then
self.formationDefault=ENUMS.Formation.RotaryWing.EchelonLeft.D300
else
self.formationDefault=ENUMS.Formation.FixedWing.EchelonLeft.Group
end
end
-- Set default formation from first waypoint.
self.option.Formation=self:GetWaypoint(1).action
self.optionDefault.Formation=self.option.Formation
-- Units of the group.
local units=self.group:GetUnits()
@ -801,11 +802,11 @@ function ARMYGROUP:_InitGroup()
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
text=text..string.format("AC type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedmax))
--text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
--text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
--text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radioOn))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))
@ -823,17 +824,40 @@ end
-- Option Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Switch to a specific formation.
-- @param #ARMYGROUP self
-- @param #number Formation New formation the group will fly in. Default is the setting of `SetDefaultFormation()`.
-- @param #boolean Permanently If true, formation always used from now on.
-- @return #ARMYGROUP self
function ARMYGROUP:SwitchFormation(Formation, Permanently)
if self:IsAlive() then
Formation=Formation or self.optionDefault.Formation
if Permanently then
self.formationPerma=Formation
else
self.formationPerma=nil
end
-- Set current formation.
self.option.Formation=Formation
self:__UpdateRoute(-1, nil, nil, Formation)
-- Debug info.
self:I(self.lid..string.format("Switching formation to %s (permanently=%s)", self.option.Formation, tostring(Permanently)))
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Misc Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get default cruise speed.
-- @param #ARMYGROUP self
-- @return #number Cruise speed (>0) in knots.
function ARMYGROUP:GetSpeedCruise()
return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7)
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -26,7 +26,7 @@
-- @field #number ceiling Max altitude the aircraft can fly at in meters.
-- @field #number tankertype The refueling system type (0=boom, 1=probe), if the group is a tanker.
-- @field #number refueltype The refueling system type (0=boom, 1=probe), if the group can refuel from a tanker.
-- @field #FLIGHTGROUP.Ammo ammo Ammunition data. Number of Guns, Rockets, Bombs, Missiles.
-- @field Ops.OpsGroup#OPSGROUP.Ammo ammo Ammunition data. Number of Guns, Rockets, Bombs, Missiles.
-- @field #boolean ai If true, flight is purely AI. If false, flight contains at least one human player.
-- @field #boolean fuellow Fuel low switch.
-- @field #number fuellowthresh Low fuel threshold in percent.
@ -1395,18 +1395,18 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
self:SwitchROT(self.option.ROT)
-- Turn TACAN beacon on.
if self.tacanDefault then
if self.tacanDefault and self.tacanDefault.Channel then
self:SwitchTACAN(self.tacanDefault.Channel, self.tacanDefault.Morse)
end
-- Turn on the radio.
if self.radioDefault then
if self.radioDefault and self.radioDefault.Freq then
self:SwitchRadio(self.radioDefault.Freq, self.radioDefault.Modu)
end
-- Set callsign.
if self.callsignDefault then
self:SwitchCallsign(self.callsignDefault.Name, self.callsignNumberDefault)
if self.callsignDefault and self.callsignDefault.NameSquad then
--self:SwitchCallsign(self.callsignDefault.Name, self.callsignNumberDefault)
end
-- TODO: make this input.

View File

@ -175,18 +175,6 @@ function NAVYGROUP:SetPatrolAdInfinitum(switch)
return self
end
--- Set default cruise speed. This is the speed a group will take by default if no speed is specified explicitly.
-- @param #NAVYGROUP self
-- @param #number Speed Speed in knots. Default 70% of max speed.
-- @return #NAVYGROUP self
function NAVYGROUP:SetSpeedCruise(Speed)
self.speedCruise=Speed and UTILS.KnotsToKmph(Speed) or self.speedmax*0.7
return self
end
--- Add a *scheduled* task.
-- @param #NAVYGROUP self
-- @param Core.Point#COORDINATE Coordinate Coordinate of the target.
@ -1065,7 +1053,7 @@ function NAVYGROUP:_InitGroup()
self.speedCruise=self.speedmax*0.7
-- Group ammo.
--self.ammo=self:GetAmmoTot()
self.ammo=self:GetAmmoTot()
self.traveldist=0
self.traveltime=timer.getAbsTime()
@ -1073,23 +1061,14 @@ function NAVYGROUP:_InitGroup()
-- Radio parameters from template.
self.radioOn=true -- Radio is always on for ships.
self.radioFreq=tonumber(self.template.units[1].frequency)/1000000
self.radioModu=tonumber(self.template.units[1].modulation)/1000000
self.radio.Freq=tonumber(self.template.units[1].frequency)/1000000
self.radio.Modu=tonumber(self.template.units[1].modulation)
self.radioDefault.Freq=self.radio.Freq
self.radioDefault.Modu=self.radio.Modu
-- If not set by the use explicitly yet, we take the template values as defaults.
if not self.radioFreqDefault then
self.radioFreqDefault=self.radioFreq
self.radioModuDefault=self.radioModu
end
-- Set default formation.
if not self.formationDefault then
if self.ishelo then
self.formationDefault=ENUMS.Formation.RotaryWing.EchelonLeft.D300
else
self.formationDefault=ENUMS.Formation.FixedWing.EchelonLeft.Group
end
end
-- Set default formation. No really applicable for ships.
self.optionDefault.Formation="Off Road"
self.option.Formation=self.optionDefault.Formation
-- Get all units of the group.
local units=self.group:GetUnits()
@ -1125,11 +1104,11 @@ function NAVYGROUP:_InitGroup()
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
text=text..string.format("AC type = %s\n", self.actype)
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedmax))
--text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
text=text..string.format("Elements = %d\n", #self.elements)
text=text..string.format("Waypoints = %d\n", #self.waypoints)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radioFreq, UTILS.GetModulationName(self.radioModu), tostring(self.radioOn))
--text=text..string.format("Ammo = %d (G=%d/R=%d/B=%d/M=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Bombs, self.ammo.Missiles)
text=text..string.format("Radio = %.1f MHz %s %s\n", self.radio.Freq, UTILS.GetModulationName(self.radio.Modu), tostring(self.radioOn))
text=text..string.format("Ammo = %d (G=%d/R=%d/M=%d/T=%d)\n", self.ammo.Total, self.ammo.Guns, self.ammo.Rockets, self.ammo.Missiles, self.ammo.Torpedos)
text=text..string.format("FSM state = %s\n", self:GetState())
text=text..string.format("Is alive = %s\n", tostring(self.group:IsAlive()))
text=text..string.format("LateActivate = %s\n", tostring(self:IsLateActivated()))

View File

@ -215,10 +215,10 @@ OPSGROUP.TaskType={
--- Callsign data.
-- @type OPSGROUP.Callsign
-- @field #number NumberS Squadron name number.
-- @field #number NumberG Group number.
-- @field #number NumberE Element number.
-- @field #string NameGroup Name of the group, e.g. Uzi.
-- @field #number NumberSquad Squadron number corresponding to a name like "Uzi".
-- @field #number NumberGroup Group number. First number after name, e.g. "Uzi-**1**-1".
-- @field #number NumberElement Element number.Second number after name, e.g. "Uzi-1-**1**"
-- @field #string NameSquad Name of the squad, e.g. "Uzi".
-- @field #string NameElement Name of group element, e.g. Uzi 11.
--- Option data.
@ -401,6 +401,24 @@ function OPSGROUP:GetLifePoints()
end
end
--- Set default cruise speed..
-- @param #OPSGROUP self
-- @param #number Speed Speed in knots.
-- @return #OPSGROUP self
function OPSGROUP:SetDefaultSpeed(Speed)
if Speed then
self.speedCruise=UTILS.KnotsToKmph(Speed)
end
return self
end
--- Get default cruise speed.
-- @param #OPSGROUP self
-- @return #number Cruise speed (>0) in knots.
function OPSGROUP:GetSpeedCruise()
return UTILS.KmphToKnots(self.speedCruise or self.speedmax*0.7)
end
--- Set detection on or off.
-- @param #OPSGROUP self
-- @param #boolean Switch If true, detection is on. If false or nil, detection is off. Default is off.
@ -2922,7 +2940,7 @@ end
-- @return #OPSGROUP self
function OPSGROUP:SwitchTACAN(Channel, Morse, UnitName, Band)
if self:IsAlive() then
if self:IsAlive() and Channel then
local unit=self.group:GetUnit(1) --Wrapper.Unit#UNIT
@ -2971,7 +2989,7 @@ function OPSGROUP:SwitchTACAN(Channel, Morse, UnitName, Band)
-- TACAN is now on.
self.tacanOn=true
self:I(self.lid..string.format("Switching TACAN to Channel %d%s Morse %s on unit %s", self.tacan.Channel, self.tacan.Band, tostring(self.tacan.Morse), self.tacan.UnitName))
self:I(self.lid..string.format("Switching TACAN to Channel %d%s Morse %s on unit %s", self.tacan.Channel, self.tacan.Band, tostring(self.tacan.Morse), self.tacan.BeaconName))
else
@ -2987,7 +3005,7 @@ end
--- Deactivate TACAN beacon.
-- @param #OPSGROUP self
-- @return #OPSGROUP self
function OPSGROUP:SwitchTACANOff()
function OPSGROUP:TurnOffTACAN()
if self.tacan.BeaconUnit and self.tacan.BeaconUnit:IsAlive() then
self.tacan.BeaconUnit:CommandDeactivateBeacon()
@ -3028,7 +3046,7 @@ function OPSGROUP:SwitchRadio(Frequency, Modulation)
if self:IsAlive() and Frequency then
Modulation=Modulation or radio.Modulation.AM
Modulation=Modulation or (self.radioDefault.Modu or radio.Modulation.AM)
local group=self.group --Wrapper.Group#GROUP
@ -3054,19 +3072,25 @@ end
--- Turn radio off.
-- @param #OPSGROUP self
-- @return #OPSGROUP self
function OPSGROUP:TurnRadioOff()
function OPSGROUP:TurnOffRadio()
if self:IsAlive() then
self.group:SetOption(AI.Option.Air.id.SILENCE, true)
--self.radioFreq=nil
--self.radioModu=nil
if self.isAircraft then
-- Radio is off.
self.radioOn=false
self:I(self.lid..string.format("Switching radio OFF"))
-- Set group to be silient.
self.group:SetOption(AI.Option.Air.id.SILENCE, true)
--self.radio.Freq=nil
--self.radio.Modu=nil
-- Radio is off.
self.radioOn=false
self:I(self.lid..string.format("Switching radio OFF"))
else
self:E(self.lid.."ERROR radio can only be turned off for aircraft!")
end
end
@ -3078,24 +3102,39 @@ end
-- @param #number Formation The formation the groups flies in.
-- @return #OPSGROUP self
function OPSGROUP:SetDefaultFormation(Formation)
self.formationDefault=Formation
self.optionDefault.Formation=Formation
return self
end
--- Switch to a specific formation.
-- @param #OPSGROUP self
-- @param #number Formation New formation the group will fly in.
-- @param #number Formation New formation the group will fly in. Default is the setting of `SetDefaultFormation()`.
-- @return #OPSGROUP self
function OPSGROUP:SwitchFormation(Formation)
if self:IsAlive() and Formation then
self.group:SetOption(AI.Option.Air.id.FORMATION, Formation)
if self:IsAlive() then
Formation=Formation or self.optionDefault.Formation
self.formation=Formation
if self.isAircraft then
self.group:SetOption(AI.Option.Air.id.FORMATION, Formation)
elseif self.isGround then
-- TODO: here we need to update the route.
else
self:E(self.lid.."ERROR: Formation can only be set for aircraft or ground units!")
return self
end
-- Set current formation.
self.option.Formation=Formation
-- Debug info.
self:I(self.lid..string.format("Switching formation to %d", self.formation))
end
@ -3110,8 +3149,8 @@ end
-- @return #OPSGROUP self
function OPSGROUP:SetDefaultCallsign(CallsignName, CallsignNumber)
self.callsignDefault.Name=CallsignName
self.callsignDefault.NumberG=CallsignNumber or 1
self.callsignDefault.NumberSquad=CallsignName
self.callsignDefault.NumberGroup=CallsignNumber or 1
return self
end
@ -3123,16 +3162,16 @@ end
-- @return #OPSGROUP self
function OPSGROUP:SwitchCallsign(CallsignName, CallsignNumber)
if self:IsAlive() and CallsignName then
if self:IsAlive() then
self.callsignName=CallsignName
self.callsignNumber=CallsignNumber or 1
self.callsign.NumberSquad=CallsignName or self.callsignDefault.NumberSquad
self.callsign.NumberGroup=CallsignNumber or self.callsignDefault.NumberGroup
self:I(self.lid..string.format("Switching callsign to %d-%d", self.callsignName, self.callsignNumber))
self:I(self.lid..string.format("Switching callsign to %d-%d", self.callsign.NumberSquad, self.callsign.NumberGroup))
local group=self.group --Wrapper.Group#GROUP
group:CommandSetCallsign(self.callsignName, self.callsignNumber)
group:CommandSetCallsign(self.callsign.NumberSquad, self.callsign.NumberGroup)
end
@ -3473,11 +3512,14 @@ function OPSGROUP:GetAmmoTot()
Ammo.Guns=0
Ammo.Rockets=0
Ammo.Bombs=0
Ammo.Torpedos=0
Ammo.Missiles=0
Ammo.MissilesAA=0
Ammo.MissilesAG=0
Ammo.MissilesAS=0
Ammo.MissilesCR=0
Ammo.MissilesSA=0
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
@ -3491,10 +3533,13 @@ function OPSGROUP:GetAmmoTot()
Ammo.Guns=Ammo.Guns+ammo.Guns
Ammo.Rockets=Ammo.Rockets+ammo.Rockets
Ammo.Bombs=Ammo.Bombs+ammo.Bombs
Ammo.Torpedos=Ammo.Torpedos+ammo.Torpedos
Ammo.Missiles=Ammo.Missiles+ammo.Missiles
Ammo.MissilesAA=Ammo.MissilesAA+ammo.MissilesAA
Ammo.MissilesAG=Ammo.MissilesAG+ammo.MissilesAG
Ammo.MissilesAS=Ammo.MissilesAS+ammo.MissilesAS
Ammo.MissilesCR=Ammo.MissilesCR+ammo.MissilesCR
Ammo.MissilesSA=Ammo.MissilesSA+ammo.MissilesSA
end

View File

@ -422,6 +422,7 @@ function SQUADRON:GetCallsign(Asset)
for i=1,Asset.nunits do
local callsign={}
callsign[1]=self.callsignName
callsign[2]=math.floor(self.callsigncounter / 10)
callsign[3]=self.callsigncounter % 10

View File

@ -91,39 +91,51 @@ PROFILER.fileName="_LuaProfiler.txt"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Start profiler.
function PROFILER.Start()
-- @param #number Delay Delay in seconds before profiler is stated. Default is immediately.
-- @param #number Duration Duration in (game) seconds before the profiler is stopped. Default is when mission ends.
function PROFILER.Start(Delay, Duration)
PROFILER.startTime=timer.getTime()
PROFILER.endTime=0
PROFILER.runTime=0
if Delay and Delay>0 then
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
else
PROFILER.startTime=timer.getTime()
PROFILER.endTime=0
PROFILER.runTime=0
-- Add event handler.
world.addEventHandler(PROFILER.eventHandler)
-- Message to screen.
local function showProfilerRunning()
timer.scheduleFunction(showProfilerRunning, nil, timer.getTime()+600)
trigger.action.outText("### Profiler running ###", 600)
end
-- Message.
showProfilerRunning()
-- Info in log.
BASE:I('############################ Profiler Started ############################')
-- Add event handler.
world.addEventHandler(PROFILER.eventHandler)
-- Message to screen.
local function showProfilerRunning()
timer.scheduleFunction(showProfilerRunning, nil, timer.getTime()+600)
trigger.action.outText("### Profiler running ###", 600)
-- Set hook.
debug.sethook(PROFILER.hook, "cr")
if Duration then
PROFILER.Stop(Duration)
end
end
-- Message.
showProfilerRunning()
-- Info in log.
BASE:I('############################ Profiler Started ############################')
-- Set hook.
debug.sethook(PROFILER.hook, "cr")
end
--- Stop profiler.
-- @param #number delay Delay before stop in seconds.
function PROFILER.Stop(delay)
-- @param #number Delay Delay before stop in seconds.
function PROFILER.Stop(Delay)
if delay and delay>0 then
if Delay and Delay>0 then
BASE:ScheduleOnce(delay, PROFILER.Stop)
BASE:ScheduleOnce(Delay, PROFILER.Stop)
else
@ -210,7 +222,6 @@ end
-- @param #string txt The text.
function PROFILER._flog(f, txt)
f:write(txt.."\r\n")
env.info("Profiler Analysis")
end
--- Show table.