This commit is contained in:
Frank 2020-11-04 22:48:14 +01:00
parent e05d57d908
commit cef0e444c9
5 changed files with 106 additions and 31 deletions

View File

@ -744,7 +744,7 @@ do -- COORDINATE
-- @return #string MGRS coordinates. -- @return #string MGRS coordinates.
function COORDINATE:GetName() function COORDINATE:GetName()
local name=self:ToStringMGRS() local name=self:ToStringMGRS()
return rname return name
end end
--- Return velocity text of the COORDINATE. --- Return velocity text of the COORDINATE.
@ -1751,9 +1751,9 @@ do -- COORDINATE
self:F2( { ExplosionIntensity } ) self:F2( { ExplosionIntensity } )
ExplosionIntensity=ExplosionIntensity or 100 ExplosionIntensity=ExplosionIntensity or 100
if Delay and Delay>0 then if Delay and Delay>0 then
SCHEDULER:New(nil, self.Explosion, {self,ExplosionIntensity}, Delay) self:ScheduleOnce(Delay, self.Explosion, self, ExplosionIntensity)
else else
trigger.action.explosion( self:GetVec3(), ExplosionIntensity ) trigger.action.explosion(self:GetVec3(), ExplosionIntensity)
end end
return self return self
end end

View File

@ -47,6 +47,7 @@
-- @field #number markerCoaliton Coalition to which the marker is dispayed. -- @field #number markerCoaliton Coalition to which the marker is dispayed.
-- @field #table DCStask DCS task structure. -- @field #table DCStask DCS task structure.
-- @field #number Ncasualties Number of own casualties during mission. -- @field #number Ncasualties Number of own casualties during mission.
-- @field #number Nkills Number of (enemy) units killed by assets of this mission.
-- @field #number Nelements Number of elements (units) assigned to mission. -- @field #number Nelements Number of elements (units) assigned to mission.
-- @field #number dTevaluate Time interval in seconds before the mission result is evaluated after mission is over. -- @field #number dTevaluate Time interval in seconds before the mission result is evaluated after mission is over.
-- @field #number Tover Mission abs. time stamp, when mission was over. -- @field #number Tover Mission abs. time stamp, when mission was over.
@ -504,8 +505,9 @@ function AUFTRAG:New(Type)
self.NrepeatFailure=0 self.NrepeatFailure=0
self.NrepeatSuccess=0 self.NrepeatSuccess=0
self.nassets=1 self.nassets=1
self.dTevaluate=0 self.dTevaluate=5
self.Ncasualties=0 self.Ncasualties=0
self.Nkills=0
self.Nelements=0 self.Nelements=0
-- FMS start state is PLANNED. -- FMS start state is PLANNED.
@ -1697,6 +1699,14 @@ function AUFTRAG:GetCasualties()
return self.Ncasualties or 0 return self.Ncasualties or 0
end end
--- Get kills, i.e. number of units that were destroyed by assets of this mission.
-- @param #AUFTRAG self
-- @return #number Number of units destroyed.
function AUFTRAG:GetKills()
return self.Nkills or 0
end
--- Check if mission is "urgent". --- Check if mission is "urgent".
-- @param #AUFTRAG self -- @param #AUFTRAG self
-- @return #boolean If `true`, mission is "urgent". -- @return #boolean If `true`, mission is "urgent".
@ -2102,6 +2112,11 @@ function AUFTRAG:onafterStatus(From, Event, To)
-- Ready to evaluate mission outcome? -- Ready to evaluate mission outcome?
local ready2evaluate=self.Tover and Tnow-self.Tover>=self.dTevaluate or false local ready2evaluate=self.Tover and Tnow-self.Tover>=self.dTevaluate or false
--env.info("FF Tover="..tostring(self.Tover))
--if self.Tover then
-- env.info("FF Tnow-Tover="..tostring(Tnow-self.Tover))
--end
-- Check if mission is OVER (done or cancelled) and enough time passed to evaluate the result. -- Check if mission is OVER (done or cancelled) and enough time passed to evaluate the result.
if self:IsOver() and ready2evaluate then if self:IsOver() and ready2evaluate then
-- Evaluate success or failure of the mission. -- Evaluate success or failure of the mission.
@ -2199,13 +2214,12 @@ function AUFTRAG:Evaluate()
local text=string.format("Evaluating mission:\n") local text=string.format("Evaluating mission:\n")
text=text..string.format("Own casualties = %d/%d\n", self.Ncasualties, self.Nelements) text=text..string.format("Own casualties = %d/%d\n", self.Ncasualties, self.Nelements)
text=text..string.format("Own losses = %.1f %%\n", owndamage) text=text..string.format("Own losses = %.1f %%\n", owndamage)
text=text..string.format("Killed units = %d\n", self.Nkills)
text=text..string.format("--------------------------\n") text=text..string.format("--------------------------\n")
text=text..string.format("Targets left = %d/%d\n", Ntargets, Ntargets0) text=text..string.format("Targets left = %d/%d\n", Ntargets, Ntargets0)
text=text..string.format("Targets life = %.1f/%.1f\n", Life, Life0) text=text..string.format("Targets life = %.1f/%.1f\n", Life, Life0)
text=text..string.format("Enemy losses = %.1f %%\n", targetdamage) text=text..string.format("Enemy losses = %.1f %%\n", targetdamage)
text=text..string.format("--------------------------\n") text=text..string.format("--------------------------\n")
--text=text..string.format("Loss ratio = %.1f %%\n", targetdamage)
--text=text..string.format("--------------------------\n")
text=text..string.format("Success Cond = %s\n", tostring(successCondition)) text=text..string.format("Success Cond = %s\n", tostring(successCondition))
text=text..string.format("Failure Cond = %s\n", tostring(failureCondition)) text=text..string.format("Failure Cond = %s\n", tostring(failureCondition))
text=text..string.format("--------------------------\n") text=text..string.format("--------------------------\n")
@ -2563,6 +2577,8 @@ function AUFTRAG:onafterAssetDead(From, Event, To, Asset)
-- Number of groups alive. -- Number of groups alive.
local N=self:CountOpsGroups() local N=self:CountOpsGroups()
self:I(self.lid..string.format("Asset %s dead! Number of ops groups remaining %d", tostring(Asset.spawngroupname), N))
-- All assets dead? -- All assets dead?
if N==0 then if N==0 then
@ -3045,7 +3061,7 @@ function AUFTRAG:CountOpsGroups()
local N=0 local N=0
for _,_groupdata in pairs(self.groupdata) do for _,_groupdata in pairs(self.groupdata) do
local groupdata=_groupdata --#AUFTRAG.GroupData local groupdata=_groupdata --#AUFTRAG.GroupData
if groupdata and groupdata.opsgroup and groupdata.opsgroup:IsAlive() then if groupdata and groupdata.opsgroup and groupdata.opsgroup:IsAlive() and not groupdata.opsgroup:IsDead() then
N=N+1 N=N+1
end end
end end

View File

@ -336,6 +336,7 @@ function FLIGHTGROUP:New(group)
self:HandleEvent(EVENTS.Crash, self.OnEventCrash) self:HandleEvent(EVENTS.Crash, self.OnEventCrash)
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit) self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
self:HandleEvent(EVENTS.UnitLost, self.OnEventUnitLost) self:HandleEvent(EVENTS.UnitLost, self.OnEventUnitLost)
self:HandleEvent(EVENTS.Kill, self.OnEventKill)
-- Init waypoints. -- Init waypoints.
self:InitWaypoints() self:InitWaypoints()
@ -715,6 +716,12 @@ function FLIGHTGROUP:GetFuelMin()
return fuelmin*100 return fuelmin*100
end end
--- Get number of kills of this group.
-- @param #FLIGHTGROUP self
-- @return #number Number of units killed.
function FLIGHTGROUP:GetKills()
return self.Nkills
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Status -- Status
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -741,18 +748,22 @@ function FLIGHTGROUP:onbeforeStatus(From, Event, To)
-- Units with life <=1 are dead. -- Units with life <=1 are dead.
if life<=1 then if life<=1 then
--env.info(string.format("FF unit %s: live<=1 in status at T=%.3f", unit:GetName(), timer.getTime()))
isdead=true isdead=true
end end
else else
-- Not alive any more. -- Not alive any more.
--env.info(string.format("FF unit %s: NOT alive in status at T=%.3f", unit:GetName(), timer.getTime()))
isdead=true isdead=true
end end
-- This one is dead. -- This one is dead.
if isdead then if isdead then
self:E(self.lid..string.format("Element %s is dead! Probably despawned without notice or landed at a too small airbase", tostring(element.name))) local text=string.format("Element %s is dead at t=%.3f! Maybe despawned without notice or landed at a too small airbase. Calling ElementDead in 60 sec to give other events a chance",
self:ElementDead(element) tostring(element.name), timer.getTime())
self:E(self.lid..text)
self:__ElementDead(60, element)
end end
end end
@ -854,9 +865,9 @@ function FLIGHTGROUP:onafterStatus(From, Event, To)
local parking=element.parking and tostring(element.parking.TerminalID) or "X" local parking=element.parking and tostring(element.parking.TerminalID) or "X"
-- Check if element is not dead and we missed an event. -- Check if element is not dead and we missed an event.
if life<=0 and element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then --if life<=0 and element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then
self:ElementDead(element) -- self:ElementDead(element)
end --end
-- Get ammo. -- Get ammo.
local ammo=self:GetAmmoElement(element) local ammo=self:GetAmmoElement(element)
@ -1177,9 +1188,9 @@ function FLIGHTGROUP:OnEventCrash(EventData)
-- Get element. -- Get element.
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
if element then if element and element.status~=OPSGROUP.ElementStatus.DEAD then
self:T3(self.lid..string.format("EVENT: Element %s crashed ==> dead", element.name)) self:I(self.lid..string.format("EVENT: Element %s crashed ==> destroyed", element.name))
self:ElementDead(element) self:ElementDestroyed(element)
end end
end end
@ -1193,7 +1204,7 @@ function FLIGHTGROUP:OnEventUnitLost(EventData)
-- Check that this is the right group. -- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
self:T(self.lid..string.format("EVENT: Unit %s lost!", EventData.IniUnitName)) self:I(self.lid..string.format("EVENT: Unit %s lost at t=%.3f", EventData.IniUnitName, timer.getTime()))
local unit=EventData.IniUnit local unit=EventData.IniUnit
local group=EventData.IniGroup local group=EventData.IniGroup
@ -1202,8 +1213,8 @@ function FLIGHTGROUP:OnEventUnitLost(EventData)
-- Get element. -- Get element.
local element=self:GetElementByName(unitname) local element=self:GetElementByName(unitname)
if element then if element and element.status~=OPSGROUP.ElementStatus.DEAD then
self:T3(self.lid..string.format("EVENT: Element %s unit lost ==> destroyed", element.name)) self:I(self.lid..string.format("EVENT: Element %s unit lost ==> destroyed t=%.3f", element.name, timer.getTime()))
self:ElementDestroyed(element) self:ElementDestroyed(element)
end end
@ -1211,6 +1222,30 @@ function FLIGHTGROUP:OnEventUnitLost(EventData)
end end
--- Flightgroup event function handling the crash of a unit.
-- @param #FLIGHTGROUP self
-- @param Core.Event#EVENTDATA EventData Event data.
function FLIGHTGROUP:OnEventKill(EventData)
-- Check that this is the right group.
if EventData and EventData.IniGroup and EventData.IniUnit and EventData.IniGroupName and EventData.IniGroupName==self.groupname then
self:I(self.lid..string.format("EVENT: Unit %s killed unit %s!", tostring(EventData.IniUnitName), tostring(EventData.TgtUnitName)))
local unit=EventData.IniUnit
local group=EventData.IniGroup
local unitname=EventData.IniUnitName
self.Nkills=self.Nkills+1
local mission=self:GetMissionCurrent()
if mission then
mission.Nkills=mission.Nkills+1
end
end
end
--- Flightgroup event function handling the crash of a unit. --- Flightgroup event function handling the crash of a unit.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @param Core.Event#EVENTDATA EventData Event data. -- @param Core.Event#EVENTDATA EventData Event data.

View File

@ -55,6 +55,7 @@
-- @field #boolean detectionOn If true, detected units of the group are analyzed. -- @field #boolean detectionOn If true, detected units of the group are analyzed.
-- @field Ops.Auftrag#AUFTRAG missionpaused Paused mission. -- @field Ops.Auftrag#AUFTRAG missionpaused Paused mission.
-- @field #number Ndestroyed Number of destroyed units. -- @field #number Ndestroyed Number of destroyed units.
-- @field #number Nkills Number kills of this groups.
-- --
-- @field Core.Point#COORDINATE coordinate Current coordinate. -- @field Core.Point#COORDINATE coordinate Current coordinate.
-- --
@ -88,7 +89,7 @@
-- --
-- @field #OPSGROUP.Spot spot Laser and IR spot. -- @field #OPSGROUP.Spot spot Laser and IR spot.
-- --
-- @field #OPSGROUP.Ammo ammo Initial ammuont of ammo. -- @field #OPSGROUP.Ammo ammo Initial ammount of ammo.
-- --
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
@ -142,6 +143,7 @@ OPSGROUP = {
icls = {}, icls = {},
callsign = {}, callsign = {},
Ndestroyed = 0, Ndestroyed = 0,
Nkills = 0,
} }
@ -354,7 +356,14 @@ function OPSGROUP:New(Group)
end end
-- Set some string id for output to DCS.log file. -- Set some string id for output to DCS.log file.
self.lid=string.format("OPSGROUP %s | ", self.groupname) self.lid=string.format("OPSGROUP %s | ", tostring(self.groupname))
if self.group then
if not self:IsExist() then
self:E(self.lid.."ERROR: GROUP does not exist! Returning nil")
return nil
end
end
-- Init set of detected units. -- Init set of detected units.
self.detectedunits=SET_UNIT:New() self.detectedunits=SET_UNIT:New()
@ -531,7 +540,11 @@ end
-- @return #OPSGROUP self -- @return #OPSGROUP self
function OPSGROUP:SetLaser(Code, CheckLOS, IROff, UpdateTime) function OPSGROUP:SetLaser(Code, CheckLOS, IROff, UpdateTime)
self.spot.Code=Code or 1688 self.spot.Code=Code or 1688
self.spot.CheckLOS=CheckLOS and CheckLOS or true if CheckLOS~=nil then
self.spot.CheckLOS=CheckLOS
else
self.spot.CheckLOS=true
end
self.spot.IRon=not IROff self.spot.IRon=not IROff
self.spot.dt=UpdateTime or 0.5 self.spot.dt=UpdateTime or 0.5
return self return self
@ -1303,7 +1316,7 @@ end
-- @return #OPSGROUP.Waypoint Waypoint data. -- @return #OPSGROUP.Waypoint Waypoint data.
function OPSGROUP:GetWaypointByID(uid) function OPSGROUP:GetWaypointByID(uid)
for _,_waypoint in pairs(self.waypoints) do for _,_waypoint in pairs(self.waypoints or {}) do
local waypoint=_waypoint --#OPSGROUP.Waypoint local waypoint=_waypoint --#OPSGROUP.Waypoint
if waypoint.uid==uid then if waypoint.uid==uid then
return waypoint return waypoint
@ -2190,11 +2203,16 @@ function OPSGROUP:onafterTaskCancel(From, Event, To, Task)
-- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone() -- Set stop flag. When the flag is true, the _TaskDone function is executed and calls :TaskDone()
Task.stopflag:Set(1) Task.stopflag:Set(1)
local done=false
if Task.dcstask.id=="Formation" then if Task.dcstask.id=="Formation" then
Task.formation:Stop() Task.formation:Stop()
self:TaskDone(Task) done=true
elseif stopflag==1 or not self:IsAlive() then elseif stopflag==1 or (not self:IsAlive()) or self:IsDead() or self:IsStopped() then
-- Manual call TaskDone if setting flag to one was not successful. -- Manual call TaskDone if setting flag to one was not successful.
done=true
end
if done then
self:TaskDone(Task) self:TaskDone(Task)
end end
@ -3480,6 +3498,10 @@ function OPSGROUP:SetLaserTarget(Target)
-- Coordinate as target. -- Coordinate as target.
self.spot.TargetType=0 self.spot.TargetType=0
self.spot.offsetTarget={x=0, y=0, z=0} self.spot.offsetTarget={x=0, y=0, z=0}
elseif Target:IsInstanceOf("SCENERY") then
-- Coordinate as target.
self.spot.TargetType=0
self.spot.offsetTarget={x=0, y=1, z=0}
else else
self:E(self.lid.."ERROR: LASER target should be a POSITIONABLE (GROUP, UNIT or STATIC) or a COORDINATE object!") self:E(self.lid.."ERROR: LASER target should be a POSITIONABLE (GROUP, UNIT or STATIC) or a COORDINATE object!")
return return
@ -3625,7 +3647,7 @@ end
-- @param #string To To state. -- @param #string To To state.
-- @param #OPSGROUP.Element Element The flight group element. -- @param #OPSGROUP.Element Element The flight group element.
function OPSGROUP:onafterElementDead(From, Event, To, Element) function OPSGROUP:onafterElementDead(From, Event, To, Element)
self:T(self.lid..string.format("Element dead %s", Element.name)) self:T(self.lid..string.format("Element dead %s at t=%.3f", Element.name, timer.getTime()))
-- Set element status. -- Set element status.
self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD) self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD)
@ -3672,7 +3694,7 @@ end
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
function OPSGROUP:onafterDead(From, Event, To) function OPSGROUP:onafterDead(From, Event, To)
self:T(self.lid..string.format("Group dead!")) self:T(self.lid..string.format("Group dead at t=%.3f", timer.getTime()))
-- Delete waypoints so they are re-initialized at the next spawn. -- Delete waypoints so they are re-initialized at the next spawn.
self.waypoints=nil self.waypoints=nil
@ -3682,6 +3704,8 @@ function OPSGROUP:onafterDead(From, Event, To)
for _,_mission in pairs(self.missionqueue) do for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG local mission=_mission --Ops.Auftrag#AUFTRAG
self:T(self.lid.."Cancelling mission because group is dead! Mission name "..tostring(mission:GetName()))
self:MissionCancel(mission) self:MissionCancel(mission)
mission:GroupDead(self) mission:GroupDead(self)
@ -3713,7 +3737,7 @@ function OPSGROUP:onafterStop(From, Event, To)
end end
-- Debug output. -- Debug output.
self:T(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from database.") self:I(self.lid.."STOPPED! Unhandled events, cleared scheduler and removed from database.")
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -525,12 +525,12 @@ function TARGET:_AddObject(Object)
elseif Object:IsInstanceOf("COORDINATE") then elseif Object:IsInstanceOf("COORDINATE") then
local coord=Object --Core.Point#COORDINATE local coord=UTILS.DeepCopy(Object) --Core.Point#COORDINATE
target.Type=TARGET.ObjectType.COORDINATE target.Type=TARGET.ObjectType.COORDINATE
target.Name=coord:ToStringMGRS() target.Name=coord:ToStringMGRS()
target.Coordinate=Object target.Coordinate=coord
target.Life0=1 target.Life0=1
target.Life=1 target.Life=1